2021-11-05 08:24 AM
I want to play an audio clip over i2s from Flash memory. My application is mono and a mono source will fit in flash, but not stereo, it is too big.
The HAL i2s interface does not appear to offer a mechanism to duplicate mono source bytes (16b) onto the stereo stream. Am I missing something? (STM32F411)
2021-11-05 08:47 AM
Try header files...
/** @defgroup SAI_Mono_Stereo_Mode SAI Mono Stereo Mode
* @{
*/
#define SAI_STEREOMODE 0x00000000U
#define SAI_MONOMODE ((uint32_t)SAI_xCR1_MONO)
located ... Users\you\STM32Cube\Repository\STM32Cube_FW_F4_V1.26.2\Drivers\STM32F4xx_HAL_Driver\Inc\...
2021-11-05 09:07 AM
#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) ||\
defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F413xx) ||\
defined(STM32F423xx)
Looks like I'm out of luck with my STM32F411 :relieved_face:
2021-11-05 09:13 AM
Then you simply in flash store mono and in RAM mini buffer copy stereo. MCU will have work.
2021-11-08 07:31 AM
OK, I've got this playing my audio clip from Flash, stored in a mono array and converted to "stereo" via a RAM buffer. My amplifier is mono, MAX98357.
All looking good except, replay appears to be correct pitch but playing at double speed and so half the replay duration.
If I play games with the replay sample rate, I can get correct replay rate but pitch is half of that expected.
I've exported a 16KHz sampling rate 16 bit audio source from Audacity, so I'm confused.
As it is simply sampled data, how can pitch be correct but rate doubled?
2021-11-08 11:47 AM
You dont show code, or explain method DMA or ? But seems as you send samples and overwrite every second sample or other mistake.
How is count of your mono samples ? Used wide is half word ?
2021-11-09 06:30 AM
I'm using Audacity to create my WAV source, and HxD to turn this into a header. I'm trying it out with an identical 3.5 second clip, in mono and stereo formats. No DMA just yet, I probably don't need it as the processor won't be very busy during playback.
In stereo:
#define SOURCE_SIZE 225394
const uint8_t source_buff[SOURCE_SIZE] = {
0x52, 0x49, 0x46, 0x46, 0x6A, 0x70, 0x03, 0x00, 0x57, 0x41, 0x56, 0x45,
0x66, 0x6D, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
0x80, 0x3E, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x00, 0x04, 0x00, 0x10, 0x00,
0x64, 0x61, 0x74, 0x61, 0x48, 0x6F, 0x03, 0x00, 0xFB, 0xFF, 0xED, 0xFF,....
if(HAL_I2S_GetState(&hi2s1) == HAL_I2S_STATE_READY){
status = HAL_I2S_Transmit (&hi2s1, source_buff, SOURCE_SIZE, 100);
}
Audio quality good, but truncated to about 1 second.
In mono:
#define SOURCE_SIZE 126104
const uint8_t source_buff[SOURCE_SIZE] = {
0x52, 0x49, 0x46, 0x46, 0x90, 0xEC, 0x01, 0x00, 0x57, 0x41, 0x56, 0x45,
0x66, 0x6D, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
0x80, 0x3E, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00,
0x64, 0x61, 0x74, 0x61, 0x6E, 0xEB, 0x01, 0x00, 0x03, 0x00,....
if( playback_active == true ) // time to play audio clip
{
buffer_content = 0;
if(HAL_I2S_GetState(&hi2s1) == HAL_I2S_STATE_READY){
while( (load_ptr < BUFFER_SIZE) && (transfer_ptr < SOURCE_SIZE) ) // load 16 bit buffer with chunk of 8 bit source
{
audio_buffer[load_ptr] = source_buff[transfer_ptr+1] + (source_buff[transfer_ptr] << 8);
audio_buffer[load_ptr+1] = audio_buffer[load_ptr]; // make into "stereo" source
transfer_ptr = transfer_ptr + 2; // two bytes
load_ptr = load_ptr + 2; // for each 16 bit sample
buffer_content = buffer_content + 1; // number of samples in this batch
}
}
if( transfer_ptr >= SOURCE_SIZE )
{
playback_active = false; // reached end of source material
transfer_ptr = 0; // reset pointer from 8 bit source
load_ptr = 0; // reset pointer in 16 bit buffer
}
if(HAL_I2S_GetState(&hi2s1) == HAL_I2S_STATE_READY)
{
load_ptr = 0; // reset pointer in 16 bit buffer
status = HAL_I2S_Transmit (&hi2s1, audio_buffer, buffer_content, 100);
}
}
Plays the full clip, but pitch is low, play rate is too fast. I imagined that pitch and rate would vary together.
2021-11-09 08:05 AM
I've just spotted that I've left the WAV header on the stereo source, but omitting it has no effect on the symptoms.
2021-11-09 08:18 AM
As first you check and learn how work last parameter 100 in your calls HAL_I2S_Transmit (&hi2s1, audio_buffer, buffer_content, 100);
As second your samples is uint8_t chaos. More more better is working with half word arrays.
Stereo samples not equal i dont understand how you create it.
In stereo:
#define SOURCE_SIZE 225394
const uint8_t source_buff[SOURCE_SIZE] = {
0x52, 0x49, 0x46, 0x46, 0x6A, 0x70, 0x03, 0x00, 0x57, 0x41, 0x56, 0x45,
when you create stereo from mono numbers need equal
0x52,0x49, 0x52,0x49
i hope audio_buffer is uint16_t
And your low pitch is result from time pause when you fill next buffer. I mean HAL_I2S_Transmit is blocked func and wait for sending data to end,
i normal is used DMA and half buffer circular mode . Play is started when first half buffer is filled, and fill second half is in same time when DMA send first data out to peripheral...
##### IO operation functions #####
===============================================================================
[..]
This subsection provides a set of functions allowing to manage the I2S data
transfers.
(#) There are two modes of transfer:
(++) Blocking mode : The communication is performed in the polling mode.
The status of all data processing is returned by the same function
after finishing transfer.
(++) No-Blocking mode : The communication is performed using Interrupts
or DMA. These functions return the status of the transfer startup.
The end of the data processing will be indicated through the
dedicated I2S IRQ when using Interrupt mode or the DMA IRQ when
using DMA mode.
(#) Blocking mode functions are :
(++) HAL_I2S_Transmit()
(++) HAL_I2S_Receive()
(#) No-Blocking mode functions with Interrupt are :
(++) HAL_I2S_Transmit_IT()
(++) HAL_I2S_Receive_IT()
(#) No-Blocking mode functions with DMA are :
(++) HAL_I2S_Transmit_DMA()
(++) HAL_I2S_Receive_DMA()
And when you convert wav files you cant use arrays from index 0, here is wav header data no audio.
2021-11-09 08:44 AM
Yes, I'm tying myself in knots trying to recreate the stereo source from stored mono. I was simply trying to save space in a system that is exclusively mono. Stereo replay sounds OK but is for some reason terminating early. I guess I need to trim down my audio file so I can just store and replay from stereo.