stm32h743_player/User/audio/audio_player_mp3.c
2024-04-08 19:08:59 +08:00

158 lines
4.6 KiB
C

#include "audio_player_mp3.h"
#include <stdio.h>
#include "main.h"
#include "ff.h"
#include "FreeRTOS.h"
#include "queue.h"
#include "elog.h"
#include "heap.h"
#include "bsp_aic3204.h"
#define MINIMP3_IMPLEMENTATION
#include "minimp3.h"
const static char *TAG = "player_mp3";
/**
* @brief 播放MP3文件
*
* @param file_name 文件路径
* @return esp_err_t 错误代码
*
* @note 本函数需要至少25600字节任务栈空间
*/
void music_mp3_play(const char *file_name)
{
FIL *file = malloc(sizeof(FIL));
uint8_t *file_buffer = malloc(FILE_BUFFER_SIZE);
FRESULT f_result = f_open(file, file_name, FA_READ);
if (f_result == FR_OK) {
elog_info(TAG, "open %s successful", file_name);
} else {
elog_error(TAG, "open %s failed, error code: %d", file_name, f_result);
return;
}
/* 创建并初始化解码器 */
mp3dec_t mp3d; //6668 bytes
mp3dec_init(&mp3d);
/* 初始化SAI */
audio_hal_start(MINIMP3_MAX_SAMPLES_PER_FRAME, sizeof(mp3d_sample_t));
int32_t file_buffer_available = 0; //剩余的缓冲区大小
while(1) {
/* 从文件中补充数据到缓冲区 */
if(file_buffer_available < FILE_BUFFER_SIZE/2) { //文件缓冲区剩余不足一半
int32_t file_buffer_consumed = (FILE_BUFFER_SIZE - file_buffer_available);
UINT br;
f_result = f_read(file, file_buffer+file_buffer_available, file_buffer_consumed, &br); //从文件中读取新的内容
if (f_result != FR_OK) {
elog_error(TAG, "file read error");
break;
}
file_buffer_available += br;
// uint32_t bytes_read = file_buffer_consumed + file_buffer_available - FILE_BUFFER_SIZE;
// if (bytes_read > 0) {
// elog_verbose(TAG, "reading %d bytes from file", (int)bytes_read);
// }
HAL_GPIO_TogglePin(LED_Y_GPIO_Port, LED_Y_Pin);
if(file_buffer_available <= 0) { //文件已经读取完毕
elog_info(TAG, "play done");
break; //结束播放
}
}
/* 解码新一帧MP3数据 */
mp3dec_frame_info_t info;
mp3d_sample_t *sample = malloc(MINIMP3_MAX_SAMPLES_PER_FRAME * sizeof(mp3d_sample_t));
uint32_t sample_count = mp3dec_decode_frame(&mp3d, file_buffer, file_buffer_available, sample, &info);
/* 将解码后的PCM数据写入SAI */
if (sample_count != 0) {
audio_hal_write(sample, sample_count * 2 * sizeof(mp3d_sample_t)); //sample_count只包含一个声道的采样数
} else {
free(sample);
}
/* 从缓冲区中删除解码完毕的帧 */
file_buffer_available -= info.frame_bytes; //从剩余缓冲区大小中减去被消耗的缓冲区大小
memmove(file_buffer, file_buffer+info.frame_bytes, file_buffer_available); //删除已消耗的缓冲区内容
if (HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin) == GPIO_PIN_RESET) {
vTaskDelay(pdMS_TO_TICKS(100));
while (HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin) == GPIO_PIN_RESET) {
vTaskDelay(pdMS_TO_TICKS(1));
}
break;
}
if (HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == GPIO_PIN_RESET) {
vTaskDelay(pdMS_TO_TICKS(100));
static uint8_t samplerate = 0;
switch (samplerate) {
case 0:
bsp_aic3204_set_fs(&hi2c1, 8000);
break;
case 1:
bsp_aic3204_set_fs(&hi2c1, 11025);
break;
case 2:
bsp_aic3204_set_fs(&hi2c1, 12000);
break;
case 3:
bsp_aic3204_set_fs(&hi2c1, 16000);
break;
case 4:
bsp_aic3204_set_fs(&hi2c1, 22050);
break;
case 5:
bsp_aic3204_set_fs(&hi2c1, 24000);
break;
case 6:
bsp_aic3204_set_fs(&hi2c1, 32000);
break;
case 7:
bsp_aic3204_set_fs(&hi2c1, 44100);
break;
case 8:
bsp_aic3204_set_fs(&hi2c1, 48000);
break;
case 9:
bsp_aic3204_set_fs(&hi2c1, 88200);
break;
case 10:
bsp_aic3204_set_fs(&hi2c1, 96000);
break;
case 11:
bsp_aic3204_set_fs(&hi2c1, 176400);
break;
case 12:
bsp_aic3204_set_fs(&hi2c1, 192000);
break;
}
samplerate ++;
if (samplerate >= 13) {
samplerate = 0;
}
while (HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == GPIO_PIN_RESET) {
vTaskDelay(pdMS_TO_TICKS(1));
}
}
}
/* 关闭文件 */
audio_hal_stop();
f_close(file);
free(file_buffer);
free(file);
tlsf_pool_statistics *dtcm_heap_statistics = get_dtcm_heap_statistics();
tlsf_pool_statistics *ahb_heap_statistics = get_ahb_heap_statistics();
elog_verbose(TAG, "free heap: DTCM: %d, AXI: %d", dtcm_heap_statistics->free_size, ahb_heap_statistics->free_size);
}