Steady and even playback

Aug 13, 2011 at 6:08 PM
Edited Aug 13, 2011 at 6:09 PM
Goal - I'm making a basic mistake no doubt.  In this example, my goal is to play two audio files in time.  "hat" on each beat, "kick" on beat one.
Problem - The rhythm is choppy and uneven.  At first I thought it was the accuracy of system.timer events so I changed it up to a loop dependent on the system.diagnostics.stopwatch.  No dice.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using NAudio.Wave;
using NAudio.CoreAudioApi;

namespace Beat
{
    class Program
    {
        static void Main(string[] args)
        {
            IWavePlayer player = null;
            WaveMixerStream32 mixer = null;
            WaveStream ws = null;
            WaveChannel32 wc1 = null;
            WaveChannel32 wc2 = null;

            ws = new WaveFileReader("kick.wav");
            wc1 = new WaveChannel32(ws);
            ws = new WaveFileReader("hat.wav");
            wc2 = new WaveChannel32(ws);

            mixer = new WaveMixerStream32();
            mixer.AutoStop = false;
            mixer.AddInputStream(wc1);
            mixer.AddInputStream(wc2);

            player = new DirectSoundOut();
            player.Init(mixer);
            player.Play();

            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
            sw.Reset();
            sw.Start();
            TimeSpan interval = new TimeSpan(0, 0, 0, 0, 180);
            
            int nCount = 0;
            while (true)
            {
                System.Threading.Thread.Sleep(1);

                if (sw.Elapsed > interval)
                {
                    sw.Reset();
                    sw.Start();
                    wc2.Position = 0;

                    nCount++;
                    if (nCount == 4)
                    {
                        wc1.Position = 0;
                        nCount = 0;
                    }
                }
            }
        }
    }
}
Coordinator
Aug 25, 2011 at 12:42 PM

This is because of buffer read sizes. The soundcard is requesting (say) 100ms at a time from the input streams, and although you are repositioning the inputs at a specific moment, the reposition doens't take effect until another Read takes place when the soundcard needs another buffer. Have a look at the latest source code for a drum machine that puts the beats in sample accurate positions.

Mark