[LAD] Advice wanted: Mixing in a large application

From: Gabriel M. Beddingfield <gabrbedd@email-addr-hidden>
Date: Fri Feb 05 2010 - 20:56:08 EET

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
Linux-audio-dev@email-addr-hidden
http://lists.linuxaudio.org/listinfo/linux-audio-dev
Received on Sat Feb 6 00:15:03 2010

This archive was generated by hypermail 2.1.8 : Sat Feb 06 2010 - 00:15:03 EET