Micro-Moog

Assign: Thursday, September 23

Due: Thursday, September 30

Assignment Policies

All assignments are partner assignments. Please make sure to review the policies and guidelines about discussing assignments with those other than your partner. Assignments are usually, but not always, a combination of paper and coded exercises. Please make two submissions (one for paper exercises and one for coded exercises) to Gradescope. Paper exercises are marked with HW to indicate a handwritten question and C to indicate a coded question. Paper submissions can receive an extra 2% bonus if they are typed. Please visit the tools section of the website for more information.

Part 1: SynthDef Practice with Saw Waves C

Starter Code

This part has no starter code. Create a new file called synthdef_saw.scd and place your name and your partner’s name at the top in a comment.

Description

The goal of this part is to get more practice writing SynthDefs in SuperCollider. Here we will create some definitions using sawtooth waves in different ways.

  1. Write a SynthDef called \saw that simply plays back a sawtooth wave with the following default arguments: outBus = 0, freq = 440, amp = 0.1. Your code should use the UGen Saw and should playback the sawtooth wave in stereo. Write an additional line to play the synth and then another to free it.

  2. Write a SynthDef called \sawOctaves that plays back a sawtooth wave and a sawtooth wave one octave above. The SynthDef should use the UGen Saw and should accept arguments outBus = 0, freq = 440, amp = 0.1. The frequency argument specifies the frequency of the lower note in the octave. The amplitude of each sawtooth wave should be half the provided amp. Write an additional line to play the synth with a frequency of 300Hz. Then write a line to set the frequency to 200Hz and then a line to free the synth. You should produce a stereo wave.

  3. Write a SynthDef called \varSaw that creates a variable sawtooth wave. A variable sawtooth wave is a waveform that can be modulated from a sawtooth wave to a triangle wave. We will not concern ourselves with the details of such an implementation. Instead we will simply use a UGen called VarSaw that can provide such a waveform. Examine the Help Documents on VarSaw to understand how exactly to use its inputs. Notice that VarSaw has a parameter for width. This controls the shape of the waveform. To add some interest to the sound, we will change the width of the waveform over time using a sine wave. In essence, this will shape the strength of the partials, creating an interesting sweeping effect.

    Some additional requirements:

    • The SynthDef should accept the following default arguments: outBus = 0, freq = 440, amp = 0.1. Note here that the amp and freq refer to the amplitude and frequency of the variable sawtooth wave and not the amplitude and frequency of the modulating sine wave.
    • Again, you will need to create a sine wave and use it to control the width of the variable sawtooth wave. The sine wave should have frequency 0.5 and should span the range from 0 to 1. Note that a sine wave is -1 to 1 by default so you will need to consider how to change the arguments to the sine wave to accomplish that goal. Note that the add argument can shift a waveform vertically.
    • Create a stereo signal.
    • Write a line to create the synth and then free it.
    • If you like, try opening up a scope to watch the waveform change in realtime using s.scope.
  4. Write a SynthDef called \sawChorus that creates a chorus effect. When singers sing the same note, each singer’s pitch is slightly different from the other singer. It’s why the sound of a choir is so rich. The same principle holds for a string section of an orchestra. To create a choir effect using sawtooth waves, we simply create several copies of the sawtooth wave, each with a pitch that shifts around the target frequency. For the purposes of this SynthDef, use six sawtooth waves.

    Some additional requirements:

    • You must use a for loop, do loop or while loop to add the six sawtooth waves together.
    • The SynthDef should accept the following default arguments: outBus = 0, freq = 440, amp = 0.1
    • To generate the deviation around the center pitch use the UGen LFNoise1.kr which will generate a changing random number -1 and 1. You can use the range method on LFNoise1 or any UGen for that matter and it will scale the output to a different range. For example, the code LFNoise1.kr(0.5).range(1, 3) will create a changing random number every two seconds between 1 and 3. Here, the idea is to use LFNoise1.kr to create a changing frequency. If each sawtooth wave has a random value close to the desired frequency, you will achieve the chorus effect. Ensure that the chorus effect works equally well for low sounds and high sounds. Think ratios! I would also have LFNoise1 change random numbers at a low rate, somewhere between every half and two seconds.
    • Each sawtooth wave’s amplitude should be divided by the number of sawtooth waves used (i.e., six).
    • Create a stereo signal. Here ensure that a different LFNoise1 controls the left channel and the right channel for each saw wave. That will create a more interesting stereo audio effect. You should be a bit careful here. If you do something like LFNoise1.kr ! 2 that will duplicate the exact same unit generator. Here we want two different copies of LFNoise1. Instead you should use {LFNoise1.kr} ! 2 which evaluates the function twice and places those contents in an array. This will give you two different UGens.
    • Create a line to play the Synth and a line to free it.

To give you a sense of what it sounds like, here is an audio file where I set the frequency to different values. It’s a pretty good synthesizer sound!

