package com.bitwaffle.spaceguts.audio; import java.nio.FloatBuffer; import java.nio.IntBuffer; import org.lwjgl.BufferUtils; import org.lwjgl.openal.AL10; import org.lwjgl.util.vector.Vector3f; import com.bitwaffle.spaceout.resources.Sounds; /** * Plays a sound from {@link Sounds} at a given location and velocity * @author TranquilMarmot */ public class SoundSource { /** Buffers for transferring data */ private FloatBuffer posBuf, velBuf; /** Handle to use for source */ private int handle; /** If this is set to true, then this source should be removed as soon as it's done playing its sound */ public boolean removeFlag = false; private boolean loop; private float pitch, currentGain; private float defaultGain; /** * Create a new source for sound * @param sound Sound to play * @param loop Whether or not to loop sound * @param location Initial location * @param velocity Initial velocity */ public SoundSource(Sounds sound, boolean loop, Vector3f location, Vector3f velocity){ // create buffers posBuf = BufferUtils.createFloatBuffer(3); velBuf = BufferUtils.createFloatBuffer(3); // generate handle IntBuffer buf = BufferUtils.createIntBuffer(1); AL10.alGenSources(buf); handle = buf.get(0); // set location and speed setLocation(location); setVelocity(velocity); this.pitch = sound.pitch; this.currentGain = sound.gain; this.defaultGain = sound.gain; this.loop = loop; // set values AL10.alSourcei(handle, AL10.AL_BUFFER, sound.getHandle()); AL10.alSourcef(handle, AL10.AL_PITCH, pitch); AL10.alSourcei(handle, AL10.AL_LOOPING, loop ? AL10.AL_TRUE : AL10.AL_FALSE); setGain(Audio.isMuted() ? 0.0f : currentGain); // all sound sources are added to this list so they can be deleted when the game exits Audio.soundSources.add(this); } /** * Sets the pitch of the sound * @param pitch New pitch */ public void setPitch(float pitch){ this.pitch = pitch; AL10.alSourcef(handle, AL10.AL_PITCH, pitch); } /** * @return Current pitch */ public float getPitch(){ return pitch; } /** * @return Current gain */ public float getCurrentGain(){ return currentGain; } /** * @return Default gain */ public float getDefaultGain(){ return defaultGain; } /** * Sets the gain of the sound * @param gain New gain (0 = none, 0.5 = 50%, 1 = 100%, 2 = 200% etc.) */ public void setGain(float gain){ this.currentGain = gain; AL10.alSourcef(handle, AL10.AL_GAIN, Audio.currentVolume() * gain); } /** * Sets the location of the sound * @param location New location */ public void setLocation(Vector3f location){ posBuf.clear(); posBuf.put(location.x); posBuf.put(location.y); posBuf.put(location.z); posBuf.rewind(); AL10.alSource (handle, AL10.AL_POSITION, posBuf); } /** * Sets the velocity of the sound * @param velocity New velocity */ public void setVelocity(Vector3f velocity){ velBuf.clear(); velBuf.put(velocity.x); velBuf.put(velocity.y); velBuf.put(velocity.z); velBuf.rewind(); AL10.alSource (handle, AL10.AL_VELOCITY, velBuf); } /** * Plays the sound */ public void playSound(){ AL10.alSourcePlay(handle); } /** * Stops sound */ public void stopSound(){ AL10.alSourceStop(handle); } /** * Pauses sound */ public void pauseSound(){ AL10.alSourcePause(handle); } /** * @return Whether or not this sound is looping */ public boolean isLooping(){ return loop; } /** * @param loop Whether or not this sound source is looping */ public void setLooping(boolean loop){ this.loop = loop; AL10.alSourcei(handle, AL10.AL_LOOPING, loop ? AL10.AL_TRUE : AL10.AL_FALSE); } /** * Rewinds sound */ public void rewindSound(){ AL10.alSourceRewind(handle); } /** * Queues a buffer * @param buffer Buffer to queue */ public void queueBuffer(int buffer){ AL10.alSourceQueueBuffers(handle, buffer); } /** * Un-queues buffers */ public void unqueueBuffers(){ AL10.alSourceUnqueueBuffers(handle); } /** * Should be called when removing source */ public void shutdown(){ AL10.alDeleteSources(handle); } /** * @return Whether or not a sound is being played right now */ public boolean isPlaying(){ int stat = AL10.alGetSourcei(handle, AL10.AL_SOURCE_STATE); if(stat == AL10.AL_PLAYING) return true; else return false; } }