⏫
Previous: 'Initializing DirectSound'
⏫
1:04Review of DirectSound init
1:04Review of DirectSound init
1:04Review of DirectSound init
2:16Tangent: methods and vtables
2:16Tangent: methods and vtables
2:16Tangent: methods and vtables
8:52Resume review of DirectSound init
8:52Resume review of DirectSound init
8:52Resume review of DirectSound init
14:21Writing to the sound buffer
14:21Writing to the sound buffer
14:21Writing to the sound buffer
16:09Discussion of waveforms for testing
16:09Discussion of waveforms for testing
16:09Discussion of waveforms for testing
18:19Dealing with buffer pointers and locks
18:19Dealing with buffer pointers and locks
18:19Dealing with buffer pointers and locks
22:59Filling the buffer regions
22:59Filling the buffer regions
22:59Filling the buffer regions
26:49Generating a test tone
26:49Generating a test tone
26:49Generating a test tone
35:28Getting the WritePointer and BytesToWrite
35:28Getting the WritePointer and BytesToWrite
35:28Getting the WritePointer and BytesToWrite
48:21Refine square wave formula
48:21Refine square wave formula
48:21Refine square wave formula
56:04Start DirectSound playing
56:04Start DirectSound playing
56:04Start DirectSound playing
59:22Don't forget to Unlock the buffer
59:22Don't forget to Unlock the buffer
59:22Don't forget to Unlock the buffer
1:02:17Review of mod operation and how we used it
1:02:17Review of mod operation and how we used it
1:02:17Review of mod operation and how we used it
1:11:09Will future broacasts use this Europe-friendly time?
1:11:09Will future broacasts use this Europe-friendly time?
1:11:09Will future broacasts use this Europe-friendly time?
1:12:43Are we going to factor sound playing to a seperate function?
1:12:43Are we going to factor sound playing to a seperate function?
1:12:43Are we going to factor sound playing to a seperate function?
1:13:45Will we rename GlobalSecondaryBuffer?
1:13:45Will we rename GlobalSecondaryBuffer?
1:13:45Will we rename GlobalSecondaryBuffer?
1:14:10Challenge: XAudio2 is supported on XP
1:14:10Challenge: XAudio2 is supported on XP
1:14:10Challenge: XAudio2 is supported on XP
1:14:49Why keyboard events instead of polling?
1:14:49Why keyboard events instead of polling?
1:14:49Why keyboard events instead of polling?
1:15:24Will we be able to remap keys?
1:15:24Will we be able to remap keys?
1:15:24Will we be able to remap keys?
1:15:43Doesn't the size of the buffer increase latency?
1:15:43Doesn't the size of the buffer increase latency?
1:15:43Doesn't the size of the buffer increase latency?
1:16:53Will we write audio filters, like reverb?
1:16:53Will we write audio filters, like reverb?
1:16:53Will we write audio filters, like reverb?
1:17:16Will we factor the code into seperate files?
1:17:16Will we factor the code into seperate files?
1:17:16Will we factor the code into seperate files?
1:18:06It takes about a second to start playing, is that expected?
1:18:06It takes about a second to start playing, is that expected?
1:18:06It takes about a second to start playing, is that expected?
1:22:39Can you show a sine wave as well?
1:22:39Can you show a sine wave as well?
1:22:39Can you show a sine wave as well?
1:23:02What is acceptable latency?
1:23:02What is acceptable latency?
1:23:02What is acceptable latency?
⏬
Next: 'Variable-Pitch Sine Wave Output'
⏬
Writing a Square Wave to DirectSound
DirectSound is Object Oriented
DirectSound in an object-oriented API. What does that mean? Casey starts this episode with a discussion of "method"
dispatch through vtables, and why c++ virtual calls are costly.
Reviewing DirectSound Inititalization
The basic process for initializing DirectSound is as follows:
- Load the Library -
LoadLibrary
("dsound.dll")
- Create a DirectSound object -
DirectSoundCreate()
- Set the Cooperative Level -
IDirectSound8::SetCooperativeLevel()
- "Create" a primary buffer -
IDirectSound8::CreateSoundBuffer()
- Create a secondary buffer
- Tell DirectSound to start playing the secondary buffer -
IDirectSoundBuffer8::Play()
Playing sounds
Audio is a complicated topic, and we start with a discussion of audio "waveforms" and how PCM audio data is encoded in
memory.
- A square wave oscillates between "full-positive" to "full-negative" every half period
- A Stereo (2-channel) 16-bit PCM audio buffer is arranged as an array of signed int16 values in (left channel value,
right channel value) pairs
- A "sample" sometimes refers to the values for all channels in a sampling period, and sometimes a value for a single
channel. Be careful.
The procedure for writing sound data into a buffer is as follows
- Figure out where in the buffer you want to start writing, and how much data you want to write
- Acquire a lock on the buffer -
IDirectSoundBuffer8::Lock()
- Because we are working with a circular buffer, this call will return 1 or 2 writable regions
- Write the samples to the buffer
- Unlock the regions -
IDirectSoundBuffer8::Unlock()
A note on audio latency
Audio latency is determined not by the size of the buffer, but by how far ahead of the PlayCursor you write. The optimal
amount of latency is the amount that will cause this frame's audio to coincide with the display of this frame's image.
On most platforms, it is very difficult to ascertain the proper amount of latency. It's an unsolved problem, and games
with need precise AV sync (like Guitar Hero) go to some lengths to achieve it.