|
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);
|