Hi all,
below is the WAV RECORDER example adapted to use the same approach:
{ Record MIC to Micro SD Card, wav format }
/*
* DI2S Version,
* WAV Recorder for Seeed XIAO ESP32S3 Sense
*
* Original: https://wiki.seeedstudio.com/xiao_esp32s3_sense_mic/
*/
#include "driver/i2s.h"
#include "FS.h"
#include "SD.h"
#include "SPI.h"
// make changes as needed
#define RECORD_TIME 20 // seconds, The maximum value is 240
#define WAV_FILE_NAME "arduino_rec_DI2S"
// do not change for best
#define SAMPLE_RATE 16000U
#define SAMPLE_BITS 16
#define WAV_HEADER_SIZE 44
#define VOLUME_GAIN 2
void setup() {
Serial.begin(115200);
while (!Serial) ;
i2s_init();
if(!SD.begin(21)){
Serial.println("Failed to mount SD Card!");
while (1) ;
}
record_wav();
i2s_deinit();
}
void loop() {
delay(1000);
Serial.printf(".");
}
void record_wav() {
delay(2000);
uint32_t sample_size = 0;
uint32_t record_size = (SAMPLE_RATE * SAMPLE_BITS / 8) * RECORD_TIME;
uint8_t *rec_buffer = NULL;
Serial.printf("Ready to start recording ...\n");
File file = SD.open("/"WAV_FILE_NAME".wav", FILE_WRITE);
// Write the header to the WAV file
uint8_t wav_header[WAV_HEADER_SIZE];
generate_wav_header(wav_header, record_size, SAMPLE_RATE);
file.write(wav_header, WAV_HEADER_SIZE);
// PSRAM malloc for recording
rec_buffer = (uint8_t *)ps_malloc(record_size);
if (rec_buffer == NULL) {
Serial.printf("malloc failed!\n");
while(1) ;
}
Serial.printf("Buffer: %d bytes\n", ESP.getPsramSize() - ESP.getFreePsram());
// Start recording
i2s_read((i2s_port_t)0, (void*)rec_buffer, record_size, &sample_size, portMAX_DELAY);
if (sample_size == 0) {
Serial.printf("Record Failed!\n");
} else {
Serial.printf("Record %d bytes\n", sample_size);
}
// Increase volume
for (uint32_t i = 0; i < sample_size; i += SAMPLE_BITS/8) {
(*(uint16_t *)(rec_buffer+i)) <<= VOLUME_GAIN;
}
// Write data to the WAV file
Serial.printf("Writing to the file ...\n");
if (file.write(rec_buffer, record_size) != record_size)
Serial.printf("Write file Failed!\n");
free(rec_buffer);
file.close();
Serial.printf("The recording is over.\n");
}
void generate_wav_header(uint8_t *wav_header, uint32_t wav_size, uint32_t sample_rate) {
// See this for reference: http://soundfile.sapp.org/doc/WaveFormat/
uint32_t file_size = wav_size + WAV_HEADER_SIZE - 8;
uint32_t byte_rate = SAMPLE_RATE * SAMPLE_BITS / 8;
const uint8_t set_wav_header[] = {
'R', 'I', 'F', 'F', // ChunkID
file_size, file_size >> 8, file_size >> 16, file_size >> 24, // ChunkSize
'W', 'A', 'V', 'E', // Format
'f', 'm', 't', ' ', // Subchunk1ID
0x10, 0x00, 0x00, 0x00, // Subchunk1Size (16 for PCM)
0x01, 0x00, // AudioFormat (1 for PCM)
0x01, 0x00, // NumChannels (1 channel)
sample_rate, sample_rate >> 8, sample_rate >> 16, sample_rate >> 24, // SampleRate
byte_rate, byte_rate >> 8, byte_rate >> 16, byte_rate >> 24, // ByteRate
0x02, 0x00, // BlockAlign
0x10, 0x00, // BitsPerSample (16 bits)
'd', 'a', 't', 'a', // Subchunk2ID
wav_size, wav_size >> 8, wav_size >> 16, wav_size >> 24, // Subchunk2Size
};
memcpy(wav_header, set_wav_header, sizeof(set_wav_header));
}
static int i2s_init() {
// Start listening for audio: MONO @ 16/16KHz
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM ),
.sample_rate = 16000U,
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
//.channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT, // Also works
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
//.communication_format = I2S_COMM_FORMAT_PCM, // Also works
.communication_format = I2S_COMM_FORMAT_I2S,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 8,
.dma_buf_len = 512,
.use_apll = false,
.tx_desc_auto_clear = false,
.fixed_mclk = 0
};
i2s_pin_config_t pin_config = {
.bck_io_num = -1, // IIS_SCLK
.ws_io_num = 42, // IIS_LCLK
.data_out_num = -1, // IIS_DSIN
.data_in_num = 41, // IIS_DOUT
};
esp_err_t ret = 0;
ret = i2s_driver_install((i2s_port_t)0, &i2s_config, 0, NULL);
if (ret != ESP_OK) {
Serial.printf("Error in i2s_driver_install");
}
ret = i2s_set_pin((i2s_port_t)0, &pin_config);
if (ret != ESP_OK) {
Serial.printf("Error in i2s_set_pin");
}
ret = i2s_zero_dma_buffer((i2s_port_t)0);
if (ret != ESP_OK) {
Serial.printf("Error in initializing dma buffer with 0");
}
return int(ret);
}
static int i2s_deinit(void) {
i2s_driver_uninstall((i2s_port_t)0); //stop & destroy i2s driver
return 0;
}
Regards all,
Valter