Go Down

Topic: Audio Capture to Micro SD (Read 5687 times) previous topic - next topic

daz1761

I've purchased this microphone for my project:  ADMP401 MEMS Microphone

http://www.coolcomponents.co.uk/catalog/breakout-board-admp401-mems-microphone-p-615.html

As I need to capture audio like a mobile phone would in the real world.  I've had a look at the playground and you tube and it seems people are experimenting audio, but using processing to display it.  I'm just interested in the raw data or a .wav file as either will be compatible with MatLab when it comes to the analysis/features side.  I understand I will probably need an micro sd reader so I've ordered one as I will need it for other sensors such as temperature, etc as I need this project to be portable.

The microphone is 0-5v and I understand that the arduino should process this at 10-bits resolution.  Any help will be much appreciated :-)
M

semicolo

From the official documentation you can sample at 10KHz, a standard audio rate below that is 8KHz.
It says the output has a VCC/2 offset, so it doesn't range from 0 to 5V. Supply is 1.8V to 3.3V.
If your arduino can run at 3.3V you'll get the best resolution if using VCC as the ADC reference.
If the sound level you record isn't too high you could use the internal 2.5V reference if your arduino supports it.

Either you add some bogus bits at the end to get a false 16bits output or you ditch the 2 lower bits to get 8bits.

You need to time the sampling interval so they're even and write to the sd card in the meantime, you'll probably have to handle sampling with interrupts to be able to do that.

That's a lot of ifs, tell us more about the exact arduino model you'll be using.

daz1761

Hi, thanks for the reply.  Sorry yes I am using an arduino uno r3 with a MEMS Microphone.  Basically, I just need to capture a few seconds of raw audio at a time in mono with the above microphone.  I have the datasheet for the microphone here:

http://www.analog.com/static/imported-files/data_sheets/ADMP401.pdf

I know when I use the "wavread" function in matlab, I get a 2 column vector of numbers which I can then analyse and plot as a graph.  I was hoping I could get the same result by capturing audio from the arduino from an sd card as I know the memory is 1kb.

I've just read about the Adafruit wave shield, but this seems to playback audio and not record.

I could record the audio straight into the computer, but it defeats the object as I'm supposed to be simulating a mobile phone audio recording.
M

semicolo

Then I'd recommend connecting the 3.3V to ARef.
From the official documentation : you must set the analog reference to EXTERNAL before calling analogRead() or you may damage the MCU.

Are you aiming for a specific sample rate?
I'd check the amplitude you get with the microphone (for example write a bit of code that does some analogReads and keep the higher and the lowest value and print any new high or low value on the serial monitor).
If the amplitude is less than 256, you can convert your readings to 8bits without really loosing information, (for example substract 512 to to get a signed 8 bits value and just in case clip the result to -128 or 127)
Start with the obvious, if it works there's no need to make things more complex.
in setup:
configure AREF
Start the SD library and open a file for writing

in the loop:
use micros() and a variable to get intervals of 125us (for 8KHz)
read a sample
write it to the sd

after some time close the file.

If this works, you're done.
Else you'll have to get your hands dirty by starting the ADC by hand so it's done in the background during writes to the sd.

daz1761

Thanks again for you reply and help.

Sorry I'm kinda new to this platform, I'm not sure if I'm getting so I need to check a few things:

So my VCC goes to AREF or the actual AUD pin go to AREF?  If the VCC goes to AREF does this mean I can put AUD into say Analogue 0?

Ive started the code but im not sure if I'm going in the right direction:

Code: [Select]
int pin = 0
int val;

void setup()
{
  Serial.begin(9600);
  analogReference(EXTERNAL);
}

void loop()
{
  if (micros() < 125) {
  val = analogRead(pin);
  Serial.println(val);
  }
}


The sample rate can be anything as long as the quality is roughly the same as when you record your voice on a mobile phone.

I'm also unsure about clipping the result to -128 or 127, would that be a function the signed int "val" would be wrapped in?

Sorry I should of mentioned, I havnt got the sd reader yet so I was just hoping to see the samples in the serial monitor for now, or if successfull I can capture the sample data live into Matlab using the fscanf function.
M

semicolo

You won't get near the sound quality you can get on a mobile phone which can do 44KHz/16bits.
The best an arduino can do is 10KHz/10bits using the arduino core (bypassing the arduino system you could go up to 15KHz/10bits, it's also written in the datasheet you can go higher by losing resolution but it's not really clear how, probably increasing the ADC clock and just reading the 8 higher bits since the 2 lowest become inaccurate, so maybe 44KHz/8bits at best).
You connect 3.3V to ARef not VCC which is 5V on the uno, then yes connect your audio input to A0.

I mentioned clipping in case values go beyond an 8 bits value:
If there's no sound you should read a value of 512, whith sound it will move around this 512 value. So substracting 512 will remove the offset.
Now if the level is low, the values will stay between -128/127 which fit nicely in an 8 bit value.
If it rarely goes beyond -128/127 you can just clip the sound to -128 or 127 to keep it in the 8bit range.
If it goes a lot above these values, you'll need to do otherwise, that's why I advised to first make some tests to see what you get.

for the micros stuff I was thinking something like (not tested)

Code: [Select]

long time;

void setup() {
  time=micros();
  analogReference(EXTERNAL);
}

void loop() {
  while (micros() < time+125); // this should give 125us intervals
  // do stuff after that 
}

xl97

#6
Mar 25, 2013, 09:52 pm Last Edit: Mar 25, 2013, 09:53 pm by xl97 Reason: 1
sorry.. didnt read through the whole thread..

so if this doesnt apply (sorry)  :)


But the Adafruit Waveshield.. that normall uses WaveHC library for .wav file playback FROM a microSD..

also has a library called WaveRP  (Record/Play).. that records audio..

this may be of some help to you? or give some more direction?



http://code.google.com/p/waverp/

Quote

WaveRP is an Arduino library for recording and playing Wave files with the Adafruit Wave Shield. It records 8-bit mono files at 4,000 to 44,100 samples per second.

Use of the Wave record/play library, WaveRP, requires the following:

Arduino with a 5 volt 328 processor.

Low noise power source such as a nine volt DC adapter or battery.

Adafruit Wave Shield (version 1.1 is best but 1.0 works)

Microphone preamp. A circuit for a simple preamp is included in the documentation.

Microphone, PC type with 3.5 mm plug. See the documentation for details.

SD/SDHC formatted with 32KB allocation units.

See the readme.txt file and library documentation for more information .
[/quote



HTH..

daz1761

@semicolo:  Thanks again for the help!  So lets see if I got this right, if the microphone sensor is outputing a value of 512 to the serial monitor when its not receiving anything means that there is an offset on the Y axis of its output?  So lets say I subtracted the 512, that would take the serial output to 0 when its not receiving anything.  If I am correct does that mean the defined integer to start with would be unsigned to receive values of -127 to 128?  And would the code look like this:

Code: [Select]
unsigned int = analogRead(pin)-512

Sorry for all the questions but I'm enjoying the learning curve  :)

@xl97:  Thanks for the script, yes I have seen the wav shield and I joined the forum to ask if this shield would solve my little recording problem...  I was quite shocked to get no response from any of their users! 
M


semicolo

Don't use unsigned types to store signed values!

More like
Code: [Select]

int value = analogRead(pin)-512;
if (value > 127)
  value = 127;
if (value < -128)
  value = -128;


Go Up