#include "audio_player_mp3.h" #include #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); // size_t free_heap = xPortGetFreeHeapSize(); // elog_verbose(TAG, "free heap: %d", free_heap); }