1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
|
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;
}
}
} |
Partager