Product SiteDocumentation Site

11.4.3. Designing the First Part

  1. I started with something simple: a single SinOsc: {; }.play;
  2. This is not exciting: it just stays the same forever, and it only uses one channel! So, I added another SinOsc to the right channel, using the [ , ] array notation. The result is { [, ] }.play;
  3. Now it sounds balanced, at least, like it's coming from the middle. But it's still boring, so I added a frequency-changing SinOsc to the right channel, resulting in { [,,50,300)) ] }.play;
  4. Since that's difficult to read, and since I know that I'm just going to keep adding things, I expand the code a little bit to make it more legible. This gives me
       var left =;
       var right = 1, 50, 300 ) );
       [ left, right ]
    I define a variable holding everything I want in the left channel, then the same for the right. I still use the [ , ] array notation to create a stereo array. Remember that SuperCollider functions return the last value stated, so it might look like the stereo array is ignored, but because this array is what is returned by the function contained between { and }, it is this array that gets played by the following ".play;"
  5. I also added a frequency controller to the left SinOsc, and realized that it's getting a bit difficult to read again, especially if I wanted to add another parameter to the objects. So I placed the's into their own variables: frequencyL and frequencyR. This results in
       var frequencyL = freq:10, mul:200, add:400 );
       var frequencyR = freq:1, mul:50, add:150 );
       var left = frequencyL );
       var right = frequencyR );
       [ left, right ]
  6. Now I can experiment with the frequency-changing SinOsc's, to make sure that I get things just right. When I realize what the parameters do, I make a note for myself (see ""), so that it will be easy to adjust it later. I also explicitly call the parameters. This isn't necessary, but it also helps to avoid future confusion. Most programmers would not explicitly call the parameters, but we're musicians, not programmers.
  7. The left channel has something like a "melody," so I decided to add a drone-like SinOsc to it. This is easy, of course, because any SinOsc left alone is automatically a drone! But, where should it be added? Into the "left" variable, of course. We'll create an array using [ , ] array notation. There are two things that I would do at this point to help with future readability:
    1. Align all of the left-channel SinOsc's vertically (using tabs and spaces), so that each line is one sound-generating UGen.
    2. At the end of each line, write a small comment describing what the UGen on that line doesn.
  8. Now the volume is a problem. For most sound-producing UGen's, the "mul" argument controls the volume. For most of those, the default is "1.0," and anything greater will create distorted output. The physics and computer science factors that wind up creating distortion are rather complicated, and it isn't necessary to understand them. What we need to know is that, if the output of a UGen (or some UGen's) sounds distorted, then we should probably adjust the "mul" argument. Sometimes, of course, you may prefer that distorted output.
    • It seems that, when you're using multiple SinOsc's in one output channel, the "mul" of all of them must not add to more than 1.0
    • We're using two output channels (left and right). We'll leave the right channel alone for now, because it has only one output UGen.
    • So, I'll change add a "mul" argument to each of the left-channel UGen's, to 0.5
  9. Now we can't hear the left channel, because the right channel is too loud! Playing with volumes (sometimes called "adjusting levels" for computers) is a constant aesthetic concern for all musicians. Add a "mul" argument to the right channel, and set it to what seems an appropriate volume for the moment. It will probably change later, but that's okay.
  10. But let's add another dimension to this: there's no reason to keep the volume static, because we can use a SinOsc to change it periodically! I added a SinOsc variable called "volumeL," which I used as the argument to "mul" for the "frequencyL" SinOsc in the left channel.
  11. And now the sheer boredom of the drone in the left channel becomes obvious. I decide to make it more interesting by adding a series of overtones (an overtone is...). I decide to add six, then experiment with which frequencies to add. But, every time I adjust one frequency, I have to re-calculate and change all the others. So I decide to add a variable for the drone's frequency: "frequencyL_drone". This way, after finding the right intervals, I can easily adjust all of them just by changing the variable. I've decided on drone*1, 2, 5, 13, and 28. These are more or less arbitrary, and I arrived on them through experimentation. Of course, the drone will be way too loud.
  12. Writing [frequencyL_drone,2*frequencyL_drone,5*frequencyL_drone,13*frequencyL_drone,28*frequencyL_drone], mul:0.1 )
    in your program is not easy to read, and actually it doesn't work out volume-balance-wise (for me, at least): the high frequencies are too loud, and the lower ones are not loud enough. In retrospect, I should have created a variable for the "mul" of these drones, so I could adjust them easily in proportion. But, I didn't.
  13. A constant drone isn't as much fun as one that slowly changes over time. So, I changed the "frequencyL_drone" value to a UGen. Because it's supposed to be a "drone," it should change only very gradually, so I used a very small freqeuncy argument. It still moves quite quickly, but people won't want to listen to this too long, anyway!
  14. I did something similar with the right channel, addding a slowly-changing drone and overtones above it.
  15. After some final volume adjustments, I feel that I have completed the first part. There is no way to know for sure that you've finished until it happens. Even then, you may want to change your program later.