<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" media="screen" href="/styles/xslt/rss.xslt"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:media="http://search.yahoo.com/mrss/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:c9="http://channel9.msdn.com">
<channel>
	<title>Channel 9</title>
    <atom:link rel="self" type="application/rss+xml" href="http://channel9.msdn.com/(A(cSFyXJXzzAEkAAAANzEyZjRjOTAtYTMyMC00ZGEwLTliYjItOTg2NTIwMzI2MjVjgc-VZjdKOTJIVbCoVXIqp0D5hoQ1))/Niners/c4f.Dan-Waters/Posts/RSS"></atom:link>
    <itunes:summary></itunes:summary>
    <itunes:author>Microsoft</itunes:author>
    <itunes:subtitle></itunes:subtitle>
    <image>
      <url>http://mschnlnine.vo.llnwd.net/d1/Dev/App_Themes/C9/images/feedimage.png</url>
      <title>Channel 9</title>
      <link>http://channel9.msdn.com/(A(cSFyXJXzzAEkAAAANzEyZjRjOTAtYTMyMC00ZGEwLTliYjItOTg2NTIwMzI2MjVjgc-VZjdKOTJIVbCoVXIqp0D5hoQ1))/Niners/c4f.Dan-Waters/Posts</link>
    </image>
    <itunes:image href=""></itunes:image>
    <itunes:category text="Technology"></itunes:category>
    <description>Channel 9 keeps you up to date with the latest news and behind the scenes info from Microsoft that developers love to keep up with. From LINQ to SilverLight – Watch videos and hear about all the cool technologies coming and the people behind them.</description>
    <link>http://channel9.msdn.com/(A(cSFyXJXzzAEkAAAANzEyZjRjOTAtYTMyMC00ZGEwLTliYjItOTg2NTIwMzI2MjVjgc-VZjdKOTJIVbCoVXIqp0D5hoQ1))/Niners/c4f.Dan-Waters/Posts</link>
    <language>en</language>
    <pubDate>Thu, 23 May 2013 13:46:00 GMT</pubDate>
    <lastBuildDate>Thu, 23 May 2013 13:46:00 GMT</lastBuildDate>
    <generator>Rev9</generator>
    <c9:totalResults>2</c9:totalResults>
    <c9:pageCount>1</c9:pageCount>
    <c9:pageSize>25</c9:pageSize>
  <item>
      <title>Generating Sound Waves with C# Wave Oscillators</title>
      <description><![CDATA[
<p>For the longest time, I've been baffled by the concept of sound in computing. How in the world is sound store? How is it played back? In classic Coding4Fun style, we'll learn by doing in this article—by building a wave oscillator application.
</p>
<h3>Optional Reading</h3>
<p>I cover the basics of this article in a multi-part blog series, which you should check out if you have trouble:</p>
<p><a href="http://blogs.msdn.com/dawate/archive/2009/06/22/intro-to-audio-programming-part-1-how-audio-data-is-represented.aspx">Part 1 - How Audio Data is Represented</a>
<br>
<a href="http://blogs.msdn.com/dawate/archive/2009/06/23/intro-to-audio-programming-part-2-demystifying-the-wav-format.aspx">Part 2 - Demystifying the WAV Format</a>
<br>
<a href="http://blogs.msdn.com/dawate/archive/2009/06/24/intro-to-audio-programming-part-3-synthesizing-simple-wave-audio-using-c.aspx">Part 3 - Synthesizing Simple WAV Audio Using C#</a>
<br>
<a href="http://blogs.msdn.com/dawate/archive/2009/06/25/intro-to-audio-programming-part-4-algorithms-for-different-sound-waves-in-c.aspx">Part 4 - Algorithms for Different Sound Waves in C#</a></p>
<h3>What's An Oscillator?</h3>
<p>An oscillator is a device or application that generates a waveform. In electrical engineering terms, it's a device that outputs an electrical current with varying voltage. If you plot the voltage over time, you get a regular wave in a particular form, such
 as a sine, square, triangle or sawtooth.</p>
<p>An oscillator is the most basic type of synthesizer. Analog synths use electrical circuits to output a sound wave. Digital synthesizers do the same thing, but with software.</p>
<p>You can create a pretty neat sounding instrument by combining the outputs of multiple oscillators. For example, if you have three oscillators oscillating at a frequency of 440Hz (concert A pitch), but each of them has a different waveform (saw, square, sine)
 you get a very interesting, layered sound. </p>
<p>But before we get too deep into this subject, let's briefly explore the physics of sound.</p>
<h3>The Physics of Sound</h3>
<p>Sound happens when air pressure changes on your ear drum. When you clap in an empty room, pressure waves bounce all over the place and dance on your eardrum. The changes in pressure are detected continuously by your ear.
</p>
<p>Digitally, “pressure” is referred to by a scalar value called <i>amplitude. </i>
The amplitude (loudness) of the wave is measured thousands of times per second (44,100 times per second on CDs). Every measurement of pressure (aka
<i>amplitude</i>) is called a <i>sample</i>—CDs are recorded with 44,100 <i>samples</i> per second, each with a value between the minimum and maximum amplitude for the bit depth.
</p>
<p>Think about 44,100 samples per second. That's a <i>lot</i> of stuff for your ear to detect. That's how we're able to hear so much stuff going on in the mix of a song, especially in stereo tracks where you have 44,100 samples per second, per ear.
</p>
<p>It turns out that there is a <a href="http://en.wikipedia.org/wiki/Nyquist-Shannon_sampling_theorem">
horribly intense mathematical theorem</a> which basically tells us that 44,100 samples per second is enough to accurately represent a pitch as high as 22 KHz. The human ear can really hear only up to 20KHz, so a 44.1KHz sampling rate is a more than high-enough
 sampling rate. </p>
<p>This whole section is expanded in detail on my blog:</p>
<p><a href="http://blogs.msdn.com/dawate/archive/2009/06/22/intro-to-audio-programming-part-1-how-audio-data-is-represented.aspx">Part 1 - How Audio Data is Represented</a></p>
<h3>Terminology</h3>
<p>So now you have a rather glancing overview of how sound works, and perhaps some clues as to how we should go about representing it in computers. Let's go over all this new terminology (plus some even newer terms) in delicious, bulleted format:</p>
<p>· <b>Sample: </b>A measurement of a sound wave at a very small point in time. 44,100 of these measurements in a row form a single channel of CD-quality audio.</p>
<p>· <b>Amplitude: </b>The value of a sample. Max and min values are dependent upon the bit depth.</p>
<p>· <b>Bit depth: </b>The number of bits used to represent a sample. 16-bit, 32-bit, etc. Max amplitude is (2^depth) / 2 – 1.</p>
<p>· <b>Sample rate (aka sampling rate, aka bit rate): </b>The number of samples per second of audio. 44,100 is standard for CD-quality audio.</p>
<h3>How sound is represented</h3>
<p>By now, you've probably surmised that a second of audio data is somehow represented by an array of some integer data type, which has a length of 44,100. You would be correct in that assumption. However, if you want sound to play from a computer's sound card,
 that data has to be accompanied with a bunch of format information. WAV is probably the easiest format to deal with.
</p>
<p>See more in the following article:</p>
<p><a href="http://blogs.msdn.com/dawate/archive/2009/06/23/intro-to-audio-programming-part-2-demystifying-the-wav-format.aspx">Part 2 - Demystifying the WAV Format</a></p>
<p>You can also see how to build out a WAV file, old school and binary style, in the 3<sup>rd</sup> part of that series:</p>
<p><a href="http://blogs.msdn.com/dawate/archive/2009/06/24/intro-to-audio-programming-part-3-synthesizing-simple-wave-audio-using-c.aspx">Part 3 - Synthesizing Simple WAV Audio Using C#</a></p>
<p>However, we are taking a slightly easier route, by using DirectSound. DirectSound gives us a lot of nice classes for all the format information, abstracting all that stuff away and allowing us to pump a stream of data into a DirectSound object and play it.
 Perfect for a synthesizer app!</p>
<p>So, let's get started!</p>
<h3>Building the app</h3>
<p>I learned some Blend while working with this app, since it's built on WPF. The image buttons are just radio buttons. I had to differentiate the group number per instance of the user control at runtime (in the constructor of the Oscillator class).</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10006604/image_2.png"><img title="image" border="0" alt="image" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10006604/image_thumb.png" width="379" height="442"></a>
</p>
<p>I'm a terrible UI designer for the most part, so this is about as sexy as I'm willing to make this application. But feel free to make it look and act better!</p>
<h4>Designing the UI</h4>
<p>There's a dirty little secret in this application. It says it can oscillate 3 waves, but in truth, there's a constant (set to 3) that you can modify. You could have six if you wanted. How did I accomplish this? Each synth that you see is an instance of a
 WPF user control called Oscillator.xaml:</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10006604/image_4.png"><img title="image" border="0" alt="image" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10006604/image_thumb_1.png" width="380" height="102"></a>
</p>
<p>I have a StackPanel called Oscs in the main window. In the Window_Loaded event handler of the main window, I use this bit of code to add instances of the usercontrol:</p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode"><span class="rem">// Add 3 oscillators</span>
Oscillator tmp;
<span class="kwrd">for</span> (<span class="kwrd">int</span> i = 0; i &lt; NUM_GENERATORS; i&#43;&#43;)
{
    tmp = <span class="kwrd">new</span> Oscillator();
    Oscs.Children.Add(tmp);
    mixer.Oscillators.Add(tmp);
}</pre>
<style type="text/css">
<!--
.csharpcode, .csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{background-color:#f4f4f4;
	width:100%;
	margin:0em}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p><b>VB <br>
</b></p>
<pre class="csharpcode"><span class="rem">' Add 3 oscillators</span>
<span class="kwrd">Dim</span> tmp <span class="kwrd">As</span> Oscillator
<span class="kwrd">Dim</span> i <span class="kwrd">As</span> <span class="kwrd">Integer</span> = 0
<span class="kwrd">While</span> i &lt; NUM_GENERATORS
    tmp = <span class="kwrd">New</span> Oscillator()
    Oscs.Children.Add(tmp)
    mixer.Oscillators.Add(tmp)
    System.Math.Max(System.Threading.Interlocked.Increment(i),i - 1)
<span class="kwrd">End</span> While</pre>
<p></p>
<p>The long rectangular canvas is used to plot the values of the generated wave, so you can visualize the wave as it's played. It is scaled along the X axis so you can see the general shape of the wave, which would be impossible without scaling it with 44,100
 samples per second.</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10006604/image_6.png"><img title="image" border="0" alt="image" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10006604/image_thumb_2.png" width="376" height="441"></a>
</p>
<p>Earlier in the article, I noted that a sound file is basically a <i>really, really long array</i> of 16- or 32-bit floating point numbers between -1 and 1. We use this data to plot the graph as well. More on that later.</p>
<p>Now that we have the UI figured out (dynamic addition of oscillators), let's take a look at exactly how the sound is produced.
</p>
<h3>Bzzzzt! Making Sounds and the Mixer</h3>
<p>One of the many cool things about DirectSound is that it basically wraps the WAV format for you. You set the buffering/format options and then shove a bunch of data into it, and it will play. Magic.</p>
<p>The way I've architected the solution is a little more modular. None of the oscillators has the ability to play itself—rather, uses its UI to control some values such as frequency, amplitude and wave type. These values are tied to public properties. The
 Oscillator component does virtually no audio work at all. </p>
<p>The generation of audio data is handled by the custom Mixer class, which takes a collection of Oscillators and, based on their properties, creates a composite of all the generators. This is done by averaging the samples in every oscillator and putting them
 into a new array of data.</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10006604/image_8.png"><img title="image" border="0" alt="image" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10006604/image_thumb_3.png" width="345" height="189"></a>
</p>
<p>The <b>Mixer</b> class looks like this:</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10006604/image_10.png"><img title="image" border="0" alt="image" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10006604/image_thumb_4.png" width="343" height="372"></a>
</p>
<p>One of the workhorses of the Mixer class is the method <b>GenerateOscillatorSampleData</b>. This takes an Oscillator as an argument to give access to the public properties set in the UI. From there, the algorithm generates 1 second of sample data (specified
 by the member <b>bufferDurationSeconds</b>) based on the wave type that has been selected in the UI. This is where the mathy stuff comes in to play. Check out this method and the different cases in the switch statement that determine what kind of wave to create
 below.</p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">short</span>[] GenerateOscillatorSampleData(Oscillator osc)
{
    <span class="rem">// Creates a looping buffer based on the params given</span>
    <span class="rem">// Fill the buffer with whatever waveform at the specified frequency            </span>
    <span class="kwrd">int</span> numSamples = Convert.ToInt32(bufferDurationSeconds * 
        waveFormat.SamplesPerSecond);
    <span class="kwrd">short</span>[] sampleData = <span class="kwrd">new</span> <span class="kwrd">short</span>[numSamples];
    <span class="kwrd">double</span> frequency = osc.Frequency;
    <span class="kwrd">int</span> amplitude = osc.Amplitude;
    <span class="kwrd">double</span> angle = (Math.PI * 2 * frequency) / 
        (waveFormat.SamplesPerSecond * waveFormat.Channels);            

    <span class="kwrd">switch</span> (osc.WaveType)
    {
        <span class="kwrd">case</span> WaveType.Sine:
            {
                <span class="kwrd">for</span> (<span class="kwrd">int</span> i = 0; i &lt; numSamples; i&#43;&#43;)
                    <span class="rem">// Generate a sine wave in both channels.</span>
                    sampleData[i] = Convert.ToInt16(amplitude * 
        Math.Sin(angle * i));
            }
            <span class="kwrd">break</span>;
        <span class="kwrd">case</span> WaveType.Square:
            {
                <span class="kwrd">for</span> (<span class="kwrd">int</span> i = 0; i &lt; numSamples; i&#43;&#43;)
                {
                    <span class="rem">// Generate a square wave in both channels.</span>
                    <span class="kwrd">if</span> (Math.Sin(angle * i) &gt; 0)
                        sampleData[i] = Convert.ToInt16(amplitude);
                    <span class="kwrd">else</span>
                        sampleData[i] = Convert.ToInt16(-amplitude);
                }
            }
            <span class="kwrd">break</span>;
        <span class="kwrd">case</span> WaveType.Sawtooth:
            {
                <span class="kwrd">int</span> samplesPerPeriod = Convert.ToInt32(
        waveFormat.SamplesPerSecond / 
        (frequency / waveFormat.Channels));
                <span class="kwrd">short</span> sampleStep = Convert.ToInt16(
        (amplitude * 2) / samplesPerPeriod);
                <span class="kwrd">short</span> tempSample = 0;

                <span class="kwrd">int</span> i = 0;
                <span class="kwrd">int</span> totalSamplesWritten = 0;
                <span class="kwrd">while</span> (totalSamplesWritten &lt; numSamples)
                {
                    tempSample = (<span class="kwrd">short</span>)-amplitude;
                    <span class="kwrd">for</span> (i = 0; i &lt; samplesPerPeriod &amp;&amp; 
        totalSamplesWritten &lt; numSamples; i&#43;&#43;)
                    {
                        tempSample &#43;= sampleStep;
                        sampleData[totalSamplesWritten] = tempSample;

                        totalSamplesWritten&#43;&#43;;
                    }
                }
            }
            <span class="kwrd">break</span>;
        <span class="kwrd">case</span> WaveType.Noise:
            {
                Random rnd = <span class="kwrd">new</span> Random();
                <span class="kwrd">for</span> (<span class="kwrd">int</span> i = 0; i &lt; numSamples; i&#43;&#43;)
                {
                    sampleData[i] = Convert.ToInt16(
        rnd.Next(-amplitude, amplitude));
                }
            }
            <span class="kwrd">break</span>;
    }
    <span class="kwrd">return</span> sampleData;
}</pre>
<p></p>
<p><b>VB.Net <br>
</b></p>
<pre class="csharpcode"><span class="kwrd">Public</span> <span class="kwrd">Function</span> GenerateOscillatorSampleData(<span class="kwrd">ByVal</span> osc <span class="kwrd">As</span> Oscillator) <span class="kwrd">As</span> <span class="kwrd">Short</span>()
    <span class="rem">' Creates a looping buffer based on the params given</span>
    <span class="rem">' Fill the buffer with whatever waveform at the specified frequency </span>
    <span class="kwrd">Dim</span> numSamples <span class="kwrd">As</span> <span class="kwrd">Integer</span> = Convert.ToInt32(
     bufferDurationSeconds * waveFormat.SamplesPerSecond)
    <span class="kwrd">Dim</span> sampleData <span class="kwrd">As</span> <span class="kwrd">Short</span>() = <span class="kwrd">New</span> <span class="kwrd">Short</span>(numSamples - 1) {}
    <span class="kwrd">Dim</span> frequency <span class="kwrd">As</span> <span class="kwrd">Double</span> = osc.Frequency
    <span class="kwrd">Dim</span> amplitude <span class="kwrd">As</span> <span class="kwrd">Integer</span> = osc.Amplitude
    <span class="kwrd">Dim</span> angle <span class="kwrd">As</span> <span class="kwrd">Double</span> = (Math.PI * 2 * frequency) /
     (waveFormat.SamplesPerSecond * waveFormat.Channels)

    <span class="kwrd">Select</span> <span class="kwrd">Case</span> osc.WaveType
        <span class="kwrd">Case</span> WaveType.Sine
            <span class="kwrd">If</span> <span class="kwrd">True</span> <span class="kwrd">Then</span>
                <span class="kwrd">For</span> i <span class="kwrd">As</span> <span class="kwrd">Integer</span> = 0 <span class="kwrd">To</span> numSamples - 1
                    <span class="rem">' Generate a sine wave in both channels.</span>
                    sampleData(i) =
                     Convert.ToInt16(amplitude * Math.Sin(angle * i))
                <span class="kwrd">Next</span>
            <span class="kwrd">End</span> <span class="kwrd">If</span>
            <span class="kwrd">Exit</span> <span class="kwrd">Select</span>
        <span class="kwrd">Case</span> WaveType.Square
            <span class="kwrd">If</span> <span class="kwrd">True</span> <span class="kwrd">Then</span>
                <span class="kwrd">For</span> i <span class="kwrd">As</span> <span class="kwrd">Integer</span> = 0 <span class="kwrd">To</span> numSamples - 1
                    <span class="rem">' Generate a square wave in both channels.</span>
                    <span class="kwrd">If</span> Math.Sin(angle * i) &gt; 0 <span class="kwrd">Then</span>
                        sampleData(i) = Convert.ToInt16(amplitude)
                    <span class="kwrd">Else</span>
                        sampleData(i) = Convert.ToInt16(-amplitude)
                    <span class="kwrd">End</span> <span class="kwrd">If</span>
                <span class="kwrd">Next</span>
            <span class="kwrd">End</span> <span class="kwrd">If</span>
            <span class="kwrd">Exit</span> <span class="kwrd">Select</span>
        <span class="kwrd">Case</span> WaveType.Sawtooth
            <span class="kwrd">If</span> <span class="kwrd">True</span> <span class="kwrd">Then</span>
                <span class="kwrd">Dim</span> samplesPerPeriod <span class="kwrd">As</span> <span class="kwrd">Integer</span> =
                 Convert.ToInt32(waveFormat.SamplesPerSecond /
                      (frequency / waveFormat.Channels))
                <span class="kwrd">Dim</span> sampleStep <span class="kwrd">As</span> <span class="kwrd">Short</span> =
                 Convert.ToInt16((amplitude * 2) / samplesPerPeriod)
                <span class="kwrd">Dim</span> tempSample <span class="kwrd">As</span> <span class="kwrd">Short</span> = 0

                <span class="kwrd">Dim</span> i <span class="kwrd">As</span> <span class="kwrd">Integer</span> = 0
                <span class="kwrd">Dim</span> totalSamplesWritten <span class="kwrd">As</span> <span class="kwrd">Integer</span> = 0
                <span class="kwrd">While</span> totalSamplesWritten &lt; numSamples
                    tempSample = <span class="kwrd">CShort</span>(-amplitude)
                    i = 0
                    <span class="kwrd">While</span> i &lt; samplesPerPeriod <span class="kwrd">AndAlso</span> totalSamplesWritten &lt; numSamples
                        tempSample &#43;= sampleStep
                        sampleData(totalSamplesWritten) = tempSample

                        totalSamplesWritten &#43;= 1
                        i &#43;= 1
                    <span class="kwrd">End</span> <span class="kwrd">While</span>
                <span class="kwrd">End</span> <span class="kwrd">While</span>
            <span class="kwrd">End</span> <span class="kwrd">If</span>
            <span class="kwrd">Exit</span> <span class="kwrd">Select</span>
        <span class="kwrd">Case</span> WaveType.Noise
            <span class="kwrd">If</span> <span class="kwrd">True</span> <span class="kwrd">Then</span>
                <span class="kwrd">Dim</span> rnd <span class="kwrd">As</span> <span class="kwrd">New</span> Random()
                <span class="kwrd">For</span> i <span class="kwrd">As</span> <span class="kwrd">Integer</span> = 0 <span class="kwrd">To</span> numSamples - 1
                    sampleData(i) = Convert.ToInt16(
                     rnd.[<span class="kwrd">Next</span>](-amplitude, amplitude))
                <span class="kwrd">Next</span>
            <span class="kwrd">End</span> <span class="kwrd">If</span>
            <span class="kwrd">Exit</span> <span class="kwrd">Select</span>
    <span class="kwrd">End</span> <span class="kwrd">Select</span>
    <span class="kwrd">Return</span> sampleData
<span class="kwrd">End</span> Function</pre>
<p></p>
<p>The Mixer is the heart of the app, and it's a beautiful example of object orientation and cohesion. Give it three things (oscillators) and it spits out a new thing you can use (an array of sample data).
</p>
<p>Now that we have the sample data, all we have to do is play it back using DirectSound.</p>
<h3>Sound Playback with DirectSound</h3>
<p>As I mentioned, DirectSound provides a wrapper over the WAV format. You set up your buffer and format information and then feed it a bunch of data in the form of an array of shorts (arrays of trousers are known to cause errors).</p>
<p>First, we initialize the format information and buffer in the Window_Loaded event handler of the main form. The values below are not really arbitrary; there is an explanation of them in the Optional Reading section above (see
<a href="http://blogs.msdn.com/dawate/archive/2009/06/23/intro-to-audio-programming-part-2-demystifying-the-wav-format.aspx">
Demystifying the WAV Format</a>). This code also contains the code to add the oscillators, as shown earlier in the article.</p>
<p><b>C#</b> <br>
</p>
<pre class="csharpcode"><span class="kwrd">private</span> <span class="kwrd">void</span> Window_Loaded(<span class="kwrd">object</span> sender, System.Windows.RoutedEventArgs e)
{
    WindowInteropHelper helper = 
        <span class="kwrd">new</span> WindowInteropHelper(Application.Current.MainWindow);
    device.SetCooperativeLevel(helper.Handle, CooperativeLevel.Normal);

    waveFormat = <span class="kwrd">new</span> Microsoft.DirectX.DirectSound.WaveFormat();
    waveFormat.SamplesPerSecond = 44100;
    waveFormat.Channels = 2;
    waveFormat.FormatTag = WaveFormatTag.Pcm;
    waveFormat.BitsPerSample = 16;
    waveFormat.BlockAlign = 4;
    waveFormat.AverageBytesPerSecond = 176400;

    bufferDesc = <span class="kwrd">new</span> BufferDescription(waveFormat);
    bufferDesc.DeferLocation = <span class="kwrd">true</span>;
    bufferDesc.BufferBytes = Convert.ToInt32(
        bufferDurationSeconds * waveFormat.AverageBytesPerSecond / waveFormat.Channels);

    <span class="rem">// Add 3 oscillators</span>
    Oscillator tmp;
    <span class="kwrd">for</span> (<span class="kwrd">int</span> i = 0; i &lt; NUM_GENERATORS; i&#43;&#43;)
    {
        tmp = <span class="kwrd">new</span> Oscillator();
        Oscs.Children.Add(tmp);
        mixer.Oscillators.Add(tmp);
    }            
}</pre>
<p><b>VB <br>
</b></p>
<pre class="csharpcode"><span class="kwrd">Private</span> <span class="kwrd">Sub</span> Window_Loaded(<span class="kwrd">ByVal</span> sender <span class="kwrd">As</span> <span class="kwrd">Object</span>, <span class="kwrd">ByVal</span> e <span class="kwrd">As</span> System.Windows.RoutedEventArgs)
    <span class="kwrd">Dim</span> helper <span class="kwrd">As</span> <span class="kwrd">New</span> WindowInteropHelper(Application.Current.MainWindow)
    device.SetCooperativeLevel(helper.Handle, CooperativeLevel.Normal)

    waveFormat = <span class="kwrd">New</span> Microsoft.DirectX.DirectSound.WaveFormat()
    waveFormat.SamplesPerSecond = 44100
    waveFormat.Channels = 2
    waveFormat.FormatTag = WaveFormatTag.Pcm
    waveFormat.BitsPerSample = 16
    waveFormat.BlockAlign = 4
    waveFormat.AverageBytesPerSecond = 176400

    bufferDesc = <span class="kwrd">New</span> BufferDescription(waveFormat)
    bufferDesc.DeferLocation = <span class="kwrd">True</span>
    bufferDesc.BufferBytes = Convert.ToInt32(
     bufferDurationSeconds * waveFormat.AverageBytesPerSecond / waveFormat.Channels)

    <span class="rem">' Add 3 oscillators</span>
    <span class="kwrd">Dim</span> tmp <span class="kwrd">As</span> Oscillator
    <span class="kwrd">For</span> i <span class="kwrd">As</span> <span class="kwrd">Integer</span> = 0 <span class="kwrd">To</span> NUM_GENERATORS - 1
        tmp = <span class="kwrd">New</span> Oscillator()
        Oscs.Children.Add(tmp)
        mixer.Oscillators.Add(tmp)
    <span class="kwrd">Next</span>
<span class="kwrd">End</span> Sub</pre>
<p></p>
<p>When you click the Play button, the application takes its collection of oscillators and passes the values of the UI controls to the Mixer (which is initialized on each click with a reference to the main form window, so it can grab the Oscillator user controls).</p>
<p>The mixer outputs an array of shorts, which we write to a DirectSound buffer.</p>
<p>Here is the code for the Play button's click event handler:</p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode"><span class="kwrd">private</span> <span class="kwrd">void</span> btnPlay_Click(<span class="kwrd">object</span> sender, System.Windows.RoutedEventArgs e)
{                                    
    mixer.Initialize(Application.Current.MainWindow);

    <span class="kwrd">short</span>[] sampleData = mixer.MixToStream();
    buffer = <span class="kwrd">new</span> SecondaryBuffer(bufferDesc, device);            
    buffer.Write(0, sampleData, LockFlag.EntireBuffer);
    buffer.Play(0, BufferPlayFlags.Default);            

    GraphWaveform(sampleData);
}</pre>
<p></p>
<p><b>VB <br>
</b></p>
<pre class="csharpcode"><span class="kwrd">Private</span> <span class="kwrd">Sub</span> btnPlay_Click(sender <span class="kwrd">As</span> <span class="kwrd">Object</span>, e <span class="kwrd">As</span> System.Windows.RoutedEventArgs)
    mixer.Initialize(Application.Current.MainWindow)

    <span class="kwrd">Dim</span> sampleData <span class="kwrd">As</span> <span class="kwrd">Short</span>() = mixer.MixToStream()
    buffer = <span class="kwrd">New</span> SecondaryBuffer(bufferDesc, device)
    buffer.Write(0, sampleData, LockFlag.EntireBuffer)
    buffer.Play(0, BufferPlayFlags.[<span class="kwrd">Default</span>])

    GraphWaveform(sampleData)
<span class="kwrd">End</span> Sub</pre>
<p></p>
<h3>Drawing Pretty Graphs</h3>
<p>All that's left is to draw the graph of the waveform on the canvas. Below is the GraphWaveform method. This method could graph anything it wanted to, as long as it was an array of shorts (not trousers). It's reminiscent of trying to graph things using Flash
 back in the day, when you had to actually figure out points and lines (most likely on paper), but WPF's Polyline object makes this rather trivial.</p>
<p><b>C#</b> <br>
</p>
<pre class="csharpcode"><span class="kwrd">private</span> <span class="kwrd">void</span> GraphWaveform(<span class="kwrd">short</span>[] data)
{
    cvDrawingArea.Children.Clear();

    <span class="kwrd">double</span> canvasHeight = cvDrawingArea.Height;
    <span class="kwrd">double</span> canvasWidth = cvDrawingArea.Width;

    <span class="kwrd">int</span> observablePoints = 1800;
            
    <span class="kwrd">double</span> xScale = canvasWidth / observablePoints;
    <span class="kwrd">double</span> yScale = (canvasHeight / 
        (<span class="kwrd">double</span>)(amplitude * 2)) * ((<span class="kwrd">double</span>)amplitude / MAX_AMPLITUDE);            

    Polyline graphLine = <span class="kwrd">new</span> Polyline();
    graphLine.Stroke = Brushes.Black;
    graphLine.StrokeThickness = 1;

    <span class="kwrd">for</span> (<span class="kwrd">int</span> i = 0; i &lt; observablePoints; i&#43;&#43;)
    {
        graphLine.Points.Add(
            <span class="kwrd">new</span> Point(i * xScale, (canvasHeight / 2) - (data[i] * yScale) ));
    }

    cvDrawingArea.Children.Add(graphLine);            
}</pre>
<p><b>VB <br>
</b></p>
<pre class="csharpcode"><span class="kwrd">Private</span> <span class="kwrd">Sub</span> GraphWaveform(<span class="kwrd">ByVal</span> data <span class="kwrd">As</span> <span class="kwrd">Short</span>())
    cvDrawingArea.Children.Clear()

    <span class="kwrd">Dim</span> canvasHeight <span class="kwrd">As</span> <span class="kwrd">Double</span> = cvDrawingArea.Height
    <span class="kwrd">Dim</span> canvasWidth <span class="kwrd">As</span> <span class="kwrd">Double</span> = cvDrawingArea.Width

    <span class="kwrd">Dim</span> observablePoints <span class="kwrd">As</span> <span class="kwrd">Integer</span> = 1800

    <span class="kwrd">Dim</span> xScale <span class="kwrd">As</span> <span class="kwrd">Double</span> = canvasWidth / observablePoints
    <span class="kwrd">Dim</span> yScale <span class="kwrd">As</span> <span class="kwrd">Double</span> = (canvasHeight / <span class="kwrd">CDbl</span>((amplitude * 2))) * (<span class="kwrd">CDbl</span>(amplitude) / MAX_AMPLITUDE)

    <span class="kwrd">Dim</span> graphLine <span class="kwrd">As</span> <span class="kwrd">New</span> Polyline()
    graphLine.Stroke = Brushes.Black
    graphLine.StrokeThickness = 1

    <span class="kwrd">For</span> i <span class="kwrd">As</span> <span class="kwrd">Integer</span> = 0 <span class="kwrd">To</span> observablePoints - 1
        graphLine.Points.Add(
         <span class="kwrd">New</span> Point(i * xScale, (canvasHeight / 2) - (data(i) * yScale)))
    <span class="kwrd">Next</span>

    cvDrawingArea.Children.Add(graphLine)
<span class="kwrd">End</span> Sub</pre>
<p></p>
<h3>Conclusion</h3>
<p>This was a really fun little project that took way less time to code than it does to explain. It's a great exercise because it requires you to think about an ancillary field of science before you can sit down and code, which is really what coding for fun's
 all about, anyway!</p>
<p>If you want to try this out, the download link for the source code is at the top of the article.</p>
<h3>About The Author</h3>
<p>Dan Waters is an Academic Evangelist at Microsoft, covering schools in the Pacific Northwest, Alaska, and Hawaii. He is based in Bellevue, WA. Dan has way too many guitars at home and tries to entice both of his young daughters to learn how to play them.
 Music, technology, and music&#43;technology are among his favorite hobbies, along with snowboarding and trying to maintain cool dad status. You can find his blog at
<a href="http://www.danwaters.com">www.danwaters.com</a> or follow him on Twitter at
<a href="http://www.twitter.com/danwaters">www.twitter.com/danwaters</a>.</p>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/(A(cSFyXJXzzAEkAAAANzEyZjRjOTAtYTMyMC00ZGEwLTliYjItOTg2NTIwMzI2MjVjgc-VZjdKOTJIVbCoVXIqp0D5hoQ1))/Niners/c4f.Dan-Waters/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:2bd34398dc634955bf3a9e7600c975ca">]]></description>
      <comments>http://channel9.msdn.com/(A(cSFyXJXzzAEkAAAANzEyZjRjOTAtYTMyMC00ZGEwLTliYjItOTg2NTIwMzI2MjVjgc-VZjdKOTJIVbCoVXIqp0D5hoQ1))/coding4fun/articles/Generating-Sound-Waves-with-C-Wave-Oscillators</comments>
      <itunes:summary>
For the longest time, I&#39;ve been baffled by the concept of sound in computing. How in the world is sound store? How is it played back? In classic Coding4Fun style, we&#39;ll learn by doing in this article—by building a wave oscillator application.
 
Optional Reading
I cover the basics of this article in a multi-part blog series, which you should check out if you have trouble: 
Part 1 - How Audio Data is Represented

Part 2 - Demystifying the WAV Format

Part 3 - Synthesizing Simple WAV Audio Using C#

Part 4 - Algorithms for Different Sound Waves in C# 
What&#39;s An Oscillator?
An oscillator is a device or application that generates a waveform. In electrical engineering terms, it&#39;s a device that outputs an electrical current with varying voltage. If you plot the voltage over time, you get a regular wave in a particular form, such
 as a sine, square, triangle or sawtooth. 
An oscillator is the most basic type of synthesizer. Analog synths use electrical circuits to output a sound wave. Digital synthesizers do the same thing, but with software. 
You can create a pretty neat sounding instrument by combining the outputs of multiple oscillators. For example, if you have three oscillators oscillating at a frequency of 440Hz (concert A pitch), but each of them has a different waveform (saw, square, sine)
 you get a very interesting, layered sound.  
But before we get too deep into this subject, let&#39;s briefly explore the physics of sound. 
The Physics of Sound
Sound happens when air pressure changes on your ear drum. When you clap in an empty room, pressure waves bounce all over the place and dance on your eardrum. The changes in pressure are detected continuously by your ear.
 
Digitally, “pressure” is referred to by a scalar value called amplitude. 
The amplitude (loudness) of the wave is measured thousands of times per second (44,100 times per second on CDs). Every measurement of pressure (aka
amplitude) is called a sample—CDs are recorded with 44,100 samples per second, each w</itunes:summary>
      <link>http://channel9.msdn.com/(A(cSFyXJXzzAEkAAAANzEyZjRjOTAtYTMyMC00ZGEwLTliYjItOTg2NTIwMzI2MjVjgc-VZjdKOTJIVbCoVXIqp0D5hoQ1))/coding4fun/articles/Generating-Sound-Waves-with-C-Wave-Oscillators</link>
      <pubDate>Mon, 03 May 2010 17:24:35 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/(A(cSFyXJXzzAEkAAAANzEyZjRjOTAtYTMyMC00ZGEwLTliYjItOTg2NTIwMzI2MjVjgc-VZjdKOTJIVbCoVXIqp0D5hoQ1))/coding4fun/articles/Generating-Sound-Waves-with-C-Wave-Oscillators</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/10006604_100.jpg" height="75" width="100"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/10006604_220.jpg" height="165" width="220"></media:thumbnail>      
      <dc:creator>Dan Waters</dc:creator>
      <itunes:author>Dan Waters</itunes:author>
      <slash:comments>4</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/(A(cSFyXJXzzAEkAAAANzEyZjRjOTAtYTMyMC00ZGEwLTliYjItOTg2NTIwMzI2MjVjgc-VZjdKOTJIVbCoVXIqp0D5hoQ1))/coding4fun/articles/Generating-Sound-Waves-with-C-Wave-Oscillators/RSS</wfw:commentRss>
      <category>Audio</category>
      <category>DirectX</category>
      <category>Media</category>
    </item>
  <item>
      <title>Building Multiplayer Texas Holdem Poker For The Zune</title>
      <description><![CDATA[
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9582637/clip_image002_2.gif"><img title="clip_image002" border="0" alt="clip_image002" align="right" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9582637/clip_image002_thumb.gif" width="240" height="320"></a>Have
 you ever been interested in creating a game that harnesses XNA's powerful network library to create multiplayer experiences for the Zune device?</p>
<p>The Zune firmware version 3.1 brought us a professionally built incarnation of Texas Holdem that supports network play. Understanding how to send and receive data with the Zune can be a little daunting at first, but once you understand the pattern, it's
 easy. </p>
<p>To build out the entire game, you probably need about a week, but you can build some simpler examples in far less time.
</p>
<p>This is an earlier project from before the release of my <a href="http://www.tinyurl.com/zunebook">
Zune game development book</a>. Accordingly, some of the code samples you see in this article may be inconsistent with what you find in the download. The code in the article is the “correct” way to do things. The code in the download is still a work in progress.</p>

<h3>The Workflow</h3>
<p>Developing multiplayer games for the Zune is interesting because you have to deploy to each device individually. Once you have a build that works for you, it's helpful to run-deploy (Control&#43;F5) to one device, leave it running there, and then plug in the
 other Zune and debug-deploy (F5) to it. This way you have one debuggable instance of the game running. Make sure to set the appropriate Zune device as the default in the XNA Game Studio Device Center (accessible from the Tools menu).</p>
<h3>Starting A Network Session</h3>
<p>Because the Zunes connect over an ad-hoc, peer-to-peer connection rather than through an access point, you will have to designate one Zune as the host device. The host is usually determined to be the one that creates a new game. Therefore, all Zunes that
 join the host's network session are simply peers. The difference between the host and the peers is that the host usually maintains the game state on top of executing the game as well, because the game data has to be centralized somewhere. Keep that in mind,
 because if one Zune is doing substantially more processing, it can lag behind and mess up your network session. Also, remember that all Zunes are running the exact same copy of the game, so the game must support both host and peer scenarios.</p>
<h4>Create / Join / Lobby Model</h4>
<p>Most peer-to-peer connected games allow a user to create or join a game. After doing so, the player is funneled into an area called the Lobby where they can specify their readiness. When all players are ready, the host can start the game. Some of this functionality
 is provided directly by the XNA Framework's Net and GamerServices libraries. </p>
<p>I normally create three separate screens based on the <a href="http://creators.xna.com/en-US/sample/network_game_state_mgt_sample">
Network Game State Management sample</a> from the Creators Club website. The first is the Create screen, which looks exactly like a lobby. It starts up a network session and waits for players to join and become ready. The code to create a network session looks
 like this (note that I have employed some abstraction to make my code a little more cohesive):</p>
<p><b>C#</b></p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">void</span> CreateZuneSession(<span class="kwrd">int</span> maxNetworkPlayers)
{
    KillSession();

    <span class="kwrd">try</span>
    {
        Session = NetworkSession.Create(NetworkSessionType.SystemLink, 1,      
            maxNetworkPlayers); 
        Me = Session.LocalGamers[0];
    }
    <span class="kwrd">catch</span> (NetworkNotAvailableException)
    {
        <span class="kwrd">throw</span> <span class="kwrd">new</span> NetworkNotAvailableException(<span class="str">&quot;Zune wireless is not 
            enabled.&quot;</span>);
    }
    <span class="kwrd">catch</span> (NetworkException ne)
    {
        <span class="kwrd">throw</span> ne;
    }

    <span class="kwrd">if</span> (Session == <span class="kwrd">null</span>)
        <span class="kwrd">throw</span> <span class="kwrd">new</span> NetworkException(<span class="str">&quot;The network session could not be 
            created.&quot;</span>);
}</pre>
<style type="text/css">
<!--
.csharpcode, .csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{background-color:#f4f4f4;
	width:100%;
	margin:0em}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p>All Zune network sessions are of the type SystemLink, much like LAN-networked Xbox consoles. The ‘1' parameter specifies the number of local players – of course, on a Zune, there can only be one.</p>
<p>This line of code sets the Session property to a newly created network session. The Join screen, running on another Zune, will find this session asynchronously as an available network session and attempt to join it. The first step is to enumerate available
 network sessions:</p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode"><span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Asynchronous: Begins to discover network sessions.</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="kwrd">public</span> <span class="kwrd">void</span> BeginGetAvailableSessions()
{
    <span class="rem">// Destroy any existing connections</span>
    KillSession();

    NetworkSession.BeginFind(NetworkSessionType.SystemLink, 1, <span class="kwrd">null</span>, <span class="kwrd">new</span> 
        AsyncCallback(SessionsFoundCallback), <span class="kwrd">null</span>);
}</pre>
<p>This code looks for SystemLink sessions and calls the callback method SessionsFoundCallback when the operation completes (successfully or unsuccessfully). If sessions are found, an event is fired. Other screens can subscribe to this event and transition
 to other screens or do other processing with the network session.</p>
<p><b>C#</b></p>
<pre class="csharpcode"><span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Called when network sessions are found.</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;param name=&quot;result&quot;&gt;&lt;/param&gt;</span>
<span class="kwrd">public</span> <span class="kwrd">void</span> SessionsFoundCallback(IAsyncResult result)
{
    AvailableNetworkSessionCollection availableSessions = <span class="kwrd">null</span>;
    availableSessions = NetworkSession.EndFind(result);

    <span class="kwrd">if</span> (NetworkSessionsFound != <span class="kwrd">null</span>)
        NetworkSessionsFound(availableSessions);
}        </pre>
<p>When all players are ready and the host presses the middle button, the network session's StartGame() method is called, which will cause all connected peers to receive a GameStarted event. This loads up the playing screen.</p>
<p><b>C#</b></p>
<pre class="csharpcode"><span class="kwrd">if</span> (allPlayersReady &amp;&amp; atLeastTwoPlayers)
{
    <span class="kwrd">if</span> (ScreenManager.Network.Session != <span class="kwrd">null</span>)
        ScreenManager.Network.Session.StartGame();
}</pre>
<p>That's basically how to connect up two Zunes in a network session. See my <a href="http://www.tinyurl.com/zunebook">
book</a> for a much more detailed explanation.</p>
<h3>Dealing With Cards</h3>
<p>As Poker is a card game, you might want to develop a testable, standalone library that you can use not only to house your objects, but also to write out all the intense logic required for a game like poker. The task of determining what a player's best hand
 is out of seven cards (and whether it beats another player's hand) is more in-depth than you might expect.
</p>
<p>An easy way to go about this is to create a Zune game library. I called mine CardLib. CardLib has objects such as these:</p>
<ul>
<li>Card which has a suit, a value, some comparers and some utility methods) </li><li>Deck, which has a collection of cards and methods like Shuffle, ResetDeck, etc.
</li><li>Dealer, which has a deck, a list of the five community cards, and methods like Shuffle, DealCard, Burn, DealFlop, DealTurn, etc.
</li><li>HoldemHand, which contains all of the logic for determining what a hand is (always 7 cards)
</li><li>BestHand, which takes a HoldemHand and determines what the best possible hand is within that hand
</li></ul>
<h4>Shuffling Cards</h4>
<p>Shuffling cards is surprisingly easy. I use the <a href="http://www.codinghorror.com/blog/archives/001015.html">
Knuth-Fisher-Yates shuffling algorithm</a>, which takes every card in the deck and randomly swaps it with another.</p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode"><span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Knuth-Fisher-Yates shuffling algorithm:</span>
<span class="rem">/// http://www.codinghorror.com/blog/archives/001015.html</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="kwrd">public</span> <span class="kwrd">void</span> Shuffle()
{
    Random rand = <span class="kwrd">new</span> Random();
    <span class="kwrd">for</span> (<span class="kwrd">int</span> cardIndex = _cards.Count - 1; cardIndex &gt; 0; cardIndex--)
    {
        <span class="kwrd">int</span> randomIndex = rand.Next(cardIndex &#43; 1);
        SwapCardsByIndex(cardIndex, randomIndex);
    }
    _dealIndex = 0;
}</pre>
<h4>Poker Logic</h4>
<p>An example method you'll see in this library is this snippet to check if the hand is a royal flush:</p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">bool</span> IsRoyalFlush(<span class="kwrd">out</span> List&lt;Card&gt; winningCards)
{
    List&lt;Card&gt; straightFlushCards;

    <span class="kwrd">if</span> (IsStraightFlush(<span class="kwrd">out</span> straightFlushCards))
    {                
        <span class="rem">// Check to make sure the straight flush cards are: 10 J Q K A</span>
        straightFlushCards.Sort();

        <span class="kwrd">if</span> (straightFlushCards[0].Value == 10 &amp;&amp;
            straightFlushCards[1].Value == Card.Jack &amp;&amp;
            straightFlushCards[2].Value == Card.Queen &amp;&amp;
            straightFlushCards[3].Value == Card.King &amp;&amp;
            straightFlushCards[4].Value == Card.Ace)
        {
            winningCards = straightFlushCards;
            <span class="kwrd">return</span> <span class="kwrd">true</span>;
        }

        <span class="kwrd">else</span>
        {
            winningCards = <span class="kwrd">null</span>;
            <span class="kwrd">return</span> <span class="kwrd">false</span>;
        }
    }
    <span class="kwrd">else</span>
    {
        winningCards = <span class="kwrd">null</span>;
        <span class="kwrd">return</span> <span class="kwrd">false</span>;
    }
}</pre>
<p>There is a ton of similar and even more disgusting logic to peruse in the HoldemHand.cs file in the region entitled “Poker Logic Fun Times.” This logic covers every possible poker hand and could probably be refactored to be way more elegant.</p>
<p>When it comes time to evaluate the winner, each player's best hand is determined and they are evaluated against each other to determine the winner. This code returns a list of WinnerInfo objects, which returns the player info and a list of the cards they
 won with.</p>
<p><b>C#</b></p>
<pre class="csharpcode"><span class="kwrd">public</span> List&lt;WinnerInfo&gt; DetermineWinners()
{
    BestHand overallBestHand = <span class="kwrd">null</span>;
    HoldemPlayer winner = <span class="kwrd">null</span>;

    List&lt;WinnerInfo&gt; winners = <span class="kwrd">new</span> List&lt;WinnerInfo&gt;();

    <span class="kwrd">foreach</span> (HoldemPlayer player <span class="kwrd">in</span> _players)
    {
        <span class="kwrd">if</span> (player.Status != PlayerStatus.Folded)
        {
            HoldemHand tempHand = <span class="kwrd">new</span> HoldemHand(player.Pocket, _communityCards);
            BestHand bestHand = tempHand.GetBestHand();

            <span class="kwrd">if</span> (overallBestHand == <span class="kwrd">null</span>) <span class="rem">// if there is no best hand yet</span>
            {
                overallBestHand = bestHand;
                winner = player;
                winners.Add(<span class="kwrd">new</span> WinnerInfo(overallBestHand, winner, Me));
            }
            <span class="kwrd">else</span>
            {
                <span class="rem">// if this hand beats the current best hand</span>
                <span class="kwrd">if</span> (BestHand.Beats(bestHand, overallBestHand))
                {
                    winners.Clear();
                    overallBestHand = bestHand;
                    winner = player;
                    winners.Add(<span class="kwrd">new</span> WinnerInfo(overallBestHand, winner, Me));
                }
                <span class="kwrd">else</span>
                {
                    <span class="kwrd">if</span> (BestHand.IsEquivalentTo(bestHand, overallBestHand))
                    {
                        winners.Add(<span class="kwrd">new</span> WinnerInfo(bestHand, player, Me));
                    }
                }
            }
        }
    }

    _winners = winners;
    <span class="kwrd">return</span> winners;
}</pre>
<h4>Drawing Cards On The Screen</h4>
<p>Rather than have 52 different sprites that represent each possible card, I just made my own sheet of Zune-sized playing cards. Horizontally, they are ordered by value (1-13) and vertically they are ordered by suit (both alphabetically and corresponding to
 the numeric value of the Suit enumeration in the project, 1-4).</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9582637/clip_image004_2.gif"><img title="clip_image004" border="0" alt="clip_image004" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9582637/clip_image004_thumb.gif" width="572" height="240"></a></p>
<p>When a specific card is requested to be drawn, a formula is used to calculate the source rectangle from this larger image. This is very similar to how fonts worked before spritefonts were introduced into XNA. This allows us to strip out the graphic of a
 specific card and draw it onscreen at some other location.</p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode"><span class="kwrd">private</span> <span class="kwrd">void</span> DrawCard(Card card, Vector2 position)
{
    <span class="kwrd">if</span> (card != Card.Undefined &amp;&amp; card.Suit != Suit.Unassigned)
        ScreenManager.SpriteBatch.Draw(_texDeck, position, GetCardSourceRect(card), Color.White);
}

<span class="kwrd">private</span> Rectangle GetCardSourceRect(Card card)
{
    <span class="kwrd">if</span> (card.Suit == Suit.Unassigned)
        <span class="kwrd">throw</span> <span class="kwrd">new</span> ArgumentException(<span class="str">&quot;Unassigned cards cannot be drawn.&quot;</span>);

    <span class="kwrd">int</span> cardColumn = card.Value - 1;
    <span class="kwrd">int</span> cardRow = (<span class="kwrd">int</span>)card.Suit - 1;

    <span class="kwrd">int</span> x = cardColumn * MainScreenElements.CARD_WIDTH;
    <span class="kwrd">int</span> y = cardRow * MainScreenElements.CARD_HEIGHT;

    <span class="kwrd">return</span> <span class="kwrd">new</span> Rectangle(x, y, MainScreenElements.CARD_WIDTH, MainScreenElements.CARD_HEIGHT);
}</pre>
<h3>Managing Network Data</h3>
<p>One thing that increases the complexity of this game (in no small way) is the management of network data. First of all, the host's actions are a superset of the peer's actions (a host is also a peer, but it also has to manage the game and network state).
 For example, when a peer decides to bet, it has to send a message to the host saying “I would like to bet,” and then the host will process that message and relay it to the other peers. The host is also responsible for managing whose turn it is and determining
 who the winner is. Theoretically, you could do a lot of this with every peer acting equally but it feels safer to me to have the host responsible for important activities like dealing cards. In fact, the host has to be the only one who can deal cards, because
 if each client maintained its own deck, it would be randomized for every peer when the deck is shuffled.
</p>
<h4>How Data Is Sent And Received</h4>
<p>I will usually create a static class called NetworkMessageSender that is responsible for sending various messages. I keep an enumeration of type byte that holds the possible network messages.
</p>
<p>I always send the byte indicating the message type first, so that when the peer receives a byte, it knows how to respond. For example, if the peer receives a CardDealt message, it can pop off a string and a card from the incoming packets. If the card is
 not intended for the peer, it can simply discard the message. </p>
<p>Data you want to send is written to a packet writer object. When the data is ready to be sent, you call the SendData method of the LocalGamer object. Depending on how important packet receipt is, you can specify the type of transmission. I use ReliableInOrder
 during poker because network data is exchanged relatively infrequently. Although there is only one local network gamer, you can use a foreach loop to ensure this code will work on other platforms.</p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode"><span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> SendData()
{
    <span class="kwrd">foreach</span> (LocalNetworkGamer gamer <span class="kwrd">in</span> NetworkSessionManager.Session.LocalGamers)
        gamer.SendData(NetworkSessionManager.PacketWriter, SendDataOptions.ReliableInOrder);
}</pre>
<p>Specific chunks of data are then sent using various static methods. Each piece of information is written sequentially. The card is serialized into a string format before being sent. The following chunk of code is used to send a card to a player.</p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">void</span> DealCards(HoldemPlayer player)
{
    NetworkSessionManager.PacketWriter.Write((<span class="kwrd">byte</span>)NetworkMessageType.Deal);
    NetworkSessionManager.PacketWriter.Write(player.Name);
    NetworkSessionManager.PacketWriter.Write(player.Pocket.Card1.Serialize());
    NetworkSessionManager.PacketWriter.Write(player.Pocket.Card2.Serialize());
    SendData();
}</pre>
<p>On the other side of that, whenever the screen updates, the game is constantly checking for new network data. The following code is part of a method that is called from the game screen's Update loop.</p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode"><span class="kwrd">private</span> <span class="kwrd">void</span> UpdateNetworkSession()
{
    NetworkSessionManager.Update();

    <span class="kwrd">foreach</span> (LocalNetworkGamer localGamer <span class="kwrd">in</span> 
        NetworkSessionManager.Session.LocalGamers)
    {
        <span class="kwrd">while</span> (localGamer.IsDataAvailable)
        {
            NetworkGamer sender;
            localGamer.ReceiveData(NetworkSessionManager.PacketReader, 
                <span class="kwrd">out</span> sender);

            <span class="rem">// Interpret the first piece of information, the message.</span>
            NetworkMessageType message = (NetworkMessageType)NetworkSessionManager.PacketReader.ReadByte();

            <span class="rem">// Determine what to read and what to do based on this message type</span>
            <span class="kwrd">switch</span> (message)
            {
                <span class="rem">// major snippage</span>
                <span class="kwrd">case</span> NetworkMessageType.Deal: <span class="rem">// Happens when a card is dealt</span>
                {
                    <span class="kwrd">string</span> playerName = NetworkSessionManager.PacketReader.ReadString();
                    <span class="kwrd">string</span> card1 = NetworkSessionManager.PacketReader.ReadString();
                    <span class="kwrd">string</span> card2 = NetworkSessionManager.PacketReader.ReadString();

                 _gameplayManager.Players[playerName].Pocket.Set(PlayerPocket.FIRST_CARD_INDEX, <span class="kwrd">new</span> 
                    Card(card1));
                 _gameplayManager.Players[playerName].Pocket.Set(PlayerPocket.SECOND_CARD_INDEX, <span class="kwrd">new</span> 
                    Card(card2));
                }
                <span class="kwrd">break</span>;
            }
        }
    }
}</pre>
<p>There is a whole bunch of similar code that underlies how the game executes. When a message needs to be sent, the NetworkMessageSender class is used. To determine what happens when a message is received, we look at that ginormous switch statement that gets
 called in the screen update loop. </p>
<p>Remember that the host is also a peer and it will receive the very same messages it sends (unless you specify otherwise). Be careful not to double-process messages if they are sent by the host. In some cases you will need to check that the current device
 is or is not the host. In the sample download, this is achieved just by checking a Boolean value that is set early on in the game.</p>
<h3>Conclusion</h3>
<p>Building Poker for the Zune, from the ground up, is no small feat! Networked Zune games are far simpler when you have a much more limited set of possible data and messages that could be sent. For example, networked Pong, Battleship or Tetris would be pretty
 easy compared to poker. Turn-based games on the Zune also provide an interesting challenge in terms of what happens when a Zune drops from the network session.</p>
<p>This is just a small dip into networked Zune game development. For a deep dive, check out my book,
<a href="http://www.tinyurl.com/zunebook">Zune Game Development using XNA 3.0</a>, also available on
<a href="http://www.apress.com/book/view/9781430218616">Apress.com as an eBook</a>. The final chapter is a sprawling 120 pages covering how to build Crazy Eights for the Zune from the ground up.</p>
<h3>About The Author</h3>
<p>Dan Waters is an Academic Developer Evangelist at Microsoft, based in Tampa, FL. When he's not out showing the latest and greatest MS technology to students and faculty, he's spending time with his wife and young daughter or rocking out on one of his (far
 too numerous) guitars. Follow Dan on <a href="http://www.twitter.com/danwaters">
Twitter</a> or check out his <a href="http://www.danwaters.com">blog</a>.</p>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/(A(cSFyXJXzzAEkAAAANzEyZjRjOTAtYTMyMC00ZGEwLTliYjItOTg2NTIwMzI2MjVjgc-VZjdKOTJIVbCoVXIqp0D5hoQ1))/Niners/c4f.Dan-Waters/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:7306567bc89345a897909e7600cc98a2">]]></description>
      <comments>http://channel9.msdn.com/(A(cSFyXJXzzAEkAAAANzEyZjRjOTAtYTMyMC00ZGEwLTliYjItOTg2NTIwMzI2MjVjgc-VZjdKOTJIVbCoVXIqp0D5hoQ1))/coding4fun/articles/Building-Multiplayer-Texas-Holdem-Poker-For-The-Zune</comments>
      <itunes:summary>
Have
 you ever been interested in creating a game that harnesses XNA&#39;s powerful network library to create multiplayer experiences for the Zune device? 
The Zune firmware version 3.1 brought us a professionally built incarnation of Texas Holdem that supports network play. Understanding how to send and receive data with the Zune can be a little daunting at first, but once you understand the pattern, it&#39;s
 easy.  
To build out the entire game, you probably need about a week, but you can build some simpler examples in far less time.
 
This is an earlier project from before the release of my 
Zune game development book. Accordingly, some of the code samples you see in this article may be inconsistent with what you find in the download. The code in the article is the “correct” way to do things. The code in the download is still a work in progress. 

The Workflow
Developing multiplayer games for the Zune is interesting because you have to deploy to each device individually. Once you have a build that works for you, it&#39;s helpful to run-deploy (Control&amp;#43;F5) to one device, leave it running there, and then plug in the
 other Zune and debug-deploy (F5) to it. This way you have one debuggable instance of the game running. Make sure to set the appropriate Zune device as the default in the XNA Game Studio Device Center (accessible from the Tools menu). 
Starting A Network Session
Because the Zunes connect over an ad-hoc, peer-to-peer connection rather than through an access point, you will have to designate one Zune as the host device. The host is usually determined to be the one that creates a new game. Therefore, all Zunes that
 join the host&#39;s network session are simply peers. The difference between the host and the peers is that the host usually maintains the game state on top of executing the game as well, because the game data has to be centralized somewhere. Keep that in mind,
 because if one Zune is doing substantially more processing, it can lag behind and mess up you</itunes:summary>
      <link>http://channel9.msdn.com/(A(cSFyXJXzzAEkAAAANzEyZjRjOTAtYTMyMC00ZGEwLTliYjItOTg2NTIwMzI2MjVjgc-VZjdKOTJIVbCoVXIqp0D5hoQ1))/coding4fun/articles/Building-Multiplayer-Texas-Holdem-Poker-For-The-Zune</link>
      <pubDate>Tue, 05 May 2009 16:06:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/(A(cSFyXJXzzAEkAAAANzEyZjRjOTAtYTMyMC00ZGEwLTliYjItOTg2NTIwMzI2MjVjgc-VZjdKOTJIVbCoVXIqp0D5hoQ1))/coding4fun/articles/Building-Multiplayer-Texas-Holdem-Poker-For-The-Zune</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/9582637_100.jpg" height="75" width="100"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/9582637_220.jpg" height="165" width="220"></media:thumbnail>      
      <dc:creator>Dan Waters</dc:creator>
      <itunes:author>Dan Waters</itunes:author>
      <slash:comments>2</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/(A(cSFyXJXzzAEkAAAANzEyZjRjOTAtYTMyMC00ZGEwLTliYjItOTg2NTIwMzI2MjVjgc-VZjdKOTJIVbCoVXIqp0D5hoQ1))/coding4fun/articles/Building-Multiplayer-Texas-Holdem-Poker-For-The-Zune/RSS</wfw:commentRss>
      <category>Gaming</category>
      <category>Hardware</category>
      <category>Puzzle</category>
      <category>card and board games</category>
    </item>    
</channel>
</rss>