Skip to main content
Niyathi Shenoy
Associate III
November 19, 2018
Question

I2S Data stored in .wav file not playing correctly!

  • November 19, 2018
  • 6 replies
  • 2355 views

Hi I have ADAU1978 which is a quad ADC that gives I2S data which im trying to store in a SD card under .wav extension. When i do this i get a .wav file of size 8kB. When i try to play it with windows media player, it doesnt throw any error,but doesnt play as well. I have attached the .wav file here. Also my code is as follows:

uint8_t pHeader[44]={0x00};

/*************WAVE Header FORMAT*************/

/* Write chunkID, must be 'RIFF' ------------------------------------------*/

 pHeader[0] = 'R';

 pHeader[1] = 'I';

 pHeader[2] = 'F';

 pHeader[3] = 'F';

  

 /* Write the file length ----------------------------------------------------*/

 /* The sampling time: this value will be be written back at the end of the 

   recording opearation. Example: 661500 Btyes = 0x000A17FC, byte[7]=0x00, byte[4]=0xFC */

pHeader[4] = 0x24;

 pHeader[5] = 0x65;

 pHeader[6] = 0x04;

 pHeader[7] = 0x00;

  

 /* Write the file format, must be 'WAVE' -----------------------------------*/

 pHeader[8] = 'W';

 pHeader[9] = 'A';

 pHeader[10] = 'V';

 pHeader[11] = 'E';

  

 /* Write the format chunk, must be'fmt ' -----------------------------------*/

 pHeader[12] = 'f';

 pHeader[13] = 'm';

 pHeader[14] = 't';

 pHeader[15] = ' ';

  

 /* Write the length of the 'fmt' data, must be 0x10 ------------------------*/

 pHeader[16] = 0x10;

 pHeader[17] = 0x00;

 pHeader[18] = 0x00;

 pHeader[19] = 0x00;

  

 /* Write the audio format, must be 0x01 (PCM) ------------------------------*/

 pHeader[20] = 0x01;

 pHeader[21] = 0x00;

  

 /* Write the number of channels, ie. 0x01 (Mono) ---------------------------*/

 // pHeader[22] = pWaveFormatStruct->NbrChannels;

 //pHeader[22] = 0x01;

pHeader[22] = 0x02;

 pHeader[23] = 0x00;

  

 /* Write the Sample Rate in Hz ---------------------------------------------*/

 /* Write Little Endian ie. 8000 = 0x00001F40 => byte[24]=0x40, byte[27]=0x00*/

pHeader[24] = 0x80;

 pHeader[25] = 0xBB;

 pHeader[26] = 0x00;

 pHeader[27] = 0x00;

  

 /* Write the Byte Rate -----------------------------------------------------*/

 pHeader[28] =0x00;

pHeader[29]=0x65;

pHeader[30] = 0x04;

pHeader[31]=0x00;

 /* Write the block alignment -----------------------------------------------*/

pHeader[32] = 0x06;

 pHeader[33] = 0x00;

  

 /* Write the number of bits per sample -------------------------------------*/

pHeader[34] = 0x18;

 pHeader[35] = 0x00;

  

 /* Write the Data chunk, must be 'data' ------------------------------------*/

 pHeader[36] = 'd';

 pHeader[37] = 'a';

 pHeader[38] = 't';

 pHeader[39] = 'a';

  

 /* Write the number of sample data -----------------------------------------*/

 /* This variable will be written back at the end of the recording operation */

 pHeader[40] = 0x00;

 pHeader[41] = 0x65;

 pHeader[42] = 0x04;

 pHeader[43] = 0x00;

/**************End of WAVE Format************/

/***********SD Card mount**********/

if(f_mount(&myFATAFS,SD_Path,1)==FR_OK)

{

HAL_GPIO_TogglePin(GPIOD,GPIO_PIN_12);

char myPath[]="0:rec.wav"; 

if(f_open(&myFILE,myPath,FA_WRITE | FA_CREATE_ALWAYS)== FR_OK)

{

HAL_GPIO_TogglePin(GPIOD,GPIO_PIN_14);

}

}

/* USER CODE BEGIN 3 */

/*********Write the wave header file*************/

if(f_write(&myFILE,(void*)pHeader,44,&testByte)==FR_OK)

{

HAL_GPIO_TogglePin(GPIOD,GPIO_PIN_15);

}

for(int i=0;i<2048;i++)

{

HAL_I2S_Receive_DMA(&hi2s2,i2s_rcvbf,2);

//HAL_I2S_Receive_DMA(&hi2s2,i2s_rcvbf1,2);

i2s_final= (i2s_rcvbf[0]<<16)+ i2s_rcvbf[1];

HAL_Delay(500);

if(f_write(&myFILE,(void*)&i2s_final,sizeof(i2s_final),&testByte)==FR_OK)

{

HAL_GPIO_TogglePin(GPIOD,GPIO_PIN_15);

}

}

f_close(&myFILE);

i2s_final=0x00000000;

HAL_Delay(1000);

}

    This topic has been closed for replies.

    6 replies

    waclawek.jan
    Super User
    November 19, 2018

    > HAL_Delay(500);

    So you've taken samples 500ms apart, and expect to play back correctly?

    (I also suspect that your i2s_rcvbf is uint8_t, as each other byte in the given file is 0x00).

    JW

    Niyathi Shenoy
    Associate III
    November 19, 2018

    i2s_rcvbf is uint16_t not uint8_t. I have tried without the delay part too...

    Tesla DeLorean
    Guru
    November 19, 2018

    A couple of bytes at a time?!

    You're going to want two much larger buffers, switching them seamlessly and managing the write to a file in another thread to avoid blocking.​

    Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
    Niyathi Shenoy
    Associate III
    November 20, 2018

    Hi Clive,

    The API, HAL_I2S_Receive_DMA(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size), Receives an amount of data in non-blocking mode with DMA and here pData is a 16 bit pointer to the receive data buffer. Also,When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S configuration phase, the Size parameter means the number of 16-bit data length in the transaction and when a 24-bit data frame or a 32-bit data frame is selected the Size parameter means the number of 16-bit data length.

    Do you have a sample code for I2S demonstration or I2S documentation. I have checked the Technical reference manual of stm32f407. Also i have checked the audio record and playback example code,but here the the output data is PCM.

    Tesla DeLorean
    Guru
    November 20, 2018

    If it were non-blocking it would return immediately, you don't look to be catching a completion interrupt or anything.

    Doing a pair of words at a time is going to have an awfully large overhead, as is writing them to a file 4 bytes at a time is also going to be brutal.

    In a CD application the audio data consists of 2352 byte sectors, each 16-bit left/right PCM sample pair taking 4 bytes.

    Audio CODECs expect a continuous stream of data, usually synchronous with the audio clock.

    I can't provide you with examples, or sample code, I'm working on different things.

    Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
    Niyathi Shenoy
    Associate III
    November 29, 2018

    Hi Clive,

    I am already receiving data in two different buffers. As you can see above in my code, HAL_I2S_Receive_DMA(&hi2s2,i2s_rcvbf,2); receives 16 bit samples in i2s_rcvbf[0] and another 16 bit of samples in i2s_rcvbf[1]. Also, HAL_I2S_Receive_DMA receives an amount of data in non-blocking mode with DMA.

    Niyathi Shenoy
    Associate III
    January 7, 2019

    Hi,

    Is there any sample code for I2S DMA receive. How is it done and how not to lose samples? I am stuck at this.