How to record audio and save it to wav file using Electret Mic Amp - MAX9814?

Hi guys. Does anyone can guide me on how to record audio using electret mic amp max9814 and save it as wav file. I prefer not to use sd card, but if need, i have arduino sd card adapter. Very new at particle, so i need help with this. Thanks

You can have a look at this

1 Like

Hi sorry for the late reply, I was busy whole day. I’m trying right now, i don’t really quite understand how to use this library. Do you mind telling me the steps? I also don’t understand when they say about server, or node

1 Like

The server is “only” needed when you want to send the acquired data over TCP to some computer for further processing. For the actual signal captureing the 01-simple.cpp demo should be enough.

When you then want to store the captured data as WAV file you’d need to employ some storage (e.g. SD) and also provide the WAV header.

But there already are other threads in this forum that do deal with that - have a search.

Alright let me try, thanks for the help

Hi, I’m back. If i use the 01-simple.cpp demo, what is it used for? I don’t really quite understand what they are doing in this library. I tried to flash in the 01-simple.cpp, it says that flash is successful but there is nothing to show that my mic is recording or capturing any signal. Sorry, I’m quite new to firmware, coding or hardware. Once again, thanks for your help

This is what you want to look at

The acquired samples are stored (in the background - aka DMA) in one of the two buffers (buffer0 and buffer1) to which you get a pointer samples and can Do something with the samples - what that “something” is depends on your needs.

Okay, I understood. Let’s say I want to just take the data. Here’s is my code.

// Simple ADC DMA example

// Repository: https://github.com/rickkas7/ADCDMAGen3_RK
// License: MIT (free for use in open or closed source products)

#include "Particle.h"

#include "ADCDMAGen3_RK.h"

// Works threaded or not
SYSTEM_THREAD(ENABLED);

// Print debug message to USB serial
SerialLogHandler logHandler;

const size_t SAMPLE_FREQ = 16000; // Hz

const size_t SAMPLES_IN_BUFFER = 1024;

// This is where the samples are stored
static nrf_saadc_value_t buffer0[SAMPLES_IN_BUFFER];
static nrf_saadc_value_t buffer1[SAMPLES_IN_BUFFER];

static nrf_saadc_value_t *bufferReady = 0;


ADCDMAGen3 adc;

void myBufferCallback(nrf_saadc_value_t *buf, size_t size);
int result = 0;

void setup() {
	// Optional, just for testing so I can see the logs below
	// waitFor(Serial.isConnected, 10000);

	Serial.begin(9600);

	ret_code_t err = adc
		.withSampleFreqHz(SAMPLE_FREQ)
		.withDoubleBuffer(SAMPLES_IN_BUFFER, buffer0, buffer1)
		.withSamplePin(A0)
		.withBufferCallback(myBufferCallback)
		.init();

	Log.info("adc.init %lu", err);

	adc.start();
}

void loop() {

	if (bufferReady) {
		int16_t *samples = (int16_t *)bufferReady;
		bufferReady = 0;

		Serial.println(*samples);

		// Do something with the samples here
		// For the default 12-bit sampling, each index in samples will be 0 - 4095 (inclusive)

	}
}

void myBufferCallback(nrf_saadc_value_t *buf, size_t size) {
	// This gets executed after each sample buffer has been read.
	// Note: This is executed in interrupt context, so beware of what you do here!

	// We just remember the buffer and handle it from loop
	bufferReady = buf;
}

The data that i obtained from this, i copied it and pasted it to excel. The data shows no difference when i talk to the mic. It is very noisy. Let’s say I want to save this file as wav file so that i can try to play back. How do I save this file as .wav file?

I'd just repeat what I said before

I tried to use the code that you sent on other post

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

Not really sure what is this code means as the code was undefined in my vscode.

That’s because the hardware sampling in that project is meant for the Photon, so that won’t work on an Argon.
But the file handling would be the same. Hence you’d need to transfer only that part from the Photon project into your Argon sampling project.

Okay i try, then I’ll post my codes in. Thanks for your help. Its quite difficult for me to understand and hence i will take more time to understand it. Not IT person here hahaha, just trying to do some project for fun :blush:. Btw is arduino microSD card adapter is compatible? I saw the sdfat library, it only says adafruit one.

Use particle sdFat library in the webIDE or Workbench

Hi, thanks for helping me again @shanevanj. I tried but very difficult to understand hahaha. Which example do you think that will help me understand on how to use this library? This is what i have done so far. Still working on it and I’m trying to continue.

// Simple ADC DMA example

// Repository: https://github.com/rickkas7/ADCDMAGen3_RK
// License: MIT (free for use in open or closed source products)

#include "Particle.h"
#include "ADCDMAGen3_RK.h"
#include "adc_hal.h"
#include "gpio_hal.h"
#include "pinmap_hal.h"
#include "pinmap_impl.h"
#include <SdFat.h>

SdFat sd;
File myFile;
int fileCount=0;
const int SPI_CS = A2;

// Works threaded or not
SYSTEM_THREAD(ENABLED);

