使用任务或其他?

时间:2014-03-24 06:34:48

标签: c# real-time voip naudio

我用C#写作。

我有一个实时音频播放器,播放来自IP电话的传入语音。我有一个byte[] Array来获取所有语音字节,当用户按下PLAY按钮时,我开始播放它。我也有STOP和PAUSE按钮。我正在使用NAudio,BufferedWaveProvider和Waveout Classes。

球员类代码:

public void PlayCall(Call call)
{
         byte[] mixedBuffer = new byte[320];
         while (call.PlayerIndex < call.AudioArray.Length) // The AudioArray keeps getting bigger
         {
             if (_state == PlayerState.PAUSED || _state == PlayerState.STOPPED)
             // either STOP or PAUSE button is clicked
                  break;
             for (int i = 0; i < 320; i++)
             {
                  mixedBuffer[i] = (byte)(call.AudioArray[call.PlayerIndex + i];
             }
             call.PlayerIndex += 320;
             Thread.Sleep(20); // This is in order to synchronize the receiving and playing of the packets. 
             try
             {
                  AddSamples(mixedBuffer);
                  Waveout.Play();
             }
             catch (InvalidOperationException ex)
             {
                  _bufferedWaveProvider.ClearBuffer();

             }
             finally
             {
                  ClearByteArray(ref mixedBuffer);
             }
         }
}

public void StopCall(Call call)
{        
    _state = PalyerState.STOPPED;
    call.PlayerIndex=0;
    Waveout.Stop();
}

public void PauseCall(Call call)
{
    _state = PlayerState.PAUSED;
    Waveout.Pause();
}

_state用于通话状态(播放,停止,暂停)。 正如您所看到的,当按下PLAY时,它会一直播放,直到按下STOP / PAUSED,然后它会中断。 (WHILE循环)。

我的问题是在我按下按钮后,某些时候Waveout.PLAY不再工作,因此BufferedWaveProvider正在变满并崩溃。 (它发生在两次点击之后的某个时间,有时在10次之后发生变化)。

我认为这与我调用方法的方式有关。也许有些与Threads / Tasks混淆,或者没有确定其中一种方法结束了......它是这样的:

观点模型的代码:

private void ExecutePlayCallMethod(Call call)
{
    call.Player.State = PlayerState.PLAYING;
    Task.Run(() => call.Player.PlayCall(call)); // 
}

private void ExecutePauseCallMethod(CAll call)
{
    Task.Run(() => call.Player.PauseCall(call));
    call.Player.State = PlayerState.PAUSED;
}

private void ExecuteStopCallMethod(Call call)
{
    call.Player.State = PlayerState.STOPPED;
    Task.Run(() => call.Player.StopCall(call));
}

请帮帮忙?我一直在努力解决这个问题..

提前致谢!

1 个答案:

答案 0 :(得分:1)

我怀疑多次调用Waveout.Play()是个问题。您只需要调用Play()一次,然后将样本提供给源wave提供程序(您的BufferedWaveProvider实例),库将负责其余部分。当wave提供程序为空时,WaveOut对象将继续保持静默,直到您提供更多样本。

顺便说一句,这可以在一个线程中实现。创建WaveOut实例,创建BufferedWaveProvider作为样本缓冲区并将其设置为运行。然后,当音频数据可用时,您只需将数据添加到BufferedWaveProvider即可播放。

BufferedWaveProvider使用线程安全的内部缓冲区,因此如果您认为确实需要,可以安全地从其他线程添加。