This project has moved. For the latest updates, please go here.

Playing a circular buffer

Jan 28, 2011 at 1:13 PM

Hi,

I am new to NAudio. I have managed to fill a MemoryStream with raw audio data and play it with the IWavePlayer using a RawSourceWaveStream. This works great!
Now, I would like to keep filling the MemoryStream while playing. (Probably, it should be a Circular data element to prevent it from growing infinitely).

Can you give me a clue on how to do this?

Gr, Sander

Feb 1, 2011 at 6:48 AM

A circular buffer did not seem necessary. The Queue in BufferedWaveProvider did the job. However, I got a WaveBadFormat exception during WaveOutOpen when I tried to play my MuLaw encoded stream directly. I fixed this by decoding the byte[] packets before adding it to the BufferedWaveProvider.

First, I create a BufferedWaveProvider:

 

private BufferedWaveProvider m_bufferedWaveProvider = new BufferedWaveProvider(new WaveFormat(8000,16,1));

 

Then, my callback function, which gets fired every time a new packet arrives, looks like this:

 

void OnDataReceived(byte[] audioData)
{
	// decode (WaveOut does not support direct MuLaw playback)
	MemoryStream byteStream = new MemoryStream(audioData);
	WaveFormat waveFormat = WaveFormat.CreateMuLawFormat(8000, 1);
	RawSourceWaveStream rawSourceWaveStream = new RawSourceWaveStream(byteStream, waveFormat);
	WaveStream pcmStream = WaveFormatConversionStream.CreatePcmStream(rawSourceWaveStream);
	byte[] decoded = ConvertNonSeekableStreamToByteArray(pcmStream);

	// add decoded data to buffer
	m_bufferedWaveProvider.AddSamples(decoded,0,decoded.Length);

	// cleanup
	byteStream.Close();
	byteStream.Dispose();
	rawSourceWaveStream.Close();
	rawSourceWaveStream.Dispose();
	pcmStream.Close();
	pcmStream.Dispose();
}

with ConvertNonSeekableStreamToByteArray defined here by Faleij.

// create waveOut
int latency = 80;
WaveCallbackInfo callbackInfo = WaveCallbackInfo.NewWindow();
WaveOut outputDevice = new WaveOut(callbackInfo);
outputDevice.DesiredLatency = latency;
m_waveOut = outputDevice;

// init and play waveOut
m_waveOut.Init(m_bufferedWaveProvider);
m_waveOut.Play();