Mercurial > audio-send
diff RecordAudioRenderer.java @ 0:f9476ff7637e
initial forking of open-al to create multiple listeners
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Tue, 25 Oct 2011 13:02:31 -0700 |
parents | |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/RecordAudioRenderer.java Tue Oct 25 13:02:31 2011 -0700 1.3 @@ -0,0 +1,1183 @@ 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 +}