Question

I am writing in C#.

I have a Real-Time audio player that plays incoming voice from IP Phone. I have a byte[] Array which gets all the voice-bytes when it comes in, and when the user presses the PLAY button, I start playing it. I also have STOP and PAUSE buttons. I am using NAudio for this, BufferedWaveProvider and Waveout Classes.

CODE IN PLAYER CLASS:

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();
}

the _state is for the State of the call (PLAYING, STOPPED, PAUSED). As you can see, When PLAY is pressed, It keeps playing until STOP/PAUSED is pressed, then it breaks. (the WHILE Loop).

My problem is after I press the buttons a little bit, at some point The Waveout.PLAY doesn't work anymore and therefore the BufferedWaveProvider is getting full and crashes. (it happens sometime after two clicks, and sometimes after 10, changing).

I think it has something to do with the way I am calling the methods. Maybe some mix-up with Threads/Tasks, or not making sure one of the methods is over.. it's like this:

CODE ON THE VIEW-MODEL:

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));
}

Help Please? I have been struggling with this for a long time..

Thanks in advance!

Was it helpful?

Solution

I suspect that calling Waveout.Play() multiple times is the problem. You only need to call Play() once, then feed samples into the source wave provider (your BufferedWaveProvider instance) and the library will take care of the rest. When the wave provider is empty the WaveOut object will continue to play silence until you provide more samples.

This can all be achieved in a single thread, incidentally. Create the WaveOut instance, create a BufferedWaveProvider as a sample buffer and set it running. Then when the audio data is available all you have to do is add the data to the BufferedWaveProvider and it will be played.

The BufferedWaveProvider uses a thread-safe internal buffer, so it's safe to add from a different thread if you feel that you really need to do so.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top