Detecting Frequency is actually a very non-trivial thing to do.
I will describe two basic approaches, but there are others
- Record an analog microphone signal and use Fourier Transform or other algorithm to extract the frequencies (Buffered Approach)
- Use a sensor, or emulate that sensor in software to convert a sound signal (phase) to a frequency signal (Frequency Counter Approach)
I will only give descriptions and prototypes, because this is a very broad question, if there is something specific you would like me to elaborate, please feel free to leave a comment.
pyaudio to capture and record audio stream data into a file. You can do this, for example, every second or every 200 milli-seconds, whatever makes sense for you.
numpy.fft to extract frequency measurements from the audio stream data.
The result of an
fft is an array of frequency bins, that is the relative "power" of that frequency in your audio sample.
There are a few caveats, it is easy to feed an array into
numpy.fft , it is a little harder to extract the result. You will have to use dimensional analysis to convert the numerical result into frequency bins in Hertz
Real Time Approach
Typically you would use some kind of sensor, which has dedicated electronics, to convert the sound into a frequency measurement.
These devices are known as "frequency counters", the fanciest of which can cost thousands of dollars and look like this.
We can implement a simple frequency counter on the raspberry pi, by using a phase counter.
Prototype of a simple (synchronous) counter
TICK_TIME = 1us
# Extra divide by two because half-phase
last_frequency = 1/( 2*(counter*TICK_TIME) )
counter = 0
counter = counter+1
Now, what this is doing is checking the value of the analog signal from an audio sensor, or, even simpler, an audio sensor that is filtered to produce
1 when the signal is above 0 and
0 when it the signal "flips".
We add up the number of times we see positive signal, when the signal flips we have an estimate of the wavelength (/2) and therefore we can estimate the frequency. Then we count the number of "negative" signals, so on and so forth
You can average these frequency measurements over some period of time to get a "cleaner" more stable signal
A good way to get this zero crossing signal is to use a type of comparator called a
An improvement on this approach is to use this input as an "interrupt" for the cpu.
Instead of checking every micro-second we can use the fact that the signal changes to issue an interrupt, and use the hardware to measure the time between interrupts.
Prototype Event Handler
last_time = time.time()
current_time = time.time()
dt = current_time - last_time
last_frequency = 1/(2*dt)
last_time = current_time