# DirectX/10.0/Direct3D/Direct Sound

This tutorial will cover the basics of using Direct Sound in DirectX 11 as well as how to load and play .wav audio files. This tutorial is based on the code in the previous DirectX 11 tutorials. I will cover a couple basics about Direct Sound in DirectX 11 as well as a bit about sound formats before we start the code part of the tutorial.
The first thing you will notice is that in DirectX 11 the Direct Sound API is still the same one from DirectX 8. The only major difference is that hardware sound mixing is generally not available on the latest Windows operating systems. The reason being is for security and operating system consistency all hardware calls now have to go through a security layer. The older sound cards used to have DMA (direct memory access) which was very fast but doesn't work with this new Windows security model. So all sound mixing is now done at the software level and hence no hardware acceleration is directly available to this API.
The nice thing about Direct Sound is that you can play any audio format you want. In this tutorial I cover the .wav audio format but you can replace the .wav code with .mp3 or anything you prefer. You can even use your own audio format if you have created one. Direct Sound is so easy to use you just create a sound buffer with the play back format you would like and then copy your audio format into the buffer's format and then it is ready to play. You can see why so many applications use Direct Sound due to its pure simplicity.
Note that Direct Sound does use two different kinds of buffers which are primary and secondary buffers. The primary buffer is the main sound memory buffer on your default sound card, USB headset, and so forth. Secondary buffers are buffers you create in memory and load your sounds into. When you play a secondary buffer the Direct Sound API takes care of mixing that sound into the primary buffer which then plays the sound. If you play multiple secondary buffers at the same time it will mix them together and play them in the primary buffer. Also note that all buffers are circular so you can set them to repeat indefinitely.
To start the tutorial we will first look at the updated frame work. The only new class is the SoundClass which contains all the DirectSound and .wav format functionality. I have removed the other classes to simplify this tutorial.

## Soundclass.h

The SoundClass encapsulates the DirectSound functionality as well as the .wav audio loading and playing capabilities.
The following libraries and headers are required for DirectSound to compile properly.
The WaveHeaderType structure used here is for the .wav file format. When loading in .wav files I first read in the header to determine the required information for loading in the .wav audio data. If you are using a different format you will want to replace this header with the one required for your audio format.
Initialize and Shutdown will handle everything needed for this tutorial. The Initialize function will initialize DirectSound and load in the .wav audio file and then play it once. Shutdown will release the .wav file and shutdown DirectSound.
Note that I only have one secondary buffer as this tutorial only loads in one sound.

## Soundclass.cpp

Use the class constructor to initialize the private member variables that are used inside the sound class.
First initialize the DirectSound API as well as the primary buffer. Once that is initialized then the LoadWaveFile function can be called which will load in the .wav audio file and initialize the secondary buffer with the audio information from the .wav file. After loading is complete then PlayWaveFile is called which then plays the .wav file once.
The Shutdown function first releases the secondary buffer which held the .wav file audio data using the ShutdownWaveFile function. Once that completes this function then called ShutdownDirectSound which releases the primary buffer and the DirectSound interface.
InitializeDirectSound handles getting an interface pointer to DirectSound and the default primary sound buffer. Note that you can query the system for all the sound devices and then grab the pointer to the primary sound buffer for a specific device, however I've kept this tutorial simple and just grabbed the pointer to the primary buffer of the default sound device.
We have to setup the description of how we want to access the primary buffer. The dwFlags are the important part of this structure. In this case we just want to setup a primary buffer description with the capability of adjusting its volume. There are other capabilities you can grab but we are keeping it simple for now.
Now that we have control of the primary buffer on the default sound device we want to change its format to our desired audio file format. Here I have decided we want high quality sound so we will set it to uncompressed CD audio quality.
The ShutdownDirectSound function handles releasing the primary buffer and DirectSound interfaces.
The LoadWaveFile function is what handles loading in a .wav audio file and then copies the data onto a new secondary buffer. If you are looking to do different formats you would replace this function or write a similar one.
To start first open the .wav file and read in the header of the file. The header will contain all the information about the audio file so we can use that to create a secondary buffer to accommodate the audio data. The audio file header also tells us where the data begins and how big it is. You will notice I check for all the needed tags to ensure the audio file is not corrupt and is the proper wave file format containing RIFF, WAVE, fmt, data, and WAVE_FORMAT_PCM tags. I also do a couple other checks to ensure it is a 44.1KHz stereo 16bit audio file. If it is mono, 22.1 KHZ, 8bit, or anything else then it will fail ensuring we are only loading the exact format we want.
Now that the wave header file has been verified we can setup the secondary buffer we will load the audio data onto. We have to first set the wave format and buffer description of the secondary buffer similar to how we did for the primary buffer. There are some changes though since this is secondary and not primary in terms of the dwFlags and dwBufferBytes.
Now the way to create a secondary buffer is fairly strange. First step is that you create a temporary IDirectSoundBuffer with the sound buffer description you setup for the secondary buffer. If this succeeds then you can use that temporary buffer to create a IDirectSoundBuffer8 secondary buffer by calling QueryInterface with the IID_IDirectSoundBuffer8 parameter. If this succeeds then you can release the temporary buffer and the secondary buffer is ready for use.
Now that the secondary buffer is ready we can load in the wave data from the audio file. First I load it into a memory buffer so I can check and modify the data if I need to. Once the data is in memory you then lock the secondary buffer, copy the data to it using a memcpy, and then unlock it. This secondary buffer is now ready for use. Note that locking the secondary buffer can actually take in two pointers and two positions to write to. This is because it is a circular buffer and if you start by writing to the middle of it you will need the size of the buffer from that point so that you don't write outside the bounds of it. This is useful for streaming audio and such. In this tutorial we create a buffer that is the same size as the audio file and write from the beginning to make things simple.
ShutdownWaveFile just does a release of the secondary buffer.
The PlayWaveFile function will play the audio file stored in the secondary buffer. The moment you use the Play function it will automatically mix the audio into the primary buffer and start it playing if it wasn't already. Also note that we set the position to start playing at the beginning of the secondary sound buffer otherwise it will continue from where it last stopped playing. And since we set the capabilities of the buffer to allow us to control the sound we set the volume to maximum here.

## Systemclass.h

Here we include the new SoundClass header file.
We create a new private variable for the SoundClass object.

## Systemclass.cpp

I will just cover the functions that have changed since the previous tutorial.
Initialize the new SoundClass object to null in the class constructor.
Here is where we create the SoundClass object and then initialize it for use. Note that in this tutorial the initialization will also start the wave file playing.
In the SystemClass::Shutdown we also shutdown the SoundClass object and release it.

## Summary

The engine now supports the basics of Direct Sound. It currently just plays a single wave file once you start the program.

## To Do Exercises

1. Recompile the program and ensure it plays the wave file in stereo sound. Press escape to close the window after.
2. Replace the sound01.wav file with your own 44.1KHz 16bit 2channel audio wave file and run the program again.
3. Rewrite the program to load two wave files and play them simultaneously.
4. Change the wave to loop instead of playing just once.