Writing a Square Wave to DirectSound
?
?

Keyboard Navigation

Global Keys

[, < / ], > Jump to previous / next episode
W, K, P / S, J, N Jump to previous / next marker
t / T Toggle theatre / SUPERtheatre mode
V Revert filter to original state Y Select link (requires manual Ctrl-c)

Menu toggling

q Quotes r References f Filter y Link c Credits

In-Menu Movement

a
w
s
d
h j k l


Quotes and References Menus

Enter Jump to timecode

Quotes, References and Credits Menus

o Open URL (in new tab)

Filter Menu

x, Space Toggle category and focus next
X, ShiftSpace Toggle category and focus previous
v Invert topics / media as per focus

Filter and Link Menus

z Toggle filter / linking mode

Credits Menu

Enter Open URL (in new tab)
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
17:02Locking the buffer
17:02Locking the buffer
17:02Locking the buffer
18:19Dealing with buffer pointers and locks
18:19Dealing with buffer pointers and locks
18:19Dealing with buffer pointers and locks
21:09The Lock() call
21:09The Lock() call
21:09The Lock() call
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
51:39Review the code
51:39Review the code
51:39Review the code
56:04Start DirectSound playing
56:04Start DirectSound playing
56:04Start DirectSound playing
57:27HOLD YOUR EARS
57:27HOLD YOUR EARS
57:27HOLD YOUR EARS
58:22HOLD YOUR EARS
58:22HOLD YOUR EARS
58:22HOLD YOUR EARS
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:00:58Final Thoughts
1:00:58Final Thoughts
1:00:58Final Thoughts
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:10:30Q&A
🗩
1:10:30Q&A
🗩
1:10:30Q&A
🗩
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:11:21Why not XAudio2?
1:11:21Why not XAudio2?
1:11:21Why not XAudio2?
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?
1:29:04No Poop Sauce
1:29:04No Poop Sauce
1:29:04No Poop Sauce

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:

  1. Load the Library - LoadLibrary("dsound.dll")
  2. Create a DirectSound object - DirectSoundCreate()
  3. Set the Cooperative Level - IDirectSound8::SetCooperativeLevel()
  4. "Create" a primary buffer - IDirectSound8::CreateSoundBuffer()
  5. Create a secondary buffer
  6. 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

  1. Figure out where in the buffer you want to start writing, and how much data you want to write
  2. 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
  3. Write the samples to the buffer
  4. 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.