2014-03-05 3 views
3

나는 4 개의 소리를 서로 연주 (sounds1-> sound2-> sound3)하고 싶지만 각 연주 중에 또는 각 소리가 끝날 때까지 기다리지 않고 내 코드의 흐름을 멈추지 않는다.사운드를 비동기식으로 재생하는 방법은 있지만 대기열에있는 소리는 어떻게 재생합니까?

나는 이것을 거의 모든 곳에서 찾았지 만 내가 읽은 모든 방향은 다른 문제에 갇혀있다.

내 최고의 내기는 지금까지 : System.Media에서 이미 사용한 SoundPlayer를 사용하고 자체 대기열 기능을 만들지 만 Soundplayer에는 "완료된 재생"이벤트가 없으므로 언제 시작할지 알 수 없습니다. 다음 소리. (정말로, Microsoft?)

다른 해결책과 문제점 : DirectSound는 .NET (C#)에서 작동하려면 복잡해 보입니다. Win Playsound는 대기열에 들어갈 수 없기 때문에 실제로 도움이되지 않습니다.

+2

백그라운드 스레드에서 'PlaySync()'를 호출 할 수 있습니다. – SLaks

+0

NAudio는'PlaybackStopped' 이벤트를 가지고 있습니다 ... 또한 내장 큐를 가질 수도 있습니다; 나는 그것에 익숙하지 않다. –

답변

3

외부의 스레드에서 PlaySync를 사용할 수 있습니다 (예 : 백그라운드 스레드). 일부 사람들은 주석을 달았습니다. 여기

이 (검증되지 않은) 샘플입니다 스레드 당신이 사용할 수있는 큐
* 과 외부 스레드 안전 *의 BlockingCollection을 사용

당신은 당신의 자신의 수업을 할 수 있습니다

또는 사운드가 끝날 때마다 이벤트를 발생시키는 메소드. 또는 PlaySync가 대기 상태가되기 때문에 스레드의 큐를 반복 할 수 있습니다.

using System.Threading; 
using System.Collections.Concurrent; 
namespace PlaySound 
{ 
    public partial class Form1 : Form 
    { 
     private Thread soundPlayThread; 
     private BlockingCollection<string> speakQueue = new BlockingCollection<string>(); 
     private CancellationTokenSource cancelSoundPlay; 
     private int soundPlayCount = 0; 

     public Form1() 
     { 
      InitializeComponent(); 
      cancelSoundPlay = new CancellationTokenSource(); 
     } 

     private void btnStartSoundPlay_Click(object sender, EventArgs e) 
     { 
      StartSoundPlay(); 
     } 

     private void btnStopSoundPlay_Click(object sender, EventArgs e) 
     { 
      cancelSoundPlay.Cancel(); 
      Console.WriteLine("Sound play cancelled."); 
     } 

     private void btnAddToQueue_Click(object sender, EventArgs e) 
     { 
      speakQueue.Add("MyFile.wav"); 
     } 

     private void queueAndPlay(string loc) 
     { 
      if (!File.Exists(loc=loc+".wav")) 
       loc=configPath+"soundnotfound.wav"; 
      speakQueue.Add(loc); 
      StartSoundPlay(); 
     } 


     private void StartSoundPlay() 
     { 
      //Sound Player Loop Thread 
      if (this.soundPlayThread == null || !this.soundPlayThread.IsAlive) 
      { 
       this.soundPlayThread = new Thread(SoundPlayerLoop); 
       this.soundPlayThread.Name = "SoundPlayerLoop"; 
       this.soundPlayThread.IsBackground = true; 
       this.soundPlayThread.Start(); 
       Console.WriteLine("Sound play started"); 
      } 
     } 
     //Method that the outside thread will use outside the thread of this class 
     private void SoundPlayerLoop() 
     { 
      var sound = new SoundPlayer(); 
      foreach (String soundToPlay in this.speakQueue.GetConsumingEnumerable(cancelSoundPlay.Token)) 
      { 
       //http://msdn.microsoft.com/en-us/library/system.media.soundplayer.playsync.aspx 
       speaker.SoundLocation=soundToPlay; 
       //Here the outside thread waits for the following play to end before continuing. 
       sound.PlaySync(); 
       soundPlayCount++; 
       Console.WriteLine("Sound play end. Count: " + soundPlayCount); 
      } 
     } 
    } 
} 
관련 문제