我使用從SharpDX樣品(https://github.com/sharpdx/SharpDX-Samples/blob/master/WindowsDesktop/XAudio2/AudioPlayerApp/AudioPlayer.cs)流的原則,在同一時間播放的幾種聲音。我如何可以同步2個Xaudio2流SourceVoices
我有同一首歌的多個版本的列表。我想在同一時間開始他們。我開始爲每首歌曲一個新的任務,我用CountDownEvent和ManualResetEvent的組合,以確保他們開始在同一時間:
在我準備緩衝區和信號CountDownEvent這首歌是準備上場的任務。然後歌曲等待ManualResetEvent的信號。當CountDownEvent具有從每個歌曲準備好信號時,它用信號通知的ManualResetEvent和SubmitSourceBuffer被調用。
9個10倍的歌曲開始樣品的同步(在歌曲之間沒有可檢測的相位,簡單地響亮),但有時是一個稍微偏離。
下面是一些代碼來闡述:
Task playingtask = Task.Factory.StartNew(() =>
{
int nextbuffer = 0;
long zeroticks = MasterClock.Elapsed.Ticks;
try
{
while (true)
{
if (oursong.ADecoder == null || oursong.Status == PlaybackStatus.Stop) { break; }
var sampleiterator = oursong.ADecoder.GetSamples(TimeSpan.FromTicks(oursong.Position)).GetEnumerator();
while (true)
{
if (oursong.ADecoder == null || oursong.Status == PlaybackStatus.Stop) { break; }
foreach (SourceVoice SVoice in oursong.SVoices)
{
while (SVoice.State.BuffersQueued == oursong.BufferRing.Length && oursong.ADecoder != null)
{
BufferEndEvent.WaitOne(1);
}
}
if (!sampleiterator.MoveNext())
{
break;
}
var bufferpointer = sampleiterator.Current;
if (bufferpointer.Size > oursong.MBufferRing[nextbuffer].Size)
{
if (oursong.MBufferRing[nextbuffer].Pointer != IntPtr.Zero)
{
SharpDX.Utilities.FreeMemory(oursong.MBufferRing[nextbuffer].Pointer);
}
oursong.MBufferRing[nextbuffer].Pointer = SharpDX.Utilities.AllocateMemory(bufferpointer.Size);
oursong.MBufferRing[nextbuffer].Size = bufferpointer.Size;
}
SharpDX.Utilities.CopyMemory(oursong.MBufferRing[nextbuffer].Pointer, bufferpointer.Pointer, bufferpointer.Size);
oursong.BufferRing[nextbuffer].AudioDataPointer = oursong.MBufferRing[nextbuffer].Pointer;
oursong.BufferRing[nextbuffer].AudioBytes = bufferpointer.Size;
if (oursong.Status == PlaybackStatus.Ready)
{
CountDownEvent.Signal();
SongManualResetEvent.WaitOne();
oursong.Status = PlaybackStatus.Start;
}
foreach (SourceVoice SVoice in oursong.SVoices)
{
SVoice.SubmitSourceBuffer(oursong.BufferRing[nextbuffer], null);
}
oursong.Position += MasterClock.Elapsed.Ticks - zeroticks;
zeroticks = MasterClock.Elapsed.Ticks;
nextbuffer = ++nextbuffer % oursong.BufferRing.Length;
}
}
}
finally
{
DisposeAudio(oursong);
oursong.Position = oursong.Start;
}
}, TaskCreationOptions.LongRunning);
旁註:我發送緩衝區爲每首歌曲到多個audiodevices,在相同的順序使用foreach語句每首歌曲。就緒狀態預先使用預置存儲器,音頻編碼器等的加載方法設置。
我知道可以使用操作集來同時啓動sourcevoices,但有另一種方法(使用時鐘或其他同步方法)確保每個播放歌曲同時發送樣本?