[Csnd] OT: canonical way of doing audio IO with portaudio in big systems
Date | 2012-05-12 19:01 |
From | Anton Kholomiov |
Subject | [Csnd] OT: canonical way of doing audio IO with portaudio in big systems |
It's not a csound question, but I know that there are many audio dsp developers on this forum, so here I ask for some help with portaudio. There are unit generators. They process buffers and I can link them in graph. I can invoke tick function that executes all ugens from sources to sinks. The thing I can not understand: how can I put portaudio in this picture. Portaudio fetches audio samples in callback function, it is called by some external process. I can imagine two ways of doing things: 1) call tick-function in callback (but if there are many portaudio-sinks) 2) portaudio sink-ugen is writing to buffer and callback function reads the buffer. But how can I do it properly? I have seen only toy portaudio examples (2-4 ugens in graph), but how can one use portaudio in big systems? or maybe you can tell me how csound is doing these things. Or maybe you can point out some resources that discuss this topic (possible caveats). Anton |
Date | 2012-05-12 20:51 |
From | Michael Gogins |
Subject | Re: [Csnd] OT: canonical way of doing audio IO with portaudio in big systems |
Conceptually, a signal flow graph consists of nodes that process signals, connected by directed edges that transfer signals from node to node. In the general case, these edges are not necessarily signal buffers, they are first-in, first-out queues of "tokens" which might be signals, buffers of signals, or whatever. In Csound, there is always one audio signal buffer at each end of each audio signal edge, and there is always one control signal sample at each end of each control signal edge. So, queues as such are not needed internally to Csound. Each "queue" is always just one buffer of the right size. So, how does this work with PortAudio? Csound uses PortAudio's callback mode. Csound is processing its graph in its thread, and the PortAudio callback is firing in its thread. The two threads are synchronized with two locks. It is a "tick-tock" system. Tick - Csound produces the PortAudio buffer, unlocks the PortAudio lock, and waits on the Csound lock. Tock - the PortAudio callback consumes the PortAudio buffer, unlocks the Csound lock, and waits on the PortAudio lock. Tick, tock, tick, tock, tick, tock... until Csound is done and closes the PortAudio stream. There is no reason this should not work with any number of PortAudio nodes in the graph, but only if only one of them ever says Tock, and only if all of the PortAudio nodes stay in sync with each other. Hope this helps, Mike On Sat, May 12, 2012 at 2:01 PM, Anton Kholomiov |