{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\"FMP\"\n", "\"AudioLabs\"\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\"C1\"\n", "

Harmonic Series

\n", "
\n", "\n", "
\n", "\n", "

\n", "In this notebook we have a closer look at the harmonic series following Section 1.3.2 of [Müller, FMP, Springer 2015].\n", "

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let $\\omega$ denote the center frequency of a musical note. For example, the music note C2 (having MIDI note number $p=36$) has the center frequency $\\omega=65.4$ Hz. The **harmonic series** is an arithmetic series $\\omega$, $2\\omega$, $3\\omega$, $4\\omega$, $\\ldots$, where the difference between consecutive harmonics is constant and equal to the fundamental frequency. Since our perception of pitch is logarithmic in frequency, we perceive higher harmonics as \"closer together\" than lower ones. This is different for the **octave series**, which is defined by the geometric progression $\\omega$, $2\\omega$, $4\\omega$, $8\\omega$, and so on. For an octave series, the difference between consecutive frequencies is perceived as \"the same\" in the sense of musical interval. Consequently, in terms of what we hear, each octave in the harmonic series is divided into increasingly \"smaller\" and more numerous intervals. \n", "\n", "Let us again consider the note C2 ($p=36$) with center frequency $\\omega=65.4$ Hz. Then, the second harmonic ($2\\omega$) sounds like a C3 (one octave higher), the third harmonic ($3\\omega$) like a G3 (a so-called **perfect fifth** above C3), and the fourth harmonic ($4\\omega$) like a C4 (two octaves higher). Starting with a C2, the following figure shows for each of the first $16$ harmonics the musical note that is closest in terms of the difference between the harmonic's frequency and the center frequency of the note as specified by\n", "\n", "$$\n", "F_\\mathrm{pitch}(p) = 2^{(p-69)/12} \\cdot 440.\n", "$$\n", "\n", "Furthermore, the difference (in cents) between each harmonic's frequency and the center frequency of the closest note is indicated (top row, in red).\n", "\n", "\"C1\"\n", "\n", "For example, the frequency of the third harmonic is just $2$ cents above the center frequency of G3, which is much smaller than the just noticeable difference. In contrast, the frequency of the $11^{\\mathrm{th}}$ harmonic is $49$ cents below the center frequency of the note F5, which is nearly half a semitone and clearly audible. If the harmonics are transposed into the span of one octave (by suitably multiplying or dividing the frequencies by a power of two), they approximate certain notes of the twelve-tone equal-tempered scale. Some of the twelve scale steps are approximated well such as the ones for C ($1^{\\mathrm{st}}$ harmonic), G ($3^{\\mathrm{rd}}$ harmonic), or D ($9^{\\mathrm{th}}$ harmonic), whereas others are problematic such as F$^\\sharp$ ($11^{\\mathrm{th}}$ harmonic), A$^\\flat$ ($13^{\\mathrm{th}}$ harmonic), or B$^\\flat$ ($7^{\\mathrm{th}}$ harmonic).\n", "\n", "The following code produces sinusoids for all of the 16 harmonic frequencies and 16 center frequencies of the notes shown in the figure above." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T08:46:36.923668Z", "iopub.status.busy": "2024-02-15T08:46:36.923372Z", "iopub.status.idle": "2024-02-15T08:46:39.970122Z", "shell.execute_reply": "2024-02-15T08:46:39.969453Z" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
NoteNote Freq. (Hz)Note SinusoidHarmonic Freq. (Hz)Harmonic SinusoidDeviation (Cents)
1C265.4165.410.00
2C3130.81130.810.00
3G3196.00196.221.96
4C4261.63261.630.00
5E4329.63327.03-13.69
6G4392.00392.441.96
7B$^\\flat$4466.16457.84-31.17
8C5523.25523.250.00
9D5587.33588.663.91
10E5659.26654.06-13.69
11F$^\\sharp$5739.99719.47-48.68
12G5783.99784.881.96
13A$^\\flat$5830.61850.2840.53
14B$^\\flat$5932.33915.69-31.17
15B5987.77981.10-11.73
16C61046.501046.500.00
" ], "text/plain": [ "" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "import IPython.display as ipd\n", "import pandas as pd\n", "from collections import OrderedDict\n", "\n", "import sys\n", "sys.path.append('..')\n", "import libfmp.c1\n", "\n", "# Computation of frequencies and differences\n", "p = 36\n", "freq = libfmp.c1.f_pitch(p)\n", "freq_harmonic = (np.asarray(range(16)) + 1) * freq\n", "sinusoid_freq_harmonic = []\n", "notes = np.asarray([36, 48, 55, 60, 64, 67, 70, 72, 74, 76, 78, 79, 80, 82, 83, 84])\n", "freq_center = libfmp.c1.f_pitch(notes)\n", "sinusoid_freq_center = []\n", "freq_deviation_cents = libfmp.c1.difference_cents(freq_harmonic, freq_center)\n", "\n", "# Generation of sinusoids\n", "dur = 4 # seconds\n", "Fs = 4000 # sampling rate\n", "\n", "for freq in freq_center:\n", " x, t = libfmp.c1.generate_sinusoid(dur=dur, Fs=Fs, freq=freq)\n", " sinusoid_freq_center.append(x)\n", "\n", "for freq in freq_harmonic:\n", " x, t = libfmp.c1.generate_sinusoid(dur=dur, Fs=Fs, freq=freq)\n", " sinusoid_freq_harmonic.append(x) \n", "\n", "# Generation of html table \n", "audio_tag_html_center = []\n", "for i in range(len(freq_center)):\n", " audio_tag = ipd.Audio(sinusoid_freq_center[i], rate=Fs)\n", " audio_tag_html = audio_tag._repr_html_().replace('\\n', '').strip()\n", " audio_tag_html = audio_tag_html.replace('\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Superposition of sinusoids with frequencies from notes:\n" ] }, { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "num_sinusoid = 16\n", "x_all_harmonic = sinusoid_freq_harmonic[0]\n", "x_all_center = sinusoid_freq_center[0]\n", "for i in range(num_sinusoid-1):\n", " x_all_harmonic = x_all_harmonic + sinusoid_freq_harmonic[i+1] \n", " x_all_center = x_all_center + sinusoid_freq_center[i+1]\n", "\n", "x_all_harmonic = x_all_harmonic / num_sinusoid\n", "x_all_center = x_all_center / num_sinusoid\n", "\n", "print('Superposition of sinusoids with frequencies from harmonics:')\n", "ipd.display(ipd.Audio(data=x_all_harmonic, rate=Fs))\n", "print('Superposition of sinusoids with frequencies from notes:')\n", "ipd.display(ipd.Audio(data=x_all_center, rate=Fs))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "Acknowledgment: This notebook was created by Meinard Müller, Frank Zalkow, and Shrishti Shetu.\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", "
\"C0\"\"C1\"\"C2\"\"C3\"\"C4\"\"C5\"\"C6\"\"C7\"\"C8\"
" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.16" } }, "nbformat": 4, "nbformat_minor": 1 }