Hi all.
the sketch below recorded 5 seconds and generated a huge code file and saved to SD card, how to play it?
the file like this:
4095,4095,4038,4038,3919,3919,3964,3964,3936,3936,3924,3924,3904, ..........
Thanks
Adam
#include <driver/i2s.h>
#include <SPI.h> // Using SPI interface for the SD card
#include <SD.h> // A dedicated library for the SD card
#include "FS.h"
#define I2S_SAMPLE_RATE 32000 // 32KHz
#define ADC_INPUT ADC1_CHANNEL_5 //pin 33
#define I2S_SAMPLE_BITS I2S_BITS_PER_SAMPLE_16BIT // 16 Bits
#define RECORD_TIME 5 // 5 Seconds
#define MIC 33
#define BUTTON 32
const int chipSelect = 5;
uint32_t wavSize = I2S_SAMPLE_RATE * I2S_SAMPLE_BITS / 8 * RECORD_TIME;
void setup() {
// Serial monitor
Serial.begin(115200);
// Button
pinMode(BUTTON,INPUT);
// Initialize the I2S peripheral
i2sInit();
// SD card:
// see if the card is present and can be initialized:
while (!SD.begin(chipSelect)) // If there was a faliure
{
Serial.println("Card failed, or not present");
delay(1000);
}
Serial.println("card initialized.");
delay(1000);
}
int rec_time = 5000; // 5 Seconds
void loop() {
if (digitalRead(BUTTON)) // Button pushed = Start recording
{
Serial.println("Adding info");
int now = millis();
while (millis() - now < rec_time)
{
save_audio();
}
Serial.println("Finished!");
}
}
// Mic functions:
void i2sInit()
{
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, // The format of the signal using ADC_BUILT_IN
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, // is fixed at 12bit, stereo, MSB
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
.communication_format = I2S_COMM_FORMAT_I2S_MSB,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 8,
.dma_buf_len = 1024,
.use_apll = false,
.tx_desc_auto_clear = false,
.fixed_mclk = 0
};
i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
i2s_set_adc_mode(ADC_UNIT_1, ADC_INPUT);
i2s_adc_enable(I2S_NUM_0);
}
String audio_file = "";
int buff_len = 2048;
void save_audio() {
// The 4 high bits are the channel, and the data is inverted
uint16_t offset = (int)ADC_INPUT * 0x1000 + 0xFFF;
size_t bytes_read;
uint16_t buffer[buff_len] = {0};
uint16_t music;
i2s_read(I2S_NUM_0, &buffer, sizeof(buffer), &bytes_read, portMAX_DELAY);
if (bytes_read == sizeof(buffer)) { // If I've read all the data into the buffer, do something
for (int i=0;i<buff_len;i++)
{
audio_file+= String(offset - buffer[i]) + ",";
}
appendFile(SD, "/test.txt",audio_file.c_str());
audio_file = "";
} else {
Serial.println("buffer empty");
}
}
// SD functions:
void createDir(fs::FS &fs, const char * path){
Serial.printf("Creating Dir: %s\n", path);
if(fs.mkdir(path)){
Serial.println("Dir created");
} else {
Serial.println("mkdir failed");
}
}
void readFile(fs::FS &fs, const char * path){
Serial.printf("Reading file: %s\n", path);
File file = fs.open(path);
if(!file){
Serial.println("Failed to open file for reading");
return;
}
Serial.print("Read from file: ");
while(file.available()){
Serial.write(file.read());
}
file.close();
}
void writeFile(fs::FS &fs, const char * path, const char * message){
// Serial.printf("Writing file: %s\n", path);
File file = fs.open(path, FILE_WRITE);
if(!file){
Serial.println("Failed to open file for writing");
return;
}
if(file.print(message)){
// Serial.println("File written");
} else {
Serial.println("Write failed");
}
file.close();
}
void appendFile(fs::FS &fs, const char * path, const char * message){
//Serial.printf("Appending to file: %s\n", path);
File file = fs.open(path, FILE_APPEND);
if(!file){
Serial.println("Failed to open file for appending");
return;
}
if(file.print(message)){
// Serial.println("Message appended");
} else {
Serial.println("Append failed");
}
file.close();
}
// WAV
const int headerSize = 44;
void wavHeader(byte* header, int wavSize){
// First 4 are for the name RIFF
header[0] = 'R';
header[1] = 'I';
header[2] = 'F';
header[3] = 'F';
// Next is the file size, which can be calculated by the formula below:
// (I2S_CHANNEL_NUM * I2S_SAMPLE_RATE * I2S_SAMPLE_BITS / 8 * RECORD_TIME)
unsigned int fileSize = wavSize + headerSize - 8;
header[4] = (byte)(fileSize & 0xFF);
header[5] = (byte)((fileSize >> 8) & 0xFF);
header[6] = (byte)((fileSize >> 16) & 0xFF);
header[7] = (byte)((fileSize >> 24) & 0xFF);
// More strings
header[8] = 'W';
header[9] = 'A';
header[10] = 'V';
header[11] = 'E';
header[12] = 'f';
header[13] = 'm';
header[14] = 't';
header[15] = ' ';
// Size of format section (Not inverted)
header[16] = 0x10;
header[17] = 0x00;
header[18] = 0x00;
header[19] = 0x00;
// Format (1 = PCM)
header[20] = 0x01;
header[21] = 0x00;
// Channels (1=mono, 2=stereo)
header[22] = 0x01;
header[23] = 0x00;
// Sample rate (make sure it matches I2S_SAMPLE_RATE)
header[24] = 0x00;
header[25] = 0x7D;
header[26] = 0x00;
header[27] = 0x00;
// Byte rate (Sample rate * channels * bits per sample / 8)
header[28] = 0x00;
header[29] = 0xFA;
header[30] = 0x00;
header[31] = 0x00;
// Block allign : channels * bits per sample / 8
header[32] = 0x02;
header[33] = 0x00;
// Bits per sample (according to I2S_SAMPLE_BITS)
header[34] = 0x10;
header[35] = 0x00;
// Data name
header[36] = 'd';
header[37] = 'a';
header[38] = 't';
header[39] = 'a';
// Size of data
header[40] = (byte)(wavSize & 0xFF);
header[41] = (byte)((wavSize >> 8) & 0xFF);
header[42] = (byte)((wavSize >> 16) & 0xFF);
header[43] = (byte)((wavSize >> 24) & 0xFF);
}