Reputation: 95
For a personal project, I need to record voice sample with a MAX9814 microphone using a esp32. The output pin of the microphone is linked to GPIO35 so I using internal ADC1 channel 7, CS pin of sd card module is wired up with GPIO5.
After reading documentation and Atomic14 explanation, I manage to write this code which therefore uses the I2S module :
#include <SPI.h>
#include <SD.h>
#include <rec-sound.h>
#include <driver/i2s.h>
// Configuration of the SD Card
const int chipSelect = 5;
// I2S Parameters
#define I2S_SAMPLE_RATE 16000
#define I2S_NUM_CHANNELS 1
#define I2S_BITS_PER_SAMPLE 16
#define RECORD_DURATION 3 // Duration in seconds
// Analog Microphone Settings - ADC1_CHANNEL_7 is GPIO35
#define ADC_MIC_CHANNEL ADC1_CHANNEL_7
// Header structure for wav file
struct wav_header {
char riff[4];
int32_t flength;
char wave[4];
char fmt[4];
int32_t chunk_size;
int16_t format_tag;
int16_t num_chans;
int32_t sample_rate;
int32_t bytes_per_second;
int16_t bytes_per_sample;
int16_t bits_per_sample;
char data[4];
int32_t dlength;
};
const int header_length = sizeof(struct wav_header);
// File on the SD Card
File wavFile;
QueueHandle_t i2s_queue;
void writeWavHeader(File &file_inp){
struct wav_header wavh;
strncpy(wavh.riff, "RIFF", 4);
strncpy(wavh.wave, "WAVE", 4);
strncpy(wavh.fmt, "fmt ", 4);
strncpy(wavh.data, "data", 4);
wavh.chunk_size = 16;
wavh.format_tag = 1;
wavh.num_chans = 1;
wavh.sample_rate = I2S_SAMPLE_RATE;
wavh.bits_per_sample = I2S_BITS_PER_SAMPLE;
wavh.bytes_per_second = wavh.sample_rate * wavh.bits_per_sample / 8 * wavh.num_chans;
wavh.bytes_per_sample = wavh.bits_per_sample / 8 * wavh.num_chans;
wavh.dlength = 0; // Will be updated later
wavh.flength = 36 + wavh.dlength; // Will be updated later
file_inp.write((byte*)&wavh, header_length);
}
void updateWavHeader(File &file) {
uint32_t fileSize = file.size();
uint32_t dataSize = fileSize - header_length;
file.seek(4);
file.write((byte*)&fileSize, 4); // Update flength
file.seek(40);
file.write((byte*)&dataSize, 4); // Update dlength
}
void setupI2S() {
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN),
.sample_rate = I2S_SAMPLE_RATE,
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = I2S_COMM_FORMAT_I2S_LSB,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 4,
.dma_buf_len = 1024,
.use_apll = false,
.tx_desc_auto_clear = false,
.fixed_mclk = 0};
//install and start i2s driver
i2s_driver_install(I2S_NUM_0, &i2s_config, 4, &i2s_queue);
//init ADC pad
i2s_set_adc_mode(ADC_UNIT_1, ADC1_CHANNEL_7);
// enable the ADC
i2s_adc_enable(I2S_NUM_0);
}
void record_mic() {
if (!SD.begin(chipSelect)) {
Serial.println("Erreur d'initialisation de la carte SD!");
while (1);
}
// Créer un nouveau fichier WAV
wavFile = SD.open("/audio.wav", FILE_WRITE);
if (!wavFile) {
Serial.println("Erreur lors de la création du fichier WAV");
return;
}
// Prepare WAV header without data size, which will be updated after saving
writeWavHeader(wavFile);
setupI2S();
Serial.println("Début de l'enregistrement...");
size_t bytes_read;
int16_t i2s_samples[256]; // Buffer for I2S samples
unsigned long startMillis = millis();
while (millis() - startMillis < RECORD_DURATION * 1000) {
i2s_read(I2S_NUM_0, i2s_samples, sizeof(i2s_samples), &bytes_read, portMAX_DELAY);
wavFile.write((byte*)i2s_samples, bytes_read);
}
// Update the data size in the WAV header
updateWavHeader(wavFile);
wavFile.close();
i2s_driver_uninstall(I2S_NUM_0);
Serial.println("Enregistrement terminé.");
}
void delete_audio_file() {
// Initialisation de la carte SD
if (!SD.begin(chipSelect)) {
Serial.println("Erreur d'initialisation de la carte SD!");
while (1);
}
Serial.println("Carte SD initialisée.");
// Supprimer le fichier audio
if (SD.exists("/audio.wav")) {
if (SD.remove("/audio.wav")) {
Serial.println("Fichier audio.wav supprimé.");
} else {
Serial.println("Erreur lors de la suppression du fichier audio.wav.");
}
} else {
Serial.println("Fichier audio.wav n'existe pas.");
}
}
But unfortunately the sound file recorded on the SD card is inaudible, as you can see on Audacity:
Moreover, it's a bit weird because the duration of the audio is close to 6 seconds while I defined 3 seconds in the code. It's possible that there is an issue in the writing of wav metadata, but I think a bad configuration of I2S is more likely.
Thank you in advance for your suggestions!
Upvotes: 0
Views: 433