cancel
Showing results for 
Search instead for 
Did you mean: 

Unable to play audio on TAS2110 codec via SAI using STM32U5G9J-DK1 board

Jinal
Visitor

Post edited by ST moderator to be inline with the community rules especially for sharing a code. Please read this post.

I’m working on playing audio on the TAS2110 codec using the STM32U5G9J-DK1 board via SAI.

  • I tested with generated sine and square waves, and I can hear output on the speaker.

  • However, when I try to play audio data stored in memory, I don’t get any sound.

To store the audio file, I created a .s file as shown below:

.section .wav_data, "a"
.global _wav_data
_wav_data:
.incbin "C:/Work/Project/Project/audio_codec/Core/Src/wav/audio.wav"
.global _wav_data_end
_wav_data_end:

I can parse the WAV data using my parser API. Parsing works fine, and I copy the samples into a buffer, then send it to SAI via DMA.

Could you please help me identify what I might be missing? Why do I not get audio output from the speaker when streaming from the WAV file?

My GPDMA and SAI configurations are set up accordingly.

Jinal_0-1757488994988.pngJinal_1-1757489026142.png

Jinal_2-1757489078805.png

Jinal_3-1757489228733.png

Jinal_4-1757489348204.png

In the linker script

.wav_data :
{
. = ALIGN(4);

_swav_data_start = .;

KEEP(*(.wav_data))

_swav_data_end = .;

} >FLASH

 

Parse API

 
int parse_wav_file(uint8_t *wav_data, uint32_t wav_size, wav_info_t *info) {

if (wav_size < 44) return -1; // Too small for header



// Check RIFF header

if (strncmp((char *)wav_data, "RIFF", 4) != 0) return -1;

if (strncmp((char *)(wav_data + 8), "WAVE", 4) != 0) return -1;



// Find fmt chunk

uint32_t offset = 12;

while (offset + 8 < wav_size) {

if (strncmp((char *)(wav_data + offset), "fmt ", 4) == 0) {

break;

}

offset += 8 + *(uint32_t *)(wav_data + offset + 4);

}

if (offset + 8 >= wav_size) return -1;



// Parse fmt chunk

uint16_t audio_format = *(uint16_t *)(wav_data + offset + 8);

info->num_channels = *(uint16_t *)(wav_data + offset + 10);

info->sample_rate = *(uint32_t *)(wav_data + offset + 12);

info->bits_per_sample = *(uint16_t *)(wav_data + offset + 22);

if (audio_format != 1 || info->num_channels != 1 || info->bits_per_sample != 16) {

return -1; // Only support mono, 16-bit PCM

}



// Find data chunk

offset += 8 + *(uint32_t *)(wav_data + offset + 4);

while (offset + 8 < wav_size) {

if (strncmp((char *)(wav_data + offset), "data", 4) == 0) {

info->data_size = *(uint32_t *)(wav_data + offset + 4);

info->data_start = wav_data + offset + 8;

return 0;

}

offset += 8 + *(uint32_t *)(wav_data + offset + 4);

}

return -1;

}

Filling audio as per below API


#define AUDIO_BUFFER_SIZE 4096

uint32_t wav_index = 0;



void fill_audio_buffer(void) {

uint32_t samples_to_copy = AUDIO_BUFFER_SIZE;

if (wav_index + samples_to_copy > wav_info.data_size / 2) {

samples_to_copy = (wav_info.data_size / 2) - wav_index;

}

memcpy(audio_buffer,

(int16_t *)(wav_info.data_start + wav_index * 2),

samples_to_copy * sizeof(int16_t));



wav_index += samples_to_copy;

}

Audio Play API

static int audio_play(uint16_t *paudioBuff, uint32_t len)

{

if(HAL_OK != HAL_SAI_Transmit_DMA(saiptr,(uint8_t*)paudioBuff, AUDIO_BUFFER_SIZE))

{

return -1;

}

return 0;

}

 

int wavPlayer_play(tas2110_data_t *tas_data)

{

uint32_t wav_size = _swav_data_end - _swav_data_start;

file_size = wav_size;

if (parse_wav_file(_wav_data, wav_size, &wav_info) != 0)

{

return -1;

}



tas2110_Configuration(tas_data);



fill_audio_buffer();

if(audio_play((uint16_t *)&audio_buffer[0], AUDIO_BUFFER_SIZE) != 0)

{

return -1;

}

return 0;

}

Callback APIs:

void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)

{

fill_audio_buffer();

HAL_SAI_Transmit_DMA(hsai, (uint8_t*)audio_buffer, AUDIO_BUFFER_SIZE);

}



void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)

{

fill_audio_buffer();

HAL_SAI_Transmit_DMA(hsai, (uint8_t*)audio_buffer, AUDIO_BUFFER_SIZE);

}

 

0 REPLIES 0