To work on this exercise, you should first work through the Lecture on Music Representations.
Furthermore, please take the opportunity to review your programming skills. Basic knowledge of Python is required for the remainder of this class. You should be confident in applying the concepts presented in units 1 to 5 of the Preparation Course Python (PCP).
Finally, we will require you to run the PCP notebook environment and the Fundamentals of Music Processing (FMP) notebook environment. Follow the links and set them up on your local machine.
Throughout the exercise, we will make use of the PCP and FMP notebooks. Please, always feel encouraged to actively work through these notebooks, play around with different parameters, other input files etc.! That is the best way to learn.
Go through the FMP Notebook on Musical Notes and Pitches and understand the meaning of the parameters. In particular:
Go through the FMP notebook on Frequency and Pitch and write the following functions:
Understand the concept of Shepard tones by going through the FMP Notebook on Chroma and Shepard Tones. Answer the following questions:
Understand how to sonify pitch-based representations by going through the corresponding part in the FMP notebook on Sonification. The notebook on the Harmonic Series may be useful to understand why we superimpose certain sinusoids in the sonification. Then,
We will now employ the concepts you have learned to recreate the following YouTube video:
import IPython.display as ipd
ipd.display(ipd.YouTubeVideo('A41CITk85jk'))
Listen to the start and the end of the YouTube video. Even though the music seems to be "rising" constantly, the start and end match up perfectly!
The piece by Johann Sebastian Bach that is being played here ends one whole tone above the tone where it started. Therefore, after six repetitions, the music arrives at an octave above the tone where it started. In the YouTube video, shepard tones are additionally used to match the frequencies at the start and after six repetitions. This creates the impression of a "neverending canon".
There are many resources on the web where you can download MIDI files, which encode symbolic music. See the FMP notebook on MIDI for more information on how to parse MIDI files. Find a MIDI of your favorite song and sonify it using the methods you have learned thus far.
Center frequency: The frequency (given in Hz) of a pitch (given in MIDI note numbers or in musical notation). (The center frequency for a pitch depends on the scale and tuning system used. For Western music, we usually consider the 12-tone equal tempered scale with reference pitch $p=69$ and reference tuning $440~\mathrm{Hz}$. In that case, the center frequency of a pitch can be computed with the function $F_\mathrm{pitch}$ given in the FMP notebook on Frequency and Pitch.)
Fundamental frequency: The lowest active frequency when a note is sung or played on an instrument. (A musical sound consists of simultaneous oscillations at many frequencies. The notebook on the Harmonic Series and on Timbre might be helpful for understanding this.
In the FMP Notebook on Chroma and Shepard Tones, a chirp signal is generated and the following statement is made:
"Here, note that the instantaneous frequency is given by the derivative of the sinusoidal's argument"
To understand this, let's start with a simple sinusoid of frequency $440$ Hz:
\begin{equation} \sin(2\pi \cdot 440 \cdot t) \end{equation}import IPython.display as ipd
import numpy as np
dur = 1 # Seconds
Fs = 22050
freq = 440
N = int(dur * Fs)
t = np.arange(N) / Fs
x = np.sin(2 * np.pi * freq * t)
ipd.display(ipd.Audio(x, rate=Fs))
Here, one can think of the phase as changing with time, corresponding to the oscillations of the sine wave. However, the rate of change of the phase, i.e. the instantaneous frequency stays constant.
In general, a chirp is a signal whose frequency increases or decreases with time. In the notebook on Shepard Tones, we want to create a signal where the frequency is increasing exponentially. That corresponds to a linear increase in pitch.
Let's say we want a sinusoid starting at frequeny 440 Hz and increasing to 880 Hz over the course of one second. In other words, the frequency at time $t$ should be
\begin{equation} f(t) = 440 \cdot 2^t \end{equation}$f(t)$ is also the rate of change of the phase of our signal. Thus, the phase should increase faster and faster, corresponding to faster and faster oscillations of the sine wave. To get the argument of the sinusoidal at time $t$ we need to integrate over this rate of change. That way we obtain the formula of the exponential chirp:
\begin{equation} \sin(2\pi \cdot 440 \cdot 2^t / \log(2)) \end{equation}def generate_chirp_exp_octave(freq_start=440, dur=8, Fs=44100, amp=1):
"""Generate one octave of a chirp with exponential frequency increase
Notebook: C1/C1S1_ChromaShepard.ipynb
Args:
freq_start: Start frequency of chirp
dur: Duration (in seconds)
Fs: Sampling rate
amp: Amplitude of generated signal
Returns:
x: chirp signal
t: Time axis (in seconds)
"""
N = int(dur * Fs)
t = np.arange(N) / Fs
x = np.sin(2 * np.pi * freq_start * np.power(2, t / dur) / np.log(2) * dur)
x = amp * x/np.max(x)
return x, t
chirp, t = generate_chirp_exp_octave(freq_start=freq, dur=dur, Fs=Fs)
ipd.display(ipd.Audio(chirp, rate=Fs))
A more formal description of the concept of instantaneous frequency can be found in Chapter 8.2.1 of the textbook