Skip to content

Sound System

Arjun Singh edited this page Oct 3, 2023 · 13 revisions

The Sound System allows you to play background music and sound effects in the game, through the SoundService.

See the How to Play Sounds section to learn how to play sounds that have already been defined, or read the SoundFile, BackgroundMusicService or EffectMusicService sections to learn more.

How to Play Sounds

Follow the steps below to play either background music or sound effects. These steps assume that the sounds have been defined in the relevant enums.

Background Music

  1. Register the SoundService in the *Screen class of whatever screen you're playing the sound (This is done by default in the MainGameScreen).
ServiceLocator.registerSoundService(new SoundService());
  1. Load the necessary SoundFiles
try {
    ServiceLocator.getSoundService().getBackgroundMusicService()
              .loadSounds(Arrays.asList(BackgroundSoundFile.values()));
} catch (InvalidSoundFileException e) {
    throw new RuntimeException(e);
}
  1. Play a chosen BackgroundMusicType
ServiceLocator.getSoundService().getBackgroundMusicService().play(BackgroundMusicType.NORMAL);
  1. When disposing the screen, also call dispose on the BackgroundMusicService to free resources.
ServiceLocator.getSoundService().getBackgroundMusicService().dispose()

Sound Effects

  1. Register the SoundService in the *Screen class of whatever screen you're playing the sound (This is done by default in the MainGameScreen).
ServiceLocator.registerSoundService(new SoundService());
  1. Load the necessary SoundFiles
// Add effects that are needed
List<SoundFile> effects = new ArrayList();
// Replace TractorHonk with whatever sound effect you wish to play
effects.add(EffectSoundFile.TractorHonk);
try {
    ServiceLocator.getSoundService().getEffectsMusicService().loadSounds(effects);
} catch (InvalidSoundFileException e) {
    throw new RuntimeException(e);
}
  1. Play the sound file
try {
    ServiceLocator.getSoundService().getEffectsMusicService().play(EffectSoundFile.TractorHonk);
} catch (InvalidSoundFileException e) {
    throw new RuntimeException(e);
}
  1. When disposing the screen, also call dispose on the EffectsMusicService to free resources.
ServiceLocator.getSoundService().getEffectsMusicService().dispose()

SoundService

This is the parent class which encapsulates the BackgroundMusicService and the EffectsMusicService. It does not provide any additional functionality of its own. Instead it simplifies access to the two MusicServices

The SoundService needs to be added to the ServiceLocator so that it can be accessed in the game.

ServiceLocator.registerSoundService(new SoundService());

Instantiating the SoundService also instantiates the two MusicServices.

SoundFile

The SoundFile interface is the basis upon which the BackgroundSoundFile and EffectSoundFile enums are built. It requires classes to provide one function - getFilePath() which allows the respective MusicService to load the sound file so that it is playable.

To define a sound that is playable within the game, you need to modify either the BackgroundSoundFile or EffectSoundFile enums that implement this interface. Using an enum and this interface allows you to decouple the name of the sound that is being played from the underlying file. Using an enum also improves the development experience, as your IDE will autocomplete SoundFile names.

BackgroundSoundFiles have one additional requirement. When defining a new BackgroundSoundFile enum value, you must also assign it a BackgroundMusicType which allows playlists/sequences of background music to be played without any additional logic.

BackgroundMusicService

The BackgroundMusicService handles playback for long background music files which are streamed from disk.

A maximum of 10 tracks can be loaded at any given time, with only one track playing.

The play(BackgroundMusicType type) function allows a collection of tracks of a given type to be played in a randomised order, replicating the effect of shuffling a playlist in a music app. Types can be defined for various in game events, which allows relevant music to be played without any additional logic. This functionality could be updated to a queue based on gameplay needs.

