SharpDX 샘플 (https://github.com/sharpdx/SharpDX-Samples/blob/master/WindowsDesktop/XAudio2/AudioPlayerApp/AudioPlayer.cs)의 스트리밍 원칙을 사용하여 동시에 여러 사운드를 재생하고 있습니다.두 개의 Xaudio2 스트리밍 소스 코드를 동기화하는 방법
동일한 노래의 여러 버전 목록이 있습니다. 나는 그들을 정확히 같은 시간에 시작하고 싶다. 각 노래에 대해 새로운 작업을 시작하고 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);
(!) 참고 : 여기에
정교 몇 가지 코드 나는 foreach는 문을 사용하여 각 노래에 대해 동일한 순서로, 여러 audiodevices에 각 노래에 대한 버퍼를 보낼 수 있습니다. 준비 상태는 메모리, 오디오 코드 등을 미리 설정하는로드 방법을 사용하여 미리 설정됩니다.작업 세트를 동시에 사용하여 소스 보이스를 시작할 수 있다는 것을 알고 있지만 다른 방법으로 (시계 또는 다른 동기화 방법 사용) 샘플이 각 연주 곡에 대해 동시에 전송되는지 확인하십시오.