It’s always a pleasure to mix programming with something tactile and even more – with something musical. Check out my little experiment of building a browser game that helps learning notes on guitar.
Learning notes means to be able to play any note (there are 12 of them) on any string (there are 6) without thinking. So when we started to learn notes at a guitar class the idea of Guitar Bro came pretty easy – I needed a trainer to constantly ask “Play X note on Y string” and check whether I played the correct note.
A while ago I have already experimented with notes recognition to tune a guitar – there is no magic, bear with me and I’ll explain how to detect a guitar note with just a browser.
I wanted this project (and actually any project) to be dead simple. I needed some constraints, otherwise it’s really hard to think and it’s almost impossible to converge to something that can be shipped fast. These are constraints I had in mind:
Play only on one string. My guitar teacher introduced me a concept of “unitar” (and he was introduced to this concept by his teacher years ago). It’s a general constraint to master an instrument. Probably, the very first guitar had only 1 string.
All calculation must happen in the browser. No fancy server setup, ideally you can open the game in your browser offline in the park and practice.
It was February back then and it took 4 month till I really started working on it. Luckily, a friend was visiting me in Berlin (I must say that many of my friends can code) and one evening we just decided to make something fun and long story short we started doing Guitar Bro.
The core of the game is to detect frequency and make sure it matches a note. For this we needed a list of all available frequencies on guitar:
Next step was to see how FFT works in the browser, so we quickly set up a little visualisation with d3 and experimented with FFT attributes to find a proper resolution and maximize accuracy.
Looking at notes frequencies above we can see that the lowest distance between two guitar notes is around 5Hz, so we need our FFT Analyser to have a resolution 5Hz or lower. FFT resolution is determind via sampling rate and FFT size (number of samples). Default sampling rate of Web Audio API FFT Analyser is 44100Hz and FFT size is always a power of 2 (from 32 to 32768). So if we set FFT size to 8192 we’ll get frequency resolution of
44100 / 8192 =~ 5.4Hz which should be enough for our purposes.
To make sure it works we set up a quick d3 visualisation for FFT output:
From the notes frequencies table we see that A-note on E-string should be around 440Hz. The biggest spike is located around this frequency, but we can improve data for analysis by using Math.pow function, check out how same input will look like:
It’s clear that the input was the A-note (grey lines – are notes of the first string). Easy approach to detect clear note is to calculate the area of the FFT curve around each note and compare these values. If some value is 95% higher then all the rest – it’s a clear note.
If you want to play with sound analysis, here is a repo with these live visualizations of Web Audio API FFT using d3.
At this step it was proven that we can use just a browser (only latest Chrome, since only latest Chrome allows to configure FFT size to have proper resolution) to detect guitar notes. But when practicing guitar normally one should have a metronome on, so you practice notes and rhythm at the same time. This is how the idea of falling notes was born: we know FPS of drawing falling notes on canvas, we know distance between falling notes. It means that we can calculate time between each pair of falling notes. And it can not only be same distance (metronome mode) but only different distances (like real songs!)
It’s mind blowing, how we went from little research prototype to a browser game which I do use to learn notes. There are obvioulsy many improvements that could be made to Guitar Bro – add Bass mode, Ukulele mode, add more songs but it won’t make any sense if no one will use it.