13 -Intervals, Multi-channel Expansion, "Quickie" Variables 

Pure20 musical intervals are ratios. An octave is 2:1. That is to say an octave above A 440 is 880. The octave above that is 1760. Interval inversions are reciprocals: an octave up is 2:1, so an octave down is 1:2. The intervals we use in western music come from the harmonic series, which are multiples of the fundamental. If the fundamental pitch (the pitch you hear) is 200 then the harmonic partials are 200, 400, 600, 800, 1000, and so on. The musical intervals they produce above the fundamental (the fundamental is the unison, or the pitch itself) are an octave, fifth, octave, third, fifth, seventh, octave, second, as illustrated in the chart below. 

Harmonic series 

Image of harmonic series in notation

C2 is the bottom pitch on the chart. The first fifth we encounter is G3, the third harmonic. In order to calculate a G2 (the fifth just above C2) you would multiply that frequency by 3 (G3) then divide by 2 to move down an octave to G2, or 3/2. Let's say C2 is 60 Hz (to make the math easy), C3 would be 120, G3 180, G2 would be one half that: 60 * 3 / 2 = 90. 

The fifth harmonic is the first major third in the series and is actually two octaves and a third (E4). To calculate a third above C2 (E2), first multiply by 5 to get E4, then divide by 2 for each octave down, a total of 4 for E2: 60 * 5 / 4 = 75. 

There are a couple tricks to memorizing interval ratios. An octave is 2:1, fifth is 3:2, fourth is 4:3, third is 5:4, minor third is 6:5, second is 9:8. Notice that all the numerators are one greater than the denominators. So if you can remember the sequence octave, fifth, fourth, third, minor third, and second, you can usually reconstruct the ratios (remember 9:8 for a second). Also, referring to the harmonic series above, note that the interval between harmonic 1 and 2 is an octave (2:1), between 2 and 3 is a fifth (3:2), between 3 and 4 a fourth (4:3), 4 and 5 a major third (5:4), 5 and 6 a minor third (6:5)… but then the system breaks 
down. What is the interval between 6 and 7? 7 and 8? Why don't we use them? Should we use them? Between 8 and 9 is the interval we use for a second (9:8). I'll leave it to you to discover the mystery of these extra intervals (just google microtuning, there is a healthy underground community). 

The patch below allows you to test different intervals. The r = 2/1 represents the ratio of the second frequency. If f = 400 and r = 2:1 ("two to one"), then f*r is 800, or 400 multiplied by 2 and divided by 1. Even though the division by 1 has no effect I express it this way so that you can try different ratios to see if they do indeed represent common intervals. Change the r value to 3/2 (a fifth), 4/3 (a fourth), 5/4, etc. Try 64/45 for a tritone. 

13.1. intervals (FSinOsc, scope, multi-channel) 

(
{
	f = 400; //fundamental
	r = 2/1; //ratio for second note in interval
	FSinOsc.ar([f, f*r], mul: 0.6)
}.scope(2)
)

The first argument for FSinOsc (fast sine oscillator) is not a single value but an array with variables. Remember that an array is a comma-separated list of values within brackets. When an array is used anywhere as an argument in a message SC expands the entire patch into two identical patches for each channel. It uses the first value of the array for the left channel and the second for the right. This wonderful feature is called multi-channel expansion. An array with more than two values will expand to more channels; as many as your hardware will handle. SC matches all the arrayed arguments, duplicating where necessary, to create parallel patches. 

13.2. multi-channel expansion 

//This code

(
{SinOsc.ar(
	LFNoise0.ar([10, 12, 14, 6], 400, [800, 1000]), 
	mul: [0.3, 0.5])}.scope(4)
)

//Becomes this in each channel:

(
//channel 1
{SinOsc.ar(
	LFNoise0.ar(10, 400, 800), 
	mul: 0.3)}.scope(1)
)

(
//channel 2
{SinOsc.ar(
	LFNoise0.ar(12, 400, 1000), 
	mul: 0.5)}.scope(1)
)

(
//channel 3
{SinOsc.ar(
	LFNoise0.ar(14, 400, 800), 
	mul: 0.3)}.scope(1)
)

(
//channel 4
{SinOsc.ar(
	LFNoise0.ar(6, 400, 1000), 
	mul: 0.5)}.scope(1)
)

