How to play this kind voice file?

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);
  
}

I don't know... I assume the library plays files as well as records them? Are you using an Arduino with a DAC?

If you can read the SD card on your computer and it's a valid WAV file you should be able to play it on your computer.

Sample Rate = 32kHz
16-bits = 2 bytes per sample (4 bytes per sample if stereo).
32K x 2 bytes x 5 seconds = 320kB.

If the whole file looks like that, something's wrong. With a 16-bit audio half of the samples should be negative, and some bigger values unless the file is very quiet. A series of zeros is "digital silence" but you'll never get pure silence if you are recording analog.

(8-bit WAV files are biased positive numbers and silence is 127 or128... I never remember exactly... The bias is taken-out at playback time.)

3 Likes

From the code, it's not a WAV file. It's a stream of I2S samples from the ADC. I2S is nominally a stereo interface. So I don't know if those are L & R or mono.

Presumably, you could simply run them through an I2S DAC. Whether that's internal or external to the ESP32 remains to be seen.

3 Likes

Thank you DVDdoug.
Yes, the all code like that, guess some thing wrong and I'll check it.

thank you gfvalvo.
yes. it is a MAX9814 mic recorded I2S data, the file is 1.6M. sampling rate (32,000 Hz) is the reason of large file?

so you capture 32K sounds sample over 2 bytes in stereo for each second. Your file is 5 seconds

32K samples/s x 2bytes/sample x 2channels x 5seconds = 640K bytes

but you write the data in decimal in the SD card (building a huge String :man_shrugging: :grimacing: :roll_eyes:...)

so any sample above 9 in decimal will take more than 1 byte in the file, not to mention the commas.

so that's why you get a huge file.

1 Like

Thank you J-M-L.
not only the larger file, the mic used MAX9814 is way low quality than the new one I got INMP441.

I like to use INMP441 with an existing code from THAT Project:

it stored audio FILE to SPIFFS, may I have a solution to save the audio to SD card?

I simply put: writeFile(SD, "/filename", audio_file.c_str()); to replace: file = SPIFFS.open(filename, FILE_WRITE); at Line 39, seems nothing written on SD? sure added relative headers.
I'll attached the modified code short later.

you have to deal with all the file.write() - this is the one saving the sample for example

1 Like

Thank you J-M-L.
there are 8 places related to 'write', 5 deal with 'flash_write_buff', do I need keep them for write to SD?

also, is that true that the SPIFFS conflict to SD card in ESP32? got into rebooting when included SD library in.

I put "*" beside 'write'.

 SPIFFS.remove(filename);
  file = SPIFFS.open(filename, FILE_*WRITE*);
  if(!file){
    Serial.println("File is not available!");
  }

  byte header[headerSize];
  wavHeader(header, FLASH_RECORD_SIZE);

  file.*write*(header, headerSize);
  listSPIFFS();
  char* i2s_read_buff = (char*) calloc(i2s_read_len, sizeof(char));
    uint8_t* flash_*write*_buff = (uint8_t*) calloc(i2s_read_len, sizeof(char));

    i2s_read(I2S_PORT, (void*) i2s_read_buff, i2s_read_len, &bytes_read, portMAX_DELAY);
    i2s_read(I2S_PORT, (void*) i2s_read_buff, i2s_read_len, &bytes_read, portMAX_DELAY);
    
    Serial.println(" *** Recording Start *** ");
    while (flash_wr_size < FLASH_RECORD_SIZE) {
        //read data from I2S bus, in this case, from ADC.
        i2s_read(I2S_PORT, (void*) i2s_read_buff, i2s_read_len, &bytes_read, portMAX_DELAY);
        //example_disp_buf((uint8_t*) i2s_read_buff, 64);
        //save original data from I2S(ADC) into flash.
        i2s_adc_data_scale(flash_*write*_buff, (uint8_t*)i2s_read_buff, i2s_read_len);
        file.*write*((const byte*) flash_*write*_buff, i2s_read_len);
        flash_wr_size += i2s_read_len;
        ets_printf("Sound recording %u%%\n", flash_wr_size * 100 / FLASH_RECORD_SIZE);
        ets_printf("Never Used Stack Size: %u\n", uxTaskGetStackHighWaterMark(NULL));
    }
    file.close();

    free(i2s_read_buff);
    i2s_read_buff = NULL;
    free(flash_*write*_buff);
    flash_*write*_buff = NULL;

