PCP Teaser

Exercise: Music Representations

Prerequisites

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.

Tasks

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.

Task: Musical Notes and Pitches

Go through the FMP Notebook on Musical Notes and Pitches and understand the meaning of the parameters. In particular:

  • Write a small function that generates a D major scale.
  • More general, write a small function that accepts a pitch class as input and outputs a major scale for the given pitch class.

Task: Pitches and Center Frequencies

Go through the FMP notebook on Frequency and Pitch and write the following functions:

  • A function that accepts a pitch as input and returns the corresponding frequency in a 12-tone equal tempered scale with reference pitch $p=69$ and reference tuning $440~\mathrm{Hz}$.
  • A function that accepts a pitch as well as parameters $p, d\in\mathbb{N}$ and $\omega\in\mathbb{R}_{>0}$ as input and returns the corresponding frequency in a $d$-tone equal tempered scale with reference pitch $p$ and tuning frequency $\omega$.
  • A function that accepts a pitch as well as parameters $p, c\in\mathbb{N}$ and $\omega\in\mathbb{R}_{>0}$ as input and returns the corresponding frequency in a scale with reference pitch $p$ and tuning frequency $\omega$ where the difference between the frequencies of two subsequent pitches of the scale is $c$ cents.

Task: Shepard Tones

Understand the concept of Shepard tones by going through the FMP Notebook on Chroma and Shepard Tones. Answer the following questions:

Task: Sonification

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,

  • Write a function that sonifies a D major scale using a sinusoidal model including harmonics.
  • Recalling the Shepard glissando, extend your function to make the sonification sound like it "rises indefinitely".

Optional Task: Bach's Neverending Canon

We will now employ the concepts you have learned to recreate the following YouTube video:

In [1]:
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".

  • You can find a CSV-representation of Bach's piece here. Using the FMP notebook on CSV representations, load the file and display a piano roll representation of the piece.
  • Sonify the piano roll representation using a sinusoidal model including harmonics.
  • Transpose the piece six times, each time one whole tone higher than before. Remember that a whole tone corresponds to two MIDI pitches. Paste the six iterations of the piece together, one after the other. Visualize the result as a piano roll and sonify it.
  • You should now have a version of the piece that ends one octave above where it started. Recalling the Shepard glissando, change your sonification so that the result "rises indefinitely".
  • Save your result as a .wav-file, open it in a music player application and turn on the loop feature ;)

Optional Task: Sonify your own MIDI

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.

Question & Answer Session

What is the difference between fundamental frequency and center frequency?

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.

What is the instantaneous frequency of a chirp signal?

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}
In [2]:
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}
In [3]:
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

MPA footer