Look at the interval patch once more. Because both frequencies are periodic, and are a mathematical ratio, the destructive and constructive points become an aggregate, and we "hear" the resulting pattern in the peaks and valleys. Here is the same example with a three channel arrayed expansion, one with the first frequency, one with the second, then the third with both added together. If you are playing back on two channels you will only hear 1 and 2. The third21 is just for analysis (though it would sound the same). Change the r = 2/1 to other ratios such as 3/2, 4/3, 5/4, 6/5, 9/8, etc. 

I'm using bus 3 for convenience in scope. It is connected to the audio input on most machines. This may cause interference with the wave. If so, set your audio input to line in and make sure nothing is connected. 

13.3. intervals 

(
{
	f = 400;	r = 2/1;
	a = FSinOsc.ar(f, 0.3);
	b = FSinOsc.ar(f*r, 0.3);
[a, b, a+b]*0.3
}.scope(3, zoom: 4)
)

In the past few patches you may have noticed I was able to use variables without declaring them. The letters a-z are automatically understood as variables by SC and are useful for quick experiments. Fair warning; you will regret using them instead of more meaningful names as your patch becomes more complex. 

Also notice that the last line of code in the function is simply the array of variables. A function "returns" the results of the last line of code regardless of what happened in the body of the function, as illustrated below. 

13.4. functions: last line is "returned" 

(
{
	a = FSinOsc.ar(200);
	b = FSinOsc.ar(1000);
	c = Pulse.ar(45);
	d = FSinOsc.ar(400);
c
}.scope(1)
)

Here are some screen shots that plot the wave forms of various intervals. The first is a fifth over one tenth of a second.  SC3 currently does not support plot. These examples were generated in SC2. 

There are lots of peaks and valleys in this example. The highest peaks and lowest valleys are where there is the greatest amount of constructive interference. The waves are adding together to push or pull farther. We hear the entire pattern as a fifth. Following are a fourth (4/3), third (5/4), minor sixth (8/5), and finally a tritone (64/45). 

With lower ratios there is more constructive interference, so fewer peaks and valleys. With high ratios there is more deconstructive interference and more peaks and valleys. Even with complex peaks and valleys we still hear the pattern. Dissonance and consonance are directly related and can be defined as the number of peaks in a pattern for a given amount of time, or the amount of time between the peaks that define the pattern. More peaks and valleys; higher dissonance. 

Our eyes (brains) recognize the pattern visually, and likewise our ears pick up on the aural pattern that results from the constructive and destructive interference. 

The next example illustrates this concept in another way. It allows you to move two pitches from low frequency to audio range. This way you can first hear the pattern as a set of clicks or pulses in low frequency. With a pulse or saw you hear a single click each period of the wave when the speaker pops back to its original position. (We hear the separate pulses as rhythmic patterns of 3/2, 4/3 etc.) Then as you move the mouse to the right, bringing the frequencies into audio range, you hear the resulting audio interval. First try running the line below to hear the difference between LFO and audio rates. Move the mouse all the way to the left for low frequency, to the right for audio frequency. 

13.5. audio frequencies (Saw, MouseX, kr, scope) 

{Saw.ar(MouseX.kr(1, 1200), 0.5)}.scope(1)

The patch below uses two frequencies defining an interval. I've set the ratio to 3:2 using upperRatio and lowerRatio. Change these to 2:1, 4:3, 5:4, etc. Try non-superparticular ratios such as 8:3, 7:2. Remember that the higher these two numbers are the more dissonant the interval will be. 

Listen to the pattern and look at the periods in the scope. Next move the mouse slowly to the 
right until the frequencies become pitches. Move all the way to the right to confirm that it is 
the interval you were trying for. 

13.6. ratios from LF to audio rate (scope, MouseX, LFSaw) 

(

{
var freq, ratioNum, ratioDenum; //declare two variables
ratioNum = 3; //assign numerator
ratioDenum = 2; //assign denominator
freq = MouseX.kr(1,440, warp: 1); //freq is mouse control
LFSaw.ar(
	[freq, freq*(ratioNum/ratioDenum)], 0, 
	0.3)
}.scope(2)
)

13. Exercises 

13.1. What is the 6th harmonic of a pitch at 200 Hz? 
13.2. What is the phase of the sine wave in channel 4?

SinOsc.ar([10, 15, 20, 25], [0, 1.25], 500, 600)

13.3. What value is returned from this function?
{a = 10; b= 15;c = 25;a =c + b;b =b +a; b}
13.4. At what frequency do humans perceive pitch? 
13.5. Arrange these frequencies from most consonant to most dissonant. 
180:160, 450:320, 600:400, 1200:600