Arduino Forum

Using Arduino => Audio => Topic started by: Lucario448 on Feb 22, 2016, 05:04 am

Title: Record audio from a microphone to an SD card?
Post by: Lucario448 on Feb 22, 2016, 05:04 am
Hello there!
My idea goes like this: I want to try to record the sound from a microphone (like my voice), to an SD card. I guess I can't expect record it at a sampling rate higher than 8 KHz (due to the timing of the functions). The audio will be stored in a "raw file" (because I don't know how to create the WAVE/RIFF header automatically); and maybe playback that recording with the same board (but that's the "stage two" of my plan). Now here are my questions:



Thanks beforehand and sorry if I made misspellings.
Title: Re: Record audio from a microphone to an SD card?
Post by: Grumpy_Mike on Feb 22, 2016, 11:15 am
1) you need an amplifier
2) no you need to bias the input waveform to 2.5V
3) shift
4) push switch, or when the input envelope drops to zero for a certain time
Title: Re: Record audio from a microphone to an SD card?
Post by: Lucario448 on Feb 22, 2016, 05:30 pm
1) you need an amplifier
Even for a desktop computer microphone?

Quote
2) no you need to bias the input waveform to 2.5V
Is that like mixing 2.5V with my audio signal?
If so, can I just put both in the same pin, or do I need some additional components? (Apart from a voltage divider)
Title: Re: Record audio from a microphone to an SD card?
Post by: Grumpy_Mike on Feb 22, 2016, 06:00 pm
Quote
Even for a desktop computer microphone?
Yes.

Quote
Is that like mixing 2.5V with my audio signal?
If you like to think of it like that. The proper way of describing is adding a DC offset.

Quote
If so, can I just put both in the same pin,
Yes you have to.
Use 10K pull up and pull down on the analogue input and couple the audio in with a none polerised capacitor as big as you have got.
Title: Re: Record audio from a microphone to an SD card?
Post by: Lucario448 on Feb 22, 2016, 08:09 pm
Use 10K pull up and pull down on the analogue input
I think this is the voltage divider part, right?

Quote
and couple the audio in with a none polerised capacitor as big as you have got.
Title: Re: Record audio from a microphone to an SD card?
Post by: DVDdoug on Feb 22, 2016, 11:04 pm
Quote
Even for a desktop computer microphone?
Almost all "computer microphones" are electret condenser types and they require 5V power (normally supplied by the soundcard).

