Open Propeller Project #6: Clarinet Tone Detection
Ken Gracey
Posts: 7,392
Let me just come right out and say it: here's a self-serving project and I'm asking you to help me write some Propeller code!
Two years ago I started taking clarinet lessons after being impressed with what middle school kids [including my own] can do after a couple of years in an active band program. I asked the band instructor what he recommends and he quickly pointed to clarinet due to portable fingering patterns and really demanding reed embouchure. I took clarinet lessons for a summer with my younger son and he bailed out for more piano but I kept going.
Could I learn something as quickly as these middle schoolers or was it too late to develop the hand/eye coordination skills? I can't dance, I have trouble reading music and counting at the same time and I'm told I have to be "feeling the music".
I'm not about to claim any success in this endeavor, but I'm pretty sure an adult could learn an instrument as well as a child. My instructor says there are certain challenges we face as adults: limited practice time; maybe desire to turn the notes upside down in descending order; frustration that causes us to quit; and whatever other biases we might have accumulated along the way. This varies by person, I'm sure. For me, simply listening to what I'm told to do can also be a challenge.
The instruction has been rewarding. At Christmas I got a special recognition as "Musician of the Month" from the local Music Institute. This only means you are following the instruction and making progress according to your level. I've also survived a few solo performances where my reeds were dry and nerves high, sending out screeches in front of the students and their parents (my friends). Improvement comes slowly, but there's been forward motion.
Open Propeller Project #6: Clarinet Tone Detection
FFT or Whatever It Takes to Bin The Tones For Use as Outputs
The Bb clarinet is the most common version of the clarinet woodwinds. It has a really wide range spanning three and a half octaves (the upper ones are really hard to play). There's a fantastic site providing sound clips and http://www.phys.unsw.edu.au/music/clarinet/index.html.
Using a Propeller BOE (or any board with the right microphone circuit) I'd like to be able to detect and bin the sounds into each note, maybe even identifying sharps and flats. Put seven LEDs on a breadboard and activate each one of them based on detecting an A, B, C, D, E, F and G note. Bonus for detecting sharps and flats, too! A whole bunch of apps for iOS make it a built-in tuner with a lot of precision, but there's not a way to control anything from within their hardware.
Like most other projects, I'm sure this has been done already for another microcontroller. I've never looked inside of a tuner.
Eventually I'd drive much larger circuits, maybe with addressable LEDs, LED light tape, and who knows what else [except a quadcopter]. It's a way of combining one hobby with another. But the first step is what this project is all about - identifying the tones.
It would be ideal to see the application be configured for all kinds of instruments and transpositions, but this isn't necessary right now.
Chip says I've got to learn to use FFT to do this properly. Yet I've been sitting on this project for six months and I haven't been able to study it a bit. Sometimes engineers walk by my desk and tell me how easy it is, yet the code hasn't written itself as easily. My lack of progress isn't due to lack of interest, though it's true that my programming skills are about the same level what we share on Learn.parallax.com and I have only negative time lately. So I need some help.
I thought it would be fun to build a Propeller BOE test project area with some relays and several LED strips, and a VGA display for feedback. Never mind the clicking relays - I know they're silly but they were the first piece of hardware I could find. Moving forward I'd use MOSFETs or something digital. Feel free to make fun of me for using them, though. I'll probably step back to a simple board with LEDs and PST to get started. I'm not even sure I want to use the hardware in my video now that I hear the relays. That's the last distraction I need at this stage.
C, ASM or Spin? Don't care! I can test every piece of code you produce.
Any takers?
Thanks,
Ken Gracey
Comments
This has been used to detect the frequencies of a kalimba. Sorry I don't have a link to that project at hand.
Having said that, others have suggested different transforms that might work better.
Edit: Here we go:
http://forums.parallax.com/showthread.php/128292-Heater-s-Fast-Fourier-Transform.
I can't find the kalimba project links. That's a shame because there is a great video of it working on youtube. It was very well done.
I'm interested in this because I have several projects in mind that need a small and fast way to detect frequencies.
Hopefully pointers to the alternatives Heater mentioned will show up here.
The people who visited Parallax last week told me about your work on this topic and identified it as a good starting point. I'll give that a look as soon as possible. The Digi guys are about to walk into the office for a meeting around our WiFi S6B programming interface and needs so I'll be offline for a bit.
Ken Gracey
This is a demo that I've worked on for my dissertation this year. This project uses quite a few objects I've found and incorporated, including Heater's FFT.. http://forums.parallax.com/showthrea...ier-Transform.
http://forums.parallax.com/showthread.php/140777-Audio-Signal-Processing-on-the-Propeller-Demo-Board?highlight=Fast+Fourier+Transform
-Phil
P.S. Can you remind us again what it means to be an official "Open Propeller Project"?
Just to clarify: when you play a C it's actually a B-flat, right? So when you play the B above middle-C, it's actually A440? And when you play a C, you want it displayed as a C, not as B-flat?
-Phil
Hmmm. "B-Sharp" would make a nice name for a C language variant, wouldn't it? 'Good name for a student language, "Be sharp!" Oh, but then there's this:
Hmmm, maybe not.
I thought that a BoeBot could move different directions depending on the tune/pitch. There are a number of riffs on that like doing patterns based on the tune. Remember the walking robots hokey pokey?
In a webinar about a year ago Andy did a very basic demo with a tin whistle but I don't know where that video is stored. I think it was just binary "sound detected" and not pitch determination.
Perfect, Bob. I will load and run the demos no later than Thursday morning. But if I miss that chance it will be Sunday before I have an opportunity again.
Looks like there's a wealth of examples to start from.
Ken Gracey
That's correct - clarinets are transposed two half notes upward from concert-pitch instruments.
A C in concert pitch is a Bb on clarinet. I could handle the notes being displayed in concert pitch just fine. That's probably more useful to flutes, oboes and other concert-pitch instruments, too.
This example could also be really interesting to some of your high school kids in PT.
Ken Gracey
Also, the QuickStart board would be an ideal platform for what you're trying to do, since it already has eight LEDs. In addition to board-mounted sigma-delta parts, all you would need externally are a mic, one pull-up resistor, and one coupling cap.
I'll keep this project in mind for next year's HS class. ('Looks like I'll be doing it again.) There are only three more sessions before summer break, and if I can get them all hitting targets with their rubberband guns, I'll consider it a victory.
-Phil
OK, when you play a "C" on a trumpet or clarinet (both are keyed to Bb) it will sound like a concert Bb. So, these instruments are two half-steps up from concert pitch. I guess the transposition depends on what instrument you're playing and which one you want to tune to. You could go up or down to match.
Ken Gracey
I found this FFT code online and brought it into a SIDE project. It compiles and runs on the Propeller in XMMC mode, but can probably be easily consolidated down to run completely from RAM. It places the complex result into bins, but I haven't figured out the frequency division of each bin. It's also scalable to make more bins for higher frequency resolution, at the cost of compute time. I just haven't studied the code long enough yet. Anyway, I thought I'd post the progress to give a jump start.
Cheers,
Daniel
I have no idea where that FFT code comes from but it uses double precision floating point arithmetic!
That might be OK if you have time to spare and space for the code.
The heater_fft uses only 32 bit integer arithmetic and the main guts of it fit into COG when compiled with FCACHE enabled with GCC. Amazingly that C code runs nearly as fast as the hand crafted PASM version.
Anyway, never mind the speed. Your question was about what frequencies are in there.
Thing is these are totally unrelated to actual Hz.
The input to an FFT may be an array of 1024 samples. Or whatever size.
The output is also 1024 samples.
So, the first sample of the output, element zero, gives the DC offset or zero frequency of the input.
The 511th sample gives the highest frequency of the input. Must be 0 to 511 because of the Nyquist limit. 1024 input samples can only represent frequencies up to 511.
The other 512 samples of the output mirror the first 512 samples. Again due to Nyquist and aliasing.
So, if that 1024 input samples is taken over one second of a signal input the FFT can only tell you about actual frequencies from 0 to 511 Hz.
If you have a higher sampling rate then you have to scale things accordingly.
Err..I hope all that makes some kind of sense.
Edit: Best way to get a feel for this is to run the code on our PC and plot the inputs and outputs somehow.
http://forums.parallax.com/showthread.php/115805-Real-Time-Goertzel-Algorithm-Object-and-DTMF-Sensing-Demo?p=838455#post838455
Too bad he didn't write it up and enter it in the contest.
Thank you for the detailed reply!
That code came from a Google search on FFTs and C. It doesn't surprise me one bit that it isn't optimized for a microcontroller. I just pulled it in to SIDE to see if it would compile and to tinker. At these stages, I wasn't worried about execution speed. As you say - the best way to get a feel for what's going on is to just mess with it .
I think I see what you're saying - the frequencies that the array bins represent is a function of the number of samples you take in a given time period, divided by 2 because that is the frequency you are guaranteed to be able to represent with the sample set (forgive me if my explanation isn't quite right, it has been some time since I've studied signals). Hence the Nyquist rate.
512 samples per second is certainly not going to give any real resolution. This would definitely have to be increased to be able to pick out much more than your standard A note (440 Hz). And assuming instant computation (which isn't possible), 1 Hz update on the tone detector isn't very practical.
I'm definitely going to have to crack my Signals and Systems book to freshen up on the analog world
http://en.wikipedia.org/wiki/Constant_Q_transform
Daniel, your code comes in at around 18KB in CMM mode with 32-bit doubles. No need for XMMC.
I have an old copy of "Numerical Recipes in C" ;-)
While a Propeller optimized FFT is best, sometimes people just want to get something going without too much pain.
If you want to get the power instead of the magnitude then square all the outputs. Take the "10*log10(output)" of each output after this to get the magnitude/power in dBs.
...
The frequency value for each bin is "(sampleFreq / N) * binPos"