2014-12-19 23 views
0

我使用從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,但有另一種方法(使用時鐘或其他同步方法)確保每個播放歌曲同時發送樣本?

回答