uint8_t MP3_Playback (void)
{
/* Init variables */
bytesLeft = 0;
outOfData = 0;
eofReached = 0;
readPtr = readBuf = (uint8_t *)(READBUF_BASEADDR);
totalDecTime = 0;
nFrames = 0;
nReadFileBlkCnt = 0;
totalReadFileTime = 0;
pcmframe_size = 0;
/* Decode and playback from audio buf 0 */
DecodeBufIdx = PlayingBufIdx = AUDIOBUF0;
audiobuf[AUDIOBUF0].Empty = audiobuf[AUDIOBUF1].Empty = 1;
/* Decode the first frame to get the frame format */
if (MP3_DecodeFrame() == 0)
{
pcmframe_size = (mp3FrameInfo.bitsPerSample / 8) * mp3FrameInfo.outputSamps;
MP3_AddAudioBuf (pcmframe_size);
}
else
{
// DEBUG_MSG("\n\rFailed to decode the 1st frame, try to increase READBUF_SIZE.\n\r");
return 0x1; /* fail to decode the first frame */
}
/* Display the frame format */
MP3_DisplayFormat();
/* configure appropriate bit rate for each mp3, otherwise,
the mp3 will be too fast or slow with default setting */
if (MP3_ConfigBitrate(mp3FrameInfo.nChans, mp3FrameInfo.bitsPerSample, mp3FrameInfo.samprate))
{
//DEBUG_MSG("Unsupported MP3 format!\n\r");
return 0x2; /* Unsupported MP3 format */
}
setMp3Bitrate(DAC_TXBITRATE);
/* Start I2S+DMA to send the first decoded frame */
DAC_Init();
Timer_6_On();
DMA_SendData((uint32_t *)audiobuf[AUDIOBUF0].BaseAddr, audiobuf[AUDIOBUF0].Size);
DAC_DMA_Done = 0;
DMA_Buf_Empty = 0;
/* Then deocder all the left frames */
do
{
/* wait for playback is complete to release buf */
while (audiobuf[DecodeBufIdx].Empty == 0)
{
/* Decoder is faster than play, all buf is full */
decode_faster_flag ^= 0x1;
if (decode_faster_flag) LED_On (LED_DEC_FASTER);
else LED_Off (LED_DEC_FASTER);
}
/* Decoder one frame */
if (MP3_DecodeFrame() == 0)
{
pcmframe_size = (mp3FrameInfo.bitsPerSample / 8) * mp3FrameInfo.outputSamps;
MP3_AddAudioBuf (pcmframe_size);
}
} while ((outOfData == 0) && (DMA_Buf_Empty ==0));
/* Playback complete */
WAIFORDMADONE;
BSP_LED_On(LED1);
BSP_LED_On(LED2);
BSP_LED_On(LED3);
HAL_Delay(1000);
BSP_LED_Off(LED1);
BSP_LED_Off(LED2);
BSP_LED_Off(LED3);
HAL_Delay(1000);
BSP_LED_On(LED1);
BSP_LED_On(LED2);
BSP_LED_On(LED3);
HAL_Delay(1000);
BSP_LED_Off(LED1);
BSP_LED_Off(LED2);
BSP_LED_Off(LED3);
if (outOfData == 1 || (DMA_Buf_Empty==1))
{
#if 1
MP3GetLastFrameInfo(hMP3Decoder, &mp3FrameInfo);
audioSecs = ((float)nFrames * mp3FrameInfo.outputSamps) / ( (float)mp3FrameInfo.samprate * mp3FrameInfo.nChans);
//DEBUG_MSG("Statistics: \n\r");
//DEBUG_MSG(" Decode: %d frames, %d ms (%d ms/frame)\n\r", nFrames, totalDecTime, totalDecTime/nFrames);
//DEBUG_MSG(" Audio duration(min:sec): %02d:%02d\n\r", (uint32_t)audioSecs/60, (uint32_t)audioSecs%60);
#ifdef SUPPORT_USB
if(MP3List[File1.fs? CurrentMP3 : PreviousMP3].drive == 0)
//DEBUG_MSG(" File read speed: %d ms/%dkB\n\r", totalReadFileTime/nReadFileBlkCnt, READBUF_SIZE_USB>>10);
#endif
#ifdef SUPPORT_SD
// if(MP3List[File1.fs? CurrentMP3 : PreviousMP3].drive == 1)
// DEBUG_MSG(" File read speed: %d ms/%dkB\n\r", totalReadFileTime/nReadFileBlkCnt, READBUF_SIZE_SD>>10);
#endif
#endif
}
return 0;
}
uint8_t MP3_DecodeFrame ()
{
uint8_t word_align, frame_decoded;
int nRead, offset, err = 0;
frame_decoded = 0;
word_align = 0;
nRead = 0;
offset = 0;
do
{
/* somewhat arbitrary trigger to refill buffer - should always be enough for a full frame */
if (bytesLeft < 2*MAINBUF_SIZE && !eofReached)
{
/* Align to 4 bytes */
word_align = (4-(bytesLeft&3)) & 3;
Timer = 0;
/* Fill read buffer */
nRead = MP3_FillReadBuffer(readBuf, readPtr, bytesLeft, word_align);
totalReadFileTime += Timer;
nReadFileBlkCnt++;
bytesLeft += nRead;
readPtr = readBuf + word_align;
if (nRead == 0)
{
eofReached = 1; /* end of file */
outOfData = 1;
}
}
/* find start of next MP3 frame - assume EOF if no sync found */
offset = MP3FindSyncWord(readPtr, bytesLeft);
if (offset < 0) {
readPtr = readBuf;
bytesLeft = 0;
continue;
}
readPtr += offset;
bytesLeft -= offset;
//simple check for valid header
if(((*(readPtr+1) & 24) == 8) || ((*(readPtr+1) & 6) != 2) || ((*(readPtr+2) & 240) == 240) || ((*(readPtr+2) & 12) == 12) || ((*(readPtr+3) & 3) == 2))
{
readPtr += 1; //header not valid, try next one
bytesLeft -= 1;
continue;
}
Timer = 0;
err = MP3Decode(hMP3Decoder, &readPtr, &bytesLeft, (short *)audiobuf[DecodeBufIdx].BaseAddr, 0);
totalDecTime += Timer;
nFrames++;
if(err == -6)
{
readPtr += 1;
bytesLeft -= 1;
continue;
}
if (err) {
/* error occurred */
switch (err) {
case ERR_MP3_INDATA_UNDERFLOW:
outOfData = 1;
break;
case ERR_MP3_MAINDATA_UNDERFLOW:
/* do nothing - next call to decode will provide more mainData */
break;
case ERR_MP3_FREE_BITRATE_SYNC:
default:
outOfData = 1;
break;
}
} else {
/* no error */
MP3GetLastFrameInfo(hMP3Decoder, &mp3FrameInfo);
frame_decoded = 1;
}
} while (!frame_decoded && !outOfData);
if (outOfData == 1) return 0x1; /* Decoder terminated */
else return 0x0; /* Decoder success. */
}