Sound



Sound



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.

  • Make them yourself. It’s easier than you might think! Get yourself a microphone (most laptops come with one, or you can get one that plugs into your USB port) and use a program like Audacity to edit the sounds.
  • Use a chiptune generator. Chiptunes are the sounds you associate with 8-bit video games: think beeps and zaps. There are a bunch of programs designed to generate these types of sounds, including bfxr, sfxr, and ChipTone.
  • Download them. Sites like Freesound.org provide access to sound files that have been released under a creative common license. Please note that different sounds might have different versions of the license- more info on that here.
  • Work with a sound artist. There are plenty of sound artists out there on Twitter and the internet, and many will do commission work on the side. Consider contacting the sound artist that worked on an indie game you played recently.

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:

  • If you have an Android project, put your images inside the assets directory inside your Android project.
  • If you do not have an Android project, put your images inside the assets directory inside your core project.

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.

Comments

Happy Coding is a community of folks just like you learning about coding.
Do you have a comment or question? Post it here!

Comments are powered by the Happy Coding forum. This page has a corresponding forum post, and replies to that post show up as comments here. Click the button above to go to the forum to post a comment!