This project has moved and is read-only. For the latest updates, please go here.

Stream WAV File

Mar 6, 2013 at 3:36 PM
Edited Mar 6, 2013 at 10:06 PM
I am trying to figure out how to stream a WAV file. There are examples on streaming MP3 files but nothing for a WAV file.

I have managed to create a WaveStream and play it back. However, when I try to break it up the first set of bytes plays but after that I get noise. In my queue I can select any one set of byte[] and it plays. It can't play two or more set of byte[].

In the example below the ConcurrentQueue will simulate what I want to stream:
// Class member variables:
ConcurrentQueue<byte[]> _cq1 = new ConcurrentQueue<byte[]>();
private static WaveFormat _waveFormat = new WaveFormat(16000, 16, 2);
private static WaveOut _waveOut1 = new WaveOut();
private static BufferedWaveProvider _waveProvider1 =
             new BufferedWaveProvider(_waveFormat);

// Class constructor
public MainWindow()
{
    _waveOut1.Init(_waveProvider1);
    _waveOut1.Play();

    _worker1.RunWorkerAsync();
    _worker2.RunWorkerAsync();
}

private void worker1_DoWork(object sender, DoWorkEventArgs e)
{
    // These methods are executed on a seperate thread.
    WaveStream convertedStream = GetAudio("MyFile.Wav");
    AddAudio(convertedStream);
}


private void worker2_DoWork(object sender, DoWorkEventArgs e)
{
    // This method is executed on a seperate thread.
    PlayAudio();
}


 

        private WaveStream GetAudio(string wavFile)
        {
            WaveFileReader reader = new WaveFileReader(wavFile);
            WaveStream convertedStream =
                new WaveFormatConversionStream(_waveFormat, reader);

            return convertedStream;
        }

        private void AddAudio(WaveStream convertedStream)
        {
            int bufferSize = (int)convertedStream.Length / _audioSamples;

            int count = bufferSize;
            convertedStream.Position = 0;
            int offset = 0;
            for (; ; )
            {
                byte[] bytes = new byte[bufferSize];
                count = convertedStream.Read(bytes, offset, bufferSize);
                _cq1.Enqueue(bytes);
                if (count == 0)
                {
                    break;
                }
            }
         }

        private void PlayAudio()
        {
            byte[] buffer;
            for (; ; )
            {
                if (_cq1.TryDequeue(out buffer))
                {
                    _waveProvider1.AddSamples(buffer, 0, buffer.Length);
                }

                Thread.Sleep(_sleepMilliSeconds);
            }
        }
Mar 6, 2013 at 10:02 PM
Bump!
Mar 6, 2013 at 10:08 PM
I'm not sure what you are trying to do here. Why not just play directly from a WaveFileReader? If you are receiving WAV over the network, then just stick it into the BufferedWaveProvider (and increase the buffer size or block when it gets full). The concurrent queue seems unnecessary.
Mar 6, 2013 at 11:15 PM
Edited Mar 7, 2013 at 1:56 PM
I am trying to simulate my network traffic before I go off and code that part. I should be able to read bytes from a queue and add them to my WaveProvider continuously.
Mar 7, 2013 at 1:55 PM
Edited Mar 7, 2013 at 1:57 PM
I figured it out. The problem was in the AddAudio method. If I use this method it works:
        private void AddAudio(WaveStream convertedStream)
        {
            int sampleRate = convertedStream.WaveFormat.SampleRate;

            int bytesRead = 0;
            while (convertedStream.Position < convertedStream.Length)
            {
                byte[] bytes = new byte[sampleRate];
                bytesRead = convertedStream.Read(bytes, 0, sampleRate);
                _cq1.Enqueue(bytes);
            }
        }