How to Play Music Using Mathematics in Python | by Nishu Jain | Towards Data Science

Why do some notes sound harmonious together? And others just don’t. Can you compose a piece of music if you’re deaf? Which “Physical construct” of sound makes the melody beautiful?
Listen to this audio, and tell me what you hear:
I like playing the piano and I love programming & mathematics. So today I thought, why not blend them together to create something awesome.
My music will tell you more about me than I ever will
The audio (above) was synthesized using Numpy and Scipy only! Don’t worry if you’re not familiar with these Python packages. They’re not that tough to understand.
In this article, we’ll see how we can generate waves with different frequencies, build our own virtual piano, and play a song. All of this, using our favorite programming language, Python.
So let’s start with some basics.
Did you know? Beethoven, one of the most famous composers ever lived, spent most of his career being deaf! He solely relied on his intuition of the patterns that he found working with his audience. He mixed his creativity with the logic of mathematics (sub-consciously) and composed the music that we still cherish.
For the sake of simplicity, we’ll use the piano as our reference instrument. So before beginning, here are some basics.
The anatomy of a keyboard (piano/instrument) is pretty simple. It consists of multiple octaves. An octave is a set of 12 keys — 7 White ones and 5 Black ones.
Each key produces a sound at a distinct frequency on pressing, and we press multiple keys simultaneously to play a chord. That’s it!
White Keys are named as C, D, E, F, G, A, B whereas Black Keys are named using two terms — Flat (b) and Sharp (#).
If a black key is on the right side of any white key, it’s called the sharp of that corresponding white key. And, if it is on the left side, it’s called the flat of that corresponding white key.
For example, the black key between C and D has two names: C# (C-Sharp) and Db (D-Flat). This is because it is on the right side of C and also on the left side of D.
We’ll use the “Sharp” terminology in this article to avoid confusion. Also, the words, “Notes” and “Keys” are used interchangeably.
Keeping that in mind, let’s begin!
You must have heard about the waves in your physics class. Waves like electromagnetic waves, mechanical waves, sound waves, etc ... oscillate repeatedly about the equilibrium at some given frequency.
Mathematically speaking, waves can be described by a wave equation like —
g(f) = A sin(2πft)
Where,
A = Amplitude or the Peak Value
f = frequency
t = time
We can easily create a function in Python to generate a NumPy array of a wave with respect to time, as shown in the following code:
You can also plot this array using some library (like matplotlib) to get a clear picture of what’s going on.
The frequency of 440Hz implies that the wave completes 440 full cycles in one second. In other words, it completes one cycle in 1/440th of a second.
Since we divided our 1 second into 44100 parts, according to the sample_rate, we can plot our one cycle by printing elements from 0 to int(44100/440)
import matplotlib.pyplot as pltplt.plot(a_wave[0:int(44100/440)])plt.xlabel('time')plt.ylabel('Amplitude')plt.show()
Note: As you can see, the cycle is not fully completed in the graph. Ideally, this cycle completes at 100.227, but since we are using the discrete time interval (at 100) it is slightly off from it’s initial value (i.e. 0).
As mentioned earlier, a piano consists of multiple octaves. Although every octave is physically identical, it may sound a bit high-pitched or low-pitched with respect to the other.
If we want to create a single octave (set of 12 keys), then we must know how each key is calibrated in relation to the other. After that, we can just double (or half) the frequency of all the keys, to get the next octave.
Pianos are tuned using an “equal temperament system”. That means the relationship between the frequency of the keys (notes) is like this —
note_freq = base_freq * 2^(n/12)
Where n is the number of notes away from the base note.
For example, if we consider C as our base note, then C# will have the frequency = base_freq * 2^(1/12)
We can easily build this logic with a single for loop in python (without using any special libraries).
So now that we have our virtual piano ready, it’s time to play something.
The song that you heard at the beginning of this article is called “Ah! vous dirai-je, maman”. This is a popular French children’s song which is famously coupled with “Twinkle Twinkle Little Star”, a nursery rhyme by Jane Taylor.
Obviously, I played the simplest version possible — in a minimum number of steps as follows:
Step-1: Get the notes of the song you want to play.
music_notes = 'C-C-G-G-A-A-G--F-F-E-E-D-D-C--G-G-F-F-E-E-D--G-G-F-F-E-E-D--C-C-G-G-A-A-G--F-F-E-E-D-D-C'
Step-2: Make a function to concatenate all the notes.
Step-3: Write the song into a file using Scipy and play.
from scipy.io.wavfile import writewrite('twinkle-twinkle.wav', samplerate, data.astype(np.int16))
Clearly, there is much more to the “Mathematics of Music” than I described here. Many questions have been left unanswered, like the theory of Consonance and Dissonance, playing Chords and Scales, tuning of a piano, etc...
Hopefully, I will cover them later.
You can find the complete source code on my Github repo.
“May not music be described as the mathematics of the sense, mathematics as music of the reason? The musician feels mathematics, the mathematician thinks music: music the dream, mathematics the working life” — James Joseph Sylvester, Mathematician
Happy Programming!
If you enjoy reading these stories, then I’m sure you would love to be a Medium paying member. It’s only $5 per month, and you’ll get unlimited access to thousands and thousands of stories and writers. You can support me by signing up using this link, and I’ll earn a small commission that will help me grow and publish more stories like this!
Some Other Articles that you may enjoy —