Sound frequencies with aubio

Small python script I wrote so that you can yell at the console and see the frequency on the screen. The results can be slightly wrong (incorrect spikes in frequency occasionally) but it was great yelling at the computer with my hostel mates to see who’s got the highest ‘range’ 😀

Link to the github gist.

The code is too small to give an explanation. However, you need to set up a few libraries before running the gist (instructions for linux) :

1. aubio – A fantastic library for analysing audio. Packages libaubio and python-aubio are available in the ubuntu/mint repositories. However, I ran into problems (repos have older versions I guess) and was able to fix them only after compiling the source. So head over to this repo, download the source code, and compile.

To compile aubio, head over to the source directory and type:

./waf configure

That will spew out a list of packages you will need at the end. Make sure you install the dev versions of each package. For example, for sndfile, do

sudo apt-get install libsndfile1-dev

 

Similarly install all the packages that you would need to use with aubio. I did not have a clue as to what I will need so I installed them all.

Now do ./waf build
and then sudo ./waf install

That should install aubio on your linux system. Time to install the python wrappers. ‘cd’ to /python directory in the aubio source.

python setup.py build to build the files and after building,
sudo python setup.py install to install the python wrappers for aubio

 

2. The snippet depends on pysoundcard, which is not available in the repos. Head over here to download the source. Build and install this python package the same way you did the aubio python wrappers

Download (or type) the gist and run it! Happy yelling!

It’s black and its listening!

I’ve been longing for this day (/night) for almost an year now! I’ve finally, finally, got some data from an electret mic and finally got it into a beaglebone black. If you really want to understand the depth of this achievement, please go through what I’ve been doing for the past few months:

 

http://electronics.stackexchange.com/questions/111458/reading-sound-with-beaglebone-black

http://electronics.stackexchange.com/questions/111969/understanding-a-circuit-diagram

http://electronics.stackexchange.com/questions/106204/connect-electret-mics-to-computer

http://electronics.stackexchange.com/questions/77160/microphone-time-delay-estimation

http://dsp.stackexchange.com/questions/11399/signal-processing-using-panda-board

http://dsp.stackexchange.com/questions/11561/sound-card-for-recording-audio

http://dsp.stackexchange.com/questions/11472/audio-interface-or-external-sound-card

 

That’s a lot of questions. And I got a lot of answers. Though I’m no where near completing the actual project, at least getting it started is a relief. I’ve tried making my own amplifier, tried an audioboard from hrc, tried another opamp IC for amplifier, and finally hit upon this : http://www.rason.org/Projects/hbmic/hbmic.pdf

The previous amplifiers I made might have been working fine – I just might not have read the values properly. Anyways, its working now and that’s all I care about.

Ain't she a (black) beauty?
Ain’t she a (black) beauty?

 

Components : Everything that was in the previous link containing the circuit diagram. I did not have 10 uF capacitors so I used 22 uF instead.

Beaglebone black : The INR 4200 beast. This board is being sold out faster than it is being produced. Lucky we could order one!

The process is pretty straightforward now that it works. The beaglebone black has a set of analog pins that can read analog inputs. I connect the mic (which produces voltage variations in the range of 20mv) to a preamplifier (built using the circuit diagram in the link and 741 opamp) and the output of the preamp (in range of 1 v) is given to the analog input of the BBB. When the sound hits the electret mic, it produces a voltage that is proportional to the amplitude of the sound. This is the signal we then amplify and finally measure.

Is this enough to do some signal processing and thus continue the project? Now that requires more experimenting and is a matter for another post.

I made the mistake of not connecting the ground of beaglebone black to the ground rail in the breadboard and cursed many perfectly working amplifier circuit because it BBB did not read.

Now we have to read this value using beaglebone.

First, enable the input output pins :

echo cape-bone-iio > /sys/devices/bone_capemgr.*/slots
If that step went well, you should not see any messages.

Then I wrote a small python script to read the analog pin 1 continously :


import os
import time

while 1:
os.system("cat /sys/devices/ocp.2/helper.14/AIN1")
time.sleep(0.1)

Replace AIN1 with your analog pin (for eg: AIN2 or AIN3) and the value in time.sleep with your desira
ble delay between reads. Saved it as test.py and python test.py does the job.

BBB reading values. Only positive values can be read. I should have given a DC bias.
BBB reading values (look hard. They’re there). Only positive values can be read. I should have given a DC bias.

The beaglebone black can read only voltages till 1.8 volts on its analog pins. Also, it can only read DC. That is why there are a lot of 0s in my screenshot – that’s where the negative voltages should go. The solution is to give a DC bias to the analog signal. Say we give 1v bias. Then the readings would be around 1V and will go below 1v when a negative peak occurs.

Getting machines to listen

I’ve been wanting to do this sound localization project for almost an year now. Its simple – have a few microphones ready, yell at it, and display the direction of sound on a screen. And being the electronics newbie I am, I had spent a considerable amount of time wondering how to connect an electret mic to my board/computer.

However, the last few days have been extremely productive and now I understand what exactly goes on when you yell at your laptop mic.

The Task : Record something using the built in mics (or any mic), store it in RAW format, access it using a python program. Understand sound.

The tool : Ladies and Gentlemen, meet ALSA – Advanced Linux Sound Architecture
Another tool : pyaudioalsa. Helps us do the necessary stuff without resorting to the C API.

You already have ALSA if you are using any of the major Gnu/linux distributions. First get pyalsaaudio and install it on your computer.

The pyalsaaudio page have some nice examples as to how to record sound. Go through it. By default, your recordings are in RAW PCM format. PCM stands for pulse code modulation. The output of your recording is actually a set of values that denote the amplitude of the input sound at various points in time. Just go through and try running the examples that come with pyaudioalsa source – record.py and playback.py.

Your recording is saved as a PCM RAW file. Try opening it in a text editor and you will see junk values.

But where are the amplitude values?

Exactly. Before that, we will try playing it back. Of course you can do it using the example program playback.py. But there’s another way. Try this on the terminal :

aplay -r 44100 -f S16_LE -c 1

That command will make ALSA play back the recording for you. 44100 is the sampling rate of the recording. How did we know that? Look inside record.py and you will see that the recording was sampled at 44.1KHz. S16_LE denotes that there are 16 bits per sample in our recording stored in little endian format? Now how did we know that?. Again, check record.py. The ‘-c 1’ tells ALSA that our recording is mono.

So that’s how you playback raw PCM files.

But what if you want to do some signal processing? What if you want to draw one of those spectrums or waveforms and other seemingly complicated stuff? Then you will need to extract the data from the RAW PCM. It sounds complicated, I know. Have no fear, python (and numpy) is here:

import numpy
data = numpy.memmap("test.pcm", dtype='h', mode='r')
print "VALUES:",data

Finally, something human readable!
Why don’t we draw a graph?
import numpy, pylab
data = numpy.memmap("test.pcm", dtype='h', mode='r')
print data
pylab.plot(data)
pylab.show()

Note : I’m very grateful to this guy for showing me how to do this.

So what do we have here? We have successfully made use of the RAW PCM data. So? There are many algorithms in Scipy and numpy that can do amazing things with that data – cross correlation,fft,convolution. Thank God (and Guido Van Rossum) for python!