public void dispose() { if (buffers == null) return; if (sourceID != -1) { audio.freeSource(sourceID); sourceID = -1; } audio.getAL().alDeleteBuffers(buffers.limit(), buffers); buffers = null; }
public void writeSamples(byte[] data, int offset, int length) { if (length < 0) throw new IllegalArgumentException("length cannot be < 0."); if (sourceID == -1) { sourceID = audio.obtainSource(true); if (sourceID == -1) return; if (buffers == null) { buffers = Buffers.newDirectIntBuffer(bufferCount); audio.getAL().alGenBuffers(buffers.limit(), buffers); if (audio.getAL().alGetError() != ALConstants.AL_NO_ERROR) throw new GdxRuntimeException("Unabe to allocate audio buffers."); } audio.getAL().alSourcei(sourceID, ALConstants.AL_LOOPING, ALConstants.AL_FALSE); audio.getAL().alSourcef(sourceID, ALConstants.AL_GAIN, volume); // Fill initial buffers. int queuedBuffers = 0; for (int i = 0; i < bufferCount; i++) { int bufferID = buffers.get(i); int written = Math.min(bufferSize, length); tempBuffer.clear(); tempBuffer.put(data, offset, written).flip(); audio .getAL() .alBufferData(bufferID, format, tempBuffer, tempBuffer.remaining(), sampleRate); ib.put(0, bufferID).rewind(); audio.getAL().alSourceQueueBuffers(sourceID, ib.limit(), ib); length -= written; offset += written; queuedBuffers++; } // Queue rest of buffers, empty. tempBuffer.clear().flip(); for (int i = queuedBuffers; i < bufferCount; i++) { int bufferID = buffers.get(i); audio .getAL() .alBufferData(bufferID, format, tempBuffer, tempBuffer.remaining(), sampleRate); audio.getAL().alSourceQueueBuffers(sourceID, ib.limit(), ib); } audio.getAL().alSourcePlay(sourceID); isPlaying = true; } while (length > 0) { int written = fillBuffer(data, offset, length); length -= written; offset += written; } }
/** Blocks until some of the data could be buffered. */ private int fillBuffer(byte[] data, int offset, int length) { int written = Math.min(bufferSize, length); outer: while (true) { audio.getAL().alGetSourcei(sourceID, ALConstants.AL_BUFFERS_PROCESSED, ib); int buffers = ib.get(0); while (buffers-- > 0) { // FIXME ib.put(0, buffers).rewind(); audio.getAL().alSourceUnqueueBuffers(sourceID, ib.limit(), ib); int bufferID = ib.get(0); if (bufferID == ALConstants.AL_INVALID_VALUE) break; renderedSeconds += secondsPerBuffer; tempBuffer.clear(); tempBuffer.put(data, offset, written).flip(); audio .getAL() .alBufferData(bufferID, format, tempBuffer, tempBuffer.remaining(), sampleRate); ib.put(0, bufferID).rewind(); audio.getAL().alSourceQueueBuffers(sourceID, ib.limit(), ib); break outer; } // Wait for buffer to be free. try { Thread.sleep((long) (1000 * secondsPerBuffer / bufferCount)); } catch (InterruptedException ignored) { } } // A buffer underflow will cause the source to stop. if (!isPlaying || !isCurrentSourcePlaying()) { audio.getAL().alSourcePlay(sourceID); isPlaying = true; } return written; }
public float getPosition() { if (sourceID == -1) return 0; audio.getAL().alGetSourcef(sourceID, ALConstants.AL_SEC_OFFSET, fb); return renderedSeconds + fb.get(0); }
public void setVolume(float volume) { this.volume = volume; if (sourceID != -1) audio.getAL().alSourcef(sourceID, ALConstants.AL_GAIN, volume); }
private boolean isCurrentSourcePlaying() { audio.getAL().alGetSourcei(sourceID, ALConstants.AL_SOURCE_STATE, ib); return (ib.get(0) == ALConstants.AL_PLAYING); }