Sep 14, 2014

50. Positional Audio

Positional audio changes as the player approaches or goes away from the source.




The audio source is a high blue box. This is only a visual representation and actual audio node is created later.


        // *** 1. Start (High Blue Box, Source of Sound)
        Box b = new Box(.1f, 1f, .1f);
        geomSource = new Geometry("Source", b);
        Material mat = new Material(assetManager,
                "Common/MatDefs/Misc/Unshaded.j3md");
        mat.setColor("Color", ColorRGBA.Blue);
        geomSource.setMaterial(mat);
        geomSource.setLocalTranslation(new Vector3f(-1.5f,0,0));
        rootNode.attachChild(geomSource);
        // *** 1. End



The player is oval shaped with arrow controls, defined next.


        // *** 2. Start (Listener is Red oval shaped)
        Sphere sphere = new Sphere(16,16,.1f);
        geomListener = new Geometry("Listener",sphere);
        Material mat1 = new Material(assetManager, 
                "Common/MatDefs/Misc/Unshaded.j3md");
        mat1.setColor("Color", ColorRGBA.Red);
        geomListener.setMaterial(mat1);
        geomListener.setLocalTranslation(3,0,0);
        geomListener.setLocalScale(new Vector3f(1,10,1));
        rootNode.attachChild(geomListener);
        // *** 2. End



The arrow keys are mapped.


        // *** 3. Start (arrows for left and right)
        inputManager.addMapping("Left", new KeyTrigger(
                KeyInput.KEY_LEFT));
        inputManager.addMapping("Right", new KeyTrigger(
                KeyInput.KEY_RIGHT));
        inputManager.addMapping("Up", new KeyTrigger(
                KeyInput.KEY_UP));
        inputManager.addMapping("Down", new KeyTrigger(
                KeyInput.KEY_DOWN));
        inputManager.addListener(analogListener,
                "Left", "Right", "Up", "Down");
        // *** 3. End



The arrow callbacks update the oval position.


        // *** 4. Start (move left or right)
        public void onAnalog(String name, 
                float value, float tpf) {
            if (name.equals("Left")) {
                geomListener.move(-.01f, 0, 0);
            } else if (name.equals("Right")) {
                geomListener.move(.01f, 0, 0);
            } else if (name.equals("Up")) {
                geomListener.move(0, .01f, 0);
            } else if (name.equals("Down")) {
                geomListener.move(0, -.01f, 0);
            }
        }
        // *** 4. End



The audio is set as positional, loaded into memory (should be small audio samples), otherwise we should stream. We should set RefDistance and MaxDistance. For ambient background audio, etc. we will not set is as positional or give the two distance values.


        // *** 5. Start (Positional Audio)
        bark = new AudioNode(assetManager,
                "Sounds/Dog/bark.wav");
        bark.setPositional(true);
        bark.setRefDistance(.03f);  // 50% volume distance
        bark.setMaxDistance(3f);    // Steady volume distance
        bark.setVolume(2);          // Initial volume
        bark.setLooping(true);      // continuous
        bark.setLocalTranslation(
                geomSource.getLocalTranslation());
        rootNode.attachChild(bark);
        bark.play();               
        // *** 5. End



For positional audio, the listener position must be updated.


        // *** 6. Start (status + new audio listener loc)
        // listener is protected variable of SimpleApplication
        dist = geomListener.getLocalTranslation().
                distance(geomSource.getLocalTranslation());
        System.out.println("Distance: " + dist);
        if (dist>3||dist<-3) System.out.println("--Steady");
        else System.out.println("--Changing");
        listener.setLocation(
                geomListener.getLocalTranslation());
        // *** 6. End



// JMonkey50.java

package mygame;

import com.jme3.app.SimpleApplication;
import com.jme3.audio.AudioNode;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.AnalogListener;
import com.jme3.input.controls.KeyTrigger;
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;
import com.jme3.scene.shape.Sphere;
import com.jme3.system.AppSettings;