In the file you linked
ThatProject/ESP32_MICROPHONE/ESP32_INMP441_RECORDING/ESP32_INMP441_RECORDING.ino at master · 0015/ThatProject · GitHub

there are only 2 file.write()

  • one when they open the file and write the WAV header
  • one for dumping the recording

what you flagged like
file = SPIFFS.open(filename, FILE_*WRITE*)
is just the fact the file is being created in WRITE mode.


I believe you can use SPIFFS and the SD file system (use Espressif APIs) but probably need to be careful on memory usage

1 Like

Thanks.
I upload the code with: "No OTA(1MB APP/3MB SPIFFS) " still got rebooting:

ELF file SHA256: e7629d5257fac8e7
13:33:05.573 -> 
13:33:05.709 -> Rebooting...
13:33:05.709 -> ets Jun  8 2016 00:22:57
13:33:05.709 -> 
13:33:05.709 -> rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
13:33:05.709 -> configsip: 0, SPIWP:0xee
13:33:05.709 -> clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
13:33:05.743 -> mode:DIO, clock div:1
13:33:05.743 -> load:0x3fff0030,len:1344
13:33:05.743 -> load:0x40078000,len:13964
13:33:05.743 -> load:0x40080400,len:3600
13:33:05.743 -> entry 0x400805f0
13:33:06.538 -> Writing file: /filename
13:33:06.538 -> Failed to open file for writing
13:33:06.538 -> 
13:33:06.538 -> Listing SPIFFS files:
13:33:06.538 -> =================================================
13:33:06.538 ->   File name                              Size
13:33:06.538 -> =================================================
13:33:06.741 ->   recording.wav                             0 bytes
13:33:06.809 -> =================================================
13:33:06.809 -> 
13:33:07.825 -> SD Card Type: SDHC
13:33:07.825 -> SD Card Size: 29818MB
13:33:08.841 ->  *** Recording Start *** 
13:33:09.487 -> Writing file: /filename
13:33:10.471 -> ets Jun  8 2016 00:22:57

Do you need spiff at all?

1 Like

I've removed SPIFFS thorough.
and modified code as below, still rebooting , where is wrong?

#include <driver/i2s.h>
#include "FS.h"
#include "SD.h"
#include "SPI.h"

#define I2S_WS  25   //15
#define I2S_SD  33   // 13
#define I2S_SCK 32   // 2
#define recordBTN 14

#define I2S_PORT I2S_NUM_0
#define I2S_SAMPLE_RATE   (16000)
#define I2S_SAMPLE_BITS   (16)
#define I2S_READ_LEN      (16 * 1024)
#define RECORD_TIME       (5) //Seconds
#define I2S_CHANNEL_NUM   (1)
#define FLASH_RECORD_SIZE (I2S_CHANNEL_NUM * I2S_SAMPLE_RATE * I2S_SAMPLE_BITS / 8 * RECORD_TIME)

File file;
const char filename[] = "/recording.wav";
const int headerSize = 44;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);

  pinMode(recordBTN, INPUT);

  SDsetting();
  i2sInit();
  xTaskCreate(i2s_adc, "i2s_adc", 1024 * 2, NULL, 1, NULL);
}

void loop() {
  // put your main code here, to run repeatedly:

}


void i2sInit(){
  i2s_config_t i2s_config = {
    .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
    .sample_rate = I2S_SAMPLE_RATE,
    .bits_per_sample = i2s_bits_per_sample_t(I2S_SAMPLE_BITS),
    .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
    .communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB),
    .intr_alloc_flags = 0,
    .dma_buf_count = 64,
    .dma_buf_len = 1024,
    .use_apll = 1
  };

  i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);

  const i2s_pin_config_t pin_config = {
    .bck_io_num = I2S_SCK,
    .ws_io_num = I2S_WS,
    .data_out_num = -1,
    .data_in_num = I2S_SD
  };

  i2s_set_pin(I2S_PORT, &pin_config);
}


void i2s_adc_data_scale(uint8_t * d_buff, uint8_t* s_buff, uint32_t len)
{
    uint32_t j = 0;
    uint32_t dac_value = 0;
    for (int i = 0; i < len; i += 2) {
        dac_value = ((((uint16_t) (s_buff[i + 1] & 0xf) << 8) | ((s_buff[i + 0]))));
        d_buff[j++] = 0;
        d_buff[j++] = dac_value * 256 / 2048;
    }
}

