Shop OBEX P1 Docs P2 Docs Learn Events
Open Propeller Project #6: Clarinet Tone Detection — Parallax Forums

Open Propeller Project #6: Clarinet Tone Detection

Ken GraceyKen Gracey Posts: 7,392
edited 2014-05-21 08:54 in Propeller 1
OPP-FFTToneDdetect.png


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
600 x 250 - 222K

Comments

  • Heater.Heater. Posts: 21,230
    edited 2014-05-19 11:04
    No idea if it helps but a quick search of the forum for "heater_fft" will find you an FFT that runs on the Propeller.

    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.
  • jazzedjazzed Posts: 11,803
    edited 2014-05-19 11:09
    Great project Ken.

    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.
  • Ken GraceyKen Gracey Posts: 7,392
    edited 2014-05-19 11:20
    Heater. wrote: »
    No idea if it helps but a quick search of the forum for "heater_fft" will find you an FFT that runs on the Propeller.

    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
  • JonnyMacJonnyMac Posts: 9,105
    edited 2014-05-19 13:37
    I believe Phil has done some work with tone decoding -- you may want to check with him. I have a friend that's new to the Propeller who wants to build a multi-channel color organ, so I'll be watching to see how your project proceeds.
  • Bob Lawrence (VE1RLL)Bob Lawrence (VE1RLL) Posts: 1,720
    edited 2014-05-19 14:05
    [h=2]Audio Signal Processing on the Propeller Demo Board[/h]
    FFT powered scrolling musical note representation:

    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 Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2014-05-19 14:32
    JonnyMac wrote:
    I believe Phil has done some work with tone decoding ...
    Yes, but I used the Goertzel method which relies on linearly-spaced frequencies. Musical notes are logarithmically spaced, so I was reluctant to suggest it as a solution.

    -Phil
  • localrogerlocalroger Posts: 3,451
    edited 2014-05-19 18:02
    Long ago I seem to recall someone posted code here for a very simple tone detector which used a method of continuously adding samples into a buffer one wavelength long. If the target tone is in the input, the maxima reinforce to very high levels, while other frequencies cancel out. This works better for specific frequencies than a general spectrum. but doesn't take a lot of RAM or CPU power so a propeller could simultaneously test for a fairly large number of frequencies. I can't find it and don't recall the details but it seems like it should work if each sample buffer is updated with an exponentially weighted moving average, which can be implemented with out multiplication or division using shifts and adds. Each sample buffer could be compared to a longer-interval noise level buffer to look for tones poking out of the current average noise level.
  • David BetzDavid Betz Posts: 14,516
    edited 2014-05-19 19:13
    This sounds like an interesting project. I like any project involving music. I'll be interested to see how this turns out. I'd contribute if I could but I think this is mostly going to involve math, not my strong suit.

    P.S. Can you remind us again what it means to be an official "Open Propeller Project"?
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2014-05-19 19:38
    Ken,

    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.
  • John KauffmanJohn Kauffman Posts: 653
    edited 2014-05-19 21:43
    I talked about this kind of idea a little with Andy.
    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.
  • Ken GraceyKen Gracey Posts: 7,392
    edited 2014-05-19 21:50
    Audio Signal Processing on the Propeller Demo Board

    FFT powered scrolling musical note representation:

    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

    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
  • Ken GraceyKen Gracey Posts: 7,392
    edited 2014-05-19 21:55
    Ken,

    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.

    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
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2014-05-19 22:04
    Ken Gracey wrote:
    A C in concert pitch is a Bb on clarinet.
    Or is it the other way around? I have a fuzzy memory of playing the trumpet (which is also keyed to Bb) in HS, and I thought a C on the trumpet was Bb in concert pitch. That that was eons and many burnt-out and besotted neurons ago, though...

    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
  • Ken GraceyKen Gracey Posts: 7,392
    edited 2014-05-19 22:38
    Or is it the other way around? I have a fuzzy memory of playing the trumpet (which is also keyed to Bb) in HS, and I thought a C on the trumpet was Bb in concert pitch. That that was eons and many burnt-out and besotted neurons ago, though...

    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
  • Daniel HarrisDaniel Harris Posts: 207
    edited 2014-05-20 10:56
    Hi guys,

    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
  • Heater.Heater. Posts: 21,230
    edited 2014-05-20 13:01
    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.
  • KeithEKeithE Posts: 957
    edited 2014-05-20 16:57
    BTW - I remembered that BradC mentioned a guitar tuner that he built with Phil's code for note detection here:

    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.
  • Daniel HarrisDaniel Harris Posts: 207
    edited 2014-05-20 23:49
    @Heater

    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 :lol:
  • Brian FairchildBrian Fairchild Posts: 549
    edited 2014-05-21 00:32
    I stumbled across this whilst looking for something else...

    http://en.wikipedia.org/wiki/Constant_Q_transform
  • jazzedjazzed Posts: 11,803
    edited 2014-05-21 08:44
    Hi guys,

    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


    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.
  • KyeKye Posts: 2,200
    edited 2014-05-21 08:54
    The output of a real2complex FFT of N samples is (N/2)+1 samples. Output sample 0 is the DC frequency and output sample (N/2) is the Nyquist frequency. To get magnitude of the signal do sqrt(pow(real,2.0),pow(imag,2.0)) of each output sample pair. Next, you need to scale the samples. This involves multiplying the middle outputs of the signal by 2 (everything but the DC and Nyquist outputs). After which you need to divide all outputs by the number of inputs.

    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"
    // Pseudo Code //
    
    int sampleFreq = 8000; // hz
    
    int inputSize = 1024;
    int inputSamples[inputSize] = {};
    
    initSamples(inputSamples);
    
    int outputSize = (inputSize/2)+1;
    float outputSamples[outputSize][2]; // 0= real, 1= imag
    
    doFFT(inputSize, inputSamples, outputSamples);
    
    float magnitudes[outputSize];
    float powers[outputSize];
    
    float magnitudesDB[outputSize];
    float powersDB[outputSize];
    
    int freqs[outputSize];
    
    for(int i = 0; i < outputSize; i++);
    {
        magnitudes[i] = sqrt(pow(outputSamples[i][0], 2.0), pow(outputSamples[i][1], 2.0));
        
        if((0 < i) && (i < (outputSize -1))
        {
            magnitudes[i] *= 2.0;    
        }
    
        magnitudes[i] /= inputSize;
    
        powers[i] = magnitudes[i] * magnitudes[i];
    
        magnitudesDB[i] = 10.0 * log10(magnitudes[i]);
        powers[i] = 10.0 * log10(powers[i]);
    
        freqs[i] = (float(sampleFreq) / float(inputSize)) * i;     
    }
    
Sign In or Register to comment.