public class JMonkey50 extends SimpleApplication {
    public static void main(String[] args) {
        AppSettings settings = new AppSettings(true);
        settings.setFrameRate(60);
        settings.setTitle("Positional Audio!");
        JMonkey50 app = new JMonkey50();
        app.setSettings(settings);
        app.start();
    }
    
    private AudioNode bark;
    private Geometry geomListener;
    private Geometry geomSource;

    @Override
    public void simpleInitApp() {
        viewPort.setBackgroundColor(ColorRGBA.White);
        setDisplayFps(false);
        setDisplayStatView(false);
        cam.setLocation(new Vector3f(-2,0,10)); // move camera left
        flyCam.setEnabled(false);
        
        // *** 1. Start (High Blue Box, Source of Sound)
        Box b = new Box(.1f, 1f, .1f);
        geomSource = new Geometry("Source", b);
        Material mat = new Material(assetManager,
                "Common/MatDefs/Misc/Unshaded.j3md");
        mat.setColor("Color", ColorRGBA.Blue);
        geomSource.setMaterial(mat);
        geomSource.setLocalTranslation(new Vector3f(-1.5f,0,0));
        rootNode.attachChild(geomSource);
        // *** 1. End

        // *** 2. Start (Listener is Red oval shaped)
        Sphere sphere = new Sphere(16,16,.1f);
        geomListener = new Geometry("Listener",sphere);
        Material mat1 = new Material(assetManager, 
                "Common/MatDefs/Misc/Unshaded.j3md");
        mat1.setColor("Color", ColorRGBA.Red);
        geomListener.setMaterial(mat1);
        geomListener.setLocalTranslation(3,0,0);
        geomListener.setLocalScale(new Vector3f(1,10,1));
        rootNode.attachChild(geomListener);
        // *** 2. End
        
        initKeys(); // initialize 4 arrows
        initAudio(); // initialize positional audio
    }
    
    private void initKeys() {
        // *** 3. Start (arrows for left and right)
        inputManager.addMapping("Left", new KeyTrigger(
                KeyInput.KEY_LEFT));
        inputManager.addMapping("Right", new KeyTrigger(
                KeyInput.KEY_RIGHT));
        inputManager.addMapping("Up", new KeyTrigger(
                KeyInput.KEY_UP));
        inputManager.addMapping("Down", new KeyTrigger(
                KeyInput.KEY_DOWN));
        inputManager.addListener(analogListener,
                "Left", "Right", "Up", "Down");
        // *** 3. End
    }
 
    private AnalogListener analogListener = 
            new AnalogListener() {
        // *** 4. Start (move left or right)
        public void onAnalog(String name, 
                float value, float tpf) {
            if (name.equals("Left")) {
                geomListener.move(-.01f, 0, 0);
            } else if (name.equals("Right")) {
                geomListener.move(.01f, 0, 0);
            } else if (name.equals("Up")) {
                geomListener.move(0, .01f, 0);
            } else if (name.equals("Down")) {
                geomListener.move(0, -.01f, 0);
            }
        }
        // *** 4. End
    };
    
 
    private void initAudio() {
        // *** 5. Start (Positional Audio)
        bark = new AudioNode(assetManager,
                "Sounds/Dog/bark.wav");
        bark.setPositional(true);
        bark.setRefDistance(.03f);  // 50% volume distance
        bark.setMaxDistance(3f);    // Steady volume distance
        bark.setVolume(2);          // Initial volume
        bark.setLooping(true);      // continuous
        bark.setLocalTranslation(
                geomSource.getLocalTranslation());
        rootNode.attachChild(bark);
        bark.play();               
        // *** 5. End
    }
    
    float dist;

    @Override
    public void simpleUpdate(float tpf) {
        // *** 6. Start (status + new audio listener loc)
        // listener is protected variable of SimpleApplication
        dist = geomListener.getLocalTranslation().
                distance(geomSource.getLocalTranslation());
        System.out.println("Distance: " + dist);
        if (dist>3||dist<-3) System.out.println("--Steady");
        else System.out.println("--Changing");
        listener.setLocation(
                geomListener.getLocalTranslation());
        // *** 6. End
    }
}


Output:


No comments:

Post a Comment