void i2s_adc(void *arg)
{
    
    int i2s_read_len = I2S_READ_LEN;
    int flash_wr_size = 0;
    size_t bytes_read;

    char* i2s_read_buff = (char*) calloc(i2s_read_len, sizeof(char));
    uint8_t* flash_write_buff = (uint8_t*) calloc(i2s_read_len, sizeof(char));

    i2s_read(I2S_PORT, (void*) i2s_read_buff, i2s_read_len, &bytes_read, portMAX_DELAY);
    i2s_read(I2S_PORT, (void*) i2s_read_buff, i2s_read_len, &bytes_read, portMAX_DELAY);
    
    Serial.println(" *** Recording Start *** ");
    while (flash_wr_size < FLASH_RECORD_SIZE) {
        //read data from I2S bus, in this case, from ADC.
        i2s_read(I2S_PORT, (void*) i2s_read_buff, i2s_read_len, &bytes_read, portMAX_DELAY);
        //example_disp_buf((uint8_t*) i2s_read_buff, 64);
        //save original data from I2S(ADC) into flash.
        i2s_adc_data_scale(flash_write_buff, (uint8_t*)i2s_read_buff, i2s_read_len);
        file.write((const byte*) flash_write_buff, i2s_read_len);
        flash_wr_size += i2s_read_len;

        //................ADD
        // If the data.txt file doesn't exist
       // Create a file on the SD card and write the data labels
       File file = SD.open("/audio.txt");
       if (!file) {
        Serial.println("File doens't exist");
        Serial.println("Creating file...");
        writeFile(SD, "/audio.txt", "");
    }
    appendFile(SD, "/audio.txt", "i2s_read_buff");
          
        ets_printf("Sound recording %u%%\n", flash_wr_size * 100 / FLASH_RECORD_SIZE);
        ets_printf("Never Used Stack Size: %u\n", uxTaskGetStackHighWaterMark(NULL));

    }
    file.close();

    free(i2s_read_buff);
    i2s_read_buff = NULL;
    free(flash_write_buff);
    flash_write_buff = NULL;
    
//   listSPIFFS();
    vTaskDelete(NULL);
}

void example_disp_buf(uint8_t* buf, int length)
{
    printf("======\n");
    for (int i = 0; i < length; i++) {
        printf("%02x ", buf[i]);
        if ((i + 1) % 8 == 0) {
            printf("\n");
        }
    }
    printf("======\n");
}

void wavHeader(byte* header, int wavSize){
  header[0] = 'R';
  header[1] = 'I';
  header[2] = 'F';
  header[3] = 'F';
  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);
  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] = 0x80;
  header[25] = 0x3E;
  header[26] = 0x00;
  header[27] = 0x00;
  header[28] = 0x00;
  header[29] = 0x7D;
  header[30] = 0x00;
  header[31] = 0x00;
  header[32] = 0x02;
  header[33] = 0x00;
  header[34] = 0x10;
  header[35] = 0x00;
  header[36] = 'd';
  header[37] = 'a';
  header[38] = 't';
  header[39] = 'a';
  header[40] = (byte)(wavSize & 0xFF);
  header[41] = (byte)((wavSize >> 8) & 0xFF);
  header[42] = (byte)((wavSize >> 16) & 0xFF);
  header[43] = (byte)((wavSize >> 24) & 0xFF);
  
}

void SDsetting() {

  if (!SD.begin()) {
    Serial.println("Card Mount Failed");
    return;
  }
  uint8_t cardType = SD.cardType();

  if (cardType == CARD_NONE) {
    Serial.println("No SD card attached");
 //   warning_Beep();
    return;
  }

  Serial.print("SD Card Type: ");
  if (cardType == CARD_MMC) {
    Serial.println("MMC");
  } else if (cardType == CARD_SD) {
    Serial.println("SDSC");
  } else if (cardType == CARD_SDHC) {
    Serial.println("SDHC");
  } else {
    Serial.println("UNKNOWN");
  }

  uint64_t cardSize = SD.cardSize() / (1024 * 1024);
  Serial.printf("SD Card Size: %lluMB\n", cardSize);

}