Here is an example (https://www.sparkfun.com/datasheets/BreakoutBoards/Amplified-Mic-Electret-v14.pdf) of an electret microphone preamp circuit with power for the mic and biased output.


Quote
Is that like mixing 2.5V with my audio signal?
Yes.   The Arduino can't read negative voltages, so and AC audio signal must be biased.   (You can subtract-out the bias in software if you wish.)   Hre is an example (http://www.instructables.com/id/Arduino-Audio-Input/step4/DC-Offset/) of a bias circuit.

Title: Re: Record audio from a microphone to an SD card?
Post by: Grumpy_Mike on Feb 22, 2016, 11:19 pm
Quote
How that capacitor goes here? Between the signal and the input pin
yes.

Quote
Non-polarized capacitor of which type?
doesn't matter.
Title: Re: Record audio from a microphone to an SD card?
Post by: Lucario448 on Feb 23, 2016, 01:40 am
All right, thank you very much!
Is not that hard to do this, but now I'm worried about two things:

analogRead function is so slow by default (and still not yet tested its "fast mode")
I don't know how long takes writting a byte to a file in a SD card. Will the technique discussed in this thread (http://"http://forum.arduino.cc/index.php?topic=377029.60") work too?
Title: Re: Record audio from a microphone to an SD card?
Post by: Grumpy_Mike on Feb 23, 2016, 03:04 pm
Quote
I don't know how long takes writting a byte to a file in a SD card.
No and you will not find out because it is not fixed. It depends on the type of SD card, where abouts on the card it is and its age. Plus a lot more factors.

Quote
Will the technique discussed in this thread work too?
No idea, the url is wrong.
Title: Re: Record audio from a microphone to an SD card?
Post by: Lucario448 on Feb 24, 2016, 05:03 am
No idea, the url is wrong.
Jeesh what I made wrong this time? How can I get the actual URL of a thread?
Title: Re: Record audio from a microphone to an SD card?
Post by: Grumpy_Mike on Feb 24, 2016, 08:45 am
Copy and past normally works for me. Just put the link into url tags and don't use the link icon.
Title: Re: Record audio from a microphone to an SD card?
Post by: Lucario448 on Feb 24, 2016, 08:02 pm
Copy and past normally works for me. Just put the link into url tags and don't use the link icon.
https://forum.arduino.cc/index.php?topic=377029.60 (https://forum.arduino.cc/index.php?topic=377029.60)

This is the actual URL of the thread then. Hope it works properly this time...
Title: Re: Record audio from a microphone to an SD card?
Post by: Grumpy_Mike on Feb 25, 2016, 08:28 am
Yes it will work.
Another technique is to put a pin high, do the code and put it low, using port manipulation. Then measure the width of the pulse on an oscilloscope.
Title: Re: Record audio from a microphone to an SD card?
Post by: Lucario448 on Feb 25, 2016, 07:32 pm
Another technique is to put a pin high, do the code and put it low, using port manipulation.
Will the "port manipulation" execute almost instantly? (unlike the digitalWrite function)

Quote
Then measure the width of the pulse on an oscilloscope.
Awwwwww. Will a cheapy one work too? I mean, this one:
http://www.amazon.com/SainSmart-DSO138-1Msps-Digital-Oscilloscope/dp/B00XXZB5LW (http://www.amazon.com/SainSmart-DSO138-1Msps-Digital-Oscilloscope/dp/B00XXZB5LW)
Title: Re: Record audio from a microphone to an SD card?
Post by: Grumpy_Mike on Feb 25, 2016, 11:07 pm
Quote
Will the "port manipulation" execute almost instantly?
Yes.

Quote
Will a cheapy one work too?
No that one is way too slow. It will only work at 1M samples per second. You have a 16MHz processor so to actually measure anything approaching accurately you need it 100 times better than this.
Title: Re: Record audio from a microphone to an SD card?
Post by: flyrontech on Feb 26, 2016, 08:11 am
FN-RM01 is a high quality MP3 audio recorder that can record voice messages to a micro SD card. Maybe you can take a few to try. It's available here on Aliexpress.
http://www.aliexpress.com/item/Digital-Audio-Recorder-with-Playback-Function-2-PCS-A-lot-MP3-Sound-Recorder-Module-micro-SD/32603016265.html?spm=2114.01010208.3.1.7UHOP1&ws_ab_test=searchweb201556_6,searchweb201602_3_505_506_503_504_10020_502_10014_10001_10002_10017_10005_10006_10003_10021_10004_10022_10018_10019,searchweb201603_1&btsid=9ee0e5dc-21b1-41d5-9541-67a047a64b5f
Title: Re: Record audio from a microphone to an SD card?
Post by: Lucario448 on Feb 26, 2016, 09:55 pm
No that one is way too slow. It will only work at 1M samples per second. You have a 16MHz processor so to actually measure anything approaching accurately you need it 100 times better than this.
Oh well, I don't wanna spend a lot of money on this, so the micros timer is my only way I think.

By the way, the MP3 module can be useful for this purpose, but I just wanna use the Arduino itself if possible. But, because the MCU hasn't enough memory for record sounds, then the cheapest way to get more space, is by interacting with a SD card (in any form factor). However, thanks anyways...
Title: Re: Record audio from a microphone to an SD card?
Post by: CrossRoads on Feb 26, 2016, 10:02 pm
Take a read thru here
http://forum.arduino.cc/index.php?topic=180769.0 (http://forum.arduino.cc/index.php?topic=180769.0)
I designed this card for the project, got hung up on integrating the ADC & DAC into it, but left myself some room to play some more when I had some time. You can see that fat16lib had the code working to record mono audio to SD card at CD quality speed/data (16 bit data, 44.1 KHz)
http://www.crossroadsfencing.com/BobuinoRev17/ (http://www.crossroadsfencing.com/BobuinoRev17/)
(http://www.crossroadsfencing.com/BobuinoRev17/Bobuino2_MIKROE483_screw.jpg)
Title: Re: Record audio from a microphone to an SD card?
Post by: CrossRoads on Feb 26, 2016, 10:03 pm
(and I got carried away and added screw terminals too vs making them a shield to sit on top)
Title: Re: Record audio from a microphone to an SD card?
Post by: Lucario448 on Feb 27, 2016, 08:26 pm
Take a read thru here
http://forum.arduino.cc/index.php?topic=180769.0 (http://forum.arduino.cc/index.php?topic=180769.0)
I've read it. Is that the code for that board of yours?

Quote
I designed this card for the project, got hung up on integrating the ADC & DAC into it, but left myself some room to play some more when I had some time. You can see that fat16lib had the code working to record mono audio to SD card at CD quality speed/data (16 bit data, 44.1 KHz)
http://www.crossroadsfencing.com/BobuinoRev17/ (http://www.crossroadsfencing.com/BobuinoRev17/)
Is that like "all-I-need-in-one" board? Yeah, it looks promising, but... I'm trying to keep up with the simple stuff.
By the way, how you can achieve a higher sampling rate? Because of the SRAM or the ADC?

And again, thank you for your replys!
Title: Re: Record audio from a microphone to an SD card?
Post by: Lucario448 on Feb 29, 2016, 05:12 pm
Oh and one more thing. This is how my SD card module will look like:
http://www.amazon.com/gp/aw/d/B00JOBVQ8Q (http://www.amazon.com/gp/aw/d/B00JOBVQ8Q)
Now my questions are:



Thanks beforehand.
Title: Re: Record audio from a microphone to an SD card?
Post by: Lucario448 on Feb 29, 2016, 10:27 pm
I've read in this page how to create the WAV file's header: http://www.topherlee.com/software/pcm-tut-wavformat.html (http://www.topherlee.com/software/pcm-tut-wavformat.html)
Now I have even more doubts (talking about the File class in the SD library):


Thanks again!
Title: Re: Record audio from a microphone to an SD card?
Post by: Grumpy_Mike on Mar 01, 2016, 02:25 pm
The big problem is there is a disconnect between the pictures and the words. The words say "ARM Arduino" that means a 3V3 one like the Due or the Zero. BUT the pictures show there is a restive divider on the logic lines meaning it is meant to be run with 5V signals.

Quote
The module has a 5V pin, would be actually safe, for the SD card, input that voltage in there? Or shall I use the 3.3V output of my board?
It looks like that module has an on board voltage regulator so connect the +5V and do not connect the 3V3.

Quote
Is the MCU actually fully compatible with a 3.3V logic level for SPI communication? I mean, what if the MOSI pin receives 5V?
It looks like the module has potential dividers on the pins.

Quote
The pins of the module, are those labeled in pairs or just for a single one?
Not at all sure what you mean. Why should anything be in pairs?

Quote
Which function will put an exact copy of this array into the file? write or print?
Nether. But write puts the actual byte in the file and print puts an ASCII representation of the value of the byte.

Quote
The size count of the file is updated every time I write (not overwrite) a new byte into it, right?
Don't know.

Quote
The print function writes an unsigned int variable as a character string
Yes.

Quote
is there a way to convert an unsigned int type variable into an array of bytes? (in its "byte form")
Yes
Code: [Select]

upperByte = variable >> 8;
lowerByte = variable && 0xff;



Title: Re: Record audio from a microphone to an SD card?
Post by: Lucario448 on Mar 01, 2016, 09:06 pm
Not at all sure what you mean. Why should anything be in pairs?
Ok, then let me explain you better this time. If you notice, every couple of pins are labeled in an horizontal line. Take a closer look at... let's say, the MOSI label; next to it, there are two pins arranged horizontally. My question is: are those couple of pins connected together? What do you think? (I hope you have understood me this time)

PD: I don't know how to tag (post) a picture, that would be easier for you...

Quote
Nether. But write puts the actual byte in the file and print puts an ASCII representation of the value of the byte.
That's fine. I could simply write every single byte by using a for loop. But wait... is there a write function that receives an entire array of bytes? Isn't that the same thing?

Quote
Code: [Select]

upperByte = variable >> 8;
lowerByte = variable && 0xff;

There are some things that I'm worried about.



I'm asking you all this because I think there is no function in the File class that writes any type of variable as a bunch of bytes (not in a character string form)
Title: Re: Record audio from a microphone to an SD card?
Post by: Grumpy_Mike on Mar 01, 2016, 09:35 pm
Quote
My question is: are those couple of pins connected together?
No look at the back, one row are connected to ground. This is normal practice.

Quote
is there a write function that receives an entire array of bytes?
Not that I know of.

Quote
Will that pair of lines just extract two bytes?
Yes.

Quote
The int type isn't supposed to have 4 bytes?
Correct the int type doesn't have four bytes it has two on an Arduino.


Quote
I need it in the "little-endian" order
So? I don't see the problem, just write it like that.

Title: Re: Record audio from a microphone to an SD card?
Post by: Lucario448 on Mar 02, 2016, 01:41 am
No look at the back, one row are connected to ground. This is normal practice.
If that is true, then this module will be nearly impossible to place in a "protoboard".

Quote
Correct the int type doesn't have four bytes it has two on an Arduino.
All right then. Let me see if I'm correct:



So what can I do? I need an unsigned integer of 4 bytes. :/
Title: Re: Record audio from a microphone to an SD card?
Post by: Grumpy_Mike on Mar 02, 2016, 07:47 am
Long int has four bytes, a long long has eight.
Title: Re: Record audio from a microphone to an SD card?
Post by: Lucario448 on Mar 02, 2016, 04:11 pm
Long int has four bytes, a long long has eight.
So, what's the keyword? (on the Arduino IDE of course)
"int" or "long int"?
Title: Re: Record audio from a microphone to an SD card?
Post by: Grumpy_Mike on Mar 02, 2016, 06:48 pm

https://www.arduino.cc/en/Reference/VariableDeclaration (https://www.arduino.cc/en/Reference/VariableDeclaration)

or

https://learn.sparkfun.com/tutorials/data-types-in-arduino (https://learn.sparkfun.com/tutorials/data-types-in-arduino)
Title: Re: Record audio from a microphone to an SD card?
Post by: Lucario448 on Mar 02, 2016, 11:55 pm
All right, so the unsigned long type is what I need. I don't think a 8 KHz sampling rate can be disrupted by long-type variable operations.
Now the thing is: how to extract every single byte from that variable, and in what order they will be extracted? I'll take care of the "byte order" part...
Title: Re: Record audio from a microphone to an SD card?
Post by: Grumpy_Mike on Mar 03, 2016, 12:43 am
Same as reply #22 only you do a bit more shifting.
Code: [Select]

byte0 = value & 0xff;
byte1 = (value >> 8) & 0xff;
byte2 = (value >> 16) & 0xff;
byte3 = (value >> 24) & 0xff;
Title: Re: Record audio from a microphone to an SD card?
Post by: pjrc on Mar 03, 2016, 01:25 am
By the way, how you can achieve a higher sampling rate?
If you're willing to go with 32 bit ARM, the Teensy audio library has working 44.1 kHz play and record, and a lot more.

This 48 minute tutorial video shows many of the features.

https://www.youtube.com/watch?v=wqt55OAabVs (https://www.youtube.com/watch?v=wqt55OAabVs)

However, recording the SD card isn't show in the video.  But you can find the example code here:
https://github.com/PaulStoffregen/Audio/blob/master/examples/Recorder/Recorder.ino (https://github.com/PaulStoffregen/Audio/blob/master/examples/Recorder/Recorder.ino)

If you really want to stay on 8 bit AVR, you're probably going to have to settle for lower quality sound.  Moving so much data around on a slow chip without DMA is really hard.  On a faster 32 bit chip with an optimized library that uses DMA to efficiently bring the audio in and out, it's much easier.
Title: Re: Record audio from a microphone to an SD card?
Post by: Lucario448 on Mar 04, 2016, 08:20 pm
I don't know what happened, but I thought I've replied that last post. I've said that the board looks awesome, and already acknowledged that with a AVR MCU I can't expect a recording sampling rate higher than 8 KHz; but, I wanna do this with what I have on hand. And also wondering if by writing data directly to the SD card there would be a jitter in the sampling rate.

On the other hand, I made this sketch for my audio recorder, compilable as it is, for now it is not well documented; but I hope that the code is self-explanatory.
I'm open to hear any suggestion, improvement, optimization, etc.; that I should make to this code. If you think that a comment is redundant or irrelevant, then just ignore it (again, it is not well documented yet).

Now here is the code:
Code: [Select]

/*
  SD card attached to SPI bus as follows:
** MOSI - pin 11
** MISO - pin 12
** CLK - pin 13
** CS - pin 10
*/

#include <SPI.h>
#include <SD.h>

PROGMEM const byte header [44] =
 // This contains the header of a WAV file. Without this, it is not recognized as such.
 // 44 bytes long.
{
 0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56,
 0x45, 0x66, 0x6D, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
 0x01, 0x00, 0x40, 0x1F, 0x00, 0x00, 0x40, 0x1F, 0x00, 0x00, 0x01,
 0x00, 0x08, 0x00, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00
};

const byte firstPos = 4;
// Position in the file to write down the overall file size minus 8.
const byte secondPos = 40;
// Position in the file to write down the overall file size minus 44.
const byte button = 2; // Pin for the button.
const byte led = 4;
// Pin for the status LED. Unfortunately, the built-in LED is already
// used by the SPI.
byte buttonState = LOW;
// Remember the button state before test the loop's condition. LOW is default or
// not pressed.
File recording;

void setup() {

 pinMode(button, INPUT);
 pinMode(led, OUTPUT);
 pinMode(10, OUTPUT);
 ADCSRA = (ADCSRA & 0xf8) | 0x04; // ADC fast mode
 digitalWrite(led, LOW);
 if (!SD.begin(10)) {
   errorStatus(); // SD card failure
 }
 if (SD.exists("REC001.wav")) {
   if (!SD.remove("REC001.wav")) {
     errorStatus();
     // Any previous (or incomplete) recording should be deleted
     // in order to make a new one. This error might occur due to
     // write-protected or damaged card.
   }
 }
}

void loop() {
 if (digitalRead(button) == HIGH) {
   recording = SD.open("REC001.wav", FILE_WRITE);
   if (recording) {
     writeHeader();
     standby();
     buttonState = LOW;
     record();
     finalize();
     finishStatus();
   } else {
     errorStatus(); // Might be write-protected card or else
   }
 }
}

void writeHeader() {
 // Puts the "idetification" of a typical WAV file (because .wav isn't enough)
 for (byte pos = 0; pos < sizeof(header); pos++) {
   recording.write(pgm_read_byte(&header[pos]));
 }
}

void record() {
 /*
  * This is how the recording process works. This will last until (normally)
  * the press of the button.
  *
  * DO NOT RESET OR POWER-down THE BOARD WHILE IN THIS STATE, UNTIL THE STATUS LED
  * GETS IN THE FINISHED STATE; otherwise file corruption and/or SD card damage will occur.
  *
  * Exceeding 4 GiB file size (149hr 7min 50sec of audio recording), when meeting a file system's
  * limitation, or filling up the memory; may cause unexpected behavior.
  */
 byte sample = 0;
 digitalWrite(led, HIGH);
 while (buttonState == LOW) {
   sample = analogRead(A0) >> 2;
   recording.write(sample);
   buttonState = digitalRead(button);
   delayMicroseconds(0);
   // Make a trial an error test to know the amount of delay
 }
 digitalWrite(led, LOW);
}

void finalize() {
 // Fills up two necessary variables in the file's header,
 // then ensures a successfully saved recording.
 byte finalValue[4];
 unsigned long fileSize = recording.size();
 unsigned long riffSize = fileSize - 8;
 unsigned long dataSize = fileSize - 44;

 finalValue[0] = riffSize & 0xff;
 finalValue[1] = (riffSize >> 8) & 0xff;
 finalValue[2] = (riffSize >> 16) & 0xff;
 finalValue[3] = (riffSize >> 24) & 0xff;
 // Is possible to make a fuction that returns an array of bytes?

 recording.seek(firstPos);
 recording.write(finalValue, 4);
 // Check if already in little-endian order

 finalValue[0] = dataSize & 0xff;
 finalValue[1] = (dataSize >> 8) & 0xff;
 finalValue[2] = (dataSize >> 16) & 0xff;
 finalValue[3] = (dataSize >> 24) & 0xff;
 // Is possible to make a fuction that returns an array of bytes?

 recording.seek(secondPos);
 recording.write(finalValue, 4);
 // Check if already in little-endian order
 recording.close();
}

void errorStatus() {
 // The status LED endlessly indicates a critical error.
 // The only way out, is by resetting the MCU (reset button or power down).
 while (true) {
   digitalWrite(led, HIGH);
   delay(250);
   digitalWrite(led, LOW);
   delay(250);
 }
}


void finishStatus() {
/* The status LED endlessly indicates a successfully saved recording.
 * The only way out, is by resetting the MCU (reset button or power down).
 *
 * From here, it is safe to reset or power-down the board.
 *
 * If there is a way to generate filenames automatically, then this function
 * will become useless.
 */
 while (true) {
   digitalWrite(led, HIGH);
   delay(1000);
   digitalWrite(led, LOW);
   delay(1000);
 }
}

void standby() {
 // The status LED endlessly indicates that the MCU is ready to record
 // (until you press the button)
 while (true) {
   digitalWrite(led, HIGH);
   if (digitalRead(button) == HIGH) {
     break;
   }
   delay(500);
   digitalWrite(led, LOW);
   if (digitalRead(button) == HIGH) {
     break;
   }
   delay(500);
 }
}
Title: Re: Record audio from a microphone to an SD card?
Post by: CrossRoads on Mar 04, 2016, 08:35 pm
Thanks, the board is quasi developmental, quasi datalogger, whatever you might find a SD card & RTC & RS232 & dual hardware serial ports with lots of SRAM (16K, twice that of a Mega) useful for.  I wired one up to prove out a standalone programmer because it had the right parts - 3.3V buffered SD card and 400mA 3.3V regulator. 150mA from an Uno/Mega is not enough to power an SD card.
I think fat16lib had the code running on a 328P board also. The fast ADC and DAC are what allow the higher sampling rate. 8 or 10 bits at lower rates don't sound that good for audio. I was going for electronic drums eventually, will get there at some point.  Need to re-visit  the trigger and peak detect circuit I had working back on 1990 before we bought a  house and moved and started doing all that homeowner stuff.