tutorials / libgdx / sound

Sound

tutorial libgdx

Sound can be an important component of games. You can use background music to set the mood, and you can use sound effects to help give the user feedback when they take certain actions. You can even give your characters voices. This tutorial introduces the framework that libGDX offers for playing music and sound effects.

Obtaining Sound Files

If you’re a programmer instead of a sound engineer or music artist, you might be asking a question: where do I get sound files in the first place? There are a few options here, and I’ll cover a few.

For the sake of working through this tutorial, I’d recommend using Freesound.org to search for sounds to use. For example here is a search for “meow” noises released under a CC0 license, which means we can use them however we want. Here is a search for banjo music.

Now that you have some sound files, let’s add them to our project!

Sound File Placement

Remember that a libGDX project is usually a few different subprojects: a core project that contains the game’s main code, and then platform projects that contain platform-specific wrappers of the core project, which allow you to deploy to multiple platforms. For example you might have an Android project, a web project, and a desktop project in addition to the core project.

LibGDX expects sounds and other files to be in different places depending on your project setup:

For example, if I’m planning on deploying to Android and web, I’ll have three projects: core, Android, and web. My sound files will be in the assets directory inside my Android project. Note that the sound files will be copied automatically into the web project when I deploy it, so I don’t have to copy them manually myself.

Loading and Playing Sounds

The Sound class is used for loading and playing small sound files (smaller than 1 MB) that only last a few seconds. We can use the Gdx.audio.newSound() utility function to load sound files from our assets directory.

Sound sound = Gdx.audio.newSound(Gdx.files.internal("meow.mp3"));

This code loads the meow.mp3 file into a Sound variable. Generally this should happen in the create() function.

Now that we have a Sound instance, we can play the sound:

sound.play();

Loading and Playing Music

The Sound class loads sound files into memory, which means less time between playing the sound and hearing it. This is okay for small sounds (plus you don’t want to wait to hear the pew pew pew when you shoot your laser), but you don’t want to do this for large sound files.

For large sound files, you generally want to stream the audio from a file instead of loading the whole file into memory. This might sound complicated, but libGDX makes this easy through its Music class.

The Music class is used for loading and playing larger sound files, generally for music or ambient background noises.

We can use the Gdx.audio.newMusic() utility function to load sound files from our assets directory.

Music music = Gdx.audio.newMusic(Gdx.files.internal("banjo.mp3"));

This code loads the banjo.mp3 file into a Music variable. Generally this should happen in the create() function.

Now that we have a Music instance, we can play the sound:

music.setLooping(true);
music.play();

Also notice the music.setLooping(true) line, which is handy for music that repeats over and over again.

Example

Putting it all together, here’s an example that plays background music, and plays a sound whenever the user taps inside a circle:

package io.happycoding.helloworld;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputAdapter;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.Vector2;

public class HelloWorldGame extends ApplicationAdapter {

    ShapeRenderer shapeRenderer;
    Music music;
    Sound sound;
    float circleX;
    float circleY;
    float circleRadius;

    public void create () {
        shapeRenderer = new ShapeRenderer();
        music = Gdx.audio.newMusic(Gdx.files.internal("banjo.mp3"));
        sound = Gdx.audio.newSound(Gdx.files.internal("meow.mp3"));
        circleX = Gdx.graphics.getWidth() / 2;
        circleY = Gdx.graphics.getHeight() / 2;
        circleRadius = Gdx.graphics.getHeight() / 3;

        Gdx.input.setInputProcessor(new InputAdapter() {

            @Override
            public boolean touchDown(int x, int y, int pointer, int button) {
                if (Vector2.dst(x, y, circleX, circleY) < circleRadius) {
                    sound.play();
                }
                return true;
            }
        });

        music.setLooping(true);
        music.play();
    }

    public void render () {
        Gdx.gl.glClearColor(.125f, .125f, .125f, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
        shapeRenderer.setColor(0, 1, 0, 1);
        shapeRenderer.circle(circleX, circleY, circleRadius);
        shapeRenderer.end();
    }

    @Override
    public void dispose() {
        music.dispose();
        sound.dispose();
        shapeRenderer.dispose();
    }
}

Also notice that the Music and Sound files are disposed of in the dispose() function.