Main Site Links Resources Tutorials
News VB Gaming Code Downloads DirectX 7
Contact Webmaster VB Programming Product Reviews DirectX 8
  General Multimedia Articles DirectX 9

DirectSound: 3D Sound
By: Jack Hoxley
Written: June 2000

Download: DS_3D.Zip (14kb)

DirectSound3D is a fairly new addition to DirectX, and is possibly one of the fastest developing areas of technology (behind 3D). New 3D soundcards are coming out all the time, with incredible sound quality. Sound has moved on from just squeaks and beeps. I happen to own one of each of the main competitors (Aureal Vortex 2 and Creative EAX) - playing games that support 3D and using 4 speakers is amazing; it adds something to the game.

Anyway; Using DirectSound3D is fairly easy; as most of it is automated - you set up the sound parameters, and set where it's coming from in 3D space and it'll do the rest. Bare in mind that it is hardware dependent - Although you dont need to enumerate for it's presence, it wont really be in full effect unless the computer either has 2 speaker 3D emulation or a full 4 (or more) speaker surround sound system. Also bare in mind that setting a buffer to be 3D has performance costs; because of this you should limit the number of 3D sounds, and give users the option of turning it off - It could well make a difference, especially if the 3D calculations are done by the processor (rather than hardware).

DirectSound3D can be combined with Direct3D; which is often the case. Because they both use the same unit/coordinate scheme it is easy to set a sound to come from a given place in your 3D world; which adds to the atmosphere greatly. You will need to bare the following things in mind when setting up your application

The coordinate system is the same for DirectSound as it is for Direct3D - X, Y, Z. It is easily shown with this diagram:

In Directsound 3D, unless set otherwise, you (the listener) is positioned at 0,0,0 This means that to get a sound in front of you it must have a +Z value; for it to be behind you it must have -Z value. For it to be to the left it must be -X, to the right it must be +X. To be above it must be +Y and below -Y. Of course, this all changes when you start moving around...

The distance from the sound to the listener needs to be very small to be heard properly. To be heard at a reasonable volume (when the normal volume is at Max) it must be within 0.5 units of the listener. Anything more than 5 will be almost silent. If the sound you are playing doesn't appear to be playing, it is quite likely to be that it is too far away. If this system does not fit into your 3D world, you can quite easily add a multiplier or divider to increase/decrease the value that you use.

And you will need to know what these are:

This class represents you - the listener; and how the sounds are played. In a typical 3D game, the position of the DirectSound3DListener would need to be the same position as the player. This object also controls the amount of Roll Off and Doppler effects of sound heard by the user, and other effects and settings related to the environment. More on this in another Tutorial.

This object does all the 3D calculations for a sound. It attaches itself to a normal sound buffer (with a normal wave file) and then modifies it. You can use this object to set the sounds properties; including orientation, direction, Velocity and position. The changes made here affect only this sound; whereas changes in Directsound3DListener affect everything on a global scale.

Step1: Initialising Everything
This is very similiar to intialising a normal DirectSound program; except for a few different variables and flags.

'We must always have the root DirectX object
Dim Dx As New DirectX7
'DirectSound will be created by DirectX
Dim Ds As DirectSound
'This is where the sound is; and what we play
'to hear it

Dim DsBuffer As DirectSoundBuffer
'This does all the 3D calculations
Dim DsBuffer3D As DirectSound3DBuffer
'The primary sound buffer
Dim DsPrimary As DirectSoundBuffer
'This represents you.
Dim DsListener As DirectSound3DListener
'Although this says D3D at the beginning
'it is only used because it has all the right
'properties for us: X, Y, Z

Dim SoundPos As D3DVECTOR
On Local Error Resume Next
Set Ds = Dx.DirectSoundCreate("")
'Tell the user we've got a problem
If Err.Number <> 0 Then
MsgBox "Unable to initialise; Either bad soundcard or bad drivers. Quiting"
End If

