Detecting Musical Notes in Python - Updates
Introduction
In my last post, I introduced my pitch_detector project, the goal of which is to detect musical notes from recorded audio. In this post, I'll provide a quick update on my (very slow) progress on the project:
- Using uv
- Calculating musical notes from frequency
- Writing tests
Please feel free to download and run the program yourself to test it out! (Link again to code)
Using uv
One of the first things I did when returning to this project was initialize the project with uv, which was introduced to me by Todd Valentic. It's really simple to use and makes tracking dependencies, creating virtual environments, and sharing code really easy.
Calculating musical notes from frequency
I also finally finished the main goal of the program: converting frequencies into musical notes. I'll ignore how I extracted frequencies from recorded audio. Instead, I'll just focus on how I came up with a function that does this:
f ( frequency_Hz ) = musical_note, octave
12 equal temperament
As discussed in previous posts, musical notes of the chromatic scale are equal-tempered (equidistant) on a logarithmic scale, which we can see clearly if we look at frequencies of the 0th octave:
note = min ( abs ( log2(notes) - log2(frequency) ) )
This works for:
min(notes) < frequency < max(notes)
In non-mathy terms, this is:
- Take the log of everything.
- Calculate the distance between the input frequency and known musical frequencies.
- Find the distance that's closest to 0 (the minimum distance).
This approach breaks when we test frequencies outside of the 0th octave range, since the "distances" calculated will not hover around 0, but will hover around the input frequency's octave. I'll skip the derivation, but the formula we actually want is:
octave = round ( frequency - MIDDLE )
note = min ( abs ( octave - (log2(notes) - log2(frequency) ) ) )
Where MIDDLE is the logarithmic middle of the 0th octave.
Writing tests
I'm now writing test cases to see where my code fails. I'm working to keep my tests readable and modular, guided by a testing blog sent to me by a friend. I'm utilizing pytest and hope to take full advantage of its features (such as fixtures) going forward.
Moving forward
My goal is a command-line program that can do real-time audio collect and processing, similar to a guitar tuner. Stay tuned for that (ba dum tss) haha.
Acknowledgements
Thanks for Todd Valentic for his guidance during the work day! The stuff I learn from him has been widely applied here. Thanks also to Mike Fosco for his advice on coding and software.
Comments
Post a Comment