// Print debug message to USB serial
SerialLogHandler logHandler;

const size_t SAMPLE_FREQ = 16000; // Hz

const size_t SAMPLES_IN_BUFFER = 1024;

// This is where the samples are stored
static nrf_saadc_value_t buffer0[SAMPLES_IN_BUFFER];
static nrf_saadc_value_t buffer1[SAMPLES_IN_BUFFER];

static nrf_saadc_value_t *bufferReady = 0;


ADCDMAGen3 adc;

void myBufferCallback(nrf_saadc_value_t *buf, size_t size);
int result = 0;

void setup() {
	// Optional, just for testing so I can see the logs below
	// waitFor(Serial.isConnected, 10000);

	Serial.begin(9600);

	if(sd.begin= SPI_CS, SPI_FULL_SPEED))
	//the sd is underlined.
		Serial.println("SD initialised");
	else
		Serial.println("failed to open card");

	ret_code_t err = adc
		.withSampleFreqHz(SAMPLE_FREQ)
		.withDoubleBuffer(SAMPLES_IN_BUFFER, buffer0, buffer1)
		.withSamplePin(A0)
		.withBufferCallback(myBufferCallback)
		.init();

	Log.info("adc.init %lu", err);

	adc.start();
}

void loop() {

	if (bufferReady) {
		int16_t *samples = (int16_t *)bufferReady;
		bufferReady = 0;

		Serial.println(*samples);

		// Do something with the samples here
		// For the default 12-bit sampling, each index in samples will be 0 - 4095 (inclusive)

	}
}

void myBufferCallback(nrf_saadc_value_t *buf, size_t size) {
	// This gets executed after each sample buffer has been read.
	// Note: This is executed in interrupt context, so beware of what you do here!

	// We just remember the buffer and handle it from loop
	bufferReady = buf;
}









So do you get an expected result before the sd code is added?

What do you want to store on the SD? - and what do you want to do with it after it is stored?

Okay basically, what I want to do is to record audio using a MAX9814 electret Mic amp. I manage to get the when i used the code without SDFat. What i want to do is like a recorder. I can record audio when button is pressed, saved it into .wav file, then saved into my sd card. I also can listen to the recording from the wav file.

These are the codes:

// Simple ADC DMA example

// Repository: https://github.com/rickkas7/ADCDMAGen3_RK
// License: MIT (free for use in open or closed source products)

#include "Particle.h"

#include "ADCDMAGen3_RK.h"

// Works threaded or not
SYSTEM_THREAD(ENABLED);

// Print debug message to USB serial
SerialLogHandler logHandler;

const size_t SAMPLE_FREQ = 16000; // Hz

const size_t SAMPLES_IN_BUFFER = 1024;

// This is where the samples are stored
static nrf_saadc_value_t buffer0[SAMPLES_IN_BUFFER];
static nrf_saadc_value_t buffer1[SAMPLES_IN_BUFFER];

static nrf_saadc_value_t *bufferReady = 0;


ADCDMAGen3 adc;

void myBufferCallback(nrf_saadc_value_t *buf, size_t size);


void setup() {
	// Optional, just for testing so I can see the logs below
	// waitFor(Serial.isConnected, 10000);

	Serial.begin(9600);

	ret_code_t err = adc
		.withSampleFreqHz(SAMPLE_FREQ)
		.withDoubleBuffer(SAMPLES_IN_BUFFER, buffer0, buffer1)
		.withSamplePin(A0)
		.withBufferCallback(myBufferCallback)
		.init();

	Log.info("adc.init %lu", err);

	adc.start();
}

void loop() {

	if (bufferReady) {
		int16_t *samples = (int16_t *)bufferReady;
		bufferReady = 0;

		Serial.println(*samples);

		// Do something with the samples here
		// For the default 12-bit sampling, each index in samples will be 0 - 4095 (inclusive)

	}
}

void myBufferCallback(nrf_saadc_value_t *buf, size_t size) {
	// This gets executed after each sample buffer has been read.
	// Note: This is executed in interrupt context, so beware of what you do here!

	// We just remember the buffer and handle it from loop
	bufferReady = buf;
}









And this is the result that I got. (I got the result by copying the whole terminal, paste it into excel, make line graph). So what i was hoping is to save this as wav file so that i can play the recording.
image

So the

example is a good start to write the data to a file

I have no idea of how to convert to a .wav - sorry can’t help there.

Okay thank you very much. I’ll take a look.

I suspect that equal sign ( = ) should acutally be a opening parenthesis ( ( ).

You'd only need to write the WAV header populated with the correct values (mono, 16bit, 16kHz sampling), convert the unsigned 12 bit samples in signed 16 bit samples (as shown in the other post) and append them to the header and finally go back to the header and update the length field in the WAV header.

1 Like

Alright understood, I'll try it when i got home. Thank you very much. So far am i on the right track?

I will need to read up more about this. I will let u know if i need help. Sorry, I'm not too familiar with IT. What I had experienced before is Arduino, which is much simplier than this hahaha. Once again, thank you @ScruffR