'Priority gives us greater control.
Ds.SetCooperativeLevel Me.hWnd, DSSCL_PRIORITY
'These two describe what our sound buffer will be like
'Using the CTRL3D flag has speed penalties; dont use it unless
'you have to - but you have to use it for 3D sounds...

'You can set the Stereo/Mono and Frequency settings here
'and they will be applied to the primary buffer.

Set DsPrimary = Ds.CreateSoundBuffer(primDesc, format)

'Get a 3D listener device
Set DsListener = DsPrimary.GetDirectSound3DListener()
'The listener is at the 3D coordinate 0,0,0

'We set the sound to be front-left
'of the listener

SoundPos.X = -0.5: SoundPos.Z = 0.5

'0 is the loudest volume
DsBuffer.SetVolume 0

Step2: Loading and Setting up
Now that we have everything initialised we can load some data into our buffer; and set the options of our buffer.

Dim bufferDesc1 As DSBUFFERDESC
Dim waveFormat1 As WAVEFORMATEX

file = App.Path & "\tester.wav"
Set DsBuffer = Ds.CreateSoundBufferFromFile(file, bufferDesc1, waveFormat1)

'The original buffer (above) must be created before this
'line; and the original buffer must have the CTRL3D flag present

Set DsBuffer3D = DsBuffer.GetDirectSound3DBuffer

'The angles define how sensitive the sound buffer will be. A
'narrower cone will result in more sensitive.
'You can have 0 degrees for no cone
'You can have 360 degrees for a full sphere
'Or you can use any of these constants
'DS3D_DEFAULTCONEANGLE - the default is 360 degrees

'the DS3D_IMMEDIATE makes Directsound stop and recalculate ALL
'Directsound3D Buffers, coordinates and positions. If you use
'DS3D_DEFFERED flag, you can make several parameter changes before
'allowing DirectSound to recalculate everything. You have to call;
'DirectSound3DListener.CommitDefferedSettings before they take effect.

DsBuffer3D.SetConeOutsideVolume -400, DS3D_IMMEDIATE

DsBuffer3D.SetPosition SoundPos.X / 50, 0, SoundPos.Z / 50, DS3D_IMMEDIATE

Now; If we play our DsBuffer object we will be getting a 3D sound. Cones are quite important, and are discussed in a later tutorial.

Step3: Positioning the sound.
Before this code is executed; you should set the sound to play looping. The code is very simple; and is included in the example project. This next piece of code will rotate the sound in a square about your position. If you listen closely you will hear the sound go past you, behind you and to either side of you.

Select Case CurrStage
Case 0 'Left
SoundPos.Z = SoundPos.Z - 0.1
If SoundPos.Z <= -0.5 Then
CurrStage = 1
End If
Case 1 'behind
SoundPos.X = SoundPos.X + 0.1
If SoundPos.X >= 0.5 Then
CurrStage = 2
End If
Case 2 'right
SoundPos.Z = SoundPos.Z + 0.1
If SoundPos.Z >= 0.5 Then
CurrStage = 3
End If
Case 3 'in front
SoundPos.X = SoundPos.X - 0.1
If SoundPos.X <= -0.5 Then
CurrStage = 0
End If
End Select

'The next line is a safety net; to stop us changing stuff at the wrong times.
If DsBuffer3D Is Nothing Then Exit Sub
DsBuffer3D.SetPosition SoundPos.X, SoundPos.Y, SoundPos.Z, DS3D_IMMEDIATE

Although this tutorial has shown you all the code needed, it is advisable to look at the demonstration program - which will give you a better idea of how this works. You can get it from the top of the page; or from my downloads page.

DirectX 4 VB 2000 Jack Hoxley. All rights reserved.
Reproduction of this site and it's contents, in whole or in part, is prohibited,
except where explicitly stated otherwise.
Design by Mateo
Contact Webmaster