advertisement

Find Code  Advanced Search   

browse free vb code
Submit Code
ASP,  HTML, and XML
Database
Dates  and Math
Files  and Directories
Forms  and Controls
Lists,  Collections, and Arrays
Miscellaneous
Multimedia/Games
Office/VBA
Network/Internet
Registry
Screen/Graphics
String  Manipulation
System/API
Windows  2000/XP
VB.NET/ASP.NET



advertisement
Direct Sound Tutorial

Author: Jack Hoxley
Category: Multimedia/Games
Difficulty: Advanced

Version Compatibility:  Visual Basic 5   Visual Basic 6

This code has been viewed 143548 times.

DirectSound, as the name suggests, plays sounds. It is mostly used for Sound Effects in games, as it can handle more than one sound at a time ("Mixing"). You can also gain more control of the users audio system through DirectSound, such as panning and volume. There is now a sub section called DirectSound3D, this allows you to specify an x,y,z coordinate for the sound to originate from, this only really comes into use on a 4 speaker surround sound computer. 3D sound is best used in First Person Shooters, where you can have explosions coming from above/below left/right or all directions.

DirectSound is incredibly important for games, many reviewers rate a game on it's 3D engine, yet forget the sound. Listen to a game with the speakers off and you'll see what a difference it makes.

As with many of the other components of DirectX, they have limited use in Visual Basic. There is very little support for true 3D positional Sound. This is mainly to do with the language itself, Visual Basic was primarily a database tool (thats why there are so many data orientated controls), because of this it was never designed to be good at making games. Professional companies use C++ for games, therefore DirectX has more support in C++ than Visual Basic.

This tutorial will show you how to make a simple application that plays multiple sounds at the same time. It will have options for panning (Left <-> Right) and volume (You know this!).
The Code from this can then be added to any game where sound effects are needed.

First, a few words:

BUFFER-These hold the Sound Data
WAV FILE-This is the file type that DSound uses: *.Wav

Click on The List to see the relevent section:

SECTION

EXPLANATION

˙Starting Your Project

The Basics, which type of project to load into Visual Basic

˙Creating The Variables

The Variables, and an explanation of them

˙Creating The Interface

How your form should look, and the code that links everything together.

˙Creating The Loading Code

Make your program load some data

˙Making It Play Something

Exactly what it says on the tin! Get some output from your program.

˙Adding in Panning And Volume

The Finishing Touches.

˙

˙


STARTING YOUR PROJECT [top]
By now you should know how to start your project.

You will also need some sounds to play, find some .Wav files (If you dont know of any, use "find file" from the start menu). Copy TWO DIFFERENT files into the folder where your project is, naming them Tester1.Wav and Tester2.Wav

Save your project, and carry on with the tutorial.

˙



CREATING THE VARIABLES [top]
There are very few variables in this project, but i need to go over them. Add these lines into the (Declarations) section of Form1:

Option Explicit˙˙˙˙ 'This means that you have to define every variable, which is good practise, and DirectX likes it more
Dim m_dx As New DirectX7
˙ 'This is the root DirectX object, DirectSound is created from this object
Dim m_ds As DirectSound˙˙˙
'This is the directSound Object. Later on we will "Create" it from the main DirectX Object
Dim m_dsBuffer(1) As DirectSoundBuffer
'Note: This is an array, it isn't needed, but it makes programming this alot easier. 'With it as it is, m_dsBuffer(0) will hold tester1.Wav and m_dsBuffer(1) will hold Tester2.wav


As you will see later on, each buffer will be called to play/stop it's contents.

˙



CREATING THE INTERFACE [top]

An Example of the interface required.

The interface, as you can see, is quite complicated. I suggest going to the DOWNLOAD PAGE to get my pre-made copy, it'll make your life a lot easier. The interface is designed will a set of controls for each Buffer, and a final master set. The controls should be fairly obvious, but you'll need to know all the names:

(1) First off, create 2 frames, with any name. The first ones caption should be "Volume" & the second "Panning"
(2) Then, within the first frame, add in two scroll bars.

scrlTester1_Vol

˙˙˙˙ .Max=0

˙˙˙˙ .Min=-5000

˙˙˙˙ .LargeChange=20

˙˙˙˙ .SmallChange=255

scrlTester2_Vol

˙˙˙˙ .Max=0

˙˙˙˙ .Min=-5000

˙˙˙˙ .LargeChange=20

˙˙˙˙ .SmallChange=255

You can add the labels in if you want, but their not really necessary.

(3) Next, in the second frame, create 2 more scroll bars, like so:

scrlTester1_Pan

˙˙˙˙ .Max=10000

˙˙˙˙ .Min=-10000

˙˙˙˙ .LargeChange=1000

˙˙˙˙ .SmallChange=500

