Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ for loop too slow

I'm trying to make an audio application with PortAudio. My callback function has been very slow and it has been creating constant underruns. I removed everything in the callback one by one until I found the issue: the for loop. I removed everything so that the only thing happening in the callback function is the for loop and it is still causing underruns. I know it is the for loop because when I reduce the number of iterations, the underruns go away.

static int patestCallback(const void *inputBuffer, void *outputBuffer,
                      unsigned long framesPerBuffer,
                      const PaStreamCallbackTimeInfo *timeInfo,
                      PaStreamCallbackFlags statusFlags, void *userData)
{
    int x = 0;
    for (int jj = 0; jj < 10000; jj++)
    {
        x++; // for testing, not actually used
    };
    return paContinue;
}

Here is my full code for testing: https://gist.github.com/johnroper100/b87641f5609dbb49bc3c1121b1f4daf1

Not really necessary for this question, but I did the same callback in the python equivalent (sounddevice) and there are no issues.

like image 486
John Roper Avatar asked Jul 03 '26 05:07

John Roper


2 Answers

From the API documentation:

When a stream is running, PortAudio calls the stream callback periodically. The callback function is responsible for processing buffers of audio samples passed via the input and output parameters.

The PortAudio stream callback runs at very high or real-time priority. It is required to consistently meet its time deadlines. Do not allocate memory, access the file system, call library functions or call other functions from the stream callback that may block or take an unpredictable amount of time to complete.

In order for a stream to maintain glitch-free operation the callback must consume and return audio data faster than it is recorded and/or played. PortAudio anticipates that each callback invocation may execute for a duration approaching the duration of frameCount audio frames at the stream sample rate. It is reasonable to expect to be able to utilise 70% or more of the available CPU time in the PortAudio callback. However, due to buffer size adaption and other factors, not all host APIs are able to guarantee audio stability under heavy CPU load with arbitrary fixed callback buffer sizes. When high callback CPU utilisation is required the most robust behavior can be achieved by using paFramesPerBufferUnspecified as the Pa_OpenStream() framesPerBuffer parameter.

I highlighted the relevant part.

like image 109
Adam Hunyadi Avatar answered Jul 05 '26 18:07

Adam Hunyadi


A for loop with nothing in it is still hard work for you CPU.

If you don't want your CPU spending all its power on that for loop you should at least make that for loop contain something that gives up CPU cycles.

The simplest way would be to put a call to sleep() or nanosleep() in there.

More advanced would be to use threads with the proper mechanisms to make them wait for the required actions.

like image 34
Brecht Sanders Avatar answered Jul 05 '26 17:07

Brecht Sanders



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!