# JME 3 Tutorial (11) - Hello Audio

Previous: Hello Terrain, Next: Hello Effects
This tutorial explains how to add 3D sound to a game, and how make sounds play together with other game events. We learn how to use the Audio Renderer, an Audio Listener, and Audio Nodes. We also make use of an Action Listener and a MouseButtonTrigger from the previous Hello Input tutorial to make a mouse click trigger a gun shot sound.

## Sample Code

    package jme3test.helloworld;
    import com.jme3.app.SimpleApplication;
    import com.jme3.audio.AudioNode;
    import com.jme3.input.controls.ActionListener;
    import com.jme3.input.controls.MouseButtonTrigger;
    import com.jme3.material.Material;
    import com.jme3.math.ColorRGBA;
    import com.jme3.math.Vector3f;
    import com.jme3.scene.Geometry;
    import com.jme3.scene.shape.Box;
    /** Sample 11 - playing 3D audio. */
    public class HelloAudio extends SimpleApplication {
      private AudioNode audio_gun;
      private AudioNode audio_nature;
      private Geometry player;
      public static void main(String[] args) {
        HelloAudio app = new HelloAudio();
        app.start();
      }
      @Override
      public void simpleInitApp() {
        flyCam.setMoveSpeed(40);
        /** just a blue box floating in space */
        Box(Vector3f.ZERO, 1, 1, 1);
        player = new Geometry("Player", box1);
        Material mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
        mat1.setColor("Color", ColorRGBA.Blue);
        player.setMaterial(mat1);
        rootNode.attachChild(player);
        /** custom init methods, see below */
        initKeys();
        initAudio();
      }
      /** We create two audio nodes. */
      private void initAudio() {
        /* gun shot sound is to be triggered by a mouse click. */
        audio_gun = new AudioNode(audioRenderer, assetManager, "Sound/Effects/Gun.wav");
        audio_gun.setLooping(false);
        audio_gun.setVolume(2);
        /* nature sound - keeps playing in a loop. */
        audio_nature = new AudioNode(audioRenderer, assetManager, "Sound/Environment/Nature.ogg");
        audio_nature.setLooping(true);
        audio_nature.setPositional(true);
        audio_nature.setLocalTranslation(Vector3f.ZERO.clone());
        audio_nature.setVolume(3);
        audioRenderer.playSource(audio_nature); // play continuously!
      }
      /** Declaring the "Shoot" action, and
       *  mapping it to a trigger (mouse click). */
      private void initKeys() {
        inputManager.addMapping("Shoot", new MouseButtonTrigger(0));
        inputManager.addListener(actionListener, "Shoot");
      }
      /** Defining the "Shoot" action: Play a gun sound. */
      private ActionListener() {
        @Override
        public void onAction(String name, boolean keyPressed, float tpf) {
          if (name.equals("Shoot") && !keyPressed) {
            audioRenderer.playSource(audio_gun); // play once!
          }
        }
      };
      /** Move the listener with the a camera - for 3D audio. */
      @Override
      public void simpleUpdate(float tpf) {
        listener.setLocation(cam.getLocation());
        listener.setRotation(cam.getRotation());
      }
    }

When you run the sample, you should see a blue cube, and hear nature ambient sounds. When you click you hear a loud shot.

## Understanding the Code Sample

In the game's `initSampleApp()` method, we create a simple blue cube geometry called `player` and attach it to the scene – it's just sample content so you see something when running the audio sample. From `initSampleApp()`, we initialize the game by calling the two custom methods `initKeys()` and `initAudio()`. You could call the lines of code in these two methods directly from `initSampleApp()`; we simply moved them into extra methods to keep the code more readable. Let's look at `initKeys()`: As we learned in previous tutorials, we use jme's `inputManager` to respond to user input. We add a mapping for a left mouse button click, and we name this new action `Shoot`.

    /** Declaring the "Shoot" action and mapping to a trigger. */
      private void initKeys() {
        // click to shoot
        inputManager.addMapping("Shoot", new MouseButtonTrigger(0));
        inputManager.addListener(actionListener, "Shoot");
      }

Setting up the ActionListener should also be familiar from previous tutorials. We declare that, when the trigger (the mouse button) is pressed and released, we want to play a gun sound.

      /** Defining the "Shoot" action: play a sound. */
      private ActionListener() {
        @Override
        public void onAction(String name, boolean keyPressed, float tpf) {
          if (name.equals("Shoot") && !keyPressed) {
            audioRenderer.playSource(audio_gun);
          }
        }
      };

Next we have a closer look at `initAudio()` to learn how to use the `AudioRenderer` and `AudioNode`s.

## AudioNodes

