package org.terasology.audio; import org.lwjgl.openal.AL10; import org.terasology.asset.AssetUri; import java.net.URL; import java.nio.ByteBuffer; import static org.lwjgl.openal.AL10.AL_SIZE; import static org.lwjgl.openal.AL10.alGetBufferi; public abstract class AbstractStreamingSound implements Sound { private final static int BUFFER_POOL_SIZE = 3; private final AssetUri uri; protected final URL audioSource; protected int[] buffers; protected int lastUpdatedBuffer; public AbstractStreamingSound(AssetUri uri, URL source) { this.uri = uri; this.audioSource = source; this.initializeBuffers(); this.reset(); } @Override public AssetUri getURI() { return uri; } protected abstract ByteBuffer fetchData(); public int[] getBuffers() { return this.buffers; } public boolean updateBuffer(int buffer) { ByteBuffer bufferData = this.fetchData(); if (bufferData == null || bufferData.limit() == 0) { return false; // no more data available } AL10.alBufferData(buffer, this.getChannels() == 1 ? AL10.AL_FORMAT_MONO16 : AL10.AL_FORMAT_STEREO16, bufferData, this.getSamplingRate()); OpenALException.checkState("Uploading buffer data"); this.lastUpdatedBuffer = buffer; return true; } private void initializeBuffers() { buffers = new int[BUFFER_POOL_SIZE]; for (int i = 0; i < buffers.length; i++) { buffers[i] = AL10.alGenBuffers(); OpenALException.checkState("Creating buffer"); } this.lastUpdatedBuffer = buffers[0]; } @Override public int getBufferSize() { return alGetBufferi(lastUpdatedBuffer, AL_SIZE); } @Override public int getBufferId() { return lastUpdatedBuffer; } public abstract int getBufferBits(); @Override protected void finalize() throws Throwable { for (int i = 0; i < buffers.length; i++) { if (buffers[i] != 0) { AL10.alDeleteBuffers(buffers[i]); } } } }