[LibGDX] Queue Sound Effects

Hi, I used this little class in a recent project to “Queue” or rather play 1 sound effect after another with a delay.

It worked quite nice, someone might find a use for it, very simple. It can be built on, to remove tracks and swap track order but heh I just made this quickly.



public class SoundSequencer {

	/** A list of tracks to play in a sequence */
	Array<Sound> sounds = new Array<Sound>();

	/** The index to play */
	int index = 0;

	/** The delay between tracks */
	double delay;

	/** The last time a track was played */
	double lastPlayed;

	/** Add a sound to the sequencer */
	public void addSound(String path) {
		Sound sound = Gdx.audio.newSound(Gdx.files.internal(path));
		if (sounds.contains(sound, true))
			return;
		sounds.add(sound);
	}
	

	/**
	 * Play the sound sequence with a given delay
	 * 
	 * @param volume 0 - 1
	 * @param delay
	 *            in seconds
	 */
	public void play(float volume, double delay) {
		if (TimeUtils.nanoTime() - lastPlayed > delay / 1000000000) {
			play(volume);
		}
	}

	/**
	 * Play the sound track
	 * 
	 * @param volume 0 - 1
	 */
	public void play(float volume) {
		if (sounds.get(index) != null) {
			sounds.get(index).play(volume);
			lastPlayed = TimeUtils.nanoTime();
		}
		nextTrack();
	}

	/** Move to the next track on the play list */
	private void nextTrack() {
		if (index + 1 > sounds.size - 1) {
			index = 0;
		} else {
			index += 1;
		}
	}
}


How does this Queuing work? As far as I can see no queuing takes place (as in one sound plays after the other). How do you determine when a sound has finished playing?

I used it for my Space Invaders game, the play method would get called each time all the aliens would move.

It would then increase the index by one, meaning the next sound effect to be played is the one in the list. So it would sort of “queue” them in a sense.

Imagine you had an enemy that had 3 hearts, each time you damage them, the sound they make is different. So you could call this each time you damage the enemy, playing the next sound effect in the list.

You could easily expand on it to play a random sound effect in the list as well.

Here is what I used it in:


// I added 3 sounds effects to each sequence using a loop

		SoundSequencer invadermove = new SoundSequencer();
		SoundSequencer invaderfast = new SoundSequencer();
		
		for(int x = 1; x <= 3; x++){
			invadermove.addSound("data/sounds/move"+x+".wav");
			invaderfast.addSound("data/sounds/fast"+x+".wav");
			
		}


Then at the bottom of my invaders move loop:



			if (alienCount > 1) {
				invadermove.play(1f);
			} else {
				invaderfast.play(1f,
						0.10f);
			}


So if we have more than 1 alien, we just play the regular invader sound with a volume of 1f.

If we have 1 alien, we play the “fast” sound effect, with a volume of 1 with a delay of 0.10f. This moves to the next sound in the queue every 0.10s.

If that makes sense, maybe queue is not the right word.

Any suggestions?

Add a varargs parameter to addSound() (addSounds()?) that is either an int telling how many times to repeat the same sound, or multiple sounds, removes for-loop boilerplate.

Have an easy way to play multiple sounds at once, like a queue of bundles of sounds.

Okay, thanks for the explanation, sounds useful!