Introduction
The most exciting feature in DirectSound 9 is the possibility to move in the 3D space, the sounds and the points of listening. Audio is so important in applications such as videogames, that 3D audio is a godsend, especially because implementing 3D audio system with DirectSound 9 is very simple.
Requirements
To understand this tutorial, it is important to have familiarity with simple audio playback with Managed DirectSound 9 and with all the general concepts about Managed DirectX, so please read the previous tutorial about sound playback. In DirectSound 9 a sound source can be used in 3D only if it is mono. This is important because even a stereo file has ‘3D sound information’. If you try to use a non-mono file, DirectSound will raise an exception.
Using 3D audio sources and listeners
The technique is so simple that I will use only a paragraph to explain it. The first step is to create a Device
and a sound
, adding some new objects for this particular purpose:
private Device dSound;
private SecondaryBuffer sound;
private Buffer3D sound3D;
private Listener3D listener;
The Buffer3D
is the new buffer object that manages the 3D virtualization of the sound. This object can be moved in the space and its properties will be considered later. Listener3D
is a point of listening and represents, obviously, a ‘human’ listener. This object can be moved in the space and has some cool options. Now you can proceed and create the objects:
dSound = new Device();
dSound.SetCooperativeLevel(this.Handle,
CooperativeLevel.Priority);
BufferDescription d = new BufferDescription();
d.ControlVolume = true;
d.ControlPan = true;
d.ControlFrequency = true;
d.ControlEffects = true;
d.Control3D = true;
d.Guid3DAlgorithm =
DSoundHelper.Guid3DAlgorithmHrtfFull;
sound = new SecondaryBuffer(filePath, d, dSound);
It is better to select, when possible, the most powerful audio card, so use the overloaded constructor of Device
, as shown in the previous tutorial. A note about d.Guid3DAlgorithm
: this property specifies the algorithm the system will use to manage the 3D audio. There are various possibilities:
Guid3DAlgorithmDefault
(audio card’s default, very easy)
Guid3DAlgorithmHrtfFull
(max quality, even if a software emulation is needed)
Guid3DAlgorithmHrtfLight
(less quality but less used resources)
Guid3DAlgorithmNoVirtualization
(only left/right effects, perfect in bad systems or even with stereo-only outputs or if you don’t move the sounds vertically)
The next step is to create the 3D buffer:
sound3D = new Buffer3D(sound);
sound3D.Mode = Mode3D.HeadRelative;
The property sound3D.Mode
specifies how the system will manage the 3D sound. There are three options:
HeadRelative
(sound and listener positions will be considered)
Normal
(listener will be virtually forced in 0, 0, 0 position)
Disable
(disables 3D sound, useful to disable it temporarily)
Now it’s time to set up the listener:
Buffer b;
BufferDescription dp = new BufferDescription();
dp.PrimaryBuffer = true;
dp.Control3D = true;
b = new Buffer(dp, dSound);
listener = new Listener3D(b);
listener.Position = new Vector3(0, 0, 0);
sound3D.Position = new Vector3(0, 0, 0);
Listener3DOrientation o = new Listener3DOrientation();
o.Front = new Vector3(0, 0, 1);
o.Top = new Vector3(0, 1, 0);
listener.Orientation = o;
sound.Play(0, BufferPlayFlags.Looping);
Vector3
is a struct
that represents one point in a 3D space. It is located inside the Microsoft.DirectX
namespace. Now you have to play the sound and move it, or move the listener. Let's see some tricks.
Listener3D
has these important members:
Position
: the position (Vector3
) of the listener.
Velocity
: (vx, vy, vz) the instantaneous speed (Vector3
) of the listener. You should use this when the listener is moving and you want to apply a Doppler effect.
Orientation
: it is the ‘forward’ orientation of the listener. You have to set the Front and the Top directions using Vector3
objects. In this tutorial I set the Front to the positive Z axis, and the Top to the positive Y axis.
DistanceFactor
: it is the measurement unit for the distances. 1 equals to a meter, so 0.001 equals to a millimeter.
RolloffFactor
: the sound attenuation in the space (0 to 10, 1 is the default for real world).
DopplerFactor
: the factor for the automatic Doppler effect (0 to 10, 1 is the default for real world). If you don’t know what the Doppler effect is, I'll explain it with an example: think of a car that is approaching you. The noise that the car produces when it approaches you is different from the noise that is produces when it goes away. This effect occurs in each type of wave phenomena, such as sound and light spreading.
Buffer3D
has these members:
Play
, Stop
and so on are inherited from the Buffer and are equal to the SecondaryBuffer
’s ones.
Position
: the sound source position (Vector3
), same as Buffer3D.Position
.
MinDistance
, MaxDistance
: the first one is the distance from where the sound starts to attenuate, the second one is the distance from where the sound stops to attenuate. In other words, until MinDistance
the sound is at its max volume, between MinDistance
and MaxDistance
the sound gradually attenuates, over MaxDistance
the sound remains at a low volume and attenuates no more. For these options Listener3D.DistanceFactor
and Listener3D.RolloffFactor
matter! Unfortunately, the best way to understand the real behaviour of these parameters is to try and test them.
Velocity
: the speed of the sound source, if it is moving, the same as Listener3D.Velocity
.
ConeOrientation
: (Vector3
) this option allows you to specify the cone inside which the sound will spread. The Vector3
is the end-point of an imaginary line starting from the sound position, defining the orientation of the cone.
ConeAngles
: (Angles
) the angle for the inside cone and outside cone: inside the first one the volume will have maximum value, inside the second one the volume will attenuate progressively (see MSDN).
ConeOutsideVolume
: specifies the volume outside the external cone described above.
There are no more interesting features to describe. See the attached demo app, that shows a moving sound source and a fixed listener. You can move the source with your mouse or make it rotate around the listener. As usual, I suggest going through the MSDN documentation: after you understand the main techniques, extending them is very simple.
Performances notes
We can say DirectSound is very fast. This statement is valid in most cases, but we need to describe some situations. For example if the audio card doesn’t support 3D sounds, DirectSound will emulate them via software. If the system (or the same app) does not have to perform other tasks, the user won’t notice the difference. But if you are developing a videogame, 3D sounds will load the CPU, slowing down the system. So make your choices right. In the demo app you may notice a little roughness of the source’s movements, even though the CPU load remains under 10%.
Conclusions
Now you should be able to manage sounds inside a 3D space. Personally, I believe it is very simple. In the next tutorial I will explain how to record sounds with DirectSound’s CaptureDevice
.