All pastes #405314 Raw Edit

JavaMan stuff

public text v1 · immutable
·published 2007-03-21 17:39 UTC
rendered paste body
import java.io.IOException;
import java.io.InputStream;
import java.nio.IntBuffer;
import java.util.HashMap;

import org.lwjgl.BufferUtils;
import org.lwjgl.Sys;
import org.lwjgl.openal.AL;
import org.lwjgl.openal.AL10;

/**
 * Responsible for holding and playing the sounds used in the game.
 *
 * @author Kevin Glass
 */
public class SoundStore {
	/** The single instance of this class */
	private static final SoundStore store = new SoundStore();

	/** True if sound effects are turned on */
	private boolean sounds;
	/** True if music is turned on */
	private boolean music;
	/** True if sound initialisation succeeded */
	private boolean soundWorks;
	/** The number of sound sources enabled - default 8 */
	private int sourceCount;
	/** The map of references to IDs of previously loaded sounds */
	private HashMap loaded = new HashMap();
	/** The ID of the buffer containing the music currently being played */
	private int currentMusic = -1;
	/** The OpenGL AL sound sources in use */
	private IntBuffer sources;
	/** The next source to be used for sound effects */
	private int nextSource;
	/** True if the sound system has been initialise */
	private boolean inited = false;

	/** The global music volume setting */
	private float musicVolume = 1.0f;
	/** The global sound fx volume setting */
	private float soundVolume = 1.0f;
	/** The last "gain" applied to music */
	private float lastMusicGain = 1.0f;

	/** True if we should fade in */
	private boolean fadeIn;
	/** The current fade in value */
	private float fade;

	private SoundStore() {
	}

	// Inidicate whether music should be playing
        public void setMusicOn(boolean music) {
          if (soundWorks) {
            this.music = music;
            if (music) {
              restartLoop();
            }
            else {
              pauseLoop();
            }
          }
        }

        // Check if music should currently be playing
        public boolean isMusicOn() {
          return music;
        }

        // Set the music volume
        public void setMusicVolume(float volume) {
          if (volume < 0) {
            volume = 0;
          }
          musicVolume = volume;

          if (soundWorks) {
            if (volume == 0) {
              volume = 0.001f;
            }
            AL10.alSourcef(sources.get(0), AL10.AL_GAIN, lastMusicGain * volume);
          }
        }

        // Set the sound volume
        public void setSoundVolume(float volume) {
          if (volume < 0) {
            volume = 0;
          }
          soundVolume = volume;
        }

	// Check if sound works at all
        public boolean soundWorks() {
          return soundWorks;
        }

	// Check if music is currently enabled
        public boolean musicOn() {
          return music;
        }

	//Get the volume for sounds
        public float getSoundVolume() {
          return soundVolume;
        }

	/**
	 * Get the volume for music
	 *
	 * @return The volume for music
	 */
	public float getMusicVolume() {
		return musicVolume;
	}

	/**
	 * Get the ID of a given source
	 *
	 * @param index The ID of a given source
	 * @return The ID of the given source
	 */
	public int getSource(int index) {
		return sources.get(index);
	}

	/**
	 * Indicate whether sound effects should be played
	 *
	 * @param sounds True if sound effects should be played
	 */
	public void setSoundsOn(boolean sounds) {
		if (soundWorks) {
			this.sounds = sounds;
		}
	}

	/**
	 * Check if sound effects are currently enabled
	 *
	 * @return True if sound effects are currently enabled
	 */
	public boolean soundsOn() {
		return sounds;
	}

        // Initialise the sound effects stored. This must be called
        // before anything else will work
        public void init() {
          System.out.println("Initialising sounds..");
          inited = true;
          try {
            AL.create();
            soundWorks = true;
            sounds = true;
            music = true;
            System.out.println("- Sound works");
          }
          catch (Exception e) {
            System.out.println("Sound initialisation failure.");
            System.out.println(e);
            soundWorks = false;
            sounds = false;
            music = false;
          }

          if (soundWorks) {
            sourceCount = 8;
            sources = BufferUtils.createIntBuffer(sourceCount);
            AL10.alGenSources(sources);

            if (AL10.alGetError() != AL10.AL_NO_ERROR) {
              sounds = false;
              music = false;
              soundWorks = false;
              System.out.println("- AL init failed");
            }
            else {
              System.out.println("- Sounds source generated");
            }
          }
        }

