package tk.amberide.engine.al;
import java.nio.IntBuffer;
import javax.sound.sampled.AudioFormat;
import org.lwjgl.BufferUtils;
import static org.lwjgl.openal.AL10.*;
import org.lwjgl.openal.AL11;
import org.lwjgl.openal.OpenALException;
/**
* A sound that can be played through OpenAL
*
* @author Kevin Glass
* @author Nathan Sweet <misc@n4te.com>
*/
public class ALAudio implements Audio {
protected int buffer;
private int index = -1;
private float length;
private boolean loop;
private float volume = 1f;
private AudioFormat format;
/**
* Create a new sound
*
* @param store The sound store from which the sound was created
* @param buffer The buffer containing the sound data
*/
ALAudio(int buffer, AudioFormat format) {
this.buffer = buffer;
this.format = format;
int bytes = alGetBufferi(buffer, AL_SIZE);
int bits = alGetBufferi(buffer, AL_BITS);
int channels = alGetBufferi(buffer, AL_CHANNELS);
int freq = alGetBufferi(buffer, AL_FREQUENCY);
length = ((bytes / (bits / 8)) / (float) freq) / channels;
}
/**
* @see org.newdawn.slick.openal.Audio#isPlaying()
*/
public State getState() {
if (index != -1 && alGetSourcei(index, AL_SOURCE_STATE) == AL_PLAYING) {
return State.PLAYING;
} else if (index != -1) {
return State.PAUSED;
}
return State.STOPPED;
}
public void start() {
if (index != -1) {
alSourcePlay(index);
} else {
int nextSource = findFreeSource();
if (nextSource == -1) {
index = -1;
return;
}
index = getSource();
alSourceStop(index);
alSourcei(index, AL_BUFFER, buffer);
alSourcef(index, AL_PITCH, 1);
alSourcef(index, AL_GAIN, volume);
alSourcei(index, AL_LOOPING, loop ? AL_TRUE : AL_FALSE);
alSourcePlay(index);
}
}
public void pause() {
if (index != -1) {
alSourcePause(index);
}
}
/**
* @see org.newdawn.slick.openal.Audio#stop()
*/
public void stop() {
if (index != -1) {
alSourceStop(index);
index = -1;
}
}
public void setVolume(float volume) {
this.volume = volume;
if (index != -1) {
alSourcef(index, AL_PITCH, volume);
}
}
public float getVolume() {
return volume;
}
public void setLooping(boolean flag) {
loop = flag;
if (index != -1) {
alSourcei(index, AL_LOOPING, loop ? AL_TRUE : AL_FALSE);
}
}
public boolean isLooping() {
return loop;
}
public void setMillisecondPosition(long position) {
alSourcei(index, AL11.AL_SEC_OFFSET, (int) ((position / 1000) % length));
}
public long getMillisecondPosition() {
return alGetSourcei(index, AL11.AL_SEC_OFFSET) * 1000;
}
public long getMillisecondLength() {
return (long) (length * 1000);
}
public AudioFormat getFormat() {
return format;
}
private int findFreeSource() {
for (int i = 1; i < 64 - 1; i++) {
int state = alGetSourcei(getSource(), AL_SOURCE_STATE);
if ((state != AL_PLAYING) && (state != AL_PAUSED)) {
return i;
}
}
return -1;
}
private int getSource() {
IntBuffer temp = BufferUtils.createIntBuffer(1);
try {
alGenSources(temp);
if (alGetError() == AL_NO_ERROR) {
return temp.get(0);
}
} catch (OpenALException e) {
}
return -1;
}
}