60 lines
4.7 KiB
HTML
60 lines
4.7 KiB
HTML
<html>
|
|
<head>
|
|
<!-- __CINERA_INCLUDES__ -->
|
|
</head>
|
|
<body>
|
|
<div id="cinera">
|
|
<!-- __CINERA_MENUS__ -->
|
|
<!-- __CINERA_PLAYER__ -->
|
|
|
|
<article id="video-notes">
|
|
<h1><!-- __CINERA_TITLE__ --></h1>
|
|
<h3 id="directsound-is-object-oriented">DirectSound is Object Oriented</h3>
|
|
<p>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.</p>
|
|
<h3 id="reviewing-directsound-inititalization">Reviewing DirectSound Inititalization</h3>
|
|
<p>The basic process for initializing DirectSound is as follows:</p>
|
|
<ol>
|
|
<li>Load the Library - <a href="http://msdn.microsoft.com/en-us/library/ms684175.aspx"><code>LoadLibrary</code></a><code>("dsound.dll")</code></li>
|
|
<li>Create a DirectSound object - <a href="http://msdn.microsoft.com/en-us/library/microsoft.directx_sdk.reference.directsoundcreate8.aspx"><code>DirectSoundCreate()</code></a></li>
|
|
<li>Set the Cooperative Level - <a href="http://msdn.microsoft.com/en-us/library/microsoft.directx_sdk.idirectsound8.idirectsound8.setcooperativelevel.aspx"><code>IDirectSound8::SetCooperativeLevel()</code></a></li>
|
|
<li>"Create" a primary buffer - <a href="http://msdn.microsoft.com/en-us/library/microsoft.directx_sdk.idirectsound8.idirectsound8.createsoundbuffer.aspx"><code>IDirectSound8::CreateSoundBuffer()</code></a></li>
|
|
<li>Create a secondary buffer</li>
|
|
<li>Tell DirectSound to start playing the secondary buffer - <a href="http://msdn.microsoft.com/en-us/library/microsoft.directx_sdk.idirectsoundbuffer8.idirectsoundbuffer8.play.aspx"><code>IDirectSoundBuffer8::Play()</code></a></li>
|
|
</ol>
|
|
<h3 id="playing-sounds">Playing sounds</h3>
|
|
<p>Audio is a complicated topic, and we start with a discussion of audio "waveforms" and how PCM audio data is encoded in
|
|
memory.</p>
|
|
<ul>
|
|
<li>A square wave oscillates between "full-positive" to "full-negative" every half period</li>
|
|
<li>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</li>
|
|
<li>A "sample" sometimes refers to the values for all channels in a sampling period, and sometimes a value for a single
|
|
channel. Be careful.</li>
|
|
</ul>
|
|
<p>The procedure for writing sound data into a buffer is as follows</p>
|
|
<ol>
|
|
<li>Figure out where in the buffer you want to start writing, and how much data you want to write
|
|
<ul>
|
|
<li>Its useful to look at the play cursor - <a href="http://msdn.microsoft.com/en-us/library/microsoft.directx_sdk.idirectsoundbuffer8.idirectsoundbuffer8.getcurrentposition.aspx"><code>IDirectSoundBuffer8::GetCurrentPosition()</code></a></li>
|
|
</ul>
|
|
</li>
|
|
<li>Acquire a lock on the buffer - <a href="http://msdn.microsoft.com/en-us/library/microsoft.directx_sdk.idirectsoundbuffer8.idirectsoundbuffer8.unlock.aspx"><code>IDirectSoundBuffer8::Lock()</code></a>
|
|
<ul>
|
|
<li>Because we are working with a circular buffer, this call will return 1 or 2 writable regions</li>
|
|
</ul>
|
|
</li>
|
|
<li>Write the samples to the buffer</li>
|
|
<li>Unlock the regions - <a href="http://msdn.microsoft.com/en-us/library/microsoft.directx_sdk.idirectsoundbuffer8.idirectsoundbuffer8.unlock.aspx"><code>IDirectSoundBuffer8::Unlock()</code></a></li>
|
|
</ol>
|
|
<h3 id="a-note-on-audio-latency">A note on audio latency</h3>
|
|
<p>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.</p>
|
|
</article>
|
|
</div>
|
|
<!-- __CINERA_SCRIPT__ -->
|
|
</body>
|
|
</html>
|