It’s about right time to release one more “remix” for one of my blog, published almost a year ago. I haven’t got much comments, not many as I was expecting, on a topic. There are some reasons, that would explain this phenomenon, but I would better to start outlining what I did in new release, and some of you who tried old version would be impressed by progress I’ve made!
Basic structure was left almost intact. Essential parts of the project: Filtering 2D and Cross-Correlation are the same, so please read my old post, if you come across this one w/o seen it first. What differs is “preprocessing”, before we get to the filtering stage. In first, I ported a code on Leonardo board. The easiness of connecting electret mic to Leonardo, just didn’t give me a choice! I played already with Leonardo ADC – electret mic’s in my previous post, and would assure you, that this guys were designed to work as a team. Uno followers have to solder a pre-amplifier, not big deal, the same time not really interesting. Code would run on Uno, except Timer and ADC settings, which you could always “copy/paste” from the old version. Feel free, be my guest.
Analog front-end is absolutely the same as I used in Sound Localization project. You would need only one mic here, just reduce the number of electrical components down.
Sampling subroutine based on Timer 4, and arduino Leonardo internal PGA set to gain x40. There are a comments in the code, so you could adjust gain up or down depends on the sensitivity of mic you have.
Windowing LUT is slightly modified Hamming/Hann cosine function, I’d say my table is an “intermediate” version of both mention inventors.
FFT is my best achievements of this year, RADIX-4. Compare to old code, about 3x faster. This is why I was able to increase FFT_SIZE up to 128, still having plenty of time. Magnitude calculation is based on approximation, very fast, because no square root extraction required. Accuracy, in the worst case scenario ~95%, which is more than enough in this project.
I changed Non-Linear compression algorithm, as now there are more Bins – 64 to pack in 16 Bands. Math is simple, and hope doesn’t need an extensive comments. Packing is necessary due memory limits, 1 sec password in current configuration (16 bands with sampling rate 4 kHz) occupied 1 kByte, full size of EEPROM on Leonardo or Uno boards.
Command Line Interface is preserved. Here is the instructions, how to set everything up and running.
And here how spectrogram looks like in LibreOffice, test phrase “Front right”, (OS Linux Ubuntu, 12.04):
Get your microphone wired / connected? All checked at least a couple times with multimeter, voltages looks o’k? Good, now you are ready to start! ( Don’t forget to upload a sketch to your arduino / Leonardo -);
1. X. First of all, open serial monitor window, and check boadrate. Should be 115200. Next, type “x” and Enter. Get some response? Does it look like a table? Excellent, data you are looking at is “raw” sampling data. Probably, just noise, acoustical or electrical. 2. F. Second test, type “f” - Enter. Again, arduino would print out a table. This time data represent “processed” by FFT analog signal. Each bin corresponds to frequency range 32 Hz. If you have a signal generator , it's right time to do a detailed check up microphone, wiring, and software. If don't have, you can use your computer's sound card and some program, there are plenty of them available on-line free of charge. Connect generator to PC USB speackers, and run a single tone, anything in audible range 16 – 2000 Hz. Check again using “f” command, if arduino registers a signal, and it's in right bin. Due “windowing” function, even pure single tone would show up at least in 2-3 neighboring bins. Amplitude depends on sensitivity of the mic, and volume of the sound. Sending “x” you can confirm, that there is no “clipping” too many “– 511” or “+511”. 3. S. Next, if all goes well till this step, you probably already notice, that whenever a mic picking-up a sound – yellow on-board LED lights up. Now, it's better shutdown your TV, iPad, radio. Make your environment as quite as possible. Try to say something with your own voice, and see if led lighting up when you start talking, and than after ~1 sec it goes off. Repeat a few times, adjusting a volume and / or distance to the mic, so led goes “on/off” reliable. Send “s” command when led is off. Don't worry, it should be no report on screen, till you say a word. Procedure is simple, send “s” - say something. After you talk, and get a printing, look carefully. Your objective, is get a “spectrogram” which consist of a few spots / blobs of digits, randomly distributed all over the “surface”. Repeat a few times with one word, than try another one and so on. With short words, very likely reporting data would be concentrated at the top ( you may need to scroll up to see the beginning), if this is a case, better to choose longer words or talk in slower tempo. Just remember, there are three dimension, time, frequency and volume. You can use a signal generator here again, spectrogram should looks like a vertical line, may be 2 - 3 parallel lines on low frequencies test tones. Changing a frequency, you can even get some curves. What is important, the must be no negative numbers. If you see them – "overloading" happens, Decrease a volume. Dynamic range is limited by 127, more close you can get to this value w/o negatives, the better. And last dimension is a frequency. For man, it would be a little bit hard to “detach” a spectrogram from the left border. It's true for everyone, who is not opera singer, me no exceptions.... 4. R and G. After you practice enough, and received Manny nice looking spectrograms, it's time to check with arduino, if it's agree with you / thinks similar. Send “r” - recording, and say a word you've get your best spectrum with. Wait a few seconds, writing to EEPROM takes time. Now send a “g” and say the same word. In the same manner, tonality and volume. See on the outputs, what is the cross-correlation factor you received. More than 50% - very good for beginning. Less – try again a few more times sending “g” and repeating same word, maybe slightly varying pronunciation. Try to reach best recognition, “crack” your own password code! ( note: Negatives number on “G” reports-form must be present.) If no luck try another password code. Now you know the drill: S – repeat, repeat, repeat....., R, G – repeat, repeat, repeat..... (joke). Can't get good match? Try your computer's test sounds, beeps, horns, clicks, barks – whatever your OS has. It doesn't have to be shorter than 1 sec, but only 1 second in the beginning would be stored / compared. My computer is able to repeat the same sound track (speakers test - "front right") with enormously high cross-factor 99 % ! I'm not a computer, my best short 86 % so far... 5. P. This command is simply reading the content of the EEPROM, so you always can verify, what you stored last time. Editing / formatting this data you can store a table in the arduino FLASH memory using PROGMEM. About 10 – 15 commands. Of course, storing data in external SD card or EEPROM, could greatly increase the “vocabulary”, the same time design of fast cross-correlation algorithm with multiple “pattern”s would be another brain teasing puzzle -);.
Link to arduino sketch, VOR (VOice Recognition).