Audio Beacon Part 1
Why an audio beacon?
An audio beacon is an autonomous sensor which buffers the audio from 1 or more microphones and stream the data in burst mode to a processing node for analysis.
The scope of this mini project is to use a Jeenode with a pre-amplified microphone and a Jeenode-USB on the computer side for the audio streaming and analysis.
Additionally I would like to compress the audio with a u-law or a-law compression.
The hardware configuration
I'm using a pre-amplified microphone module that you can buy in my shop. The microphone is pretty simple with an opamp and a variable gain through a potentiometer. However it must be connected to a voltage divider to give a constant offset. So I have used two 100kOhm resistors between the Vcc and the GND plus an additional trim pot of 10kOhm. A capacitor of 10uF decouple the AC of the microphone before entering the voltage divider for the biasing.
Dim lights Embed Embed this video on your site
The microphone has a 3 wire interface: black is ground, red is the power in the range [3.3V,5V] and blue carry the amplified signal. I connected the microphone on Port 2 of the Jeenode. So black to G, red to P and blue to A.
We start by importing the required libraries and allocating 2 payloads: one for the audio and one for the transmission through the RFM12B. We want to use a basic sampling rate of 8 kHz and because we have 1 microphone (at the moment) we will record a single channel.
The RFM12B radio module which has a payload limit of 66 bytes and therefore we will buffer the audio and then "burst" the data in 4 packets.
The compression flag will be used to decide if we want to compress the audio or not. This is a very critical aspect: every radio module such as the zigbee series, the nordic series and the rfm12b are based on bytes. The ADC of the arduino or jeenode is a 2 byte long value.
We have several options and I will show you the last 2:
- expand every audio sample in 2 bytes
- truncate or scale the audio sample of 2 bytes to 1 byte with the map function
- use the a-law or u-law compression
The function responsible for the conversion at 8kHz is an interrupt routine, used in CTC mode which is the the faster way to sample as explained in this tutorial.
The ISR is basically converting the value from the microphone and storing into the audio buffer. If there is no compression we use the linear mapping of the arduino to convert the int into a byte, if there is compression we can use either the a-law or u-law compression algorithm.
Once the buffer is full we reset the sample counter and we are ready to send data.
The reset buffer function is useful to empty the buffers, the print_buffer function is very interesting because it stops the sampling, sends the data over the serial and the resume the sampling.
It is very important to disable the interrupt because otherwise the serial transmission will be interrupted (sorry for the word game) by the sampling.
And now into the crucial bits necessary to start, stop and resume sampling by using the OCR register.
The setup is quite straightforward:
Generating tone signals with Matlab
To test the microphone, you can generate an audio sample with a determined tone.
I'm familiar with Matlab so I did a simple script to generate a wav file.
You can play the tone with a headset facing the microphone.
Recording the audio stream
We then need to record the samples from the Jeenode/arduino over the serial port and test the quality of the microphone:
The simple script reads the serial port with a buffer of 66*4 bytes, which is the same size as configured on the board.
Mu-Law compression
Hazelware in his blog explains very well the algorithm, so I copy&paste his explanation with the code which works fantastic on arduino and the jeenode.
The purpose of the algorithm is to compress a 16-bit source sample down to an 8-bit sample. The crux of Mu-Law functionality is deciding which of the samples need to keep the most of their precision. Even the "most-important" sample will still lose precision. It simply becomes a matter of determining how much each sample loses, and minimizing the loss on samples deemed "more important". First, the algorithm first stores off the sign. It then adds in a bias value which (due to wrapping) will cause high valued samples to lose precision. The top five most significant bits are pulled out of the sample (which has been previously biased). Then, the bottom three bits of the compressed byte are generated using a small look-up table, based on the biased value of the source sample. The 8-bit compressed sample is then finally created by logically OR'ing together the 5 most important bits, the 3 lower bits, and the sign when applicable. The bits are the logically NOT'ed, which I assume is for transmission reasons.
Download the code
Last Updated (Wednesday, 14 July 2010 10:03)




Comments
Interesting thing, it's the closest reference i've seen that does an audio "streaming" from the arduino to the PC. Just curious, how did it perform? (ths audio quality) ...
RSS feed for comments to this post