Product SiteDocumentation Site

11.3.9. Combining Audio; the Mix Class

One of the requirements of multi-channel audio is the ability to combine a large number of UGen's into a small number of channels - normally just two. The SuperCollider interpreter allows you to accomplish this in a number of ways, which are explained here.

11.3.9.1. The "Mix" Class

The "Mix" Class allows you to combine a mutli-channel Array into one channel. It's just that simple: you put in an Array of UGens, and out comes a single-channel combination of them.
Here are the two possible syntaxes for the "Mix" Class:

Mix.new(ArrayOfUGens);

and

Mix(ArrayOfUGens);

The second form is simply a short-hand version of the first. The Mix Class doesn't really create "Mix" Objects either - it's just a Function that combines many UGen's into one.
Here's an example of the "Mix" Class in action:
{
   Mix( [SinOsc.ar(220, 0, 0.1),
         SinOsc.ar(440, 0, 0.1),
         SinOsc.ar(660, 0, 0.1),
         SinOsc.ar(880, 0, 0.1),
         SinOsc.ar(850, 0, 0.1),
         SinOsc.ar(870, 0, 0.1),
         SinOsc.ar(880, 0, 0.1),
         SinOsc.ar(885, 0, 0.1),
         SinOsc.ar(890, 0, 0.1),
         SinOsc.ar(1000, 0, 0.1)] );
}.play;
Notice how all of these SinOscs are heard through the left channel only. The Mix class mixes all the UGen's together into one. You could use a bus to send the audio to both the left and right channels. What happens if we don't use the Mix class? Try to remove the function, and find out. You only hear some of the SinOsc's. Which ones? The first two, representing the left and right channels. If your audio interface has more than two channels, you may be able to hear more than those first two channels.
There is another function offered by the Mix class, and it is a kind of loop. The function is called Fill, and it takes two arguments: the number of times to run a function, and the function to run. The function is provided with one argument (like in a "do" loop), which is the number of times the function has already been run.
(
   var n = 8;
   var sineFunc =
   {
      arg iteration;

      var freq = 440 + iteration;
      SinOsc.ar( freq:freq, mul:1/n );
   };

   { Mix.fill( n, sineFunc ); }.play;
)
As you can see, the fill function itself is quite simple: you provide the number of UGen's to create, and a function that creates UGen's. It's the sineFunc function that is a little confusing. The argument is called "iteration", because it holds how many times the function has already been run - how many iterations have happened already. It uses this value to help calculate the frequency (stored in a variable called freq), and then creates a SinOsc UGen. The mul argument helps to automatically control the volume level. Since the total volume should be no more than 1.0, the sineFunc function calculates UGen's' volume by dividing 1, the maximum level, by the number of UGen's that will be created. The slowly pulsating volume is part of the acoustic result of this many frequencies being so close together - it is not a hidden effect by SuperCollider.