wch-code/ch32v307_mp3_dac/User/audio/audio_player.c

232 lines
6.6 KiB
C

#include "audio_player.h"
#include <stdlib.h>
#include "debug.h"
#include "bsp_key.h"
#include "bsp_led.h"
#include "ff.h"
#include "tlsf.h"
#define AUDIO_PLAYER_MUSIC_FILE_LIST_MAX 600 //最大音频文件数量
#define AUDIO_PLAYER_MUSIC_FILE_NAME_LENGTH 13 //FAT32中短文件名占用13字节
#define AUDIO_PLAYER_MUSIC_DEFAULT_DIR "" //默认音频文件存储目录
static const char* audio_player_music_ext_names[] = {"MP3", "WAV", ""};
typedef enum {
audio_player_mode_normal, //顺序播放
audio_player_mode_single_repeat, //单曲循环
} audio_player_mode_e;
audio_hal_result_t audio_player_playing_routine(void)
{
bsp_key_event_e key_event = bsp_key_get_event();
switch (key_event){
case bsp_key_none:
return audio_hal_ok;
case bsp_key_next_short:
return audio_hal_result_next;
case bsp_key_prev_short:
return audio_hal_result_prev;
case bsp_key_pause_short:
return audio_hal_result_pause;
case bsp_key_next_long:
return audio_hal_result_random;
case bsp_key_prev_long:
return audio_hal_result_repeat;
default:
LOG_W("unhandled key event: %s", bsp_key_get_event_string(key_event));
}
return audio_hal_ok;
}
audio_hal_result_t audio_player_play_file(const char *path)
{
char* ext_name = strrchr(path, '.') + 1; //指针定位到扩展名
if(!strcasecmp(ext_name, "MP3")) {
return audio_mp3_play(path, audio_player_playing_routine);
} else if(!strcasecmp(ext_name, "WAV")) {
return audio_wav_play(path, audio_player_playing_routine);
}
LOG_W("unknown file format \"%s\" of %s", ext_name, path);
return audio_hal_error_unsupported_format;
}
bool audio_player_check_file_ext(const char* path, const char** ext_table)
{
char* ext_name = strrchr(path,'.') + 1; //指针定位到扩展名
if(ext_name == NULL) { //不存在扩展名
return false;
}
if(ext_table[0][0] == '\0') {
return true;//未指定扩展名 均返回真
}
uint8_t i = 0;
while(ext_table[i][0] != '\0') { //以此检查是否与每个扩展名匹配
if(!strcasecmp(ext_name, ext_table[i])) {
return true;
}
i ++;
}
return false;
}
uint32_t audio_player_search_file(const char* music_dir, char *file_list)
{
uint16_t file_count = 0;
DIR dir;
FRESULT f_result = f_opendir(&dir, music_dir);
if (f_result != FR_OK) {
LOG_E("error while reading directory, error code=%d", f_result);
return 0;
}
while (1) {
FILINFO fileinfo;
f_result = f_readdir(&dir, &fileinfo);
if (f_result != FR_OK) {
LOG_E("error while reading directory, error code=%d", f_result);
break;
}
if (fileinfo.fname[0] == '\0') { //文件夹遍历完毕
LOG_I("%d files saved in list", file_count);
break;
}
if(audio_player_check_file_ext(fileinfo.fname, audio_player_music_ext_names) == 0) { //不受支持的文件类型
continue;
}
if(fileinfo.fattrib & AM_DIR) { //是一个目录
continue;
}
if (file_list != NULL) { //如果指针非空 则复制到文件列表中
strcpy(file_list + file_count * AUDIO_PLAYER_MUSIC_FILE_NAME_LENGTH, fileinfo.fname);
}
file_count ++;
if (file_count >= AUDIO_PLAYER_MUSIC_FILE_LIST_MAX) {
LOG_W("more than %d files are found, discarding more files", AUDIO_PLAYER_MUSIC_FILE_LIST_MAX);
break;
}
}
f_result = f_closedir(&dir);
if (f_result != FR_OK) {
LOG_E("error while closing directory, error code=%d", f_result);
}
return file_count;
}
void audio_player(void)
{
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_RNG, ENABLE);
RNG_Cmd(ENABLE);
uint32_t current_file_index = 0;
uint32_t audio_file_count = audio_player_search_file(AUDIO_PLAYER_MUSIC_DEFAULT_DIR, NULL); //首先搜索音频文件数
if (audio_file_count == 0) {
LOG_E("error while searching for music files");
return;
}
LOG_D("allocating %d bytes of memory for music file list", audio_file_count * AUDIO_PLAYER_MUSIC_FILE_NAME_LENGTH);
char *audio_file_list = tlsf_malloc(audio_file_count * AUDIO_PLAYER_MUSIC_FILE_NAME_LENGTH); //为文件列表申请内存
if (audio_file_list == NULL) {
LOG_E("error while allocating memory for music file list");
return;
}
audio_player_search_file(AUDIO_PLAYER_MUSIC_DEFAULT_DIR, audio_file_list); //然后将文件名保存到列表中
uint8_t switch_direction = 1; //1为下一首 0为上一首
while(1) {
char dir[20];
sprintf(dir, AUDIO_PLAYER_MUSIC_DEFAULT_DIR "/%s", audio_file_list + current_file_index * AUDIO_PLAYER_MUSIC_FILE_NAME_LENGTH);
LOG_D("index of playing file: %d, total files: %d", current_file_index+1, audio_file_count);
audio_hal_result_t play_result = audio_player_play_file(dir);
switch (play_result)
{
case audio_hal_error_open_file:
case audio_hal_error_read_file: //文件系统错误
goto error;
case audio_hal_error_insufficient_memory: //无法恢复的错误
LOG_E("unrecoverable error, resetting system");
NVIC_SystemReset();
break;
case audio_hal_error_unsupported_format:
case audio_hal_error_unsupported_parameter: //文件不支持
if (switch_direction == 1) { //根据上次切换方向逐一尝试
goto next_file;
} else {
goto prev_file;
}
break;
case audio_hal_result_repeat: //重复播放当前文件
break;
case audio_hal_ok: //正常播放完成
next_file:
case audio_hal_result_next:
switch_direction = 1;
current_file_index ++;
if(current_file_index >= audio_file_count) {
current_file_index = 0;
}
break;
prev_file:
case audio_hal_result_prev:
switch_direction = 0;
if(current_file_index != 0) {
current_file_index --;
} else {
current_file_index = audio_file_count - 1;
}
break;
case audio_hal_result_random:
uint32_t new_file_index = RNG_GetRandomNumber() % audio_file_count;
if (new_file_index > current_file_index) {
switch_direction = 1;
} else {
switch_direction = 0;
}
current_file_index = new_file_index;
break;
default:
LOG_W("unhandled play result: %d", play_result);
break;
}
}
error:
if (audio_file_list != NULL) {
tlsf_free(audio_file_list);
}
}