In this lesson, you will expand on the Theremin you built in lesson 1 by adding vibrato as a parameter that you can control with the Gametrak, adding a second voice, and adding distortion that increases with the volume.
Polyphony, encapsulation, abstraction, reuse, parameters.
[patcher ], [tanh~ ] , [times~ ] , [plus~ ]
Vibrato is an expressive musical device that is created by slowly oscillating the pitch being played (Theremin virtuoso Clara Rockmore (1911-98) was famous for her beautiful vibrato). Of course, you can add vibrato by simply shaking the part of the Gametrak that controls the frequency of our Theremin, but since it takes many years of practice to be able to control smooth, even vibrato, we’ll extend our patch to do it for us.
The [vib~ ] object takes two parameters (see the help file for a demonstration): (1) the frequency in Hz around which the output will oscillate (left inlet), and (2) a parameter between 0–1 that controls both the speed and depth of the oscillation (right inlet).
We’ll wire the [vib~ ] object in between the [sinewave~ ] and [gain~ ] objects and control the speed and depth of the oscillation using the Gametrak.
Now our Theremin has three parameters that we are controlling with the Gametrak, but we’re not making very efficient use of our controller. In this section, we’ll remap the three parameters of the Theremin to the left joystick and make a copy of the instrument that we can control with the right joystick.
Gametrak parameter | Theremin parameter |
/x | frequency |
/y | vibrato |
/z | gain |
Since we had been controlling the frequency with the /z parameter which has a range of 0–1 and we will now be controlling the frequency with the /x parameter which has a range of -1–1, we will need to change the arguments of the [scale ] object so that the first two are -1–1.
We can improve our Theremin increasing the brightness of the tone as the volume increases. Increased brightness occurs when harmonics are added to our sine wave, which we can do by gradually transforming our nice round sine wave into a square wave. One way to do this is to increase its amplitude and send its output through a [tanh~ ] object. See the file called brightness.maxpat in the demos folder for a demonstration of how this works.
We would now like to apply the change that we’ve made to the left joystick (part 3 of today’s lab) to the right joystick. There are at least two ways to implement this change for the second voice that we want to avoid: (1) we can simply repeat the necessary steps, or we can (2) delete the right side and copy the objects from the left and rewire them. While neither of these scenarios may seem like a problem, try to imagine what it would be like if your patch contained 20 voices each with 20 objects. As we continue to copy and paste groups of objects that represent some sort of functionality, we quickly run into the need to abstract that functionality in a way that would allow us to make the change to one part of the patch and have that change propagate through all instances of that abstraction.
The objects that you had selected have now been encapsulated in an object called [p ], which is short for [patcher ]. We call this object a “subpatch” or a “subpatcher.”
There is no need to rewire your patch—since the subpatch and the abstraction you just made have the same number of inlets and outlets, Max will simply replace the subpatch with your [Theremin ] abstraction, keeping the connections in tact.
The abstraction you made in part 4 allows you to make a change to the file you saved on disk (Theremin.maxpat) and to have that change take effect wherever it is used. Try it:
But what if we want to change the parameters of the [scale ] object in the left instance of the [Theremin t]o [scale -1. 1. 200. 1000.] and those of the right instance to [scale -1. 1. 750. 3500.] so that we have a low and a high instrument? For this, we need to expose these parameters so they can be accessed from the patch that contains the instances.