tags:

views:

634

answers:

5

Hi, I have a guitar and I need my pc to be able to tell what note is being played, recognizing the tone. Is it possible to do it in python, also is it possible with pygame? Being able of doing it in pygame would be very helpful.

+2  A: 

You will need to use an audio library such as the built-in audioop.

Analyzing the specific note being played is not trivial, but can be done using those APIs.

Also could be of use: http://wiki.python.org/moin/PythonInMusic

Yuval A
The `audioop` module can only do quite primitive analysis and compression techniques. This is not at all adequate for the asker's purposes. The wiki link is a long list of links that probably causes more confusion than it avoids.
intgr
+10  A: 

To recognize the frequency of an audio signal, you would use the FFT (fast Fourier transform) algorithm. As far as I can tell, PyGame has no means to record audio, nor does it support the FFT transform.

First, you need to capture the raw sampled data from the sound card; this kind of data is called PCM (Pulse Code Modulation). The simplest way to capture audio in Python is using the PyAudio library (Python bindings to PortAudio). GStreamer can also do it, it's probably an overkill for your purposes. Capturing 16-bit samples at a rate of 48000 Hz is pretty typical and probably the best a normal sound card will give you.

Once you have raw PCM audio data, you can use the fftpack module from the scipy library to run the samples through the FFT transform. This will give you a frequency distribution of the analysed audio signal, i.e., how strong is the signal in certain frequency bands. Then, it's a matter of finding the frequency that has the strongest signal.

You might need some additional filtering to avoid harmonic frequencies I am not sure.

intgr
Is there a standard way for dealing with a sequence of notes?
unutbu
I am not sure what you are asking, can you elaborate?
intgr
If you FFT a sequence of notes, you gain information about the dominant frequencies, but lose information about the time-position of the notes. (Or am I wrong?) I suppose you could try to chop up the raw audio so as to apply the FFT to single notes, but figuring out where to chop seems hard.
unutbu
True, the usual approach is breaking input down into small enough chunks that timing context isn't lost. Of course this is a trade-off between timing precision and frequency precision.
intgr
A: 

This link shows some one doing it in VB.NET but the basics of what need to be done to achieve your goal is captured in these links below.

Dean
+7  A: 

I once wrote a utility that does exactly that - it analyses what sounds are being played.

You can look at the code here (or you can download the whole project. its integrated with Frets On Fire, a guitar hero open source clone to create a real guitar hero). It was tested using a guitar, an harmonica and whistles :) The code is ugly, but it works :)

I used pymedia to record, and scipy for the FFT.

Except for the basics that others already noted, I can give you some tips:

  1. If you record from mic, there is a lot of noise. You'll have to use a lot of trial-and-error to set thresholds and sound clean up methods to get it working. One possible solution is to use an electric guitar, and plug its output to the audio-in. This worked best for me.
  2. Specifically, there is a lot of noise around 50Hz. That's not so bad, but its overtones (see below) are at 100 Hz and 150 Hz, and that's close to guitar's G2 and D3.... As I said my solution was to switch to an electric guitar.
  3. There is a tradeoff between speed of detection, and accuracy. The more samples you take, the longer it will take you to detect sounds, but you'll be more accurate detecting the exact pitch. If you really want to make a project out of this, you probably need to use several time scales.
  4. When a tones is played, it has overtones. Sometimes, after a few seconds, the overtones might even be more powerful than the base tone. If you don't deal with this, your program with think it heard E2 for a few seconds, and then E3. To overcome this, I used a list of currently playing sounds, and then as long as this note, or one of its overtones had energy in it, I assumed its the same note being played....
  5. It is specifically hard to detect when someone plays the same note 2 (or more) times in a row, because it's hard to distinguish between that, and random fluctuations of sound level. You'll see in my code that I had to use a constant that had to be configured to match the guitar used (apparently every guitar has its own pattern of power fluctuations).
Ofri Raviv
A: 

Very similar questions:

Turning sound into a sequence of notes is not an easy thing to do, especially with multiple notes at once. Read through Google results for "frequency estimation" and "note recognition".

I have some Python frequency estimation examples, but this is only a portion of what you need to solve to get notes from guitar recordings.

endolith