In FM Synthesis, the depth of modulation (D) and the frequency of modulation (M) control the number of generated significant sideband pairs together, using the following formula: IM = D / M. We can measure depth of modulation in hz, which means how many hz by which the carrier frequency deviates. Thus, the result of D / M is a unit-less number, called the Index of Modulation, or IM. When D = 0, there is no sideband generated (see Introduction to Computer Music, Chapter 4 for more detail.)
Create an FM instrument, a function named fminstr
, in the file proj3.sal
that takes the following keyword parameters:
pitch
: the carrier frequency in steps (a number)im
: a time-varying index of modulation (of type SOUND)You may use additional parameters to control loudness (vel:
), vibrato, C:M ratio, envelope parameters, etc. The stretch factor should allow you to control the duration of the instrument sound. The default behavior should be a tone with a fundamental frequency controlled by pitch
and where higher im
produces more and stronger harmonics.
Be sure that your instrument uses an envelope to control overall amplitude. If you run play osc(g4)
in Nyquist, you will hear an example of what your instrument should not sound like! In fact, if your envelope has just a quick fade-in, a constant hold, and then a quick fade-out, we will not consider that to be an envelope. Be musical. Be creative.
An example that plays the instrument is:
play fminstr(pitch: g4, im: const(0, 1)) ~ 2
In this example, the IM parameter is the constant zero with a duration of 1, so this is expected to play a boring sine tone at pitch G4.
Create a function named part1
with no parameters. Running this should instantiate a single instance of your fminstr
and return the sound, which should last about as long as the stretch factor. So the command play part1() ~ 3
should play about 3s and will demonstrate that you completed Part 1. Your part1
function can pass in and demonstrate optional keyword parameters you have added.
Hint: Be sure to test part1
with different durations (stretch factors).
Demonstrate the instrument by using PWL to create an interesting Index of Modulation. In other words, replace const(0, 1) in the previous example with an interesting, time-varying IM. You can use the envelope editor in the Nyquist IDE to draw an envelope if you like, and you can apply scale factors and offsets to the PWL function to fine tune your sonic result.
Keep in mind that if you put in a long PWL envelope (or any other envelope), your fminstr()
code will not magically deduce you want all of the other components to stretch to the duration of the envelope.
Create a function named part2
with no parameters. Running this should instantiate a single instance of your fminstr
with your PWL modulation and return the sound, which should be 3 to 5s long and contain obvious changes in brightness due to a time-varying im
. So the command play part2()
will demonstrate that you completed Part 2.
For a (hopefully) more interesting composition, we are going to analyze a real sound, extract the time-varying spectral centroid, and use that to control the Index of Modulation of one or more FM sounds.
Read the documentation on spectral centroids in the accompanying files (look in the downloaded directory), and try out the project3-demos.sal
that is provided. To summarize, you call spectral-centroid()
on an input sound (or filename), and it returns an envelope that tracks the spectral centroid of the input sound.
The idea here is that when the input sound gets brighter, the spectral centroid goes up. If we use spectral centroid to control the Index of Modulation, an increasing spectral centroid should cause the Index of Modulation to increase, and therefore the FM sound should get brighter. Thus, there should be a connection between spectral variation of the source sound analyzed with spectral-centroid()
and the spectral variation of your synthesized sound.
Your technical task is to make this connection between input sound and output sound. This is a rare case where we are going to suggest assigning the spectral centroid (sound) to a global variable. If you do that, then any note can reference the spectral centroid. For example:
set *sc* = 0.003 * spectral-centroid(...) play seq(fminstr(pitch: c4, im: *sc*), fminstr(pitch: c4, im: *sc*) ~ 2)
This plays two notes. The first runs nominally from 0s to 1s, and it will use the first second of the spectral centroid sound to control its IM. The second note runs nominally from 1 to 3s (the duration is 2 because of the stretch operator ~), and this note will use the spectral centroid from 1 to 3s. It is important to note that the second note does not begin “reading” the *sc*
variable from the beginning. This is consistent with the idea that, in Nyquist, sounds have an absolute start time.
Note 1: You could align the beginning of the spectral centroid with the beginning of the note by replacing *sc*
with cue(*sc*)
. The cue behavior shifts its sound parameter to start at the time specified in the environment. However, we think it will be more interesting to let the IM evolve throughout your piece and let each note access the current state of the spectral centroid as the piece is being playing.
Note 2: Why did we multiply spectral-centroid(…) by 0.003? The point is that spectral-centroid
is measured in hz and will probably range into the thousands, but reasonable values of IM are probably going to be in the single digits. Is 0.003 the right scale factor? No, it is just a rough guess, and you should adjust it.
Note 3: You can use a score here rather than SEQ.
Your musical task is to create something interesting, with a duration of 30 to 60 seconds. We do not want to box you in to a specific procedure, but we are looking for a result that shows interesting spectral variation driven by the spectral centroid of a source sound. Some possibilities include:
lowpass8(*sc*, 10)
will remove most frequencies in *sc*
above 10 hz, leaving you with a smoother control function. (See the project3-demo.sal
file.)PAN
function), or other effects.Grading will be based on meeting the technical specifications of the assignment:
fminstr
and part1
and part2
functions in your proj3.sal
.proj3.sal
code should not immediately compute spectral centroids or FM tones.Note that the following must be strictly adhered to:
proj3.sal
proj3comp.sal
. Note: Code should be clearly commented in case we want to run it.proj3part2.wav
proj3comp.wav
proj3input.wav
proj3comp.txt