I am writing a program that uses PortAudio to get audio input from the computer into my program. PortAudio, in their Writing a Callback tutorial, says that the callback is triggered as an Interrupt Handler, and explains that code written in the callback needs to not do:
memory allocation/deallocation, I/O (including file I/O as well as console I/O, such as printf()), context switching (such as exec() or yield()), mutex operations, or anything else that might rely on the OS
The problem I'm having is figuring out how would I go about processing the audio coming from the callback without being able to use malloc. My current (and working) callback looks like this.
int Audio::paCallback( const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void *userData ) {
// Cast data passed through stream to our structure.
auto *in = (uint16_t *) inputBuffer;
// Get number of audio channels, for instance stereo would be two
int numberOfChannels = Pa_GetDeviceInfo(Pa_GetDefaultOutputDevice())->maxInputChannels;
for (int i = 0; i < numberOfChannels; i++) {
auto storedStream = (uint16_t *) malloc(sizeof(uint16_t) * (framesPerBuffer + 2));
storedStream[0] = uint16_t(i);
storedStream[1] = uint16_t(framesPerBuffer);
for (int j = 0; j < storedStream[1]; j++) {
storedStream[j + 2] = in[numberOfChannels*j+i];
}
audioQueue->push(&storedStream);
}
return 0;
}
I know I shouldn't be using malloc, so how would I go about fixing this?
While looking for examples of code, I found that Audacity, a free audio editing software, uses PortAudio. I have looked at Audacity's PortAudio callback (line 2391 in AudioIO.cpp), and all they do is call two functions. In the second function, they call alloca, which allocates memory.
Is it ok to call functions from an interrupt handler that then do memory allocation, or would the functions also be executed within the interrupt context?