void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
    Serial.printf("Listing directory: %s\n", dirname);

    File root = fs.open(dirname);
    if(!root){
        Serial.println("Failed to open directory");
        return;
    }
    if(!root.isDirectory()){
        Serial.println("Not a directory");
        return;
    }

    File file = root.openNextFile();
    while(file){
        if(file.isDirectory()){
            Serial.print("  DIR : ");
            Serial.println(file.name());
            if(levels){
                listDir(fs, file.path(), levels -1);
            }
        } else {
            Serial.print("  FILE: ");
            Serial.print(file.name());
            Serial.print("  SIZE: ");
            Serial.println(file.size());
        }
        file = root.openNextFile();
    }
}

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();
}

Thank you gfvalvo.
The unit used ESP32 internal I2S and left only with L/R to GND.
seems it can be play with by ESP32 I2S? why here got just digital code and the sketch below got playable wav file?

Try opening the file once and closing it when all is received

1 Like

Thanks.

The revision code below, it is not upto the file operate yet, rebooting happened as long as SD card checked.

#include <driver/i2s.h>
#include "FS.h"
#include "SD.h"
#include "SPI.h"

#define I2S_WS  25   //15
#define I2S_SD  33   // 13
#define I2S_SCK 32   // 2
#define recordBTN 14

#define I2S_PORT I2S_NUM_0
#define I2S_SAMPLE_RATE   (16000)
#define I2S_SAMPLE_BITS   (16)
#define I2S_READ_LEN      (16 * 1024)
#define RECORD_TIME       (5) //Seconds
#define I2S_CHANNEL_NUM   (1)
#define FLASH_RECORD_SIZE (I2S_CHANNEL_NUM * I2S_SAMPLE_RATE * I2S_SAMPLE_BITS / 8 * RECORD_TIME)

File file;
const char filename[] = "/recording.wav";
const int headerSize = 44;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);

  pinMode(recordBTN, INPUT);

  SDsetting();
  i2sInit();
  xTaskCreate(i2s_adc, "i2s_adc", 1024 * 2, NULL, 1, NULL);
}

void loop() {
  // put your main code here, to run repeatedly:

}


void i2sInit(){
  i2s_config_t i2s_config = {
    .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
    .sample_rate = I2S_SAMPLE_RATE,
    .bits_per_sample = i2s_bits_per_sample_t(I2S_SAMPLE_BITS),
    .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
    .communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB),
    .intr_alloc_flags = 0,
    .dma_buf_count = 64,
    .dma_buf_len = 1024,
    .use_apll = 1
  };

  i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);

  const i2s_pin_config_t pin_config = {
    .bck_io_num = I2S_SCK,
    .ws_io_num = I2S_WS,
    .data_out_num = -1,
    .data_in_num = I2S_SD
  };

  i2s_set_pin(I2S_PORT, &pin_config);
}


void i2s_adc_data_scale(uint8_t * d_buff, uint8_t* s_buff, uint32_t len)
{
    uint32_t j = 0;
    uint32_t dac_value = 0;
    for (int i = 0; i < len; i += 2) {
        dac_value = ((((uint16_t) (s_buff[i + 1] & 0xf) << 8) | ((s_buff[i + 0]))));
        d_buff[j++] = 0;
        d_buff[j++] = dac_value * 256 / 2048;
    }
}

void i2s_adc(void *arg)
{
    
    int i2s_read_len = I2S_READ_LEN;
    int flash_wr_size = 0;
    size_t bytes_read;

    char* i2s_read_buff = (char*) calloc(i2s_read_len, sizeof(char));
    uint8_t* flash_write_buff = (uint8_t*) calloc(i2s_read_len, sizeof(char));

    i2s_read(I2S_PORT, (void*) i2s_read_buff, i2s_read_len, &bytes_read, portMAX_DELAY);
    i2s_read(I2S_PORT, (void*) i2s_read_buff, i2s_read_len, &bytes_read, portMAX_DELAY);
    
    Serial.println(" *** Recording Start *** ");
    while (flash_wr_size < FLASH_RECORD_SIZE) {
        //read data from I2S bus, in this case, from ADC.
        i2s_read(I2S_PORT, (void*) i2s_read_buff, i2s_read_len, &bytes_read, portMAX_DELAY);
        //example_disp_buf((uint8_t*) i2s_read_buff, 64);
        //save original data from I2S(ADC) into flash.
        i2s_adc_data_scale(flash_write_buff, (uint8_t*)i2s_read_buff, i2s_read_len);
        file.write((const byte*) flash_write_buff, i2s_read_len);
        flash_wr_size += i2s_read_len;

        //................ADD
        // If the data.txt file doesn't exist
       // Create a file on the SD card and write the data labels
       File file = SD.open("/audio.txt");
       if (!file) {
        Serial.println("File doens't exist");
        Serial.println("Creating file...");
        writeFile(SD, "/audio.txt", "");
    }
    appendFile(SD, "/audio.txt", "i2s_read_buff");
          
        ets_printf("Sound recording %u%%\n", flash_wr_size * 100 / FLASH_RECORD_SIZE);
        ets_printf("Never Used Stack Size: %u\n", uxTaskGetStackHighWaterMark(NULL));

    }
    file.close();

    free(i2s_read_buff);
    i2s_read_buff = NULL;
    free(flash_write_buff);
    flash_write_buff = NULL;
    
//   listSPIFFS();
    vTaskDelete(NULL);
}

