Files
OpenTXW81X/sdk/app/amr_app/amr_app.c
T
2025-08-27 09:51:58 +01:00

720 lines
17 KiB
C

#include "sys_config.h"
#include "typesdef.h"
#include "osal/string.h"
#include "osal/semaphore.h"
#include "osal/mutex.h"
#include "osal/irq.h"
#include "osal/task.h"
#include "osal/sleep.h"
#include "osal/timer.h"
#include "osal/work.h"
#include "custom_mem/custom_mem.h"
#include "stream_frame.h"
#include "interf_dec.h"
#include "sp_dec.h"
#include "typedef.h"
#include "amr_app.h"
#include "fatfs/osal_file.h"
#include "osal/string.h"
static uint32_t get_amrnb_data_len(void *data)
{
struct data_structure *d = (struct data_structure *)data;
return ((uint32_t)d->priv);
}
static uint32_t set_amrnb_data_len(void *data,uint32_t len)
{
struct data_structure *d = (struct data_structure *)data;
d->priv = (void*)len;
return (uint32_t)len;
}
static const stream_ops_func stream_sound_ops =
{
.get_data_len = get_amrnb_data_len,
.set_data_len = set_amrnb_data_len,
// .set_data_time = set_sound_data_time,
};
static int opcode_func(stream *s,void *priv,int opcode)
{
int res = 0;
switch(opcode)
{
case STREAM_OPEN_ENTER:
break;
case STREAM_OPEN_EXIT:
{
stream_data_dis_mem_custom(s);
streamSrc_bind_streamDest(s,R_SPEAKER);
streamSrc_bind_streamDest(s,R_SAVE_STREAM_DATA);
s->priv = priv;
}
break;
case STREAM_OPEN_FAIL:
break;
case STREAM_DATA_DIS:
{
struct data_structure *data = (struct data_structure *)priv;
//int data_num = (int)data->priv;
data->type = SET_DATA_TYPE(SOUND,SOUND_AMRNB);//设置声音的类型
data->priv = (void*)(AMRNB_TO_PCM_SIZE*2);
//注册对应函数
data->ops = (stream_ops_func*)&stream_sound_ops;
//申请最大的音频size
data->data = (void*)custom_malloc_psram((AMRNB_TO_PCM_SIZE*2));
}
break;
case STREAM_DATA_DESTORY:
{
struct data_structure *data = (struct data_structure *)priv;
if(data->data)
{
custom_free_psram(data->data);
}
}
break;
//如果释放空间,则删除所有的节点
case STREAM_DATA_FREE:
{
}
break;
case STREAM_DATA_FREE_END:
break;
//每次即将发送到一个流,就调用一次
case STREAM_SEND_TO_DEST:
{
}
break;
//数据发送完成
case STREAM_SEND_DATA_FINISH:
{
}
break;
//退出,则关闭对应得流
case STREAM_CLOSE_EXIT:
{
}
break;
//这里移除priv(流名称动态申请)
case STREAM_DEL:
{
if(s->priv)
{
custom_free(s->priv);
}
}
default:
//默认都返回成功
break;
}
return res;
}
static struct amr_extern_read *g_amrnb_decode = NULL;
//读取当前amr解码的状态,如果播放之前,最好先判断一下
uint8_t get_amrnb_decode_status()
{
//os_printf("g_amrnb_decode:%X\n",g_amrnb_decode);
if(g_amrnb_decode)
{
// os_printf("g_amrnb_decode->inside_status:%d\n",g_amrnb_decode->inside_status);
return g_amrnb_decode->inside_status;
}
return AMR_STOP;
}
//外部调用,可以控制mp3解码状态,但不是立刻生效,应该是等待解码下一帧开始生效
uint8_t set_amrnb_decode_status(uint8_t status)
{
if(g_amrnb_decode)
{
g_amrnb_decode->status = status;
}
return 1;
}
void amrnb_decode_file_thread(void *d)
{
stream *s = NULL;
uint32_t offset = 0;
uint32_t readlen = 0;
uint32_t read_size = 0;
uint32_t timeout = 0;
int frames = 0;
int send_success = 0;
struct data_structure *data = NULL;
uint32_t data_offset = 0;
short *buf = NULL;
short synth[160];
unsigned char analysis[32];
enum Mode dec_mode;
char magic[8];
const short block_size[16]={ 12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0 };
struct amr_extern_read *amr = (struct amr_extern_read*)d;
char *amr_stream_name = (char*)custom_malloc(64);
os_sprintf(amr_stream_name,"%s_%d",S_AMRNB_AUDIO,(uint32_t)(os_jiffies()%1000));
s = open_stream_available(amr_stream_name,8,0,opcode_func,amr_stream_name);
if(!s)
{
goto amrnb_decode_file_thread_end;
}
int * destate;
os_printf("%s:%d start\n",__FUNCTION__,__LINE__);
//识别是否为正常的amrnb数据
readlen = amr->amr_read( amr,magic, offset,sizeof( char )*strlen( AMRNB_MAGIC_NUMBER ));
offset += readlen;
if (strncmp( magic, AMRNB_MAGIC_NUMBER, strlen( AMRNB_MAGIC_NUMBER ) ) )
{
os_printf("%s:%d\tmagic:%s\n",__FUNCTION__,__LINE__,magic);
goto amrnb_decode_file_thread_end;
}
broadcast_cmd_to_destStream(s,SET_CMD_TYPE(CMD_AUDIO_DAC_MODIFY_HZ,8000));
destate = Decoder_Interface_init();
/* find mode, read file */
while(amr->amr_read( amr,analysis, offset,sizeof (unsigned char)) > 0)
{
//这里判断一下是否暂停或者其他操作
if(amr->status == AMR_PAUSE)
{
printf("%s pause\n",__FUNCTION__);
amr->inside_status = amr->status;
while(amr->status == AMR_PAUSE)
{
os_sleep_ms(1);
}
amr->inside_status = AMR_PLAY;
}
//退出
if(amr->status == AMR_STOP)
{
printf("%s stop\n",__FUNCTION__);
//mad_read->inside_status = mad_read->status;
break;
}
offset += sizeof (unsigned char);
dec_mode = (analysis[0] >> 3) & 0x000F;
read_size = block_size[dec_mode];
readlen = amr->amr_read( amr,&analysis[1], offset,read_size);
if(readlen <= 0)
{
break;
}
offset += readlen;
frames ++;
/* call decoder */
//可以设置正确的buf位置
Decoder_Interface_Decode(destate, analysis, synth, 0);
//这里进行拷贝数据到节点,然后发送,先获取data,然后设置copy buf的空间
timeout = 0;
while(!data && timeout < 1000)
{
data = get_src_data_f(s);
if(!data)
{
os_sleep_ms(1);
timeout++;
}
else
{
//数据拷贝偏移清0
data_offset = 0;
}
}
//timeout超时,可能由异常
if(timeout >= 1000)
{
break;
}
//这里是拷贝数据
buf = (short*)get_stream_real_data(data);
memcpy(buf+data_offset,synth,160*2);
data_offset+=160;
//实际这里一定不能大于,如果大于就是越界了,当data_offset == AMRNB_TO_PCM_SIZE,代表这个音频数据
//写满,可以发送出去进行播放
if(data_offset >= AMRNB_TO_PCM_SIZE)
{
//先hold住,因为可能不会立刻发送成功
hold_data(data);
//尝试发送
timeout = 0;
set_stream_real_data_len(data,AMRNB_TO_PCM_SIZE*2);
send_success = 0;
while(!send_success && timeout < 1000)
{
send_success = send_data_to_stream(data);
if(!send_success)
{
os_sleep_ms(1);
timeout++;
}
}
//发送成功或者超时,则释放
free_data(data);
//os_printf("%s2 data:%X\n",__FUNCTION__,data);
data = NULL;
//timeout超时,可能由异常
if(timeout >= 1000 || send_success == 0)
{
os_printf("%s:%d timeout:%d\t send_success:%d err ~~~~~~~~~~~~~~~~~~\n",__FUNCTION__,__LINE__,timeout,send_success);
break;
}
data_offset = 0;
}
//osal_fwrite( synth, sizeof (short), 160, file_speech );
}
if(data)
{
if(data_offset > 0)
{
//这里将剩余数据清0
buf = (short*)get_stream_real_data(data);
memset(buf+data_offset,0,(AMRNB_TO_PCM_SIZE-data_offset)*2);
set_stream_real_data_len(data,AMRNB_TO_PCM_SIZE*2);
send_success = 0;
timeout = 0;
hold_data(data);
while(!send_success && timeout < 1000)
{
send_success = send_data_to_stream(data);
if(!send_success)
{
os_sleep_ms(1);
timeout++;
}
}
//发送成功或者超时,则释放
free_data(data);
}
else
{
force_del_data(data);
}
//os_printf("%s1 data:%X\n",__FUNCTION__,data);
data = NULL;
}
Decoder_Interface_exit(destate);
os_printf("frames:%d\n",frames);
os_printf("%s:%d end\n",__FUNCTION__,__LINE__);
amrnb_decode_file_thread_end:
amr->inside_status = AMR_STOP;
amr->amr_close(amr,NULL);
if(s)
{
close_stream(s);
}
}
#include "dec_if.h"
void amrwb_decode_file_thread(void *d)
{
stream *s = NULL;
uint32_t offset = 0;
uint32_t readlen = 0;
uint32_t timeout = 0;
int frames = 0;
int send_success = 0;
struct data_structure *data = NULL;
uint32_t data_offset = 0;
short *buf = NULL;
Word16 synth[L_FRAME16k]; /* Buffer for speech @ 16kHz */
UWord8 serial[NB_SERIAL_MAX];
//unsigned char analysis[32];
char magic[16] = {0};
const UWord8 block_size[16]= {18, 24, 33, 37, 41, 47, 51, 59, 61, 6, 6, 0, 0, 0, 1, 1};
void *st;
Word16 mode;
struct amr_extern_read *amr = (struct amr_extern_read*)d;
char *amr_stream_name = (char*)custom_malloc(64);
os_sprintf(amr_stream_name,"%s_%d",S_AMRWB_AUDIO,(uint32_t)(os_jiffies()%1000));
s = open_stream_available(amr_stream_name,8,0,opcode_func,amr_stream_name);
if(!s)
{
goto amrwb_decode_file_thread_end;
}
os_printf("%s:%d start\n",__FUNCTION__,__LINE__);
//识别是否为正常的amrnb数据
readlen = amr->amr_read( amr,magic, offset,sizeof( char )*strlen( AMRWB_MAGIC_NUMBER ));
offset += readlen;
os_printf("magic:%s\n",magic);
if (strncmp( magic, AMRWB_MAGIC_NUMBER, strlen( AMRWB_MAGIC_NUMBER ) ) )
{
goto amrwb_decode_file_thread_end;
}
//修改一下硬件的采样率
broadcast_cmd_to_destStream(s,SET_CMD_TYPE(CMD_AUDIO_DAC_MODIFY_HZ,16000));
st = D_IF_init();
/* find mode, read file */
while(amr->amr_read( amr,serial, offset,sizeof (UWord8)) > 0)
{
//这里判断一下是否暂停或者其他操作
if(amr->status == AMR_PAUSE)
{
printf("%s pause\n",__FUNCTION__);
amr->inside_status = amr->status;
while(amr->status == AMR_PAUSE)
{
os_sleep_ms(1);
}
amr->inside_status = AMR_PLAY;
}
//退出
if(amr->status == AMR_STOP)
{
printf("%s stop\n",__FUNCTION__);
//mad_read->inside_status = mad_read->status;
break;
}
offset += sizeof (unsigned char);
mode = (Word16)((serial[0] >> 3) & 0x0F);
readlen = amr->amr_read( amr,&serial[1], offset,block_size[mode]-1);
if(readlen <= 0)
{
break;
}
offset += readlen;
frames ++;
/* call decoder */
//可以设置正确的buf位置
D_IF_decode( st, serial, synth, _good_frame);
//这里进行拷贝数据到节点,然后发送,先获取data,然后设置copy buf的空间
timeout = 0;
while(!data && timeout < 1000)
{
data = get_src_data_f(s);
if(!data)
{
os_sleep_ms(1);
timeout++;
}
else
{
//数据拷贝偏移清0
data_offset = 0;
}
}
//timeout超时,可能由异常
if(timeout >= 1000)
{
break;
}
//这里是拷贝数据
buf = (short*)get_stream_real_data(data);
memcpy(buf+data_offset,synth,L_FRAME16k*2);
data_offset+=L_FRAME16k;
//实际这里一定不能大于,如果大于就是越界了,当data_offset == AMRWB_TO_PCM_SIZE,代表这个音频数据
//写满,可以发送出去进行播放
if(data_offset >= AMRWB_TO_PCM_SIZE)
{
//先hold住,因为可能不会立刻发送成功
hold_data(data);
//尝试发送
timeout = 0;
set_stream_real_data_len(data,AMRWB_TO_PCM_SIZE*2);
send_success = 0;
while(!send_success && timeout < 1000)
{
send_success = send_data_to_stream(data);
if(!send_success)
{
os_sleep_ms(1);
timeout++;
}
}
//发送成功或者超时,则释放
free_data(data);
//os_printf("%s2 data:%X\n",__FUNCTION__,data);
data = NULL;
//timeout超时,可能由异常
if(timeout >= 1000 || send_success == 0)
{
os_printf("%s:%d timeout:%d\t send_success:%d err ~~~~~~~~~~~~~~~~~~\n",__FUNCTION__,__LINE__,timeout,send_success);
break;
}
data_offset = 0;
}
//osal_fwrite( synth, sizeof (short), 160, file_speech );
}
if(data)
{
if(data_offset > 0)
{
_os_printf("++++++++++++++++++++++\n");
//这里将剩余数据清0
buf = (short*)get_stream_real_data(data);
memset(buf+data_offset,0,(AMRWB_TO_PCM_SIZE-data_offset)*2);
set_stream_real_data_len(data,AMRWB_TO_PCM_SIZE*2);
send_success = 0;
timeout = 0;
hold_data(data);
while(!send_success && timeout < 1000)
{
send_success = send_data_to_stream(data);
if(!send_success)
{
os_sleep_ms(1);
timeout++;
}
}
//发送成功或者超时,则释放
free_data(data);
}
else
{
force_del_data(data);
}
//os_printf("%s1 data:%X\n",__FUNCTION__,data);
data = NULL;
}
D_IF_exit(st);
os_printf("frames:%d\n",frames);
os_printf("%s:%d end\n",__FUNCTION__,__LINE__);
amrwb_decode_file_thread_end:
amr->inside_status = AMR_STOP;
amr->amr_close(amr,NULL);
if(s)
{
close_stream(s);
}
}
//需要根据MP3的读取长度配置
#define SD_TMP_SIZE (4096)
//这里只是读取一次文件,如果长度不对,不
uint32_t amr_read_func(struct amr_extern_read *e_read,void *ptr,uint32_t offset,uint32_t size)
{
void *fp = e_read->fp;
uint32_t len;
uint32_t read_size = SD_TMP_SIZE;
uint32_t read_offset = 0;
//os_printf("read size:%d\tptr:%X\n",size,ptr);
while(size)
{
if(size > SD_TMP_SIZE)
{
len = osal_fread(e_read->sd_buf,1,SD_TMP_SIZE,fp);
read_size += SD_TMP_SIZE;
}
else
{
len = osal_fread(e_read->sd_buf,1,size,fp);
read_size = size;
}
memcpy(ptr+read_offset,e_read->sd_buf,read_size);
read_offset += read_size;
size -= read_size;
}
return read_offset;
}
void amr_close_func(struct amr_extern_read *e_read,void *data)
{
osal_fclose(e_read->fp);
custom_free(e_read->sd_buf);
e_read->fp = NULL;
custom_free(e_read);
}
void amr_seek_func(struct amr_extern_read *e_read,uint32_t offset)
{
osal_fseek(e_read->fp,offset);
}
char myamr_buf[4098];
void *amr_read_init(char *filename)
{
//已经有使用该mp3解码,需要先等待解码结束才可以继续,可以去读取状态或者控制状态
struct amr_extern_read *e_read = (struct amr_extern_read*)custom_malloc(sizeof(struct amr_extern_read));
memset(e_read,0,sizeof(struct amr_extern_read));
e_read->fp = osal_fopen(filename,"rb");
os_printf("e_read->fp:%X\n",e_read->fp);
e_read->readsize = osal_fsize(e_read->fp);
os_printf("e_read->readsize:%d\n",e_read->readsize);
e_read->amr_read = amr_read_func;
e_read->amr_close = amr_close_func;
e_read->amr_seek = amr_seek_func;
//注意,这个要用sram的空间
e_read->sd_buf = (uint8_t*)custom_malloc(SD_TMP_SIZE);
//sd卡临时buf申请
os_printf("sd_buf:%X\n",e_read->sd_buf);
g_amrnb_decode = e_read;
return (void*)e_read;
}
void amr_decode_thread(void *d)
{
char *filename = (char *)d;
uint32_t count = 0;
uint8_t status = get_amrnb_decode_status();
if(status != AMR_STOP)
{
set_amrnb_decode_status(AMR_STOP);
}
while((get_amrnb_decode_status() != AMR_STOP) && count < 1000)
{
os_sleep_ms(1);
count ++;
}
if(count >= 1000)
{
os_printf("%s creat fail:%d\n",__FUNCTION__,get_amrnb_decode_status());
return;
}
struct amr_extern_read *amr = (struct amr_extern_read*)amr_read_init(filename);
//这里先判断是amrwb还是amrnb,根据不同去创建不同的线程
if(amr)
{
char magic[16];
amr->amr_read( amr,magic, 0,sizeof( char )*strlen( AMRWB_MAGIC_NUMBER ));
amr->amr_seek(amr,0);
//如果不是wb就是nb(即使不是nb,也会进去判断后退出)
if (strncmp( magic, AMRWB_MAGIC_NUMBER, strlen( AMRWB_MAGIC_NUMBER ) ) == 0 )
{
os_task_create("amrwb", amrwb_decode_file_thread, (void*)amr, OS_TASK_PRIORITY_NORMAL, 0, NULL, 4*1024);
}
else
{
os_task_create("amrnb", amrnb_decode_file_thread, (void*)amr, OS_TASK_PRIORITY_NORMAL, 0, NULL, 3*1024);
}
}
}