network streaming

Apr 22, 2009 at 3:56 PM
Hello, everyone!
I am new to the N Audio project and kinda in a time-crisis so... can anyone help me understand how to play a sound that I receive over the network? I would be most satisfied to play it after it is fully received.

Please, pretty please!
Coordinator
May 14, 2009 at 5:58 PM

Hi there

It really depends what format the sound you are receiving over the network is in. Is it WAV, or a compressed format? NAudio can play sounds from any source, but eventually they have to turn into PCM. This is the hard part.

Mark

May 15, 2009 at 9:01 AM

Hello

Right now I have a WAV that i must play... and further more... it has to be streamed. As I  understand, the architecture of NAudio does not support streaming, so I started using DirectSound.

Thanks for the relpy, anyways

7Turturi

Coordinator
Jun 8, 2009 at 9:40 AM

NAudio does support streaming. The whole architecture is based on streams that are connected together in a graph. You derive from WaveStream and in the Read method simply provide data from the network source.

Mark

Sep 24, 2010 at 6:27 AM

Hi Mark,

Have you managed to write up a sample of how to stream audio over network using NAudio?

Cheers

Coordinator
Sep 27, 2010 at 10:43 AM

I'm afraid not.

Sep 28, 2010 at 4:36 AM

I have now got network streaming working... My initial problem was not reading the correct size chucnks of data from the stream before sending over the network.

This class must be added to NAudio:

using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Threading;

namespace NAudio.Wave {

class BufferedAudioStream {

private byte[] _buffer;
private int _position;

public BufferedAudioStream(byte[] buffer) {
_position = 0;
_buffer = buffer;
}

public byte[] Buffer {
get {
return _buffer;
}
}

public int Position {
get {
return _position;
}
set {
_position = value;
}
}
}

public class BufferedSampleStream : WaveStream {

private WaveFormat _waveformat;
private long _position;
private Queue<BufferedAudioStream> _sampQueue;

public BufferedSampleStream() {
_waveformat = new WaveFormat(44100, 2);
_position = 0;
_sampQueue = new Queue<BufferedAudioStream>();
}

public BufferedSampleStream(int rate, int channels) {
_waveformat = new WaveFormat(rate, channels);
_position = 0;
_sampQueue = new Queue<BufferedAudioStream>();
}

/// <summary>
/// Adds a byte[] array of PCM encoded samples to be streamed
/// </summary>
public void AddSamples(byte[] buffer, int offset, int count) {
byte[] nbuffer = new byte[count];
Buffer.BlockCopy(buffer, offset, nbuffer, 0, count);

lock (_sampQueue) {
_sampQueue.Enqueue(new BufferedAudioStream(nbuffer));
}
}

/// <summary>
/// We can read from this stream
/// </summary>
public override bool CanRead { get { return true; } }

/// <summary>
/// We can seek within this stream
/// </summary>
public override bool CanSeek { get { return false; } }

/// <summary>
/// We can't write to this stream
/// </summary>
public override bool CanWrite { get { return false; } }

public override WaveFormat WaveFormat {
get {
return _waveformat;
}
}

/// <summary>
/// An alternative way of repositioning.
/// See <see cref="Stream.Seek"/>
/// </summary>
public override long Seek(long offset, SeekOrigin origin) {
return Position;
}

public override long Length {
get { return long.MaxValue / 32; }
}

public override long Position {
get {
return _position;
}
set {
_position = value;
}
}

public override bool HasData(int count) {
// This buffered sample stream will always return some type of audio data
return true;
}

/// <summary>
/// Reads sample data from queued samples, if queue is empty generates silence
/// </summary>
public override int Read(byte[] buffer, int offset, int count) {
int read = 0;
while (read < count) {
int required = count - read;
if (_sampQueue.Count == 0) {
// Return a zero filled buffer
for (int n = 0; n < required; n++)
buffer[offset + n] = 0;

read += required;
else {
BufferedAudioStream sblock = (BufferedAudioStream)_sampQueue.Peek();

int nread = sblock.Buffer.Length - sblock.Position;

// If this buffer must be read in it's entirety
if (nread <= required) {
// Read entire buffer
Buffer.BlockCopy(sblock.Buffer, sblock.Position, buffer, offset + read, nread);
read += nread;

_sampQueue.Dequeue();

else // the number of bytes that can be read is greater than that required
                    {
Buffer.BlockCopy(sblock.Buffer, sblock.Position, buffer, offset + read, required);
sblock.Position += required;
read += required;
}
}

}

_position += read;

return read;
}

}

}

Server Side Code:

void PlayFile() {

string fileName = "c:\\temp\\Music\\1.mp3";
WaveStream mp3Reader = new Mp3FileReader(fileName);
WaveStream pcmStream = WaveFormatConversionStream.CreatePcmStream(mp3Reader);
WaveStream blockAlignedStream = new BlockAlignReductionStream(pcmStream);

int intSize = GetBlockSize(blockAlignedStream.WaveFormat,  200);
byte[] buffer = new byte[intSize];
while (true) {
int intOffset = 0;

int intRead = blockAlignedStream.Read(buffer, intOffset, intSize);
if (intRead == 0) {
break;
}

//SERVER: Code Send data over network
}
}
		private int GetBlockSize(NAudio.Wave.WaveFormat waveFormat, int intLatencyMS) {
int bytes = intLatencyMS * (waveFormat.AverageBytesPerSecond / 1000);
bytes -= bytes % waveFormat.BlockAlign;
return bytes;
}
Client Side Code:
//Init Sound Output
NAudio.Wave.BufferedSampleStream bufferedStream = new BufferedSampleStream();

waveOutDevice.Init(bufferedStream);
waveOutDevice.Play();
//When data is received from NetworkStream
bufferedStream.AddSamples(buffer, intOffset, intSize);
Coordinator
Sep 29, 2010 at 9:54 AM

cool, NAudio could do with something like this

Feb 6, 2013 at 11:02 AM
Edited Feb 6, 2013 at 11:04 AM
please send naudio practise sharp source code project in C# for FLAC file reader in my mail address sudip.deba@gmail.com
Coordinator
Feb 6, 2013 at 11:05 AM
NAudio and Practise Sharp are both open source projects. Click "Source Code" above to get the NAudio. To get practise sharp source code, go to its home page, and you can download the latest source from there.