我用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));
}
请帮帮忙?我一直在努力解决这个问题..
提前致谢!
答案 0 :(得分:1)
我怀疑多次调用Waveout.Play()
是个问题。您只需要调用Play()
一次,然后将样本提供给源wave提供程序(您的BufferedWaveProvider
实例),库将负责其余部分。当wave提供程序为空时,WaveOut
对象将继续保持静默,直到您提供更多样本。
顺便说一句,这可以在一个线程中实现。创建WaveOut
实例,创建BufferedWaveProvider
作为样本缓冲区并将其设置为运行。然后,当音频数据可用时,您只需将数据添加到BufferedWaveProvider
即可播放。
BufferedWaveProvider
使用线程安全的内部缓冲区,因此如果您认为确实需要,可以安全地从其他线程添加。