• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Open source mixer AU proposal
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Open source mixer AU proposal


  • Subject: Re: Open source mixer AU proposal
  • From: James Chandler Jr <email@hidden>
  • Date: Fri, 8 Aug 2003 14:07:25 -0700

On Friday, August 8, 2003, at 08:13 AM, Robert Grant wrote:
What I'm looking for is a mixer that is somewhat akin to real-world mixers. I want:

Stereo/mono inputs
per input:
input gain fader
input balance/pan (balance for stereo, pan for mono)
send levels
pre/post fader switches for the sends (not essential but nice to have)
Some basic EQ (lo/mid/hi) would also be nice but not essential
multiple stereo effect send busses (say 4)
Effect Return busses if it's technically feasible (see below)
Stereo master out.

As I've demonstrated here many times I'm not talented enough to build this myself or even have much idea about how to get started. So I'm interested in working on a SourceForge type project with a BSD-type license (because I want to build commercial apps with it) with a few others - I'd probably be able to fill in some of the blanks :-). It wouldn't need a GUI I think because hosts would happily provide their own (especially if it is often coupled with the Stereo mixer).

Hi Robert

I'm very ignorant on CoreAudio, so far have only learned a bit about CoreMIDI. My suggestions might be entirely the wrong way on CoreAudio.

The way I do a Mixer on PC--

The lowest level is an assortment of asm tight loops for various mixing functions. Since PC (at least in our code) frequently uses interleaved stereo files, there are dedicated asm functions for MixMonoToMono, MixMonoToStereo (for mono tracks which must be panned into a stereo buss), MixStereoToStereo, etc. There are also special variants for various built-in format conversions, so 16 bit integer buffers can for instance be mixed to a float output buffer without the higher-level code having to make sure all the audio is in float format before entering the mixer.

Perhaps format conversions would be unnecessary in a CoreAudio implementation where all streams are assumed to be float... Similarly, perhaps interleaved stereo variants would be unnecessary if stereo is always handled in CoreAudio with a pair of Mono streams. Hey, already said I'm ignorant of CoreAudio!

One might write a single tight-loop asm buffer-mixing function that would handle all the possible format differences. Might be the desirable way to do it. My coworker who writes the audio sequencing code and the mixer outer loop, wanted separate lean-n-mean functions, so he could optimize at a higher level when feeding the mixer. Sometimes it isn't wise to put unnecessary conditionals in tight loops.

The low-level mix functions take pointers to input and output buffers, and left/right gain multipliers.

Our implementation uses two aux stereo busses and a stereo main mix buss, but one could fairly easily make a mixer object with arbitrary number of aux send/return and master outputs.

We have an object which maintains a graph of up to 4 audio plugins. The mixer object instantiates a four-filter graph object for each track, though if a graph doesn't contain any plugins it just passes the buffer from input to output without doing anything. EQ or any other plugin can be inserted in the graph slots. Each filtergraph object has provisions for mute/bypass, so individual plugins in each graph can be bypassed by the user without having to remove the plugin from the graph.

Aux returns and the Master output are treated like tracks, each with its own insert filtergraph. The Aux returns are mixed into the main output just like Tracks, except the input to the Aux insert filtergraphs comes from the aux busses. There is also an insert filtergraph on the master output buss, for global plugins like EQ or PeakLimit.

When we add softsynth plugin capability, we hope to mix them just like any other track, except the softsynth will just be the first plugin in a Track's insert filtergraph.

The mixer loop gets called to render each audio output buffer, after input track buffers have been fetched--

Here is possible simple pseudocode assuming stereo interleaved Tracks and an arbitrary number of Aux Busses. It would require added code to support solo/mute or whatever.

NumTrks = NumberOfInputTracks + NumberOfAuxReturns + 1;
//every slot in the mixer is a track, including Aux returns and Master out
MasterIndex = NumTrks - 1;
//array index of the master buss
//The mixer output is retrieved from TrkBuffer[MasterIndex]
Aux1Index = MasterIndex - NumberOfAuxReturns
//array index of the first Aux Return
Array of Track input audio buffers-- TrkBuffer[NumTrks]
Array of LeftGain[NumTrks] and RightGain[NumTrks]
//multiplier factors for track left/right gain
//Pan knobs are pre-calculated into LeftGain and RightGain values in the Mixer UI code
Array of AuxSendGain[NumberOfAuxReturns]
//Aux Send multiplier factors
Array of PostFaderBool[NumberOfInputTracks]
//True if Aux Send is PostFader, False if Aux Send is PreFader
Array of FilterGraphs-- FilterGraphArray[NumTrks]

for (Trk = Aux1Index; Trk <= MasterIndex; ++Trk)
{
ZeroTheTrack(TrkBuffer[Trk]);
//Fill mix destination buffers with zero
}
for (Trk = 0; Trk < NumTrks; ++Trk)
{
CallFilterGraph(FilterGraphArray[Trk], TrkBuffer[Trk], TrkBuffer[Trk])
//Call plugin insert chain, placing the filtergraph output back into TrkBuffer
MixStereoToStereo(TrkBuffer[Trk], TrkBuffer[MasterIndex], LeftGain[Trk], RightGain[Trk]);
//Mix the Track or Aux buffer into the master output
//if Trk == MasterIndex, it applies the final master gain slider to the output buss in-place
if (Trk >= Aux1Index) //Don't mix Aux back into Aux, or Master back into Master
continue;
for (i = Aux1Index; i < MasterIndex; ++i) //mix tracks to Aux Sends
{
if PostFaderBool[Trk] //PreFader patching
MixStereoToStereo(TrkBuffer[Trk], TrkBuffer[i], LeftGain[Trk] * AuxSendGain[i], RightGain[Trk] * AuxSendGain[i]);
else //PostFader patching
MixStereoToStereo(TrkBuffer[Trk], TrkBuffer[i], AuxSendGain[i], AuxSendGain[i]);
}
}

Conveniently ignoring the probable numerous logic mistakes, this will mix all the tracks to the master and aux busses.

The last few iterations apply insert effects to the aux busses, mix aux returns to the master, and finally the last iteration will apply master insert effects and then apply the master gain.

It seems like a lot of rigamarole to go thru. Perhaps there are simpler more efficient strategies. However, its amazing how well the code runs on a modestly-fast computer.

James Chandler Jr.
_______________________________________________
coreaudio-api mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/coreaudio-api
Do not post admin requests to the list. They will be ignored.

References: 
 >Open source mixer AU proposal (From: Robert Grant <email@hidden>)

  • Prev by Date: Re: SetParameter at note scope?
  • Next by Date: Re: ThreadSafe Note Scheduling Code (Was Re: Threading)
  • Previous by thread: Open source mixer AU proposal
  • Next by thread: Re: Open source mixer AU proposal
  • Index(es):
    • Date
    • Thread