Functions

  • play(BackgroundMusicType type)

    • Begins playing loaded Music instances of the provided type, randomly cycling through a sequence of tracks defined in the enum.
    • Parameters:
      • type: The type of background music to be played.
    • Throws:
      • IllegalStateException: If there are no available Music instances of the given type.
  • play(SoundFile sound, boolean looping)

    • Plays a given sound file with specified looping behavior.
    • Parameters:
      • sound: An enum value that implements the SoundFile interface.
      • looping: A flag to control if the sound loops.
    • Returns:
      • long: 0 (no play ID is returned for background music instances).
    • Throws:
      • InvalidSoundFileException: If the sound file is not an instance of BackgroundSoundFile or is unplayable.
  • play(SoundFile sound)

    • Plays a given sound file without specifying looping (defaults to false).
    • Parameters:
      • sound: An enum value that implements the SoundFile interface.
    • Returns:
      • long: 0 (no play ID is returned for background music instances).
    • Throws:
      • InvalidSoundFileException: If the sound file is not an instance of BackgroundSoundFile or is unplayable.
  • pause(SoundFile sound)

    • Pauses a specific track.
    • Parameters:
      • sound: The SoundFile to pause.
    • Throws:
      • InvalidSoundFileException: If the given SoundFile is not active.
  • pause()

    • Pauses whichever track is currently playing.
  • unPause()

    • Unpauses current music if it is paused.
  • stop(SoundFile sound)

    • Stops playback for a given sound file.
    • Parameters:
      • sound: An enum value that implements the SoundFile interface.
    • Throws:
      • InvalidSoundFileException: If the sound file is not playing.
  • setMuted(boolean muted)

    • Sets the mute status of the background music.
    • Parameters:
      • muted: The boolean state to set.
  • isMuted()

    • Returns the current mute status.
    • Returns:
      • boolean: The current mute status.
  • isPlaying(SoundFile sound)

    • Checks if the given sound file is playing.
    • Parameters:
      • sound: An enum value that implements the SoundFile interface.
    • Returns:
      • boolean: True if playing, false if not.
    • Throws:
      • InvalidSoundFileException: If the sound file is not loaded or not an instance of BackgroundSoundFile.
  • loadSounds(List<SoundFile> sounds)

    • Loads a list of sound files into memory (up to 10 tracks).
    • Parameters:
      • sounds: A list of SoundFiles to be loaded into memory.
    • Throws:
      • InvalidSoundFileException: If the provided list contains non-BackgroundSoundFile instances.
  • dispose()

    • Disposes of all loaded Music instances and resets internal maps.

EffectsMusicService

The EffectsMusicService handles playback for short (less than or equal to 5s) sound effects that are played from memory. The implementation provides a convenient interface over the Gdx.Audio.Sound class and adds some additional management data structures.

All files must ideally be in the WAV format to ensure consistent playback (looping is unstable for other file formats).

There is no limit on the number of sound effects that can be loaded, but loading too many will cause performance issues, so please be judicious.

Unlike the BackgroundMusicService, multiple EffectSoundFiles can be played at the same time. Moreover, multiple instances of the same EffectSoundFile (for example gunshots) can also be played at the same time. These instances are referred to by their long integer id, which is returned by the play() function.

Due to the limitations of LibGDX, the progress of sound effects cannot be tracked. So like a gunshot, once the sound effect is played you only have very limited control over it. Looping sound effects can be controlled to some extent, because they are tracked by the EffectsMusicService's internal data structure.

Functions

  • play(SoundFile soundFile, boolean looping)

    • Plays a specified sound effect.
    • Parameters:
      • soundFile: Enum value implementing EffectSoundFile interface.
      • looping: Boolean flag indicating whether the sound effect should loop.
    • Returns:
      • long: ID of the playing sound instance.
  • play(SoundFile sound)

    • Overloaded method for playing a non-looping sound effect.
    • Parameters:
      • sound: Enum value implementing EffectSoundFile interface.
    • Returns:
      • long: ID of the playing sound instance.
  • pause(SoundFile sound)

    • Pauses a specified sound effect (equivalent to stop(sound)).
  • stop(SoundFile soundFile)

    • Stops all instances of a specified sound effect.
    • Parameters:
      • soundFile: Enum value implementing EffectSoundFile interface.
  • stop(SoundFile soundFile, long id)

    • Stops a specific instance of a sound effect.
    • Parameters:
      • soundFile: Enum value implementing EffectSoundFile interface.
      • id: ID of the sound instance to stop.
  • setMuted(boolean muted)

    • Sets the mute status for sound playback.
    • Parameters:
      • muted: Boolean flag indicating mute status.
  • isMuted()

    • Checks if sound playback is muted.
    • Returns:
      • boolean: Mute status.
  • isPlaying(SoundFile sound)

    • Checks if any instance of a specified sound effect is currently playing.
    • Parameters:
      • sound: Enum value implementing EffectSoundFile interface.
    • Returns:
      • boolean: Playback status.
  • isPlaying(SoundFile sound, long id)

    • Checks if a specific instance of a sound effect is playing.
    • Parameters:
      • sound: Enum value implementing EffectSoundFile interface.
      • id: ID of the sound instance to check.
    • Returns:
      • boolean: Playback status.
  • loadSounds(List<SoundFile> sounds)

    • Loads sound files into memory for playback.
    • Parameters:
      • sounds: List of enum values implementing EffectSoundFile interface.
  • dispose()

    • Disposes of all loaded sound resources.

UML Diagram

The UML diagram for the Sound System shows how the different classes, interfaces and enumerations interact with each other. EffectsMusicService and BackgroundMusicService both implement MusicService, which are both instantiated by SoundService. Two enumeration files, BackgroundSoundFile and BackgroundMusicType are both called within BackgroundMusicService as well.

image

Clone this wiki locally