title: WinMM Library Issues
body: <p>I wrote a WinMM library wrapper library that exposes WaveOut and WaveIn classes for the purpose of recording and playing raw audio streams.</p>
  
  <p>Everything works great, but in order to follow the operating system specs on how to handle the finished buffers, I added a thread that unprepares the buffers and frees the memory.  I also got all of the synchronization down, so that the classes are solid and thread-safe.</p>
  
  <p>However, there seems to be a rare issue where I add a buffer to the WaveOut device and the operating system returns a success code, but if the device is reset immediately afterwords, the OS does not mark the buffer as finished and return it to the application.</p>
  
  <p>It seems that it is loosing the buffers.  So, the problem is, I'm keeping track of the count of individual buffers sent to the device and blocking joining the Close() function to the thread that cleans them up.</p>
  
  <p>Any ideas, or known bugs?</p>
  
  <p>PS:  This does NOT seem to happen on a Quad Core in Vista, but does happen on my Dual Core in XP pro.</p>
  
  <p><strong>EDIT1: I'm totally willing to expose the full source code, once I get it uploaded and propery licensed on codeplex, if that would help anybody.</strong></p>
  
  <p><strong>EDIT2: Posted library to CodePlex: <a href="http://winmm.codeplex.com/" rel="nofollow noreferrer">http://winmm.codeplex.com/</a></strong></p>
  
  <p>Here is an idea of what causes the issue:</p>
  
  <pre><code>public partial class MainView : Form
  {
      private WaveIn waveIn = new WaveIn(WaveIn.WaveInMapperDeviceId);
      private WaveOut waveOut = new WaveOut(WaveOut.WaveOutMapperDeviceId);
  
      public MainView()
      {
          InitializeComponent();
  
          WaveFormat format = WaveFormat.Pcm44Khz16BitMono;
  
          waveOut.Open(format);
  
          waveIn.DataReady += new EventHandler&lt;DataReadyEventArgs&gt;(WaveIn_DataReady);
  
          // Tweaking these values affects the internal buffering thread.
          // Setting too small of a QueueSize with too small of a BufferSize
          //  will cause buffer underruns, which will sound like choppy audio.
          waveIn.BufferQueueSize = 200;
          waveIn.BufferSize = 64;
  
          waveIn.Open(format);
  
          waveIn.Start();
      }
  
      void WaveIn_DataReady(object sender, DataReadyEventArgs e)
      {
          if (waveOut != null)
          {
              lock (waveOut)
              {
                  // We have to check for null after the lock,
                  //  because waveOut may have been disposed
                  //  inside another lock.
                  if (waveOut != null)
                  {
                      waveOut.Write(e.Data);
                  }
              }
          }
      }
  
      private void MainView_FormClosed(object sender, FormClosedEventArgs e)
      {
          if (waveIn != null)
          {
              lock (waveIn)
              {
                  waveIn.Dispose();
                  waveIn = null;
              }
          }
  
          if (waveOut != null)
          {
              lock (waveOut)
              {
                  waveOut.Dispose();
                  waveOut = null;
              }
          }
      }
  }
  </code></pre>