Using audio is quite simple. Save your audio files into your `assets/Sound` directory. jME3 supports both Ogg Vorbis (.ogg) and Wave (.wav) files. For each sound you create an audio node. A sound node can be used like any node in the jME scene graph. We create one node for a gunshot sound, and one for a nature sound.

      private AudioNode audio_gun;
      private AudioNode audio_nature;

Look at our custom `initAudio()` method: Here we initialize the sound objects and set their parameters.

        audio_gun    = new AudioNode( audioRenderer, assetManager, "Sound/Effects/Gun.wav");
        ...
        audio_nature = new AudioNode( audioRenderer, assetManager, "Sound/Environment/Nature.ogg");

These two lines create new sound nodes from the given audio files in the assetManager. In the next lines we specify that we want the gunshot sound to play only once – we don't want it to loop. We specify its volume as gain factor (at 0, sound is muted, at 2, it is twice as loud, etc.).

        audio_gun.setLooping(false);
        audio_gun.setVolume(2);

The nature sound is different: We want it to loop continuously as background sound. This is why we set looping to true, and we already call the play() method on the node. We also choose to set its volume to 3.

        audio_nature.setLooping(true);
        audio_nature.setVolume(3);
    ...
        audioRenderer.playSource(audio_nature); // play continuously!
      }

We can choose to make the audio_nature a positional sound that comes from a certain place. We have to give the node an explicit translation, in this example we choose Vector3f.ZERO (which stands for the coordinates `0.0f,0.0f,0.0f`, the center of the scene.) Since jME supports 3D audio, you will be able to hear this sound coming from this particular location. Making the sound positional is optional.

        audio_nature.setPositional(true);
        audio_nature.setLocalTranslation(Vector3f.ZERO.clone());

## Triggering Audio

The two sounds are used differently:

- The gunshot is situational. We want to play it only once, right when it is triggered.
  - This is why we made it `setLooping(false)`
- The nature sound is a background noise. We want it to start playing and loop on as long as the game runs.
  - This is why we made it `setLooping(true)`

Now every sound knows whether it loops or not. The actual `play` command is the same for both files:

        audioRenderer.playSource(audio_nature);
    ...
        audioRenderer.playSource(audio_gun);

Appart from the looping Boolean, the only difference is where play() is called:

- We start playing the background nature sound right after we have created it, in the initAudio() method.
- The gunshot sound, however, is triggered situationally, only as part of the `Shoot` input action that we defined in the ActionListener.

     /** Defining the "Shoot" action: Play a gun sound. */
      private ActionListener() {
        @Override
        public void onAction(String name, boolean keyPressed, float tpf) {
          if (name.equals("Shoot") && !keyPressed) {
            audioRenderer.playSource(audio_gun); // play once!
          }
        }
      };

## Your Ear in the Scene - 3D Audio Listener

To keep up the 3D audio effect, jME needs to know the position of the sound source, and the position of the ears of the player. The ear is represented by an 3D Audio Listener object. The `listener` is a built-in object in a SimpleApplication (it is not related to any other Java Listeners, such as the input manager's ActionListener). In order to make the most of the 3D audio effect, we use the `simpleUpdate()` method to move and rotate the listener (the player's ears) together with the camera (the player's eyes).

    public void simpleUpdate(float tpf) {
      listener.setLocation(cam.getLocation());
      listener.setRotation(cam.getRotation());
    }

## Global, Directional, Positional?

In this example, we defined the nature sound as coming from a certain position, but not the gunshot sound. This means our gunshot is global and can be heard everywhere with the same volume. JME3 also supports directional sounds, that can only be heard from a certain direction (More about Audio here). How do you make this decision?

- In a game with moving enemies you may want to make the gun shot or footsteps positional sounds. In these cases you must move the audio nodes to the location of the enemy before playing it. This way a player with stereo speakers could hear from which direction the steps or gun shots are coming.
- Similarly, you may have game levels where you want one background sound to play globally. In this case, you would make the audio_nature neither positional nor directional (set both to false).
- If you want sound to be "absorbed by the walls" and only broadcast in one direction, you would make it directional. (More about Audio here.)

In short, you must choose in every situation whether you want a sound to be global, directional, or positional.

## Conclusion

You now know how to add the two most common types of sound to your game: Global sounds and positional sounds. You can play sounds in two ways: Either continuously in a loop, or situationally just once. You also learned to use sound files that are in either .ogg or .wav format. Tip: jME's Audio implementation also supports more advanced effects such as reverberation and the Doppler effect. You can also create directional sounds, and stream long sound files instead of buffering first. Find out more about these features from the sample code included in the jme3test directory and from the advanced Audio docs. Want some fire and explosions to go with your sounds? Read on to learn more about effects.

sound, documentation, beginner,, beginner, intro

view online version