cancel
Showing results for 
Search instead for 
Did you mean: 

STM32WB55 + Helix MP3 decoder: PCM plays 6× too slow via SAI + DMA

raffone
Associate

Hi all,

I’m testing MP3 playback on a Nucleo-WB55RG.
Setup:

  • SD card via FATFS

  • Helix MP3 decoder (libhelix-mp3)

  • PCM out via SAI1_A (I²S) → external DAC

  • DMA in circular mode, 2× half-buffer callbacks

What works:

  • A test sine wave buffer played via SAI+DMA works fine at 44.1 kHz stereo.

  • DMA callbacks fire at the expected rate.

  • So SAI + DMA peripheral config is correct.

What fails:

  • When I decode MP3 frames with Helix and feed them into the DMA buffer, audio plays but it is ~6× too slow and distorted.

  • Console output shows decoded frames and DMA half/full interrupts incrementing normally.

Suspect code (fill_half):

static int fill_half(Mp3Ctx *c, uint16_t *target, int targetHalfwords)
{
int written = 0;

while (written < targetHalfwords) {
if (c->bytesLeft < 4 && c->eof) break;
refill_readbuf(c);

int offset = MP3FindSyncWord(c->readPtr, c->bytesLeft);
if (offset < 0) { if (c->eof) break; c->readPtr++; c->bytesLeft--; continue; }
c->readPtr += offset;
c->bytesLeft -= offset;

int16_t frameBuf[1152*2]; // stereo max
int err = MP3Decode(c->dec, &c->readPtr, &c->bytesLeft, frameBuf, 0);
if (err) { if (!c->eof) continue; break; }

MP3FrameInfo info;
MP3GetLastFrameInfo(c->dec, &info);

// <<<<< HERE IS MY CONFUSION >>>>>
// Helix docs say info.outputSamps is total PCM samples (all channels).
// But I’m not sure if I’m copying the right number of halfwords.

int totalSamples = info.outputSamps; // e.g. 1152 for mono, 2304 for stereo?
int nch = info.nChans;

if (nch == 2) {
int toCopy = (totalSamples <= (targetHalfwords - written)) ?
totalSamples : (targetHalfwords - written);
memcpy(&target[written], frameBuf, toCopy * sizeof(int16_t));
written += toCopy;
} else {
// mono → stereo
for (int i = 0; i < totalSamples && written + 1 < targetHalfwords; i++) {
int16_t s = frameBuf[i];
target[written++] = s;
target[written++] = s;
}
}
}
return written;
}

Question:

  • Is my use of info.outputSamps correct?

  • Should I treat it as “samples per channel” or “total interleaved samples”?

  • Has anyone else run into the slow playback symptom when using Helix with STM32 + DMA?

Thanks!

0 REPLIES 0