scrlTester2_Pan

˙˙˙˙ .Max=10000

˙˙˙˙ .Min=-10000

˙˙˙˙ .LargeChange=1000

˙˙˙˙ .SmallChange=500

(4) As a guide, use the picture to create the main "Control Panel", give each button these names/captions

cmdTester1_Play

˙˙˙˙ .Caption="Play Tester1.Wav"

cmdTester2_Play

˙˙˙ .Caption="Play Tester2.Wav"

cmdBoth_Play

˙˙˙ .Caption="Play Both"

cmdTester1_Stop

˙˙ .Caption="Stop Tester1.Wav"

cmdTester2_Stop

˙˙ .Caption="Stop Tester2.Wav"

cmdBoth_Stop

˙˙ .Caption="Stop Both"

cmdTester1_Pause

˙˙ .Caption="Pause Tester1.Wav"

cmdTester2_Pause

˙˙ .Caption="Pause Tester2.Wav"

cmdBoth_Pause

˙˙ .Caption="Pause Both"

(5) Then, the last part (phew!) is the Check Boxes:

chTester1_Loop

˙˙˙ .Caption="Tester1.Wav Loop"

chTester2_Loop

˙˙˙ .Caption="Tester2.Wav Loop"

chBoth_Loop

˙˙˙ .Caption="Loop Both Sounds"


You should now have an interface.

Next, We need to create the linking code. These are short portions of code that go in each control to make it all happen. Remember, dont run the project whilst adding these lines in, you'll get error messages about lots of things (Cos' we 'aint finished the code yet!). The Code for the Scroll Bars will be covered later on, as that needs a bit more detail.

Becase you have added all the controls and names, Paste these parts into the relevent places:

Private Sub Form_Load()
˙˙˙ Me.Show

˙˙˙ On Local Error Resume Next

˙˙˙ 'First we have to create a DSound object, this must be done before any features can be used.

˙˙˙ 'It must also be done before we set the cooperativelevel or create any buffers.

˙˙˙ Set m_ds = m_dx.DirectSoundCreate("")

˙˙˙ 'This checks for any errors, if there are no errors the user has got DX7 and a functional sound card

˙˙˙ If Err.Number <> 0 Then

˙˙˙˙˙˙˙ MsgBox "Unable to start DirectSound. Check to see that your sound card is properly installed"

˙˙˙˙˙˙˙ End

˙˙˙ End If

˙˙˙ 'THIS MUST BE SET BEFORE WE CREATE ANY BUFFERS

˙˙˙ 'associating our DS object with our window is important. This tells windows to stop

˙˙˙ 'other sounds from interfering with ours, and ours not to interfere with other apps.

˙˙˙ 'The sounds will only be played when the from has got focus....

˙˙˙ 'DSSCL_PRIORITY=no cooperation, exclusive access to the sound card

˙˙˙˙˙˙˙ 'Needed for games

˙˙˙ 'DSSCL_NORMAL=cooperates with other apps, shares resources

˙˙˙˙˙˙˙ 'Good for general windows multimedia apps.

˙˙˙ m_ds.SetCooperativeLevel Me.hwnd, DSSCL_PRIORITY

˙˙˙ LoadWave˙
'This sub is created later on, wait and see what it does.....................
End Sub

')))))))))))))))))))))(LOOPING CODE)(((((((((((((((((((((((((((((((((((((((((((((
'I have grouped all these parts together, as they are almost identical.

'In all 3 cases it checks if the checkBox has been de-selected

'then, checks to see if there is anything in the buffers (Has it been loaded yet?)

'Lastly, it stops the sound playing, and "Rewinds" it back to the beginning.

'The Buffer Check is an error handler, you cant modify the buffer if there is nothing there
'It would cause an error if you attempt to stop a buffer playing when

'it's empty......

Private Sub chBoth_Loop_Click()

If chBoth_Loop.Value = 0 Then

If m_dsBuffer(0) Is Nothing And m_dsBuffer(1) Is Nothing Then Exit Sub

m_dsBuffer(0).Stop

m_dsBuffer(0).SetCurrentPosition 0

m_dsBuffer(1).Stop

m_dsBuffer(1).SetCurrentPosition 0

End If

End Sub

Private Sub chTester1_Loop_Click()
If chTester1_Loop.Value = 0 Then

If m_dsBuffer(0) Is Nothing Then Exit Sub

m_dsBuffer(0).Stop

m_dsBuffer(0).SetCurrentPosition 0

End If

End Sub

Private Sub chTester2_Loop_Click()
If chTester2_Loop.Value = 0 Then

If m_dsBuffer(1) Is Nothing Then Exit Sub

m_dsBuffer(1).Stop

m_dsBuffer(1).SetCurrentPosition 0

End If

End Sub

