
de.lessvoid.nifty.sound.openal.Music Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of nifty-openal-soundsystem Show documentation
Show all versions of nifty-openal-soundsystem Show documentation
This is an OpenAL/lwjgl based SoundDevice for Nifty GUI. It was extracted out of Slick2D to be
independent of the whole Slick2D library and to be used with none Slick2D based renderes. All credits for the
original code go to Kevin Glass and all Slick2D contributers.
package de.lessvoid.nifty.sound.openal;
import de.lessvoid.nifty.sound.openal.slick.Audio;
import de.lessvoid.nifty.sound.openal.slick.AudioImpl;
import de.lessvoid.nifty.sound.openal.slick.SoundStore;
import de.lessvoid.nifty.tools.resourceloader.NiftyResourceLoader;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.net.URL;
import java.util.ArrayList;
import java.util.logging.Logger;
/**
* A piece of music loaded and playable within the game. Only one piece of music can
* play at any given time and a channel is reserved so music will always play.
*
* @author kevin
* @author Nathan Sweet
*/
public class Music {
private final Logger log = Logger.getLogger(Music.class.getName());
/**
* The music currently being played or null if none
*/
@Nullable
private static Music currentMusic;
/**
* Poll the state of the current music. This causes streaming music
* to stream and checks listeners. Note that if you're using a game container
* this will be auto-magically called for you.
*
* @param delta The amount of time since last poll
*/
public static void poll(int delta) {
if (currentMusic != null) {
SoundStore.get().poll(delta);
if (!SoundStore.get().isMusicPlaying()) {
if (!currentMusic.positioning) {
Music oldMusic = currentMusic;
currentMusic = null;
oldMusic.fireMusicEnded();
}
} else {
currentMusic.update(delta);
}
}
}
/**
* The sound from FECK representing this music
*/
private Audio sound;
/**
* True if the music is playing
*/
private boolean playing;
/**
* The list of listeners waiting for notification that the music ended
*/
@Nonnull
private final ArrayList listeners = new ArrayList();
/**
* The volume of this music
*/
private float volume = 1.0f;
/**
* Start gain for fading in/out
*/
private float fadeStartGain;
/**
* End gain for fading in/out
*/
private float fadeEndGain;
/**
* Countdown for fading in/out
*/
private int fadeTime;
/**
* Duration for fading in/out
*/
private int fadeDuration;
/**
* True if music should be stopped after fading in/out
*/
private boolean stopAfterFade;
/**
* True if the music is being repositioned and it is therefore normal that it's not playing
*/
private boolean positioning;
/**
* The position that was requested
*/
private float requiredPosition = -1;
/**
* Create and load a piece of music (either OGG or MOD/XM)
*
* @param ref The location of the music
* @throws SlickException
*/
public Music(@Nonnull String ref, @Nonnull final NiftyResourceLoader resourceLoader) throws Exception {
this(ref, false, resourceLoader);
}
/**
* Create and load a piece of music (either OGG or MOD/XM)
*
* @param ref The location of the music
* @throws SlickException
*/
public Music(@Nonnull URL ref, final NiftyResourceLoader resourceLoader) throws Exception {
this(ref, false, resourceLoader);
}
/**
* Create and load a piece of music (either OGG or MOD/XM)
*
* @param url The location of the music
* @param streamingHint A hint to indicate whether streaming should be used if possible
* @throws SlickException
*/
public Music(@Nonnull URL url, boolean streamingHint, final NiftyResourceLoader resourceLoader) throws Exception {
SoundStore.get().init();
String ref = url.getFile();
try {
if (ref.toLowerCase().endsWith(".ogg")) {
if (streamingHint) {
sound = SoundStore.get().getOggStream(url, resourceLoader);
} else {
sound = SoundStore.get().getOgg(url.openStream());
}
} else if (ref.toLowerCase().endsWith(".wav")) {
sound = SoundStore.get().getWAV(url.openStream());
} else if (ref.toLowerCase().endsWith(".xm") || ref.toLowerCase().endsWith(".mod")) {
sound = SoundStore.get().getMOD(url.openStream());
} else if (ref.toLowerCase().endsWith(".aif") || ref.toLowerCase().endsWith(".aiff")) {
sound = SoundStore.get().getAIF(url.openStream());
} else {
throw new Exception("Only .xm, .mod, .ogg, and .aif/f are currently supported.");
}
} catch (Exception e) {
log.warning(e.toString());
throw new Exception("Failed to load sound: " + url);
}
}
/**
* Create and load a piece of music (either OGG or MOD/XM)
*
* @param ref The location of the music
* @param streamingHint A hint to indicate whether streaming should be used if possible
* @throws SlickException
*/
public Music(
@Nonnull String ref,
boolean streamingHint,
@Nonnull final NiftyResourceLoader resourceLoader) throws Exception {
SoundStore.get().init();
try {
if (ref.toLowerCase().endsWith(".ogg")) {
if (streamingHint) {
sound = SoundStore.get().getOggStream(ref, resourceLoader);
} else {
sound = SoundStore.get().getOgg(ref, resourceLoader);
}
} else if (ref.toLowerCase().endsWith(".wav")) {
sound = SoundStore.get().getWAV(ref, resourceLoader);
} else if (ref.toLowerCase().endsWith(".xm") || ref.toLowerCase().endsWith(".mod")) {
sound = SoundStore.get().getMOD(ref, resourceLoader);
} else if (ref.toLowerCase().endsWith(".aif") || ref.toLowerCase().endsWith(".aiff")) {
sound = SoundStore.get().getAIF(ref, resourceLoader);
} else {
throw new Exception("Only .xm, .mod, .ogg, and .aif/f are currently supported.");
}
} catch (Exception e) {
log.warning(e.toString());
throw new Exception("Failed to load sound: " + ref);
}
}
/**
* Add a listener to this music
*
* @param listener The listener to add
*/
public void addListener(MusicListener listener) {
listeners.add(listener);
}
/**
* Remove a listener from this music
*
* @param listener The listener to remove
*/
public void removeListener(MusicListener listener) {
listeners.remove(listener);
}
/**
* Fire notifications that this music ended
*/
private void fireMusicEnded() {
playing = false;
for (int i = 0; i < listeners.size(); i++) {
listeners.get(i).musicEnded(this);
}
}
/**
* Fire notifications that this music was swapped out
*
* @param newMusic The new music that will be played
*/
private void fireMusicSwapped(Music newMusic) {
playing = false;
for (int i = 0; i < listeners.size(); i++) {
listeners.get(i).musicSwapped(this, newMusic);
}
}
/**
* Loop the music
*/
public void loop() {
loop(1.0f, 1.0f);
}
/**
* Play the music
*/
public void play() {
play(1.0f, 1.0f);
}
/**
* Play the music at a given pitch and volume
*
* @param pitch The pitch to play the music at (1.0 = default)
* @param volume The volume to play the music at (1.0 = default)
*/
public void play(float pitch, float volume) {
startMusic(pitch, volume, false);
}
/**
* Loop the music at a given pitch and volume
*
* @param pitch The pitch to play the music at (1.0 = default)
* @param volume The volume to play the music at (1.0 = default)
*/
public void loop(float pitch, float volume) {
startMusic(pitch, volume, true);
}
/**
* play or loop the music at a given pitch and volume
*
* @param pitch The pitch to play the music at (1.0 = default)
* @param volume The volume to play the music at (1.0 = default)
* @param loop if false the music is played once, the music is looped otherwise
*/
private void startMusic(float pitch, float volume, boolean loop) {
if (currentMusic != null) {
currentMusic.stop();
currentMusic.fireMusicSwapped(this);
}
currentMusic = this;
if (volume < 0.0f) {
volume = 0.0f;
}
if (volume > 1.0f) {
volume = 1.0f;
}
sound.playAsMusic(pitch, volume, loop);
playing = true;
setVolume(volume);
if (requiredPosition != -1) {
setPosition(requiredPosition);
}
}
/**
* Pause the music playback
*/
public void pause() {
playing = false;
AudioImpl.pauseMusic();
}
/**
* Stop the music playing
*/
public void stop() {
sound.stop();
}
/**
* Resume the music playback
*/
public void resume() {
playing = true;
AudioImpl.restartMusic();
}
/**
* Check if the music is being played
*
* @return True if the music is being played
*/
public boolean playing() {
return (currentMusic == this) && (playing);
}
/**
* Set the volume of the music as a factor of the global volume setting
*
* @param volume The volume to play music at. 0 - 1, 1 is Max
*/
public void setVolume(float volume) {
// Bounds check
if (volume > 1) {
volume = 1;
} else if (volume < 0) {
volume = 0;
}
this.volume = volume;
// This sound is being played as music
if (currentMusic == this) {
SoundStore.get().setCurrentMusicVolume(volume);
}
}
/**
* Get the individual volume of the music
*
* @return The volume of this music, still effected by global SoundStore volume. 0 - 1, 1 is Max
*/
public float getVolume() {
return volume;
}
/**
* Fade this music to the volume specified
*
* @param duration Fade time in milliseconds.
* @param endVolume The target volume
* @param stopAfterFade True if music should be stopped after fading in/out
*/
public void fade(int duration, float endVolume, boolean stopAfterFade) {
this.stopAfterFade = stopAfterFade;
fadeStartGain = volume;
fadeEndGain = endVolume;
fadeDuration = duration;
fadeTime = duration;
}
/**
* Update the current music applying any effects that need to updated per
* tick.
*
* @param delta The amount of time in milliseconds thats passed since last update
*/
void update(int delta) {
if (!playing) {
return;
}
if (fadeTime > 0) {
fadeTime -= delta;
if (fadeTime < 0) {
fadeTime = 0;
if (stopAfterFade) {
stop();
return;
}
}
float offset = (fadeEndGain - fadeStartGain) * (1 - (fadeTime / (float) fadeDuration));
setVolume(fadeStartGain + offset);
}
}
/**
* Seeks to a position in the music. For streaming music, seeking before the current position causes
* the stream to be reloaded.
*
* @param position Position in seconds.
* @return True if the seek was successful
*/
public boolean setPosition(float position) {
if (playing) {
requiredPosition = -1;
positioning = true;
playing = false;
boolean result = sound.setPosition(position);
playing = true;
positioning = false;
return result;
} else {
requiredPosition = position;
return false;
}
}
/**
* The position into the sound thats being played
*
* @return The current position in seconds.
*/
public float getPosition() {
return sound.getPosition();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy