#include "audio_player.h" #include #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_ok; 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: //正常播放完成 case audio_hal_result_next: next_file: switch_direction = 1; current_file_index ++; if(current_file_index >= audio_file_count) { current_file_index = 0; } break; case audio_hal_result_prev: prev_file: 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); } }