'))))))))))))))))))))))))))(END LOOPING CODE)((((((((((((((((((((((((((((

')))))))))))))))))))))))))))))))(PAUSING CODE)(((((((((((((((((((((((((
'Again, i have grouped them together because they are almost

'identical. The buffer.STOP function pauses it. to stop it and put

'it back to the beggining you have to tell it to (See later on). If you tell it to stop

'next time the user clicks play, it'll resume from where it was........

Private Sub cmdBoth_Pause_Click()
If m_dsBuffer(0) Is Nothing And m_dsBuffer(1) Is Nothing Then Exit Sub

m_dsBuffer(0).Stop

m_dsBuffer(1).Stop

End Sub

Private Sub cmdTester1_Pause_Click()
If m_dsBuffer(0) Is Nothing Then Exit Sub

m_dsBuffer(0).Stop

End Sub

Private Sub cmdTester2_Pause_Click()
If m_dsBuffer(1) Is Nothing Then Exit Sub

m_dsBuffer(1).Stop

End Sub

')))))))))))))))))))))))))(END PAUSING CODE)((((((((((((((((((((((((((((((((

')))))))))))))))))))))))))))))))(STOPPING)((((((((((((((((((((((
'Yet again, i've grouped them together.

'All these subs do is stop the sound, then set it's position back to 0 (the beggining)

Private Sub cmdBoth_Stop_Click()
If m_dsBuffer(0) Is Nothing And m_dsBuffer(1) Is Nothing Then Exit Sub

m_dsBuffer(0).Stop

m_dsBuffer(0).SetCurrentPosition 0˙
'This line could be changed to make it start in˙
'the middle of a sound file

m_dsBuffer(1).Stop

m_dsBuffer(1).SetCurrentPosition 0

End Sub

Private Sub cmdTester1_Stop_Click()
If m_dsBuffer(0) Is Nothing Then Exit Sub

m_dsBuffer(0).Stop

m_dsBuffer(0).SetCurrentPosition 0

End Sub

Private Sub cmdTester2_Stop_Click()
If m_dsBuffer(1) Is Nothing Then Exit Sub

m_dsBuffer(1).Stop

m_dsBuffer(1).SetCurrentPosition 0

End Sub

'))))))))))))))))))))))))))))))))))))))))))))))))))(END STOPPING CODE)((((((((((((((((((((((((((((((


This is all of the linking code for now, there is more later on, but this will do for now. Remember, dont run the project, you'll get an error message if you click on anything.

˙



CREATING THE LOADING PROCEDURE [top]
The Next Step is getting it to load some data into the Buffer. This is going to be in the sub "LoadWave", which was mentioned in the Form_Load sub. Paste this code in to the sub:

Sub LoadWave()

˙˙˙ Dim bufferDesc As DSBUFFERDESC 'a new object that when filled in is passed to the DS object to describe
˙˙
˙ 'what sort of buffer to create, very similiar to DirectDraw's surface descriptions
˙˙˙ Dim waveFormat As WAVEFORMATEX

˙
˙˙ 'These settings should do for almost any app....
˙˙˙ bufferDesc.lFlags = DSBCAPS_CTRLFREQUENCY Or DSBCAPS_CTRLPAN Or DSBCAPS_CTRLVOLUME Or DSBCAPS_STATIC

˙˙˙ waveFormat.nFormatTag = WAVE_FORMAT_PCM
˙˙˙ waveFormat.nChannels = 2˙˙˙ '2 channels

˙˙˙ waveFormat.lSamplesPerSec = 22050
'22 hz (i think), only change this if you understand hertz etc.......
˙˙˙ waveFormat.nBitsPerSample = 16˙
'16 bit rather than 8 bit (Better Quality)
˙˙˙ waveFormat.nBlockAlign = waveFormat.nBitsPerSample / 8 * waveFormat.nChannels

˙˙˙ waveFormat.lAvgBytesPerSec = waveFormat.lSamplesPerSec * waveFormat.nBlockAlign

˙
˙˙ 'this next line creates a buffer with the specified file in it, 'BufferDesc' and 'waveformat'
˙˙˙ 'describe the properties of the new buffer. they can only be modified when creating a new buffer...

˙
˙˙ Dim sFile As String
˙˙˙ sFile = App.Path & "\tester1.wav"
'This file should be in your projects folder......
˙˙˙ Set m_dsBuffer(0) = m_ds.CreateSoundBufferFromFile(sFile, bufferDesc, waveFormat)

˙˙˙ sFile = App.Path & "\tester2.wav"

˙˙˙ Set m_dsBuffer(1) = m_ds.CreateSoundBufferFromFile(sFile, bufferDesc, waveFormat)

˙˙˙ 'checks for any errors

