doubao_chat/apps/common/example/audio/play_audio_buffer/main.c

392 lines
8.3 KiB
C

#include "system/includes.h"
#include "server/audio_server.h"
#include "app_config.h"
#ifdef USE_AUDIO_BUFFER_TEST
enum {
AUDIO_SUCC = 0,
AUDIO_EFOPEN,
AUDIO_EREQ_OPEN,
AUDIO_EREQ_START,
AUDIO_EMEM,
AUDIO_ESER_OPEN,
};
struct audio_buffer_hdl {
char volume;
int play_time;
FILE *file;
u8 read_file_end_flag;
int audio_data_offset;
struct server *dec_server;
volatile u8 run_flag;
OS_SEM r_sem;
OS_SEM w_sem;
u8 *cache_buf;
cbuffer_t save_cbuf;
int sample_rate;
int channel;
};
static struct audio_buffer_hdl audio_buffer_handler;
#define __this (&audio_buffer_handler)
#define FIRST_INFO_SECTOR 512
#define READ_DATA_SIZE 512
static int audio_buffer_dec_stop(void)
{
int err = 0;
union audio_req req = {0};
if (!__this->file) {
return 0;
}
req.dec.cmd = AUDIO_DEC_STOP;
server_request(__this->dec_server, AUDIO_REQ_DEC, &req);
int argv[2];
argv[0] = AUDIO_SERVER_EVENT_END;
argv[1] = (int)__this->file;
server_event_handler_del(__this->dec_server, 2, argv);
fclose(__this->file);
__this->file = NULL;
return 0;
}
extern void audio_uninit();
static void dec_server_event_handler(void *priv, int argc, int *argv)
{
switch (argv[0]) {
case AUDIO_SERVER_EVENT_ERR:
log_i("audio_buffer: AUDIO_SERVER_EVENT_ERR\n");
case AUDIO_SERVER_EVENT_END:
log_i("audio_buffer: AUDIO_SERVER_EVENT_END\n");
audio_buffer_dec_stop();
audio_uninit();
break;
case AUDIO_SERVER_EVENT_CURR_TIME:
log_d("play_time: %d\n", argv[1]);
__this->play_time = argv[1];
break;
}
}
extern u8 audio_get_read_file_is_end();
extern void audio_pend_read_semaphore();
extern void audio_post_write_semaphore();
static int audio_vfs_fread(void *file, void *data, u32 len)
{
cbuffer_t *cbuf = (cbuffer_t *)file;
u32 rlen;
do {
rlen = cbuf_get_data_size(cbuf);
if (rlen < len) {
if (audio_get_read_file_is_end()) {
return cbuf_read(cbuf, data, rlen);
}
audio_post_write_semaphore();
audio_pend_read_semaphore();
continue;
}
if (cbuf_read(cbuf, data, len) > 0) {
return len;
}
} while (__this->run_flag);
return 0;
}
static int audio_vfs_fclose(void *file)
{
return 0;
}
static int audio_vfs_flen(void *file)
{
return flen(__this->file);
}
static int audio_vfs_fseek(void *file, u32 offset, int orig)
{
__this->audio_data_offset = offset;
return 0;
}
static const struct audio_vfs_ops audio_vfs_ops = {
.fread = audio_vfs_fread,
.fclose = audio_vfs_fclose,
.flen = audio_vfs_flen,
.fseek = audio_vfs_fseek,
};
static void init_audio_buffer_hdl()
{
memset(__this, 0, sizeof(__this));
}
static u8 audio_is_info_read(int read_offset)
{
return read_offset ? 1 : 0;
}
static void audio_file_data_offset()
{
fseek(__this->file, __this->audio_data_offset, SEEK_SET);
}
static int audio_check_cbuf_is_write_able(int write_len)
{
return cbuf_is_write_able(&__this->save_cbuf, write_len);
}
static void audio_semaphore_del()
{
os_sem_del(&__this->r_sem, 0);
os_sem_del(&__this->w_sem, 0);
}
static void audio_semaphore_create()
{
os_sem_create(&__this->r_sem, 0);
os_sem_create(&__this->w_sem, 0);
}
static void audio_post_write_semaphore()
{
os_sem_set(&__this->w_sem, 0);
os_sem_post(&__this->w_sem);
}
static void audio_pend_write_semaphore()
{
os_sem_pend(&__this->w_sem, 0);
}
static void audio_post_read_semaphore()
{
os_sem_set(&__this->r_sem, 0);
os_sem_post(&__this->r_sem);
}
static void audio_pend_read_semaphore()
{
os_sem_pend(&__this->r_sem, 0);
}
static void audio_set_read_file_is_end()
{
__this->read_file_end_flag = 1;
}
static u8 audio_get_read_file_is_end()
{
return __this->read_file_end_flag;
}
static int prewriting_audio_data()
{
u8 buf[READ_DATA_SIZE];
int rlen = 0;
rlen = fread(buf, 1, READ_DATA_SIZE, __this->file);
ASSERT(rlen == READ_DATA_SIZE);
rlen = cbuf_write(&__this->save_cbuf, buf, rlen);
return rlen;
}
static int file_data_write_cbuf()
{
u8 buf[READ_DATA_SIZE];
int rlen;
rlen = fread(buf, 1, READ_DATA_SIZE, __this->file);
rlen = cbuf_write(&__this->save_cbuf, buf, rlen);
return rlen;
}
static u8 is_audio_file_data_end(int rlen)
{
return rlen != READ_DATA_SIZE ? 1 : 0;
}
static void read_file_to_cbuf(void *priv)
{
int rlen;
//prewriting_audio_data();
audio_pend_write_semaphore();
audio_file_data_offset();
while (__this->run_flag) {
if (!audio_check_cbuf_is_write_able(READ_DATA_SIZE)) {
audio_pend_write_semaphore();
continue;
}
rlen = file_data_write_cbuf();
audio_post_read_semaphore();
if (is_audio_file_data_end(rlen)) {
audio_set_read_file_is_end();
break;
}
}
}
static void audio_free_init_cbuf()
{
if (__this->cache_buf) {
free(__this->cache_buf);
__this->cache_buf = NULL;
}
}
static void close_file_from_sdcard()
{
if (__this->file) {
close(__this->file);
__this->file = NULL;
}
}
static void dec_server_uninit()
{
server_close(__this->dec_server);
__this->dec_server = NULL;
}
static int audio_malloc_init_cbuf()
{
__this->cache_buf = malloc(__this->sample_rate * __this->channel * 10);
if (!__this->cache_buf) {
return AUDIO_EMEM;
}
cbuf_init(&__this->save_cbuf, __this->cache_buf, __this->sample_rate * __this->channel * 10);
return AUDIO_SUCC;
}
static void set_audio_parameter()
{
__this->volume = 50;
__this->sample_rate = 16000;
__this->channel = 2;
__this->run_flag = 1;
}
static int open_file_from_sdcard()
{
__this->file = fopen("mnt/sdfile/res/demo/animal.mp3", "r");
if (!__this->file) {
return AUDIO_EFOPEN;
}
return AUDIO_SUCC;
}
static void audio_uninit()
{
audio_free_init_cbuf();
close_file_from_sdcard();
dec_server_uninit();
audio_semaphore_del();
__this->run_flag = 0;
}
static void audio_init()
{
int ret = AUDIO_SUCC;
init_audio_buffer_hdl();
set_audio_parameter();
audio_semaphore_create();
ASSERT(ret = dec_server_init_and_register() == AUDIO_SUCC, "ret = %d\n", ret);
ASSERT(ret = open_file_from_sdcard() == AUDIO_SUCC, "ret = %d\n", ret);
ASSERT(ret = audio_malloc_init_cbuf() == AUDIO_SUCC, "ret = %d\n", ret);
}
static int audio_buffer_data_in()
{
thread_fork("read_file_to_cbuf", 20, READ_DATA_SIZE * 2, 20, 0, read_file_to_cbuf, NULL);
return AUDIO_SUCC;
}
static int audio_buffer_data_out()
{
union audio_req req = {0};
req.dec.volume = __this->volume;
req.dec.output_buf_len = 6 * 1024;
req.dec.sample_rate = __this->sample_rate;
req.dec.channel = __this->channel;
req.dec.vfs_ops = &audio_vfs_ops;
req.dec.dec_type = "mp3";
req.dec.sample_source = "dac";
req.dec.file = (FILE *)&__this->save_cbuf;
req.dec.cmd = AUDIO_DEC_OPEN;
int err = server_request(__this->dec_server, AUDIO_REQ_DEC, &req);
if (err) {
if (__this->cache_buf) {
free(__this->cache_buf);
__this->cache_buf = NULL;
}
__this->run_flag = 0;
return AUDIO_EREQ_OPEN;
}
req.dec.cmd = AUDIO_DEC_START;
server_request(__this->dec_server, AUDIO_REQ_DEC, &req);
if (err) {
if (__this->cache_buf) {
free(__this->cache_buf);
__this->cache_buf = NULL;
}
__this->run_flag = 0;
return AUDIO_EREQ_START;
}
return AUDIO_SUCC;
}
static int dec_server_init_and_register()
{
__this->dec_server = server_open("audio_server", "dec");
if (!__this->dec_server) {
return AUDIO_ESER_OPEN;
}
server_register_event_handler_to_task(__this->dec_server, NULL, dec_server_event_handler, "app_core");
return AUDIO_SUCC;
}
static int audio_buffer_play()
{
int ret = AUDIO_SUCC;
audio_init();
audio_buffer_data_in();
ASSERT(ret == audio_buffer_data_out(), "ret = %d\n", ret);
return 0;
}
static void audio_buffer_thread()
{
while (!storage_device_ready()) {
os_time_dly(20);
}
audio_buffer_play();
}
static void main()
{
thread_fork("audio_buffer", 20, 1024, 0, 0, audio_buffer_thread, 0);
}
late_initcall(main);
#endif