190 lines
5.6 KiB
Java
190 lines
5.6 KiB
Java
/*
|
|
* Copyright (c) 2002-2008 LWJGL Project
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are
|
|
* met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* * Neither the name of 'LWJGL' nor the names of
|
|
* its contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
package org.lwjgl.examples.spaceinvaders;
|
|
|
|
import java.nio.IntBuffer;
|
|
|
|
import org.lwjgl.BufferUtils;
|
|
import org.lwjgl.LWJGLException;
|
|
import org.lwjgl.openal.AL;
|
|
import org.lwjgl.openal.AL10;
|
|
import org.lwjgl.util.WaveData;
|
|
|
|
|
|
/**
|
|
* <p>
|
|
* Simple sound manager for OpenAL using n sources accessed in
|
|
* a round robin schedule. Source n is reserved for a single buffer and checking for
|
|
* whether it's playing.
|
|
* </p>
|
|
* @author Brian Matzon <brian@matzon.dk>
|
|
* @version $Revision$
|
|
* $Id$
|
|
*/
|
|
public class SoundManager {
|
|
|
|
/** We support at most 256 buffers*/
|
|
private int[] buffers = new int[256];
|
|
|
|
/** Number of sources is limited tby user (and hardware) */
|
|
private int[] sources;
|
|
|
|
/** Our internal scratch buffer */
|
|
private IntBuffer scratchBuffer = BufferUtils.createIntBuffer(256);
|
|
|
|
/** Whether we're running in no sound mode */
|
|
private boolean soundOutput;
|
|
|
|
/** Current index in our buffers */
|
|
private int bufferIndex;
|
|
|
|
/** Current index in our source list */
|
|
private int sourceIndex;
|
|
|
|
/**
|
|
* Creates a new SoundManager
|
|
*/
|
|
public SoundManager() {
|
|
}
|
|
|
|
/**
|
|
* Plays a sound effect
|
|
* @param buffer Buffer index to play gotten from addSound
|
|
*/
|
|
public void playEffect(int buffer) {
|
|
if(soundOutput) {
|
|
// make sure we never choose last channel, since it is used for special sounds
|
|
int channel = sources[(sourceIndex++ % (sources.length-1))];
|
|
|
|
// link buffer and source, and play it
|
|
AL10.alSourcei(channel, AL10.AL_BUFFER, buffers[buffer]);
|
|
AL10.alSourcePlay(channel);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Plays a sound on last source
|
|
* @param buffer Buffer index to play gotten from addSound
|
|
*/
|
|
public void playSound(int buffer) {
|
|
if(soundOutput) {
|
|
AL10.alSourcei(sources[sources.length-1], AL10.AL_BUFFER, buffers[buffer]);
|
|
AL10.alSourcePlay(sources[sources.length-1]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Whether a sound is playing on last source
|
|
* @return true if a source is playing right now on source n
|
|
*/
|
|
public boolean isPlayingSound() {
|
|
return AL10.alGetSourcei(sources[sources.length-1], AL10.AL_SOURCE_STATE) == AL10.AL_PLAYING;
|
|
}
|
|
|
|
/**
|
|
* Initializes the SoundManager
|
|
*
|
|
* @param sources Number of sources to create
|
|
*/
|
|
public void initialize(int channels) {
|
|
try {
|
|
AL.create();
|
|
|
|
// allocate sources
|
|
scratchBuffer.limit(channels);
|
|
AL10.alGenSources(scratchBuffer);
|
|
scratchBuffer.rewind();
|
|
scratchBuffer.get(sources = new int[channels]);
|
|
|
|
// could we allocate all channels?
|
|
if(AL10.alGetError() != AL10.AL_NO_ERROR) {
|
|
throw new LWJGLException("Unable to allocate " + channels + " sources");
|
|
}
|
|
|
|
// we have sound
|
|
soundOutput = true;
|
|
} catch (LWJGLException le) {
|
|
le.printStackTrace();
|
|
System.out.println("Sound disabled");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Adds a sound to the Sound Managers pool
|
|
*
|
|
* @param path Path to file to load
|
|
* @return index into SoundManagers buffer list
|
|
*/
|
|
public int addSound(String path) {
|
|
// Generate 1 buffer entry
|
|
scratchBuffer.rewind().position(0).limit(1);
|
|
AL10.alGenBuffers(scratchBuffer);
|
|
buffers[bufferIndex] = scratchBuffer.get(0);
|
|
|
|
// load wave data from buffer
|
|
WaveData wavefile = WaveData.create("spaceinvaders/" + path);
|
|
|
|
// copy to buffers
|
|
AL10.alBufferData(buffers[bufferIndex], wavefile.format, wavefile.data, wavefile.samplerate);
|
|
|
|
// unload file again
|
|
wavefile.dispose();
|
|
|
|
// return index for this sound
|
|
return bufferIndex++;
|
|
}
|
|
|
|
/**
|
|
* Destroy this SoundManager
|
|
*/
|
|
public void destroy() {
|
|
if(soundOutput) {
|
|
|
|
// stop playing sounds
|
|
scratchBuffer.position(0).limit(sources.length);
|
|
scratchBuffer.put(sources).flip();
|
|
AL10.alSourceStop(scratchBuffer);
|
|
|
|
// destroy sources
|
|
AL10.alDeleteSources(scratchBuffer);
|
|
|
|
// destroy buffers
|
|
scratchBuffer.position(0).limit(bufferIndex);
|
|
scratchBuffer.put(buffers, 0, bufferIndex).flip();
|
|
AL10.alDeleteBuffers(scratchBuffer);
|
|
|
|
// destory OpenAL
|
|
AL.destroy();
|
|
}
|
|
}
|
|
}
|