Introduction
Managed DirectSound 9 is a part of Managed DirectX 9 library. In this tutorial I’m going to explain how to play sounds with Microsoft Managed DirectSound 9, how to apply effects, select the output audio device and a few more tricks. I hope you’ll discover that DirectSound is not as difficult as it seems.
Requirements
In order to develop and run applications using Managed DirectSound 9 (and all Managed DirectX 9), you have to install in your system the DirectX 9 standard redistributable package specifying in the command line the argument /InstallManagedDX (for example D:\Download\dxsetup /InstallManagedDX). You can also download from Microsoft’s website the package called the ‘DirectX 9.0c Redistributable for Software Developers - with updated DirectX for Managed Code and D3DX’, which includes and installs automatically the Managed DirectX libraries. Obviously, you have to add to your projects the references to Microsoft.DirectX
and Microsoft.DirectX.DirectSound
.
Here is an important note: in order to run the apps, the user is not forced to install the Managed DX9, but it is sufficient to copy in your apps’ root folder the referenced assemblies. To do this, set the LocalCopy
property of the assemblies to true
or copy them manually. I suggest the first way because if you create the Installer for the app with Visual Studio, it will detect the references and copy the assemblies to the installation destination. In the second way you have to remember to add them manually. To simplify your life, add these using
clauses to your source files:
using Microsoft.DirectX;
using Microsoft.DirectX.DirectSound;
First lines of code: play a Wave file
The first operation you have to do, is to create a DirectSound Device
:
private Device dSound;
After this, set it up:
dSound = new Device();
dSound.SetCooperartiveLevel(handle,
CooperativeLevel.Priority);
Notes: handle
is the handle to your main window (IntPtr
), so write this.Handle
. CooperativeLevel
sets the hardware managing of the playback. There are three possibilities, but you should use Priority
because it uses the hardware acceleration whenever possible. The Device
constructor is overloaded: we’ll see other options later on.
The next step is to create a sound
, using a Buffer, and its descriptor:
private SecondaryBuffer sound;
private BufferDescription d = new BufferDescription();
d.ControlPan = true;
d.ControlVolume = true;
d.ControlFrequency = true;
d.ControlEffects = true;
The flags are:
ControlPan
: allows you to control the balance (left/right) of the sound.
ControlVolume
: allows you to control the volume of the sound.
ControlFrequency
: allows you to control the sampling frequency of the sound (rarely used).
ControlEffects
: allows you to apply effects to the sound.
There are a few other flags, but we are not interested in them.
sound = new SecondaryBuffer(filePath, d, dSound);
filePath
is the full path of the .wav file, d
is the descriptor created above, and dSound
is the Device
that will play the sound
. After this, the sound
is ready to be played. As a first parameter you can also specify System.IO.Stream
, for example if you are receiving the sound from the Internet (in this case you must manage the difference between data consuming and receiving rates: think about your media player when it stops the playback to retrieve more data from the server).
The operations you can perform with a SecondaryBuffer
are:
Using speakers
Another amazing thing you can do, is to set the correct type of speakers attached to the output audio card. This option allows you to obtain better sound on each output system. The property you have to set is dSound.SpeakerConfig
:
Speakers s = new Speakers();
s.Mono = false;
s.Headphone = false;
s.Stereo = false;
s.Quad = false;
s.FiveDotOne = false;
s.SevenDotOne = true;
s.Surround = false;
dSound.SpeakerConfig = s;
Note: if you set the Speakers
creating a new Speakers
object every time, you can avoid resetting the old properties. So just replace the old Speakers
object.
Choosing between sound cards
In many systems there are more than one sound card. DirectSound 9 allows you to choose the correct one, arranging a way to select the default one, or to choose the card that the user wants. To enumerate and show the user the installed cards, do as follows (supposing that the list of sound cards is put into a ComboBox
, named cmbAudioCards
):
private DevicesCollection devList = new DevicesCollection();
cmbAudioCards.Items.Clear();
for(int i = 0; i < devList.Count; i++) {
cmbAudioCards.Items.Add(devList[i].Description);
}
The first element is the default audio card that is always listed. The other items are the ‘physical’ audio cards. For example you can see:
- Main Audio Driver
- Audio SB Live! [400]
- Bluetooth Audio
When the user selects a specific card, you can rebuild the Device as follows (in the ComboBox
event handler):
dSound = new Device(devList[cmbAudioCards.SelectedIndex].DriverGuid);
dSound.SetCooperativeLevel(this.Handle, CooperativeLevel.Priority);
sound = new SecondaryBuffer(filePath, d, dSound);
DriverGuid
is the Global Unique Identifier of the driver instance for the selected audio card. At the first start, or if the user doesn’t select a specific audio card, you can use the default constructor of Device
, or select via-code the first element in devList
, that is the default audio card.
Selecting different audio cards can effect the system performance: in the example above, the SoundBlaster Live! has in-hardware acceleration capabilities and supports upto 5.1 systems. Bluetooth audio is worst, and can cause a CPU load increment while applying effects or when managing 3D audio.
Applying effects to the audio playback
One of the most important features of DirectSound 9 is the possibility to apply real-time audio effects to the sounds in playback. You can also apply a virtually unlimited chain of effects (according to the system capabilities). All the effects are applied in-hardware whenever possible, otherwise emulated via-software (causing an important drop in the performance!). Remember to set the flag sound.ControlEffects
to true
!
In DirectSound 9 there are – needless to say :) – 9 effects: Chorus, Compressor, Distortion, Echo, Flanger, Gargle, Interactive3DLevel2Reverb, ParamEqualizer, WavesReverb. I want to say that there is not much documentation about these effects, especially because each of them has different settings. The first thing is to create an array of EffectDescription
:
EffectDescription[] fx = new EffectDescription[1];
In this example we use only one effect, but if you want, you can use more effects by creating an array long enough, and inserting one effect per element. Suppose you want to apply the Echo effect:
fx[0].GuidEffectClass = DSoundHelper.StandardEchoGuid;
sound.SetEffects(fx);
Suppose now you want to apply the Parametric Equalizer effect:
fx[0].GuidEffectClass = DSoundHelper.StandardParamEqGuid;
sound.SetEffects(fx);
Note: you can apply effects only when the sound is not played. As I reported above, each effect has different options. I will explain here how to set up the Parametric Equalizer effect:
fx[0].GuidEffectClass = DSoundHelper.StandardParamEqGuid;
sound.SetEffects(fx);
ParamEqEffect eqEffect = (ParamEqEffect)sound.GetEffects(0);
EffectsParamEq eqParams = eqEffect.AllParameters;
eqParams.Bandwidth = 36;
eqParams.Gain = ParamEqEffect.GainMax;
eqEffect.AllParameters = eqParams;
Abstracting the procedure, you have to first create an array of effects with StandardEFFECTNAMEGuid
, then set the parameters, using EFFECTNAMEEffect
and EffectsEFFECTNAME
objects, where EFFECTNAME is the name of the Effect. Always remember to perform the correct casts. To reset the effects on a sound, you have to overwrite it:
sound = new SecondaryBuffer(filePath, d, dSound);
For further info about the effects, please go through the MSDN Library.
Conclusions
By now you should have developed a little familiarity with a DirectSound device, the Effects and other options. DirectSound fits to playbacks of short sounds, such as explosions, shots and so on. If you want to play a long Wave sound you should use the namespace Microsoft.DirectX.AudioVideoPlayback
, that I will explain in future. In the next tutorial I will explain how to use 3D Sounds with DirectSound.