	/**
	 * Play the specified buffer as a sound effect with the specified
	 * pitch and gain.
	 *
	 * @param buffer The ID of the buffer to play
	 * @param pitch The pitch to play at
	 * @param gain The gain to play at
	 */
        void playAsSound(int buffer, float pitch, float gain) {
          gain *= soundVolume;
          if (gain == 0) {
            gain = 0.001f;
          }
          if (soundWorks) {
            if (sounds) {
              nextSource++;
              if (nextSource > sourceCount - 1) {
                nextSource = 1;
              }
              AL10.alSourceStop(sources.get(nextSource));

              AL10.alSourcei(sources.get(nextSource), AL10.AL_BUFFER, buffer);
              AL10.alSourcef(sources.get(nextSource), AL10.AL_PITCH, pitch);
              AL10.alSourcef(sources.get(nextSource), AL10.AL_GAIN, gain);

              AL10.alSourcePlay(sources.get(nextSource));
            }
          }
        }

	/**
	 * Play the specified buffer as music (i.e. use the music channel)
	 *
	 * @param buffer The buffer to be played
	 * @param pitch The pitch to play the music at
	 * @param gain The gaing to play the music at
	 */
        void playAsMusic(int buffer, float pitch, float gain) {
          lastMusicGain = gain;
          gain *= musicVolume;
          if (gain == 0) {
            gain = 0.001f;
          }

          if (soundWorks) {
            if (currentMusic != -1) {
              AL10.alSourceStop(sources.get(0));
            }

            AL10.alSourcei(sources.get(0), AL10.AL_BUFFER, buffer);
            AL10.alSourcef(sources.get(0), AL10.AL_PITCH, pitch);
            AL10.alSourcef(sources.get(0), AL10.AL_GAIN, gain);
            AL10.alSourcei(sources.get(0), AL10.AL_LOOPING, AL10.AL_TRUE);

            currentMusic = sources.get(0);

            if (!music) {
              pauseLoop();
            }
            else {
              AL10.alSourcePlay(sources.get(0));
            }
          }
        }

	/**
	 * Set the pitch at which the current music is being played
	 *
	 * @param pitch The pitch at which the current music is being played
	 */
        public void setMusicPitch(float pitch) {
          if (soundWorks) {
            AL10.alSourcef(sources.get(0), AL10.AL_PITCH, pitch);
          }
        }

	/**
	 * Pause the music loop that is currently playing
	 */
        public void pauseLoop() {
          if ((soundWorks) && (currentMusic != -1)) {
            AL10.alSourcePause(currentMusic);
          }
        }

	/**
	 * Restart the music loop that is currently paused
	 */
        public void restartLoop() {
          if ((music) && (soundWorks) && (currentMusic != -1)) {
            AL10.alSourcePlay(currentMusic);
          }
        }

	/**
	 * Get the Sound based on a specified OGG file
	 *
	 * @param ref The reference to the OGG file in the classpath
	 * @return The Sound read from the OGG file
	 * @throws IOException Indicates a failure to load the OGG
	 */
        public Sound getOgg(String ref) throws IOException {
          if (!soundWorks) {
            return new Sound(this, 0);
          }

          if (!inited) {
            throw new RuntimeException("Can't load sounds until SoundStore is init()");
          }
          int buffer = -1;

          if (loaded.get(ref) != null) {
            buffer = ((Integer) loaded.get(ref)).intValue();
          }
          else {
            System.out.println("Loading: " + ref);
            try {
              IntBuffer buf = BufferUtils.createIntBuffer(1);

              InputStream in = Thread.currentThread().getContextClassLoader().
                               getResourceAsStream(ref);

              OggDecoder decoder = new OggDecoder();
              OggData ogg = decoder.getData(in);

              AL10.alGenBuffers(buf);
              AL10.alBufferData(buf.get(0),
                                ogg.channels > 1 ? AL10.AL_FORMAT_STEREO16 :
                                AL10.AL_FORMAT_MONO16, ogg.data, ogg.rate);

              loaded.put(ref, new Integer(buf.get(0)));

              buffer = buf.get(0);
            }
            catch (Exception e) {
              System.out.println(e);
              Sys.alert("Error", "Failed to load: " + ref + " - " + e.getMessage());
              System.exit(0);
            }
          }

          if (buffer == -1) {
            throw new IOException("Unable to load: " + ref);
          }

          return new Sound(this, buffer);
        }

	/**
	 * Poll the streaming system
	 *
	 * @param delta The amount of time passed since last poll
	 */
        public void poll(int delta) {
          if (!soundWorks) {
            return;
          }

          if (music) {
            if ((fadeIn) && (currentMusic != -1)) {
              fade += 0.0005f * delta;
              if (fade >= 1) {
                fade = 1;
                fadeIn = false;
              }
              AL10.alSourcef(currentMusic, AL10.AL_GAIN, fade * musicVolume);
            }
          }
          else {
            if (currentMusic != -1) {
              fadeIn = true;
              fade = 0;
              AL10.alSourcef(currentMusic, AL10.AL_GAIN, fade * musicVolume);
            }
          }
        }

	/**
	 * Get the single instance of this class
	 *
	 * @return The single instnace of this class
	 */
        public static SoundStore get() {
          return store;
        }
}