Playing audio from byte[]

Nov 29, 2010 at 12:59 PM

Hello,

 

I've got a quick question about how to play audio originating from a byte[] -- basically, I've recorded audio and streamed it over a network, and now I got the bytes from the buffer, but is unsure how to proceed to play it on a IWavePlayer (I guess)

This is my best guess O_O

 

private void audioReceive(IAsyncResult asyn)
        {
            MemoryStream mem = new MemoryStream();
            int readBytes = 0;
            StateObject state = (StateObject)asyn.AsyncState;
            readBytes = state.getWorkSocket().EndReceive(asyn);

            mem.Write(state.getBuffer(), 0, readBytes);
            mem.Position = 0;
            waveStream = new WaveFileReader(mem);
            waveOut.Init(waveStream);
            waveOut.Play();

            mem.Close();
        }

Nov 30, 2010 at 9:22 PM
Edited Nov 30, 2010 at 9:22 PM

I know its probably a simple issue, I just can't figure it out. Isn't it possible to directly play from a byte[] instead of writing it to a file, then read it into a memory stream again and play it? I guess writing it into a file adds some kind of header needed, but isn't there something like that for raw byte stored in a buffer too?

 

I had a look at the Buffer classes, but they don't seem to be implemented? Atleast I cannot call the constructors.

Coordinator
Nov 30, 2010 at 9:28 PM

use the RawSourceWaveStream I recently added (make your own copy of the class if you can't do a get latest)

Mark

Nov 30, 2010 at 10:47 PM

That is wonderfull, just what I was looking for!

 

For another question, what would be the best approach to buffer the incomming data and then playing it?

 

I tried using a global memorystream as a stream source for the waveStream, and then simply write to the memorystream as data comes in through the network.

 

 private void audioReceive(IAsyncResult asyn)
        {
            int readBytes = 0;
            try
            {
                StateObject state = (StateObject)asyn.AsyncState;
                readBytes = state.getWorkSocket().EndReceive(asyn);
                audioBuffer.Write(state.getBuffer(), 0, readBytes);          // audioBuffer is the global memory stream
                audioBuffer.Position = 0;

                waveOut.Play();
                this.audioSocket.BeginReceive(state.getBuffer(), 0, state.getBufferSize(), SocketFlags.None, new AsyncCallback(audioReceive), state);

            }
            catch (Exception ez)
            {
                MessageBox.Show("audioReceive: " + this.textbox_nick.Text + "        " +ez.ToString());
            }
        }

 

I get very choppy, sporadic sound which is perfectly understandable considering I rewrite from offset 0 everytime data is received, it was just to test it actually plays something.

The problem is now, I am not sure how this coordination between the memorystream and the waveplayer works out. For example, what are the side effect of waveOut.Play() in terms of the read bytes in the stream? Say if the player plays up to 400 bytes out of 800, will the stream now be of length 400 or will the streampointer be at 400 out of 800? WIll the waveplayer 'pause' when the stream is empty, and then resume whenever it is filled?

 

Love your work, cheers!

Coordinator
Dec 1, 2010 at 6:07 AM

Try the BufferedWaveProvider, should do what you want:

http://naudio.codeplex.com/SourceControl/changeset/view/64392#1651306

Mark