˙˙˙ If Err.Number <> 0 Then
'basically, generate an error message if the number is anything but 0(0=no error)
˙˙˙˙˙˙˙ MsgBox "unable to find " + sFile

˙˙˙˙˙˙˙ End

˙˙˙ End If

˙˙˙ 'check the panning and volume "properties"
˙˙˙ scrlTester1_Pan_Change
'instead of writing all the code out again, just call the
˙˙˙ scrlTester1_Vol_Change
'sub that it's in.........
˙˙˙ scrlTester2_Pan_Change

˙˙˙ scrlTester2_Vol_Change

End Sub


Note: If you get an error message, but you know that the files are there, it could be that they are in the wrong format. You cant tell the difference until you try to load them, but some .Wav files are PCM format (Which is what DirectSound wants) and others aren't. If this happens, select another sound file.

˙



MAKING IT PLAY SOMETHING [top]
Now we're going to get a response from our program. I am going to go over the code that goes into:

cmdBoth_Play
cmdTester1_Play
cmdTester2_Play

Open up the relevent windows, and paste in this code:

Private Sub cmdBoth_Play_Click()
Dim flag As Long

flag = 0
'Set the value to normal, then only change it if the checkBox is checked...
If chBoth_Loop.Value <> 0 Then flag = 1
'decide whether or not too loop the sound
m_dsBuffer(0).Play flag

m_dsBuffer(1).Play flag

'When you type out "m_dsbuffer(*).play" a menu will drop down with "DSBPLAY_NORMAL"˙

'and "DSBPLAY_LOOPING", The "flag variable is the same, 0 = normal, 1=looping.

End Sub

'These next 2 portions are almost identical....
Private Sub cmdTester1_Play_Click()

Dim flag As Long

flag = 0

If chTester1_Loop.Value <> 0 Then flag = 1

m_dsBuffer(0).Play flag

End Sub

Private Sub cmdTester2_Play_Click()
Dim flag As Long

flag = 0

If chTester2_Loop.Value <> 0 Then flag = 1˙

m_dsBuffer(1).Play flag

End Sub


Ok, so it's not really that complicated, but i thought i'd cover it in a seperate section.
The Next section is a bit more interesting.

˙



ADDING IN VOLUME AND PANNING [top]
The Volume is pretty simple, the panning is very useful. If you are making a platformer game, you can use this to make a sound come from the left or right of the player; adding a whole new dimension to the environment. It is also very very simple.
You should already have set up the individual ScrollBars and their properties, so open up the code window and enter this code:

Private Sub scrlTester1_Pan_Change()
If m_dsBuffer(0) Is Nothing Then Exit Sub
'This line stops it changing anything on
'a buffer if it's empty.

m_dsBuffer(0).SetPan scrlTester1_Pan.Value

End Sub

Private Sub scrlTester1_Vol_Change()
If m_dsBuffer(0) Is Nothing Then Exit Sub

m_dsBuffer(0).SetVolume scrlTester1_Vol.Value

End Sub

Private Sub scrlTester2_Pan_Change()
If m_dsBuffer(1) Is Nothing Then Exit Sub

m_dsBuffer(1).SetPan scrlTester2_Pan.Value

End Sub

Private Sub scrlTester2_Vol_Change()
If m_dsBuffer(1) Is Nothing Then Exit Sub

m_dsBuffer(1).SetVolume scrlTester2_Vol.Value

End Sub

All in all, extremely simple. BUT, you might have noticed the odd Maximum/minimum settings for the controls. This is the only thing that you have to watch out for,
Volume is -5000 (Mute) to 0 (Loudest). It is only a "percentage" of the volume set in control panel. If the Volume is set low there, no matter what you set the internal volume to be, it wont get any louder than this. Panning is -10,000(Full Left) to 0(Center) to 10,000(Full Right). Ok, that's it! Have fun.

OVERVIEW
Ok, so what have you just done?

You have made a program that stores a .Wav file in memory and the plays it back at a set volume and audio balance(Panning).

Things to remember:
Storing files in memory takes up RAM, which is ok if you only have 5-6 small sounds. If you are holding 10 or More Large sounds in memory, performance will be very sluggish. At some point i will post a tutorial on streaming, which loads a file as it plays it, instead of storing it in memory.

¸2000 Jack Hoxley -˙All rights reserved.

The material on this page may be reproduced as long as credit is˙given to myself "Jack˙Hoxley"

The author can be e-mailed at jollyjeffers@greenonions.netscapeonline.co.uk. His web site is http://members.dencity.com/dx4vb/

Sponsored Links

internet.commediabistro.comJusttechjobs.comGraphics.com

Search:

WebMediaBrands Corporate Info

Legal Notices, Licensing, Permissions, Privacy Policy.
Advertise | Newsletters | Shopping | E-mail Offers