私有方法區域
#region 私有方法
private void InitNotifications()
{
notifyThread = new Thread(NotifyThreadHandler);
isRunning = true;
notifyThread.IsBackground = true;
notifyThread.Start();
notificationEvent = new AutoResetEvent(false);
notify = new Notify(m_Buffer);
// 緩衝區切 4 段,每播放 1/4 發送訊號
for (int i = 0; i < 4; i++)
{
positionNotify[i].Offset = ((notifySize * (i + 1)) - 1);
positionNotify[i].EventNotifyHandle = notificationEvent.SafeWaitHandle.DangerousGetHandle();
}
notify.SetNotificationPositions(positionNotify, 4);
nextWriteOffset = 0;
}
private void NotifyThreadHandler()
{
while (isRunning)
{
try
{
notificationEvent.WaitOne(-1, true);
Play();
}
catch (Exception) { }
}
}
private void Play()
{
try
{
int currentPlayPosition, currentWritePosition;
m_Buffer.GetCurrentPosition(out currentPlayPosition, out currentWritePosition);
int lockSize = currentWritePosition - nextWriteOffset;
if (lockSize < 0) lockSize += m_BufferBytes; // 環狀回繞
lockSize -= lockSize % notifySize; // 對齊通知粒度
if (lockSize != 0)
{
byte[] data = new byte[lockSize];
if (circularBuffer.Read(data) > 0)
{
m_Buffer.Write(nextWriteOffset, data, LockFlag.None);
nextWriteOffset = (nextWriteOffset + lockSize) % m_BufferBytes;
}
}
}
catch (Exception) { }
finally { }
}
#endregion
核心邏輯解析
- 通知機制:
AutoResetEvent + Notify 讓背景執行緒在播放位置到達特定點時喚醒。
- 環狀寫入:計算可寫區塊大小、對齊、從
circularBuffer 讀取資料寫入 SecondaryBuffer,寫入指標模運算回繞。
- Looping 播放:
m_Buffer.Play(0, BufferPlayFlags.Looping) 使緩衝區循環播放,寫入指標歸零即無縫銜接。