Mercurial > audio-send
changeset 4:ed256a687dfe
removed very old crufty java program
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Tue, 25 Oct 2011 13:17:37 -0700 |
parents | 96298d83959c |
children | ff36dfa1addb |
files | RecordAudioRenderer.java cleanup-message.txt org/cleanup-message.txt |
diffstat | 3 files changed, 100 insertions(+), 1283 deletions(-) [+] |
line wrap: on
line diff
1.1 --- a/RecordAudioRenderer.java Tue Oct 25 13:16:27 2011 -0700 1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 1.3 @@ -1,1183 +0,0 @@ 1.4 -package com.jme3.capture; 1.5 - 1.6 -import static org.lwjgl.openal.AL10.AL_BUFFER; 1.7 -import static org.lwjgl.openal.AL10.AL_BUFFERS_PROCESSED; 1.8 -import static org.lwjgl.openal.AL10.AL_CONE_INNER_ANGLE; 1.9 -import static org.lwjgl.openal.AL10.AL_CONE_OUTER_ANGLE; 1.10 -import static org.lwjgl.openal.AL10.AL_CONE_OUTER_GAIN; 1.11 -import static org.lwjgl.openal.AL10.AL_DIRECTION; 1.12 -import static org.lwjgl.openal.AL10.AL_FALSE; 1.13 -import static org.lwjgl.openal.AL10.AL_FORMAT_MONO16; 1.14 -import static org.lwjgl.openal.AL10.AL_FORMAT_MONO8; 1.15 -import static org.lwjgl.openal.AL10.AL_FORMAT_STEREO16; 1.16 -import static org.lwjgl.openal.AL10.AL_FORMAT_STEREO8; 1.17 -import static org.lwjgl.openal.AL10.AL_GAIN; 1.18 -import static org.lwjgl.openal.AL10.AL_LOOPING; 1.19 -import static org.lwjgl.openal.AL10.AL_MAX_DISTANCE; 1.20 -import static org.lwjgl.openal.AL10.AL_ORIENTATION; 1.21 -import static org.lwjgl.openal.AL10.AL_PAUSED; 1.22 -import static org.lwjgl.openal.AL10.AL_PITCH; 1.23 -import static org.lwjgl.openal.AL10.AL_POSITION; 1.24 -import static org.lwjgl.openal.AL10.AL_REFERENCE_DISTANCE; 1.25 -import static org.lwjgl.openal.AL10.AL_RENDERER; 1.26 -import static org.lwjgl.openal.AL10.AL_SOURCE_RELATIVE; 1.27 -import static org.lwjgl.openal.AL10.AL_SOURCE_STATE; 1.28 -import static org.lwjgl.openal.AL10.AL_STOPPED; 1.29 -import static org.lwjgl.openal.AL10.AL_TRUE; 1.30 -import static org.lwjgl.openal.AL10.AL_VELOCITY; 1.31 -import static org.lwjgl.openal.AL10.AL_VENDOR; 1.32 -import static org.lwjgl.openal.AL10.AL_VERSION; 1.33 -import static org.lwjgl.openal.AL10.alBufferData; 1.34 -import static org.lwjgl.openal.AL10.alDeleteBuffers; 1.35 -import static org.lwjgl.openal.AL10.alDeleteSources; 1.36 -import static org.lwjgl.openal.AL10.alGenBuffers; 1.37 -import static org.lwjgl.openal.AL10.alGenSources; 1.38 -import static org.lwjgl.openal.AL10.alGetError; 1.39 -import static org.lwjgl.openal.AL10.alGetSourcei; 1.40 -import static org.lwjgl.openal.AL10.alGetString; 1.41 -import static org.lwjgl.openal.AL10.alListener; 1.42 -import static org.lwjgl.openal.AL10.alListener3f; 1.43 -import static org.lwjgl.openal.AL10.alListenerf; 1.44 -import static org.lwjgl.openal.AL10.alSource3f; 1.45 -import static org.lwjgl.openal.AL10.alSourcePause; 1.46 -import static org.lwjgl.openal.AL10.alSourcePlay; 1.47 -import static org.lwjgl.openal.AL10.alSourceQueueBuffers; 1.48 -import static org.lwjgl.openal.AL10.alSourceStop; 1.49 -import static org.lwjgl.openal.AL10.alSourceUnqueueBuffers; 1.50 -import static org.lwjgl.openal.AL10.alSourcef; 1.51 -import static org.lwjgl.openal.AL10.alSourcei; 1.52 - 1.53 -import java.lang.reflect.Field; 1.54 -import java.nio.ByteBuffer; 1.55 -import java.nio.FloatBuffer; 1.56 -import java.nio.IntBuffer; 1.57 -import java.util.ArrayList; 1.58 -import java.util.Vector; 1.59 -import java.util.concurrent.atomic.AtomicBoolean; 1.60 -import java.util.logging.Level; 1.61 -import java.util.logging.Logger; 1.62 - 1.63 -import org.lwjgl.LWJGLException; 1.64 -import org.lwjgl.openal.AL; 1.65 -import org.lwjgl.openal.AL11; 1.66 -import org.lwjgl.openal.ALC10; 1.67 -import org.lwjgl.openal.ALCdevice; 1.68 -import org.lwjgl.openal.EFX10; 1.69 -import org.lwjgl.openal.OpenALException; 1.70 - 1.71 -import com.jme3.audio.AudioBuffer; 1.72 -import com.jme3.audio.AudioData; 1.73 -import com.jme3.audio.AudioNode; 1.74 -import com.jme3.audio.AudioNode.Status; 1.75 -import com.jme3.audio.AudioParam; 1.76 -import com.jme3.audio.AudioRenderer; 1.77 -import com.jme3.audio.AudioStream; 1.78 -import com.jme3.audio.Environment; 1.79 -import com.jme3.audio.Filter; 1.80 -import com.jme3.audio.Listener; 1.81 -import com.jme3.audio.ListenerParam; 1.82 -import com.jme3.audio.LowPassFilter; 1.83 -import com.jme3.math.Vector3f; 1.84 -import com.jme3.util.BufferUtils; 1.85 - 1.86 - 1.87 - 1.88 -public class RecordAudioRenderer implements AudioRenderer, Runnable { 1.89 - 1.90 - 1.91 - 1.92 - public static void getMainSamples(){ 1.93 - 1.94 - } 1.95 - 1.96 - 1.97 - private static final Logger logger = Logger.getLogger(RecordAudioRenderer.class.getName()); 1.98 - 1.99 - // When multiplied by STREAMING_BUFFER_COUNT, will equal 44100 * 2 * 2 1.100 - // which is exactly 1 second of audio. 1.101 - private static final int BUFFER_SIZE = 35280; 1.102 - private static final int STREAMING_BUFFER_COUNT = 5; 1.103 - 1.104 - private final static int MAX_NUM_CHANNELS = 2; 1.105 - private IntBuffer ib = BufferUtils.createIntBuffer(1); 1.106 - private final FloatBuffer fb = BufferUtils.createVector3Buffer(2); 1.107 - private final ByteBuffer nativeBuf = BufferUtils.createByteBuffer(BUFFER_SIZE); 1.108 - private final byte[] arrayBuf = new byte[BUFFER_SIZE]; 1.109 - 1.110 - private int[] channels; 1.111 - private AudioNode[] chanSrcs; 1.112 - private int nextChan = 0; 1.113 - private ArrayList<Integer> freeChans = new ArrayList<Integer>(); 1.114 - 1.115 - private Listener listener; 1.116 - private boolean audioDisabled = false; 1.117 - 1.118 - private boolean supportEfx = false; 1.119 - private int auxSends = 0; 1.120 - private int reverbFx = -1; 1.121 - private int reverbFxSlot = -1; 1.122 - 1.123 - // RLM: this is to call the native methods which require the OpenAL device ID. 1.124 - // currently it is obtained through reflection. 1.125 - private long deviceID; 1.126 - 1.127 - // Update audio 20 times per second 1.128 - private static final float UPDATE_RATE = 0.05f; 1.129 - 1.130 - private final Thread audioThread = new Thread(this, "jME3 Audio Thread"); 1.131 - private final AtomicBoolean threadLock = new AtomicBoolean(false); 1.132 - 1.133 - public RecordAudioRenderer(){ 1.134 - } 1.135 - 1.136 - public static native void helloEveryone(); 1.137 - 1.138 - 1.139 - public static native void nstep(long device); 1.140 - public void step(){ 1.141 - nstep(this.deviceID); 1.142 - } 1.143 - 1.144 - 1.145 - 1.146 - public void getMainSamples(ByteBuffer buffer){ 1.147 - ngetMainSamples(this.deviceID, buffer, buffer.position()); 1.148 - } 1.149 - public static native void ngetMainSamples(long device, ByteBuffer buffer, int position); 1.150 - 1.151 - 1.152 - public void getAuxSamples(ByteBuffer buffer){ 1.153 - ngetAuxSamples(this.deviceID, buffer, buffer.position()); 1.154 - } 1.155 - public static native void ngetAuxSamples(long device, ByteBuffer buffer, int position); 1.156 - 1.157 - 1.158 - 1.159 - public void initialize(){ 1.160 - if (!audioThread.isAlive()){ 1.161 - audioThread.setDaemon(true); 1.162 - audioThread.setPriority(Thread.NORM_PRIORITY+1); 1.163 - audioThread.start(); 1.164 - }else{ 1.165 - throw new IllegalStateException("Initialize already called"); 1.166 - } 1.167 - } 1.168 - 1.169 - private void checkDead(){ 1.170 - if (audioThread.getState() == Thread.State.TERMINATED) 1.171 - throw new IllegalStateException("Audio thread is terminated"); 1.172 - } 1.173 - 1.174 - public void run(){ 1.175 - initInThread(); 1.176 - synchronized (threadLock){ 1.177 - threadLock.set(true); 1.178 - threadLock.notifyAll(); 1.179 - } 1.180 - 1.181 - 1.182 - helloEveryone(); 1.183 - System.out.println("AudioRecorder: Trying to call native methods."); 1.184 - System.out.println("our device ID is : " + this.deviceID); 1.185 - 1.186 - 1.187 - 1.188 - 1.189 - long updateRateNanos = (long) (UPDATE_RATE * 1000000000); 1.190 - mainloop: while (true){ 1.191 - long startTime = System.nanoTime(); 1.192 - 1.193 - if (Thread.interrupted()) 1.194 - break; 1.195 - 1.196 - synchronized (threadLock){ 1.197 - updateInThread(UPDATE_RATE); 1.198 - } 1.199 - 1.200 - long endTime = System.nanoTime(); 1.201 - long diffTime = endTime - startTime; 1.202 - 1.203 - if (diffTime < updateRateNanos){ 1.204 - long desiredEndTime = startTime + updateRateNanos; 1.205 - while (System.nanoTime() < desiredEndTime){ 1.206 - try{ 1.207 - Thread.sleep(1); 1.208 - }catch (InterruptedException ex){ 1.209 - break mainloop; 1.210 - } 1.211 - } 1.212 - } 1.213 - } 1.214 - 1.215 - synchronized (threadLock){ 1.216 - cleanupInThread(); 1.217 - } 1.218 - } 1.219 - 1.220 - public void initInThread(){ 1.221 - try{ 1.222 - if (!AL.isCreated()){ 1.223 - AL.create("Aurellem", 44100, 15, false); 1.224 - } 1.225 - }catch (OpenALException ex){ 1.226 - logger.log(Level.SEVERE, "Failed to load audio library", ex); 1.227 - audioDisabled = true; 1.228 - return; 1.229 - }catch (LWJGLException ex){ 1.230 - logger.log(Level.SEVERE, "Failed to load audio library", ex); 1.231 - audioDisabled = true; 1.232 - return; 1.233 - } 1.234 - 1.235 - ALCdevice device = AL.getDevice(); 1.236 - 1.237 - // RLM: use reflection to grab the ID of our device for use later. 1.238 - try { 1.239 - Field deviceIDField; 1.240 - deviceIDField = ALCdevice.class.getDeclaredField("device"); 1.241 - deviceIDField.setAccessible(true); 1.242 - try {deviceID = (Long)deviceIDField.get(device);} 1.243 - catch (IllegalArgumentException e) {e.printStackTrace();} 1.244 - catch (IllegalAccessException e) {e.printStackTrace();} 1.245 - deviceIDField.setAccessible(false);} 1.246 - catch (SecurityException e) {e.printStackTrace();} 1.247 - catch (NoSuchFieldException e) {e.printStackTrace();} 1.248 - 1.249 - 1.250 - 1.251 - String deviceName = ALC10.alcGetString(device, ALC10.ALC_DEVICE_SPECIFIER); 1.252 - 1.253 - logger.log(Level.FINER, "Audio Device: {0}", deviceName); 1.254 - logger.log(Level.FINER, "Audio Vendor: {0}", alGetString(AL_VENDOR)); 1.255 - logger.log(Level.FINER, "Audio Renderer: {0}", alGetString(AL_RENDERER)); 1.256 - logger.log(Level.FINER, "Audio Version: {0}", alGetString(AL_VERSION)); 1.257 - 1.258 - // Find maximum # of sources supported by this implementation 1.259 - // RLM: this may not be wise -- exceeding the number of available channels 1.260 - // can crash some versions of OpenAL 1.261 - ArrayList<Integer> channelList = new ArrayList<Integer>(); 1.262 - for (int i = 0; i < MAX_NUM_CHANNELS; i++){ 1.263 - int chan = alGenSources(); 1.264 - if (alGetError() != 0){ 1.265 - break; 1.266 - }else{ 1.267 - channelList.add(chan); 1.268 - } 1.269 - } 1.270 - 1.271 - channels = new int[channelList.size()]; 1.272 - for (int i = 0; i < channels.length; i++){ 1.273 - channels[i] = channelList.get(i); 1.274 - } 1.275 - 1.276 - ib = BufferUtils.createIntBuffer(channels.length); 1.277 - chanSrcs = new AudioNode[channels.length]; 1.278 - 1.279 - logger.log(Level.INFO, "AudioRenderer supports {0} channels", channels.length); 1.280 - 1.281 - supportEfx = ALC10.alcIsExtensionPresent(device, "ALC_EXT_EFX"); 1.282 - // RLM: disable this for now. 1.283 - supportEfx = false; 1.284 - logger.log(Level.FINER, "Audio EFX support: {0}", supportEfx); 1.285 - 1.286 - if (supportEfx){ 1.287 - ib.position(0).limit(1); 1.288 - ALC10.alcGetInteger(device, EFX10.ALC_EFX_MAJOR_VERSION, ib); 1.289 - int major = ib.get(0); 1.290 - ib.position(0).limit(1); 1.291 - ALC10.alcGetInteger(device, EFX10.ALC_EFX_MINOR_VERSION, ib); 1.292 - int minor = ib.get(0); 1.293 - logger.log(Level.INFO, "Audio effect extension version: {0}.{1}", new Object[]{major, minor}); 1.294 - 1.295 - ALC10.alcGetInteger(device, EFX10.ALC_MAX_AUXILIARY_SENDS, ib); 1.296 - auxSends = ib.get(0); 1.297 - logger.log(Level.INFO, "Audio max auxilary sends: {0}", auxSends); 1.298 - 1.299 - // create slot 1.300 - ib.position(0).limit(1); 1.301 - EFX10.alGenAuxiliaryEffectSlots(ib); 1.302 - reverbFxSlot = ib.get(0); 1.303 - 1.304 - // create effect 1.305 - ib.position(0).limit(1); 1.306 - EFX10.alGenEffects(ib); 1.307 - reverbFx = ib.get(0); 1.308 - EFX10.alEffecti(reverbFx, EFX10.AL_EFFECT_TYPE, EFX10.AL_EFFECT_REVERB); 1.309 - 1.310 - // attach reverb effect to effect slot 1.311 -// EFX10.alAuxiliaryEffectSloti(reverbFxSlot, EFX10.AL_EFFECTSLOT_EFFECT, reverbFx); 1.312 - } 1.313 - } 1.314 - 1.315 - public void cleanupInThread(){ 1.316 - 1.317 - 1.318 - if (audioDisabled){ 1.319 - AL.destroy(); 1.320 - return; 1.321 - } 1.322 - 1.323 - // delete channel-based sources 1.324 - ib.clear(); 1.325 - ib.put(channels); 1.326 - ib.flip(); 1.327 - alDeleteSources(ib); 1.328 - 1.329 - if (supportEfx){ 1.330 - ib.position(0).limit(1); 1.331 - ib.put(0, reverbFx); 1.332 - EFX10.alDeleteEffects(ib); 1.333 - 1.334 - ib.position(0).limit(1); 1.335 - ib.put(0, reverbFxSlot); 1.336 - EFX10.alDeleteAuxiliaryEffectSlots(ib); 1.337 - } 1.338 - 1.339 - // XXX: Delete other buffers/sources 1.340 - AL.destroy(); 1.341 - } 1.342 - 1.343 - public void cleanup(){ 1.344 - // kill audio thread 1.345 - 1.346 - if (audioThread.isAlive()){ 1.347 - audioThread.interrupt(); 1.348 - } 1.349 - 1.350 - Byte[] data1 = new Byte[this.fullWaveData1.size()]; 1.351 - data1 = this.fullWaveData1.toArray(data1); 1.352 - 1.353 - Byte[] data2 = new Byte[this.fullWaveData2.size()]; 1.354 - data2 = this.fullWaveData2.toArray(data2); 1.355 - System.out.println(this.fullWaveData1.size()); 1.356 - System.out.println("Saving WAVE data!"); 1.357 - /*for (int i = 0; i < data1.length;i++){ 1.358 - System.out.print(data1[i]+","); 1.359 - if (i%32 ==0){System.out.println();} 1.360 - } 1.361 - */ 1.362 - 1.363 - 1.364 - StdAudio.save("/home/r/wave-output/data2.wav", data2); 1.365 - StdAudio.save("/home/r/wave-output/data1.wav", data1); 1.366 - } 1.367 - 1.368 - private void updateFilter(Filter f){ 1.369 - int id = f.getId(); 1.370 - if (id == -1){ 1.371 - ib.position(0).limit(1); 1.372 - EFX10.alGenFilters(ib); 1.373 - id = ib.get(0); 1.374 - f.setId(id); 1.375 - } 1.376 - 1.377 - if (f instanceof LowPassFilter){ 1.378 - LowPassFilter lpf = (LowPassFilter) f; 1.379 - EFX10.alFilteri(id, EFX10.AL_FILTER_TYPE, EFX10.AL_FILTER_LOWPASS); 1.380 - EFX10.alFilterf(id, EFX10.AL_LOWPASS_GAIN, lpf.getVolume()); 1.381 - EFX10.alFilterf(id, EFX10.AL_LOWPASS_GAINHF, lpf.getHighFreqVolume()); 1.382 - }else{ 1.383 - throw new UnsupportedOperationException("Filter type unsupported: "+ 1.384 - f.getClass().getName()); 1.385 - } 1.386 - 1.387 - f.clearUpdateNeeded(); 1.388 - } 1.389 - 1.390 - public void updateSourceParam(AudioNode src, AudioParam param){ 1.391 - checkDead(); 1.392 - synchronized (threadLock){ 1.393 - while (!threadLock.get()){ 1.394 - try { 1.395 - threadLock.wait(); 1.396 - } catch (InterruptedException ex) { 1.397 - } 1.398 - } 1.399 - if (audioDisabled) 1.400 - return; 1.401 - 1.402 - // There is a race condition in AudioNode that can 1.403 - // cause this to be called for a node that has been 1.404 - // detached from its channel. For example, setVolume() 1.405 - // called from the render thread may see that that AudioNode 1.406 - // still has a channel value but the audio thread may 1.407 - // clear that channel before setVolume() gets to call 1.408 - // updateSourceParam() (because the audio stopped playing 1.409 - // on its own right as the volume was set). In this case, 1.410 - // it should be safe to just ignore the update 1.411 - if (src.getChannel() < 0) 1.412 - return; 1.413 - 1.414 - assert src.getChannel() >= 0; 1.415 - 1.416 - int id = channels[src.getChannel()]; 1.417 - switch (param){ 1.418 - case Position: 1.419 - if (!src.isPositional()) 1.420 - return; 1.421 - 1.422 - Vector3f pos = src.getWorldTranslation(); 1.423 - alSource3f(id, AL_POSITION, pos.x, pos.y, pos.z); 1.424 - break; 1.425 - case Velocity: 1.426 - if (!src.isPositional()) 1.427 - return; 1.428 - 1.429 - Vector3f vel = src.getVelocity(); 1.430 - alSource3f(id, AL_VELOCITY, vel.x, vel.y, vel.z); 1.431 - break; 1.432 - case MaxDistance: 1.433 - if (!src.isPositional()) 1.434 - return; 1.435 - 1.436 - alSourcef(id, AL_MAX_DISTANCE, src.getMaxDistance()); 1.437 - break; 1.438 - case RefDistance: 1.439 - if (!src.isPositional()) 1.440 - return; 1.441 - 1.442 - alSourcef(id, AL_REFERENCE_DISTANCE, src.getRefDistance()); 1.443 - break; 1.444 - case ReverbFilter: 1.445 - if (!src.isPositional() || !src.isReverbEnabled()) 1.446 - return; 1.447 - 1.448 - int filter = EFX10.AL_FILTER_NULL; 1.449 - if (src.getReverbFilter() != null){ 1.450 - Filter f = src.getReverbFilter(); 1.451 - if (f.isUpdateNeeded()){ 1.452 - updateFilter(f); 1.453 - } 1.454 - filter = f.getId(); 1.455 - } 1.456 - AL11.alSource3i(id, EFX10.AL_AUXILIARY_SEND_FILTER, reverbFxSlot, 0, filter); 1.457 - break; 1.458 - case ReverbEnabled: 1.459 - if (!src.isPositional()) 1.460 - return; 1.461 - 1.462 - if (src.isReverbEnabled()){ 1.463 - updateSourceParam(src, AudioParam.ReverbFilter); 1.464 - }else{ 1.465 - AL11.alSource3i(id, EFX10.AL_AUXILIARY_SEND_FILTER, 0, 0, EFX10.AL_FILTER_NULL); 1.466 - } 1.467 - break; 1.468 - case IsPositional: 1.469 - if (!src.isPositional()){ 1.470 - // play in headspace 1.471 - alSourcei(id, AL_SOURCE_RELATIVE, AL_TRUE); 1.472 - alSource3f(id, AL_POSITION, 0,0,0); 1.473 - alSource3f(id, AL_VELOCITY, 0,0,0); 1.474 - }else{ 1.475 - alSourcei(id, AL_SOURCE_RELATIVE, AL_FALSE); 1.476 - updateSourceParam(src, AudioParam.Position); 1.477 - updateSourceParam(src, AudioParam.Velocity); 1.478 - updateSourceParam(src, AudioParam.MaxDistance); 1.479 - updateSourceParam(src, AudioParam.RefDistance); 1.480 - updateSourceParam(src, AudioParam.ReverbEnabled); 1.481 - } 1.482 - break; 1.483 - case Direction: 1.484 - if (!src.isDirectional()) 1.485 - return; 1.486 - 1.487 - Vector3f dir = src.getDirection(); 1.488 - alSource3f(id, AL_DIRECTION, dir.x, dir.y, dir.z); 1.489 - break; 1.490 - case InnerAngle: 1.491 - if (!src.isDirectional()) 1.492 - return; 1.493 - 1.494 - alSourcef(id, AL_CONE_INNER_ANGLE, src.getInnerAngle()); 1.495 - break; 1.496 - case OuterAngle: 1.497 - if (!src.isDirectional()) 1.498 - return; 1.499 - 1.500 - alSourcef(id, AL_CONE_OUTER_ANGLE, src.getOuterAngle()); 1.501 - break; 1.502 - case IsDirectional: 1.503 - if (src.isDirectional()){ 1.504 - updateSourceParam(src, AudioParam.Direction); 1.505 - updateSourceParam(src, AudioParam.InnerAngle); 1.506 - updateSourceParam(src, AudioParam.OuterAngle); 1.507 - alSourcef(id, AL_CONE_OUTER_GAIN, 0); 1.508 - }else{ 1.509 - alSourcef(id, AL_CONE_INNER_ANGLE, 360); 1.510 - alSourcef(id, AL_CONE_OUTER_ANGLE, 360); 1.511 - alSourcef(id, AL_CONE_OUTER_GAIN, 1f); 1.512 - } 1.513 - break; 1.514 - case DryFilter: 1.515 - if (src.getDryFilter() != null){ 1.516 - Filter f = src.getDryFilter(); 1.517 - if (f.isUpdateNeeded()){ 1.518 - updateFilter(f); 1.519 - 1.520 - // NOTE: must re-attach filter for changes to apply. 1.521 - alSourcei(id, EFX10.AL_DIRECT_FILTER, f.getId()); 1.522 - } 1.523 - }else{ 1.524 - alSourcei(id, EFX10.AL_DIRECT_FILTER, EFX10.AL_FILTER_NULL); 1.525 - } 1.526 - break; 1.527 - case Looping: 1.528 - if (src.isLooping()){ 1.529 - if (!(src.getAudioData() instanceof AudioStream)){ 1.530 - alSourcei(id, AL_LOOPING, AL_TRUE); 1.531 - } 1.532 - }else{ 1.533 - alSourcei(id, AL_LOOPING, AL_FALSE); 1.534 - } 1.535 - break; 1.536 - case Volume: 1.537 - alSourcef(id, AL_GAIN, src.getVolume()); 1.538 - break; 1.539 - case Pitch: 1.540 - alSourcef(id, AL_PITCH, src.getPitch()); 1.541 - break; 1.542 - } 1.543 - } 1.544 - } 1.545 - 1.546 - private void setSourceParams(int id, AudioNode src, boolean forceNonLoop){ 1.547 - if (src.isPositional()){ 1.548 - Vector3f pos = src.getWorldTranslation(); 1.549 - Vector3f vel = src.getVelocity(); 1.550 - alSource3f(id, AL_POSITION, pos.x, pos.y, pos.z); 1.551 - alSource3f(id, AL_VELOCITY, vel.x, vel.y, vel.z); 1.552 - alSourcef(id, AL_MAX_DISTANCE, src.getMaxDistance()); 1.553 - alSourcef(id, AL_REFERENCE_DISTANCE, src.getRefDistance()); 1.554 - alSourcei(id, AL_SOURCE_RELATIVE, AL_FALSE); 1.555 - 1.556 - if (src.isReverbEnabled()){ 1.557 - int filter = EFX10.AL_FILTER_NULL; 1.558 - if (src.getReverbFilter() != null){ 1.559 - Filter f = src.getReverbFilter(); 1.560 - if (f.isUpdateNeeded()){ 1.561 - updateFilter(f); 1.562 - } 1.563 - filter = f.getId(); 1.564 - } 1.565 - AL11.alSource3i(id, EFX10.AL_AUXILIARY_SEND_FILTER, reverbFxSlot, 0, filter); 1.566 - } 1.567 - }else{ 1.568 - // play in headspace 1.569 - alSourcei(id, AL_SOURCE_RELATIVE, AL_TRUE); 1.570 - alSource3f(id, AL_POSITION, 0,0,0); 1.571 - alSource3f(id, AL_VELOCITY, 0,0,0); 1.572 - } 1.573 - 1.574 - if (src.getDryFilter() != null){ 1.575 - Filter f = src.getDryFilter(); 1.576 - if (f.isUpdateNeeded()){ 1.577 - updateFilter(f); 1.578 - 1.579 - // NOTE: must re-attach filter for changes to apply. 1.580 - alSourcei(id, EFX10.AL_DIRECT_FILTER, f.getId()); 1.581 - } 1.582 - } 1.583 - 1.584 - if (forceNonLoop){ 1.585 - alSourcei(id, AL_LOOPING, AL_FALSE); 1.586 - }else{ 1.587 - alSourcei(id, AL_LOOPING, src.isLooping() ? AL_TRUE : AL_FALSE); 1.588 - } 1.589 - alSourcef(id, AL_GAIN, src.getVolume()); 1.590 - alSourcef(id, AL_PITCH, src.getPitch()); 1.591 - alSourcef(id, AL11.AL_SEC_OFFSET, src.getTimeOffset()); 1.592 - 1.593 - if (src.isDirectional()){ 1.594 - Vector3f dir = src.getDirection(); 1.595 - alSource3f(id, AL_DIRECTION, dir.x, dir.y, dir.z); 1.596 - alSourcef(id, AL_CONE_INNER_ANGLE, src.getInnerAngle()); 1.597 - alSourcef(id, AL_CONE_OUTER_ANGLE, src.getOuterAngle()); 1.598 - alSourcef(id, AL_CONE_OUTER_GAIN, 0); 1.599 - }else{ 1.600 - alSourcef(id, AL_CONE_INNER_ANGLE, 360); 1.601 - alSourcef(id, AL_CONE_OUTER_ANGLE, 360); 1.602 - alSourcef(id, AL_CONE_OUTER_GAIN, 1f); 1.603 - } 1.604 - } 1.605 - 1.606 - public void updateListenerParam(Listener listener, ListenerParam param){ 1.607 - checkDead(); 1.608 - synchronized (threadLock){ 1.609 - while (!threadLock.get()){ 1.610 - try { 1.611 - threadLock.wait(); 1.612 - } catch (InterruptedException ex) { 1.613 - } 1.614 - } 1.615 - if (audioDisabled) 1.616 - return; 1.617 - 1.618 - switch (param){ 1.619 - case Position: 1.620 - Vector3f pos = listener.getLocation(); 1.621 - alListener3f(AL_POSITION, pos.x, pos.y, pos.z); 1.622 - break; 1.623 - case Rotation: 1.624 - Vector3f dir = listener.getDirection(); 1.625 - Vector3f up = listener.getUp(); 1.626 - fb.rewind(); 1.627 - fb.put(dir.x).put(dir.y).put(dir.z); 1.628 - fb.put(up.x).put(up.y).put(up.z); 1.629 - fb.flip(); 1.630 - alListener(AL_ORIENTATION, fb); 1.631 - break; 1.632 - case Velocity: 1.633 - Vector3f vel = listener.getVelocity(); 1.634 - alListener3f(AL_VELOCITY, vel.x, vel.y, vel.z); 1.635 - break; 1.636 - case Volume: 1.637 - alListenerf(AL_GAIN, listener.getVolume()); 1.638 - break; 1.639 - } 1.640 - } 1.641 - } 1.642 - 1.643 - private void setListenerParams(Listener listener){ 1.644 - Vector3f pos = listener.getLocation(); 1.645 - Vector3f vel = listener.getVelocity(); 1.646 - Vector3f dir = listener.getDirection(); 1.647 - Vector3f up = listener.getUp(); 1.648 - 1.649 - alListener3f(AL_POSITION, pos.x, pos.y, pos.z); 1.650 - alListener3f(AL_VELOCITY, vel.x, vel.y, vel.z); 1.651 - fb.rewind(); 1.652 - fb.put(dir.x).put(dir.y).put(dir.z); 1.653 - fb.put(up.x).put(up.y).put(up.z); 1.654 - fb.flip(); 1.655 - alListener(AL_ORIENTATION, fb); 1.656 - alListenerf(AL_GAIN, listener.getVolume()); 1.657 - } 1.658 - 1.659 - private int newChannel(){ 1.660 - if (freeChans.size() > 0) 1.661 - return freeChans.remove(0); 1.662 - else if (nextChan < channels.length){ 1.663 - return nextChan++; 1.664 - }else{ 1.665 - return -1; 1.666 - } 1.667 - } 1.668 - 1.669 - private void freeChannel(int index){ 1.670 - if (index == nextChan-1){ 1.671 - nextChan--; 1.672 - } else{ 1.673 - freeChans.add(index); 1.674 - } 1.675 - } 1.676 - 1.677 - public void setEnvironment(Environment env){ 1.678 - checkDead(); 1.679 - synchronized (threadLock){ 1.680 - while (!threadLock.get()){ 1.681 - try { 1.682 - threadLock.wait(); 1.683 - } catch (InterruptedException ex) { 1.684 - } 1.685 - } 1.686 - if (audioDisabled) 1.687 - return; 1.688 - 1.689 - EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_DENSITY, env.getDensity()); 1.690 - EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_DIFFUSION, env.getDiffusion()); 1.691 - EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_GAIN, env.getGain()); 1.692 - EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_GAINHF, env.getGainHf()); 1.693 - EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_DECAY_TIME, env.getDecayTime()); 1.694 - EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_DECAY_HFRATIO, env.getDecayHFRatio()); 1.695 - EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_REFLECTIONS_GAIN, env.getReflectGain()); 1.696 - EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_REFLECTIONS_DELAY, env.getReflectDelay()); 1.697 - EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_LATE_REVERB_GAIN, env.getLateReverbGain()); 1.698 - EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_LATE_REVERB_DELAY, env.getLateReverbDelay()); 1.699 - EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_AIR_ABSORPTION_GAINHF, env.getAirAbsorbGainHf()); 1.700 - EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_ROOM_ROLLOFF_FACTOR, env.getRoomRolloffFactor()); 1.701 - 1.702 - // attach effect to slot 1.703 - EFX10.alAuxiliaryEffectSloti(reverbFxSlot, EFX10.AL_EFFECTSLOT_EFFECT, reverbFx); 1.704 - } 1.705 - } 1.706 - 1.707 - private boolean fillBuffer(AudioStream stream, int id){ 1.708 - int size = 0; 1.709 - int result; 1.710 - 1.711 - while (size < arrayBuf.length){ 1.712 - result = stream.readSamples(arrayBuf, size, arrayBuf.length - size); 1.713 - 1.714 - if(result > 0){ 1.715 - size += result; 1.716 - }else{ 1.717 - break; 1.718 - } 1.719 - } 1.720 - 1.721 - if(size == 0) 1.722 - return false; 1.723 - 1.724 - nativeBuf.clear(); 1.725 - nativeBuf.put(arrayBuf, 0, size); 1.726 - nativeBuf.flip(); 1.727 - 1.728 - alBufferData(id, convertFormat(stream), nativeBuf, stream.getSampleRate()); 1.729 - 1.730 - return true; 1.731 - } 1.732 - 1.733 - private boolean fillStreamingSource(int sourceId, AudioStream stream){ 1.734 - if (!stream.isOpen()) 1.735 - return false; 1.736 - 1.737 - boolean active = true; 1.738 - int processed = alGetSourcei(sourceId, AL_BUFFERS_PROCESSED); 1.739 - 1.740 -// while((processed--) != 0){ 1.741 - if (processed > 0){ 1.742 - int buffer; 1.743 - 1.744 - ib.position(0).limit(1); 1.745 - alSourceUnqueueBuffers(sourceId, ib); 1.746 - buffer = ib.get(0); 1.747 - 1.748 - active = fillBuffer(stream, buffer); 1.749 - 1.750 - ib.position(0).limit(1); 1.751 - ib.put(0, buffer); 1.752 - alSourceQueueBuffers(sourceId, ib); 1.753 - } 1.754 - 1.755 - if (!active && stream.isOpen()) 1.756 - stream.close(); 1.757 - 1.758 - return active; 1.759 - } 1.760 - 1.761 - private boolean attachStreamToSource(int sourceId, AudioStream stream){ 1.762 - boolean active = true; 1.763 - for (int id : stream.getIds()){ 1.764 - active = fillBuffer(stream, id); 1.765 - ib.position(0).limit(1); 1.766 - ib.put(id).flip(); 1.767 - alSourceQueueBuffers(sourceId, ib); 1.768 - } 1.769 - return active; 1.770 - } 1.771 - 1.772 - private boolean attachBufferToSource(int sourceId, AudioBuffer buffer){ 1.773 - alSourcei(sourceId, AL_BUFFER, buffer.getId()); 1.774 - return true; 1.775 - } 1.776 - 1.777 - private boolean attachAudioToSource(int sourceId, AudioData data){ 1.778 - if (data instanceof AudioBuffer){ 1.779 - return attachBufferToSource(sourceId, (AudioBuffer) data); 1.780 - }else if (data instanceof AudioStream){ 1.781 - return attachStreamToSource(sourceId, (AudioStream) data); 1.782 - } 1.783 - throw new UnsupportedOperationException(); 1.784 - } 1.785 - 1.786 - private void clearChannel(int index){ 1.787 - // make room at this channel 1.788 - if (chanSrcs[index] != null){ 1.789 - AudioNode src = chanSrcs[index]; 1.790 - 1.791 - int sourceId = channels[index]; 1.792 - alSourceStop(sourceId); 1.793 - 1.794 - if (src.getAudioData() instanceof AudioStream){ 1.795 - AudioStream str = (AudioStream) src.getAudioData(); 1.796 - ib.position(0).limit(STREAMING_BUFFER_COUNT); 1.797 - ib.put(str.getIds()).flip(); 1.798 - alSourceUnqueueBuffers(sourceId, ib); 1.799 - }else if (src.getAudioData() instanceof AudioBuffer){ 1.800 - alSourcei(sourceId, AL_BUFFER, 0); 1.801 - } 1.802 - 1.803 - if (src.getDryFilter() != null){ 1.804 - // detach filter 1.805 - alSourcei(sourceId, EFX10.AL_DIRECT_FILTER, EFX10.AL_FILTER_NULL); 1.806 - } 1.807 - if (src.isPositional()){ 1.808 - AudioNode pas = (AudioNode) src; 1.809 - if (pas.isReverbEnabled()) { 1.810 - AL11.alSource3i(sourceId, EFX10.AL_AUXILIARY_SEND_FILTER, 0, 0, EFX10.AL_FILTER_NULL); 1.811 - } 1.812 - } 1.813 - 1.814 - chanSrcs[index] = null; 1.815 - } 1.816 - } 1.817 - 1.818 - public void update(float tpf){ 1.819 - //ByteBuffer test = BufferUtils.createByteBuffer(1); 1.820 - //AurellemTransport.getAuxSamples(AL.getDevice(), test); 1.821 - } 1.822 - 1.823 - Vector<Byte> fullWaveData1 = new Vector<Byte>(); 1.824 - Vector<Byte> fullWaveData2 = new Vector<Byte>(); 1.825 - 1.826 - public void updateInThread(float tpf){ 1.827 - if (audioDisabled) 1.828 - return; 1.829 - 1.830 - step(); 1.831 - ByteBuffer test = BufferUtils.createByteBuffer(4096); 1.832 - test.clear(); 1.833 - this.getMainSamples(test); 1.834 - byte[] waveData = new byte[4096]; 1.835 - test.get(waveData, 0, 4096); 1.836 - //System.out.println("J DATA:"); 1.837 - /*for (int j = 0; j < 1; j++){ 1.838 - for(int i = 64 * j; i < (64*j) + 64; i++){ 1.839 - System.out.print(waveData[i]); 1.840 - } 1.841 - System.out.println(); 1.842 - }*/ 1.843 - 1.844 - ByteBuffer test2 = BufferUtils.createByteBuffer(4096); 1.845 - test2.clear(); 1.846 - this.getAuxSamples(test2); 1.847 - byte[] waveData2 = new byte[4096]; 1.848 - test2.get(waveData2, 0, 4096); 1.849 - //System.out.print("wave1:"); 1.850 - //for (int j = 0; j< 32; j++){ 1.851 - // System.out.print(waveData[j]+","); 1.852 - // } 1.853 - //System.out.println(); 1.854 - //System.out.print("wave2:"); 1.855 - // for (int j = 0; j< 4096; j++){ 1.856 - // if (waveData2[j] != 0){ 1.857 - // System.out.println("fucked at : " + j); 1.858 - // } 1.859 - 1.860 - /* System.out.print(waveData2[j]+","); 1.861 - if (0 == (j % 64)){System.out.println();}*/ 1.862 - //} 1.863 - //System.out.println(); 1.864 - 1.865 - for (byte b : waveData){ 1.866 - this.fullWaveData1.add(b); 1.867 - } 1.868 - 1.869 - for (byte b : waveData2){ 1.870 - this.fullWaveData2.add(b); 1.871 - } 1.872 - 1.873 - 1.874 - for (int i = 0; i < channels.length; i++){ 1.875 - AudioNode src = chanSrcs[i]; 1.876 - if (src == null) 1.877 - continue; 1.878 - 1.879 - int sourceId = channels[i]; 1.880 - 1.881 - // is the source bound to this channel 1.882 - // if false, it's an instanced playback 1.883 - boolean boundSource = i == src.getChannel(); 1.884 - 1.885 - // source's data is streaming 1.886 - boolean streaming = src.getAudioData() instanceof AudioStream; 1.887 - 1.888 - // only buffered sources can be bound 1.889 - assert (boundSource && streaming) || (!streaming); 1.890 - 1.891 - int state = alGetSourcei(sourceId, AL_SOURCE_STATE); 1.892 - boolean wantPlaying = src.getStatus() == Status.Playing; 1.893 - boolean stopped = state == AL_STOPPED; 1.894 - 1.895 - if (streaming && wantPlaying){ 1.896 - AudioStream stream = (AudioStream) src.getAudioData(); 1.897 - if (stream.isOpen()){ 1.898 - fillStreamingSource(sourceId, stream); 1.899 - if (stopped) 1.900 - alSourcePlay(sourceId); 1.901 - 1.902 - }else{ 1.903 - if (stopped){ 1.904 - // became inactive 1.905 - src.setStatus(Status.Stopped); 1.906 - src.setChannel(-1); 1.907 - clearChannel(i); 1.908 - freeChannel(i); 1.909 - 1.910 - // And free the audio since it cannot be 1.911 - // played again anyway. 1.912 - deleteAudioData(stream); 1.913 - } 1.914 - } 1.915 - }else if (!streaming){ 1.916 - boolean paused = state == AL_PAUSED; 1.917 - 1.918 - // make sure OAL pause state & source state coincide 1.919 - assert (src.getStatus() == Status.Paused && paused) || (!paused); 1.920 - 1.921 - if (stopped){ 1.922 - if (boundSource){ 1.923 - src.setStatus(Status.Stopped); 1.924 - src.setChannel(-1); 1.925 - } 1.926 - clearChannel(i); 1.927 - freeChannel(i); 1.928 - } 1.929 - } 1.930 - } 1.931 - } 1.932 - 1.933 - public void setListener(Listener listener) { 1.934 - checkDead(); 1.935 - synchronized (threadLock){ 1.936 - while (!threadLock.get()){ 1.937 - try { 1.938 - threadLock.wait(); 1.939 - } catch (InterruptedException ex) { 1.940 - } 1.941 - } 1.942 - if (audioDisabled) 1.943 - return; 1.944 - 1.945 - if (this.listener != null){ 1.946 - // previous listener no longer associated with current 1.947 - // renderer 1.948 - this.listener.setRenderer(null); 1.949 - } 1.950 - 1.951 - this.listener = listener; 1.952 - this.listener.setRenderer(this); 1.953 - setListenerParams(listener); 1.954 - } 1.955 - } 1.956 - 1.957 - public void playSourceInstance(AudioNode src){ 1.958 - checkDead(); 1.959 - synchronized (threadLock){ 1.960 - while (!threadLock.get()){ 1.961 - try { 1.962 - threadLock.wait(); 1.963 - } catch (InterruptedException ex) { 1.964 - } 1.965 - } 1.966 - if (audioDisabled) 1.967 - return; 1.968 - 1.969 - if (src.getAudioData() instanceof AudioStream) 1.970 - throw new UnsupportedOperationException( 1.971 - "Cannot play instances " + 1.972 - "of audio streams. Use playSource() instead."); 1.973 - 1.974 - if (src.getAudioData().isUpdateNeeded()){ 1.975 - updateAudioData(src.getAudioData()); 1.976 - } 1.977 - 1.978 - // create a new index for an audio-channel 1.979 - int index = newChannel(); 1.980 - if (index == -1) 1.981 - return; 1.982 - 1.983 - int sourceId = channels[index]; 1.984 - 1.985 - clearChannel(index); 1.986 - 1.987 - // set parameters, like position and max distance 1.988 - setSourceParams(sourceId, src, true); 1.989 - attachAudioToSource(sourceId, src.getAudioData()); 1.990 - chanSrcs[index] = src; 1.991 - 1.992 - // play the channel 1.993 - alSourcePlay(sourceId); 1.994 - } 1.995 - } 1.996 - 1.997 - 1.998 - public void playSource(AudioNode src) { 1.999 - checkDead(); 1.1000 - synchronized (threadLock){ 1.1001 - while (!threadLock.get()){ 1.1002 - try { 1.1003 - threadLock.wait(); 1.1004 - } catch (InterruptedException ex) { 1.1005 - } 1.1006 - } 1.1007 - if (audioDisabled) 1.1008 - return; 1.1009 - 1.1010 - //assert src.getStatus() == Status.Stopped || src.getChannel() == -1; 1.1011 - 1.1012 - if (src.getStatus() == Status.Playing){ 1.1013 - return; 1.1014 - }else if (src.getStatus() == Status.Stopped){ 1.1015 - 1.1016 - // allocate channel to this source 1.1017 - int index = newChannel(); 1.1018 - if (index == -1) { 1.1019 - logger.log(Level.WARNING, "No channel available to play {0}", src); 1.1020 - return; 1.1021 - } 1.1022 - clearChannel(index); 1.1023 - src.setChannel(index); 1.1024 - 1.1025 - AudioData data = src.getAudioData(); 1.1026 - if (data.isUpdateNeeded()) 1.1027 - updateAudioData(data); 1.1028 - 1.1029 - chanSrcs[index] = src; 1.1030 - setSourceParams(channels[index], src, false); 1.1031 - attachAudioToSource(channels[index], data); 1.1032 - } 1.1033 - 1.1034 - alSourcePlay(channels[src.getChannel()]); 1.1035 - src.setStatus(Status.Playing); 1.1036 - } 1.1037 - } 1.1038 - 1.1039 - 1.1040 - public void pauseSource(AudioNode src) { 1.1041 - checkDead(); 1.1042 - synchronized (threadLock){ 1.1043 - while (!threadLock.get()){ 1.1044 - try { 1.1045 - threadLock.wait(); 1.1046 - } catch (InterruptedException ex) { 1.1047 - } 1.1048 - } 1.1049 - if (audioDisabled) 1.1050 - return; 1.1051 - 1.1052 - if (src.getStatus() == Status.Playing){ 1.1053 - assert src.getChannel() != -1; 1.1054 - 1.1055 - alSourcePause(channels[src.getChannel()]); 1.1056 - src.setStatus(Status.Paused); 1.1057 - } 1.1058 - } 1.1059 - } 1.1060 - 1.1061 - 1.1062 - public void stopSource(AudioNode src) { 1.1063 - synchronized (threadLock){ 1.1064 - while (!threadLock.get()){ 1.1065 - try { 1.1066 - threadLock.wait(); 1.1067 - } catch (InterruptedException ex) { 1.1068 - } 1.1069 - } 1.1070 - if (audioDisabled) 1.1071 - return; 1.1072 - 1.1073 - if (src.getStatus() != Status.Stopped){ 1.1074 - int chan = src.getChannel(); 1.1075 - assert chan != -1; // if it's not stopped, must have id 1.1076 - 1.1077 - src.setStatus(Status.Stopped); 1.1078 - src.setChannel(-1); 1.1079 - clearChannel(chan); 1.1080 - freeChannel(chan); 1.1081 - 1.1082 - if (src.getAudioData() instanceof AudioStream) { 1.1083 - 1.1084 - AudioStream stream = (AudioStream)src.getAudioData(); 1.1085 - if (stream.isOpen()) { 1.1086 - stream.close(); 1.1087 - } 1.1088 - 1.1089 - // And free the audio since it cannot be 1.1090 - // played again anyway. 1.1091 - deleteAudioData(src.getAudioData()); 1.1092 - } 1.1093 - } 1.1094 - } 1.1095 - } 1.1096 - 1.1097 - private int convertFormat(AudioData ad){ 1.1098 - switch (ad.getBitsPerSample()){ 1.1099 - case 8: 1.1100 - if (ad.getChannels() == 1) 1.1101 - return AL_FORMAT_MONO8; 1.1102 - else if (ad.getChannels() == 2) 1.1103 - return AL_FORMAT_STEREO8; 1.1104 - 1.1105 - break; 1.1106 - case 16: 1.1107 - if (ad.getChannels() == 1) 1.1108 - return AL_FORMAT_MONO16; 1.1109 - else 1.1110 - return AL_FORMAT_STEREO16; 1.1111 - } 1.1112 - throw new UnsupportedOperationException("Unsupported channels/bits combination: "+ 1.1113 - "bits="+ad.getBitsPerSample()+", channels="+ad.getChannels()); 1.1114 - } 1.1115 - 1.1116 - private void updateAudioBuffer(AudioBuffer ab){ 1.1117 - int id = ab.getId(); 1.1118 - if (ab.getId() == -1){ 1.1119 - ib.position(0).limit(1); 1.1120 - alGenBuffers(ib); 1.1121 - id = ib.get(0); 1.1122 - ab.setId(id); 1.1123 - } 1.1124 - 1.1125 - ab.getData().clear(); 1.1126 - alBufferData(id, convertFormat(ab), ab.getData(), ab.getSampleRate()); 1.1127 - ab.clearUpdateNeeded(); 1.1128 - } 1.1129 - 1.1130 - private void updateAudioStream(AudioStream as){ 1.1131 - if (as.getIds() != null){ 1.1132 - deleteAudioData(as); 1.1133 - } 1.1134 - 1.1135 - int[] ids = new int[STREAMING_BUFFER_COUNT]; 1.1136 - ib.position(0).limit(STREAMING_BUFFER_COUNT); 1.1137 - alGenBuffers(ib); 1.1138 - ib.position(0).limit(STREAMING_BUFFER_COUNT); 1.1139 - ib.get(ids); 1.1140 - 1.1141 - as.setIds(ids); 1.1142 - as.clearUpdateNeeded(); 1.1143 - } 1.1144 - 1.1145 - private void updateAudioData(AudioData ad){ 1.1146 - if (ad instanceof AudioBuffer){ 1.1147 - updateAudioBuffer((AudioBuffer) ad); 1.1148 - }else if (ad instanceof AudioStream){ 1.1149 - updateAudioStream((AudioStream) ad); 1.1150 - } 1.1151 - } 1.1152 - 1.1153 - public void deleteAudioData(AudioData ad){ 1.1154 - synchronized (threadLock){ 1.1155 - while (!threadLock.get()){ 1.1156 - try { 1.1157 - threadLock.wait(); 1.1158 - } catch (InterruptedException ex) { 1.1159 - } 1.1160 - } 1.1161 - if (audioDisabled) 1.1162 - return; 1.1163 - 1.1164 - if (ad instanceof AudioBuffer){ 1.1165 - AudioBuffer ab = (AudioBuffer) ad; 1.1166 - int id = ab.getId(); 1.1167 - if (id != -1){ 1.1168 - ib.put(0,id); 1.1169 - ib.position(0).limit(1); 1.1170 - alDeleteBuffers(ib); 1.1171 - ab.resetObject(); 1.1172 - } 1.1173 - }else if (ad instanceof AudioStream){ 1.1174 - AudioStream as = (AudioStream) ad; 1.1175 - int[] ids = as.getIds(); 1.1176 - if (ids != null){ 1.1177 - ib.clear(); 1.1178 - ib.put(ids).flip(); 1.1179 - alDeleteBuffers(ib); 1.1180 - as.resetObject(); 1.1181 - } 1.1182 - } 1.1183 - } 1.1184 - } 1.1185 - 1.1186 -}
2.1 --- a/cleanup-message.txt Tue Oct 25 13:16:27 2011 -0700 2.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 2.3 @@ -1,100 +0,0 @@ 2.4 -My name is Robert McIntyre. I am seeking help packaging some changes 2.5 -I've made to open-al. 2.6 - 2.7 -* tl;dr how do I distribute changes to open-al which involve adding a 2.8 - new device? 2.9 - 2.10 -* Background / Motivation 2.11 - 2.12 -I'm working on an AI simulation involving multiple listeners, where 2.13 -each listener is a separate AI entity. Since each AI entity can move 2.14 -independently, I needed to add multiple listener functionality to 2.15 -open-al. Furthermore, my entire simulation allows time to dilate 2.16 -depending on how hard the entities are collectively "thinking," so 2.17 -that the entities can keep up with the simulation. Therefore, I 2.18 -needed to have a system that renders sound on-demand instead of trying 2.19 -to render in real time as open-al does. 2.20 - 2.21 -I don't need any of the more advanced effects, just 3D positioning, 2.22 -and I'm only using open-al from jMonkeyEngine3 that uses the LWJGL 2.23 -bindings that importantly only allow access to one and only one 2.24 -context. 2.25 - 2.26 -Under these constraints, I made a new device which renders sound in 2.27 -small, user-defined increments. It must be explicitly told to render 2.28 -sound or it won't do anything. It maintains a separate "auxiliary 2.29 -context" for every additional listener, and syncs the sources from the 2.30 -LWJGL context whenever it is about to render samples. I've tested it 2.31 -and it works quite well for my purposes. So far, I've gotten 1,000 2.32 -separate listeners to work in a single simulation easily. 2.33 - 2.34 -The code is here: 2.35 -http://aurellem.localhost/audio-send/html/send.html 2.36 -No criticism is too harsh! 2.37 - 2.38 -Note that the java JNI bindings that are part of the device code right 2.39 -now would be moved to a separate file the the same way that LWJGL does 2.40 -it. I left them there for now to show how the device might be used. 2.41 - 2.42 -Although I made this for my own AI work, it's ideal for recording 2.43 -perfect audio from a video game to create trailers/demos, since the 2.44 -computer doesn't have to try to record the sound in real time. This 2.45 -device could be used to record audio in any system that wraps open-al 2.46 -and only exposes one context, which is what many wrappers do. 2.47 - 2.48 - 2.49 -* Actual Question 2.50 - 2.51 -My question is about packaging --- how do you recommend I distribute 2.52 -my new device? I got it to work by just grafting it on the open-al's 2.53 -primitive object system, but this requires quite a few changes to main 2.54 -open-al source files, and as far as I can tell requires me to 2.55 -recompile open-al against my new device. 2.56 - 2.57 -I also don't want the user to be able to hide my devices presence 2.58 -using their ~/.alsoftrc file, since that gets in the way of easy 2.59 -recording when the system is wrapped several layers deep, and they've 2.60 -already implicitly requested my device anyway by using my code in the 2.61 -first place. 2.62 - 2.63 -The options I have thought of so far are: 2.64 - 2.65 -1.) Create my own C-artifact, compiled against open-al, which somehow 2.66 -"hooks in" my device to open-al and forces open-al to use it to the 2.67 -exclusion of all other devices. This new artifact would have bindings 2.68 -for java, etc. I don't know how to do this, since there doesn't seem 2.69 -to be any way to access the list of devices in Alc/ALc.c for example. 2.70 -In order to add a new device to open-al I had to modify 5 separate 2.71 -files, documented here: 2.72 - 2.73 -http://aurellem.localhost/audio-send/html/add-new-device.html 2.74 - 2.75 -and there doesn't seem to be a way to get the same effect 2.76 -programmatically. 2.77 - 2.78 -2.) Strip down open-al to a minimal version that only has my device 2.79 -and deal with selecting the right open-al library at a higher level, 2.80 -depending on whether the user wants to record sound or actually hear 2.81 -it. I don't like this because I can't easily benefit from 2.82 -improvements in the main open-al distribution. It also would involve 2.83 -more significant modification to jMonkeyEngine3's logic which selects 2.84 -the appropriate C-artifact at runtime. 2.85 - 2.86 -3.) Get this new device added to open-al, and provide a java wrapper 2.87 -for it in a separate artifact. Problem here is that this device does 2.88 -not have the same semantics as the other devices --- it must be told 2.89 -to render sound, doesn't support multiple user-created contexts, and 2.90 -it exposes extra functions for retrieving the rendered sounds. It also 2.91 -might be too "niche" for open-al proper. 2.92 - 2.93 -4.) Maybe abandon the device metaphor and use something better suited 2.94 -to my problem that /can/ be done as in (1)? 2.95 - 2.96 - 2.97 -I'm sure someone here knows enough about open-al's devices to give me 2.98 -a better solution than these 4! All help would be most appreciated. 2.99 - 2.100 -sincerely, 2.101 ---Robert McIntyre 2.102 - 2.103 -
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/org/cleanup-message.txt Tue Oct 25 13:17:37 2011 -0700 3.3 @@ -0,0 +1,100 @@ 3.4 +My name is Robert McIntyre. I am seeking help packaging some changes 3.5 +I've made to open-al. 3.6 + 3.7 +* tl;dr how do I distribute changes to open-al which involve adding a 3.8 + new device? 3.9 + 3.10 +* Background / Motivation 3.11 + 3.12 +I'm working on an AI simulation involving multiple listeners, where 3.13 +each listener is a separate AI entity. Since each AI entity can move 3.14 +independently, I needed to add multiple listener functionality to 3.15 +open-al. Furthermore, my entire simulation allows time to dilate 3.16 +depending on how hard the entities are collectively "thinking," so 3.17 +that the entities can keep up with the simulation. Therefore, I 3.18 +needed to have a system that renders sound on-demand instead of trying 3.19 +to render in real time as open-al does. 3.20 + 3.21 +I don't need any of the more advanced effects, just 3D positioning, 3.22 +and I'm only using open-al from jMonkeyEngine3 that uses the LWJGL 3.23 +bindings that importantly only allow access to one and only one 3.24 +context. 3.25 + 3.26 +Under these constraints, I made a new device which renders sound in 3.27 +small, user-defined increments. It must be explicitly told to render 3.28 +sound or it won't do anything. It maintains a separate "auxiliary 3.29 +context" for every additional listener, and syncs the sources from the 3.30 +LWJGL context whenever it is about to render samples. I've tested it 3.31 +and it works quite well for my purposes. So far, I've gotten 1,000 3.32 +separate listeners to work in a single simulation easily. 3.33 + 3.34 +The code is here: 3.35 +http://aurellem.localhost/audio-send/html/send.html 3.36 +No criticism is too harsh! 3.37 + 3.38 +Note that the java JNI bindings that are part of the device code right 3.39 +now would be moved to a separate file the the same way that LWJGL does 3.40 +it. I left them there for now to show how the device might be used. 3.41 + 3.42 +Although I made this for my own AI work, it's ideal for recording 3.43 +perfect audio from a video game to create trailers/demos, since the 3.44 +computer doesn't have to try to record the sound in real time. This 3.45 +device could be used to record audio in any system that wraps open-al 3.46 +and only exposes one context, which is what many wrappers do. 3.47 + 3.48 + 3.49 +* Actual Question 3.50 + 3.51 +My question is about packaging --- how do you recommend I distribute 3.52 +my new device? I got it to work by just grafting it on the open-al's 3.53 +primitive object system, but this requires quite a few changes to main 3.54 +open-al source files, and as far as I can tell requires me to 3.55 +recompile open-al against my new device. 3.56 + 3.57 +I also don't want the user to be able to hide my devices presence 3.58 +using their ~/.alsoftrc file, since that gets in the way of easy 3.59 +recording when the system is wrapped several layers deep, and they've 3.60 +already implicitly requested my device anyway by using my code in the 3.61 +first place. 3.62 + 3.63 +The options I have thought of so far are: 3.64 + 3.65 +1.) Create my own C-artifact, compiled against open-al, which somehow 3.66 +"hooks in" my device to open-al and forces open-al to use it to the 3.67 +exclusion of all other devices. This new artifact would have bindings 3.68 +for java, etc. I don't know how to do this, since there doesn't seem 3.69 +to be any way to access the list of devices in Alc/ALc.c for example. 3.70 +In order to add a new device to open-al I had to modify 5 separate 3.71 +files, documented here: 3.72 + 3.73 +http://aurellem.localhost/audio-send/html/add-new-device.html 3.74 + 3.75 +and there doesn't seem to be a way to get the same effect 3.76 +programmatically. 3.77 + 3.78 +2.) Strip down open-al to a minimal version that only has my device 3.79 +and deal with selecting the right open-al library at a higher level, 3.80 +depending on whether the user wants to record sound or actually hear 3.81 +it. I don't like this because I can't easily benefit from 3.82 +improvements in the main open-al distribution. It also would involve 3.83 +more significant modification to jMonkeyEngine3's logic which selects 3.84 +the appropriate C-artifact at runtime. 3.85 + 3.86 +3.) Get this new device added to open-al, and provide a java wrapper 3.87 +for it in a separate artifact. Problem here is that this device does 3.88 +not have the same semantics as the other devices --- it must be told 3.89 +to render sound, doesn't support multiple user-created contexts, and 3.90 +it exposes extra functions for retrieving the rendered sounds. It also 3.91 +might be too "niche" for open-al proper. 3.92 + 3.93 +4.) Maybe abandon the device metaphor and use something better suited 3.94 +to my problem that /can/ be done as in (1)? 3.95 + 3.96 + 3.97 +I'm sure someone here knows enough about open-al's devices to give me 3.98 +a better solution than these 4! All help would be most appreciated. 3.99 + 3.100 +sincerely, 3.101 +--Robert McIntyre 3.102 + 3.103 +