Audio Delay Before Playback

I had a problem when the received audio data played stuttering, so I came up with the idea to linger a bit before it starts playing, so the application will have more time to collect audio sections before it starts playing. The idea is that it will play through the collected sound, as the rest comes to the application before it is needed.

//A raised event from a udp class when data is received (from it own thread)
void udpClient_DataReceived(byte[] bytes) 
{
    audioQueue.Enqueue (bytes); //ConcurrentQueue

    if (audioQueue.Count > 10 && !playing) { //count > 10 is about a one second delay
        playing = true;
        PlayQueue ();
    }
}

private void PlayQueue()
{
    byte[] a;
    while (audioQueue.Count > 0) {
        audioQueue.TryDequeue (out a);
        audIn.PlayAudio (a);
    }
    playing = false;
}

However, the code has 2 problems:

1) If the sound length is shorter than the set limit, it will not be played until more audio is collected. Therefore, I need some kind of delay that does not require a minimum amount of data to run it.

2) . while PlayQueue. , .

, , .

+4
2

, , ManualResetEvent AutoResetEvent, , Set Wait , .

/ Interlocked . , .

1 , .

    bool play = true; // global keep running flag.
    int m_numberOfSamples = 0;

    // Call this ONCE, at the start of your app.
    void Init()
    {
        // perform any initialization here... maybe allocate queue..
    }

    void EnqueueSample(byte[] bytes)
    {
        audioQueue.Enqueue(bytes); //ConcurrentQueue

        int numberOfSamples = Interlocked.Increment(ref m_numberOfSamples);
        if(numberOfSamples == 1)
        {
            // this is a case of first sample
            // Start a Task with a 1 sec delay
            Task.Factory.StartNew(() =>
                {
                    // Buffering...
                    // if you want to buffer x samples, use 1000*x/SampleRate instead of 1000 for 1 sec.
                    Task.Delay(1000).Wait();
                    PlayQueue();
                }, TaskCreationOptions.LongRunning);
        }
    }

    private void PlayQueue()
    {
        // if we are here, there is at least 1 sample already.
        byte[] a;
        int remainingSamples = 0;
        do
        {
            if (audioQueue.TryDequeue(out a))  // check if we succesfull got an array
            {
                audIn.PlayAudio(a);
                remainingSamples = Interlocked.Decrement(ref m_numberOfSamples);
            }
        }
        while (play && remainingSamples > 0);
        // we got out either by play = false or remainingSamples == 0
        // if remainingSamples == 0, we will get back here with a different **Task**
        // after a new sample has entered into the queue and again we buffer 1 sec using the Task.Delay
    }
+3

udpclient , . (ConcurrentQueue ) , , PlayQueue, , , udpclient. , TryDequeue.

, ConcurrentQueue EventwaitHandle, .

:

var mre = new ManualResetEvent(false);
Thread audio;
bool play = true; // global keep running flag.

// Call this ONCE, at the start of your app.
void Init()
{
    audio  = new Thread(PlayQueue);
    audio.Start();
}

void udpClient_DataReceived(byte[] bytes) 
{
    audioQueue.Enqueue (bytes); //ConcurrentQueue

    mre.Set(); // this signals that we have data

    // disbale the timer if the stream is done
    // and/or set play to false
    // based on bytes received in your byte array
}

private void PlayQueue()
{
    var aTimer = new System.Timers.Timer(1000); // play after 1 second
    var timeEvent = new ManualResetEvent(false);
    aTimer.Elapsed += (s,e) => { timeEvent.Set(); };  // the time will start the play
    byte[] a;
    mre.WaitOne();  // wait until there is data
    atimer.Enabled = true; // it will start playimg after 1000 miliseconds
    timeEvent.WaitOne(); // wait for the timer

    while (play) {
        if (audioQueue.TryDequeue (out a))  // check if we succesfull got an array
        {
           audIn.PlayAudio (a);
        }
    }
}

, . , , ...

+2

Source: https://habr.com/ru/post/1527167/


All Articles