Vizard 7 » Tutorials & Examples » Multimedia » 3D sound » Tutorial: 3D Sound
7.6

Tutorial: 3D Sound

This tutorial will teach you how to use 3d sounds in your script. Sounds will be attached to various objects in the scene so that it seems the sounds are being emitted from the locations of these objects.

This content is discussed in more detail in the reference section.

Attaching 3D sound to an object

If you have trouble getting the code in this tutorial to work, you can find the complete example script 3Dsound.py in the \tutorials\multimedia directory.

 

Add the following initial code:

import viz
import vizact

viz.setMultiSample(4)
viz.fov(60)
viz.go()

piazza = viz.addChild('piazza.osgb')

male = viz.addAvatar('vcc_male.cfg',pos=[8, 0, 7])
female = viz.addAvatar('vcc_female.cfg',pos=[8,0,9],euler=[180,0,0])
male.state(14)
female.state(14)

bird1 = viz.addAvatar('pigeon.cfg',pos=[-6.5, 0.43, -1.56],euler=[120,0,0])
bird1.state(1)

bird2 = viz.addAvatar('pigeon.cfg',pos=[5.61, 4.5, -9.88],euler=[-90,0,0])
bird2.state(1)

Using the <node3D>.playsound command, sounds can be attached to objects and sub-parts of objects. First, let's add the sound of water to the fountain:

piazza.playsound('fountain.wav',viz.LOOP,node='fountain-sound')

In the line above, playsound is called on the piazza object, which contains a fountain-sound node in it's scene graph. The fountain.wav file will be played so it sounds like it's coming from fountain-sound's position. If the node argument was left out, the sound would originate from the piazza's center point instead. Using loop mode makes it possible to create the natural continuous sound of a fountain with an audio file that's only a few seconds long.

 

Run the script and move in towards the fountain and see how the volume changes. Move to the left or right of the fountain and notice how the sound appears to be coming from the left or the right.

 

Next, let's add some conversation to the avatars by attaching sound to the head bone of the male avatar:

male.playsound('conversation.wav',viz.LOOP,node='Bip01 Head')

With avatars, the node argument will take the name of a bone to apply the sound to. If we don't specify a bone here, the sound will appear to originate from his center point, located at his feet. Run the script again and listen to the avatars in conversation.

 

Move in closely and you may be able to hear that both female and male voices originate from the head bone of the male. Ideally, we would want two sound files playing independently, one for each voice. An alternative is to play the one sound from a location between the two avatars. We can make sound appear from any location in space by attaching it to a group node. A group node functions like other nodes, but is invisible and has no associated geometry. It has a transformation matrix, a place in the scene graph, and works with most node3D commands:

#male.playsound('conversation.wav',viz.LOOP,node='Bip01 Head')

conversation_node = viz.addGroup(pos=[8,1.8,8])
conversation_node.playsound('conversation.wav',viz.LOOP)

Next, let's add the sound of bells coming from the bell tower:

bell_sound = piazza.playsound('bells.wav',node='bell-sound')
bell_sound.minmax(0,3)

The <multimedia:sound3D>.minmax command is used to clamp the sound volume so the chiming bells resonate throughout the courtyard. No matter where you are outside the max distance of 3 meters, it will sound as if you are 3 meters from the sound origin. Run the script with and without that line and hear the difference.

 

Loop mode was specified for both the fountain and conversation sounds at the time they were added. With the bell sound, the mode was not specified, so the sound stops after it plays through once. Once a sound is created, it can be played, paused, stopped, or set to play in loop mode. Let's add some user interaction so that every time the user presses '1' the bells are played again:

vizact.onkeydown('1',bell_sound.play)

Now, we'll make the birds call each other using sounds controlled by timers:

def startBird1():
    bird1_sound = bird1.playsound('birds.wav')
    vizact.ontimer(14,bird1_sound.play)

vizact.ontimer2(7,0,startBird1)

bird2_sound = bird2.playsound('birds.wav')
vizact.ontimer(14,bird2_sound.play)

Each bird is playing a sound every 14 seconds, but bird1's timer  is delayed 7 seconds so that the calls alternate.

 

Add the following code to position the viewpoint near bird2 with a key press:

def birdView():
    viz.MainView.setPosition([5.9,4.9,-10.2])
    viz.MainView.setEuler([-43.5,29,0])

vizact.onkeydown('2',birdView)

Run the script and press the '2' key. If you listen carefully you can hear the both the near and distant birds calls.

Sound Debug

To verify that sounds have been placed correctly and are playing at the correct times enable sound3D debug mode. This will render a sound icon at the location of all currently playing 3D sounds. Add the following line of code to toggle debug mode with the spacebar:

vizact.onkeydown(' ',viz.setDebugSound3D,viz.TOGGLE)

Run the script again and press the spacebar. There are sound icons immediately visible at the fountain and in between the avatars. Press the '2' key to move up near bird2 and see icons appear and disappear in sync with the bird calls. These sounds are emitted from the birds' center points because bones were not specified when the sounds were added. This is made apparent with the icon rendered at bird2's feet.

Note: 3D sounds only work with .WAV files that are recorded in mono.

Attaching 3D sound to objects

Controlling sound playback