X3D Audio

Introduction

I've been working with the guys in the Xj3D project, implementing the audio and video elements of their java X3D loader.

For the Java3D X3D loader, we built the X3D audio implementation using the Java3D API (version 1.3). The X3D Sound node maps to a Java3D ConeSound. While the Java3D API supports a sound model very similar to the X3D model, the implementation is greatly complicated by the large number of bugs in Sun's Java3D audio implementation. The severity and quantity of bugs we have encountered suggests Sun have barely tested this API.

Known Java3D Bugs

The following are known issues with the Java3D audio libraries that affect the Xj3D sound implementation:

  • Sound fails to start.
    Some sound nodes fail to start correctly when the scene initially loads.
  • Back attenuation is wrong.
    The ellipsoid gain envelope does not correctly enforce the minBack and maxBack values.
These bugs are present in Java3D 1.3 and 1.3.1 beta 1.

Minimal Sound Test

Here's a very simple audio sample.

#VRML V2.0 utf8 
  Sound {
    source AudioClip { 
      loop TRUE   # Loop forever 
      url "doodoo.wav"
    } 
    minFront 200
  } 
minsound.wrl

I set minFront to 200 to ensure the initial view position is inside the sound envelope. Without that you hear nothing, as the default viewer position will be outside the default gain envelope.

Controlling Sounds

In the following example, I route the touchTime from two cubes to start and stop the audio. Click on the green box to start the audio, on the red box to stop the audio.

#VRML V2.0 utf8 

# Click on green box to start sound,
# click on red box to stop sound.

Sound {
   source DEF CLIP AudioClip { 
      loop TRUE
      url "doodoo.wav"
   } 
   spatialize TRUE
   maxFront 200
}

Transform {
   translation -0.5 0 0
   children [
      Shape {
	 geometry Box {size 1 1 1}
	 appearance Appearance {
	    material Material { diffuseColor 0 1 0 }
	 }
      }
      DEF GREEN TouchSensor {}
     ]
}
ROUTE GREEN.touchTime TO CLIP.startTime


Transform {
   translation 0.5 0 0
   children [
      Shape {
	 geometry Box {size 1 1 1}
	 appearance Appearance {
	    material Material { diffuseColor 1 0 0 }
	 }
      }
      DEF RED TouchSensor {}
     ]
}
ROUTE RED.touchTime TO CLIP.stopTime
switchsound.wrl
Multiple Sources

This example uses prototypes to create 9 sound sources. This tests the prototype implementation, as well as multiple voices. As in the previous example, click on the green cube to start a source, or the red cube to stop it.

#VRML V2.0 utf8 

PROTO Speaker [
	    field MFString url ["doodoo.wav"]
	    field SFVec3f position 0 0 0
	   ]
{
   Transform {
      translation IS position
      children [
	 Sound {         # Looped soundtrack 
	    source DEF CLIP AudioClip { 
	       loop TRUE   # Loop forever 
	       url IS url
	    } 
	    spatialize TRUE
	    minFront 0
	    maxFront 20
	    minBack 0
	    maxBack 20 
	 }
	 Group {
	    children
	    [
	     Transform {
		children [
		   Shape {
		      geometry Box {size 1 1 1}
		      appearance Appearance {
			 material Material { diffuseColor 0 1 0 }
		      }
		   }
		   DEF GREEN TouchSensor {}
		  ]
	     }
	     Transform {
		translation .25 .25 .25
		children [
		   Shape {
		      geometry Box {size 1 1 1}
		      appearance Appearance {
			 material Material { diffuseColor 1 0 0 }
		      }
		   }
		   DEF RED TouchSensor {}
		  ]
	     }
	    ]
	 }
	]
   }
   ROUTE GREEN.touchTime TO CLIP.startTime
   ROUTE RED.touchTime TO CLIP.stopTime
}

Speaker { url "one.wav" position   -3 0 0 }
Speaker { url "two.wav" position    0 0 0 }
Speaker { url "three.wav" position  3 0 0 }

Speaker { url "four.wav" position   -3 0 -3 }
Speaker { url "five.wav" position    0 0 -3 }
Speaker { url "six.wav"  position    3 0 -3 }

Speaker { url "seven.wav" position   -3 0 -6 }
Speaker { url "eight.wav" position    0 0 -6 }
Speaker { url "nine.wav"  position    3 0 -6 }
multisound.wrl