Go Down

Topic: Pitch Detection: Guitar to MIDI (Read 10336 times)previous topic - next topic

00hubblemp

May 12, 2008, 03:09 am
I am interested in using the Arduino to convert a single guitar string pluck into MIDI, so I need to be able to detect pitch and amplitude. As this only needs to calculate the pitch of one string I don't think the pitch detection algorithm needs to be complicated. I have a pickup that will send the signal into one of the analog pins. The pseudo code for the program should look like this:

1. Read in one or more oscillations at 44100kHz (take approxiamately 2000 samples?) (fairly easy)
2. Analyze amplitude and then scale to 0-127 (unsure how to do this)
3. Analyze the pitch and then scale to 0-127 (unsure how to do this)
4. Send out a MIDI note on (easy as I have done this with other projects)

Could anyone help me in a non-CPU intensive algorithm/code that will perform the above tasks with minimal latency?

Once I have done this I intend to use all 6 strings.

crimony

#1
May 13, 2008, 02:21 am
There is no "non-CPU intensive" algorithm to determine an unknown pitch. FFT is the most efficient known algorithm for this task. Latency will depend on the length of the FFT, which will be determined by how much precision you want - a 128-point FFT at a 44.1 kHz sampling rate will give you ~350 Hz resolution, not enough to discriminate between low frequencies, so you will need to drop your sampling rate or increase the number of points in the FFT. FFT execution time is O(nlogn), so doubling the size should increase the execution time by 2.3.

You won't be able to store 2000 samples as the ATMega168 only has 1024 bytes of RAM, some of which will be required for other program variables.

FFT will give you the amplitudes of each frequency (pitch) component, so you scan through the output and find the largest peak, then measure the amplitude.

There's an ATMega FFT implementation here. 64-point execution time is 3.4 ms. I think 64-point is the biggest you're going to be able to manage as the algorithm is 16-bit, and you need 2*(N + 2*N + N/2) = 448 bytes of RAM for the input / butterfly / output buffers. For 128-point, you will therefore need 896 bytes of RAM. If you can keep your variable requirements of the rest of the prog down to 128 bytes then you might squeeze it in.

reginr

#2
Sep 05, 2008, 04:57 amLast Edit: Sep 05, 2008, 04:58 am by reginr Reason: 1
00hubblemp thanks for the post on FFTs maybe that's the reason why those Godin, Carvin midi guitars are expensive.....

I have an idea    if you were dealing with a steel stringed guitar then you can somehow use the fret wires to determine the what pitch the string is at without doing an intensive FFT thingy, its going to be messy since you are going to wire all fret wires to some sort of multiplexer.

Is there a solid state thing that can convert the frequency to volts? would it be fast enough for the Arduino to determine its pitch by the level of volts?

I would like to do the same project but on a nylon string guitar like a yamaha SLG100n or a cheap Aria.
Any thoughts?

weirdo557

#3
Sep 05, 2008, 05:52 am
http://www.national.com/mpf/LM/LM2917.html

frequency to voltage converter

Quijonsith

#4
Sep 05, 2008, 08:16 amLast Edit: Sep 05, 2008, 08:22 am by Quijonsith Reason: 1
one could use a switched capacitor bandpass filter IC and scan through the frequencies of the audio spectrum.  If one is specifically dealing with music there are 120 distinct musical notes in the audio spectrum, and only 22 distinct notes on any one string of a guitar.  You wouldn't be able to tell what string you're on by the frequency alone because many notes appear on the guitar neck in more than one location, IE playing the low-E string open is the same as playing the A string at the 5th fret.

The audio spectrum from 0 octave to 10th octave goes from 16.35Hz to 15804.27Hz.  With standard tuning a six string guitar ranges from E2 (82.41Hz) to D6 (1174.66Hz).  The formula for the individual note frequencies can be found here: http://en.wikipedia.org/wiki/Note.

The Q required for 1/12 octave resolution (individual note resolution) is 17.31.  The entire note range of a standard guitar not including duplicates is only 46 notes.  You could conceivably scan every note on the guitar and only need 92 bytes to store the ADC conversions of each note, and that's if you don't use complicated code to kill dead memory space between the extra 6 bits not being used when you store an ADC conversion.  You could even double buffer the notes and still only use 184 bytes for ADC conversions.

You would simply set the Q and center frequency of the filter IC and sample the audio, though I'd recommend using a circuit like the one macegr posted at http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1216393384/6 between the filter IC and the arduino to bring the audio to a usable level.

That all being said, then the idea is to simply scan through a mere 46 frequencies, which is about 1/3 of the entire audio spectrum.  The arduino is not capable of 44khz sampling rate, but 10khz is doable not accounting for how long it takes to setup the bandpass filter between note reads.

If you really feel limited by the 1k of ram in the arduino as I did, you could get a sanguino (assuming there are any kits available again yet).  64k of flash and 4k of ram.  I'm working on a 115 band audio spectrum analyzer project and using the sanguino for it.  I'm planning to sample my audio for the display using the method I've described here.

Also, considering that the highest note on the guitar is only 1174.66Hz at standard tuning you could use the counters in the arduino to measure the frequency, but that would only work for one note at a time.  It wouldn't work for chords.

BigMike

#5
Sep 05, 2008, 12:15 pm
As you are only doing one note at a time, you could try measuring the time between zero crossings.

You would probably need to have some low pass filtering to cut down the risk of a harmonic causing false zero crossings.

As a slight aside - do the commercial guitar to midi converters handle bent notes?

Regards,

Mike

reginr

#6
Sep 08, 2008, 04:43 am
Thanks for the posts

I looked at you tubes videos with midi pickups, so far I didn't notice anyone bending the notes.

There is a company that converts the vibration optically (perhaps using some sort of infrared sensor)

I heard that its open source I just don't have the chance to find the source

This for all the Arduino gurus out there, If you were to do it how will you convert the string vibrations optically?

I'm thinking of an opens source project that would convert guitar music directly to midi (without the need of a separate 13pin guitar pickup and a 13pin to 5 pin midi converter)

reginr

#7
Sep 08, 2008, 05:05 am
Quote
http://www.national.com/mpf/LM/LM2917.html

frequency to voltage converter

Thanks for the post!

Is there any website where I can get just a few pieces?  Thanks!

melka

#8
Sep 08, 2008, 05:26 am
digikey
http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail?name=LM2917N-8-ND
or ask for samples on the national semi site
http://www.national.com/mpf/LM/LM2917.html#Availability

Grumpy_Mike

#9
Sep 08, 2008, 12:34 pm
Quote
without the need of a separate 13pin guitar pickup and a 13pin to 5 pin midi converter)

If it were possible then why do you think the commercial guys go to the bother of a 13 13pin guitar pickup?
There is great pressure to make things low cost and commercial developers don't make a complex system just for the hell of it.

Suggestions here sound fine but will not work, it is a much harder thing than you imagine. Just try it and see.
Switch mode band pass filters take too long to produce an output from a valid input and scanning a whole lot of notes is just too time consuming. Especially when you consider the post filter peak detector to decide which is the biggest. Optically you have the same problem as electrically, there is an oscillation and you have to detect the frequency. The problem is that most of the time the software gets it right but not enough of the time to be reliable and usable.

Hey I am called Grumpy after all and would love to be proved wrong.

Go Up