Sign in to follow this  
Erakis

DirectSound Network player

Recommended Posts

Hi, I have a UDP server receiving about 10 000 bytes per second. Wav sound format is (8000hz, 16bits, 1 channel). Using DirectSound I would like to create a player to play this data. Sometime, is it possible that server doesn't receive data for a couple a seconde and the player must no crash for that reason. However, I did not found any good exemple to help me. Thank

Share this post


Link to post
Share on other sites
Hi,

Using the Microsoft SDK sample (CaptureSound), I have now done an implementation of what I need. But there is a problem when playing data from the stream. Sounds like the buffer isn't filled correctly, size or time, don't know... Here is the code :


public class StreamPlayer
{
public const int NumberPlayNotifications = 16;
private SecondaryBuffer m_PlayBuffer = null;
private WaveFormat m_WaveFormat;
private BufferDescription m_PlayBufferDescription;
private AutoResetEvent m_NotificationEvent = null;
private BufferPositionNotify[] m_PositionNotify = new BufferPositionNotify[NumberPlayNotifications + 1];
private Thread m_NotifyThread = null;
private Notify m_ApplicationNotify = null;
private int m_PlayBufferSize = 0;
private int m_NextPlayOffset = 0;
private int m_NotifySize = 0;
private int m_SampleCount = 0;
private Device m_SoundDevice;
private bool m_Playing = false;

// File to play
private FileStream m_FileStream = null;

// Constructor
public StreamPlayer( Control owner )
{
m_SoundDevice = new Device();
m_SoundDevice.SetCooperativeLevel(owner, CooperativeLevel.Normal);

// Define the format for the raw waveform data.
m_WaveFormat = new WaveFormat();
m_WaveFormat.SamplesPerSecond = 8000;
m_WaveFormat.BitsPerSample = 16;
m_WaveFormat.Channels = 1;
m_WaveFormat.FormatTag = WaveFormatTag.Pcm;
m_WaveFormat.BlockAlign = (short)(m_WaveFormat.Channels * (m_WaveFormat.BitsPerSample / 8));
m_WaveFormat.AverageBytesPerSecond = m_WaveFormat.SamplesPerSecond * m_WaveFormat.BlockAlign;

// Sound buffer description
m_PlayBufferDescription = new BufferDescription(m_WaveFormat);

// Load wav file (hard coded here to test class)
m_FileStream = new FileStream("Test.riff", FileMode.Open, FileAccess.Read);
}

// Create capture buffer
private void CreatePlayerBuffer()
{
// Free ressource
if (m_ApplicationNotify != null)
{
m_ApplicationNotify.Dispose();
m_ApplicationNotify = null;
}
if (m_PlayBuffer != null)
{
m_PlayBuffer.Dispose();
m_PlayBuffer = null;
}

// Set the notification size
m_NotifySize = (1024 > m_WaveFormat.AverageBytesPerSecond / 8) ? 1024 : (m_WaveFormat.AverageBytesPerSecond / 8);
m_NotifySize -= m_NotifySize % m_WaveFormat.BlockAlign;

// Set the buffer sizes
m_PlayBufferDescription.BufferBytes = m_PlayBufferSize = (m_NotifySize * NumberPlayNotifications);
m_PlayBufferDescription.ControlVolume = true;
m_PlayBufferDescription.GlobalFocus = true;
m_PlayBufferDescription.ControlPositionNotify = true;

// Create the actual sound buffer; the heart of the streaming sound features.
m_PlayBuffer = new SecondaryBuffer(m_PlayBufferDescription, m_SoundDevice);

// Play buffer is set to 0
m_NextPlayOffset = 0;

// Init notifications
InitNotifications();
}

// Init notifications
private void InitNotifications()
{
// Create a thread to monitor the notify events
if (m_NotifyThread == null)
{
m_NotifyThread = new Thread(new ThreadStart(WaitThread));
m_Playing = true;
m_NotifyThread.Start();

// Create a notification event, for when the sound stops playing
m_NotificationEvent = new AutoResetEvent(false);
}

// Setup the notification positions
for (int i = 0; i < NumberPlayNotifications; i++)
{
m_PositionNotify[i].Offset = (m_NotifySize * i) + m_NotifySize - 1;
m_PositionNotify[i].EventNotifyHandle = m_NotificationEvent.Handle;
}
m_ApplicationNotify = new Notify( m_PlayBuffer );
m_ApplicationNotify.SetNotificationPositions(m_PositionNotify, NumberPlayNotifications);
}

// Wait thread (waiting for notification)
private void WaitThread()
{
// Start playing buffer content now
this.m_PlayBuffer.Play(0, BufferPlayFlags.Looping);

// Wait for notification
while (m_Playing)
{
// Sit here and wait for a message to arrive
m_NotificationEvent.WaitOne(Timeout.Infinite, true);
FillBuffer();
}
}

/// Fill buffer on notification
private void FillBuffer()
{
try
{
// Read n data in file stream
byte[] playData = null;
int fileStreamLength = (int)m_FileStream.Length;
if (m_SampleCount >= fileStreamLength)
{
// Sound has been sucessfully played
m_Playing = false;
return;
}
else if ((m_SampleCount + m_NotifySize) <= fileStreamLength)
{
// Fill playing buffer with n data from file stream
m_FileStream.Seek(m_SampleCount, SeekOrigin.Current);
playData = new byte[m_NotifySize];
m_FileStream.Read(playData, 0, m_NotifySize);
m_PlayBuffer.Write(m_NextPlayOffset, playData, LockFlag.None);
m_SampleCount += playData.Length;
m_NextPlayOffset += playData.Length;
}
else if ((m_SampleCount + m_NotifySize) > fileStreamLength)
{
// Fill playing buffer with lefting data from file stream
m_FileStream.Seek(m_SampleCount, SeekOrigin.Current);
playData = new byte[m_NotifySize];
int byteLefting = fileStreamLength - m_SampleCount;
m_FileStream.Read(playData, 0, byteLefting);
m_PlayBuffer.Write(m_NextPlayOffset, playData, LockFlag.None);
m_SampleCount += byteLefting;
m_NextPlayOffset += byteLefting;
}

// Circular buffer
m_NextPlayOffset %= m_PlayBufferSize;
}
catch (Exception e)
{
System.Console.WriteLine("StreamPlayer : FillBuffer (" + e.ToString() + ")");
}

}

// Start playing
public void StartPlaying()
{
CreatePlayerBuffer();
}

// Stop playing
public void StopPlaying()
{
this.m_Playing = false;
if (m_PlayBuffer != null)
{
m_PlayBuffer.Stop();
m_PlayBuffer = null;
}
}
}


The song is playing but it seem to be play to much faster or something else. Or maybe I did something wrong. The WAV file "Test.riff" was make using SoundRec32 with (8000hz, 16bit, 1 channel) format. After that I open it with UltraEdit and I removed the wav riff header just to keep the essential (DATA) ;)

Thank to help me.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this