Hi guys, I looking at reworking the mixer in a medium/large C++ application. Any pointer/opinions/theories on how this should be approached? (I know many of you have encountered the problem.)
In particular, I'm thinking about having a central Mixer object that the other parts of the application interface with. This Mixer object would own, maintain, send, return, and mix the buffers for everybody. For those wanting/needing more details... read on. APPLICATION ----------- The application is Composite (http://gabe.is-a-geek.org/composite/). It is intended to have DAW-like attributes... but is more along the lines of a sequencer. Mixing is currently implemented directly in the process() callback and inside the sampler.[1] RATIONALE --------- The Sampler currently has a pointer to a parent class Engine so that it can have access to the output buffers (currently tied to AudioOutput 'drivers'). I would like to make Sampler a more self-contained class. APPROACHES I'M CONSIDERING -------------------------- A. Create an abstract Mixer class. This class will manage the audio buffers, their connects, send/return, etc. The sampler class would, for instance, request from the Mixer a buffer allocation. On every process cycle, the Sampler would get a fresh copy of the buffer pointer. In this way, the Mixer could, if it wanted to, serve up the exact same pointer that jack_get_buffer() returns. B. Have Sampler own all its output buffers. Force other applications to query or connect to them in order to do mixing. An example of this approach would be the LV2 amp example.[2] However, with this approach I'm concerned that I won't be able to avoid buffer thrashing. THINGS I'VE SEEN ELSEWHERE -------------------------- Most applications I've looked at have a very de-centralized approch. If you are the author of one of these -- forgive me if I've failed to grok your code! :-) * Ingen handles mixing as a feature of a "connection." It also appears that gain has to be handled elsewhere (like an amplifier insert.) However, in Composite I'd like to avoid setting up an arb. connection framework at this stage. * Ardour appears to handle channel gain internal to each channel/buffer object. The output mix-downs are more or less handled directly in the process() callback.[3] * Non-daw appears to handle it similar to Ardour. * All of them, at the core, implement the mixing as some manner of basic function... like a specialized memcpy(). * All of them implement SSE optimizations in mixing, or at least have them on their TO-DO list. Any thoughts or comments are appreciated! Thanks, Gabriel [1] If digging in the code, it's roughly at: src/Tritium/src/EnginePrivate.cpp:438 src/Tritium/src/Sampler.cpp:419 src/Tritium/src/Sampler.cpp:598 Current git revision cfebf2058... [2] http://lv2plug.in/plugins/Amp-example.lv2/ [3] See, e.g. AudioTrack::roll() in libs/ardour/audio_track.cc _______________________________________________ Linux-audio-dev mailing list [email protected] http://lists.linuxaudio.org/listinfo/linux-audio-dev
