Adding 3D Sound

Three dimensional sound can add to the feeling of immersion in a virtual environment, but it generally isn't as important as lighting or 3D user interaction. As has been stated often in this book, spatial navigation in the real world is multisensory in nature. As with any spatial cue, lack of or improper use of aural cues will detract from the user's feeling of immersion.

Java 3D has a fairly sophisticated 3D Sound model that can be used to advantage in many situations. At present, the Java 3D Sound model is based on panning only. Panning is the gradual switching between speakers. When we develop our 3D shopping mall demonstration in Chapter 14, we will use the JMF Sound Player in conjunction with the Java 3D Sound classes.

In general, it is helpful to think of Sound nodes in terms of some of the ideas presented in the section on “Lighting.” Like lighting, sounds can be directional and can fall off over distance. For many of the same reasons that lighting can be challenging, sound too can be difficult to use. It is often difficult to notice the subtleties of sound effects.

The Java 3D sound package supports three basic types of sounds: 1) Background sounds that are present throughout the environment (much like an ambient light), 2) Point sounds that emanate in all directions and have an attenuation (much as a PointLight simulates light energy), and 3) Cone sounds that act like a SpotLight to provide a directional source of sound.

Two additional classes are useful in creating sounds. The SoundScape node class specifies the area of space in which a sound is active, much like Bounds are used in lighting the scene.

The second class used to create sounds is the AuralAttributes object. This object is used to control how the amplitude of the sound attenuates with respect to distance from the object (like the Fog and Light nodes). Other properties are contained in the AuralAttributes object including looping and playback properties.

Because the sound objects are Leaf nodes, they can be added the same way as any Leaf node.

You must remember to set the SchedulingBounds for any sound that is to be heard. Again, this is directly analogous to the situation for lighting.

Listing 11.14 demonstrates the use of Directional and Point Sound Nodes.

Listing 11.14 SoundExample.java
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.geometry.ColorCube;
import com.sun.j3d.utils.geometry.Sphere;
import com.sun.j3d.utils.geometry.Box;

import com.sun.j3d.utils.universe.*;
import java.io.File;
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.audioengines.javasound.*;

public class SoundExample extends Applet {

  VirtualUniverse universe;
  Locale locale;
  TransformGroup vpTrans;
  View view;
  Bounds bounds;

. . .

    Point2f[] gainfield;

    public BranchGroup createSceneGraph() {
    // Create the root of the subgraph
      BranchGroup objRoot = new BranchGroup();

      TransformGroup objTrans = new TransformGroup();
        objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
     objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
     objRoot.addChild(objTrans);

    // Create a simple shape leaf node and add it into the scene graph.
       objTrans.addChild(new ColorCube(0.02));

       TransformGroup sphereTrans = new TransformGroup();
           sphereTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
       sphereTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);

       Sphere sphere = new Sphere(.4f, Sphere.GENERATE_NORMALS |
                  Sphere.GENERATE_TEXTURE_COORDS, 45);
           sphereTrans.addChild(sphere);

       Transform3D tmptrans = new Transform3D();
       sphereTrans.getTransform(tmptrans);
       tmptrans.setTranslation(new Vector3f(0.f, 0.f, 7.f));
           sphereTrans.setTransform(tmptrans);
           objRoot.addChild(sphereTrans);

       objTrans.addChild(new OpenRoom());

        BoundingSphere bounds =
           new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);

        Transform3D yAxis = new Transform3D();
    sphereTrans.getTransform(yAxis);

       Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE,
                        0, 0,
                        2500, 0, 0,
                        0, 0, 0);

    RotationInterpolator rotator =
            new RotationInterpolator(rotationAlpha, sphereTrans, yAxis,
                         0.0f, (float) Math.PI*2.0f);

    rotator.setSchedulingBounds(bounds);
. . .
        Color3f red = new Color3f(1.f, 0.f, 0.f);
        Color3f blue = new Color3f(0.f, 0.f, 1.f);

        Point3f Point1 = new Point3f(2.f, 2.f, -2.f);
        Point3f atten = new Point3f(.1f,0.4f,0.01f);


    AmbientLight al = new AmbientLight();
       al.setInfluencingBounds(bounds);

       PointLight redlight = new PointLight(red, Point1, atten);

       redlight.setInfluencingBounds(bounds);


       objTrans.addChild(al);
        sphereTrans.addChild(rotator);

       objTrans.addChild(redlight);


        // Create an AuralAttribute with reverb params set

        Soundscape soundScape2 = new Soundscape();
        AuralAttributes attributes2 = new AuralAttributes();
        attributes2.setReverbOrder(2);
        attributes2.setReverbDelay(2.f);
        attributes2.setReflectionCoefficient(0.f);

        attributes2.setFrequencyScaleFactor(10.5f);
        attributes2.setVelocityScaleFactor(1000.f);

        soundScape2.setApplicationBounds(bounds);
        soundScape2.setAuralAttributes(attributes2);

        objRoot.addChild(soundScape2);

        //
        // Instantiatiate a PointSound and add it to the scene graph
        //
        PointSound sound = new PointSound();
        sound.setCapability(PointSound.ALLOW_ENABLE_WRITE);
        sound.setCapability(PointSound.ALLOW_INITIAL_GAIN_WRITE);
        sound.setCapability(PointSound.ALLOW_SOUND_DATA_WRITE);
        sound.setCapability(PointSound.ALLOW_DURATION_READ);
        sound.setCapability(PointSound.ALLOW_POSITION_WRITE);
        sound.setCapability(PointSound.ALLOW_LOOP_WRITE);
        sound.setCapability(Sound.INFINITE_LOOPS);
        sound.setSchedulingBounds(bounds);

         MediaContainer sample  = new MediaContainer();

        sample.setCacheEnable(true);
        sample.setURLString(filename[0]);
        System.out.println("urlstring: " + sample.getURLString());
        sound.setSoundData(sample);
        Point3f soundPos = new Point3f(0.0f, 0.0f, 0.0f);
        sound.setPosition(soundPos);


        Point2f[] gf = {
            new Point2f(0.f, 1.0f),
            new Point2f(5.f, 0.4f),
            new Point2f(10.f, 0.2f),
            new Point2f(15.f, 0.1f),
            new Point2f(20.f, 0.0025f),
            new Point2f(25.f, 0.0f)

        };

        sound.setDistanceGain(gf);
        sound.setLoop(Sound.INFINITE_LOOPS);

        sound.setEnable(true);

    //objTrans.addChild(sound);
      sphereTrans.addChild(sound);
    return objRoot;
    }

    public void genGainField() {

        System.out.println("generating gain parameters");
        gainfield = new Point2f[4];
        float gain = .5f;
        float distance = 10.f;

        for (int ii=0; ii< 4; ii++) {
            distance = distance - 2.5f;
            gain = gain + .5f;

          //  System.out.println("distance: " + distance + " gain: " +  gain);
            gainfield[ii] = new Point2f(distance, gain);
        }

    }
. . .
					

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset