Ну вот при содействии форумчан удалось таки записать звук с микрофона. ESP32-wrover-b, Микрофон на плате max9814 (OUT подключен к GPIO36 (SENSOR VP)), и microSD-карта class 10 8Гб. Звук пишется довольно качественно для голоса, длина записи может регулироваться конечным размером аудиоданных не стал заморачиваться с кнопками, цель была не в этом. Формат файла 8 бит, 8КГц.
Скетч:
Прошу предложения, замечания и 12-ти битный wav-файл (они вообще бывают и проигрываются стандартными плеерами?). Не допер как собрать чанк формата и не нашел конвертера который бы мог сделать 12 бит, а так хоть хексом подгляжу.
Скетч:
Код:
#include <Arduino.h>
#include <driver/adc.h>
#include "FS.h"
#include "SD.h"
#include "SPI.h"
#define AUDIO_BUFFER_MAX 51200 //эмпирически выбрал. склеек не слышно. буфер успевает записаться на SD пока другой заполняется новыми аудио данными
uint8_t audioBuffer[AUDIO_BUFFER_MAX];
uint8_t audioBufferTmp[AUDIO_BUFFER_MAX];
uint32_t bufferPointer = 0;
bool transmitNow = false;
bool recordStarting = false;
hw_timer_t * timer = NULL; // our timer
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
fs::File fContent;
int touch_sensor_value = 0;
const int VALUE_THRESHOLD = 70;
volatile bool audio_buffer_ready = false;
int interruptCounter = 0;
size_t audio_data_size = 0;
byte header[44] = {};
bool startRecording = true;
void setup() {
Serial.begin(115200);
if (!SD.begin()) {
Serial.println("Card Mount Failed");
startRecording = false;
return;
}
startRecording = true;
if (SD.exists("/file.wav"))
SD.remove("/file.wav");
Serial.println("Ready");
adc1_config_width(ADC_WIDTH_12Bit);
adc1_config_channel_atten(ADC1_CHANNEL_0, ADC_ATTEN_11db);
fContent = SD.open("/file.wav", FILE_WRITE);
fContent.write((const byte *)header, sizeof(header));
Serial.println("Rec started file.wav");
timer = timerBegin(0, 80, true);
timerAttachInterrupt(timer, &onTimer, true);
timerAlarmWrite(timer, 125, true);
timerAlarmEnable(timer);
}
void IRAM_ATTR onTimer() {
portENTER_CRITICAL_ISR(&timerMux);
uint16_t sample = adc1_get_raw(ADC1_CHANNEL_0);
uint8_t value = map(sample, 0, 4095, 0, 255);
audioBuffer[bufferPointer] = value;
bufferPointer++;
if (bufferPointer == AUDIO_BUFFER_MAX)
{
memcpy(audioBufferTmp, audioBuffer, AUDIO_BUFFER_MAX);
bufferPointer = 0;
audio_buffer_ready = true;
}
portEXIT_CRITICAL_ISR(&timerMux);
}
void loop() {
if (!startRecording)
return;
if (audio_buffer_ready)
{
audio_buffer_ready = false;
audio_data_size += fContent.write((const uint8_t *)audioBufferTmp, sizeof(audioBufferTmp));
}
if (audio_data_size > 500000) //500000 это тот самый размер аудиоданных (~1 мин)
{
startRecording = false;
timerAlarmDisable(timer);
CreateWavHeader(header, audio_data_size);
fContent.seek(0);
fContent.write((const byte *)header, sizeof(header));
fContent.close();
SD.end(); //корректно отключаем SD, я уже одну убил
Serial.println("Done!");
Serial.print("Audio Data size:");
Serial.println(audio_data_size, DEC);
}
}
void CreateWavHeader(byte* header, int waveDataSize) {
header[0] = 'R';
header[1] = 'I';
header[2] = 'F';
header[3] = 'F';
unsigned int fileSizeMinus8 = waveDataSize + 44 - 8;
header[4] = (byte)(fileSizeMinus8 & 0xFF);
header[5] = (byte)((fileSizeMinus8 >> 8) & 0xFF);
header[6] = (byte)((fileSizeMinus8 >> 16) & 0xFF);
header[7] = (byte)((fileSizeMinus8 >> 24) & 0xFF);
header[8] = 'W';
header[9] = 'A';
header[10] = 'V';
header[11] = 'E';
header[12] = 'f';
header[13] = 'm';
header[14] = 't';
header[15] = ' ';
header[16] = 0x10;
header[17] = 0x00;
header[18] = 0x00;
header[19] = 0x00;
header[20] = 0x01;
header[21] = 0x00;
header[22] = 0x01;
header[23] = 0x00;
header[24] = 0x40;
header[25] = 0x1F;
header[26] = 0x00;
header[27] = 0x00;
header[28] = 0x40;
header[29] = 0x1F;
header[30] = 0x00;
header[31] = 0x00;
header[32] = 0x01;
header[33] = 0x00;
header[34] = 0x08;
header[35] = 0x00;
header[36] = 'd';
header[37] = 'a';
header[38] = 't';
header[39] = 'a';
header[40] = (byte)(waveDataSize & 0xFF);
header[41] = (byte)((waveDataSize >> 8) & 0xFF);
header[42] = (byte)((waveDataSize >> 16) & 0xFF);
header[43] = (byte)((waveDataSize >> 24) & 0xFF);
}
uint16_t changeEndianess(uint16_t val)
{
return (val << 8) | ((val >> 8) & 0x00ff);
}