Awesome project! As a professional audio developer, I was really blown away that this was the author's first project working with audio.
For anyone interested, I'd recommend checking out "The Infinite Jukebox", which has a similar goal, but perhaps a more robust approach: http://infinitejukebox.playlistmachinery.com
If I had to guess at why your approach didn't work well on recorded music, it's probably because most of the time, there is more than a single event happening at a time, so picking out just the highest FFT bin is probably not a very robust "fingerprint" of that part of the music. The infinite jukebox uses timbral features as the fingerprint, rather than just a single note.
Thanks for the clarification. I guess like all trade-offs, it's context dependent. I see the advantages of having a realtime usable non-optimized build for debugging. Since I use modern libraries like Eigen, that option has not been available to me for some time.
With "modern" techniques, the performance ceiling is a bit higher - whether that benefit is worth it depends on a lot of factors.
I work using C++17 for high performance applications, and I can relate to a lot of these gripes. I think it's a fair point that C++ is unreasonably complex as a language, and it's been a serious problem in the community for a long time.
One part that really struck me as odd is the focus on non-optimized performance. To me, this is an important consideration, but not nearly as important as optimized performance. Using techniques like ranges can definitely slow down debug performance, but much of the time it _dramatically increases_ optimized performance vs. naive techniques.
How do ranges speed up optimized builds? One of the best techniques for very high performance code is separation of specifying the algorithm and scheduling the computation. What I mean by this is techniques like [eigen](http://eigen.tuxfamily.org/index.php?title=Main_Page) and [halide](http://halide-lang.org) where you can control _what_ gets done and _how_ it gets done separately. Being able to modify execution orders like this is critical for ensuring that you're using your single-core parallelism and cache space in an efficient way. This sort of control is exactly what you get out of range view transformers.
For those interested in an open source design embodying these techniques, I have an open source hardware design here: https://github.com/russellmcc/dco with a blog write-up here: https://www.russellmcc.com/posts/2013-12-01-DCO.html .
Also of relevance is an open source hardware design for the later roland alpha juno digital oscillator design: https://github.com/russellmcc/alphaosc https://www.russellmcc.com/posts/2019-06-14-Alpha-DCO.html