void example_disp_buf(uint8_t* buf, int length)
{
    printf("======\n");
    for (int i = 0; i < length; i++) {
        printf("%02x ", buf[i]);
        if ((i + 1) % 8 == 0) {
            printf("\n");
        }
    }
    printf("======\n");
}

void wavHeader(byte* header, int wavSize){
  header[0] = 'R';
  header[1] = 'I';
  header[2] = 'F';
  header[3] = 'F';
  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);
  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] = 0x80;
  header[25] = 0x3E;
  header[26] = 0x00;
  header[27] = 0x00;
  header[28] = 0x00;
  header[29] = 0x7D;
  header[30] = 0x00;
  header[31] = 0x00;
  header[32] = 0x02;
  header[33] = 0x00;
  header[34] = 0x10;
  header[35] = 0x00;
  header[36] = 'd';
  header[37] = 'a';
  header[38] = 't';
  header[39] = 'a';
  header[40] = (byte)(wavSize & 0xFF);
  header[41] = (byte)((wavSize >> 8) & 0xFF);
  header[42] = (byte)((wavSize >> 16) & 0xFF);
  header[43] = (byte)((wavSize >> 24) & 0xFF);
  
}

void SDsetting() {

  if (!SD.begin()) {
    Serial.println("Card Mount Failed");
    return;
  }
  uint8_t cardType = SD.cardType();

  if (cardType == CARD_NONE) {
    Serial.println("No SD card attached");
 //   warning_Beep();
    return;
  }

  Serial.print("SD Card Type: ");
  if (cardType == CARD_MMC) {
    Serial.println("MMC");
  } else if (cardType == CARD_SD) {
    Serial.println("SDSC");
  } else if (cardType == CARD_SDHC) {
    Serial.println("SDHC");
  } else {
    Serial.println("UNKNOWN");
  }

  uint64_t cardSize = SD.cardSize() / (1024 * 1024);
  Serial.printf("SD Card Size: %lluMB\n", cardSize);

}

/* 
void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
    Serial.printf("Listing directory: %s\n", dirname);

    File root = fs.open(dirname);
    if(!root){
        Serial.println("Failed to open directory");
        return;
    }
    if(!root.isDirectory()){
        Serial.println("Not a directory");
        return;
    }

    File file = root.openNextFile();
    while(file){
        if(file.isDirectory()){
            Serial.print("  DIR : ");
            Serial.println(file.name());
            if(levels){
                listDir(fs, file.path(), levels -1);
            }
        } else {
            Serial.print("  FILE: ");
            Serial.print(file.name());
            Serial.print("  SIZE: ");
            Serial.println(file.size());
        }
        file = root.openNextFile();
    }
}   */

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();
}

Serial Monitor:

10:15:37.966 -> ELF file SHA256: ea50376e75406204
10:15:37.966 -> 
10:15:38.101 -> Rebooting...
10:15:38.101 -> ets Jun  8 2016 00:22:57
10:15:38.101 -> 
10:15:38.101 -> rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
10:15:38.101 -> configsip: 0, SPIWP:0xee
10:15:38.135 -> clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
10:15:38.135 -> mode:DIO, clock div:1
10:15:38.135 -> load:0x3fff0030,len:1344
10:15:38.135 -> load:0x40078000,len:13964
10:15:38.135 -> load:0x40080400,len:3600
10:15:38.135 -> entry 0x400805f0
10:15:38.375 -> SD Card Type: SDHC
10:15:38.375 -> SD Card Size: 29818MB
10:15:39.427 ->  *** Recording Start *** 
10:15:39.938 -> Guru Meditation Error: Core  0 panic'ed (Unhandled debug exception). 
10:15:39.938 -> Debug exception reason: Stack canary watchpoint triggered (i2s_adc) 
10:15:39.938 -> Core  0 register dump:
10:15:39.938 -> PC      : 0x40084b01  PS      : 0x00060836  A0      : 0x00060830  A1      : 0x3ffe6730  
10:15:39.938 -> A2      : 0x3ffbdb8c  A3      : 0x00000000  A4      : 0x3ffc3600  A5      : 0x000000c0  
10:15:39.969 -> A6      : 0x00040000  A7      : 0x00000010  A8      : 0x3ff65000  A9      : 0x00000001  
10:15:39.969 -> A10     : 0x00000010  A11     : 0x00000010  A12     : 0x00000030  A13     : 0x00000040  
10:15:39.969 -> A14     : 0x00040000  A15     : 0xffffffff  SAR     : 0x0000000a  EXCCAUSE: 0x00000001  
10:15:39.969 -> EXCVADDR: 0x00000000  LBEG    : 0x4008465d  LEND    : 0x40084665  LCOUNT  : 0x00000027  
10:15:40.008 -> 
10:15:40.008 -> 
10:15:40.008 -> Backtrace: 0x40084afe:0x3ffe6730 0x0006082d:0x3ffe6820 |<-CORRUPTED
10:15:40.008 -> 
10:15:40.008 -> 
10:15:40.008 -> 
10:15:40.008 -> 
10:15:40.008 -> ELF file SHA256: ea50376e75406204
10:15:40.008 -> 
10:15:40.144 -> Rebooting...

here you write in the file

but you open it only later

1 Like

moved that line:

 //save original data from I2S(ADC) into flash.

        File file = SD.open("/audio.txt");
        
        i2s_adc_data_scale(flash_write_buff, (uint8_t*)i2s_read_buff, i2s_read_len);
       

still rebooting.
searched online said power supply, I added one external power beside USB, no changes.

post the code for the i2s_adc() task

1 Like

this one:

void i2s_adc(void *arg)
{
    
    int i2s_read_len = I2S_READ_LEN;
    int flash_wr_size = 0;
    size_t bytes_read;

    char* i2s_read_buff = (char*) calloc(i2s_read_len, sizeof(char));
    uint8_t* flash_write_buff = (uint8_t*) calloc(i2s_read_len, sizeof(char));

    i2s_read(I2S_PORT, (void*) i2s_read_buff, i2s_read_len, &bytes_read, portMAX_DELAY);
    i2s_read(I2S_PORT, (void*) i2s_read_buff, i2s_read_len, &bytes_read, portMAX_DELAY);
    
    Serial.println(" *** Recording Start *** ");
    while (flash_wr_size < FLASH_RECORD_SIZE) {
        //read data from I2S bus, in this case, from ADC.
        i2s_read(I2S_PORT, (void*) i2s_read_buff, i2s_read_len, &bytes_read, portMAX_DELAY);
        //example_disp_buf((uint8_t*) i2s_read_buff, 64);
        //save original data from I2S(ADC) into flash.

        File file = SD.open("/audio.txt");
        
        i2s_adc_data_scale(flash_write_buff, (uint8_t*)i2s_read_buff, i2s_read_len);
        file.write((const byte*) flash_write_buff, i2s_read_len);
        flash_wr_size += i2s_read_len;

        //................ADD
        // If the data.txt file doesn't exist
       // Create a file on the SD card and write the data labels
    //   File file = SD.open("/audio.txt");
       if (!file) {
        Serial.println("File doens't exist");
        Serial.println("Creating file...");
        writeFile(SD, "/audio.txt", "");
    }
    appendFile(SD, "/audio.txt", "i2s_read_buff");
          
        ets_printf("Sound recording %u%%\n", flash_wr_size * 100 / FLASH_RECORD_SIZE);
        ets_printf("Never Used Stack Size: %u\n", uxTaskGetStackHighWaterMark(NULL));

    }
    file.close();

    free(i2s_read_buff);
    i2s_read_buff = NULL;
    free(flash_write_buff);
    flash_write_buff = NULL;
    
//   listSPIFFS();
    vTaskDelete(NULL);
}