Part 2: Micro-Moog C

The main part of this assignment involves creating your own synthesizer. We will model our synthesizer after the classic synthesizer developed by Robert Moog in the 1960s. The Moog synthesizer has been used in all genres of music including classic rock groups like the Rolling Stones and the Beatles, rap artists like Dr. Dre, and many other groups that incorporate electronic music.

The Moog synthesizer is an example of subtractive synthesis. The basic idea is we take a sound source like a sawtooth or square wave, pass that signal through a filter which attentuates (i.e., subtracts) the harmonics in the sound source, shape the amplitude of the sound using an amplitude envelope, and finally pass it through a reverberation unit to give the sound a sense of space. Your goal for this assignment is to create SynthDefs for each of these four phases of the sound generation and then connect the signal path using busses and groups.

The diagram below summarizes the signal path. The first step in the chain is the oscillator (i.e., a sawtooth, sine, triangle or pulse wave). That signal is routed to a Voltage Controlled Filter (VCF) which attenuates the harmonics. The term VCF comes from electronics where audio signals are represented as changes in voltages. The third step in the chain is a Voltage Controlled Amplifier (VCA) which applies an amplitude envelope to the sound. The final step is a reverberation unit. Here we will borrow a builtin reverb that comes with SuperCollider. Soon though we will learn how to make our own!

Diagram of signal flow path

When you are done, I have created a GUI which you can launch to play your synthesizer using your computer keyboard.

Starter Code

Download the starter code to get started. Take a look over the top half. You can ignore the code below that creates the GUI under the header “Starter Code - DO NOT MODIFY”. You should see the four SynthDefs requiring your implementation. The functions ~start and ~free are needed to connect the Synths together using busses.

IMPORTANT: Do not change the arguments to any of the SynthDefs and do not modify their initial values. That will be important for the GUI to work properly.

Step 1: Create the SynthDef for the Sound Source

Your first step should be to create the SynthDef \oscillator. This will be the sound source. \oscillator will be able to choose between several different waveforms like sawtooth or square and output a mono signal. The following is a description of the arguments to \oscillator.

Some implementation details and hints.

You should thoroughly test that all arguments work by creating a synth and using the .set method to change arguments. Use the space under the header “Testing” to try things out. I will ignore everything under this header when grading your work.

Step 2: Complete

Go ahead and complete the rest of the SynthDefs. Below is a description for the arguments to each one and some implementation hints. Fortunately, the remaining SynthDefs involve less explanation than \oscillator.

The Voltage Controlled Filter: \vcf

The Voltage Controlled Amplifier: \vca

The voltage controlled amplifier generates an ADSR amplitude envelope to shape the sound. The envelope can be triggered using a gate and shutoff by closing the gate (i.e., setting it to zero).

Reverberation: \reverb

The \reverb SynthDef should add space to the sound. Reverb creates the reflections that give the sound a sense of distance and ambiance. You should use the UGen FreeVerb.ar to create the reverb.

Step 3: Connect the SynthDefs

The function ~start should create audio busses to connect the whole signal path together. It should also create instances of each synth. Place all four synths in the same group so they are easier to free.

Each Synth needs to be assigned to a specific environment variable. You must name each of your synths to these respective variables in order for the GUI to work: ~osc, ~vcf, ~vca, and ~verb.

The function ~free should free all audio busses and the group containing all the synths. You should free using the group you create in ~start.

Running the GUI

When you are done and believe everything to be working, try out the keyboard GUI by executing the starter code at the bottom. The video below shows how changing each element of the GUI effects the sound. You should make sure your implementation works as I have shown.

DEMONSTRATION VIDEO

Grading and Style

My solution took roughly 70 lines of code to write. However, the solution to this assignment can be a little tricky, particularly routing each Synth to each other. It is difficult because SuperCollider will simply make no sound if things are not working correctly. If you are having trouble, consider using the .poll method, the audio version of a print statement, on any UGen to see what your sound source looks like and if you are getting non-zero values (i.e., sound).

For style, you should have a few comments here and there, particularly in the \oscillator SynthDef explaining your signal flow and what each part is doing. Do not try and write your SynthDef all on one line. You should make use of variables to name different parts of your SynthDef and keep each line short, at most two UGens per line. Readability is important!

You will be grading on the following:

Submission

Feedback

When you are finished with the problem set, please fill out the form linked here to provide feedback on how long the problem set took you and how difficult you found it. Note that you must fill out this form to receive credit for the problem set.

Submission Guidelines

All assignments in this course are submitted through Gradescope. There are two kinds of assignments in this course: paper assignments and code assignments. Both are submitted to Gradescope. Most assignments are a mix of code and paper assignments. Each question or question part will be marked either “code” or “paper” to indicate which kind of question it is. For paper assignments, note that typed answers will receive a small additional bonus of 2%.