STM32H750XB_RT-THREAD/38-SAI—音频/SAI—MP3播放器/User/mp3Player/mp3Player.c

266 lines
7.5 KiB
C
Raw Permalink Normal View History

2025-07-21 06:34:29 +00:00
/*
******************************************************************************
* @file recorder.c
* @author fire
* @version V1.0
* @date 2015-xx-xx
* @brief WM8978<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܲ<EFBFBD><EFBFBD><EFBFBD>+mp3<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
******************************************************************************
* @attention
*
* ʵ<EFBFBD><EFBFBD>ƽ̨:Ұ<EFBFBD><EFBFBD> STM32 H750 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* <EFBFBD><EFBFBD>̳ :http://www.chuxue123.com
* <EFBFBD>Ա<EFBFBD> :http://firestm32.taobao.com
*
******************************************************************************
*/
#include <stdio.h>
#include <string.h>
#include "./usart/bsp_debug_usart.h"
#include "./wm8978/bsp_wm8978.h"
#include "ff.h"
#include "./mp3Player/mp3Player.h"
#include "mp3dec.h"
#include "./sai/bsp_sai.h"
/* <20>Ƽ<EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD>¸<EFBFBD>ʽmp3<70>ļ<EFBFBD><C4BC><EFBFBD>
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʣ<EFBFBD>44100Hz
* <EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD>2
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʣ<EFBFBD>320kbps
*/
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>СΪ2304*16/8<>ֽ<EFBFBD>(16ΪPCM<43><4D><EFBFBD><EFBFBD>Ϊ16λ)<29><>
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƕ<EFBFBD><EFBFBD><EFBFBD>MP3BUFFER_SIZEΪ2304<EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ΪMP3BUFFER_SIZE*2<EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD>
*/
#define MP3BUFFER_SIZE 2304
#define INPUTBUF_SIZE 3000
static HMP3Decoder Mp3Decoder; /* mp3<70><33><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8> */
static MP3FrameInfo Mp3FrameInfo; /* mP3֡<33><D6A1>Ϣ */
static MP3_TYPE mp3player; /* mp3<70><33><EFBFBD><EFBFBD><EFBFBD>豸 */
volatile uint8_t Isread=0; /* DMA<4D><41><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɱ<EFBFBD>־ */
static uint8_t bufflag=0; /* <20><><EFBFBD>ݻ<EFBFBD><DDBB><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD>־ */
uint32_t led_delay=0;
uint8_t inputbuf[INPUTBUF_SIZE]={0}; /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EBBBBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>1940<34>ֽ<EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>MP3֡<33><D6A1>С */
__attribute__((at(0x30000000))) short outbuffer[2][MP3BUFFER_SIZE]; /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><D2B2>I2S<32><53><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD>ʵ<EFBFBD><CAB5>ռ<EFBFBD><D5BC><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD>RECBUFFER_SIZE*2 */
FIL file; /* file objects */
FRESULT result;
UINT bw; /* File R/W count */
/**
* @brief MP3<EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD>Ƶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param <EFBFBD><EFBFBD>
* @retval <EFBFBD><EFBFBD>
*/
int times = 0;
void mp3PlayerDemo(const char *mp3file)
{
uint8_t *read_ptr=inputbuf;
uint32_t frames=0;
int err=0, i=0, outputSamps=0;
int read_offset = 0; /* <20><>ƫ<EFBFBD><C6AB>ָ<EFBFBD><D6B8> */
int bytes_left = 0; /* ʣ<><CAA3><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD> */
mp3player.ucFreq = SAI_AUDIOFREQ_DEFAULT;
mp3player.ucStatus = STA_IDLE;
mp3player.ucVolume = 40;
result=f_open(&file,mp3file,FA_READ);
if(result!=FR_OK)
{
printf("Open mp3file :%s fail!!!->%d\r\n",mp3file,result);
result = f_close (&file);
return; /* ֹͣ<CDA3><D6B9><EFBFBD><EFBFBD> */
}
printf("<EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD> -> %s\n",mp3file);
//<2F><>ʼ<EFBFBD><CABC>MP3<50><33><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Mp3Decoder = MP3InitDecoder();
if(Mp3Decoder==0)
{
printf("<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>helix<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>\n");
return; /* ֹͣ<CDA3><D6B9><EFBFBD><EFBFBD> */
}
printf("<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>...\n");
Delay_ms(10); /* <20>ӳ<EFBFBD>һ<EFBFBD><D2BB>ʱ<EFBFBD><EFBFBD>ȴ<EFBFBD>I2S<32>жϽ<D0B6><CFBD><EFBFBD> */
wm8978_Reset(); /* <20><>λWM8978<37><38><EFBFBD><EFBFBD>λ״̬ */
/* <20><><EFBFBD><EFBFBD>WM8978оƬ<D0BE><C6AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ΪDAC<41><43><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD> */
wm8978_CfgAudioPath(DAC_ON, EAR_LEFT_ON | EAR_RIGHT_ON);
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD> */
wm8978_SetOUT1Volume(mp3player.ucVolume);
/* <20><><EFBFBD><EFBFBD>WM8978<37><38>Ƶ<EFBFBD>ӿ<EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD>׼I2S<32>ӿڣ<D3BF>16bit */
wm8978_CfgAudioIF(SAI_I2S_STANDARD, 16);
/* <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>I2S */
SAI_Play_Stop();
SAI_GPIO_Config();
// SAIxA_Tx_Config(SAI_I2S_STANDARD,SAI_PROTOCOL_DATASIZE_16BIT,mp3player.ucFreq);
// SAIA_TX_DMA_Init();
bufflag=0;
Isread=0;
mp3player.ucStatus = STA_PLAYING; /* <20><><EFBFBD><EFBFBD>״̬ */
result=f_read(&file,inputbuf,INPUTBUF_SIZE,&bw);
if(result!=FR_OK)
{
printf("<EFBFBD><EFBFBD>ȡ%sʧ<73><CAA7> -> %d\r\n",mp3file,result);
MP3FreeDecoder(Mp3Decoder);
return;
}
read_ptr=inputbuf;
bytes_left=bw;
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><D1AD><EFBFBD><EFBFBD> */
while(mp3player.ucStatus == STA_PLAYING)
{
read_offset = MP3FindSyncWord(read_ptr, bytes_left); //Ѱ<><D1B0>֡ͬ<D6A1><CDAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD>һ<EFBFBD><D2BB>ͬ<EFBFBD><CDAC><EFBFBD>ֵ<EFBFBD>λ<EFBFBD><CEBB>
if(read_offset < 0) //û<><C3BB><EFBFBD>ҵ<EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD>
{
result=f_read(&file,inputbuf,INPUTBUF_SIZE,&bw);
if(result!=FR_OK)
{
printf("<EFBFBD><EFBFBD>ȡ%sʧ<73><CAA7> -> %d\r\n",mp3file,result);
break;
}
read_ptr=inputbuf;
bytes_left=bw;
continue; //<2F><><EFBFBD><EFBFBD>ѭ<EFBFBD><D1AD>2<EFBFBD><32><EFBFBD>ص<EFBFBD>ѭ<EFBFBD><D1AD>1
}
read_ptr += read_offset; //ƫ<><C6AB><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD>ֵ<EFBFBD>λ<EFBFBD><CEBB>
bytes_left -= read_offset; //ͬ<><CDAC><EFBFBD><EFBFBD>֮<EFBFBD><D6AE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݴ<EFBFBD>С
if(bytes_left < 1024) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
/* ע<><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ط<EFBFBD><D8B7><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD>õ<EFBFBD><C3B5><EFBFBD>DMA<4D><41>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>Ҫ4<D2AA>ֽڶ<D6BD><DAB6><EFBFBD> */
i=(uint32_t)(bytes_left)&3; //<2F>ж϶<D0B6><CFB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD>
if(i) i=4-i; //<2F><>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD>
memcpy(inputbuf+i, read_ptr, bytes_left); //<2F>Ӷ<EFBFBD><D3B6><EFBFBD>λ<EFBFBD>ÿ<EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>
read_ptr = inputbuf+i; //ָ<><D6B8><EFBFBD><EFBFBD><EFBFBD>ݶ<EFBFBD><DDB6><EFBFBD>λ<EFBFBD><CEBB>
result = f_read(&file, inputbuf+bytes_left+i, INPUTBUF_SIZE-bytes_left-i, &bw);//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if(result!=FR_OK)
{
printf("<EFBFBD><EFBFBD>ȡ%sʧ<73><CAA7> -> %d\r\n",mp3file,result);
break;
}
bytes_left += bw; //<2F><>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С
}
err = MP3Decode(Mp3Decoder, &read_ptr, &bytes_left, outbuffer[bufflag], 0); //bufflag<61><67>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>mp3<70><33><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E5A1A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EBA1A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EBA1A2><EFBFBD>ݸ<EFBFBD>ʽ
frames++;
if (err != ERR_MP3_NONE) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
switch (err)
{
case ERR_MP3_INDATA_UNDERFLOW:
printf("ERR_MP3_INDATA_UNDERFLOW\r\n");
result = f_read(&file, inputbuf, INPUTBUF_SIZE, &bw);
read_ptr = inputbuf;
bytes_left = bw;
break;
case ERR_MP3_MAINDATA_UNDERFLOW:
/* do nothing - next call to decode will provide more mainData */
printf("ERR_MP3_MAINDATA_UNDERFLOW\r\n");
break;
default:
printf("UNKNOWN ERROR:%d\r\n", err);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֡
if (bytes_left > 0)
{
bytes_left --;
read_ptr ++;
}
break;
}
Isread=1;
}
else //<2F><><EFBFBD><EFBFBD><EFBFBD>޴<EFBFBD><DEB4><EFBFBD><EFBFBD><EFBFBD>׼<EFBFBD><D7BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>PCM
{
MP3GetLastFrameInfo(Mp3Decoder, &Mp3FrameInfo); //<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>DAC */
outputSamps = Mp3FrameInfo.outputSamps; //PCM<43><4D><EFBFBD>ݸ<EFBFBD><DDB8><EFBFBD>
if (outputSamps > 0)
{
if (Mp3FrameInfo.nChans == 1) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>һ<EFBFBD>ݵ<EFBFBD><DDB5><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
for (i = outputSamps - 1; i >= 0; i--)
{
outbuffer[bufflag][i * 2] = outbuffer[bufflag][i];
outbuffer[bufflag][i * 2 + 1] = outbuffer[bufflag][i];
}
outputSamps *= 2;
}//if (Mp3FrameInfo.nChans == 1) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}//if (outputSamps > 0)
/* <20><><EFBFBD>ݽ<EFBFBD><DDBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD>ò<EFBFBD><C3B2><EFBFBD><EFBFBD><EFBFBD> */
if (Mp3FrameInfo.samprate != mp3player.ucFreq) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
mp3player.ucFreq = Mp3FrameInfo.samprate;
printf(" \r\n Bitrate %dKbps", Mp3FrameInfo.bitrate/1000);
printf(" \r\n Samprate %dHz", mp3player.ucFreq);
printf(" \r\n BitsPerSample %db", Mp3FrameInfo.bitsPerSample);
printf(" \r\n nChans %d", Mp3FrameInfo.nChans);
printf(" \r\n Layer %d", Mp3FrameInfo.layer);
printf(" \r\n Version %d", Mp3FrameInfo.version);
printf(" \r\n OutputSamps %d", Mp3FrameInfo.outputSamps);
printf("\r\n");
if(mp3player.ucFreq >= SAI_AUDIOFREQ_DEFAULT) //I2S_AudioFreq_Default = 2<><32><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֡<EFBFBD><D6A1>ÿ<EFBFBD>ζ<EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
SAIxA_Tx_Config(SAI_I2S_STANDARD,SAI_PROTOCOL_DATASIZE_16BIT,mp3player.ucFreq); //<2F><><EFBFBD>ݲ<EFBFBD><DDB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޸<EFBFBD>iis<69><73><EFBFBD><EFBFBD>
SAIA_TX_DMA_Init((uint32_t)(&outbuffer[0]),(uint32_t)&outbuffer[1],outputSamps);
}
SAI_Play_Start();
}
}//else <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if(file.fptr==file.fsize) //mp3<70>ļ<EFBFBD><C4BC><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD>ɣ<EFBFBD><C9A3>˳<EFBFBD>
{
printf("END\r\n");
break;
}
while(Isread==0)
{
led_delay++;
if(led_delay==0xffffff)
{
led_delay=0;
// LED4_TOGGLE;
}
//Input_scan(); //<2F>ȴ<EFBFBD>DMA<4D><41><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɣ<EFBFBD><C9A3>˼<EFBFBD><CBBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>а<EFBFBD><D0B0><EFBFBD>ɨ<EFBFBD><EFBFBD><E8BCB0><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD>
}
Isread=0;
}
SAI_Play_Stop();
mp3player.ucStatus=STA_IDLE;
MP3FreeDecoder(Mp3Decoder);
f_close(&file);
}
/* DMA<4D><41><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>жϻص<CFBB><D8B5><EFBFBD><EFBFBD><EFBFBD> */
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѿ<EFBFBD><D1BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɣ<EFBFBD><C9A3><EFBFBD>Ҫ<EFBFBD>л<EFBFBD><D0BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>»<EFBFBD><C2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݲ<EFBFBD><DDB2><EFBFBD>
ͬʱ<EFBFBD><EFBFBD>ȡWAV<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
void MusicPlayer_SAI_DMA_TX_Callback(void)
{
if(DMA_Instance->CR&(1<<19)) //<2F><>ǰʹ<C7B0><CAB9>Memory1<79><31><EFBFBD><EFBFBD>
{
bufflag=0; //<2F><><EFBFBD>Խ<EFBFBD><D4BD><EFBFBD><EFBFBD>ݶ<EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0
}
else //<2F><>ǰʹ<C7B0><CAB9>Memory0<79><30><EFBFBD><EFBFBD>
{
bufflag=1; //<2F><><EFBFBD>Խ<EFBFBD><D4BD><EFBFBD><EFBFBD>ݶ<EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>1
}
Isread=1; // DMA<4D><41><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɱ<EFBFBD>־
}
/***************************** (END OF FILE) *********************************/