/* * 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 channels Number of channels 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(); } } }