Playing short sound effects

We will get started with the Libgdx sound system by playing short sound effects, also known as SFX. Often, effects go unnoticed, and this is really unfair towards them! As an exercise, try turning the effects' volume down in an action shooter and see how much you enjoy it. It is not the same experience at all, is it?

The sample shown in this recipe will illustrate how to play, pause, resume, and stop sounds. We will map the number keys from 1 to 7 to different sounds. The P key will pause the sounds, R will resume playback, and S will stop playback.

Getting ready

Make sure the sample projects are in your Eclipse workspace to follow this recipe.

How to do it…

The code for this recipe will be found in the SoundEffectSample class. Follow these instructions to master how to play back sound effects:

  1. Unsurprisingly, the class through which we will work is called Sound. An IntMap of Sound instances will help us manage the sound collection of our sample. The effects will be played when the user presses the number keys from 1 to 7:
    private IntMap<Integer, Sound> soundKeys;
  2. We use the create() method to construct our collections and populate them. Sound objects are instantiated through the Gdx.audio.newSound() method passing in the appropriate file handle; we instantiate with all seven effects under the data/sfx folder. The key sound dictionary will contain the key code from Keys.NUM_1 to Keys.NUM_7, pointing to the corresponding entries in the sound arrays. Finally, we set our SoundEffectSample class as the input processor and show the sample controls on the console output:
    public void create() {	
      sounds = new IntMap<Sound>();
      sounds.put(Keys.NUM_1, Gdx.audio.newSound(Gdx.files.internal("data/sfx/sfx_01.wav")));
      …
    
      Gdx.input.setInputProcessor(this);
    
      Gdx.app.log("SoundEffectSample", "Instructions");
      …
    }
  3. Sound objects need disposing when they are no longer needed so as to avoid nasty resource leaks. We iterate over the sound collections calling dispose() on all of the entries:
    public void dispose() {
      for (Sound sound : sounds.values()) {
        sound.dispose();
      }
    }
  4. A Sound object can be used to play several instances of itself at the same time. Every time we call its play() method, the effect will be played and we will get a playID handle back, which we can use to refer to the instance later.
  5. Effect operations are performed from within the keyDown() event handler. When a user presses the S key, we need to stop playing all sounds. Calling the stop() method on a Sound object will halt all effects that were played from it:
    if (keycode == Keys.S) {
      for (Sound sound : sounds.values()) {
        sound.stop();
      }
    
    Gdx.app.log("SoundEffectSample", "Sounds stopped");
    }
  6. Upon pressing the P key, we simply pause all instances by calling the pause() method:
    else if (keycode == Keys.P) {
      for (Sound sound : sounds.values()) {
        sound.pause();
    }
        
      Gdx.app.log("SoundEffectSample", "Sounds paused");
    }
  7. If the user presses R, we call the resume() method and all the instances to resume the paused sounds:
    else if (keycode == Keys.R) {
      for (Sound sound : sounds.values()) {
        sound.resume();
      }
    
      Gdx.app.log("SoundEffectSample", "Sounds resumed");
    }
  8. When the pressed key is none of the above, we perform a lookup in the sounds dictionary to see whether there is a sound we should play using the play() method:
    else {
      Sound sound = sounds.get(keycode);
    
      if (sound != null)
      {
        sound.play();
        Gdx.app.log("SoundEffectSample", "Playing sound");
      }
    }
  9. To add basic support for touchscreens, we play a random Sound instance from the array whenever the user touches the screen:
    public boolean touchDown (int screenX, int screenY, int pointer, int button) {
      Sound sound = sounds.get(MathUtils.random(sounds.size - 1));
      sound.play();
    
      Gdx.app.log("SoundEffectSample", "Playing sound");
      return true;
    }
  10. You should now be able to run the sample, play around with it, and check for yourself.

How it works…

Libgdx offers an audio interface to let us work with sound effects and music in a platform-agnostic way. Each backend implements it using different resources, as follows:

  • The desktop backend uses OpenAL
  • The Android backend uses the official Android SDK, mostly SoundPool, AudioManager, and MediaPlayer
  • The HTML5 backend uses the sound tag, and falls back to Flash if the former does not work
  • The RoboVM backend also uses OpenAL

Several formats are supported for sound effects in Libgdx. Make your choice depending on your needs: WAV, MP3, and OGG (unsupported in iOS).

There's more…

Quite a few goodies are available to us in the Sound interface.

Handling sounds individually

We already mentioned that the play() method returns a handle that we can store to manage effect instances individually later on. The other methods are as follows:

long soundID = sound.play();
sound.pause(soundID);
sound.resume(soundID);
sound.stop(soundID);

Note that if the effect of the handle references has finished playing, anything that we do with its handle will have no effect and fail silently.

Changing the volume

Volume is represented with a float ranging from 0.0f to 1.0f. We can set an effect's volume by doing the following:

sound.setVolume(soundID, volume); 

Creating looping sounds

To play a sound effect that will keep playing indefinitely, you can make use of the loop() method, which also returns a handle to reference the instance later on:

long soundID = sound.loop();

You can change your mind at any time and tell an effect to stop looping; in this case, you will have to call setLooping() with the corresponding handle:

sound.setLooping(soundID, false);

Managing effect priorities

There is a limit on how many sound effects can be played at a time, but such limits are configurable on Android and desktops at application startup time, through the configuration objects passed to the application instance:

AndroidApplicationConfiguration.maxSimultaneousSounds
LwglApplicationConfiguration.audioDeviceSimultaneousSources

If your game environment is rich and complex, it is not rare to exceed the sound limit at times. However, you might be quite keen on making sure that very specific instances play above all others. For instance, in an RPG, you might not care if the cow in the background moos, as long as the NPC that gives the player a new quest is properly heard.

Libgdx lets us give the sound system hints on how important an effect request is:

sound.setPriority(soundID, priority);

Priorities are set using integer values indicating their positions on the sound queue, so sounds with a smaller priority will be considered first if the queue is full.

See also

  • We tackled how to play short sound effects. For longer audio files, read the Audio streaming for background music recipe
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.129.210.102