Issue with Esp32 writing WAV data into micro SD card

Good morning everyone,
so here is my issue:


This image is showing the data saved on my micro sd card. As you all can see, 2 points are recorded correctly, 2 are incorrect and this pattern repeats itself throughout the file.
I thought maybe recording the I2S data into the buffer could be the issue.

Nope, everything looks good here.
So the source of my problem seems to be recording data from my buffer into the microSD card. How can I fix this?

The microSD card is in SPI (cannot change this, my PCB is designed this way). The I2S is setup in PCM, 24bit, 44100Hz, 1 channel.
Here is the code:

#include "Arduino.h"
#include "FS.h"
#include "Wav.h"
#include "I2S.h"
#include "SD.h"
#include "SPI.h"


//comment the first line and uncomment the second if you use ADC
#define I2S_MODE I2S_MODE_RX
//#define I2S_MODE I2S_MODE_ADC_BUILT_IN

const int record_time = 3;  // second
const char filename[] = "/sound.wav"; //name of file created

const int headerSize = 44; //WAV header size
const int waveDataSize = record_time * 132000; //rough calculation seconds * Byte rate
const int numCommunicationData = 4096; //number of byte in buffer
const int numPartWavData = numCommunicationData/4; //number of int32 in buffer
byte header[headerSize]; //contains wav header
int communicationData[numPartWavData]; //was char before, now stores the values received by the ADC
//char partWavData[numPartWavData]; //relic of old code
size_t bytesRead; //number of bytes read
File file; //create file variable to write to  

void setup() {
  Serial.begin(115200); //initialize serial communication
  if (!SD.begin()) Serial.println("SD begin failed"); //test if micro sd card is present and functionnal
  //wait for sd card to connect
  while(!SD.begin()){
    Serial.print(".");
    delay(500);
  }
  CreateWavHeader(header, waveDataSize); //create wav header in sd card
  SD.remove(filename);
  file = SD.open(filename, FILE_WRITE); //create file and set it up for write
  if (!file) return;
  file.write(header, headerSize); //write the wav header
  I2S_Init(I2S_MODE, I2S_BITS_PER_SAMPLE_32BIT); //initialize the I2S
  Serial.println("start recording");
  //for loop ends once ther is enough data recorded to fit the amount of time desired
  for (int j = 0; j < waveDataSize/numPartWavData; ++j) {
    i2s_read(I2S_NUM_0, (char *)communicationData, numCommunicationData ,&bytesRead, portMAX_DELAY); //read ADC and put values in buffer
    //ADC sends back signed 24bit value, need to bit shift since the wav file expects a signed int 32 bit 
    for (int i = 0; i < numPartWavData; i++)
    {
      communicationData[i] <<= 8;
    }    
    //display buffer part of the buffer to verify the values 
    printf("[0]%d [1]%d [2]%d [3]%d \n", communicationData[0], communicationData[1], communicationData[2], communicationData[3]);

    //both of these work but give out the same error
    //Only half of the values are written properly. 
    //file.write((const byte*)communicationData, numCommunicationData);
    file.print((char *)communicationData);
  }
  file.close();
  Serial.println("finish");
}

void loop() {
}

This is what I get when I put all the values in the buffer equal to 100000. As you all can see, even the second value is messed up and the 3rd and fourth are non existent.

Perhaps there is confusion over big and little endian and the size of default integer variables.

Carefully check the definition of .wav file format and how those relate to ESP32 integer variables.

What is the purpose of this line?

communicationData[i] <<= 8;

From my understanding the ADC sends a signed 24bit value (example: 0xFF FF FF)
When stored in an signed int32 it loses its signed property (example 0x 00 FF FF FF)
so,

communicationData[i] <<= 8;

allows me to keep the signed property (0xFF FF FF 00).

Now as for the big and little endian, I know the WAV header is little endian. Should I make a function that switches the byte places? Would that explain the holes I am seeing on audacity?

If your research determines that ESP32 integers are big endian, then that would be an excellent idea.

When stored in an signed int32 it loses its signed property

Only if you store it incorrectly.

ESP32 is little endian so the issue isn't there.

The i2s_read function stores the received data in a buffer, it does so byte by byte (thanks (char *)). I think my issue could be there, I'll try modifying that line.

i2s_read(I2S_NUM_0, (char *)communicationData, numCommunicationData ,&bytesRead, portMAX_DELAY); //read ADC and put values in buffer

changed it so we are strictly dealing with integers:

i2s_read(I2S_NUM_0, (int *)communicationData, numPartWavData ,&bytesRead, portMAX_DELAY); //read ADC and put values in buffer

and
image
Still the same issue as before. I'll try and extract the binary/hex values from the file and see if my understanding of wav if f***ed or it is really an issue with something else

Try writing a short file with a well defined constant data value, like 0x12345678, and take a look at a HEX format file dump.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.