Hi all,
I'm currently working on creating Mess, a Buzz-like software studio written in
C++ on Linux, and have run into a somewhat critical problem (note: this is my
first "real" audio app): I'm using PortAudio as audio API and it's
outputbuffer keeps underflowing because my callback function is too slow.
One of my goals is to enable the user to make a network of synths, samples,
effects,etc. ("machines" in Buzz-terminology). My initial idea for
implementing this was to associate a buffer and a process-function with each
machine. If the machine only generated sound, the process-function would
simply fill the buffer, if it was an effect the buffer would contain the
effect's input which would be consequently overwritten by the effect's
output. The MachineManager class contained a processChain-function which was
responsible for calling each machine's process-function in the right order
and copying and mixing the contents of the buffers according to the
connections in the network.
PortAudio's callback called the processChain-function and next copied the
contents of the master machine's buffer (the master represents the output in
the network) to PortAudio's outputbuffer.
As a test I made a simple sine tone generating machine and connected it to the
master. This resulted in some weird noises when using small buffers and in
clear sine tones with pauses inbetween when using very large buffers.
In an attempt to let the callback do less work, I made an extra thread
together with a set of two buffers with read/write flags, the idea being that
the thread continuously tried to fill the buffers with the write flag set,
using processChain (after this the buffer's flag would be set to 'read' ; if
there was nothing left to write the thread would go to sleep) and the
callback function given to PortAudio would check each time it ran for a
readable buffer and copy that to it's own outputbuffer (and setting the just
read buffer's flag to 'write', awakening the thread with processChain in it).
This again resulted in some weird noises (mostly due to thread scheduling not
quite going the way I expected).
The problem with my first method seems to be the copying of all the buffers
that makes the callback function too slow, but I don't immediately see any
other way of doing it (is there one?).
In retrospect the second way just seems wrong.
So my question right now is: how can I process a chain of machines in a fast
enough way?
Raf
Show replies by date