ch32v307_mp3_dac: add wav player and pause function
This commit is contained in:
parent
8a7d6b9587
commit
c993ad3a75
@ -126,7 +126,7 @@
|
|||||||
</toolChain>
|
</toolChain>
|
||||||
</folderInfo>
|
</folderInfo>
|
||||||
<sourceEntries>
|
<sourceEntries>
|
||||||
<entry excluding="User/3rdparty/fatfs/ffsystem.c|User/3rdparty/fatfs/ffunicode.c|User/audio/audio_wav.h|User/audio/audio_wav.c|User/audio/audio_mp3_rom.h|User/audio/audio_mp3_rom.c|User/audio_mp3_rom.h|User/audio_mp3_rom.c|Startup|Peripheral|Ld|Debug|Core" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
<entry excluding="User/3rdparty/fatfs/ffsystem.c|User/3rdparty/fatfs/ffunicode.c|User/audio/audio_mp3_rom.h|User/audio/audio_mp3_rom.c|User/audio_mp3_rom.h|User/audio_mp3_rom.c|Startup|Peripheral|Ld|Debug|Core" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
||||||
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Core"/>
|
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Core"/>
|
||||||
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Ld"/>
|
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Ld"/>
|
||||||
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Peripheral"/>
|
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Peripheral"/>
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
audio_hal_ok = 0, //配置成功或正常播放完毕
|
audio_hal_ok = 0, //配置成功或正常播放完毕
|
||||||
|
audio_hal_invalid_argument, //错误的参数
|
||||||
audio_hal_error_open_file, //无法打开文件
|
audio_hal_error_open_file, //无法打开文件
|
||||||
audio_hal_error_read_file, //无法读取文件
|
audio_hal_error_read_file, //无法读取文件
|
||||||
audio_hal_error_insufficient_memory, //内存不足
|
audio_hal_error_insufficient_memory, //内存不足
|
||||||
@ -13,6 +14,7 @@ typedef enum {
|
|||||||
|
|
||||||
audio_hal_result_next, //切换下一曲
|
audio_hal_result_next, //切换下一曲
|
||||||
audio_hal_result_prev, //切换上一曲
|
audio_hal_result_prev, //切换上一曲
|
||||||
|
audio_hal_result_pause, //暂停播放
|
||||||
audio_hal_result_random, //随机切换音乐
|
audio_hal_result_random, //随机切换音乐
|
||||||
audio_hal_result_repeat, //重新播放当前音乐
|
audio_hal_result_repeat, //重新播放当前音乐
|
||||||
} audio_hal_result_t;
|
} audio_hal_result_t;
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
#include "audio_mp3.h"
|
#include "audio_mp3.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
#include "delay.h"
|
||||||
#include "bsp_led.h"
|
#include "bsp_led.h"
|
||||||
#include "ff.h"
|
#include "ff.h"
|
||||||
#include "tlsf.h"
|
#include "tlsf.h"
|
||||||
@ -21,8 +22,14 @@ typedef struct {
|
|||||||
|
|
||||||
audio_hal_result_t audio_mp3_get_id3v2_size(FIL* file, uint32_t *id3v2_size)
|
audio_hal_result_t audio_mp3_get_id3v2_size(FIL* file, uint32_t *id3v2_size)
|
||||||
{
|
{
|
||||||
|
if (id3v2_size == NULL) {
|
||||||
|
LOG_E("id3v2_size is null");
|
||||||
|
return audio_hal_invalid_argument;
|
||||||
|
}
|
||||||
|
|
||||||
FRESULT f_result = f_lseek(file, 0); //定位到文件开头
|
FRESULT f_result = f_lseek(file, 0); //定位到文件开头
|
||||||
if (f_result != FR_OK) {
|
if (f_result != FR_OK) {
|
||||||
|
LOG_E("seeking file failed, error code=%d", f_result);
|
||||||
return audio_hal_error_read_file;
|
return audio_hal_error_read_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,6 +37,7 @@ audio_hal_result_t audio_mp3_get_id3v2_size(FIL* file, uint32_t *id3v2_size)
|
|||||||
audio_mp3_id3v2_head_t id3v2_head;
|
audio_mp3_id3v2_head_t id3v2_head;
|
||||||
f_result = f_read(file, &id3v2_head, sizeof(id3v2_head), &br); //读取ID3v2标签头
|
f_result = f_read(file, &id3v2_head, sizeof(id3v2_head), &br); //读取ID3v2标签头
|
||||||
if (f_result != FR_OK) {
|
if (f_result != FR_OK) {
|
||||||
|
LOG_E("error while reading file, error code=%d", f_result);
|
||||||
return audio_hal_error_read_file;
|
return audio_hal_error_read_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,7 +97,7 @@ audio_hal_result_t audio_mp3_play(const char *file_name, audio_hal_result_t (*pl
|
|||||||
|
|
||||||
f_result = f_lseek(file, id3v2_offset); //跳过ID3v2 Tag
|
f_result = f_lseek(file, id3v2_offset); //跳过ID3v2 Tag
|
||||||
if (f_result != FR_OK) {
|
if (f_result != FR_OK) {
|
||||||
LOG_E("seek file %s failed, error code=%d", file_name, f_result);
|
LOG_E("seeking file %s failed, error code=%d", file_name, f_result);
|
||||||
error_code = audio_hal_error_read_file;
|
error_code = audio_hal_error_read_file;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@ -146,15 +154,31 @@ audio_hal_result_t audio_mp3_play(const char *file_name, audio_hal_result_t (*pl
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t paused = 0;
|
||||||
while(1) {
|
while(1) {
|
||||||
/* 执行播放中用户事件处理代码 */
|
/* 执行播放中用户事件处理代码 */
|
||||||
if (playing_routine != NULL) {
|
if (playing_routine != NULL) {
|
||||||
error_code = playing_routine();
|
error_code = playing_routine();
|
||||||
if (error_code != audio_hal_ok) {
|
if (error_code == audio_hal_result_pause) {
|
||||||
|
paused = !paused;
|
||||||
|
if (paused != 0) {
|
||||||
|
audio_hal_pause();
|
||||||
|
LOG_D("play paused");
|
||||||
|
} else {
|
||||||
|
audio_hal_resume();
|
||||||
|
LOG_D("play resumed");
|
||||||
|
}
|
||||||
|
} else if (error_code != audio_hal_ok) {
|
||||||
LOG_W("user routine returned %d, exiting", error_code);
|
LOG_W("user routine returned %d, exiting", error_code);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (paused) {
|
||||||
|
delay_ms(10);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
#if AUDIO_MP3_DECODE_TIME_DEBUG
|
#if AUDIO_MP3_DECODE_TIME_DEBUG
|
||||||
TIM_SetCounter(TIM4, 0);
|
TIM_SetCounter(TIM4, 0);
|
||||||
TIM_Cmd(TIM4, ENABLE); //使能定时器2
|
TIM_Cmd(TIM4, ENABLE); //使能定时器2
|
||||||
|
|||||||
@ -6,6 +6,6 @@
|
|||||||
#define AUDIO_MP3_DECODE_TIME_DEBUG 0
|
#define AUDIO_MP3_DECODE_TIME_DEBUG 0
|
||||||
#define AUDIO_MP3_FILE_BUFFER_SIZE 8192
|
#define AUDIO_MP3_FILE_BUFFER_SIZE 8192
|
||||||
|
|
||||||
audio_hal_result_t audio_mp3_play(const char *file_name, audio_hal_result_t (*playing_process)(void));
|
audio_hal_result_t audio_mp3_play(const char *file_name, audio_hal_result_t (*playing_routine)(void));
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -32,7 +32,7 @@ audio_hal_result_t audio_player_playing_routine(void)
|
|||||||
return audio_hal_result_prev;
|
return audio_hal_result_prev;
|
||||||
|
|
||||||
case bsp_key_pause_short:
|
case bsp_key_pause_short:
|
||||||
return audio_hal_ok;
|
return audio_hal_result_pause;
|
||||||
|
|
||||||
case bsp_key_next_long:
|
case bsp_key_next_long:
|
||||||
return audio_hal_result_random;
|
return audio_hal_result_random;
|
||||||
@ -53,8 +53,8 @@ audio_hal_result_t audio_player_play_file(const char *path)
|
|||||||
|
|
||||||
if(!strcasecmp(ext_name, "MP3")) {
|
if(!strcasecmp(ext_name, "MP3")) {
|
||||||
return audio_mp3_play(path, audio_player_playing_routine);
|
return audio_mp3_play(path, audio_player_playing_routine);
|
||||||
// } else if(!strcasecmp(ext_name, "WAV")) {
|
} else if(!strcasecmp(ext_name, "WAV")) {
|
||||||
// return audio_wav_play(path, audio_player_playing_routine);
|
return audio_wav_play(path, audio_player_playing_routine);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_W("unknown file format \"%s\" of %s", ext_name, path);
|
LOG_W("unknown file format \"%s\" of %s", ext_name, path);
|
||||||
@ -178,7 +178,7 @@ void audio_player(void)
|
|||||||
|
|
||||||
case audio_hal_error_unsupported_format:
|
case audio_hal_error_unsupported_format:
|
||||||
case audio_hal_error_unsupported_parameter: //文件不支持
|
case audio_hal_error_unsupported_parameter: //文件不支持
|
||||||
if (switch_direction == 1) { //上次切换方向是下一曲
|
if (switch_direction == 1) { //根据上次切换方向逐一尝试
|
||||||
goto next_file;
|
goto next_file;
|
||||||
} else {
|
} else {
|
||||||
goto prev_file;
|
goto prev_file;
|
||||||
@ -189,8 +189,8 @@ void audio_player(void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case audio_hal_ok: //正常播放完成
|
case audio_hal_ok: //正常播放完成
|
||||||
case audio_hal_result_next:
|
|
||||||
next_file:
|
next_file:
|
||||||
|
case audio_hal_result_next:
|
||||||
switch_direction = 1;
|
switch_direction = 1;
|
||||||
current_file_index ++;
|
current_file_index ++;
|
||||||
if(current_file_index >= audio_file_count) {
|
if(current_file_index >= audio_file_count) {
|
||||||
@ -198,8 +198,8 @@ next_file:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case audio_hal_result_prev:
|
|
||||||
prev_file:
|
prev_file:
|
||||||
|
case audio_hal_result_prev:
|
||||||
switch_direction = 0;
|
switch_direction = 0;
|
||||||
if(current_file_index != 0) {
|
if(current_file_index != 0) {
|
||||||
current_file_index --;
|
current_file_index --;
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "audio_hal.h"
|
#include "audio_hal.h"
|
||||||
#include "audio_mp3.h"
|
#include "audio_mp3.h"
|
||||||
//#include "audio_wav.h"
|
#include "audio_wav.h"
|
||||||
|
|
||||||
void audio_player(void);
|
void audio_player(void);
|
||||||
|
|
||||||
|
|||||||
233
ch32v307_mp3_dac/User/audio/audio_wav.c
Normal file
233
ch32v307_mp3_dac/User/audio/audio_wav.c
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
#include "audio_wav.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "delay.h"
|
||||||
|
#include "bsp_led.h"
|
||||||
|
#include "ff.h"
|
||||||
|
#include "tlsf.h"
|
||||||
|
|
||||||
|
typedef struct __attribute__((packed)) { //RIFF块 用于指示文件类型
|
||||||
|
uint32_t chunk_id; /* ID:"RIFF" 即0x46464952 */
|
||||||
|
uint32_t chunk_size ;/* 集合大小 等于文件总大小-8 */
|
||||||
|
uint32_t format;/* 格式:"WAVE" 即0x45564157 */
|
||||||
|
} audio_wav_riff_chunk_t;
|
||||||
|
|
||||||
|
typedef struct __attribute__((packed)) { //FMT块 用于记录WAV文件的信息
|
||||||
|
uint32_t chunk_id; /* ID:"fmt " 即0x20746D66 */
|
||||||
|
uint32_t chunk_size; /* 子集合大小(不包括ID和Size) */
|
||||||
|
uint16_t audio_format; /* 音频格式 0X01:线性PCM 0X11:IMA ADPCM */
|
||||||
|
uint16_t channel_count; /* 通道数量 1表示单声道 2表示双声道 */
|
||||||
|
uint32_t sample_rate; /* 采样率 */
|
||||||
|
uint32_t byte_rate; /* 字节速率 */
|
||||||
|
uint16_t block_align; /* 块对齐(字节) */
|
||||||
|
uint16_t sample_size; /* 单个采样数据大小;4位ADPCM,设置为4 */
|
||||||
|
} audio_wav_fmt_chunk_t;
|
||||||
|
|
||||||
|
typedef struct __attribute__((packed)) { //通用的Chunk头定义 用于寻找"data"块
|
||||||
|
uint32_t chunk_id; /* ID:"data" 即0x61746164 */
|
||||||
|
uint32_t chunk_size; /* 子集合大小(不包括ID和Size) */
|
||||||
|
} audio_wav_hdr_chunk_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t format; /* 音频格式 0X01表示线性PCM 0X11表示IMA ADPCM */
|
||||||
|
uint16_t channel_count; /* 通道数量 1表示单声道 2表示双声道 */
|
||||||
|
uint16_t block_align; /* 块对齐(字节) */
|
||||||
|
uint32_t bitrate; /* 比特率(位速) */
|
||||||
|
uint32_t sample_rate; /* 采样率 */
|
||||||
|
uint16_t sample_size; /* 位数 如16bit, 24bit, 32bit */
|
||||||
|
uint32_t data_offset; /* 数据帧开始的位置(在文件里面的偏移) */
|
||||||
|
} audio_wav_info_t;
|
||||||
|
|
||||||
|
static audio_hal_result_t audio_wav_get_info(FIL* file, audio_wav_info_t* wav_info)
|
||||||
|
{
|
||||||
|
if (wav_info == NULL) {
|
||||||
|
LOG_E("wav_info is null");
|
||||||
|
return audio_hal_invalid_argument;
|
||||||
|
}
|
||||||
|
memset(wav_info, 0, sizeof(audio_wav_info_t));
|
||||||
|
|
||||||
|
uint8_t read_buffer[sizeof(audio_wav_fmt_chunk_t)]; //最大的头类型
|
||||||
|
UINT br;
|
||||||
|
|
||||||
|
FRESULT f_result = f_lseek(file, 0); //定位到文件最开头
|
||||||
|
if (f_result != FR_OK) {
|
||||||
|
LOG_E("seeking file failed, error code=%d", f_result);
|
||||||
|
return audio_hal_error_read_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
f_result = f_read(file, read_buffer, sizeof(audio_wav_riff_chunk_t), &br);
|
||||||
|
if (f_result != FR_OK) {
|
||||||
|
LOG_E("error while reading file, error code=%d", f_result);
|
||||||
|
return audio_hal_error_read_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
audio_wav_riff_chunk_t *riff_chunk = (audio_wav_riff_chunk_t*)read_buffer; //RIFF块
|
||||||
|
|
||||||
|
if(riff_chunk->chunk_id != 0x46464952 || riff_chunk->format != 0x45564157) { //如果块ID不是RIFF或格式不是WAVE
|
||||||
|
LOG_E("RIFF chunk mismatch, file is not valid RIFF file");
|
||||||
|
return audio_hal_error_unsupported_format; //不是RIFF文件
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t fptr = sizeof(audio_wav_riff_chunk_t); //跳过RIFF块 12bytes
|
||||||
|
|
||||||
|
f_result = f_lseek(file, fptr); //定位到fptr处
|
||||||
|
if (f_result != FR_OK) {
|
||||||
|
LOG_E("seeking file failed, error code=%d", f_result);
|
||||||
|
return audio_hal_error_read_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
f_result = f_read(file, read_buffer, sizeof(audio_wav_fmt_chunk_t), &br);
|
||||||
|
if (f_result != FR_OK) {
|
||||||
|
LOG_E("error while reading file, error code=%d", f_result);
|
||||||
|
return audio_hal_error_read_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
audio_wav_fmt_chunk_t *fmt_chunk = (audio_wav_fmt_chunk_t*)read_buffer; //FMT块
|
||||||
|
if(fmt_chunk->chunk_id != 0x20746D66) { //判断是否为FMT块
|
||||||
|
LOG_E("FMT chunk mismatch, file is not valid WAVE file");
|
||||||
|
return audio_hal_error_unsupported_format; //文件格式不是WAVE
|
||||||
|
}
|
||||||
|
|
||||||
|
wav_info->format = fmt_chunk->audio_format; //音频格式
|
||||||
|
wav_info->channel_count = fmt_chunk->channel_count; //通道数
|
||||||
|
wav_info->sample_rate = fmt_chunk->sample_rate; //采样率
|
||||||
|
wav_info->bitrate = fmt_chunk->byte_rate*8; //位速率是8倍的字节速率
|
||||||
|
wav_info->block_align = fmt_chunk->block_align; //块对齐
|
||||||
|
wav_info->sample_size = fmt_chunk->sample_size; //位数 16/24/32位
|
||||||
|
|
||||||
|
fptr += fmt_chunk->chunk_size + 8; //去掉FMTChunk的大小 注意chunk_size不包含ID和Size的大小
|
||||||
|
|
||||||
|
while(1) { //找到PCM数据的开始
|
||||||
|
f_result = f_lseek(file, fptr);
|
||||||
|
if (f_result != FR_OK) {
|
||||||
|
LOG_E("seeking file failed, error code=%d", f_result);
|
||||||
|
return audio_hal_error_read_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
f_result = f_read(file, read_buffer, sizeof(audio_wav_hdr_chunk_t), &br);
|
||||||
|
if (f_result != FR_OK) {
|
||||||
|
LOG_E("error while reading file, error code=%d", f_result);
|
||||||
|
return audio_hal_error_read_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
audio_wav_hdr_chunk_t *chunk_hdr = (audio_wav_hdr_chunk_t*)read_buffer;
|
||||||
|
|
||||||
|
if(chunk_hdr->chunk_id == 0x61746164) { //是"data"块
|
||||||
|
wav_info->data_offset = fptr + 8; //跳过Chunkt头
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fptr += chunk_hdr->chunk_size + 8; //继续寻找下一个Chunk
|
||||||
|
|
||||||
|
if(fptr > 4096) { //找了4k还没有找到
|
||||||
|
LOG_E("cannot find valid data chunk, file is not valid WAVE file");
|
||||||
|
return audio_hal_error_unsupported_format; //文件格式不是WAVE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return audio_hal_ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
audio_hal_result_t audio_wav_play(const char* file_name, audio_hal_result_t (*playing_routine)(void))
|
||||||
|
{
|
||||||
|
audio_hal_result_t error_code = audio_hal_ok;
|
||||||
|
FIL *file = NULL;
|
||||||
|
|
||||||
|
file = tlsf_malloc(sizeof(FIL));
|
||||||
|
if (file == NULL) {
|
||||||
|
LOG_E("error while allocating memory for mp3 file");
|
||||||
|
error_code = audio_hal_error_insufficient_memory;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
FRESULT f_result = f_open(file, file_name, FA_READ);
|
||||||
|
if (f_result == FR_OK) {
|
||||||
|
LOG_I("open %s successful", file_name);
|
||||||
|
} else {
|
||||||
|
LOG_E("open %s failed, error code=%d", file_name, f_result);
|
||||||
|
error_code = audio_hal_error_open_file;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
audio_wav_info_t wav_info;
|
||||||
|
error_code = audio_wav_get_info(file, &wav_info); //获取文件信息
|
||||||
|
if(error_code != audio_hal_ok) {
|
||||||
|
LOG_E("error while getting wave file info of %s", file_name);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wav_info.format == 0x01) { //音频格式不PCM
|
||||||
|
LOG_I("wave file format: PCM, bitrate: %dkbps", wav_info.bitrate / 1000);
|
||||||
|
} else {
|
||||||
|
LOG_E("format of wave file(0x%02X) is not supported", wav_info.format);
|
||||||
|
error_code = audio_hal_error_unsupported_parameter;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 初始化Audio HAL */
|
||||||
|
error_code = audio_hal_start(AUDIO_WAV_FILE_BUFFER_SIZE / wav_info.channel_count / (wav_info.sample_size / 8),
|
||||||
|
wav_info.sample_size, wav_info.sample_rate, wav_info.channel_count);
|
||||||
|
if (error_code != audio_hal_ok) {
|
||||||
|
LOG_E("error while starting audio hal, error code=%d", error_code);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
f_result = f_lseek(file, wav_info.data_offset);
|
||||||
|
if (f_result != FR_OK) {
|
||||||
|
LOG_E("seeking file failed, error code=%d", f_result);
|
||||||
|
error_code = audio_hal_error_read_file;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT br;
|
||||||
|
uint8_t paused = 0;
|
||||||
|
while(1) {
|
||||||
|
/* 执行播放中用户事件处理代码 */
|
||||||
|
if (playing_routine != NULL) {
|
||||||
|
error_code = playing_routine();
|
||||||
|
if (error_code == audio_hal_result_pause) {
|
||||||
|
paused = !paused;
|
||||||
|
if (paused != 0) {
|
||||||
|
audio_hal_pause();
|
||||||
|
LOG_D("play paused");
|
||||||
|
} else {
|
||||||
|
audio_hal_resume();
|
||||||
|
LOG_D("play resumed");
|
||||||
|
}
|
||||||
|
} else if (error_code != audio_hal_ok) {
|
||||||
|
LOG_W("user routine returned %d, exiting", error_code);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (paused) {
|
||||||
|
delay_ms(10);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 等待播放完成并获取空闲缓冲区 */
|
||||||
|
void *sample = audio_hal_get_free_buffer();
|
||||||
|
f_result = f_read(file, sample, AUDIO_WAV_FILE_BUFFER_SIZE, &br); //填充缓冲区
|
||||||
|
if (f_result != FR_OK) {
|
||||||
|
LOG_E("error while reading file, error code=%d", f_result);
|
||||||
|
error_code = audio_hal_error_read_file;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
audio_hal_dac_postprocess(sample);
|
||||||
|
|
||||||
|
if(br < AUDIO_WAV_FILE_BUFFER_SIZE) { //文件读取到末尾
|
||||||
|
LOG_I("play done");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
error:
|
||||||
|
audio_hal_stop();
|
||||||
|
|
||||||
|
if (file) {
|
||||||
|
f_close(file);
|
||||||
|
tlsf_free(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
return error_code;
|
||||||
|
}
|
||||||
10
ch32v307_mp3_dac/User/audio/audio_wav.h
Normal file
10
ch32v307_mp3_dac/User/audio/audio_wav.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#ifndef __AUDIO_WAV_H
|
||||||
|
#define __AUDIO_WAV_H
|
||||||
|
|
||||||
|
#include "audio_hal.h"
|
||||||
|
|
||||||
|
#define AUDIO_WAV_FILE_BUFFER_SIZE 4608
|
||||||
|
|
||||||
|
audio_hal_result_t audio_wav_play(const char* file_name, audio_hal_result_t (*playing_routine)(void));
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -9,13 +9,12 @@
|
|||||||
#include "ff.h"
|
#include "ff.h"
|
||||||
#include "tlsf.h"
|
#include "tlsf.h"
|
||||||
|
|
||||||
#define TLSF_POOL_SIZE 36 * 1024
|
static uint8_t tlsf_pool[36 * 1024];
|
||||||
static uint8_t tlsf_pool[TLSF_POOL_SIZE];
|
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
delay_init();
|
delay_init();
|
||||||
init_memory_pool(TLSF_POOL_SIZE, tlsf_pool);
|
init_memory_pool(sizeof(tlsf_pool), tlsf_pool);
|
||||||
|
|
||||||
audio_hal_init_dac();
|
audio_hal_init_dac();
|
||||||
bsp_usart1_init(115200);
|
bsp_usart1_init(115200);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user