Initial commit: TXW82x FPV v2.7.0.7-42229 SDK + project sources

This commit is contained in:
2026-07-06 11:30:13 +08:00
commit e76462eeb7
3451 changed files with 1415300 additions and 0 deletions

View File

@@ -0,0 +1,27 @@
#ifndef _AAC_CODE_H_
#define _AAC_CODE_H_
#include "basic_include.h"
#include "lib/heap/av_heap.h"
#include "lib/heap/av_psram_heap.h"
#include "audio_code_ctrl.h"
#ifdef PSRAM_HEAP
#define AAC_CODE_MALLOC av_psram_malloc
#define AAC_CODE_ZALLOC av_psram_zalloc
#define AAC_CODE_CALLOC av_psram_calloc
#define AAC_CODE_FREE av_psram_free
#else
#define AAC_CODE_MALLOC av_malloc
#define AAC_CODE_ZALLOC av_zalloc
#define AAC_CODE_CALLOC av_calloc
#define AAC_CODE_FREE av_free
#endif
#define AAC_DEBUG(fmt, args...) //os_printf(fmt, ##args)
#define AAC_INFO os_printf
struct msi *aac_encode_init(char *filename, uint32_t samplerate, uint8_t direct_to_record, AUENC_INIT *auenc_init);
struct msi *aac_decode_init(char *filename, uint8_t loop_mode, AUDEC_INIT *audec_init);
#endif

View File

@@ -0,0 +1,584 @@
#include "basic_include.h"
#include "csi_kernel.h"
#include "lib/multimedia/msi.h"
#include "lib/multimedia/framebuff.h"
#include "lib/audio/audio_code/audio_code.h"
#include "autpc_msi/autpc_msi.h"
#include "osal_file.h"
#include "aac_code.h"
#define BUFF_SIZE 2048
#define MAX_AAC_DECODE_RXBUF 4
#define MAX_AAC_DECODE_TXBUF 4
struct aac_decode_struct {
AUDIO_TRACK audio_track;
struct fbpool tx_pool;
struct os_event event;
struct msi *msi;
struct msi *src_msi;
struct msi *autpc_msi;
char *msi_name;
void *task_hdl;
void *aac_fp;
uint8_t loop_mode;
uint8_t direct_to_dac;
uint8_t use_tpc;
uint8_t speed;
uint8_t pitch;
uint8_t destroy_self;
uint8_t next_status;
uint8_t current_status;
uint8_t inbuf[BUFF_SIZE];
int16_t dec_buf[1024*2];
};
static int32_t aac_file_read(struct aac_decode_struct *aac_decode_s, uint8_t *buf, uint32_t size)
{
int32_t read_len = 0;
read_len = osal_fread(buf, size, 1, aac_decode_s->aac_fp);
return read_len;
}
static void aac_file_decode(struct aac_decode_struct *s)
{
uint8_t endOfRead = 0;
uint8_t *enc_ptr = NULL;
int16_t *data = NULL;
int32_t ret = 0;
int32_t read_len = 0;
int32_t dec_samples = 0;
int32_t unproc_data_size = 0;
uint32_t enc_ptr_offset = 0;
uint32_t bytes_to_read = 0;
uint32_t interval_time = 0;
struct framebuff *frame_buf = NULL;
AUCODE_HDL *aac_dec = NULL;
AUCODE_FRAME_INFO aac_info;
AUDIO_TRACK *audac_fiter_track = NULL;
aac_dec = audio_coder_open(AAC_DEC, 0, 0);
if(!aac_dec)
return;
enc_ptr = s->inbuf;
while(1) {
if(s->next_status == AUCODEC_PAUSE) {
if(s->current_status == AUCODEC_RUN) {
msi_output_cmd(s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(s->audio_track)));
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_END_STREAM,(uint32_t)(&(s->audio_track)));
}
s->current_status = AUCODEC_PAUSE;
while(s->next_status == AUCODEC_PAUSE) {
os_sleep_ms(1);
}
}
if(s->next_status == AUCODEC_EXIT) {
s->current_status = AUCODEC_EXIT;
goto aac_decode_end;
}
s->current_status = AUCODEC_RUN;
if(unproc_data_size < 1536 && !endOfRead) {
bytes_to_read = BUFF_SIZE - unproc_data_size;
if(unproc_data_size)
os_memcpy(s->inbuf, enc_ptr+enc_ptr_offset, unproc_data_size);
read_len = aac_file_read(s, s->inbuf+unproc_data_size, bytes_to_read);
if(read_len <= 0) {
AAC_INFO("aac read fail,ret:%d,line:%d!\r\n",read_len,__LINE__);
endOfRead = 1;
}
else
unproc_data_size += read_len;
enc_ptr = s->inbuf;
enc_ptr_offset = 0;
}
if(unproc_data_size > 0) {
while(!frame_buf) {
frame_buf = fbpool_get(&s->tx_pool, 0, s->msi);
if(!frame_buf)
os_sleep_ms(1);
}
data = (int16_t*)frame_buf->data;
dec_samples = audio_decode_data(aac_dec, enc_ptr+enc_ptr_offset, unproc_data_size, s->dec_buf, &aac_info);
if(dec_samples <= 0) {
enc_ptr_offset += 1;
unproc_data_size -= 1;
msi_delete_fb(s->msi, frame_buf);
frame_buf = NULL;
continue;
}
if(aac_info.channels == 2) {
for(uint32_t i=0; i<dec_samples; i++)
data[i] = s->dec_buf[2*i];
}
else {
for(uint32_t i=0; i<dec_samples; i++)
data[i] = s->dec_buf[i];
}
enc_ptr_offset += aac_info.frame_bytes;
unproc_data_size -= aac_info.frame_bytes;
frame_buf->len = dec_samples*2;
frame_buf->mtype = F_AUDIO;
frame_buf->stype = FSTYPE_AUDIO_PCM;
s->audio_track.samplerate = aac_info.samplerate;
if(s->use_tpc && !s->autpc_msi) {
s->autpc_msi = autpc_msi_init(s->audio_track.samplerate, s->speed, s->pitch, dec_samples, &(s->audio_track));
if(s->autpc_msi == NULL) {
goto aac_decode_end;
}
if(s->direct_to_dac) {
msi_add_output(s->autpc_msi, NULL, "R_AUDAC");
}
msi_add_output(s->msi, NULL, s->autpc_msi->name);
}
ret = msi_output_fb(s->msi, frame_buf);
AAC_DEBUG("aac decode send framebuff:%p,ret:%d\r\n",frame_buf,ret);
msi_cmd("R_AUDAC", MSI_CMD_AUDAC, MSI_AUDAC_GET_FILTER_TRACK, (uint32_t)(&audac_fiter_track));
if(s->direct_to_dac && (!s->use_tpc) && (audac_fiter_track != (&(s->audio_track)))) {
interval_time = (frame_buf->len>>1)*1000/(aac_info.samplerate);
os_sleep_ms(interval_time);
}
frame_buf = NULL;
}
else if(endOfRead) {
goto aac_decode_end;
}
}
aac_decode_end:
msi_output_cmd(s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(s->audio_track)));
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_END_STREAM,(uint32_t)(&(s->audio_track)));
if(frame_buf) {
msi_delete_fb(s->msi, frame_buf);
frame_buf = NULL;
}
if(aac_dec)
audio_coder_close(aac_dec);
}
static void aac_msi_decode(struct aac_decode_struct *s)
{
uint8_t clear_finish = 1;
uint8_t *enc_ptr = NULL;
int16_t *send_data = NULL;
int32_t ret = 0;
int32_t data_len = 0;
int32_t dec_samples = 0;
uint32_t clear_flag = 0;
struct framebuff *recv_frame_buf = NULL;
struct framebuff *send_frame_buf = NULL;
AUCODE_HDL *aac_dec = NULL;
AUCODE_FRAME_INFO aac_info;
aac_dec = audio_coder_open(AAC_DEC, 0, 1);
if(!aac_dec)
return;
while(1) {
os_event_wait(&s->event, coder_clear_event, &clear_flag, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, 0);
if(clear_flag & coder_clear_event) {
clear_flag = 0;
clear_finish = 0;
}
if(s->next_status == AUCODEC_PAUSE) {
if(s->current_status == AUCODEC_RUN) {
msi_output_cmd(s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(s->audio_track)));
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_END_STREAM,(uint32_t)(&(s->audio_track)));
aac_dec = audio_coder_open(AAC_DEC, 0, 1);
if(!aac_dec)
return;
}
s->current_status = AUCODEC_PAUSE;
}
recv_frame_buf = msi_get_fb(s->msi, 0);
if(recv_frame_buf) {
if(clear_finish == 0) {
goto aac_decode_frame_end;
}
if(s->current_status == AUCODEC_PAUSE) {
goto aac_decode_frame_end;
}
else {
s->current_status = AUCODEC_RUN;
while(!send_frame_buf) {
send_frame_buf = fbpool_get(&s->tx_pool, 0, s->msi);
if(!send_frame_buf)
os_sleep_ms(1);
}
data_len = recv_frame_buf->len;
if(data_len > 0) {
enc_ptr = recv_frame_buf->data;
dec_samples = audio_decode_data(aac_dec, enc_ptr, data_len, s->dec_buf, &aac_info);
}
if((dec_samples <= 0) || (data_len <= 0)) {
msi_delete_fb(s->msi, send_frame_buf);
send_frame_buf = NULL;
goto aac_decode_frame_end;
}
send_data = (int16_t*)send_frame_buf->data;
if(aac_info.channels == 2) {
for(uint32_t i=0; i<dec_samples; i++)
send_data[i] = s->dec_buf[2*i];
}
else {
for(uint32_t i=0; i<dec_samples; i++)
send_data[i] = s->dec_buf[i];
}
send_frame_buf->len = dec_samples*2;
send_frame_buf->mtype = F_AUDIO;
send_frame_buf->stype = FSTYPE_AUDIO_PCM;
s->audio_track.samplerate = aac_info.samplerate;
if(s->use_tpc && !s->autpc_msi) {
s->autpc_msi = autpc_msi_init(s->audio_track.samplerate, s->speed, s->pitch, dec_samples, &(s->audio_track));
if(s->autpc_msi == NULL) {
goto aac_decode_end;
}
if(s->direct_to_dac) {
msi_add_output(s->autpc_msi, NULL, "R_AUDAC");
}
msi_add_output(s->msi, NULL, s->autpc_msi->name);
}
ret = msi_output_fb(s->msi, send_frame_buf);
AAC_DEBUG("aac decode send framebuff:%p,ret:%d\r\n",send_frame_buf,ret);
send_frame_buf = NULL;
}
aac_decode_frame_end:
AAC_DEBUG("aac decode delete framebuff:%p,len:%d,\r\n",recv_frame_buf,recv_frame_buf->len);
msi_delete_fb(s->msi, recv_frame_buf);
recv_frame_buf = NULL;
}
else {
if(clear_finish == 0) {
clear_finish = 1;
os_event_set(&s->event, coder_clear_finish_event, NULL);
}
os_sleep_ms(1);
}
if(s->next_status == AUCODEC_EXIT) {
s->current_status = AUCODEC_EXIT;
goto aac_decode_end;
}
}
aac_decode_end:
msi_output_cmd(s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(s->audio_track)));
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_END_STREAM,(uint32_t)(&(s->audio_track)));
if(recv_frame_buf) {
msi_delete_fb(NULL, recv_frame_buf);
recv_frame_buf = NULL;
}
if(send_frame_buf) {
msi_delete_fb(s->msi, send_frame_buf);
send_frame_buf = NULL;
}
if(aac_dec)
audio_coder_close(aac_dec);
}
static void aac_decode_thread(void *d)
{
struct aac_decode_struct *s = (struct aac_decode_struct *)d;
msi_get(s->msi);
if(s->direct_to_dac) {
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(s->audio_track)));
}
s->msi->enable = 1;
if(s->aac_fp) {
do {
osal_fseek(s->aac_fp, 0);
aac_file_decode(s);
if(s->current_status == AUCODEC_EXIT) {
break;
}
}while(s->loop_mode);
}
else
aac_msi_decode(s);
if(s->direct_to_dac) {
s->audio_track.priority &= 0x3F;
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(s->audio_track)));
}
os_event_set(&s->event, coder_exit_event, NULL);
while((s->next_status != AUCODEC_EXIT) && (s->destroy_self == 0)) {
s->current_status = AUCODEC_END;
os_sleep_ms(5);
}
if(s->src_msi) {
msi_del_output(s->src_msi, NULL, s->msi->name);
s->src_msi = NULL;
}
if(s->next_status != AUCODEC_EXIT)
msi_destroy(s->msi);
msi_put(s->msi);
}
static int32_t aac_decode_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
{
int32_t ret = RET_OK;
struct aac_decode_struct *aac_decode_s = (struct aac_decode_struct*)(msi->priv);
switch(cmd_id) {
case MSI_CMD_AUCODER:
{
ret = RET_ERR;
if(aac_decode_s) {
uint32_t cmd_self = (uint32_t)param1;
switch(cmd_self) {
case MSI_AUCODER_PAUSE:
{
if(aac_decode_s->current_status == AUCODEC_RUN) {
aac_decode_s->next_status = AUCODEC_PAUSE;
}
ret = RET_OK;
break;
}
case MSI_AUCODER_CONTINUE:
{
if(aac_decode_s->current_status == AUCODEC_PAUSE) {
aac_decode_s->next_status = AUCODEC_RUN;
}
ret = RET_OK;
break;
}
case MSI_AUCODER_GET_STATUS:
{
*((uint32_t*)param2) = (uint32_t)(aac_decode_s->current_status);
ret = RET_OK;
break;
}
case MSI_AUCODER_SET_SPEED:
{
aac_decode_s->speed = (uint8_t)param2;
ret = msi_output_cmd(aac_decode_s->msi,MSI_CMD_AUTPC,MSI_AUTPC_SET_SPEED,(uint32_t)(aac_decode_s->speed));
break;
}
case MSI_AUCODER_GET_SPEED:
{
*((uint32_t*)param2) = (uint32_t)(aac_decode_s->speed);
ret = RET_OK;
break;
}
case MSI_AUCODER_SET_PITCH:
{
aac_decode_s->pitch = (uint8_t)param2;
ret = msi_output_cmd(aac_decode_s->msi,MSI_CMD_AUTPC,MSI_AUTPC_SET_PITCH,(uint32_t)(aac_decode_s->pitch));
break;
}
case MSI_AUCODER_GET_PITCH:
{
*((uint32_t*)param2) = (uint32_t)(aac_decode_s->pitch);
ret = RET_OK;
break;
}
case MSI_AUCODER_CLEAR_STREAM:
{
os_event_set(&aac_decode_s->event, coder_clear_event, NULL);
os_event_wait(&aac_decode_s->event, coder_clear_finish_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
msi_output_cmd(aac_decode_s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(aac_decode_s->audio_track)));
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_CLEAR_STREAM,(uint32_t)(&(aac_decode_s->audio_track)));
ret = RET_OK;
break;
}
case MSI_AUCODER_SET_SRCMSI:
{
if(aac_decode_s->src_msi) {
msi_del_output(aac_decode_s->src_msi, NULL, msi->name);
}
aac_decode_s->src_msi = NULL;
ret = msi_add_output((struct msi*)param2, NULL, msi->name);
if(ret == RET_OK) {
aac_decode_s->src_msi = (struct msi*)param2;
}
break;
}
case MSI_AUCODER_DIRECT_TO_DAC:
{
uint32_t direct_to_dac = param2;
if(direct_to_dac && aac_decode_s->direct_to_dac == 0) {
aac_decode_s->direct_to_dac = 1;
if(aac_decode_s->use_tpc == 0) {
msi_add_output(msi, NULL, "R_AUDAC");
}
else if(aac_decode_s->autpc_msi) {
msi_add_output(aac_decode_s->autpc_msi, NULL, "R_AUDAC");
}
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(aac_decode_s->audio_track)));
}
else if(aac_decode_s->direct_to_dac == 1) {
aac_decode_s->direct_to_dac = 0;
if(aac_decode_s->use_tpc == 0) {
msi_del_output(msi, NULL, "R_AUDAC");
}
else if(aac_decode_s->autpc_msi) {
msi_del_output(aac_decode_s->autpc_msi, NULL, "R_AUDAC");
}
aac_decode_s->audio_track.priority &= 0x3F;
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(aac_decode_s->audio_track)));
}
break;
}
case MSI_AUCODER_DEINIT:
{
msi_destroy(msi);
ret = RET_OK;
break;
}
default:
break;
}
}
break;
}
case MSI_CMD_TRANS_FB:
{
ret = RET_ERR;
struct framebuff *frame_buf = (struct framebuff *)param1;
if(frame_buf->mtype == F_AUDIO) {
ret = RET_OK;
}
break;
}
case MSI_CMD_FREE_FB:
{
ret = RET_ERR;
if(aac_decode_s) {
struct framebuff *frame_buf = (struct framebuff *)param1;
fbpool_put(&aac_decode_s->tx_pool, frame_buf);
}
break;
}
case MSI_CMD_PRE_DESTROY:
{
if(aac_decode_s && aac_decode_s->task_hdl) {
aac_decode_s->next_status = AUCODEC_EXIT;
}
break;
}
case MSI_CMD_POST_DESTROY:
{
if(aac_decode_s) {
if(aac_decode_s->task_hdl) {
os_event_wait(&aac_decode_s->event, coder_exit_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
}
for(uint32_t i=0; i<MAX_AAC_DECODE_TXBUF; i++) {
struct framebuff *frame_buf = (aac_decode_s->tx_pool.pool)+i;
if(frame_buf->data) {
AAC_CODE_FREE(frame_buf->data);
frame_buf->data = NULL;
}
}
fbpool_destroy(&aac_decode_s->tx_pool);
if(aac_decode_s->event.hdl) {
os_event_del(&aac_decode_s->event);
}
if(aac_decode_s->aac_fp) {
osal_fclose(aac_decode_s->aac_fp);
aac_decode_s->aac_fp = NULL;
}
if(aac_decode_s->autpc_msi) {
autpc_msi_deinit(aac_decode_s->autpc_msi);
aac_decode_s->autpc_msi = NULL;
}
if(aac_decode_s->msi_name) {
AAC_CODE_FREE(aac_decode_s->msi_name);
aac_decode_s->msi_name = NULL;
}
AAC_CODE_FREE(aac_decode_s);
aac_decode_s = NULL;
}
break;
}
default:
break;
}
return ret;
}
struct msi *aac_decode_init(char *filename, uint8_t loop_mode, AUDEC_INIT *audec_init)
{
#if AUDIO_EN
char *msi_name = NULL;
msi_name = (char*)AAC_CODE_ZALLOC(sizeof(char)*32);
if(msi_name == NULL) {
os_printf("alloc autpc msi namefail\n");
return NULL;
}
os_snprintf(msi_name, 20, "SR_AAC_DECODE_""%04d", (int)(os_jiffies()));
struct msi *msi = msi_new(msi_name, MAX_AAC_DECODE_RXBUF, NULL);
if(msi == NULL) {
AAC_INFO("create aac decode msi fail!\r\n");
return NULL;
}
struct aac_decode_struct *aac_decode_s = (struct aac_decode_struct*)AAC_CODE_ZALLOC(sizeof(struct aac_decode_struct));
if(!aac_decode_s) {
AAC_INFO("aac_decode_s malloc fail!\r\n");
goto aac_decode_init_err;
}
msi->priv = aac_decode_s;
msi->action = (msi_action)aac_decode_msi_action;
fbpool_init(&aac_decode_s->tx_pool, MAX_AAC_DECODE_TXBUF);
for(uint32_t i=0; i<MAX_AAC_DECODE_TXBUF; i++) {
struct framebuff *frame_buf = (aac_decode_s->tx_pool.pool)+i;
frame_buf->data = (uint8_t*)AAC_CODE_MALLOC(1024 * sizeof(int16_t));
if(frame_buf->data == NULL)
{
AAC_INFO("aac decode malloc framebuff data fail!\r\n");
goto aac_decode_init_err;
}
frame_buf->priv = &(aac_decode_s->audio_track);
}
if(os_event_init(&aac_decode_s->event) != RET_OK) {
AAC_INFO("create aac decode event fail!\r\n");
goto aac_decode_init_err;
}
if(filename) {
aac_decode_s->aac_fp = osal_fopen((const char*)filename, "rb");
if(aac_decode_s->aac_fp == NULL) {
AAC_INFO("open aac file %s fail!\r\n", filename);
goto aac_decode_init_err;
}
}
if(audec_init->src_msi && (msi_add_output(audec_init->src_msi, NULL, msi->name) != RET_OK)) {
goto aac_decode_init_err;
}
aac_decode_s->msi = msi;
aac_decode_s->msi_name = msi_name;
aac_decode_s->src_msi = audec_init->src_msi;
aac_decode_s->loop_mode = loop_mode;
aac_decode_s->direct_to_dac = audec_init->direct_to_dac;
aac_decode_s->use_tpc = audec_init->use_tpc;
aac_decode_s->speed = audec_init->speed;
aac_decode_s->pitch = audec_init->pitch;
aac_decode_s->destroy_self = audec_init->destroy_self;
aac_decode_s->audio_track.priority = audec_init->priority;
aac_decode_s->audio_track.track_type = audec_init->track_type;
aac_decode_s->next_status = AUCODEC_RUN;
aac_decode_s->current_status = AUCODEC_RUN;
if(audec_init->direct_to_dac && !aac_decode_s->use_tpc) {
msi_add_output(msi, NULL, "R_AUDAC");
}
#if AAC_DEC_CTRL == AUCODER_RUN_IN_CPU1
aac_decode_s->task_hdl = os_task_create("aac_decode_thread", aac_decode_thread, (void*)aac_decode_s, OS_TASK_PRIORITY_ABOVE_NORMAL, 0, NULL, 1024);
#else
aac_decode_s->task_hdl = os_task_create("aac_decode_thread", aac_decode_thread, (void*)aac_decode_s, OS_TASK_PRIORITY_NORMAL, 0, NULL, 2048);
#endif
if(aac_decode_s->task_hdl == NULL) {
AAC_INFO("create aac decode task fail!\r\n");
goto aac_decode_init_err;
}
return msi;
aac_decode_init_err:
msi_destroy(msi);
#endif
return NULL;
}

View File

@@ -0,0 +1,404 @@
#include "basic_include.h"
#include "csi_kernel.h"
#include "lib/multimedia/msi.h"
#include "lib/multimedia/framebuff.h"
#include "lib/audio/audio_code/audio_code.h"
#include "osal_file.h"
#include "aac_code.h"
#define MAX_AAC_ENCODE_RXBUF 4
#define MAX_AAC_ENCODE_TXBUF 20
struct aac_encode_struct {
struct fbpool tx_pool;
struct os_event event;
struct msi *msi;
struct msi *src_msi;
void *task_hdl;
void *aac_fp;
uint8_t direct_to_record;
uint8_t stop_record;
uint8_t destroy_self;
uint8_t next_status;
uint8_t current_status;
uint8_t enc_buf[1536];
int16_t inbuf[1024];
uint32_t samplerate;
AUDIO_INFO audio_info;
};
static void aac_encode_thread(void *d)
{
uint8_t clear_finish = 1;
uint8_t get_audio_time = 0;
uint8_t update_audio_time = 0;
uint8_t *send_data = NULL;
int16_t *recv_data = NULL;
int32_t enc_bytes = 0;
int32_t ret = 0;
uint32_t data_len = 0;
uint32_t data_offset = 0;
uint32_t inbuf_offset = 0;
uint32_t inbuf_reslen = 2048;
uint32_t audio_time = 0;
uint32_t clear_flag = 0;
struct framebuff *send_frame_buf = NULL;
struct framebuff *recv_frame_buf = NULL;
struct aac_encode_struct *s = (struct aac_encode_struct *)d;
AUCODE_HDL *aac_enc = NULL;
s->msi->enable = 1;
msi_get(s->msi);
aac_enc = audio_coder_open(AAC_ENC, s->samplerate, 1);
if (aac_enc == NULL)
goto aac_encode_thread_end;
s->audio_info.nsamples = 1024;
s->audio_info.time_interval = s->audio_info.nsamples * 1000 / s->samplerate;
s->audio_info.samplerate = s->samplerate;
while(1) {
os_event_wait(&s->event, coder_clear_event, &clear_flag, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, 0);
if(clear_flag & coder_clear_event) {
clear_flag = 0;
clear_finish = 0;
}
if(s->next_status == AUCODEC_PAUSE) {
if(s->current_status == AUCODEC_RUN) {
audio_coder_close(aac_enc);
aac_enc = audio_coder_open(AAC_ENC, s->samplerate, 1);
if (aac_enc == NULL)
goto aac_encode_thread_end;
}
s->current_status = AUCODEC_PAUSE;
inbuf_reslen = 2048;
inbuf_offset = 0;
}
recv_frame_buf = msi_get_fb(s->msi, 0);
if(recv_frame_buf) {
if(clear_finish == 0) {
inbuf_reslen = 2048;
inbuf_offset = 0;
goto aac_encode_frame_end;
}
if(s->next_status == AUCODEC_PAUSE) {
goto aac_encode_frame_end;
}
else {
s->current_status = AUCODEC_RUN;
recv_data = (int16_t*)recv_frame_buf->data;
data_len = recv_frame_buf->len;
data_offset = 0;
if(!get_audio_time) {
get_audio_time = 1;
audio_time = recv_frame_buf->time;
}
if(update_audio_time) {
audio_time = recv_frame_buf->time;
update_audio_time = 0;
}
while(data_len >= inbuf_reslen) {
os_memcpy(s->inbuf + (inbuf_offset/2), recv_data + (data_offset/2), inbuf_reslen);
data_len -= inbuf_reslen;
data_offset += inbuf_reslen;
enc_bytes = audio_encode_data(aac_enc, s->inbuf, 1024, s->enc_buf);
inbuf_reslen = 2048;
inbuf_offset = 0;
if(enc_bytes < 0) {
AAC_INFO("aac encode failed\n");
break;
}
if(enc_bytes > 0) {
if(s->aac_fp)
osal_fwrite(s->enc_buf, 1, enc_bytes, s->aac_fp);
send_frame_buf = fbpool_get(&s->tx_pool, 0, s->msi);
if(send_frame_buf) {
send_frame_buf->data = (uint8_t*)AAC_CODE_MALLOC(enc_bytes);
if(!send_frame_buf->data) {
AAC_INFO("aac encode malloc send_frame_buf->data fail!\n");
msi_delete_fb(s->msi, send_frame_buf);
send_frame_buf = NULL;
goto aac_encode_frame_end;
}
send_data = send_frame_buf->data;
os_memcpy(send_data, s->enc_buf, enc_bytes);
send_frame_buf->len = enc_bytes;
send_frame_buf->mtype = F_AUDIO;
send_frame_buf->time = audio_time;
send_frame_buf->priv = &(s->audio_info);
ret = msi_output_fb(s->msi, send_frame_buf);
AAC_DEBUG("aac encode send framebuff:%p,ret:%d\r\n",send_frame_buf,ret);
send_frame_buf = NULL;
}
audio_time += (1024 * 1000 / s->samplerate);
if(data_len == 0)
update_audio_time = 1;
}
aac_encode_frame_end:
os_sleep_ms(1);
}
if(data_len) {
os_memcpy(s->inbuf + (inbuf_offset/2), recv_data + (data_offset/2), data_len);
inbuf_reslen -= data_len;
inbuf_offset += data_len;
data_offset = 0;
data_len = 0;
}
}
AAC_DEBUG("aac encode delete framebuff:%p,len:%d,\r\n",recv_frame_buf,recv_frame_buf->len);
msi_delete_fb(s->msi, recv_frame_buf);
recv_frame_buf = NULL;
}
else {
if(clear_finish == 0) {
clear_finish = 1;
os_event_set(&s->event, coder_clear_finish_event, NULL);
}
os_sleep_ms(1);
}
if(s->stop_record) {
if(s->aac_fp) {
osal_fclose(s->aac_fp);
s->aac_fp = NULL;
}
s->direct_to_record = 0;
s->stop_record = 0;
}
if(s->next_status == AUCODEC_EXIT) {
s->current_status = AUCODEC_EXIT;
goto aac_encode_thread_end;
}
}
aac_encode_thread_end:
if(aac_enc)
audio_coder_close(aac_enc);
os_event_set(&s->event, coder_exit_event, NULL);
while((s->next_status != AUCODEC_EXIT) && (s->destroy_self == 0)) {
s->current_status = AUCODEC_END;
os_sleep_ms(5);
}
if(s->src_msi) {
msi_del_output(s->src_msi, NULL, s->msi->name);
s->src_msi = NULL;
}
if(s->next_status != AUCODEC_EXIT) {
msi_destroy(s->msi);
}
msi_put(s->msi);
}
static int32_t aac_encode_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
{
int32_t ret = RET_OK;
struct aac_encode_struct *aac_encode_s = (struct aac_encode_struct*)(msi->priv);
switch(cmd_id) {
case MSI_CMD_AUCODER:
{
ret = RET_ERR;
if(aac_encode_s) {
uint32_t cmd_self = (uint32_t)param1;
switch(cmd_self) {
case MSI_AUCODER_PAUSE:
{
if(aac_encode_s->current_status == AUCODEC_RUN) {
aac_encode_s->next_status = AUCODEC_PAUSE;
}
ret = RET_OK;
break;
}
case MSI_AUCODER_CONTINUE:
{
if(aac_encode_s->current_status == AUCODEC_PAUSE) {
aac_encode_s->next_status = AUCODEC_RUN;
}
ret = RET_OK;
break;
}
case MSI_AUCODER_GET_STATUS:
{
*((uint32_t*)param2) = (uint32_t)(aac_encode_s->current_status);
ret = RET_OK;
break;
}
case MSI_AUCODER_CLEAR_STREAM:
{
os_event_set(&aac_encode_s->event, coder_clear_event, NULL);
os_event_wait(&aac_encode_s->event, coder_clear_finish_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
ret = RET_OK;
break;
}
case MSI_AUCODER_SET_SRCMSI:
{
if(aac_encode_s->src_msi) {
msi_del_output(aac_encode_s->src_msi, NULL, msi->name);
}
aac_encode_s->src_msi = NULL;
ret = msi_add_output((struct msi*)param2, NULL, msi->name);
if(ret == RET_OK) {
aac_encode_s->src_msi = (struct msi*)param2;
}
break;
}
case MSI_AUCODER_DEINIT:
{
aac_encode_s->stop_record = param2;
msi_destroy(msi);
ret = RET_OK;
break;
}
default:
break;
}
}
break;
}
case MSI_CMD_TRANS_FB:
{
ret = RET_ERR;
struct framebuff *frame_buf = (struct framebuff *)param1;
if(frame_buf->mtype == F_AUDIO) {
ret = RET_OK;
}
break;
}
case MSI_CMD_FREE_FB:
{
ret = RET_ERR;
if(aac_encode_s) {
struct framebuff *frame_buf = (struct framebuff *)param1;
if(frame_buf->data) {
AAC_CODE_FREE(frame_buf->data);
frame_buf->data = NULL;
}
fbpool_put(&aac_encode_s->tx_pool, frame_buf);
}
break;
}
case MSI_CMD_PRE_DESTROY:
{
if(aac_encode_s && aac_encode_s->task_hdl) {
aac_encode_s->next_status = AUCODEC_EXIT;
}
break;
}
case MSI_CMD_POST_DESTROY:
{
if(aac_encode_s) {
if(aac_encode_s->task_hdl) {
os_event_wait(&aac_encode_s->event, coder_exit_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
}
for(uint32_t i=0; i<MAX_AAC_ENCODE_TXBUF; i++) {
struct framebuff *frame_buf = (aac_encode_s->tx_pool.pool)+i;
if(frame_buf->data) {
AAC_CODE_FREE(frame_buf->data);
frame_buf->data = NULL;
}
}
fbpool_destroy(&aac_encode_s->tx_pool);
if(aac_encode_s->event.hdl) {
os_event_del(&aac_encode_s->event);
}
if(aac_encode_s->aac_fp) {
osal_fclose(aac_encode_s->aac_fp);
aac_encode_s->aac_fp = NULL;
}
AAC_CODE_FREE(aac_encode_s);
aac_encode_s = NULL;
}
break;
}
default:
break;
}
return ret;
}
struct msi *aac_encode_init(char *filename, uint32_t samplerate, uint8_t direct_to_record, AUENC_INIT *auenc_init)
{
#if AUDIO_EN
uint8_t msi_isnew = 0;
struct aac_encode_struct *aac_encode_s = NULL;
struct msi *msi = msi_new("SR_AAC_ENCODE", MAX_AAC_ENCODE_RXBUF, &msi_isnew);
if(msi && !msi_isnew) {
aac_encode_s = (struct aac_encode_struct*)(msi->priv);
if(aac_encode_s) {
if((samplerate != aac_encode_s->samplerate) || (direct_to_record && aac_encode_s->direct_to_record)) {
AAC_INFO("aac_encode_init conflict!\r\n");
goto aac_encode_init_err;
}
}
}
else if(msi && msi_isnew) {
aac_encode_s = (struct aac_encode_struct *)AAC_CODE_ZALLOC(sizeof(struct aac_encode_struct));
if(!aac_encode_s) {
AAC_INFO("aac_encode_s malloc fail!\r\n");
goto aac_encode_init_err;
}
msi->priv = aac_encode_s;
msi->action = (msi_action)aac_encode_msi_action;
fbpool_init(&aac_encode_s->tx_pool, MAX_AAC_ENCODE_TXBUF);
for(uint32_t i=0; i<MAX_AAC_ENCODE_TXBUF; i++) {
struct framebuff *frame_buf = (aac_encode_s->tx_pool.pool)+i;
frame_buf->data = NULL;
}
if(os_event_init(&aac_encode_s->event) != RET_OK) {
AAC_INFO("create aac encode event fail!\r\n");
goto aac_encode_init_err;
}
if(auenc_init->src_msi && (msi_add_output(auenc_init->src_msi, NULL, msi->name) != RET_OK)) {
goto aac_encode_init_err;
}
aac_encode_s->msi = msi;
aac_encode_s->src_msi = auenc_init->src_msi;
aac_encode_s->samplerate = samplerate;
aac_encode_s->destroy_self = auenc_init->destroy_self;
aac_encode_s->next_status = AUCODEC_RUN;
aac_encode_s->current_status = AUCODEC_RUN;
}
else {
AAC_INFO("create aac encode msi fail!\r\n");
return NULL;
}
if(direct_to_record && filename) {
aac_encode_s->aac_fp = osal_fopen((const char*)filename, "wb+");
if(aac_encode_s->aac_fp == NULL) {
AAC_INFO("open aac record file %s fail!\r\n", filename);
goto aac_encode_init_err;
}
aac_encode_s->direct_to_record = 1;
}
else if(direct_to_record && !filename) {
AAC_INFO("aac record file is null!\r\n");
goto aac_encode_init_err;
}
else if(!direct_to_record && filename) {
AAC_INFO("aac record direct_to_record is 0!\r\n");
goto aac_encode_init_err;
}
if(msi_isnew) {
#if AAC_ENC_CTRL == AUCODER_RUN_IN_CPU1
aac_encode_s->task_hdl = os_task_create("aac_encode_thread", aac_encode_thread, (void*)aac_encode_s, OS_TASK_PRIORITY_ABOVE_NORMAL, 0, NULL, 1024);
#else
aac_encode_s->task_hdl = os_task_create("aac_encode_thread", aac_encode_thread, (void*)aac_encode_s, OS_TASK_PRIORITY_NORMAL, 0, NULL, 3072);
#endif
if(aac_encode_s->task_hdl == NULL) {
AAC_INFO("create aac encode task fail!\r\n");
goto aac_encode_init_err;
}
}
return msi;
aac_encode_init_err:
msi_destroy(msi);
#endif
return NULL;
}

View File

@@ -0,0 +1,27 @@
#ifndef _ALAW_CODE_H_
#define _ALAW_CODE_H_
#include "basic_include.h"
#include "lib/heap/av_heap.h"
#include "lib/heap/av_psram_heap.h"
#include "audio_code_ctrl.h"
#ifdef PSRAM_HEAP
#define ALAW_CODE_MALLOC av_psram_malloc
#define ALAW_CODE_ZALLOC av_psram_zalloc
#define ALAW_CODE_CALLOC av_psram_calloc
#define ALAW_CODE_FREE av_psram_free
#else
#define ALAW_CODE_MALLOC av_malloc
#define ALAW_CODE_ZALLOC av_zalloc
#define ALAW_CODE_CALLOC av_calloc
#define ALAW_CODE_FREE av_free
#endif
#define ALAW_DEBUG(fmt, args...) //os_printf(fmt, ##args)
#define ALAW_INFO os_printf
struct msi *alaw_encode_init(uint32_t samplerate, AUENC_INIT *auenc_init);
struct msi *alaw_decode_init(AUDEC_INIT *audec_init);
#endif

View File

@@ -0,0 +1,427 @@
#include "basic_include.h"
#include "csi_kernel.h"
#include "lib/multimedia/msi.h"
#include "lib/multimedia/framebuff.h"
#include "lib/audio/audio_code/audio_code.h"
#include "autpc_msi/autpc_msi.h"
#include "alaw_code.h"
#define MAX_ALAW_DECODE_RXBUF 4
#define MAX_ALAW_DECODE_TXBUF 4
struct alaw_decode_struct {
AUDIO_TRACK audio_track;
struct fbpool tx_pool;
struct os_event event;
struct msi *msi;
struct msi *src_msi;
struct msi *autpc_msi;
char *msi_name;
void *task_hdl;
uint8_t direct_to_dac;
uint8_t use_tpc;
uint8_t speed;
uint8_t pitch;
uint8_t destroy_self;
uint8_t next_status;
uint8_t current_status;
int16_t dec_buf[960]; //按照16k、60ms的最大长度若超过该长度则需修改数组大小;
};
static void alaw_decode(struct alaw_decode_struct *s)
{
uint8_t clear_finish = 1;
uint8_t *enc_ptr = NULL;
int32_t ret = 0;
int32_t data_len = 0;
int32_t dec_samples = 0;
uint32_t clear_flag = 0;
struct framebuff *recv_frame_buf = NULL;
struct framebuff *send_frame_buf = NULL;
AUCODE_HDL *alaw_dec = NULL;
AUCODE_FRAME_INFO alaw_info;
alaw_dec = audio_coder_open(ALAW_DEC, 8000, 1);
if(!alaw_dec)
return;
while(1) {
os_event_wait(&s->event, coder_clear_event, &clear_flag, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, 0);
if(clear_flag & coder_clear_event) {
clear_flag = 0;
clear_finish = 0;
}
if(s->next_status == AUCODEC_PAUSE) {
if(s->current_status == AUCODEC_RUN) {
msi_output_cmd(s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(s->audio_track)));
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_END_STREAM,(uint32_t)(&(s->audio_track)));
audio_coder_close(alaw_dec);
alaw_dec = audio_coder_open(ALAW_DEC, 8000, 1);
if(!alaw_dec)
return;
}
s->current_status = AUCODEC_PAUSE;
}
recv_frame_buf = msi_get_fb(s->msi, 0);
if(recv_frame_buf) {
if(clear_finish == 0) {
goto alaw_decode_frame_end;
}
if(s->next_status == AUCODEC_PAUSE) {
goto alaw_decode_frame_end;
}
else {
s->current_status = AUCODEC_RUN;
while(!send_frame_buf) {
send_frame_buf = fbpool_get(&s->tx_pool, 0, s->msi);
if(!send_frame_buf)
os_sleep_ms(1);
}
data_len = recv_frame_buf->len;
if(data_len > 0) {
enc_ptr = recv_frame_buf->data;
dec_samples = audio_decode_data(alaw_dec, enc_ptr, data_len, s->dec_buf, &alaw_info);
}
if((dec_samples <= 0) || (data_len <= 0)) {
msi_delete_fb(s->msi, send_frame_buf);
send_frame_buf = NULL;
goto alaw_decode_frame_end;
}
send_frame_buf->data = (uint8_t*)ALAW_CODE_MALLOC(dec_samples*2);
if(!send_frame_buf->data) {
ALAW_INFO("alaw decode malloc send_frame_buf->data fail!\n");
msi_delete_fb(s->msi, send_frame_buf);
send_frame_buf = NULL;
goto alaw_decode_frame_end;
}
os_memcpy(send_frame_buf->data, s->dec_buf, dec_samples*2);
send_frame_buf->len = dec_samples*2;
send_frame_buf->mtype = F_AUDIO;
send_frame_buf->stype = FSTYPE_AUDIO_PCM;
s->audio_track.samplerate = alaw_info.samplerate;
if(s->use_tpc && !s->autpc_msi) {
s->autpc_msi = autpc_msi_init(s->audio_track.samplerate, s->speed, s->pitch, dec_samples, &(s->audio_track));
if(s->autpc_msi == NULL) {
goto alaw_decode_end;
}
if(s->direct_to_dac) {
msi_add_output(s->autpc_msi, NULL, "R_AUDAC");
}
msi_add_output(s->msi, NULL, s->autpc_msi->name);
}
ret = msi_output_fb(s->msi, send_frame_buf);
ALAW_DEBUG("alaw decode send framebuff:%p,ret:%d\r\n",send_frame_buf,ret);
send_frame_buf = NULL;
}
alaw_decode_frame_end:
ALAW_DEBUG("alaw decode delete framebuff:%p,len:%d,\r\n",recv_frame_buf,recv_frame_buf->len);
msi_delete_fb(s->msi, recv_frame_buf);
recv_frame_buf = NULL;
}
else {
if(clear_finish == 0) {
clear_finish = 1;
os_event_set(&s->event, coder_clear_finish_event, NULL);
}
os_sleep_ms(1);
}
if(s->next_status == AUCODEC_EXIT) {
s->current_status = AUCODEC_EXIT;
goto alaw_decode_end;
}
}
alaw_decode_end:
msi_output_cmd(s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(s->audio_track)));
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_END_STREAM,(uint32_t)(&(s->audio_track)));
if(recv_frame_buf) {
msi_delete_fb(NULL, recv_frame_buf);
recv_frame_buf = NULL;
}
if(send_frame_buf) {
msi_delete_fb(s->msi, send_frame_buf);
send_frame_buf = NULL;
}
if(alaw_dec)
audio_coder_close(alaw_dec);
}
static void alaw_decode_thread(void *d)
{
struct alaw_decode_struct *s = (struct alaw_decode_struct *)d;
msi_get(s->msi);
if(s->direct_to_dac) {
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(s->audio_track)));
}
s->msi->enable = 1;
alaw_decode(s);
if(s->direct_to_dac) {
s->audio_track.priority &= 0x3F;
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(s->audio_track)));
}
os_event_set(&s->event, coder_exit_event, NULL);
while((s->next_status != AUCODEC_EXIT) && (s->destroy_self == 0)) {
s->current_status = AUCODEC_END;
os_sleep_ms(5);
}
if(s->src_msi) {
msi_del_output(s->src_msi, NULL, s->msi->name);
s->src_msi = NULL;
}
if(s->next_status != AUCODEC_EXIT)
msi_destroy(s->msi);
msi_put(s->msi);
}
static int32_t alaw_decode_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
{
int32_t ret = RET_OK;
struct alaw_decode_struct *alaw_decode_s = (struct alaw_decode_struct*)(msi->priv);
switch(cmd_id) {
case MSI_CMD_AUCODER:
{
ret = RET_ERR;
if(alaw_decode_s) {
uint32_t cmd_self = (uint32_t)param1;
switch(cmd_self) {
case MSI_AUCODER_PAUSE:
{
if(alaw_decode_s->current_status == AUCODEC_RUN) {
alaw_decode_s->next_status = AUCODEC_PAUSE;
}
ret = RET_OK;
break;
}
case MSI_AUCODER_CONTINUE:
{
if(alaw_decode_s->current_status == AUCODEC_PAUSE) {
alaw_decode_s->next_status = AUCODEC_RUN;
}
ret = RET_OK;
break;
}
case MSI_AUCODER_GET_STATUS:
{
*((uint32_t*)param2) = (uint32_t)(alaw_decode_s->current_status);
ret = RET_OK;
break;
}
case MSI_AUCODER_SET_SPEED:
{
alaw_decode_s->speed = (uint8_t)param2;
ret = msi_output_cmd(alaw_decode_s->msi,MSI_CMD_AUTPC,MSI_AUTPC_SET_SPEED,(uint32_t)(alaw_decode_s->speed));
break;
}
case MSI_AUCODER_GET_SPEED:
{
*((uint32_t*)param2) = (uint32_t)(alaw_decode_s->speed);
ret = RET_OK;
break;
}
case MSI_AUCODER_SET_PITCH:
{
alaw_decode_s->pitch = (uint8_t)param2;
ret = msi_output_cmd(alaw_decode_s->msi,MSI_CMD_AUTPC,MSI_AUTPC_SET_PITCH,(uint32_t)(alaw_decode_s->pitch));
break;
}
case MSI_AUCODER_GET_PITCH:
{
*((uint32_t*)param2) = (uint32_t)(alaw_decode_s->pitch);
ret = RET_OK;
break;
}
case MSI_AUCODER_CLEAR_STREAM:
{
os_event_set(&alaw_decode_s->event, coder_clear_event, NULL);
os_event_wait(&alaw_decode_s->event, coder_clear_finish_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
msi_output_cmd(alaw_decode_s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(alaw_decode_s->audio_track)));
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_CLEAR_STREAM,(uint32_t)(&(alaw_decode_s->audio_track)));
ret = RET_OK;
break;
}
case MSI_AUCODER_SET_SRCMSI:
{
if(alaw_decode_s->src_msi) {
msi_del_output(alaw_decode_s->src_msi, NULL, msi->name);
}
alaw_decode_s->src_msi = NULL;
ret = msi_add_output((struct msi*)param2, NULL, msi->name);
if(ret == RET_OK) {
alaw_decode_s->src_msi = (struct msi*)param2;
}
break;
}
case MSI_AUCODER_DIRECT_TO_DAC:
{
uint32_t direct_to_dac = param2;
if(direct_to_dac && alaw_decode_s->direct_to_dac == 0) {
alaw_decode_s->direct_to_dac = 1;
if(alaw_decode_s->use_tpc == 0) {
msi_add_output(msi, NULL, "R_AUDAC");
}
else if(alaw_decode_s->autpc_msi) {
msi_add_output(alaw_decode_s->autpc_msi, NULL, "R_AUDAC");
}
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(alaw_decode_s->audio_track)));
}
else if(alaw_decode_s->direct_to_dac == 1) {
alaw_decode_s->direct_to_dac = 0;
if(alaw_decode_s->use_tpc == 0) {
msi_del_output(msi, NULL, "R_AUDAC");
}
else if(alaw_decode_s->autpc_msi) {
msi_del_output(alaw_decode_s->autpc_msi, NULL, "R_AUDAC");
}
alaw_decode_s->audio_track.priority &= 0x3F;
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(alaw_decode_s->audio_track)));
}
break;
}
case MSI_AUCODER_DEINIT:
{
msi_destroy(msi);
ret = RET_OK;
break;
}
default:
break;
}
}
break;
}
case MSI_CMD_TRANS_FB:
{
ret = RET_ERR;
struct framebuff *frame_buf = (struct framebuff *)param1;
if(frame_buf->mtype == F_AUDIO) {
ret = RET_OK;
}
break;
}
case MSI_CMD_FREE_FB:
{
ret = RET_ERR;
if(alaw_decode_s) {
struct framebuff *frame_buf = (struct framebuff *)param1;
if(frame_buf->data) {
ALAW_CODE_FREE(frame_buf->data);
frame_buf->data = NULL;
}
fbpool_put(&alaw_decode_s->tx_pool, frame_buf);
}
break;
}
case MSI_CMD_PRE_DESTROY:
{
if(alaw_decode_s && alaw_decode_s->task_hdl) {
alaw_decode_s->next_status = AUCODEC_EXIT;
}
break;
}
case MSI_CMD_POST_DESTROY:
{
if(alaw_decode_s) {
if(alaw_decode_s->task_hdl) {
os_event_wait(&alaw_decode_s->event, coder_exit_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
}
for(uint32_t i=0; i<MAX_ALAW_DECODE_TXBUF; i++) {
struct framebuff *frame_buf = (alaw_decode_s->tx_pool.pool)+i;
if(frame_buf->data) {
ALAW_CODE_FREE(frame_buf->data);
frame_buf->data = NULL;
}
}
fbpool_destroy(&alaw_decode_s->tx_pool);
if(alaw_decode_s->event.hdl) {
os_event_del(&alaw_decode_s->event);
}
if(alaw_decode_s->autpc_msi) {
autpc_msi_deinit(alaw_decode_s->autpc_msi);
alaw_decode_s->autpc_msi = NULL;
}
if(alaw_decode_s->msi_name) {
ALAW_CODE_FREE(alaw_decode_s->msi_name);
alaw_decode_s->msi_name = NULL;
}
ALAW_CODE_FREE(alaw_decode_s);
alaw_decode_s = NULL;
}
break;
}
default:
break;
}
return ret;
}
struct msi *alaw_decode_init(AUDEC_INIT *audec_init)
{
#if AUDIO_EN
char *msi_name = NULL;
msi_name = (char*)ALAW_CODE_ZALLOC(sizeof(char)*32);
if(msi_name == NULL) {
os_printf("alloc autpc msi namefail\n");
return NULL;
}
os_snprintf(msi_name, 20, "SR_ALAW_DECODE_""%04d", (int)(os_jiffies()));
struct msi *msi = msi_new(msi_name, MAX_ALAW_DECODE_RXBUF, NULL);
if(msi == NULL) {
ALAW_INFO("create alaw decode msi fail!\r\n");
return NULL;
}
struct alaw_decode_struct *alaw_decode_s = (struct alaw_decode_struct*)ALAW_CODE_ZALLOC(sizeof(struct alaw_decode_struct));
if(!alaw_decode_s) {
ALAW_INFO("alaw_decode_s malloc fail!\r\n");
goto alaw_decode_init_err;
}
msi->priv = alaw_decode_s;
msi->action = (msi_action)alaw_decode_msi_action;
fbpool_init(&alaw_decode_s->tx_pool, MAX_ALAW_DECODE_TXBUF);
for(uint32_t i=0; i<MAX_ALAW_DECODE_TXBUF; i++) {
struct framebuff *frame_buf = (alaw_decode_s->tx_pool.pool)+i;
frame_buf->data = NULL;
frame_buf->priv = &(alaw_decode_s->audio_track);
}
if(os_event_init(&alaw_decode_s->event) != RET_OK) {
ALAW_INFO("create alaw decode event fail!\r\n");
goto alaw_decode_init_err;
}
if(audec_init->src_msi && (msi_add_output(audec_init->src_msi, NULL, msi->name) != RET_OK)) {
goto alaw_decode_init_err;
}
alaw_decode_s->msi = msi;
alaw_decode_s->msi_name = msi_name;
alaw_decode_s->src_msi = audec_init->src_msi;
alaw_decode_s->direct_to_dac = audec_init->direct_to_dac;
alaw_decode_s->use_tpc = audec_init->use_tpc;
alaw_decode_s->speed = audec_init->speed;
alaw_decode_s->pitch = audec_init->pitch;
alaw_decode_s->destroy_self = audec_init->destroy_self;
alaw_decode_s->audio_track.priority = audec_init->priority;
alaw_decode_s->audio_track.track_type = audec_init->track_type;
alaw_decode_s->next_status = AUCODEC_RUN;
alaw_decode_s->current_status = AUCODEC_RUN;
if(audec_init->direct_to_dac && !alaw_decode_s->use_tpc) {
msi_add_output(msi, NULL, "R_AUDAC");
}
alaw_decode_s->task_hdl = os_task_create("alaw_decode_thread", alaw_decode_thread, (void*)alaw_decode_s, OS_TASK_PRIORITY_ABOVE_NORMAL, 0, NULL, 1024);
if(alaw_decode_s->task_hdl == NULL) {
ALAW_INFO("create opus decode task fail!\r\n");
goto alaw_decode_init_err;
}
return msi;
alaw_decode_init_err:
msi_destroy(msi);
#endif
return NULL;
}

View File

@@ -0,0 +1,319 @@
#include "basic_include.h"
#include "csi_kernel.h"
#include "lib/multimedia/msi.h"
#include "lib/multimedia/framebuff.h"
#include "lib/audio/audio_code/audio_code.h"
#include "alaw_code.h"
#define MAX_ALAW_ENCODE_RXBUF 4
#define MAX_ALAW_ENCODE_TXBUF 4
struct alaw_encode_struct {
struct fbpool tx_pool;
struct os_event event;
struct msi *msi;
struct msi *src_msi;
void *task_hdl;
uint8_t destroy_self;
uint8_t next_status;
uint8_t current_status;
uint8_t enc_buf[1024];
uint32_t samplerate;
AUDIO_INFO audio_info;
};
static void alaw_encode_thread(void *d)
{
uint8_t clear_finish = 1;
uint8_t *send_data = NULL;
int16_t *recv_data = NULL;
int32_t enc_bytes = 0;
int32_t ret = 0;
uint32_t data_len = 0;
uint32_t clear_flag = 0;
struct framebuff *send_frame_buf = NULL;
struct framebuff *recv_frame_buf = NULL;
struct alaw_encode_struct *s = (struct alaw_encode_struct *)d;
AUCODE_HDL *alaw_enc = NULL;
s->msi->enable = 1;
msi_get(s->msi);
alaw_enc = audio_coder_open(ALAW_ENC, s->samplerate, 1);
if (alaw_enc == NULL)
goto alaw_encode_thread_end;
while(1) {
os_event_wait(&s->event, coder_clear_event, &clear_flag, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, 0);
if(clear_flag & coder_clear_event) {
clear_flag = 0;
clear_finish = 0;
}
if(s->next_status == AUCODEC_PAUSE) {
if(s->current_status == AUCODEC_RUN) {
audio_coder_close(alaw_enc);
alaw_enc = audio_coder_open(ALAW_ENC, s->samplerate, 1);
if (alaw_enc == NULL)
goto alaw_encode_thread_end;
}
s->current_status = AUCODEC_PAUSE;
}
recv_frame_buf = msi_get_fb(s->msi, 0);
if(recv_frame_buf) {
if(s->audio_info.nsamples == 0) {
s->audio_info.nsamples = recv_frame_buf->len / 2;
s->audio_info.time_interval = s->audio_info.nsamples * 1000 / s->samplerate;
s->audio_info.samplerate = s->samplerate;
}
if(clear_finish == 0) {
goto alaw_encode_frame_end;
}
if(s->next_status == AUCODEC_PAUSE) {
goto alaw_encode_frame_end;
}
else {
s->current_status = AUCODEC_RUN;
recv_data = (int16_t*)recv_frame_buf->data;
data_len = recv_frame_buf->len;
enc_bytes = audio_encode_data(alaw_enc, (int16_t*)recv_data, data_len/2, s->enc_buf);
send_frame_buf = fbpool_get(&s->tx_pool, 0, s->msi);
if(send_frame_buf) {
send_frame_buf->data = (uint8_t*)ALAW_CODE_MALLOC(enc_bytes);
if(!send_frame_buf->data) {
ALAW_INFO("alaw encode malloc send_frame_buf->data fail!\n");
msi_delete_fb(s->msi, send_frame_buf);
send_frame_buf = NULL;
goto alaw_encode_frame_end;
}
send_data = send_frame_buf->data;
os_memcpy(send_data, s->enc_buf, enc_bytes);
send_frame_buf->len = enc_bytes;
send_frame_buf->mtype = F_AUDIO;
send_frame_buf->time = recv_frame_buf->time;
send_frame_buf->priv = &(s->audio_info);
ret = msi_output_fb(s->msi, send_frame_buf);
ALAW_DEBUG("alaw encode send framebuff:%p,ret:%d\r\n",send_frame_buf,ret);
send_frame_buf = NULL;
}
}
alaw_encode_frame_end:
ALAW_DEBUG("alaw encode delete framebuff:%p,len:%d,\r\n",recv_frame_buf,recv_frame_buf->len);
msi_delete_fb(s->msi, recv_frame_buf);
recv_frame_buf = NULL;
}
else {
if(clear_finish == 0) {
clear_finish = 1;
os_event_set(&s->event, coder_clear_finish_event, NULL);
}
os_sleep_ms(1);
}
if(s->next_status == AUCODEC_EXIT) {
s->current_status = AUCODEC_EXIT;
goto alaw_encode_thread_end;
}
}
alaw_encode_thread_end:
if(alaw_enc)
audio_coder_close(alaw_enc);
os_event_set(&s->event, coder_exit_event, NULL);
while((s->next_status != AUCODEC_EXIT) && (s->destroy_self == 0)) {
s->current_status = AUCODEC_END;
os_sleep_ms(5);
}
if(s->src_msi) {
msi_del_output(s->src_msi, NULL, s->msi->name);
s->src_msi = NULL;
}
if(s->next_status != AUCODEC_EXIT)
msi_destroy(s->msi);
msi_put(s->msi);
}
static int32_t alaw_encode_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
{
int32_t ret = RET_OK;
struct alaw_encode_struct *alaw_encode_s = (struct alaw_encode_struct*)(msi->priv);
switch(cmd_id) {
case MSI_CMD_AUCODER:
{
ret = RET_ERR;
if(alaw_encode_s) {
uint32_t cmd_self = (uint32_t)param1;
switch(cmd_self) {
case MSI_AUCODER_PAUSE:
{
if(alaw_encode_s->current_status == AUCODEC_RUN) {
alaw_encode_s->next_status = AUCODEC_PAUSE;
}
ret = RET_OK;
break;
}
case MSI_AUCODER_CONTINUE:
{
if(alaw_encode_s->current_status == AUCODEC_PAUSE) {
alaw_encode_s->next_status = AUCODEC_RUN;
}
ret = RET_OK;
break;
}
case MSI_AUCODER_GET_STATUS:
{
*((uint32_t*)param2) = (uint32_t)(alaw_encode_s->current_status);
ret = RET_OK;
break;
}
case MSI_AUCODER_CLEAR_STREAM:
{
os_event_set(&alaw_encode_s->event, coder_clear_event, NULL);
os_event_wait(&alaw_encode_s->event, coder_clear_finish_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
ret = RET_OK;
break;
}
case MSI_AUCODER_SET_SRCMSI:
{
if(alaw_encode_s->src_msi) {
msi_del_output(alaw_encode_s->src_msi, NULL, msi->name);
}
alaw_encode_s->src_msi = NULL;
ret = msi_add_output((struct msi*)param2, NULL, msi->name);
if(ret == RET_OK) {
alaw_encode_s->src_msi = (struct msi*)param2;
}
break;
}
case MSI_AUCODER_DEINIT:
{
msi_destroy(msi);
ret = RET_OK;
break;
}
default:
break;
}
}
break;
}
case MSI_CMD_TRANS_FB:
{
ret = RET_ERR;
struct framebuff *frame_buf = (struct framebuff *)param1;
if(frame_buf->mtype == F_AUDIO) {
ret = RET_OK;
}
break;
}
case MSI_CMD_FREE_FB:
{
ret = RET_ERR;
if(alaw_encode_s) {
struct framebuff *frame_buf = (struct framebuff *)param1;
if(frame_buf->data) {
ALAW_CODE_FREE(frame_buf->data);
frame_buf->data = NULL;
}
fbpool_put(&alaw_encode_s->tx_pool, frame_buf);
}
break;
}
case MSI_CMD_PRE_DESTROY:
{
if(alaw_encode_s && alaw_encode_s->task_hdl) {
alaw_encode_s->next_status = AUCODEC_EXIT;
}
break;
}
case MSI_CMD_POST_DESTROY:
{
if(alaw_encode_s) {
if(alaw_encode_s->task_hdl) {
os_event_wait(&alaw_encode_s->event, coder_exit_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
}
for(uint32_t i=0; i<MAX_ALAW_ENCODE_TXBUF; i++) {
struct framebuff *frame_buf = (alaw_encode_s->tx_pool.pool)+i;
if(frame_buf->data) {
ALAW_CODE_FREE(frame_buf->data);
frame_buf->data = NULL;
}
}
fbpool_destroy(&alaw_encode_s->tx_pool);
if(alaw_encode_s->event.hdl) {
os_event_del(&alaw_encode_s->event);
}
ALAW_CODE_FREE(alaw_encode_s);
alaw_encode_s = NULL;
}
break;
}
default:
break;
}
return ret;
}
struct msi *alaw_encode_init(uint32_t samplerate, AUENC_INIT *auenc_init)
{
#if AUDIO_EN
uint8_t msi_isnew = 0;
struct alaw_encode_struct *alaw_encode_s = NULL;
struct msi *msi = msi_new("SR_ALAW_ENCODE", MAX_ALAW_ENCODE_RXBUF, &msi_isnew);
if(msi && !msi_isnew) {
alaw_encode_s = (struct alaw_encode_struct*)(msi->priv);
if(alaw_encode_s) {
if(samplerate != alaw_encode_s->samplerate) {
ALAW_INFO("alaw_encode_init conflict!\r\n");
goto alaw_encode_init_err;
}
}
}
else if(msi && msi_isnew) {
alaw_encode_s = (struct alaw_encode_struct *)ALAW_CODE_ZALLOC(sizeof(struct alaw_encode_struct));
if(!alaw_encode_s) {
ALAW_INFO("alaw_encode_s malloc fail!\r\n");
goto alaw_encode_init_err;
}
msi->priv = alaw_encode_s;
msi->action = (msi_action)alaw_encode_msi_action;
fbpool_init(&alaw_encode_s->tx_pool, MAX_ALAW_ENCODE_TXBUF);
for(uint32_t i=0; i<MAX_ALAW_ENCODE_TXBUF; i++) {
struct framebuff *frame_buf = (alaw_encode_s->tx_pool.pool)+i;
frame_buf->data = NULL;
}
if(os_event_init(&alaw_encode_s->event) != RET_OK) {
ALAW_INFO("create alaw encode event fail!\r\n");
goto alaw_encode_init_err;
}
if(auenc_init->src_msi && (msi_add_output(auenc_init->src_msi, NULL, msi->name) != RET_OK)) {
goto alaw_encode_init_err;
}
alaw_encode_s->msi = msi;
alaw_encode_s->src_msi = auenc_init->src_msi;
alaw_encode_s->samplerate = samplerate;
alaw_encode_s->destroy_self = auenc_init->destroy_self;
alaw_encode_s->next_status = AUCODEC_RUN;
alaw_encode_s->current_status = AUCODEC_RUN;
}
else {
ALAW_INFO("create alaw encode msi fail!\r\n");
return NULL;
}
if(msi_isnew) {
alaw_encode_s->task_hdl = os_task_create("alaw_encode_thread", alaw_encode_thread, (void*)alaw_encode_s, OS_TASK_PRIORITY_ABOVE_NORMAL, 0, NULL, 1024);
if(alaw_encode_s->task_hdl == NULL) {
ALAW_INFO("create alaw encode task fail!\r\n");
goto alaw_encode_init_err;
}
}
return msi;
alaw_encode_init_err:
msi_destroy(msi);
#endif
return NULL;
}

View File

@@ -0,0 +1,466 @@
#include "basic_include.h"
#include "csi_kernel.h"
#include "lib/multimedia/msi.h"
#include "lib/multimedia/framebuff.h"
#include "lib/audio/audio_code/audio_code.h"
#include "autpc_msi/autpc_msi.h"
#include "osal_file.h"
#include "amr_decode.h"
#define BUFF_SIZE 1024
#define MAX_AMR_DECODE_TXBUF 4
#define AMRNB_HEADER "#!AMR\n"
#define AMRWB_HEADER "#!AMR-WB\n"
enum {
AMR_NB = 1,
AMR_WB,
};
struct amr_decode_struct {
AUDIO_TRACK audio_track;
struct fbpool tx_pool;
struct os_event event;
struct msi *msi;
struct msi *autpc_msi;
char *msi_name;
void *task_hdl;
void *amr_fp;
uint8_t loop_mode;
uint8_t direct_to_dac;
uint8_t use_tpc;
uint8_t speed;
uint8_t pitch;
uint8_t destroy_self;
uint8_t amr_type;
uint8_t next_status;
uint8_t current_status;
uint8_t inbuf[BUFF_SIZE];
uint32_t buf_size;
uint32_t buf_offset;
};
static int32_t amr_file_read(struct amr_decode_struct *amr_decode_s, uint8_t *buf, uint32_t size)
{
int32_t read_len = 0;
read_len = osal_fread(buf, size, 1, amr_decode_s->amr_fp);
return read_len;
}
static void amr_decode(struct amr_decode_struct *s)
{
uint8_t endOfRead = 0;
uint8_t *enc_ptr = NULL;
int16_t *data = NULL;
int32_t ret = 0;
int32_t read_len = 0;
int32_t dec_samples = 0;
uint32_t unproc_data_size = 0;
uint32_t enc_ptr_offset = 0;
uint32_t bytes_to_read = 0;
uint32_t interval_time = 0;
struct framebuff *frame_buf = NULL;
AUCODE_HDL *amr_dec = NULL;
AUCODE_FRAME_INFO amr_info;
AUDIO_TRACK *audac_fiter_track = NULL;
while(!s->amr_type) {
read_len = amr_file_read(s, s->inbuf+unproc_data_size,BUFF_SIZE);
if(read_len <= 0) {
AMR_INFO("amr read fail,ret:%d,line:%d!\r\n",read_len,__LINE__);
return;
}
s->buf_size = read_len + unproc_data_size;
if(s->buf_size < os_strlen(AMRWB_HEADER)) {
unproc_data_size = s->buf_size;
os_sleep_ms(1);
continue;
}
if(os_strncmp(s->inbuf, AMRWB_HEADER, os_strlen(AMRWB_HEADER)) == 0) {
s->amr_type = AMR_WB;
s->buf_size -= os_strlen(AMRWB_HEADER);
s->buf_offset = 0;
os_memcpy(s->inbuf, s->inbuf+os_strlen(AMRWB_HEADER), s->buf_size-os_strlen(AMRWB_HEADER));
}
else if(os_strncmp(s->inbuf, AMRNB_HEADER, os_strlen(AMRNB_HEADER)) == 0) {
s->amr_type = AMR_NB;
s->buf_size -= os_strlen(AMRNB_HEADER);
s->buf_offset = 0;
os_memcpy(s->inbuf, s->inbuf+os_strlen(AMRNB_HEADER), s->buf_size-os_strlen(AMRNB_HEADER));
}
else {
AMR_INFO("amr header err!\n");
return;
}
}
unproc_data_size = s->buf_size;
if(s->amr_type == AMR_NB)
amr_dec = audio_coder_open(AMRNB_DEC, 0, 0);
else if(s->amr_type == AMR_WB)
amr_dec = audio_coder_open(AMRWB_DEC, 0, 0);
else {
AMR_INFO("unknow amr type!\r\n");
return;
}
if(!amr_dec)
return;
enc_ptr = s->inbuf;
while(1) {
if(s->next_status == AUCODEC_PAUSE) {
if(s->current_status == AUCODEC_RUN) {
msi_output_cmd(s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(s->audio_track)));
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_END_STREAM,(uint32_t)(&(s->audio_track)));
}
s->current_status = AUCODEC_PAUSE;
while(s->next_status == AUCODEC_PAUSE) {
os_sleep_ms(1);
}
}
if(s->next_status == AUCODEC_EXIT) {
s->current_status = AUCODEC_EXIT;
goto amr_decode_end;
}
s->current_status = AUCODEC_RUN;
if(unproc_data_size < 128 && !endOfRead) {
bytes_to_read = BUFF_SIZE - unproc_data_size;
if(unproc_data_size)
os_memcpy(s->inbuf, enc_ptr+enc_ptr_offset, unproc_data_size);
read_len = amr_file_read(s, s->inbuf+unproc_data_size, bytes_to_read);
if(read_len <= 0) {
AMR_INFO("amr read fail,ret:%d,line:%d!\r\n",read_len,__LINE__);
endOfRead = 1;
}
else
unproc_data_size += read_len;
enc_ptr = s->inbuf;
enc_ptr_offset = 0;
}
if(unproc_data_size > 0) {
while(!frame_buf) {
frame_buf = fbpool_get(&s->tx_pool, 0, s->msi);
if(!frame_buf)
os_sleep_ms(1);
}
data = (int16_t*)frame_buf->data;
dec_samples = audio_decode_data(amr_dec, enc_ptr+enc_ptr_offset, unproc_data_size, data, &amr_info);
if(dec_samples <= 0) {
enc_ptr_offset += 1;
unproc_data_size -= 1;
msi_delete_fb(s->msi, frame_buf);;
frame_buf = NULL;
continue;
}
enc_ptr_offset += amr_info.frame_bytes;
unproc_data_size -= amr_info.frame_bytes;
frame_buf->len = dec_samples*2;
frame_buf->mtype = F_AUDIO;
frame_buf->stype = FSTYPE_AUDIO_PCM;
s->audio_track.samplerate = amr_info.samplerate;
ret = msi_output_fb(s->msi, frame_buf);
if(s->use_tpc && !s->autpc_msi) {
s->autpc_msi = autpc_msi_init(s->audio_track.samplerate, s->speed, s->pitch, dec_samples, &(s->audio_track));
if(s->autpc_msi == NULL) {
goto amr_decode_end;
}
msi_add_output(s->msi, NULL, s->autpc_msi->name);
if(s->direct_to_dac) {
msi_add_output(s->autpc_msi, NULL, "R_AUDAC");
}
}
AMR_DEBUG("amr decode send framebuff:%p,ret:%d\r\n",frame_buf,ret);
msi_cmd("R_AUDAC", MSI_CMD_AUDAC, MSI_AUDAC_GET_FILTER_TRACK, (uint32_t)(&audac_fiter_track));
if(s->direct_to_dac && (!s->use_tpc) && (audac_fiter_track != (&(s->audio_track)))) {
interval_time = (frame_buf->len>>1)*1000/(amr_info.samplerate);
os_sleep_ms(interval_time);
}
frame_buf = NULL;
}
else if(endOfRead) {
goto amr_decode_end;
}
}
amr_decode_end:
msi_output_cmd(s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(s->audio_track)));
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_END_STREAM,(uint32_t)(&(s->audio_track)));
if(frame_buf) {
msi_delete_fb(s->msi, frame_buf);
frame_buf = NULL;
}
if(amr_dec)
audio_coder_close(amr_dec);
}
static void amr_decode_thread(void *d)
{
struct amr_decode_struct *s = (struct amr_decode_struct *)d;
msi_get(s->msi);
if(s->direct_to_dac) {
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(s->audio_track)));
}
s->msi->enable = 1;
do {
osal_fseek(s->amr_fp, 0);
amr_decode(s);
if(s->current_status == AUCODEC_EXIT) {
break;
}
}while(s->loop_mode);
if(s->direct_to_dac) {
s->audio_track.priority &= 0x3F;
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(s->audio_track)));
}
os_event_set(&s->event, coder_exit_event, NULL);
while((s->next_status != AUCODEC_EXIT) && (s->destroy_self == 0)) {
s->current_status = AUCODEC_END;
os_sleep_ms(5);
}
if(s->next_status != AUCODEC_EXIT)
msi_destroy(s->msi);
msi_put(s->msi);
}
static int32_t amr_decode_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
{
int32_t ret = RET_OK;
struct amr_decode_struct *amr_decode_s = (struct amr_decode_struct*)(msi->priv);
switch(cmd_id) {
case MSI_CMD_AUCODER:
{
ret = RET_ERR;
if(amr_decode_s) {
uint32_t cmd_self = (uint32_t)param1;
switch(cmd_self) {
case MSI_AUCODER_PAUSE:
{
if(amr_decode_s->current_status == AUCODEC_RUN) {
amr_decode_s->next_status = AUCODEC_PAUSE;
}
ret = RET_OK;
break;
}
case MSI_AUCODER_CONTINUE:
{
if(amr_decode_s->current_status == AUCODEC_PAUSE) {
amr_decode_s->next_status = AUCODEC_RUN;
}
ret = RET_OK;
break;
}
case MSI_AUCODER_GET_STATUS:
{
*((uint32_t*)param2) = (uint32_t)(amr_decode_s->current_status);
ret = RET_OK;
break;
}
case MSI_AUCODER_SET_SPEED:
{
amr_decode_s->speed = (uint8_t)param2;
ret = msi_output_cmd(amr_decode_s->msi,MSI_CMD_AUTPC,MSI_AUTPC_SET_SPEED,(uint32_t)(amr_decode_s->speed));
break;
}
case MSI_AUCODER_GET_SPEED:
{
*((uint32_t*)param2) = (uint32_t)(amr_decode_s->speed);
ret = RET_OK;
break;
}
case MSI_AUCODER_SET_PITCH:
{
amr_decode_s->pitch = (uint8_t)param2;
ret = msi_output_cmd(amr_decode_s->msi,MSI_CMD_AUTPC,MSI_AUTPC_SET_PITCH,(uint32_t)(amr_decode_s->pitch));
break;
}
case MSI_AUCODER_GET_PITCH:
{
*((uint32_t*)param2) = (uint32_t)(amr_decode_s->pitch);
ret = RET_OK;
break;
}
case MSI_AUCODER_CLEAR_STREAM:
{
ret = RET_OK;
break;
}
case MSI_AUCODER_DIRECT_TO_DAC:
{
uint32_t direct_to_dac = param2;
if(direct_to_dac && amr_decode_s->direct_to_dac == 0) {
amr_decode_s->direct_to_dac = 1;
if(amr_decode_s->use_tpc == 0) {
msi_add_output(msi, NULL, "R_AUDAC");
}
else if(amr_decode_s->autpc_msi) {
msi_add_output(amr_decode_s->autpc_msi, NULL, "R_AUDAC");
}
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(amr_decode_s->audio_track)));
}
else if(amr_decode_s->direct_to_dac == 1) {
amr_decode_s->direct_to_dac = 0;
if(amr_decode_s->use_tpc == 0) {
msi_del_output(msi, NULL, "R_AUDAC");
}
else if(amr_decode_s->autpc_msi) {
msi_del_output(amr_decode_s->autpc_msi, NULL, "R_AUDAC");
}
amr_decode_s->audio_track.priority &= 0x3F;
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(amr_decode_s->audio_track)));
}
break;
}
case MSI_AUCODER_DEINIT:
{
msi_destroy(msi);
ret = RET_OK;
break;
}
default:
break;
}
}
break;
}
case MSI_CMD_FREE_FB:
{
ret = RET_ERR;
if(amr_decode_s) {
struct framebuff *frame_buf = (struct framebuff *)param1;
fbpool_put(&amr_decode_s->tx_pool, frame_buf);
}
break;
}
case MSI_CMD_PRE_DESTROY:
{
if(amr_decode_s && amr_decode_s->task_hdl) {
amr_decode_s->next_status = AUCODEC_EXIT;
}
break;
}
case MSI_CMD_POST_DESTROY:
{
if(amr_decode_s) {
if(amr_decode_s->task_hdl) {
os_event_wait(&amr_decode_s->event, coder_exit_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
}
for(uint32_t i=0; i<MAX_AMR_DECODE_TXBUF; i++) {
struct framebuff *frame_buf = (amr_decode_s->tx_pool.pool)+i;
if(frame_buf->data) {
AMR_DECODE_FREE(frame_buf->data);
frame_buf->data = NULL;
}
}
fbpool_destroy(&amr_decode_s->tx_pool);
if(amr_decode_s->event.hdl) {
os_event_del(&amr_decode_s->event);
}
if(amr_decode_s->amr_fp) {
osal_fclose(amr_decode_s->amr_fp);
amr_decode_s->amr_fp = NULL;
}
if(amr_decode_s->autpc_msi) {
autpc_msi_deinit(amr_decode_s->autpc_msi);
amr_decode_s->autpc_msi = NULL;
}
if(amr_decode_s->msi_name) {
AMR_DECODE_FREE(amr_decode_s->msi_name);
amr_decode_s->msi_name = NULL;
}
AMR_DECODE_FREE(amr_decode_s);
amr_decode_s = NULL;
}
break;
}
default:
break;
}
return ret;
}
struct msi *amr_decode_init(char *filename, uint8_t loop_mode, AUDEC_INIT *audec_init)
{
#if AUDIO_EN
char *msi_name = NULL;
msi_name = (char*)AMR_DECODE_ZALLOC(sizeof(char)*32);
if(msi_name == NULL) {
os_printf("alloc autpc msi namefail\n");
return NULL;
}
os_snprintf(msi_name, 20, "SR_AMR_DECODE_""%04d", (int)(os_jiffies()));
struct msi *msi = msi_new(msi_name, 0, NULL);
if(msi == NULL) {
AMR_INFO("create amr decode msi fail!\r\n");
return NULL;
}
struct amr_decode_struct *amr_decode_s = (struct amr_decode_struct*)AMR_DECODE_ZALLOC(sizeof(struct amr_decode_struct));
if(!amr_decode_s) {
AMR_INFO("amr_decode_s malloc fail!\r\n");
goto amr_decode_init_err;
}
msi->priv = amr_decode_s;
msi->action = (msi_action)amr_decode_msi_action;
fbpool_init(&amr_decode_s->tx_pool, MAX_AMR_DECODE_TXBUF);
for(uint32_t i=0; i<MAX_AMR_DECODE_TXBUF; i++) {
struct framebuff *frame_buf = (amr_decode_s->tx_pool.pool)+i;
frame_buf->data = (uint8_t*)AMR_DECODE_MALLOC(320 * sizeof(int16_t));
if(frame_buf->data == NULL) {
AMR_INFO("amr decode malloc framebuff data fail!\r\n");
goto amr_decode_init_err;
}
frame_buf->priv = &(amr_decode_s->audio_track);;
}
if(filename) {
amr_decode_s->amr_fp = osal_fopen((const char*)filename, "rb");
if(amr_decode_s->amr_fp == NULL) {
AMR_INFO("open amr file %s fail!\r\n", filename);
goto amr_decode_init_err;
}
}
else {
AMR_INFO("arm filename is null!\r\n");
goto amr_decode_init_err;
}
if(os_event_init(&amr_decode_s->event) != RET_OK) {
AMR_INFO("create amr decode event fail!\r\n");
goto amr_decode_init_err;
}
amr_decode_s->msi = msi;
amr_decode_s->msi_name = msi_name;
amr_decode_s->loop_mode = loop_mode;
amr_decode_s->direct_to_dac = audec_init->direct_to_dac;
amr_decode_s->use_tpc = audec_init->use_tpc;
amr_decode_s->speed = audec_init->speed;
amr_decode_s->pitch = audec_init->pitch;
amr_decode_s->destroy_self = audec_init->destroy_self;
amr_decode_s->audio_track.priority = audec_init->priority;
amr_decode_s->audio_track.track_type = audec_init->track_type;
amr_decode_s->next_status = AUCODEC_RUN;
amr_decode_s->current_status = AUCODEC_RUN;
if(audec_init->direct_to_dac && !amr_decode_s->use_tpc) {
msi_add_output(msi, NULL, "R_AUDAC");
}
#if AMRNB_DEC_CTRL == AUCODER_RUN_IN_CPU1
amr_decode_s->task_hdl = os_task_create("amr_decode_thread", amr_decode_thread, (void*)amr_decode_s, OS_TASK_PRIORITY_ABOVE_NORMAL, 0, NULL, 1024);
#else
amr_decode_s->task_hdl = os_task_create("amr_decode_thread", amr_decode_thread, (void*)amr_decode_s, OS_TASK_PRIORITY_NORMAL, 0, NULL, 4096);
#endif
if(amr_decode_s->task_hdl == NULL) {
AMR_INFO("create amr decode task fail!\r\n");
goto amr_decode_init_err;
}
return msi;
amr_decode_init_err:
msi_destroy(msi);
#endif
return NULL;
}

View File

@@ -0,0 +1,24 @@
#ifndef _AMR__DECODE_MSI_H_
#define _AMR__DECODE_MSI_H_
#include "basic_include.h"
#include "lib/heap/av_heap.h"
#include "lib/heap/av_psram_heap.h"
#include "audio_code_ctrl.h"
#ifdef PSRAM_HEAP
#define AMR_DECODE_MALLOC av_psram_malloc
#define AMR_DECODE_ZALLOC av_psram_zalloc
#define AMR_DECODE_FREE av_psram_free
#else
#define AMR_DECODE_MALLOC av_malloc
#define AMR_DECODE_ZALLOC av_zalloc
#define AMR_DECODE_FREE av_free
#endif
#define AMR_DEBUG(fmt, args...) //os_printf(fmt, ##args)
#define AMR_INFO os_printf
struct msi *amr_decode_init(char *filename, uint8_t loop_mode, AUDEC_INIT *audec_init);
#endif

View File

@@ -0,0 +1,130 @@
#include "basic_include.h"
#include "audio_code_ctrl.h"
#include "aac_code.h"
#include "alaw_code.h"
#include "amr_decode.h"
#include "mp3_decode.h"
#include "opus_code.h"
#include "wave_code.h"
struct msi *audio_encode_init(uint32_t coder, uint32_t samplerate, AUENC_INIT *auenc_init)
{
struct msi *msi = NULL;
switch(coder) {
case AAC_ENC:
msi = aac_encode_init(NULL, samplerate, 0, auenc_init);
break;
case ALAW_ENC:
msi = alaw_encode_init(samplerate, auenc_init);
break;
case OPUS_ENC:
msi = opus_encode_init(samplerate, auenc_init);
break;
default:
break;
}
return msi;
}
struct msi *audio_decode_init(uint32_t coder, uint32_t samplerate, AUDEC_INIT *audec_init)
{
struct msi *msi = NULL;
switch(coder) {
case AAC_DEC:
msi = aac_decode_init(NULL, 0, audec_init);
break;
case ALAW_DEC:
msi = alaw_decode_init(audec_init);
break;
case AMRNB_DEC:
case AMRWB_DEC:
msi = amr_decode_init(NULL, 0, audec_init);
break;
case MP3_DEC:
msi = mp3_decode_init(NULL, 0, audec_init);
break;
case OPUS_DEC:
msi = opus_decode_init(samplerate, audec_init);
break;
default:
break;
}
return msi;
}
int32_t audio_code_set_src_msi(struct msi *msi, struct msi *src_msi)
{
int32_t ret = RET_ERR;
ret = msi_do_cmd(msi, MSI_CMD_AUCODER, MSI_AUCODER_SET_SRCMSI, (uint32_t)src_msi);
return ret;
}
int32_t audio_encode_deinit(struct msi *msi)
{
int32_t ret = RET_ERR;
ret = msi_do_cmd(msi, MSI_CMD_AUCODER, MSI_AUCODER_DEINIT, 0);
return ret;
}
int32_t audio_decode_deinit(struct msi *msi)
{
int32_t ret = RET_ERR;
ret = msi_do_cmd(msi, MSI_CMD_AUCODER, MSI_AUCODER_DEINIT, 0);
return ret;
}
int32_t audio_encode_set_bitrate(struct msi *msi, uint32_t bitrate)
{
int32_t ret = RET_ERR;
ret = msi_do_cmd(msi, MSI_CMD_AUCODER, MSI_AUCODER_SET_BITRATE, bitrate);
return ret;
}
int32_t audio_code_continue(struct msi *msi)
{
int32_t ret = RET_ERR;
ret = msi_do_cmd(msi, MSI_CMD_AUCODER, MSI_AUCODER_CONTINUE, 0);
return ret;
}
int32_t audio_code_pause(struct msi *msi)
{
int32_t ret = RET_ERR;
ret = msi_do_cmd(msi, MSI_CMD_AUCODER, MSI_AUCODER_PAUSE, 0);
return ret;
}
int32_t audio_code_clear(struct msi *msi)
{
int32_t ret = RET_ERR;
ret = msi_do_cmd(msi, MSI_CMD_AUCODER, MSI_AUCODER_CLEAR_STREAM, 0);
return ret;
}
int32_t audio_code_add_output(struct msi *msi, const char *msi_name)
{
int32_t ret = RET_ERR;
ret = msi_add_output(msi, NULL, msi_name);
return ret;
}
int32_t audio_code_del_output(struct msi *msi, const char *msi_name)
{
int32_t ret = RET_ERR;
ret = msi_del_output(msi, NULL, msi_name);
return ret;
}
int32_t audio_code_direct_to_dac(struct msi *msi, uint32_t direct_to_dac)
{
int32_t ret = RET_ERR;
ret = msi_do_cmd(msi, MSI_CMD_AUCODER, MSI_AUCODER_DIRECT_TO_DAC, direct_to_dac);
return ret;
}
int32_t audio_code_get_status(struct msi *msi)
{
int32_t ret = RET_ERR;
msi_do_cmd(msi, MSI_CMD_AUCODER, MSI_AUCODER_GET_STATUS, (uint32_t)(&ret));
return ret;
}

View File

@@ -0,0 +1,85 @@
#ifndef _AUDIO_CODER_CTRL_H_
#define _AUDIO_CODER_CTRL_H_
#include "basic_include.h"
#include "lib/audio/audio_code/audio_code.h"
#include "lib/multimedia/msi.h"
#include "lib/multimedia/framebuff.h"
#define PACKET_LOSS_CONCEALMENT -1
#define OUTPUT_MUTE_DATA -2
#define DECODE_ADD_FADE_IN -3
#define DECODE_ADD_FADE_OUT -4
typedef struct {
int32_t decode_operation;
} AUDECODER_OPERATION;
typedef struct {
uint16_t nsamples;
uint16_t time_interval;
uint32_t samplerate;
} AUDIO_INFO;
typedef struct {
uint8_t track_type;
uint8_t priority;
uint32_t samplerate;
} AUDIO_TRACK;
typedef struct {
struct msi *src_msi;
uint8_t destroy_self;
} AUENC_INIT;
typedef struct {
struct msi *src_msi;
uint8_t track_type;
uint8_t priority;
uint8_t direct_to_dac;
uint8_t use_tpc;
uint8_t speed;
uint8_t pitch;
uint8_t destroy_self;
} AUDEC_INIT;
enum {
CALL_TRACK = 1,
MEDIA_TRACK,
BELL_TRACK,
};
enum {
AUCODEC_RUN,
AUCODEC_PAUSE,
AUCODEC_END,
AUCODEC_EXIT,
};
enum {
coder_clear_event = BIT(0),
coder_clear_finish_event = BIT(1),
coder_exit_event = BIT(2),
};
enum {
play_disabled = 0x00,
play_interruptible = 0x40,
play_nonInterruptible = 0x80,
};
struct msi *audio_encode_init(uint32_t coder, uint32_t samplerate, AUENC_INIT *auenc_init);
struct msi *audio_decode_init(uint32_t coder, uint32_t samplerate, AUDEC_INIT *audec_init);
int32_t audio_code_set_src_msi(struct msi *msi, struct msi *src_msi);
int32_t audio_encode_deinit(struct msi *msi);
int32_t audio_decode_deinit(struct msi *msi);
int32_t audio_encode_set_bitrate(struct msi *msi, uint32_t bitrate);
int32_t audio_code_continue(struct msi *msi);
int32_t audio_code_pause(struct msi *msi);
int32_t audio_code_clear(struct msi *msi);
int32_t audio_code_add_output(struct msi *msi, const char *msi_name);
int32_t audio_code_del_output(struct msi *msi, const char *msi_name);
int32_t audio_code_direct_to_dac(struct msi *msi, uint32_t direct_to_dac);
int32_t audio_code_get_status(struct msi *msi);
#endif

View File

@@ -0,0 +1,278 @@
#include "basic_include.h"
#include "csi_kernel.h"
#include "fatfs/osal_file.h"
#include "audio_media_ctrl.h"
#include "audio_msi/audio_adc.h"
#include "lib/heap/av_heap.h"
#include "lib/heap/av_psram_heap.h"
#include "aac/aac_code.h"
#include "amr/amr_decode.h"
#include "mp3/mp3_decode.h"
#include "wave/wave_code.h"
#define RECORD_DIR "0:/audio"
#define MAX(a, b) ((a) > (b) ? a : b)
struct audio_record_struct {
char filename[30];
uint8_t record_format;
int32_t record_time; //seconds
uint8_t is_running;
uint32_t sampleRate;
struct msi *msi;
};
static struct audio_record_struct *audio_record_s = NULL;
static char *get_file_extension(char *filename) {
char *dot = os_strrchr((const char*)filename, '.');
if (!dot || dot == filename) {
return filename;
}
return dot + 1;
}
static uint32_t a2i(char *str)
{
uint32_t ret = 0;
uint32_t indx = 0;
char str_buf[32];
memset(str_buf, 0, 32);
while (str[indx] != '\0')
{
if (str[indx] == '.')
break;
str_buf[indx] = str[indx];
indx++;
}
indx = 0;
while (str_buf[indx] != '\0')
{
if (str_buf[indx] >= '0' && str_buf[indx] <= '9')
{
ret = ret * 10 + str_buf[indx] - '0';
}
indx++;
}
return ret;
}
static void creat_audio_filename(char *dir_name)
{
DIR dir;
FRESULT ret;
FILINFO finfo;
int indx = 0;
ret = f_opendir(&dir, dir_name);
if (ret != FR_OK)
{
f_mkdir(dir_name);
f_opendir(&dir, dir_name);
}
while (1)
{
ret = f_readdir(&dir, &finfo);
if (ret != FR_OK || finfo.fname[0] == 0)
break;
indx = MAX(indx, a2i(finfo.fname));
}
f_closedir(&dir);
indx++;
#if DEFAULT_RECORD_FORMAT == RECORD_AAC
os_sprintf((char*)(audio_record_s->filename), "%s/a%d.%s", dir_name, indx, "aac");
#else
os_sprintf((char*)(audio_record_s->filename), "%s/a%d.%s", dir_name, indx, "wav");
#endif
}
static void audio_file_record_thread(void *d)
{
uint8_t status = AUCODEC_EXIT;
uint32_t count = 0;
uint32_t start_time = 0;
AUENC_INIT auenc_init;
auenc_init.destroy_self = 0;
auenc_init.src_msi = get_auadc_msi(AUSYS_AUAD);
os_printf("start record file:%s\n",audio_record_s->filename);
if(audio_record_s->record_format == WAV) {
audio_record_s->msi = wave_encode_init(audio_record_s->filename, audio_record_s->sampleRate, &auenc_init);
}
else if(audio_record_s->record_format == AAC) {
audio_record_s->msi = aac_encode_init(audio_record_s->filename, audio_record_s->sampleRate, 1, &auenc_init);
}
if(audio_record_s->msi == NULL) {
os_printf("audio encode init err!\r\n");
goto audio_record_thread_end;
}
start_time = os_jiffies();
while(audio_record_s->is_running && (audio_record_s->record_time < 0 ||
(os_jiffies()-start_time)/1000 < audio_record_s->record_time)) {
status = AUCODEC_END;
msi_do_cmd(audio_record_s->msi, MSI_CMD_AUCODER, MSI_AUCODER_GET_STATUS, (uint32_t)(&status));
if(status == AUCODEC_END) {
os_printf("record err!\r\n");
goto audio_record_thread_end;
}
count++;
if(count % 1000 == 0)
{
os_printf("%s\t\trecord time:%d\r\n",__FUNCTION__,os_jiffies()-start_time);
}
os_sleep_ms(1);
}
audio_record_thread_end:
msi_do_cmd(audio_record_s->msi, MSI_CMD_AUCODER, MSI_AUCODER_DEINIT, 1);
av_free(audio_record_s);
audio_record_s = NULL;
os_printf("audio record thread end!\r\n");
}
int32_t audio_file_record_pause(void)
{
int32_t ret = RET_ERR;
if(audio_record_s && audio_record_s->is_running) {
ret = msi_do_cmd(audio_record_s->msi, MSI_CMD_AUCODER, MSI_AUCODER_PAUSE, 0);
}
return ret;
}
int32_t audio_file_record_continue(void)
{
int32_t ret = RET_ERR;
if(audio_record_s && audio_record_s->is_running) {
ret = msi_do_cmd(audio_record_s->msi, MSI_CMD_AUCODER, MSI_AUCODER_CONTINUE, 0);
}
return ret;
}
int32_t audio_file_record_stop(void)
{
uint32_t count = 0;
if(audio_record_s) {
audio_record_s->is_running = 0;
while(audio_record_s && ((++count) < 1000))
os_sleep_ms(1);
return RET_OK;
}
return RET_ERR;
}
int32_t audio_file_record_status(struct msi *msi)
{
int32_t ret = RET_ERR;
if(audio_record_s && audio_record_s->is_running) {
msi_do_cmd(audio_record_s->msi, MSI_CMD_AUCODER, MSI_AUCODER_GET_STATUS, (uint32_t)(&ret));
}
return ret;
}
int32_t audio_file_record_init(char *filename, uint32_t sampleRate, int32_t record_time)
{
uint8_t *file_extension = NULL;
if(audio_record_s) {
os_printf("%s err,already recording!\r\n", __FUNCTION__);
return RET_ERR;
}
else {
audio_record_s = (struct audio_record_struct *)av_zalloc(sizeof(struct audio_record_struct));
if(!audio_record_s) {
os_printf("malloc audio_record_s fail!\r\n");
return RET_ERR;
}
}
os_memset(audio_record_s->filename, 0, sizeof(audio_record_struct));
if(filename) {
file_extension = (uint8_t*)get_file_extension((char*)filename);
if((os_strncmp(file_extension, "wav", 3)==0) || (os_strncmp(file_extension, "WAV", 3)==0)) {
audio_record_s->record_format = WAV;
}
else if((os_strncmp(file_extension, "aac", 3)==0) || (os_strncmp(file_extension, "AAC", 3)==0)) {
audio_record_s->record_format = AAC;
}
else {
os_printf("Unsupported audio record format!\r\n");
av_free(audio_record_s);
audio_record_s = NULL;
return RET_ERR;
}
os_memcpy(audio_record_s->filename, filename, os_strlen(filename));
}
else {
#if DEFAULT_RECORD_FORMAT == RECORD_AAC
audio_record_s->record_format = AAC;
creat_audio_filename(RECORD_DIR);
#else
audio_record_s->record_format = WAV;
creat_audio_filename(RECORD_DIR);
#endif
}
audio_record_s->sampleRate = sampleRate;
audio_record_s->record_time = record_time;
audio_record_s->is_running = 1;
os_task_create("audio_file_record_thread", audio_file_record_thread, audio_record_s, OS_TASK_PRIORITY_NORMAL, 0, NULL, 1024);
return RET_OK;
}
int32_t audio_file_play_pause(struct msi *msi)
{
int32_t ret = RET_ERR;
ret = msi_do_cmd(msi, MSI_CMD_AUCODER, MSI_AUCODER_PAUSE, 0);
return ret;
}
int32_t audio_file_play_continue(struct msi *msi)
{
int32_t ret = RET_ERR;
ret = msi_do_cmd(msi, MSI_CMD_AUCODER, MSI_AUCODER_CONTINUE, 0);
return ret;
}
int32_t audio_file_play_stop(struct msi *msi)
{
int32_t ret = RET_ERR;
ret = msi_do_cmd(msi, MSI_CMD_AUCODER, MSI_AUCODER_DEINIT, 0);
return ret;
}
int32_t audio_file_play_status(struct msi *msi)
{
int32_t ret = RET_ERR;
msi_do_cmd(msi, MSI_CMD_AUCODER, MSI_AUCODER_GET_STATUS, (uint32_t)(&ret));
return ret;
}
struct msi *audio_file_play_init(char *filename, uint8_t play_mode, AUDEC_INIT *audec_init)
{
uint8_t *file_extension = NULL;
uint8_t audio_format = 0;
struct msi *msi = NULL;
if(filename) {
file_extension = (uint8_t*)get_file_extension((char*)filename);
if((os_strncmp(file_extension, "wav", 3)==0) || (os_strncmp(file_extension, "WAV", 3)==0))
audio_format = WAV;
else if((os_strncmp(file_extension, "mp3", 3)==0) || (os_strncmp(file_extension, "MP3", 3)==0))
audio_format = MP3;
else if((os_strncmp(file_extension, "amr", 3)==0) || (os_strncmp(file_extension, "AMR", 3)==0))
audio_format = AMR;
else if((os_strncmp(file_extension, "aac", 3)==0) || (os_strncmp(file_extension, "AAC", 3)==0))
audio_format = AAC;
else {
return NULL;
}
}
else {
os_printf("enter audio filename\n");
return NULL;
}
switch(audio_format) {
case WAV:msi = wave_decode_init(filename, (play_mode==2), audec_init);break;
case MP3:msi = mp3_decode_init(filename, (play_mode==2), audec_init);break;
case AMR:msi = amr_decode_init(filename, (play_mode==2), audec_init);break;
case AAC:msi = aac_decode_init(filename, (play_mode==2), audec_init);break;
default:break;
}
return msi;
}

View File

@@ -0,0 +1,43 @@
#ifndef _AUDIO_MEDIA_CTRL_H_
#define _AUDIO_MEDIA_CTRL_H_
#include "basic_include.h"
#include "audio_code_ctrl.h"
enum {
WAV = 1,
MP3,
AMR,
AAC,
};
enum {
NORMAL_PLAY = 1,
LOOP_PLAY,
};
#define RECORD_WAV 1
#define RECORD_AAC 2
#define DEFAULT_RECORD_FORMAT RECORD_AAC
typedef struct {
uint8_t filename[30];
uint8_t record_format;
uint8_t is_running;
int32_t record_time; //seconds
uint32_t sampleRate;
} audio_record_struct;
int32_t audio_file_record_pause(void);
int32_t audio_file_record_continue(void);
int32_t audio_file_record_stop(void);
int32_t audio_file_record_status(struct msi *msi);
int32_t audio_file_record_init(char *filename, uint32_t sampleRate, int32_t record_time);
int32_t audio_file_play_pause(struct msi *msi);
int32_t audio_file_play_continue(struct msi *msi);
int32_t audio_file_play_stop(struct msi *msi);
int32_t audio_file_play_status(struct msi *msi);
struct msi *audio_file_play_init(char *filename, uint8_t play_mode, AUDEC_INIT *audec_init);
#endif

View File

@@ -0,0 +1,768 @@
#include "basic_include.h"
#include "csi_kernel.h"
#include "lib/multimedia/msi.h"
#include "lib/multimedia/framebuff.h"
#include "lib/audio/audio_code/audio_code.h"
#include "autpc_msi/autpc_msi.h"
#include "osal_file.h"
#include "mp3_decode.h"
#include "mp3_getInfo.h"
#define BUFF_SIZE 2048
#define MAX_MP3_DECODE_RXBUF 4
#define MAX_MP3_DECODE_TXBUF 8
struct mp3_decode_struct {
AUDIO_TRACK audio_track;
struct fbpool tx_pool;
struct os_event event;
struct msi *msi;
struct msi *src_msi;
struct msi *autpc_msi;
char *msi_name;
void *task_hdl;
void *mp3_fp;
uint8_t mp3_filename[20];
uint8_t loop_mode;
uint8_t direct_to_dac;
uint8_t use_tpc;
uint8_t speed;
uint8_t pitch;
uint8_t destroy_self;
uint8_t get_first_frame;
uint8_t next_status;
uint8_t current_status;
uint8_t inbuf[BUFF_SIZE];
int16_t dec_buf[1152*2];
uint32_t file_size;
uint32_t buf_offset;
uint32_t buf_size;
CUR_MP3_INFO *cur_mp3_info;
};
static int32_t mp3_file_read(struct mp3_decode_struct *mp3_decode_s, uint8_t *buf, uint32_t size)
{
int32_t read_len = 0;
read_len = osal_fread(buf, size, 1, mp3_decode_s->mp3_fp);
return read_len;
}
static void mp3_file_decode(struct mp3_decode_struct *s)
{
uint8_t endOfRead = 0;
uint8_t *enc_ptr = NULL;
int16_t *data = NULL;
int32_t ret = 0;
int32_t dec_samples = 0;
int32_t read_len = 0;
int32_t unproc_data_size = 0;
int32_t ID3V2_offset = 0;
uint32_t ID3V2_len = 0;
uint32_t enc_ptr_offset = 0;
uint32_t bytes_to_read = 0;
uint32_t interval_time = 0;
struct framebuff *frame_buf = NULL;
AUCODE_HDL *mp3_dec = NULL;
AUCODE_FRAME_INFO mp3_info;
AUDIO_TRACK *audac_fiter_track = NULL;
while(!s->get_first_frame) {
bytes_to_read = BUFF_SIZE - unproc_data_size;
read_len = mp3_file_read(s, s->inbuf+unproc_data_size,bytes_to_read);
if(read_len <= 0) {
MP3_INFO("mp3 read fail,ret:%d,line:%d!\r\n",read_len,__LINE__);
goto mp3_decode_end;
}
s->buf_size = read_len + unproc_data_size;
if(os_strncmp(s->inbuf, "ID3", 3) == 0) {
if (s->buf_size < 10) {
unproc_data_size = s->buf_size;
os_sleep_ms(1);
continue;
}
ID3V2_len = (s->inbuf[6]&0x7F)*0x200000+ (s->inbuf[7]&0x7F)*0x4000 +
(s->inbuf[8]&0x7F)*0x80 +(s->inbuf[9]&0x7F);
ID3V2_offset = (ID3V2_len+10);
while(ID3V2_offset >= s->buf_size) {
os_sleep_ms(1);
ID3V2_offset -= s->buf_size;
read_len = mp3_file_read(s, s->inbuf,BUFF_SIZE);
if(read_len <= 0) {
MP3_INFO("mp3 read fail,ret:%d,line:%d!\r\n",read_len,__LINE__);
goto mp3_decode_end;
}
s->buf_size = read_len;
}
if(ID3V2_offset) {
s->buf_size -= ID3V2_offset;
os_memcpy(s->inbuf, s->inbuf+ID3V2_offset, s->buf_size);
}
if(s->buf_size <= 1) {
os_sleep_ms(1);
unproc_data_size = s->buf_size;
continue;
}
}
for(uint32_t i=0; i<(s->buf_size-1); i++) {
if( ( (s->inbuf[i] << 8) | (s->inbuf[i+1] & 0xE0) ) == 0xFFE0 ) {
s->get_first_frame = 1;
unproc_data_size = s->buf_size - i;
break;
}
}
if(!s->get_first_frame) {
unproc_data_size = 1;
s->inbuf[0] = s->inbuf[s->buf_size-1];
}
os_sleep_ms(1);
}
mp3_dec = audio_coder_open(MP3_DEC, 0, 0);
if(mp3_dec == NULL)
return;
enc_ptr = s->inbuf;
while(1) {
if(s->next_status == AUCODEC_PAUSE) {
if(s->current_status == AUCODEC_RUN) {
msi_output_cmd(s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(s->audio_track)));
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_END_STREAM,(uint32_t)(&(s->audio_track)));
}
s->current_status = AUCODEC_PAUSE;
while(s->next_status == AUCODEC_PAUSE) {
os_sleep_ms(1);
}
}
if(s->next_status == AUCODEC_EXIT) {
s->current_status = AUCODEC_EXIT;
goto mp3_decode_end;
}
s->current_status = AUCODEC_RUN;
if(unproc_data_size < BUFF_SIZE && !endOfRead) {
bytes_to_read = BUFF_SIZE - unproc_data_size;
if(unproc_data_size)
os_memcpy(s->inbuf, enc_ptr+enc_ptr_offset, unproc_data_size);
read_len = mp3_file_read(s, s->inbuf+unproc_data_size, bytes_to_read);
if(read_len <= 0) {
MP3_INFO("mp3 read fail,ret:%d,line:%d!\r\n",read_len,__LINE__);
endOfRead = 1;
}
else
unproc_data_size += read_len;
enc_ptr = s->inbuf;
enc_ptr_offset = 0;
}
if(unproc_data_size > 0) {
while(!frame_buf) {
frame_buf = fbpool_get(&s->tx_pool, 0, s->msi);
if(!frame_buf)
os_sleep_ms(1);
}
data = (int16_t*)frame_buf->data;
dec_samples = audio_decode_data(mp3_dec, enc_ptr+enc_ptr_offset, unproc_data_size, s->dec_buf, &mp3_info);
if(dec_samples <= 0) {
enc_ptr_offset += 1;
unproc_data_size -= 1;
msi_delete_fb(s->msi, frame_buf);
frame_buf = NULL;
continue;
}
if(mp3_info.channels == 2) {
for(uint32_t i=0; i<dec_samples; i++)
data[i] = s->dec_buf[2*i];
}
else {
for(uint32_t i=0; i<dec_samples; i++)
data[i] = s->dec_buf[i];
}
enc_ptr_offset += mp3_info.frame_bytes;
unproc_data_size -= mp3_info.frame_bytes;
frame_buf->len = dec_samples*2;
frame_buf->mtype = F_AUDIO;
frame_buf->stype = FSTYPE_AUDIO_PCM;
s->audio_track.samplerate = mp3_info.samplerate;
if(s->use_tpc && !s->autpc_msi) {
s->autpc_msi = autpc_msi_init(s->audio_track.samplerate, s->speed, s->pitch, dec_samples, &(s->audio_track));
if(s->autpc_msi == NULL) {
goto mp3_decode_end;
}
if(s->direct_to_dac) {
msi_add_output(s->autpc_msi, NULL, "R_AUDAC");
}
msi_add_output(s->msi, NULL, s->autpc_msi->name);
}
ret = msi_output_fb(s->msi, frame_buf);
MP3_DEBUG("mp3 decode send framebuff:%p,ret:%d\r\n",frame_buf,ret);
msi_cmd("R_AUDAC", MSI_CMD_AUDAC, MSI_AUDAC_GET_FILTER_TRACK, (uint32_t)(&audac_fiter_track));
if(s->direct_to_dac && (!s->use_tpc) && (audac_fiter_track != (&(s->audio_track)))) {
interval_time = (frame_buf->len>>1)*1000/(mp3_info.samplerate);
os_sleep_ms(interval_time);
}
frame_buf = NULL;
}
else if(endOfRead){
goto mp3_decode_end;
}
}
mp3_decode_end:
msi_output_cmd(s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(s->audio_track)));
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_END_STREAM,(uint32_t)(&(s->audio_track)));
if(frame_buf) {
msi_delete_fb(s->msi, frame_buf);
frame_buf = NULL;
}
if(mp3_dec) {
audio_coder_close(mp3_dec);
}
}
static void update_frame_buf(struct msi *msi, struct framebuff * frame_buf)
{
msi_delete_fb(NULL, frame_buf);
frame_buf = NULL;
while(!frame_buf) {
frame_buf = msi_get_fb(msi, 0);
os_sleep_ms(1);
}
}
static void mp3_msi_decode(struct mp3_decode_struct *s)
{
uint8_t clear_finish = 1;
uint8_t find_ID3 = 0;
uint8_t endOfRead = 0;
uint8_t *recv_data = NULL;
int16_t *send_data = NULL;
uint8_t *enc_ptr = NULL;
int32_t ret = 0;
int32_t data_len = 0;
int32_t dec_samples = 0;
int32_t unproc_data_size = 0;
int32_t ID3V2_offset = 0;
uint32_t ID3V2_len = 0;
uint32_t bytes_to_copy = 0;
uint32_t recv_data_offset = 0;
uint32_t enc_ptr_offset = 0;
uint32_t clear_flag = 0;
struct framebuff *recv_frame_buf = NULL;
struct framebuff *send_frame_buf = NULL;
AUCODE_HDL *mp3_dec = NULL;
AUCODE_FRAME_INFO mp3_info;
mp3_dec = audio_coder_open(MP3_DEC, 0, 0);
if(mp3_dec == NULL)
return;
enc_ptr = s->inbuf;
while(1) {
get_recv_frame_buf_again:
os_event_wait(&s->event, coder_clear_event, &clear_flag, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, 0);
if(clear_flag & coder_clear_event) {
clear_flag = 0;
clear_finish = 0;
}
recv_frame_buf = msi_get_fb(s->msi, 0);
if(recv_frame_buf) {
data_len = recv_frame_buf->len;
recv_data = recv_frame_buf->data;
recv_data_offset = 0;
if(data_len <= 0)
endOfRead = 1;
if(!s->get_first_frame) {
if(data_len <= 0)
goto mp3_decode_end;
if((os_strncmp(recv_data, "ID3", 3) == 0) && !find_ID3) {
ID3V2_len = (recv_data[6]&0x7F)*0x200000+ (recv_data[7]&0x7F)*0x4000 +
(recv_data[8]&0x7F)*0x80 +(recv_data[9]&0x7F);
ID3V2_offset = (ID3V2_len+10);
while(ID3V2_offset >= data_len) {
ID3V2_offset -= data_len;
update_frame_buf(s->msi, recv_frame_buf);
data_len = recv_frame_buf->len;
if(data_len <= 0)
goto mp3_decode_end;
}
recv_data_offset = ID3V2_offset;
data_len -= ID3V2_offset;
if(data_len <= 1) {
os_memcpy(s->inbuf, recv_data+recv_data_offset, data_len);
s->buf_size = data_len;
unproc_data_size = data_len;
update_frame_buf(s->msi, recv_frame_buf);
recv_data_offset = 0;
data_len = recv_frame_buf->len;
if(data_len <= 0)
goto mp3_decode_end;
}
}
find_ID3 = 1;
while(data_len) {
bytes_to_copy = data_len>(BUFF_SIZE-unproc_data_size)?(BUFF_SIZE-unproc_data_size):data_len;
os_memcpy(s->inbuf+unproc_data_size, recv_data+recv_data_offset, bytes_to_copy);
s->buf_size += bytes_to_copy;
data_len -= bytes_to_copy;
recv_data_offset += bytes_to_copy;
for(uint32_t i=0; i<(s->buf_size-1); i++) {
if( ( (s->inbuf[i] << 8) | (s->inbuf[i+1] & 0xE0) ) == 0xFFE0 ) {
s->get_first_frame = 1;
unproc_data_size = s->buf_size - i;
s->buf_size -= i;
enc_ptr_offset += i;
goto mp3_get_first_frame;
}
}
}
if(!s->get_first_frame) {
unproc_data_size = 1;
s->inbuf[0] = s->inbuf[s->buf_size-1];
s->buf_size = 1;
continue;
}
}
}
else {
if(clear_finish == 0) {
clear_finish = 1;
os_event_set(&s->event, coder_clear_finish_event, NULL);
}
os_sleep_ms(1);
}
mp3_get_first_frame:
if(s->next_status == AUCODEC_EXIT) {
s->current_status = AUCODEC_EXIT;
goto mp3_decode_end;
}
if(s->next_status == AUCODEC_PAUSE) {
if(recv_frame_buf)
msi_delete_fb(s->msi, recv_frame_buf);
recv_frame_buf = NULL;
enc_ptr_offset = 0;
unproc_data_size = 0;
if(s->current_status == AUCODEC_RUN) {
audio_coder_close(mp3_dec);
if(send_frame_buf) {
msi_delete_fb(s->msi, send_frame_buf);
}
send_frame_buf = NULL;
msi_output_cmd(s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(s->audio_track)));
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_END_STREAM,(uint32_t)(&(s->audio_track)));
mp3_dec = audio_coder_open(MP3_DEC, 0, 0);
if(mp3_dec == NULL)
return;
}
s->current_status = AUCODEC_PAUSE;
}
else
s->current_status = AUCODEC_RUN;
if(clear_finish == 0) {
if(recv_frame_buf)
msi_delete_fb(s->msi, recv_frame_buf);
recv_frame_buf = NULL;
enc_ptr_offset = 0;
unproc_data_size = 0;
continue;
}
while((data_len>0) || (unproc_data_size>0)) {
if((data_len) >= (BUFF_SIZE-unproc_data_size)) {
os_memcpy(enc_ptr, enc_ptr+enc_ptr_offset, unproc_data_size);
bytes_to_copy = BUFF_SIZE - unproc_data_size;
os_memcpy(enc_ptr+unproc_data_size, recv_data+recv_data_offset, bytes_to_copy);
data_len -= bytes_to_copy;
recv_data_offset += bytes_to_copy;
enc_ptr_offset = 0;
unproc_data_size += bytes_to_copy;
}
else if(!endOfRead) {
bytes_to_copy = data_len;
if(bytes_to_copy) {
os_memcpy(enc_ptr, enc_ptr+enc_ptr_offset, unproc_data_size);
os_memcpy(enc_ptr+unproc_data_size, recv_data+recv_data_offset, bytes_to_copy);
data_len -= bytes_to_copy;
recv_data_offset += bytes_to_copy;
enc_ptr_offset = 0;
unproc_data_size += bytes_to_copy;
}
msi_delete_fb(NULL, recv_frame_buf);
recv_frame_buf = NULL;
goto get_recv_frame_buf_again;
}
while(!send_frame_buf) {
send_frame_buf = fbpool_get(&s->tx_pool, 0, s->msi);
if(!send_frame_buf)
os_sleep_ms(1);
}
send_data = (int16_t*)send_frame_buf->data;
dec_samples = audio_decode_data(mp3_dec, enc_ptr+enc_ptr_offset, unproc_data_size, s->dec_buf, &mp3_info);
if(dec_samples <= 0) {
enc_ptr_offset += 1;
unproc_data_size -= 1;
msi_delete_fb(s->msi, send_frame_buf);
send_frame_buf = NULL;
continue;
}
if(mp3_info.channels == 2) {
for(uint32_t i=0; i<dec_samples; i++)
send_data[i] = s->dec_buf[2*i];
}
else {
for(uint32_t i=0; i<dec_samples; i++)
send_data[i] = s->dec_buf[i];
}
enc_ptr_offset += mp3_info.frame_bytes;
unproc_data_size -= mp3_info.frame_bytes;
send_frame_buf->len = dec_samples*2;
send_frame_buf->mtype = F_AUDIO;
send_frame_buf->stype = FSTYPE_AUDIO_PCM;
s->audio_track.samplerate = mp3_info.samplerate;
if(s->use_tpc && !s->autpc_msi) {
s->autpc_msi = autpc_msi_init(s->audio_track.samplerate, s->speed, s->pitch, dec_samples, &(s->audio_track));
if(s->autpc_msi == NULL) {
goto mp3_decode_end;
}
if(s->direct_to_dac) {
msi_add_output(s->autpc_msi, NULL, "R_AUDAC");
}
msi_add_output(s->msi, NULL, s->autpc_msi->name);
}
ret = msi_output_fb(s->msi, send_frame_buf);
MP3_DEBUG("mp3 decode send framebuff:%p,ret:%d\r\n",send_frame_buf,ret);
send_frame_buf = NULL;
}
if(endOfRead)
goto mp3_decode_end;
}
mp3_decode_end:
msi_output_cmd(s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(s->audio_track)));
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_END_STREAM,(uint32_t)(&(s->audio_track)));
if(recv_frame_buf) {
msi_delete_fb(NULL, recv_frame_buf);
recv_frame_buf = NULL;
}
if(send_frame_buf) {
msi_delete_fb(s->msi, send_frame_buf);
send_frame_buf = NULL;
}
if(mp3_dec) {
audio_coder_close(mp3_dec);
}
}
static void mp3_decode_thread(void *d)
{
struct mp3_decode_struct *s = (struct mp3_decode_struct *)d;
if(s->mp3_fp) {
curmp3_info_init(&s->cur_mp3_info, s->mp3_filename);
s->file_size = osal_fsize(s->mp3_fp);
get_curmp3_size(s->cur_mp3_info, s->file_size);
find_first_frame(s->cur_mp3_info, s->mp3_fp);
if(s->cur_mp3_info->normal_frame_offset)
s->get_first_frame = 1;
}
msi_get(s->msi);
if(s->direct_to_dac) {
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(s->audio_track)));
}
s->msi->enable = 1;
if(s->mp3_fp) {
do {
if(s->cur_mp3_info)
osal_fseek(s->mp3_fp, s->cur_mp3_info->first_frame_offset);
else
osal_fseek(s->mp3_fp, 0);
mp3_file_decode(s);
if(s->current_status == AUCODEC_EXIT) {
break;
}
}while(s->loop_mode);
}
else
mp3_msi_decode(s);
if(s->direct_to_dac) {
s->audio_track.priority = play_disabled;
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(s->audio_track)));
}
os_event_set(&s->event, coder_exit_event, NULL);
while((s->next_status != AUCODEC_EXIT) && (s->destroy_self == 0)) {
s->current_status = AUCODEC_END;
os_sleep_ms(5);
}
if(s->cur_mp3_info)
clear_curmp3_info(s->cur_mp3_info);
if(s->src_msi) {
msi_del_output(s->src_msi, NULL, s->msi->name);
s->src_msi = NULL;
}
if(s->next_status != AUCODEC_EXIT)
msi_destroy(s->msi);
msi_put(s->msi);
}
static int32_t mp3_decode_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
{
int32_t ret = RET_OK;
struct mp3_decode_struct *mp3_decode_s = (struct mp3_decode_struct*)(msi->priv);
switch(cmd_id) {
case MSI_CMD_AUCODER:
{
ret = RET_ERR;
if(mp3_decode_s) {
uint32_t cmd_self = (uint32_t)param1;
switch(cmd_self) {
case MSI_AUCODER_PAUSE:
{
if(mp3_decode_s->current_status == AUCODEC_RUN) {
mp3_decode_s->next_status = AUCODEC_PAUSE;
}
ret = RET_OK;
break;
}
case MSI_AUCODER_CONTINUE:
{
if(mp3_decode_s->current_status == AUCODEC_PAUSE) {
mp3_decode_s->next_status = AUCODEC_RUN;
}
ret = RET_OK;
break;
}
case MSI_AUCODER_GET_STATUS:
{
*((uint32_t*)param2) = (uint32_t)(mp3_decode_s->current_status);
ret = RET_OK;
break;
}
case MSI_AUCODER_SET_SPEED:
{
mp3_decode_s->speed = (uint8_t)param2;
ret = msi_output_cmd(mp3_decode_s->msi,MSI_CMD_AUTPC,MSI_AUTPC_SET_SPEED,(uint32_t)(mp3_decode_s->speed));
break;
}
case MSI_AUCODER_GET_SPEED:
{
*((uint32_t*)param2) = (uint32_t)(mp3_decode_s->speed);
ret = RET_OK;
break;
}
case MSI_AUCODER_SET_PITCH:
{
mp3_decode_s->pitch = (uint8_t)param2;
ret = msi_output_cmd(mp3_decode_s->msi,MSI_CMD_AUTPC,MSI_AUTPC_SET_PITCH,(uint32_t)(mp3_decode_s->pitch));
break;
}
case MSI_AUCODER_GET_PITCH:
{
*((uint32_t*)param2) = (uint32_t)(mp3_decode_s->pitch);
ret = RET_OK;
break;
}
case MSI_AUCODER_CLEAR_STREAM:
{
os_event_set(&mp3_decode_s->event, coder_clear_event, NULL);
os_event_wait(&mp3_decode_s->event, coder_clear_finish_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
msi_output_cmd(mp3_decode_s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(mp3_decode_s->audio_track)));
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_CLEAR_STREAM,(uint32_t)(&(mp3_decode_s->audio_track)));
ret = RET_OK;
break;
}
case MSI_AUCODER_SET_SRCMSI:
{
if(mp3_decode_s->src_msi) {
msi_del_output(mp3_decode_s->src_msi, NULL, msi->name);
}
mp3_decode_s->src_msi = NULL;
ret = msi_add_output((struct msi*)param2, NULL, msi->name);
if(ret == RET_OK) {
mp3_decode_s->src_msi = (struct msi*)param2;
}
break;
}
case MSI_AUCODER_DIRECT_TO_DAC:
{
uint32_t direct_to_dac = param2;
if(direct_to_dac && mp3_decode_s->direct_to_dac == 0) {
mp3_decode_s->direct_to_dac = 1;
if(mp3_decode_s->use_tpc == 0) {
msi_add_output(msi, NULL, "R_AUDAC");
}
else if(mp3_decode_s->autpc_msi) {
msi_add_output(mp3_decode_s->autpc_msi, NULL, "R_AUDAC");
}
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(mp3_decode_s->audio_track)));
}
else if(mp3_decode_s->direct_to_dac == 1) {
mp3_decode_s->direct_to_dac = 0;
if(mp3_decode_s->use_tpc == 0) {
msi_del_output(msi, NULL, "R_AUDAC");
}
else if(mp3_decode_s->autpc_msi) {
msi_del_output(mp3_decode_s->autpc_msi, NULL, "R_AUDAC");
}
mp3_decode_s->audio_track.priority &= 0x3F;
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(mp3_decode_s->audio_track)));
}
break;
}
case MSI_AUCODER_DEINIT:
{
msi_destroy(msi);
ret = RET_OK;
break;
}
default:
break;
}
}
break;
}
case MSI_CMD_TRANS_FB:
{
ret = RET_ERR;
struct framebuff *frame_buf = (struct framebuff *)param1;
if(frame_buf->mtype == F_AUDIO) {
ret = RET_OK;
}
break;
}
case MSI_CMD_FREE_FB:
{
ret = RET_ERR;
if(mp3_decode_s) {
struct framebuff *frame_buf = (struct framebuff *)param1;
fbpool_put(&mp3_decode_s->tx_pool, frame_buf);
}
break;
}
case MSI_CMD_PRE_DESTROY:
{
if(mp3_decode_s && mp3_decode_s->task_hdl) {
mp3_decode_s->next_status = AUCODEC_EXIT;
}
break;
}
case MSI_CMD_POST_DESTROY:
{
if(mp3_decode_s) {
if(mp3_decode_s->task_hdl) {
os_event_wait(&mp3_decode_s->event, coder_exit_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
}
for(uint32_t i=0; i<MAX_MP3_DECODE_TXBUF; i++) {
struct framebuff *frame_buf = (mp3_decode_s->tx_pool.pool)+i;
if(frame_buf->data) {
MP3_DECODE_FREE(frame_buf->data);
frame_buf->data = NULL;
}
}
fbpool_destroy(&mp3_decode_s->tx_pool);
if(mp3_decode_s->event.hdl) {
os_event_del(&mp3_decode_s->event);
}
if(mp3_decode_s->mp3_fp) {
osal_fclose(mp3_decode_s->mp3_fp);
mp3_decode_s->mp3_fp = NULL;
}
if(mp3_decode_s->autpc_msi) {
autpc_msi_deinit(mp3_decode_s->autpc_msi);
mp3_decode_s->autpc_msi = NULL;
}
if(mp3_decode_s->msi_name) {
MP3_DECODE_FREE(mp3_decode_s->msi_name);
mp3_decode_s->msi_name = NULL;
}
MP3_DECODE_FREE(mp3_decode_s);
mp3_decode_s = NULL;
}
break;
}
default:
break;
}
return ret;
}
struct msi *mp3_decode_init(char *filename, uint8_t loop_mode, AUDEC_INIT *audec_init)
{
#if AUDIO_EN
char *msi_name = NULL;
msi_name = (char*)MP3_DECODE_ZALLOC(sizeof(char)*32);
if(msi_name == NULL) {
os_printf("alloc autpc msi namefail\n");
return NULL;
}
os_snprintf(msi_name, 20, "SR_MP3_DECODE_""%04d", (int)(os_jiffies()));
struct msi *msi = msi_new(msi_name, MAX_MP3_DECODE_RXBUF, NULL);
os_printf("mp3 msi name:%s\n",msi_name);
if(msi == NULL) {
MP3_INFO("create mp3 decode msi fail!\r\n");
return NULL;
}
struct mp3_decode_struct *mp3_decode_s = (struct mp3_decode_struct*)MP3_DECODE_ZALLOC(sizeof(struct mp3_decode_struct));
if(!mp3_decode_s) {
MP3_INFO("mp3_decode_s malloc fail!\r\n");
goto mp3_decode_init_err;
}
msi->priv = mp3_decode_s;
msi->action = (msi_action)mp3_decode_msi_action;
fbpool_init(&mp3_decode_s->tx_pool, MAX_MP3_DECODE_TXBUF);
for(uint32_t i=0; i<MAX_MP3_DECODE_TXBUF; i++) {
struct framebuff *frame_buf = (mp3_decode_s->tx_pool.pool)+i;
frame_buf->data = (uint8_t*)MP3_DECODE_MALLOC(1152 * sizeof(int16_t));
if(frame_buf->data == NULL)
{
MP3_INFO("mp3 decode malloc framebuff data fail!\r\n");
goto mp3_decode_init_err;
}
frame_buf->priv = &(mp3_decode_s->audio_track);
}
if(os_event_init(&mp3_decode_s->event) != RET_OK) {
MP3_INFO("create mp3 decode event fail!\r\n");
goto mp3_decode_init_err;
}
if(filename) {
os_memcpy(mp3_decode_s->mp3_filename, filename, 20);
mp3_decode_s->mp3_fp = osal_fopen((const char*)mp3_decode_s->mp3_filename, "rb");
if(mp3_decode_s->mp3_fp == NULL) {
MP3_INFO("open mp3 file %s fail!\r\n", mp3_decode_s->mp3_filename);
goto mp3_decode_init_err;
}
}
if(audec_init->src_msi && (msi_add_output(audec_init->src_msi, NULL, msi->name) != RET_OK)) {
goto mp3_decode_init_err;
}
mp3_decode_s->msi = msi;
mp3_decode_s->msi_name = msi_name;
mp3_decode_s->src_msi = audec_init->src_msi;
mp3_decode_s->loop_mode = loop_mode;
mp3_decode_s->direct_to_dac = audec_init->direct_to_dac;
mp3_decode_s->use_tpc = audec_init->use_tpc;
mp3_decode_s->speed = audec_init->speed;
mp3_decode_s->pitch = audec_init->pitch;
mp3_decode_s->destroy_self = audec_init->destroy_self;
mp3_decode_s->audio_track.priority = audec_init->priority;
mp3_decode_s->audio_track.track_type = audec_init->track_type;
mp3_decode_s->next_status = AUCODEC_RUN;
mp3_decode_s->current_status = AUCODEC_RUN;
if(audec_init->direct_to_dac && !mp3_decode_s->use_tpc) {
msi_add_output(msi, NULL, "R_AUDAC");
}
mp3_decode_s->task_hdl = os_task_create("mp3_decode_thread", mp3_decode_thread, (void*)mp3_decode_s, OS_TASK_PRIORITY_BELOW_NORMAL, 0, NULL, 3072);
if(mp3_decode_s->task_hdl == NULL) {
MP3_INFO("create mp3 decode task fail!\r\n");
goto mp3_decode_init_err;
}
return msi;
mp3_decode_init_err:
msi_destroy(msi);
#endif
return NULL;
}

View File

@@ -0,0 +1,26 @@
#ifndef _MP3_DECODE_MSI_H_
#define _MP3_DECODE_MSI_H_
#include "basic_include.h"
#include "lib/heap/av_heap.h"
#include "lib/heap/av_psram_heap.h"
#include "audio_code_ctrl.h"
#ifdef PSRAM_HEAP
#define MP3_DECODE_MALLOC av_psram_malloc
#define MP3_DECODE_ZALLOC av_psram_zalloc
#define MP3_DECODE_CALLOC av_psram_calloc
#define MP3_DECODE_FREE av_psram_free
#else
#define MP3_DECODE_MALLOC av_malloc
#define MP3_DECODE_ZALLOC av_zalloc
#define MP3_DECODE_CALLOC av_calloc
#define MP3_DECODE_FREE av_free
#endif
#define MP3_DEBUG(fmt, args...) //os_printf(fmt, ##args)
#define MP3_INFO os_printf
struct msi *mp3_decode_init(char *filename, uint8_t loop_mode, AUDEC_INIT *audec_init);
#endif

View File

@@ -0,0 +1,472 @@
#include "basic_include.h"
//#include "keyWork.h"
//#include "keyScan.h"
#include "osal_file.h"
#include "mp3_getInfo.h"
#include "mp3_decode.h"
#include "audio_code_ctrl.h"
#include "lib/heap/av_heap.h"
#include "lib/heap/av_psram_heap.h"
#define MP3_SAVE_INFO 0
#if MP3_SAVE_INFO
#define MAX_FORWARD_TIME 10
struct key_callback_list_s *key_seek_list = NULL;
#endif
const uint32_t bitrate_table[5][15] = {
/* MPEG-1 */
{ 0, 32000, 64000, 96000, 128000, 160000, 192000, 224000, /* Layer I */
256000, 288000, 320000, 352000, 384000, 416000, 448000 },
{ 0, 32000, 48000, 56000, 64000, 80000, 96000, 112000, /* Layer II */
128000, 160000, 192000, 224000, 256000, 320000, 384000 },
{ 0, 32000, 40000, 48000, 56000, 64000, 80000, 96000, /* Layer III */
112000, 128000, 160000, 192000, 224000, 256000, 320000 },
/* MPEG-2 MPEG-2.5 */
{ 0, 32000, 48000, 56000, 64000, 80000, 96000, 112000, /* Layer I */
128000, 144000, 160000, 176000, 192000, 224000, 256000 },
{ 0, 8000, 16000, 24000, 32000, 40000, 48000, 56000, /* Layer */
64000, 80000, 96000, 112000, 128000, 144000, 160000 } /* II & III */
};
const uint32_t samplingrate_table[4][3] = { //value s are in Hz
{11025 , 12000 , 8000}, //MPEG Version 2.5
{0,0,0}, //reserved
{22050, 24000, 16000}, //MPEG Version 2 (ISO/IEC 13818-3)
{44100, 48000, 32000} //MPEG Version 1 (ISO/IEC 11172-3)
};
const uint8_t layerIII_inbytes[4][4] = {
{17,17,17,9}, /*MPEG Version 2.5*/
{0, 0, 0, 0}, /*reserved*/
{17,17,17,9}, /*MPEG Version 2*/
{32,32,32,17} /*MPEG Version 1*/
};
const uint16_t samples_table[4][4] = {
{0,576,1152,384}, /*MPEG Version 2.5 {reserve,layerIII,layerII,layerI}*/
{0,0,0,0}, /*reserved {reserve,layerIII,layerII,layerI}*/
{0,576,1152,384}, /*MPEG Version 2 {reserve,layerIII,layerII,layerI}*/
{0,1152,1152,384} /*MPEG Version 1 {reserve,layerIII,layerII,layerI}*/
};
uint32_t get_curmp3_size(CUR_MP3_INFO *cur_mp3_info, uint32_t s)
{
if(!cur_mp3_info)
return 0;
cur_mp3_info->total_size =s;
return cur_mp3_info->total_size;
}
void curmp3_info_init(CUR_MP3_INFO **cur_mp3_info, uint8_t *mp3_filename)
{
#if MP3_SAVE_INFO
char dirname_len = strlen("0:mp3/");
char extension_len = strlen("mp3");
char filename_temp[50] = {0};
#endif
if(!(*cur_mp3_info))
(*cur_mp3_info) = (CUR_MP3_INFO*)MP3_DECODE_ZALLOC(sizeof(CUR_MP3_INFO));
else
os_memset((*cur_mp3_info), 0, sizeof(CUR_MP3_INFO));
#if MP3_SAVE_INFO
os_memcpy(filename_temp, mp3_filename+dirname_len, strlen(mp3_filename)-dirname_len-extension_len);
filename_temp[strlen(mp3_filename)-dirname_len-extension_len] = '\0';
os_sprintf((*cur_mp3_info)->mp3_st_filename, "0:MP3_SEEK/%s%s", filename_temp, "st");
os_printf("mp3_st_filename:%s\n",(*cur_mp3_info)->mp3_st_filename);
#endif
}
// void get_curmp3_totaltime_ergodic(void *fp, uint32_t first_frame_offset)
// {
// uint8_t bitrate_index = 0;
// uint8_t padding = 0;
// uint8_t frame_head[4];
// int32_t read_len = 0;
// uint32_t bitrate = 0;
// uint32_t frame_len = 0;
// uint32_t offset = 0;
// uint32_t current_seek = 0;
// uint32_t read_frame_cnt = 0;
// uint32_t read_second_cnt = 0;
// if(!cur_mp3_info)
// return;
// current_seek = osal_ftell(fp);
// osal_fseek(fp, first_frame_offset);
// osal_fread(frame_head, 1, 4, fp);
// offset = first_frame_offset;
// bitrate_index = (frame_head[2]>>4)&0xf;
// bitrate = bitrate_table[cur_mp3_info->bitrate_table_index][bitrate_index];
// padding = ((frame_head[2]>>1)&0x1) * cur_mp3_info->padding_mul;
// frame_len = cur_mp3_info->samples/8*bitrate/cur_mp3_info->samplingrate + padding;
// offset = first_frame_offset+4;
// // printf("samples:%d samplingrate:%d bitrate:%d\n",cur_mp3_info->samples,cur_mp3_info->samplingrate,bitrate);
// INIT_LIST_HEAD((struct list_head *)&cur_mp3_info->seek_table_head);
// MP3_SEEK_TABLE *sub_seek_table = MP3_DECODE_ZALLOC(sizeof(MP3_SEEK_TABLE));
// list_add_tail((struct list_head *)&sub_seek_table->sub_table_list,(struct list_head *)&cur_mp3_info->seek_table_head);
// sub_seek_table->sub_table[0] = first_frame_offset;
// while(1) {
// osal_fseek(fp, offset+frame_len-4);
// offset += frame_len;
// read_len = osal_fread(frame_head, 1, 4, fp);
// if(((cur_mp3_info->total_size-offset)==124) && (strncmp((const char*)frame_head, "TAG", 3)==0)) { //ID3V1
// break;
// }
// if(((frame_head[0]<<8) | (frame_head[1]&0xE0)) != 0xFFE0) {
// break;
// }
// if((offset+frame_len-4) >= cur_mp3_info->total_size ) { //end
// break;
// }
// cur_mp3_info->total_frame++;
// bitrate_index = (frame_head[2]>>4)&0xf;
// bitrate = bitrate_table[cur_mp3_info->bitrate_table_index][bitrate_index];
// padding = ((frame_head[2]>>1)&0x1) * cur_mp3_info->padding_mul;
// frame_len = cur_mp3_info->samples/8*bitrate/cur_mp3_info->samplingrate + padding;
// read_frame_cnt++;
// if(read_frame_cnt >= (cur_mp3_info->one_second_frame)) {
// read_second_cnt++;
// if(read_second_cnt >= 100) {
// sub_seek_table = (MP3_SEEK_TABLE*)MP3_DECODE_ZALLOC(sizeof(MP3_SEEK_TABLE));
// list_add_tail((struct list_head *)&sub_seek_table->sub_table_list,(struct list_head *)&cur_mp3_info->seek_table_head);
// read_second_cnt -= 100;
// }
// sub_seek_table->sub_table[read_second_cnt] = offset-4;
// read_frame_cnt -= (cur_mp3_info->one_second_frame);
// }
// }
// cur_mp3_info->totaltime = cur_mp3_info->total_frame * cur_mp3_info->samples / cur_mp3_info->samplingrate;
// cur_mp3_info->once_move_time = (cur_mp3_info->totaltime%100)?(cur_mp3_info->totaltime/100+1):(cur_mp3_info->totaltime/100);
// MP3_INFO("total_frame:%d total_time:%d once_move_time:%d\n",cur_mp3_info->total_frame, cur_mp3_info->totaltime,cur_mp3_info->once_move_time);
// cur_mp3_info->get_totaltime = 1;
// osal_fseek(fp, current_seek);
// }
// uint32_t get_mp3_seek(void)
// {
// if(!cur_mp3_info)
// return 0;
// return cur_mp3_info->offset_seek;
// }
// uint32_t get_curmp3_playtime(void)
// {
// if(!cur_mp3_info)
// return 0;
// cur_mp3_info->playtime = cur_mp3_info->play_frame * cur_mp3_info->samples / cur_mp3_info->samplingrate;
// // printf("record:%d %d\n",cur_mp3_info->playtime,cur_mp3_info->play_frame);
// return cur_mp3_info->playtime;
// }
// uint32_t get_curmp3_playframe(void)
// {
// if(!cur_mp3_info)
// return 0;
// cur_mp3_info->play_frame++;
// return cur_mp3_info->play_frame;
// }
// void update_curmp3_playtime(uint32_t update_time)
// {
// if(!cur_mp3_info)
// return;
// cur_mp3_info->playtime = update_time;
// }
// void update_curmp3_playframe(uint32_t update_frame)
// {
// if(!cur_mp3_info)
// return;
// cur_mp3_info->play_frame = update_frame;
// }
// void set_mp3_seek(int16_t move_time)
// {
// uint8_t table_pos = 0;
// uint32_t offset_seek = 0;
// uint32_t target_time = 0;
// uint32_t target_frame = 0;
// uint32_t table_index = 0;
// struct list_head *seek_table_list = NULL;
// MP3_SEEK_TABLE *seek_table = NULL;
// target_time = ((cur_mp3_info->playtime + move_time)<0)?0:(cur_mp3_info->playtime + move_time);
// target_time = (target_time>cur_mp3_info->totaltime)?cur_mp3_info->totaltime:target_time;
// target_frame = cur_mp3_info->one_second_frame*target_time;
// table_index = target_time/100;
// table_pos = target_time%100;
// seek_table_list = cur_mp3_info->seek_table_head.next;
// while(table_index>0) {
// seek_table_list = seek_table_list->next;
// table_index--;
// }
// seek_table = list_entry((struct list_head *)seek_table_list,MP3_SEEK_TABLE,sub_table_list);
// offset_seek = seek_table->sub_table[table_pos];
// osal_fseek(cur_mp3_info->mp3_fp,offset_seek);
// update_curmp3_playtime(target_time);
// update_curmp3_playframe(target_frame);
// cur_mp3_info->offset_seek = offset_seek;
// MP3_INFO("**file pos:%x time:%d frame:%d**\n",offset_seek,cur_mp3_info->playtime,cur_mp3_info->play_frame);
// }
// //
// //uint32_t key_seek_callback(struct key_callback_list_s *callback_list,uint32_t keyvalue,uint32_t extern_value)
// //{
// // uint32 key_val = 0;
// //
// // if(!cur_mp3_info)
// // return 0;
// //
// // if(((keyvalue>>8) != AD_A) && ((keyvalue>>8) != AD_B))
// // return 0;
// // if(get_mp3_decode_status() == MP3_STOP) {
// // _os_printf("mp3 stop\n");
// // return 0;
// // }
// // key_val = (keyvalue & 0xff);
// // if((keyvalue>>8) == AD_A) {
// // if(key_val == KEY_EVENT_DOWN) {
// // os_sema_down(&seek_sema,5000);
// // set_mp3_seek(-cur_mp3_info->once_move_time);
// // }
// // else if((key_val == KEY_EVENT_LDOWN) || (key_val == KEY_EVENT_REPEAT)) {
// // set_mp3_seek(-cur_mp3_info->once_move_time);
// // }
// // else if((key_val == KEY_EVENT_SUP) || (key_val == KEY_EVENT_LUP)) {
// // cur_mp3_info->update_fops = 1;
// // os_sema_up(&seek_sema);
// // }
// // }
// // else if((keyvalue>>8) == AD_B) {
// // if(key_val == KEY_EVENT_DOWN) {
// // os_sema_down(&seek_sema,5000);
// // set_mp3_seek(cur_mp3_info->once_move_time);
// // }
// // else if((key_val == KEY_EVENT_LDOWN) || (key_val == KEY_EVENT_REPEAT)) {
// // set_mp3_seek(cur_mp3_info->once_move_time);
// // }
// // else if((key_val == KEY_EVENT_SUP) || (key_val == KEY_EVENT_LUP)) {
// // cur_mp3_info->update_fops = 1;
// // os_sema_up(&seek_sema);
// // }
// // }
// // return 1;
// //}
// int32_t at_set_mp3_seek(const char *cmd, char *argv[], uint32_t argc)
// {
// int32_t seek_time = 0;
// uint32_t forward_time = 0;
// if(!cur_mp3_info)
// return 0;
// // if(get_mp3_decode_status() == AUCODEC_EXIT) {
// // MP3_INFO("mp3 stop\n");
// // return 0;
// // }
// if(argc < 1) {
// MP3_INFO("%s %d,enter the seek\n",__FUNCTION__,argc);
// return 0;
// }
// if(argv[0]) {
// seek_time = os_atoi(argv[0]);
// if(seek_time == 0)
// return 1;
// // forward_time = (seek_time<MAX_FORWARD_TIME)?seek_time:MAX_FORWARD_TIME;
// forward_time = seek_time;
// os_sema_down(&seek_sema,5000);
// set_mp3_seek(forward_time);
// cur_mp3_info->update_fops = 1;
// os_sema_up(&seek_sema);
// }
// return 0;
// }
// int seektable_check(CUR_MP3_INFO *mp3_info)
// {
// int32_t ret = 0;
// uint32_t read_buf[4] = {0};
// uint32_t seek_table_len = 0;
// uint32_t *cache_buf = NULL;
// cache_buf = (uint32_t*)MP3_DECODE_ZALLOC(sizeof(uint32_t)*100);
// if(!cache_buf)
// goto seektable_check_end;
// osal_fread(read_buf, 4, 4, mp3_info->mp3_st_fp);
// if((read_buf[0]==mp3_info->total_size) && (read_buf[1]==mp3_info->first_frame_offset)
// && (read_buf[2]==mp3_info->normal_frame_offset)) {
// mp3_info->total_frame = read_buf[3];
// seek_table_len = osal_fsize(mp3_info->mp3_st_fp) - sizeof(read_buf);
// INIT_LIST_HEAD((struct list_head *)&mp3_info->seek_table_head);
// while(seek_table_len) {
// MP3_SEEK_TABLE *sub_seek_table = MP3_DECODE_ZALLOC(sizeof(MP3_SEEK_TABLE));
// list_add_tail((struct list_head *)&sub_seek_table->sub_table_list,(struct list_head *)&mp3_info->seek_table_head);
// osal_fread((void*)cache_buf, 4, 100, mp3_info->mp3_st_fp);
// os_memcpy(sub_seek_table->sub_table, cache_buf, sizeof(uint32_t)*100);
// seek_table_len -= 100*4;
// }
// cur_mp3_info->totaltime = cur_mp3_info->total_frame * cur_mp3_info->samples / cur_mp3_info->samplingrate;
// cur_mp3_info->once_move_time = (cur_mp3_info->totaltime%100)?(cur_mp3_info->totaltime/100+1):(cur_mp3_info->totaltime/100);
// MP3_INFO("total_frame:%d total_time:%d once_move_time:%d\n",cur_mp3_info->total_frame, cur_mp3_info->totaltime,cur_mp3_info->once_move_time);
// cur_mp3_info->get_totaltime = 1;
// ret = 1;
// }
// seektable_check_end:
// if(cache_buf)
// MP3_DECODE_FREE((void*)cache_buf);
// osal_fclose(mp3_info->mp3_st_fp);
// return ret;
// }
void find_first_frame(CUR_MP3_INFO *cur_mp3_info, void *fp)
{
uint8_t mp3_head[512];
uint8_t bitrate_index = 0;
uint8_t channel_mode = 0x11;
uint8_t padding = 0;
uint8_t layer_index = 0;
uint8_t mpeg_index = 0;
uint8_t samplingrate_index = 0;
int32_t bitrate = 0;
uint32_t offset = 0;
uint32_t first_frame_offset = 0;
uint32_t seek = 0;
uint32_t frame_len = 0;
if(!cur_mp3_info) {
return;
}
osal_fread(mp3_head, 512, 1, fp);
if(os_strncmp(mp3_head+offset, "ID3", 3) == 0) {
uint32_t ID3V2_len = (mp3_head[6]&0x7F)*0x200000+ (mp3_head[7]&0x7F)*0x4000 +
(mp3_head[8]&0x7F)*0x80 +(mp3_head[9]&0x7F);
offset += (ID3V2_len+10);
}
MP3_INFO("ID3 offset:%x\n",offset);
osal_fseek(fp,offset);
seek = offset;
osal_fread(mp3_head,1,512,fp);
while(((mp3_head[offset-seek]<<8) | (mp3_head[offset-seek+1]&0xE0)) != 0xFFE0) {
offset++;
if((offset+1) > (seek+512)) {
osal_fseek(fp,offset);
osal_fread(mp3_head, 1, 512, fp);
seek = offset;
}
}
osal_fseek(fp,offset);
seek = offset;
osal_fread(mp3_head,1,512,fp);
cur_mp3_info->mp3_fp = fp;
first_frame_offset = offset;
// os_printf("\n***first frame offset:%x****\n",first_frame_offset);
cur_mp3_info->first_frame_offset = first_frame_offset;
layer_index = (mp3_head[first_frame_offset-seek+1]>>1)&0x3;
mpeg_index = (mp3_head[first_frame_offset-seek+1]>>3)&0x3;
samplingrate_index = (mp3_head[first_frame_offset-seek+2]>>2)&0x3;
cur_mp3_info->samplingrate = samplingrate_table[mpeg_index][samplingrate_index];
cur_mp3_info->samples = samples_table[mpeg_index][layer_index];
channel_mode = (mp3_head[first_frame_offset-seek+3]>>6)&0x3;
if(mpeg_index == 3) { /*MPEG 1*/
switch(layer_index) {
case 0:break;
case 1:cur_mp3_info->bitrate_table_index = 2;break; /*layer III*/
case 2:cur_mp3_info->bitrate_table_index = 1;break; /*layer II*/
case 3:cur_mp3_info->bitrate_table_index = 0;break; /*layer I*/
default:break;
}
}
else if((mpeg_index == 0) || (mpeg_index == 2)) { /*MPEG 2、MPEG2.5*/
switch(layer_index) {
case 0:break;
case 1:cur_mp3_info->bitrate_table_index = 4;break;
case 2:cur_mp3_info->bitrate_table_index = 4;break;
case 3:cur_mp3_info->bitrate_table_index = 3;break;
default:break;
}
}
bitrate_index = (mp3_head[first_frame_offset-seek+2]>>4)&0xf;
bitrate = bitrate_table[cur_mp3_info->bitrate_table_index][bitrate_index];
if(layer_index == 3)
cur_mp3_info->padding_mul = 4;
else if((layer_index == 1) || (layer_index == 2))
cur_mp3_info->padding_mul = 1;
padding = ((mp3_head[first_frame_offset-seek+2]>>1)&0x1) * cur_mp3_info->padding_mul;
frame_len = cur_mp3_info->samples/8*bitrate/cur_mp3_info->samplingrate + padding;
MP3_INFO("first frame samples:%d samplingrate:%d channel_mode:%d bitrate:%d frame_len:%d\n",
cur_mp3_info->samples,cur_mp3_info->samplingrate,channel_mode,bitrate,frame_len);
cur_mp3_info->normal_frame_offset = cur_mp3_info->first_frame_offset+frame_len;
cur_mp3_info->one_second_frame = cur_mp3_info->samplingrate/cur_mp3_info->samples;
#if MP3_SAVE_INFO
int32_t ret = 0;
DIR st_dir;
os_sema_init(&seek_sema, 1);
if(!key_seek_list)
key_seek_list = add_keycallback(key_seek_callback, NULL);
MP3_INFO("one_second_frame:%d",cur_mp3_info->one_second_frame);
ret = f_opendir(&st_dir,"0:/MP3_SEEK");
if(ret == FR_OK) {
cur_mp3_info->mp3_st_fp = osal_fopen(cur_mp3_info->mp3_st_filename, "r");
if(cur_mp3_info->mp3_st_fp) {
if(seektable_check(cur_mp3_info)) {
return;
}
osal_fclose(cur_mp3_info->mp3_st_fp);
}
}
else{
ret = f_mkdir("0:/MP3_SEEK");
}
get_curmp3_totaltime_ergodic(fp, first_frame_offset);
cur_mp3_info->mp3_st_fp = osal_fopen(cur_mp3_info->mp3_st_filename, "wb");
if(cur_mp3_info->mp3_st_fp) {
osal_fwrite(cur_mp3_info, 4, 4, cur_mp3_info->mp3_st_fp);
struct list_head *seek_table_list = cur_mp3_info->seek_table_head.next;
struct list_head *seek_table_head = &cur_mp3_info->seek_table_head;
while(seek_table_list != seek_table_head) {
MP3_SEEK_TABLE *seek_table = list_entry((struct list_head *)seek_table_list,MP3_SEEK_TABLE,sub_table_list);
osal_fwrite(seek_table->sub_table, 100, 4, cur_mp3_info->mp3_st_fp);
seek_table_list = seek_table_list->next;
}
osal_fclose(cur_mp3_info->mp3_st_fp);
}
#endif
}
// uint32_t get_curmp3_songtime(uint32_t brate)
// {
// if(!cur_mp3_info) {
// return 0;
// }
// if(cur_mp3_info->get_totaltime == 1) {
// return cur_mp3_info->totaltime;
// }
// return 0;
// }
void clear_curmp3_info(CUR_MP3_INFO *cur_mp3_info)
{
if(cur_mp3_info) {
MP3_DECODE_FREE(cur_mp3_info);
}
#if MP3_SAVE_INFO
if(key_seek_list) {
remove_keycallback(key_seek_list);
key_seek_list = NULL;
}
struct list_head *list_n = (struct list_head *)&cur_mp3_info->seek_table_head;
struct list_head *head = (struct list_head *)&cur_mp3_info->seek_table_head;
MP3_SEEK_TABLE *seek_table = NULL;
while(list_n->next != head) {
list_n = list_n->next;
seek_table = list_entry((struct list_head *)list_n,MP3_SEEK_TABLE,sub_table_list);
MP3_DECODE_FREE(seek_table);
}
os_sema_del(&seek_sema);
#endif
}

View File

@@ -0,0 +1,46 @@
#ifndef _MP3_GETINFO_MSI_H_
#define _MP3_GETINFO_MSI_H_
#include "basic_include.h"
typedef struct {
struct list_head sub_table_list;
uint32_t sub_table[100];
}MP3_SEEK_TABLE;
typedef struct {
uint32_t total_size;
uint32_t first_frame_offset;
uint32_t normal_frame_offset;
uint32_t total_frame;
uint32_t once_move_time;
uint32_t offset_seek;
uint32_t samplingrate;
uint32_t one_second_frame;
int32_t playtime;
int32_t play_frame;
uint16_t totaltime;
uint16_t samples;
uint8_t get_totaltime;
uint8_t update_fops;
uint8_t bitrate_table_index;
uint8_t padding_mul;
void *mp3_fp;
void *mp3_st_fp;
char mp3_st_filename[50];
struct list_head seek_table_head;
}CUR_MP3_INFO;
struct os_semaphore seek_sema;
uint32_t get_curmp3_size(CUR_MP3_INFO *cur_mp3_info, uint32_t s);
void curmp3_info_init(CUR_MP3_INFO **cur_mp3_info, uint8_t *mp3_filename);
void clear_curmp3_info(CUR_MP3_INFO *cur_mp3_info);
void find_first_frame(CUR_MP3_INFO *cur_mp3_info, void *fp);
#endif

View File

@@ -0,0 +1,27 @@
#ifndef _OPUS_CODE_H_
#define _OPUS_CODE_H_
#include "basic_include.h"
#include "lib/heap/av_heap.h"
#include "lib/heap/av_psram_heap.h"
#include "audio_code_ctrl.h"
#ifdef PSRAM_HEAP
#define OPUS_CODE_MALLOC av_psram_malloc
#define OPUS_CODE_ZALLOC av_psram_zalloc
#define OPUS_CODE_CALLOC av_psram_calloc
#define OPUS_CODE_FREE av_psram_free
#else
#define OPUS_CODE_MALLOC av_malloc
#define OPUS_CODE_ZALLOC av_zalloc
#define OPUS_CODE_CALLOC av_calloc
#define OPUS_CODE_FREE av_free
#endif
#define OPUS_DEBUG(fmt, args...) //os_printf(fmt, ##args)
#define OPUS_INFO os_printf
struct msi *opus_encode_init(uint32_t samplerate, AUENC_INIT *auenc_init);
struct msi *opus_decode_init(uint32_t samplerate, AUDEC_INIT *audec_init);
#endif

View File

@@ -0,0 +1,454 @@
#include "basic_include.h"
#include "csi_kernel.h"
#include "lib/multimedia/msi.h"
#include "lib/multimedia/framebuff.h"
#include "lib/audio/audio_code/audio_code.h"
#include "autpc_msi/autpc_msi.h"
#include "opus_code.h"
#define MAX_OPUS_DECODE_RXBUF 4
#define MAX_OPUS_DECODE_TXBUF 4
struct opus_decode_struct {
AUDIO_TRACK audio_track;
struct fbpool tx_pool;
struct os_event event;
struct msi *msi;
struct msi *src_msi;
struct msi *autpc_msi;
char *msi_name;
void *task_hdl;
uint8_t direct_to_dac;
uint8_t use_tpc;
uint8_t speed;
uint8_t pitch;
uint8_t destroy_self;
uint8_t next_status;
uint8_t current_status;
int16_t dec_buf[960]; //按照16k、60ms的最大长度若超过该长度则需修改数组大小;
uint32_t coder_sampleRate;
};
static void opus_decode(struct opus_decode_struct *s)
{
uint8_t clear_finish = 1;
uint8_t *enc_ptr = NULL;
int32_t ret = 0;
int32_t data_len = 0;
int32_t dec_samples = 0;
uint32_t dec_operation = 0;
uint32_t clear_flag = 0;
struct framebuff *recv_frame_buf = NULL;
struct framebuff *send_frame_buf = NULL;
AUCODE_HDL *opus_dec = NULL;
AUCODE_FRAME_INFO opus_info;
opus_dec = audio_coder_open(OPUS_DEC, s->coder_sampleRate, 1);
if(!opus_dec)
return;
while(1) {
os_event_wait(&s->event, coder_clear_event, &clear_flag, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, 0);
if(clear_flag & coder_clear_event) {
clear_flag = 0;
clear_finish = 0;
}
if(s->next_status == AUCODEC_PAUSE) {
if(s->current_status == AUCODEC_RUN) {
audio_coder_close(opus_dec);
msi_output_cmd(s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(s->audio_track)));
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_END_STREAM,(uint32_t)(&(s->audio_track)));
opus_dec = audio_coder_open(OPUS_DEC, s->coder_sampleRate, 1);
if(!opus_dec)
return;
}
s->current_status = AUCODEC_PAUSE;
}
recv_frame_buf = msi_get_fb(s->msi, 0);
if(recv_frame_buf) {
if(clear_finish == 0) {
goto opus_decode_frame_end;
}
if(s->next_status == AUCODEC_PAUSE) {
goto opus_decode_frame_end;
}
else {
s->current_status = AUCODEC_RUN;
while(!send_frame_buf) {
send_frame_buf = fbpool_get(&s->tx_pool, 0, s->msi);
if(!send_frame_buf)
os_sleep_ms(1);
}
if(recv_frame_buf->priv)
dec_operation = ((AUDECODER_OPERATION*)recv_frame_buf->priv)->decode_operation;
if(dec_operation == PACKET_LOSS_CONCEALMENT)
dec_samples = audio_decode_do_plc(opus_dec, s->dec_buf);
else if(dec_operation == OUTPUT_MUTE_DATA)
dec_samples = audio_decode_output_mute(opus_dec, s->dec_buf);
else {
if(dec_operation == DECODE_ADD_FADE_IN)
audio_decode_fade_in(opus_dec);
else if(dec_operation == DECODE_ADD_FADE_OUT)
audio_decode_fade_out(opus_dec);
data_len = recv_frame_buf->len;
if(data_len > 0) {
enc_ptr = recv_frame_buf->data;
dec_samples = audio_decode_data(opus_dec, enc_ptr, data_len, s->dec_buf, &opus_info);
}
else {
msi_delete_fb(s->msi, send_frame_buf);
send_frame_buf = NULL;
goto opus_decode_frame_end;
}
}
if(dec_samples <= 0) {
msi_delete_fb(s->msi, send_frame_buf);
send_frame_buf = NULL;
goto opus_decode_frame_end;
}
send_frame_buf->data = (uint8_t*)OPUS_CODE_MALLOC(dec_samples*2);
if(!send_frame_buf->data) {
OPUS_INFO("opus decode malloc send_frame_buf->data fail!\n");
msi_delete_fb(s->msi, send_frame_buf);
send_frame_buf = NULL;
goto opus_decode_frame_end;
}
os_memcpy(send_frame_buf->data, s->dec_buf, dec_samples*2);
send_frame_buf->len = dec_samples*2;
send_frame_buf->mtype = F_AUDIO;
send_frame_buf->stype = FSTYPE_AUDIO_PCM;
s->audio_track.samplerate = opus_info.samplerate;
if(s->use_tpc && !s->autpc_msi) {
s->autpc_msi = autpc_msi_init(s->audio_track.samplerate, s->speed, s->pitch, dec_samples, &(s->audio_track));
if(s->autpc_msi == NULL) {
goto opus_decode_end;
}
if(s->direct_to_dac) {
msi_add_output(s->autpc_msi, NULL, "R_AUDAC");
}
msi_add_output(s->msi, NULL, s->autpc_msi->name);
}
ret = msi_output_fb(s->msi, send_frame_buf);
OPUS_DEBUG("opus decode send framebuff:%p,ret:%d\r\n",send_frame_buf,ret);
send_frame_buf = NULL;
}
opus_decode_frame_end:
OPUS_DEBUG("opus decode delete framebuff:%p,len:%d,\r\n",recv_frame_buf,recv_frame_buf->len);
msi_delete_fb(s->msi, recv_frame_buf);
recv_frame_buf = NULL;
}
else {
if(clear_finish == 0) {
clear_finish = 1;
os_event_set(&s->event, coder_clear_finish_event, NULL);
}
os_sleep_ms(1);
}
if(s->next_status == AUCODEC_EXIT) {
s->current_status = AUCODEC_EXIT;
goto opus_decode_end;
}
}
opus_decode_end:
msi_output_cmd(s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(s->audio_track)));
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_END_STREAM,(uint32_t)(&(s->audio_track)));
if(recv_frame_buf) {
msi_delete_fb(NULL, recv_frame_buf);
recv_frame_buf = NULL;
}
if(send_frame_buf) {
msi_delete_fb(s->msi, send_frame_buf);
send_frame_buf = NULL;
}
if(opus_dec)
audio_coder_close(opus_dec);
}
static void opus_decode_thread(void *d)
{
struct opus_decode_struct *s = (struct opus_decode_struct *)d;
msi_get(s->msi);
if(s->direct_to_dac) {
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(s->audio_track)));
}
s->msi->enable = 1;
opus_decode(s);
if(s->direct_to_dac) {
s->audio_track.priority &= 0x3F;
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(s->audio_track)));
}
os_event_set(&s->event, coder_exit_event, NULL);
while((s->next_status != AUCODEC_EXIT) && (s->destroy_self == 0)) {
s->current_status = AUCODEC_END;
os_sleep_ms(5);
}
if(s->src_msi) {
msi_del_output(s->src_msi, NULL, s->msi->name);
s->src_msi = NULL;
}
if(s->next_status != AUCODEC_EXIT)
msi_destroy(s->msi);
msi_put(s->msi);
}
static int32_t opus_decode_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
{
int32_t ret = RET_OK;
struct opus_decode_struct *opus_decode_s = (struct opus_decode_struct *)(msi->priv);
switch(cmd_id) {
case MSI_CMD_AUCODER:
{
ret = RET_ERR;
if(opus_decode_s) {
uint32_t cmd_self = (uint32_t)param1;
switch(cmd_self) {
case MSI_AUCODER_PAUSE:
{
if(opus_decode_s->current_status == AUCODEC_RUN) {
opus_decode_s->next_status = AUCODEC_PAUSE;
}
ret = RET_OK;
break;
}
case MSI_AUCODER_CONTINUE:
{
if(opus_decode_s->current_status == AUCODEC_PAUSE) {
opus_decode_s->next_status = AUCODEC_RUN;
}
ret = RET_OK;
break;
}
case MSI_AUCODER_GET_STATUS:
{
*((uint32_t*)param2) = (uint32_t)(opus_decode_s->current_status);
ret = RET_OK;
break;
}
case MSI_AUCODER_SET_SPEED:
{
opus_decode_s->speed = (uint8_t)param2;
ret = msi_output_cmd(opus_decode_s->msi,MSI_CMD_AUTPC,MSI_AUTPC_SET_SPEED,(uint32_t)(opus_decode_s->speed));
break;
}
case MSI_AUCODER_GET_SPEED:
{
*((uint32_t*)param2) = (uint32_t)(opus_decode_s->speed);
ret = RET_OK;
break;
}
case MSI_AUCODER_SET_PITCH:
{
opus_decode_s->pitch = (uint8_t)param2;
ret = msi_output_cmd(opus_decode_s->msi,MSI_CMD_AUTPC,MSI_AUTPC_SET_PITCH,(uint32_t)(opus_decode_s->pitch));
break;
}
case MSI_AUCODER_GET_PITCH:
{
*((uint32_t*)param2) = (uint32_t)(opus_decode_s->pitch);
ret = RET_OK;
break;
}
case MSI_AUCODER_CLEAR_STREAM:
{
os_event_set(&opus_decode_s->event, coder_clear_event, NULL);
os_event_wait(&opus_decode_s->event, coder_clear_finish_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
msi_output_cmd(opus_decode_s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(opus_decode_s->audio_track)));
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_CLEAR_STREAM,(uint32_t)(&(opus_decode_s->audio_track)));
ret = RET_OK;
break;
}
case MSI_AUCODER_SET_SRCMSI:
{
if(opus_decode_s->src_msi) {
msi_del_output(opus_decode_s->src_msi, NULL, msi->name);
}
opus_decode_s->src_msi = NULL;
ret = msi_add_output((struct msi*)param2, NULL, msi->name);
if(ret == RET_OK) {
opus_decode_s->src_msi = (struct msi*)param2;
}
break;
}
case MSI_AUCODER_DIRECT_TO_DAC:
{
uint32_t direct_to_dac = param2;
if(direct_to_dac && opus_decode_s->direct_to_dac == 0) {
opus_decode_s->direct_to_dac = 1;
if(opus_decode_s->use_tpc == 0) {
msi_add_output(msi, NULL, "R_AUDAC");
}
else if(opus_decode_s->autpc_msi) {
msi_add_output(opus_decode_s->autpc_msi, NULL, "R_AUDAC");
}
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(opus_decode_s->audio_track)));
}
else if(opus_decode_s->direct_to_dac == 1) {
opus_decode_s->direct_to_dac = 0;
if(opus_decode_s->use_tpc == 0) {
msi_del_output(msi, NULL, "R_AUDAC");
}
else if(opus_decode_s->autpc_msi) {
msi_del_output(opus_decode_s->autpc_msi, NULL, "R_AUDAC");
}
opus_decode_s->audio_track.priority &= 0x3F;
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(opus_decode_s->audio_track)));
}
break;
}
case MSI_AUCODER_DEINIT:
{
msi_destroy(msi);
ret = RET_OK;
break;
}
default:
break;
}
}
break;
}
case MSI_CMD_TRANS_FB:
{
ret = RET_ERR;
struct framebuff *frame_buf = (struct framebuff *)param1;
if(frame_buf->mtype == F_AUDIO) {
ret = RET_OK;
}
break;
}
case MSI_CMD_FREE_FB:
{
ret = RET_ERR;
if(opus_decode_s) {
struct framebuff *frame_buf = (struct framebuff *)param1;
if(frame_buf->data) {
OPUS_CODE_FREE(frame_buf->data);
frame_buf->data = NULL;
}
fbpool_put(&opus_decode_s->tx_pool, frame_buf);
}
break;
}
case MSI_CMD_PRE_DESTROY:
{
if(opus_decode_s && opus_decode_s->task_hdl) {
opus_decode_s->next_status = AUCODEC_EXIT;
}
break;
}
case MSI_CMD_POST_DESTROY:
{
if(opus_decode_s) {
if(opus_decode_s->task_hdl) {
os_event_wait(&opus_decode_s->event, coder_exit_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
}
for(uint32_t i=0; i<MAX_OPUS_DECODE_TXBUF; i++) {
struct framebuff *frame_buf = (opus_decode_s->tx_pool.pool)+i;
if(frame_buf->data) {
OPUS_CODE_FREE(frame_buf->data);
frame_buf->data = NULL;
}
}
fbpool_destroy(&opus_decode_s->tx_pool);
if(opus_decode_s->event.hdl) {
os_event_del(&opus_decode_s->event);
}
if(opus_decode_s->autpc_msi) {
autpc_msi_deinit(opus_decode_s->autpc_msi);
opus_decode_s->autpc_msi = NULL;
}
if(opus_decode_s->msi_name) {
OPUS_CODE_FREE(opus_decode_s->msi_name);
opus_decode_s->msi_name = NULL;
}
OPUS_CODE_FREE(opus_decode_s);
opus_decode_s = NULL;
}
break;
}
default:
break;
}
return ret;
}
struct msi *opus_decode_init(uint32_t samplerate, AUDEC_INIT *audec_init)
{
#if AUDIO_EN
char *msi_name = NULL;
int32_t random_value = 0;
msi_name = (char*)OPUS_CODE_ZALLOC(sizeof(char)*32);
if(msi_name == NULL) {
os_printf("alloc autpc msi namefail\n");
return NULL;
}
os_random_bytes((uint8_t*)(&random_value), 4);
os_snprintf(msi_name, 20, "SR_OPUS_DECODE_""%04d", random_value);
struct msi *msi = msi_new(msi_name, MAX_OPUS_DECODE_RXBUF, NULL);
if(msi == NULL) {
OPUS_INFO("create opus decode msi fail!\r\n");
return NULL;
}
struct opus_decode_struct *opus_decode_s = (struct opus_decode_struct *)OPUS_CODE_ZALLOC(sizeof(struct opus_decode_struct));
if(!opus_decode_s) {
OPUS_INFO("opus_decode_s malloc fail!\r\n");
goto opus_decode_init_err;
}
msi->priv = opus_decode_s;
msi->action = (msi_action)opus_decode_msi_action;
fbpool_init(&opus_decode_s->tx_pool, MAX_OPUS_DECODE_TXBUF);
for(uint32_t i=0; i<MAX_OPUS_DECODE_TXBUF; i++) {
struct framebuff *frame_buf = (opus_decode_s->tx_pool.pool)+i;
frame_buf->data = NULL;
frame_buf->priv = &(opus_decode_s->audio_track);
}
if(os_event_init(&opus_decode_s->event) != RET_OK) {
OPUS_INFO("create opus decode event fail!\r\n");
goto opus_decode_init_err;
}
if(audec_init->src_msi && (msi_add_output(audec_init->src_msi, NULL, msi->name) != RET_OK)) {
goto opus_decode_init_err;
}
opus_decode_s->msi = msi;
opus_decode_s->msi_name = msi_name;
opus_decode_s->src_msi = audec_init->src_msi;
opus_decode_s->direct_to_dac = audec_init->direct_to_dac;
opus_decode_s->coder_sampleRate = samplerate;
opus_decode_s->use_tpc = audec_init->use_tpc;
opus_decode_s->speed = audec_init->speed;
opus_decode_s->pitch = audec_init->pitch;
opus_decode_s->destroy_self = audec_init->destroy_self;
opus_decode_s->audio_track.priority = audec_init->priority;
opus_decode_s->audio_track.track_type = audec_init->track_type;
opus_decode_s->next_status = AUCODEC_RUN;
opus_decode_s->current_status = AUCODEC_RUN;
if(audec_init->direct_to_dac && !opus_decode_s->use_tpc) {
msi_add_output(msi, NULL, "R_AUDAC");
}
os_printf("opus_track:%x\n",&(opus_decode_s->audio_track));
#if OPUS_DEC_CTRL == AUCODER_RUN_IN_CPU1
opus_decode_s->task_hdl = os_task_create("opus_decode_thread", opus_decode_thread, (void*)opus_decode_s, OS_TASK_PRIORITY_ABOVE_NORMAL, 0, NULL, 1024);
#else
opus_decode_s->task_hdl = os_task_create("opus_decode_thread", opus_decode_thread, (void*)opus_decode_s, OS_TASK_PRIORITY_NORMAL, 0, NULL, 2048);
#endif
if(opus_decode_s->task_hdl == NULL) {
OPUS_INFO("create opus decode task fail!\r\n");
goto opus_decode_init_err;
}
return msi;
opus_decode_init_err:
msi_destroy(msi);
#endif
return NULL;
}

View File

@@ -0,0 +1,378 @@
#include "basic_include.h"
#include "csi_kernel.h"
#include "lib/multimedia/msi.h"
#include "lib/multimedia/framebuff.h"
#include "lib/audio/audio_code/audio_code.h"
#include "opus_code.h"
#define MAX_OPUS_ENCODE_RXBUF 4
#define MAX_OPUS_ENCODE_TXBUF 14
#define FRAME_SIZE 160
struct opus_encode_struct {
struct fbpool tx_pool;
struct os_event event;
struct msi *msi;
struct msi *src_msi;
void *task_hdl;
uint8_t destroy_self;
uint8_t next_status;
uint8_t current_status;
uint8_t enc_buf[1024];
int16_t inbuf[FRAME_SIZE];
uint32_t samplerate;
uint32_t new_bitrate;
uint32_t cur_bitrate;
AUDIO_INFO audio_info;
};
static void opus_encode_thread(void *d)
{
uint8_t clear_finish = 1;
uint8_t get_audio_time = 0;
uint8_t update_audio_time = 0;
uint8_t *send_data = NULL;
int16_t *recv_data = NULL;
int32_t enc_bytes = 0;
int32_t ret = 0;
uint32_t data_len = 0;
uint32_t data_offset = 0;
uint32_t inbuf_offset = 0;
uint32_t inbuf_reslen = (FRAME_SIZE << 1);
uint32_t audio_time = 0;
uint32_t clear_flag = 0;
struct framebuff *send_frame_buf = NULL;
struct framebuff *recv_frame_buf = NULL;
struct opus_encode_struct *s = (struct opus_encode_struct *)d;
AUCODE_HDL *opus_enc = NULL;
s->msi->enable = 1;
msi_get(s->msi);
opus_enc = audio_coder_open(OPUS_ENC, s->samplerate, 1);
if (opus_enc == NULL)
goto opus_encode_thread_end;
s->audio_info.nsamples = FRAME_SIZE;
s->audio_info.time_interval = s->audio_info.nsamples * FRAME_SIZE / s->samplerate;
s->audio_info.samplerate = s->samplerate;
while(1) {
os_event_wait(&s->event, coder_clear_event, &clear_flag, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, 0);
if(clear_flag & coder_clear_event) {
clear_flag = 0;
clear_finish = 0;
}
if(s->next_status == AUCODEC_PAUSE) {
if(s->current_status == AUCODEC_RUN) {
audio_coder_close(opus_enc);
opus_enc = audio_coder_open(OPUS_ENC, s->samplerate, 1);
if(opus_enc == NULL)
goto opus_encode_thread_end;
}
s->current_status = AUCODEC_PAUSE;
inbuf_reslen = (FRAME_SIZE << 1);
inbuf_offset = 0;
}
if(s->cur_bitrate != s->new_bitrate) {
if(audio_encoder_set_bitrate(opus_enc, s->new_bitrate) == RET_OK) {
s->cur_bitrate = s->new_bitrate;
}
}
recv_frame_buf = msi_get_fb(s->msi, 0);
if(recv_frame_buf) {
if(clear_finish == 0) {
inbuf_reslen = (FRAME_SIZE << 1);
inbuf_offset = 0;
goto opus_encode_frame_end;
}
if(s->next_status == AUCODEC_PAUSE) {
goto opus_encode_frame_end;
}
else {
s->current_status = AUCODEC_RUN;
recv_data = (int16_t*)recv_frame_buf->data;
data_len = recv_frame_buf->len;
data_offset = 0;
if(!get_audio_time) {
get_audio_time = 1;
audio_time = recv_frame_buf->time;
}
if(update_audio_time) {
audio_time = recv_frame_buf->time;
update_audio_time = 0;
}
while(data_len >= inbuf_reslen) {
os_memcpy(s->inbuf + (inbuf_offset/2), recv_data + (data_offset/2), inbuf_reslen);
data_len -= inbuf_reslen;
data_offset += inbuf_reslen;
enc_bytes = audio_encode_data(opus_enc, s->inbuf, FRAME_SIZE, s->enc_buf);
inbuf_reslen = (FRAME_SIZE << 1);
inbuf_offset = 0;
while(!send_frame_buf) {
send_frame_buf = fbpool_get(&s->tx_pool, 0, s->msi);
if(!send_frame_buf)
os_sleep_ms(1);
}
if(send_frame_buf) {
send_frame_buf->data = (uint8_t*)OPUS_CODE_MALLOC(enc_bytes);
if(!send_frame_buf->data) {
OPUS_INFO("opus encode malloc send_frame_buf->data fail!\n");
msi_delete_fb(s->msi, send_frame_buf);
send_frame_buf = NULL;
goto opus_encode_frame_end;
}
send_data = send_frame_buf->data;
os_memcpy(send_data, s->enc_buf, enc_bytes);
send_frame_buf->len = enc_bytes;
send_frame_buf->mtype = F_AUDIO;
send_frame_buf->time = audio_time;
send_frame_buf->priv = &(s->audio_info);
ret = msi_output_fb(s->msi, send_frame_buf);
OPUS_DEBUG("opus encode send framebuff:%p,ret:%d\r\n",send_frame_buf,ret);
send_frame_buf = NULL;
}
audio_time += (FRAME_SIZE * 1000 / s->samplerate);
if(data_len == 0)
update_audio_time = 1;
opus_encode_frame_end:
os_sleep_ms(1);
}
if(data_len) {
os_memcpy(s->inbuf + (inbuf_offset/2), recv_data + (data_offset/2), data_len);
inbuf_reslen -= data_len;
inbuf_offset += data_len;
data_offset = 0;
data_len = 0;
}
}
OPUS_DEBUG("opus encode delete framebuff:%p,len:%d,\r\n",recv_frame_buf,recv_frame_buf->len);
msi_delete_fb(s->msi, recv_frame_buf);
recv_frame_buf = NULL;
}
else {
if(clear_finish == 0) {
clear_finish = 1;
os_event_set(&s->event, coder_clear_finish_event, NULL);
}
os_sleep_ms(1);
}
if(s->next_status == AUCODEC_EXIT) {
goto opus_encode_thread_end;
}
}
opus_encode_thread_end:
if(opus_enc)
audio_coder_close(opus_enc);
os_event_set(&s->event, coder_exit_event, NULL);
while((s->next_status != AUCODEC_EXIT) && (s->destroy_self == 0)) {
s->current_status = AUCODEC_END;
os_sleep_ms(5);
}
if(s->src_msi) {
msi_del_output(s->src_msi, NULL, s->msi->name);
s->src_msi = NULL;
}
if(s->next_status != AUCODEC_EXIT)
msi_destroy(s->msi);
msi_put(s->msi);
}
static int32_t opus_encode_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
{
int32_t ret = RET_OK;
struct opus_encode_struct *opus_encode_s = (struct opus_encode_struct*)(msi->priv);
switch(cmd_id) {
case MSI_CMD_AUCODER:
{
ret = RET_ERR;
if(opus_encode_s) {
uint32_t cmd_self = (uint32_t)param1;
switch(cmd_self) {
case MSI_AUCODER_PAUSE:
{
if(opus_encode_s->current_status == AUCODEC_RUN) {
opus_encode_s->next_status = AUCODEC_PAUSE;
}
ret = RET_OK;
break;
}
case MSI_AUCODER_CONTINUE:
{
if(opus_encode_s->current_status == AUCODEC_PAUSE) {
opus_encode_s->next_status = AUCODEC_RUN;
}
ret = RET_OK;
break;
}
case MSI_AUCODER_GET_STATUS:
{
*((uint32_t*)param2) = (uint32_t)(opus_encode_s->current_status);
ret = RET_OK;
break;
}
case MSI_AUCODER_SET_BITRATE:
{
opus_encode_s->new_bitrate = param2;
ret = RET_OK;
break;
}
case MSI_AUCODER_CLEAR_STREAM:
{
os_event_set(&opus_encode_s->event, coder_clear_event, NULL);
os_event_wait(&opus_encode_s->event, coder_clear_finish_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
ret = RET_OK;
break;
}
case MSI_AUCODER_SET_SRCMSI:
{
if(opus_encode_s->src_msi) {
msi_del_output(opus_encode_s->src_msi, NULL, msi->name);
}
opus_encode_s->src_msi = NULL;
ret = msi_add_output((struct msi*)param2, NULL, msi->name);
if(ret == RET_OK) {
opus_encode_s->src_msi = (struct msi*)param2;
}
break;
}
case MSI_AUCODER_DEINIT:
{
msi_destroy(msi);
ret = RET_OK;
break;
}
default:
break;
}
}
break;
}
case MSI_CMD_TRANS_FB:
{
ret = RET_ERR;
struct framebuff *frame_buf = (struct framebuff *)param1;
if(frame_buf->mtype == F_AUDIO) {
ret = RET_OK;
}
break;
}
case MSI_CMD_FREE_FB:
{
ret = RET_ERR;
if(opus_encode_s) {
struct framebuff *frame_buf = (struct framebuff *)param1;
if(frame_buf->data) {
OPUS_CODE_FREE(frame_buf->data);
frame_buf->data = NULL;
}
fbpool_put(&opus_encode_s->tx_pool, frame_buf);
}
break;
}
case MSI_CMD_PRE_DESTROY:
{
if(opus_encode_s && opus_encode_s->task_hdl) {
opus_encode_s->next_status = AUCODEC_EXIT;
}
break;
}
case MSI_CMD_POST_DESTROY:
{
if(opus_encode_s) {
if(opus_encode_s->task_hdl) {
os_event_wait(&opus_encode_s->event, coder_exit_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
}
for(uint32_t i=0; i<MAX_OPUS_ENCODE_TXBUF; i++) {
struct framebuff *frame_buf = (opus_encode_s->tx_pool.pool)+i;
if(frame_buf->data) {
OPUS_CODE_FREE(frame_buf->data);
frame_buf->data = NULL;
}
}
fbpool_destroy(&opus_encode_s->tx_pool);
if(opus_encode_s->event.hdl) {
os_event_del(&opus_encode_s->event);
}
OPUS_CODE_FREE(opus_encode_s);
opus_encode_s = NULL;
}
break;
}
default:
break;
}
return ret;
}
struct msi *opus_encode_init(uint32_t samplerate, AUENC_INIT *auenc_init)
{
#if AUDIO_EN
uint8_t msi_isnew = 0;
struct opus_encode_struct *opus_encode_s = NULL;
struct msi *msi = msi_new("SR_OPUS_ENCODE", MAX_OPUS_ENCODE_RXBUF, &msi_isnew);
if(msi && !msi_isnew) {
opus_encode_s = (struct opus_encode_struct*)(msi->priv);
if(opus_encode_s) {
if(samplerate != opus_encode_s->samplerate) {
OPUS_INFO("opus_encode_init conflict!\r\n");
goto opus_encode_init_err;
}
}
}
else if(msi && msi_isnew) {
opus_encode_s = (struct opus_encode_struct*)OPUS_CODE_ZALLOC(sizeof(struct opus_encode_struct));
if(!opus_encode_s) {
OPUS_INFO("opus_encode_s malloc fail!\r\n");
goto opus_encode_init_err;
}
msi->priv = opus_encode_s;
msi->action = (msi_action)opus_encode_msi_action;
fbpool_init(&opus_encode_s->tx_pool, MAX_OPUS_ENCODE_TXBUF);
for(uint32_t i=0; i<MAX_OPUS_ENCODE_TXBUF; i++) {
struct framebuff *frame_buf = (opus_encode_s->tx_pool.pool)+i;
frame_buf->data = NULL;
}
if(os_event_init(&opus_encode_s->event) != RET_OK) {
OPUS_INFO("create opus encode event fail!\r\n");
goto opus_encode_init_err;
}
if(auenc_init->src_msi && (msi_add_output(auenc_init->src_msi, NULL, msi->name) != RET_OK)) {
goto opus_encode_init_err;
}
opus_encode_s->msi = msi;
opus_encode_s->src_msi = auenc_init->src_msi;
opus_encode_s->samplerate = samplerate;
opus_encode_s->destroy_self = auenc_init->destroy_self;
opus_encode_s->next_status = AUCODEC_RUN;
opus_encode_s->current_status = AUCODEC_RUN;
}
else {
OPUS_INFO("create opus encode msi fail!\r\n");
return NULL;
}
if(msi_isnew) {
#if OPUS_ENC_CTRL == AUCODER_RUN_IN_CPU1
opus_encode_s->task_hdl = os_task_create("opus_encode_thread", opus_encode_thread, (void*)opus_encode_s, OS_TASK_PRIORITY_ABOVE_NORMAL, 0, NULL, 1024);
#else
opus_encode_s->task_hdl = os_task_create("opus_encode_thread", opus_encode_thread, (void*)opus_encode_s, OS_TASK_PRIORITY_BELOW_NORMAL, 0, NULL, 3072);
#endif
if(opus_encode_s->task_hdl == NULL) {
OPUS_INFO("create opus encode task fail!\r\n");
goto opus_encode_init_err;
}
}
return msi;
opus_encode_init_err:
msi_destroy(msi);
#endif
return NULL;
}

View File

@@ -0,0 +1,142 @@
#include "prompt_tone.h"
#include "audio_code_ctrl.h"
#define MAX_PROMPTTONE_TXBUF 4
static int32_t prompt_tone_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
{
int32_t ret = RET_OK;
PROMPT_TONE_STRUCT *tone_s = (PROMPT_TONE_STRUCT*)msi->priv;
switch(cmd_id) {
case MSI_CMD_FREE_FB:
{
ret = RET_ERR;
if(tone_s) {
struct framebuff *frame_buf = (struct framebuff *)param1;
fbpool_put(&tone_s->tx_pool, frame_buf);
}
break;
}
case MSI_CMD_POST_DESTROY:
{
if(tone_s) {
for(uint32_t i=0; i<MAX_PROMPTTONE_TXBUF; i++) {
struct framebuff *frame_buf = (tone_s->tx_pool.pool)+i;
if(frame_buf->data) {
PROMPTTONE_FREE(frame_buf->data);
frame_buf->data = NULL;
}
}
fbpool_destroy(&tone_s->tx_pool);
PROMPTTONE_FREE(tone_s);
}
break;
}
default:
break;
}
return ret;
}
void prompt_tone_task(void *d)
{
struct framebuff *frame_buf = NULL;
PROMPT_TONE_STRUCT *tone_s = (PROMPT_TONE_STRUCT*)d;
while(1) {
if(audio_code_get_status(tone_s->mp3_msi) == AUCODEC_END) {
msi_do_cmd(tone_s->mp3_msi, MSI_CMD_AUCODER, MSI_AUCODER_DEINIT, 0);
break;
}
frame_buf = fbpool_get(&tone_s->tx_pool, 0, NULL);
if(frame_buf) {
if(tone_s->tone_buf_offset >= tone_s->tone_buf_size) {
frame_buf->len = 0;
}
else if((tone_s->tone_buf_offset+1024) < tone_s->tone_buf_size) {
os_memcpy(frame_buf->data, tone_s->tone_buf+tone_s->tone_buf_offset, 1024);
frame_buf->len = 1024;
tone_s->tone_buf_offset += 1024;
}
else {
os_memcpy(frame_buf->data, tone_s->tone_buf+tone_s->tone_buf_offset,
tone_s->tone_buf_size-tone_s->tone_buf_offset);
frame_buf->len = tone_s->tone_buf_size-tone_s->tone_buf_offset;
tone_s->tone_buf_offset = tone_s->tone_buf_size;
}
frame_buf->msi = tone_s->msi;
frame_buf->mtype = F_AUDIO;
msi_get(frame_buf->msi);
msi_output_fb(tone_s->msi, frame_buf);
}
else
os_sleep_ms(1);
}
msi_destroy(tone_s->msi);
}
struct msi *play_prompt_tone(const uint8_t *tone_buf, uint32_t size)
{
uint8_t msi_isnew = 0;
struct framebuff *frame_buf = NULL;
struct msi *tone_msi = NULL;
struct msi *mp3_msi = NULL;
AUDEC_INIT audec_init;
tone_msi = msi_new("S_PROMPTTONE", MAX_PROMPTTONE_TXBUF, &msi_isnew);
if(tone_msi == NULL) {
os_printf("create prompt_tone msi fail\n");
return NULL;
}
if(tone_msi && !msi_isnew) {
os_printf("prompt_tone msi has been created\n");
return NULL;
}
PROMPT_TONE_STRUCT *tone_s = (PROMPT_TONE_STRUCT*)PROMPTTONE_ZALLOC(sizeof(PROMPT_TONE_STRUCT));
if(tone_s == NULL) {
os_printf("malloc tone_s fail!\n");
goto play_prompt_tone_err;
}
tone_s->msi = tone_msi;
tone_s->msi->enable = 1;
tone_s->msi->action = prompt_tone_msi_action;
tone_s->tone_buf = tone_buf;
tone_s->tone_buf_size = size;
fbpool_init(&tone_s->tx_pool, MAX_PROMPTTONE_TXBUF);
for(uint32_t i=0; i<MAX_PROMPTTONE_TXBUF; i++) {
frame_buf = (tone_s->tx_pool.pool)+i;
frame_buf->data = (uint8_t*)PROMPTTONE_MALLOC(sizeof(uint8_t) * 1024);
if(!frame_buf->data)
goto play_prompt_tone_err;
}
tone_s->msi->priv = tone_s;
audec_init.track_type = BELL_TRACK;
audec_init.priority = play_interruptible;
audec_init.direct_to_dac = 1;
audec_init.use_tpc = 0;
audec_init.destroy_self = 0;
audec_init.src_msi = tone_msi;
mp3_msi = audio_decode_init(MP3_DEC, 0, &audec_init);
if(mp3_msi == NULL) {
os_printf("tone_s create mp3 msi fail!\n");
goto play_prompt_tone_err;
}
msi_add_output(tone_msi, NULL, mp3_msi->name);
tone_s->mp3_msi = mp3_msi;
tone_s->task_hdl = os_task_create("prompt_tone_task", prompt_tone_task, (void*)tone_s, OS_TASK_PRIORITY_NORMAL, 0, NULL, 1024);
if(tone_s->task_hdl == NULL) {
os_printf("create tone_s task fail!\r\n");
goto play_prompt_tone_err;
}
return tone_msi;
play_prompt_tone_err:
if(tone_msi)
msi_destroy(tone_msi);
return NULL;
}
void play_prompt_tone_test(void)
{
play_prompt_tone(connect_mp3, 2969);
}

View File

@@ -0,0 +1,33 @@
#ifndef _PROMPT_TONE_H_
#define _PROMPT_TONE_H_
#include "basic_include.h"
#include "lib/heap/av_heap.h"
#include "lib/heap/av_psram_heap.h"
#include "lib/multimedia/msi.h"
#include "lib/multimedia/framebuff.h"
#ifdef PSRAM_HEAP
#define PROMPTTONE_MALLOC av_psram_malloc
#define PROMPTTONE_ZALLOC av_psram_zalloc
#define PROMPTTONE_FREE av_psram_free
#else
#define PROMPTTONE_MALLOC av_malloc
#define PROMPTTONE_ZALLOC av_zalloc
#define PROMPTTONE_FREE av_free
#endif
typedef struct {
const uint8_t *tone_buf;
void *task_hdl;
uint32_t tone_buf_size;
uint32_t tone_buf_offset;
struct fbpool tx_pool;
struct msi *msi;
struct msi *mp3_msi;
} PROMPT_TONE_STRUCT;
extern const uint8_t connect_mp3[];
extern const uint8_t disconnect_mp3[];
#endif

View File

@@ -0,0 +1,607 @@
#include "basic_include.h"
#include "prompt_tone.h"
const uint8_t connect_mp3[] = {
0xff, 0xf3, 0x2a, 0xc0, 0x00, 0x00, 0x00, 0x02,
0x5c, 0x00, 0x00, 0x00, 0x00, 0x12, 0x49, 0x10,
0x52, 0x45, 0x09, 0x20, 0x44, 0x3b, 0x00, 0x7c,
0x50, 0x9c, 0xd7, 0x63, 0xe9, 0x88, 0xbe, 0xdf,
0x74, 0xee, 0xef, 0x3f, 0xcf, 0xb5, 0x71, 0x9a,
0xcf, 0xff, 0xb1, 0xb8, 0x7e, 0x7d, 0xee, 0xa5,
0x9a, 0x7d, 0x82, 0x4d, 0x63, 0x9c, 0xcf, 0xdd,
0xca, 0x7b, 0x19, 0xf5, 0x35, 0x65, 0x14, 0xb4,
0x9a, 0xef, 0xfe, 0xf5, 0x86, 0xf3, 0xec, 0xfb,
0xe9, 0xff, 0xf3, 0x38, 0xc0, 0x3c, 0x00, 0x00,
0x02, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x02, 0x6e,
0x6e, 0x4f, 0x12, 0x7d, 0x98, 0x6f, 0x33, 0xff,
0xff, 0xf0, 0xe0, 0x30, 0x37, 0x9d, 0xaf, 0xda,
0xb1, 0xd5, 0x01, 0x3c, 0x51, 0x88, 0x53, 0x43,
0xd2, 0xb3, 0xde, 0x18, 0x57, 0x6a, 0x3f, 0xc9,
0xbd, 0x3c, 0x48, 0x2a, 0x28, 0xd6, 0x7f, 0xa0,
0x3f, 0x38, 0x8b, 0xae, 0x34, 0x09, 0x52, 0x57,
0xce, 0xe0, 0x02, 0x7d, 0x28, 0xaf, 0xa1, 0x43,
0x29, 0x7e, 0xcc, 0xa2, 0xb7, 0xcc, 0xbf, 0xea,
0xcc, 0x3e, 0xf1, 0xa4, 0x38, 0x09, 0x91, 0x6a,
0x6f, 0xed, 0x2d, 0xec, 0xb1, 0xff, 0xc7, 0x5d,
0xde, 0xbb, 0x96, 0xff, 0xbf, 0xfd, 0xb9, 0xba,
0x6b, 0xf9, 0x6a, 0xaf, 0xda, 0xff, 0xf3, 0x2a,
0xc0, 0x9b, 0x00, 0x00, 0x02, 0x5c, 0x01, 0x40,
0x00, 0x00, 0xe5, 0x5a, 0x48, 0x55, 0xfc, 0x1a,
0x50, 0xa9, 0x12, 0xdc, 0xa3, 0xeb, 0xfb, 0x26,
0xdd, 0xaf, 0x34, 0xcb, 0x3f, 0xff, 0x52, 0x10,
0xaa, 0xff, 0x5e, 0xa2, 0x8f, 0xff, 0x58, 0xb8,
0x5a, 0xaa, 0xeb, 0xeb, 0x93, 0x00, 0x36, 0x7d,
0x74, 0x59, 0x07, 0x6a, 0x08, 0x9a, 0xea, 0xbb,
0xa9, 0x74, 0xd9, 0x24, 0x4f, 0x4c, 0x53, 0x44,
0x42, 0x61, 0x3f, 0x01, 0x14, 0x00, 0xff, 0xf3,
0x38, 0xc0, 0xd7, 0x1a, 0xb9, 0x72, 0xa9, 0x97,
0x8b, 0xc3, 0x02, 0x77, 0xc1, 0x86, 0x32, 0x22,
0xa1, 0x97, 0xb0, 0xe9, 0x10, 0xea, 0x84, 0xa7,
0x4f, 0xf0, 0x20, 0xcc, 0x44, 0xf1, 0xef, 0xbc,
0xf0, 0xa4, 0xa7, 0x37, 0x21, 0x38, 0xae, 0x6e,
0x32, 0x58, 0xb3, 0x59, 0xe9, 0x2e, 0x94, 0x51,
0xb8, 0x6b, 0x96, 0x28, 0x04, 0xd0, 0x2a, 0xb5,
0xc8, 0x93, 0xff, 0xd4, 0xc2, 0x83, 0x95, 0xb1,
0x9a, 0x94, 0x06, 0x5e, 0x32, 0xce, 0x50, 0x0a,
0xaf, 0xf4, 0xd2, 0x53, 0xa6, 0xb5, 0xa0, 0xee,
0xee, 0xce, 0x85, 0x2b, 0xdd, 0xaa, 0x52, 0x09,
0x12, 0x2b, 0x1f, 0x01, 0x1b, 0x0e, 0x14, 0x97,
0xfe, 0x5e, 0x91, 0xc2, 0xcd, 0xac, 0x5a, 0xc9,
0xbc, 0x41, 0xff, 0xf3, 0x2a, 0xc0, 0xcb, 0x13,
0x69, 0x4e, 0xb1, 0x8f, 0xc2, 0xd0, 0x02, 0x58,
0x67, 0xab, 0x71, 0x02, 0x89, 0x29, 0x01, 0x20,
0x75, 0x2b, 0x76, 0xbb, 0x88, 0xcc, 0x35, 0xe5,
0x54, 0xae, 0x86, 0x81, 0x88, 0x5c, 0x9c, 0x74,
0xb3, 0x12, 0xc1, 0xdd, 0x2f, 0x8a, 0x6e, 0x2d,
0xd2, 0x55, 0x9e, 0x50, 0x4a, 0x50, 0x00, 0x6b,
0xfe, 0xeb, 0x5f, 0x2d, 0xa7, 0x2a, 0xb2, 0x34,
0xb7, 0xda, 0xfd, 0xf1, 0xda, 0x9a, 0x71, 0x58,
0xb8, 0xf2, 0xe5, 0xff, 0xf3, 0x38, 0xc0, 0xb9,
0x15, 0x39, 0x3e, 0xb1, 0x96, 0xa0, 0xf1, 0x2a,
0x94, 0x22, 0xfe, 0x2d, 0x8b, 0xb2, 0xfa, 0xa7,
0x4e, 0x20, 0x60, 0x8a, 0xcf, 0xdd, 0x6b, 0x4d,
0x68, 0x9e, 0x66, 0x6a, 0x2f, 0xb6, 0x70, 0x0f,
0x04, 0x49, 0x4e, 0x6e, 0xfe, 0x90, 0x45, 0x22,
0xa0, 0xe3, 0x58, 0xd3, 0xa4, 0x9f, 0x0d, 0x6f,
0x67, 0xac, 0x70, 0xa3, 0x6c, 0x10, 0x2d, 0xbb,
0x35, 0x4c, 0x17, 0xa6, 0x71, 0xba, 0x80, 0x05,
0x96, 0x51, 0x96, 0x52, 0x80, 0x1b, 0xff, 0xf9,
0xfa, 0xb6, 0x87, 0xf6, 0x7b, 0xdd, 0xe2, 0x61,
0xb8, 0xba, 0x98, 0xae, 0xe2, 0x58, 0x5e, 0x67,
0x1e, 0xc4, 0x8a, 0xf6, 0xfa, 0xfd, 0x6f, 0x64,
0xf6, 0xa2, 0x93, 0xa9, 0x15, 0xaa, 0xe8, 0xff,
0xf3, 0x2a, 0xc0, 0xc3, 0x12, 0x79, 0x36, 0x9d,
0x76, 0x98, 0xf1, 0x46, 0x19, 0xd2, 0xa2, 0x4a,
0x00, 0x6c, 0x26, 0x1b, 0x5c, 0x86, 0x3e, 0xfd,
0xc0, 0x73, 0x0e, 0x6e, 0x53, 0x2e, 0xdb, 0xbd,
0x1a, 0x9c, 0xc3, 0x8d, 0x1d, 0x28, 0xba, 0x6c,
0x33, 0x59, 0x6a, 0xda, 0xde, 0xb0, 0x7f, 0x94,
0x92, 0x94, 0x00, 0x67, 0x77, 0x39, 0xdd, 0x75,
0x22, 0xad, 0x55, 0xdc, 0x8a, 0xae, 0x42, 0xad,
0x57, 0x4d, 0x03, 0xaa, 0x22, 0xe5, 0x11, 0x0a,
0xff, 0xf3, 0x38, 0xc0, 0xb5, 0x14, 0x11, 0x36,
0x95, 0x76, 0x36, 0x65, 0x02, 0x81, 0xda, 0x23,
0x22, 0x5b, 0x46, 0xdf, 0x52, 0x0a, 0xa0, 0x7d,
0x14, 0x4f, 0x2c, 0xfa, 0x6c, 0x82, 0xdd, 0x06,
0x4c, 0xc9, 0x6e, 0x9b, 0xb1, 0x80, 0xe4, 0x01,
0xb8, 0x22, 0xe1, 0x36, 0x94, 0x47, 0xf9, 0x56,
0x12, 0x2d, 0x4a, 0xda, 0xe7, 0x5f, 0xed, 0xf2,
0xa0, 0x42, 0xaf, 0x66, 0x01, 0xf9, 0xb5, 0xad,
0x00, 0x43, 0x2c, 0x35, 0x17, 0x5e, 0x40, 0xd2,
0xc3, 0xeb, 0x00, 0x5e, 0x7e, 0x0f, 0x33, 0x45,
0x3b, 0xc7, 0x6f, 0x6d, 0x39, 0xf7, 0xaf, 0xe4,
0xe6, 0x1d, 0xa0, 0x10, 0x25, 0xff, 0x8c, 0xb8,
0x0c, 0x5a, 0xbb, 0x83, 0xd7, 0x09, 0xd4, 0xe3,
0xe7, 0x11, 0x50, 0x6c, 0xff, 0xf3, 0x2a, 0xc0,
0xc3, 0x12, 0x61, 0x36, 0x9d, 0x96, 0x46, 0xa1,
0x02, 0xee, 0x6f, 0xfb, 0x63, 0xe9, 0x21, 0x88,
0x73, 0x95, 0xa4, 0x52, 0xe6, 0x0d, 0x6f, 0xf5,
0xfd, 0xe1, 0xa2, 0x3a, 0x6b, 0xdb, 0x77, 0x25,
0x98, 0x44, 0xc1, 0x5b, 0xbf, 0x56, 0x6a, 0xe3,
0x5a, 0xdf, 0xff, 0xff, 0xfc, 0xf7, 0xff, 0xff,
0xdd, 0xd6, 0x8f, 0xe7, 0x1d, 0xcc, 0x3c, 0xf2,
0x39, 0x9e, 0xeb, 0xbf, 0x9f, 0xfe, 0xef, 0xd6,
0x59, 0x7f, 0xac, 0x40, 0x60, 0xff, 0xf3, 0x38,
0xc0, 0xb5, 0x13, 0x59, 0x3e, 0x98, 0xd7, 0x45,
0x98, 0x02, 0x03, 0x93, 0x64, 0xdf, 0x8b, 0x8b,
0xb4, 0x9a, 0xee, 0x1d, 0x57, 0xa6, 0x60, 0x78,
0x00, 0xc0, 0x03, 0x09, 0xf8, 0x0f, 0x8d, 0x0c,
0x2a, 0x5d, 0x40, 0xc9, 0x27, 0x71, 0xf4, 0x1a,
0x0a, 0x4b, 0x6a, 0xe6, 0xaa, 0x2f, 0x24, 0xba,
0x24, 0xea, 0x4c, 0x5d, 0x2e, 0x08, 0xe0, 0x31,
0x50, 0xa0, 0x85, 0xcc, 0x7f, 0xb7, 0xeb, 0xa2,
0x51, 0x20, 0x89, 0x7f, 0xff, 0xff, 0xff, 0xf5,
0xa4, 0x70, 0xd8, 0xf7, 0xff, 0xff, 0xfc, 0x35,
0x22, 0x40, 0x4a, 0xa8, 0x09, 0xaf, 0x03, 0x00,
0x06, 0x37, 0xb9, 0x76, 0x06, 0x62, 0xa5, 0x59,
0xcc, 0x3f, 0xad, 0x21, 0x84, 0x11, 0x54, 0x60,
0x87, 0xff, 0xf3, 0x2a, 0xc0, 0xc6, 0x18, 0x79,
0x62, 0xc1, 0x97, 0x88, 0xc8, 0x02, 0xb9, 0xf1,
0x7c, 0x32, 0x6a, 0x5a, 0x48, 0x4d, 0x54, 0xce,
0x8a, 0xea, 0x36, 0xd2, 0x2c, 0x01, 0x51, 0xa4,
0x4c, 0x96, 0x27, 0x9d, 0x25, 0xf6, 0x5a, 0xea,
0xb3, 0x9d, 0x13, 0xd1, 0x22, 0xff, 0xdb, 0x43,
0x55, 0x9c, 0x84, 0x92, 0xf6, 0xf5, 0xdb, 0x1a,
0x0a, 0x24, 0xe7, 0x7f, 0xff, 0xff, 0xfc, 0x4a,
0xfa, 0xf9, 0x52, 0xbf, 0xbf, 0x80, 0x14, 0x6c,
0xc2, 0x7e, 0xff, 0xf3, 0x38, 0xc0, 0xa0, 0x13,
0x31, 0xd2, 0xc1, 0x77, 0xc8, 0x98, 0x02, 0x15,
0x41, 0x49, 0x23, 0xee, 0x90, 0xb7, 0x03, 0x5f,
0x05, 0xa7, 0xad, 0x1b, 0x5a, 0x5f, 0x0d, 0x39,
0xdb, 0xff, 0xad, 0x25, 0xb1, 0x78, 0x1a, 0x48,
0x61, 0x33, 0xaf, 0x57, 0xf9, 0xd6, 0xbd, 0x47,
0x7a, 0x32, 0xd4, 0x0f, 0x8b, 0x5c, 0xef, 0x4f,
0xa3, 0x8b, 0xa5, 0xab, 0x38, 0xd5, 0x55, 0x91,
0x15, 0x7c, 0xcb, 0xca, 0x23, 0x90, 0xb9, 0x75,
0x50, 0xde, 0xe5, 0x80, 0x7e, 0xbd, 0x59, 0xaf,
0x97, 0x80, 0x1c, 0xa7, 0x0f, 0x22, 0x20, 0x92,
0x21, 0xe3, 0xb2, 0xcf, 0x0d, 0xb0, 0x68, 0xd8,
0x1b, 0x1a, 0x37, 0x6e, 0x8a, 0x21, 0xa4, 0x36,
0x0f, 0x59, 0x4f, 0xa9, 0x7d, 0x49, 0xff, 0xf3,
0x2a, 0xc0, 0xb2, 0x12, 0x39, 0xd2, 0xb1, 0x96,
0x2d, 0x0a, 0xda, 0x33, 0xc8, 0xa0, 0x24, 0xdd,
0x25, 0x77, 0x7f, 0xf9, 0x99, 0x14, 0xd7, 0x58,
0x72, 0xd8, 0x08, 0x8a, 0xc2, 0x4b, 0x8a, 0x2a,
0x8b, 0x2f, 0x59, 0x17, 0xd5, 0xa3, 0xc0, 0xc4,
0x3d, 0xbf, 0xd6, 0x3f, 0xb7, 0x73, 0xa8, 0x40,
0x59, 0xa8, 0x05, 0x6b, 0x77, 0x00, 0x19, 0x77,
0xa4, 0xd2, 0x4c, 0xa4, 0x62, 0x3a, 0x19, 0x51,
0xfa, 0x03, 0x6c, 0x21, 0x54, 0x0a, 0x08, 0xff,
0xf3, 0x38, 0xc0, 0xa5, 0x11, 0x89, 0x3a, 0xbd,
0x96, 0x0c, 0xde, 0xd6, 0x3d, 0xf4, 0x49, 0x91,
0x2d, 0x2d, 0x5e, 0xd4, 0xea, 0xdd, 0x4b, 0x6a,
0x42, 0xf4, 0x0d, 0x43, 0x74, 0xaa, 0xaf, 0xf7,
0xa1, 0x49, 0x01, 0x86, 0x5e, 0x4c, 0xdb, 0x23,
0xcc, 0x11, 0xdc, 0xd9, 0x26, 0xde, 0x44, 0x80,
0xc5, 0x9e, 0xa9, 0x34, 0x5d, 0xf3, 0x0d, 0x8a,
0xac, 0xf1, 0x85, 0xfb, 0xde, 0xad, 0x20, 0x7f,
0xfd, 0x9a, 0xff, 0x9b, 0x80, 0xb4, 0x36, 0x49,
0x42, 0x43, 0x11, 0x26, 0x9c, 0x67, 0xb1, 0xb0,
0xb7, 0x00, 0xf9, 0x80, 0x14, 0x64, 0xb0, 0xb5,
0x69, 0xe3, 0x9b, 0x43, 0x56, 0xd7, 0x75, 0xba,
0x49, 0x32, 0xce, 0x88, 0xec, 0x9c, 0xb5, 0x55,
0xe6, 0xa3, 0x4e, 0xff, 0xf3, 0x2a, 0xc0, 0xbd,
0x11, 0xa9, 0x3a, 0xb1, 0x96, 0x0d, 0x1a, 0xc6,
0x55, 0x9e, 0x19, 0x01, 0x13, 0x50, 0x85, 0xde,
0xe7, 0x1d, 0x43, 0xf8, 0xcd, 0x9b, 0xb5, 0xae,
0xfb, 0x7d, 0xa6, 0x10, 0x75, 0xcc, 0x00, 0xa3,
0xec, 0x1f, 0x41, 0x3b, 0x52, 0xaa, 0xb9, 0x5a,
0xbf, 0x97, 0x80, 0x26, 0x3f, 0xa9, 0x6c, 0x65,
0xcc, 0xc8, 0x89, 0xe9, 0x33, 0x3a, 0xcf, 0x8a,
0x58, 0x05, 0xc9, 0x00, 0x34, 0xf1, 0xdc, 0x8b,
0xb7, 0x50, 0x75, 0x8a, 0xff, 0xf3, 0x38, 0xc0,
0xb2, 0x12, 0x59, 0x3a, 0xa5, 0x96, 0x2d, 0x22,
0xc6, 0x8d, 0x53, 0xad, 0xea, 0xa6, 0xb7, 0x53,
0x32, 0x83, 0xfe, 0x03, 0x41, 0x8c, 0x7a, 0xd5,
0xfe, 0x99, 0x7f, 0x14, 0x2b, 0x75, 0xfc, 0x2b,
0x06, 0x5c, 0x2e, 0x50, 0x55, 0x62, 0xba, 0xe5,
0xd5, 0xe8, 0x31, 0x5b, 0xff, 0xae, 0x8b, 0x77,
0xfd, 0x26, 0x0c, 0x1b, 0x73, 0xd0, 0x64, 0x5e,
0x69, 0x58, 0xa4, 0xdb, 0x80, 0x39, 0xab, 0x37,
0x13, 0x9b, 0x1d, 0xa0, 0x1e, 0xb5, 0x90, 0xd2,
0x04, 0x28, 0x40, 0x37, 0x20, 0x09, 0x26, 0xef,
0x21, 0xe2, 0x03, 0x8c, 0x44, 0xe8, 0xa2, 0xc9,
0xdd, 0x07, 0xd1, 0x5a, 0x4a, 0x16, 0x90, 0xb1,
0x91, 0xde, 0x1e, 0x5e, 0x57, 0x2a, 0x2d, 0x57,
0xff, 0xf3, 0x2a, 0xc0, 0xc7, 0x12, 0x39, 0x32,
0xb5, 0x96, 0x0d, 0x14, 0xd2, 0x40, 0x08, 0x1c,
0x3f, 0x92, 0x06, 0x81, 0xf3, 0xc0, 0x20, 0x01,
0xf7, 0x8f, 0x25, 0x85, 0x5a, 0xa0, 0x08, 0x88,
0xac, 0x54, 0xb1, 0x5a, 0xbf, 0x43, 0x29, 0xfe,
0x2b, 0x53, 0x98, 0x05, 0x3c, 0x88, 0x6a, 0x31,
0xd2, 0x62, 0x84, 0x23, 0x3a, 0xe5, 0x13, 0x30,
0x16, 0x80, 0x8d, 0x13, 0xaf, 0x4a, 0xcc, 0x3e,
0x48, 0x54, 0x6b, 0xaf, 0x55, 0x05, 0x59, 0x6a,
0x43, 0xff, 0xf3, 0x38, 0xc0, 0xba, 0x13, 0x31,
0x3e, 0xad, 0x96, 0x1d, 0x18, 0xd6, 0x0b, 0x38,
0x1e, 0x26, 0x76, 0xb1, 0x3b, 0x17, 0x73, 0xa8,
0xd0, 0x04, 0x0c, 0x09, 0x38, 0x50, 0x54, 0x89,
0x02, 0xc3, 0x83, 0xee, 0x84, 0xea, 0x46, 0xf9,
0x82, 0xc9, 0x48, 0xf4, 0xb8, 0xd3, 0xd0, 0xea,
0x9a, 0x84, 0x3d, 0xbf, 0xf2, 0x25, 0x58, 0xca,
0x75, 0x00, 0x55, 0x6c, 0xb5, 0x4e, 0x60, 0x08,
0x72, 0xcc, 0x54, 0x64, 0x35, 0x22, 0x0e, 0x1a,
0x08, 0x1f, 0x2e, 0x0c, 0xb8, 0x24, 0x90, 0x58,
0x11, 0x75, 0xab, 0x62, 0x89, 0x10, 0x65, 0x21,
0xe8, 0xa6, 0xf5, 0x5f, 0x5a, 0x83, 0xda, 0x22,
0x9c, 0x4a, 0x57, 0xc2, 0xf5, 0x0d, 0xd1, 0x28,
0x12, 0xb8, 0xec, 0xe1, 0xd3, 0xff, 0xf3, 0x2a,
0xc0, 0xcc, 0x12, 0xc1, 0x36, 0xa7, 0x86, 0x0d,
0x0a, 0xd2, 0xc5, 0xa1, 0x55, 0xd2, 0x96, 0x80,
0x14, 0x72, 0xb4, 0x39, 0xb1, 0x94, 0xa5, 0xf6,
0x7c, 0x3c, 0xca, 0xbf, 0xd6, 0x64, 0x95, 0xf5,
0x80, 0x56, 0xa9, 0x5a, 0xaf, 0x77, 0x00, 0xe6,
0x4a, 0x7b, 0x7a, 0x3f, 0x34, 0x1b, 0x85, 0xc3,
0xa9, 0x64, 0x60, 0xd2, 0x03, 0x3d, 0x00, 0x6f,
0x04, 0x83, 0x3a, 0x90, 0x65, 0xc4, 0xfa, 0xca,
0x7e, 0x8b, 0xb2, 0x74, 0xd0, 0x52, 0xff, 0xf3,
0x38, 0xc0, 0xbd, 0x13, 0x49, 0x36, 0x98, 0xd6,
0x0c, 0x4a, 0xd2, 0x6e, 0x5f, 0x29, 0x87, 0x44,
0x2e, 0x13, 0x1b, 0x53, 0xee, 0x59, 0x2e, 0xb9,
0x44, 0x34, 0xd2, 0x66, 0x62, 0xb0, 0x28, 0x40,
0x44, 0x75, 0x87, 0x0b, 0x01, 0xca, 0x19, 0x69,
0x73, 0x49, 0xb2, 0xc0, 0xf5, 0x3f, 0x86, 0xc0,
0xe2, 0x72, 0xee, 0x40, 0x61, 0x6c, 0x4f, 0x70,
0x7a, 0x80, 0x7a, 0xa5, 0x59, 0xab, 0x77, 0x81,
0x12, 0x20, 0xa3, 0x41, 0x64, 0xcc, 0x88, 0x44,
0x4d, 0xcf, 0x59, 0x7d, 0x1b, 0xfc, 0xf0, 0x00,
0x8b, 0x96, 0x37, 0xf1, 0xe3, 0x79, 0x02, 0xbe,
0xa3, 0x7b, 0x63, 0xae, 0x7f, 0x9f, 0x93, 0x10,
0x61, 0xd7, 0x0e, 0x67, 0x4d, 0xbd, 0xb5, 0xde,
0xe6, 0x28, 0xff, 0xf3, 0x2a, 0xc0, 0xce, 0x12,
0x49, 0x3e, 0x9d, 0x76, 0x0d, 0x10, 0xd2, 0x74,
0x6a, 0x8f, 0x69, 0x72, 0x90, 0xfb, 0x52, 0x5d,
0x0f, 0x34, 0x41, 0x72, 0x68, 0xb8, 0xfe, 0xcf,
0x91, 0xb7, 0xd3, 0xa3, 0x24, 0x40, 0xfd, 0x46,
0x49, 0x26, 0xe2, 0x3d, 0xcc, 0xe0, 0x6a, 0xf1,
0xca, 0xc2, 0x77, 0x2e, 0xf7, 0xa0, 0x98, 0x9f,
0x05, 0xdc, 0x56, 0x46, 0xcb, 0x55, 0x44, 0xe9,
0x24, 0xe5, 0xda, 0x08, 0xaa, 0x83, 0x50, 0x49,
0x23, 0x14, 0x10, 0xff, 0xf3, 0x38, 0xc0, 0xc0,
0x14, 0xe1, 0x6a, 0xa1, 0x96, 0x1c, 0xc4, 0xd2,
0x14, 0x28, 0x68, 0x2c, 0xc2, 0x15, 0xe2, 0x1b,
0x21, 0xa3, 0xa9, 0x13, 0x99, 0x11, 0xef, 0x63,
0xc8, 0xda, 0xe4, 0x48, 0xf9, 0x1c, 0xdf, 0x81,
0x90, 0x1a, 0x79, 0x70, 0xe9, 0x21, 0x77, 0x86,
0xd0, 0x5c, 0xa9, 0x4b, 0x4d, 0xd5, 0xc8, 0x80,
0x56, 0xa6, 0x09, 0x37, 0x24, 0xf0, 0x8e, 0x6c,
0x46, 0xb9, 0xd7, 0x51, 0xea, 0x9e, 0x49, 0x62,
0xc3, 0x73, 0x59, 0x35, 0x40, 0x7f, 0x11, 0xc8,
0x38, 0xce, 0x31, 0x8c, 0xed, 0x25, 0x8c, 0xfb,
0x53, 0xe3, 0xee, 0xd8, 0xb7, 0xd6, 0xa4, 0xdb,
0x01, 0x11, 0x75, 0x3c, 0xa4, 0x3b, 0x99, 0x5a,
0xa4, 0x34, 0xc1, 0x74, 0xc9, 0x38, 0x91, 0xff,
0xf3, 0x2a, 0xc0, 0xcb, 0x11, 0xb1, 0x32, 0xa5,
0x96, 0x0e, 0x16, 0xc6, 0xcd, 0xc8, 0xce, 0x62,
0xa9, 0x05, 0x1c, 0x06, 0x60, 0x4d, 0x70, 0x74,
0xb7, 0x80, 0x67, 0x4d, 0xda, 0xcd, 0xd4, 0xad,
0xcb, 0x5b, 0x69, 0xfd, 0x46, 0x49, 0x24, 0xa3,
0xc3, 0x8d, 0x92, 0x92, 0x53, 0x24, 0x8e, 0xa2,
0xe1, 0x39, 0x67, 0x1e, 0x11, 0xe0, 0x29, 0xe0,
0xfd, 0xce, 0xfd, 0xa9, 0x6f, 0xd5, 0xee, 0xbd,
0x74, 0xe5, 0x0f, 0x19, 0x7d, 0x9b, 0xd2, 0x2e,
0xff, 0xf3, 0x38, 0xc0, 0xc0, 0x13, 0x09, 0x9e,
0x9b, 0x5e, 0x1c, 0xc6, 0xee, 0x99, 0xff, 0x42,
0x89, 0x0a, 0x3c, 0x0c, 0xa7, 0x56, 0x9c, 0x1c,
0x0f, 0xd1, 0x6b, 0x1d, 0x0f, 0x89, 0x26, 0xcb,
0x70, 0x45, 0xcd, 0x39, 0x84, 0x82, 0xc2, 0xa1,
0x06, 0x5a, 0x1b, 0x0d, 0xb5, 0xc4, 0x0b, 0x15,
0xff, 0xdd, 0x68, 0xbf, 0x48, 0xaa, 0xaa, 0x69,
0xb6, 0xdb, 0xa8, 0xd6, 0xba, 0x5e, 0x86, 0x86,
0x56, 0x24, 0xc8, 0x99, 0x98, 0xd1, 0x84, 0x03,
0x5d, 0x1d, 0xaf, 0xa0, 0x7d, 0x34, 0xc8, 0xd2,
0xd1, 0xaa, 0x0e, 0xba, 0x13, 0xee, 0xe8, 0x31,
0x79, 0x8c, 0xcf, 0x1a, 0x24, 0x43, 0x43, 0xb7,
0x89, 0xb7, 0xdd, 0x33, 0x4d, 0x85, 0xbd, 0xe7,
0xfc, 0x4e, 0xbf, 0x4d, 0xff, 0xf3, 0x2a, 0xc0,
0xd2, 0x13, 0x81, 0x86, 0x93, 0x86, 0x1b, 0xca,
0xd0, 0xed, 0x97, 0x54, 0x14, 0x43, 0x05, 0xc9,
0x04, 0xc1, 0xb5, 0xa6, 0x31, 0x26, 0xe0, 0xa7,
0x77, 0xe3, 0xdc, 0x79, 0x17, 0xb2, 0xb0, 0xf0,
0x2b, 0x52, 0x74, 0x04, 0xd2, 0x9d, 0x7a, 0xf9,
0xa5, 0xd7, 0x7b, 0x8d, 0xff, 0x3a, 0x86, 0xca,
0x06, 0x53, 0x5f, 0x33, 0xdf, 0x76, 0xff, 0x2b,
0x33, 0xea, 0xb8, 0x34, 0x55, 0x0c, 0x68, 0x3e,
0x4c, 0xca, 0x08, 0xc7, 0xae, 0xff, 0xf3, 0x38,
0xc0, 0xc0, 0x13, 0x29, 0x5e, 0x97, 0x5e, 0x1b,
0xc6, 0xd2, 0x57, 0x26, 0x8c, 0xbe, 0x2c, 0x80,
0x22, 0x05, 0xe4, 0x45, 0x10, 0x04, 0x24, 0x01,
0xdc, 0x92, 0x24, 0x73, 0x45, 0xe6, 0x3c, 0xcc,
0x6b, 0xca, 0x5c, 0x33, 0x31, 0x94, 0xd5, 0x95,
0x6b, 0x65, 0xf5, 0x09, 0xda, 0x91, 0xcc, 0x20,
0xbe, 0xef, 0xad, 0x85, 0x01, 0x02, 0x1c, 0xc1,
0x00, 0xf8, 0xb6, 0xa5, 0x10, 0x6b, 0xfe, 0xfe,
0x04, 0x24, 0xd0, 0x9b, 0x5d, 0x55, 0x56, 0x95,
0x57, 0x6d, 0x55, 0x54, 0x39, 0x01, 0x10, 0x01,
0x05, 0xa9, 0x99, 0x98, 0x58, 0xe0, 0x93, 0xc3,
0xb6, 0x58, 0xa0, 0x68, 0xeb, 0xca, 0xb8, 0xa8,
0x2a, 0x0a, 0x9d, 0x54, 0x88, 0x2a, 0x0a, 0x89,
0x81, 0xff, 0xf3, 0x2a, 0xc0, 0xd2, 0x13, 0x21,
0x42, 0xa7, 0x86, 0x1c, 0x8c, 0xee, 0xa0, 0x69,
0xe5, 0x8b, 0x3d, 0xde, 0x78, 0xb7, 0xf0, 0xee,
0x47, 0xc9, 0x5c, 0x35, 0xc9, 0xca, 0x9d, 0x59,
0xdf, 0xf8, 0x88, 0x01, 0x68, 0x84, 0x5a, 0xab,
0x51, 0x33, 0xe5, 0x12, 0xe0, 0xef, 0xa9, 0xff,
0xff, 0xfd, 0x4b, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf3, 0x38, 0xc0, 0xc1, 0x15,
0x69, 0xce, 0x88, 0xd6, 0x1b, 0xc6, 0xca, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3,
0x2a, 0xc0, 0xca, 0x10, 0xf0, 0x92, 0x7e, 0x36,
0x08, 0x50, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xf3, 0x38, 0xc0, 0xc2, 0x08, 0x80, 0x76, 0x35,
0x88, 0x00, 0xc4, 0x84, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xf3, 0x2a, 0xc0, 0xff,
0x0f, 0x00, 0x02, 0x5c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xf3, 0x38, 0xc0,
0xff, 0x17, 0xc0, 0x02, 0x5c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xf3, 0x2a, 0xc0, 0xff, 0x0f, 0x00, 0x02,
0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00
};
const uint8_t disconnect_mp3[] = {
0xff, 0xf3, 0x2a, 0xc0, 0x00, 0x0c, 0xd0, 0x02,
0x3e, 0x5f, 0x40, 0x00, 0x02, 0x96, 0xdd, 0xae,
0xd1, 0x14, 0x24, 0xb7, 0x00, 0x18, 0x2e, 0x1f,
0x10, 0x14, 0x0c, 0x02, 0x00, 0x80, 0xd0, 0x42,
0xf1, 0x03, 0x94, 0x71, 0xb0, 0xfa, 0xb9, 0x78,
0x80, 0xe0, 0x20, 0xb0, 0xff, 0xff, 0xcb, 0xbc,
0x3f, 0xf8, 0x81, 0xc0, 0x87, 0xf9, 0xfc, 0x3e,
0x5c, 0xff, 0xf2, 0x8e, 0xff, 0xff, 0x29, 0x88,
0x00, 0x75, 0x56, 0x58, 0x57, 0x96, 0x68, 0x35,
0x70, 0xff, 0xf3, 0x38, 0xc0, 0x08, 0x11, 0x89,
0x12, 0xdb, 0x1f, 0x81, 0x39, 0x02, 0x02, 0x00,
0x29, 0xdc, 0xb2, 0xf9, 0xb8, 0x00, 0xe6, 0x64,
0xe3, 0x76, 0x21, 0xb0, 0x09, 0x84, 0xc5, 0x79,
0xa6, 0x4d, 0x6e, 0x79, 0xac, 0x50, 0xda, 0xa7,
0xa3, 0x7a, 0xf5, 0x3c, 0x48, 0x57, 0xe2, 0x59,
0x9e, 0x0a, 0xae, 0x08, 0x6f, 0x2b, 0x60, 0x53,
0x11, 0xbe, 0x52, 0xaa, 0xbd, 0x50, 0xc4, 0xbf,
0x1f, 0xbe, 0x2d, 0x43, 0x14, 0xd9, 0x0f, 0xd2,
0xd5, 0xfd, 0x39, 0x15, 0x00, 0x32, 0x35, 0x55,
0x67, 0x87, 0x79, 0x66, 0x62, 0x23, 0x00, 0x6b,
0xe5, 0x9b, 0x6d, 0xb0, 0x02, 0x13, 0x60, 0x08,
0xcd, 0x90, 0xea, 0x40, 0x18, 0x51, 0x88, 0x2c,
0x8a, 0x66, 0xf4, 0xba, 0x22, 0xff, 0xf3, 0x2a,
0xc0, 0x20, 0x11, 0xd9, 0x12, 0xbf, 0x1f, 0x81,
0x50, 0x02, 0x9c, 0xc6, 0x72, 0xa7, 0x75, 0x24,
0xea, 0xc1, 0x24, 0x37, 0x6e, 0x2a, 0x07, 0xfe,
0x25, 0x0a, 0x71, 0x63, 0x6e, 0x23, 0xcc, 0x8a,
0xfa, 0x3a, 0x3c, 0x6d, 0x14, 0xaf, 0xce, 0xed,
0x2c, 0x96, 0x76, 0xe9, 0x57, 0x3b, 0xbd, 0x9e,
0x49, 0x20, 0x23, 0x33, 0x34, 0x68, 0x85, 0x88,
0x03, 0x40, 0x00, 0x00, 0x29, 0xd4, 0xcf, 0x76,
0xd8, 0x00, 0x62, 0x94, 0x60, 0xaa, 0xff, 0xf3,
0x38, 0xc0, 0x14, 0x10, 0xe9, 0x0e, 0xe3, 0x1f,
0x81, 0x39, 0x02, 0xb2, 0x0d, 0xdd, 0x0c, 0x53,
0xd5, 0x0e, 0x4e, 0x3f, 0xb3, 0x67, 0x0f, 0x03,
0xf1, 0x7b, 0x99, 0x1d, 0x06, 0xf5, 0x0d, 0x72,
0x84, 0xbd, 0x1f, 0xca, 0x6a, 0x74, 0xa2, 0x8f,
0x2a, 0xe2, 0x39, 0xcf, 0x2c, 0x9e, 0xa7, 0xad,
0xf2, 0xfd, 0xa5, 0x6d, 0x5c, 0x97, 0xf3, 0x9f,
0x92, 0xfc, 0xa0, 0x8e, 0x0c, 0x21, 0x88, 0x44,
0x87, 0x1d, 0x46, 0xcc, 0xd1, 0x19, 0x2e, 0x75,
0xf3, 0x2b, 0x01, 0x97, 0xaa, 0x31, 0xf0, 0x5c,
0x01, 0x82, 0x52, 0x73, 0x45, 0xe4, 0x45, 0xd2,
0xdf, 0xe7, 0x0d, 0xc9, 0x7f, 0x4f, 0xba, 0x93,
0x31, 0x42, 0x66, 0x76, 0xf8, 0x0d, 0x8f, 0xfc,
0xe7, 0x1a, 0xff, 0xf3, 0x2a, 0xc0, 0x2f, 0x0d,
0x18, 0xee, 0xdb, 0xbf, 0xc1, 0x50, 0x02, 0x2a,
0x1c, 0x7f, 0x50, 0x0d, 0x20, 0x25, 0x3b, 0xbd,
0x44, 0x10, 0x22, 0x6a, 0x11, 0x3e, 0x63, 0x29,
0x4c, 0xbb, 0xb9, 0x58, 0xae, 0x49, 0x65, 0x2d,
0x72, 0xd4, 0x99, 0x47, 0xa7, 0x97, 0x91, 0xc6,
0xb3, 0xb1, 0x2e, 0x50, 0xce, 0x27, 0xdf, 0xfe,
0x74, 0x4d, 0x51, 0xff, 0xff, 0xff, 0xd1, 0xff,
0x57, 0xff, 0xf4, 0xb3, 0x06, 0xff, 0xfb, 0x7f,
0xff, 0xfd, 0x65, 0xff, 0xf3, 0x38, 0xc0, 0x36,
0x0e, 0x82, 0x6a, 0xb7, 0xb6, 0x2e, 0x5b, 0x02,
0x40, 0x4a, 0x8a, 0x4a, 0x10, 0x05, 0x88, 0xc9,
0x92, 0x9f, 0x94, 0xe7, 0xf6, 0xd1, 0x4d, 0x76,
0x4f, 0xa7, 0x5b, 0xac, 0xbe, 0x16, 0x48, 0x00,
0x60, 0xa8, 0x13, 0xe6, 0x08, 0xd6, 0xc8, 0x8a,
0x29, 0x2d, 0xa8, 0x51, 0x7f, 0xfe, 0x79, 0xff,
0xfd, 0xd0, 0x76, 0x5b, 0xb2, 0x6a, 0x65, 0xe8,
0x2e, 0x82, 0xec, 0xab, 0xff, 0xfe, 0xe6, 0x69,
0x11, 0x43, 0x12, 0xd8, 0xca, 0x0e, 0x06, 0x4f,
0xff, 0x87, 0x60, 0x22, 0x00, 0xcd, 0xa2, 0x10,
0x14, 0x24, 0x62, 0x4c, 0xd9, 0x49, 0x37, 0xe9,
0x2d, 0x04, 0xa8, 0xd4, 0x8a, 0x7a, 0x24, 0xf9,
0x24, 0x17, 0xe8, 0x00, 0xda, 0xba, 0x8c, 0xff,
0xf3, 0x2a, 0xc0, 0x5b, 0x0f, 0xa2, 0x66, 0xd3,
0xdc, 0x80, 0x05, 0xe2, 0x30, 0xde, 0x88, 0x45,
0x22, 0x46, 0x09, 0xfd, 0x2f, 0xfd, 0x15, 0x92,
0x49, 0x7f, 0xff, 0xff, 0xcc, 0x8c, 0x7f, 0xea,
0x7f, 0xff, 0x5a, 0x29, 0x13, 0xc2, 0x98, 0x04,
0x78, 0xf2, 0x87, 0xff, 0x80, 0x27, 0x58, 0x23,
0x0a, 0xce, 0x83, 0x11, 0x26, 0x04, 0x62, 0x4d,
0x5d, 0x95, 0xe8, 0xad, 0x94, 0xa6, 0x30, 0xb5,
0x49, 0x9c, 0xa8, 0xcc, 0xb4, 0x5c, 0x14, 0x98,
0xff, 0xf3, 0x38, 0xc0, 0x58, 0x0f, 0xaa, 0x66,
0xb7, 0xe6, 0x88, 0x0b, 0xe0, 0x0a, 0x66, 0x1e,
0xd9, 0xeb, 0x33, 0x62, 0x54, 0x00, 0x0c, 0x99,
0xa0, 0x89, 0x02, 0x17, 0x12, 0x6a, 0xfd, 0xac,
0x93, 0x0c, 0xe2, 0x23, 0x9b, 0xff, 0x7f, 0xff,
0xd4, 0xe0, 0x6e, 0x01, 0xb0, 0xb6, 0xff, 0xff,
0xff, 0xff, 0xd2, 0x1f, 0x92, 0x20, 0x5d, 0xa9,
0x00, 0xd7, 0x41, 0x50, 0x14, 0x68, 0xdf, 0xbb,
0x3a, 0x94, 0xea, 0xaa, 0x8a, 0x48, 0x6e, 0x4a,
0x89, 0xc8, 0x0a, 0x90, 0x53, 0x0d, 0x52, 0xa9,
0x6c, 0x91, 0xc0, 0x0c, 0xc4, 0x24, 0x52, 0x1f,
0xc2, 0xfc, 0xff, 0x7a, 0xab, 0x4c, 0x7e, 0x1e,
0x25, 0x8b, 0xff, 0xff, 0xff, 0x59, 0x47, 0xff,
0xff, 0xff, 0x85, 0x10, 0xff, 0xf3, 0x2a, 0xc0,
0x78, 0x10, 0x42, 0x66, 0xaf, 0xe6, 0xa0, 0x1b,
0x64, 0x29, 0x45, 0x9f, 0xff, 0x46, 0xff, 0xff,
0x19, 0x2f, 0xf5, 0x7a, 0x00, 0x22, 0x0c, 0xdd,
0xa3, 0x11, 0x19, 0x75, 0x82, 0xa8, 0x93, 0x6d,
0xfa, 0xd9, 0x34, 0x99, 0x9d, 0x9f, 0x41, 0x3a,
0xce, 0x17, 0x88, 0x88, 0x7e, 0x20, 0x5d, 0x25,
0x57, 0xbb, 0x25, 0x48, 0x35, 0x11, 0xd8, 0xb8,
0xd5, 0x10, 0x21, 0x69, 0xfb, 0x2b, 0x52, 0xeb,
0x19, 0x23, 0x53, 0x6f, 0xff, 0xff, 0xf3, 0x38,
0xc0, 0x73, 0x10, 0x92, 0xaa, 0xae, 0x56, 0x68,
0x05, 0xe2, 0xea, 0x57, 0x5f, 0x95, 0xbf, 0xf6,
0xff, 0xfd, 0x6b, 0x38, 0x0d, 0xa2, 0x6e, 0xaf,
0xfe, 0xa1, 0x00, 0x46, 0x00, 0xbf, 0xa4, 0x11,
0x3b, 0xbe, 0xa3, 0x1d, 0x2e, 0xad, 0x6c, 0xdf,
0x9c, 0xd3, 0x52, 0xba, 0xf6, 0x1d, 0xc6, 0xc6,
0x00, 0x99, 0x77, 0xe8, 0xac, 0xa8, 0x20, 0x05,
0xab, 0xa8, 0xa8, 0x22, 0xa5, 0x17, 0x7b, 0xf4,
0x66, 0xcc, 0x34, 0x8c, 0x09, 0xaa, 0x2a, 0xff,
0xee, 0xcc, 0xa5, 0xf5, 0xad, 0x35, 0x2c, 0x95,
0xb7, 0xff, 0xff, 0xb2, 0x91, 0x4a, 0x27, 0xc0,
0x06, 0x81, 0xe5, 0xfe, 0xe8, 0xf3, 0x44, 0xb0,
0xdc, 0xe0, 0x45, 0x0c, 0xa0, 0xa4, 0x01, 0x2b,
0xbe, 0xff, 0xf3, 0x2a, 0xc0, 0x8f, 0x10, 0x22,
0x62, 0xab, 0xe6, 0x98, 0x0b, 0xe0, 0xc3, 0x2c,
0xc3, 0x4d, 0xfa, 0x2a, 0x5a, 0xbf, 0xb2, 0x5a,
0x8c, 0x8b, 0x46, 0x80, 0x7c, 0x7f, 0x39, 0x30,
0x00, 0x26, 0xc8, 0x06, 0xcb, 0x2a, 0x14, 0x8d,
0xbd, 0xaf, 0x5b, 0x4c, 0x46, 0x10, 0xd6, 0xba,
0xbe, 0xb5, 0x76, 0x7b, 0x54, 0xfb, 0x5c, 0xa4,
0xde, 0xbf, 0xff, 0xfa, 0x06, 0x6c, 0xb1, 0x3f,
0x00, 0x79, 0x16, 0x9f, 0xfe, 0x88, 0x56, 0x12,
0x13, 0x00, 0xff, 0xf3, 0x38, 0xc0, 0x8a, 0x11,
0x9a, 0x66, 0xa7, 0xe6, 0x68, 0x0f, 0xe1, 0x34,
0x00, 0xbe, 0x93, 0x00, 0x29, 0xb6, 0xdb, 0x47,
0x2e, 0x97, 0xf5, 0x77, 0xf4, 0xf5, 0x14, 0xc6,
0x50, 0x51, 0x09, 0xa9, 0xb7, 0x98, 0xd2, 0x07,
0xd4, 0xeb, 0x33, 0x14, 0xd1, 0xf4, 0x4f, 0x95,
0x09, 0xd1, 0x52, 0x9f, 0x3b, 0x66, 0x9b, 0x7b,
0xdb, 0x9a, 0x1d, 0x63, 0x7a, 0x53, 0xeb, 0xec,
0xba, 0x90, 0x2a, 0x32, 0x1c, 0xe1, 0x5e, 0x04,
0xd0, 0x8c, 0x8f, 0xfd, 0xff, 0xdb, 0xeb, 0x7f,
0xf5, 0x92, 0x2a, 0x02, 0x44, 0x0b, 0xbe, 0x84,
0x11, 0x3b, 0xb7, 0xc3, 0x9c, 0x2b, 0x9f, 0xb7,
0xa3, 0x75, 0x36, 0xfe, 0xaa, 0x8e, 0xa8, 0x8b,
0x11, 0x60, 0x5c, 0x64, 0x92, 0x3c, 0xff, 0xf3,
0x2a, 0xc0, 0xa2, 0x10, 0x8a, 0x66, 0xa3, 0xe6,
0x68, 0x1b, 0xe1, 0xe4, 0xe0, 0x6d, 0xc6, 0xce,
0x70, 0x7c, 0x8b, 0x31, 0x1e, 0xcd, 0xf9, 0xd2,
0x75, 0xdd, 0xfd, 0x5b, 0x6b, 0x7d, 0xfb, 0xfa,
0xcd, 0xde, 0xab, 0x55, 0xdb, 0xb7, 0xeb, 0x9a,
0xa4, 0x99, 0xd2, 0x28, 0x14, 0x38, 0x86, 0x2d,
0xb6, 0xfd, 0xca, 0x03, 0xd0, 0xca, 0x50, 0x43,
0x0b, 0xbc, 0xa3, 0x21, 0x29, 0x76, 0xb7, 0x58,
0x89, 0xe5, 0xf0, 0xd3, 0x05, 0xab, 0xb0, 0xff,
0xf3, 0x38, 0xc0, 0x9b, 0x11, 0x42, 0x66, 0x9b,
0xe6, 0x69, 0xdb, 0x4d, 0xd0, 0x4c, 0x79, 0x16,
0xd0, 0x8e, 0x81, 0x8d, 0x13, 0x6a, 0xaa, 0x75,
0xe1, 0xe0, 0x41, 0xd3, 0x44, 0x31, 0x89, 0xa7,
0xbf, 0xec, 0x26, 0xd3, 0x96, 0xf5, 0x7d, 0x7a,
0xae, 0xcf, 0xf5, 0x1e, 0xba, 0xd7, 0xf5, 0x2f,
0xa3, 0xfd, 0x66, 0xaa, 0x3e, 0x3e, 0x82, 0xfd,
0x03, 0x5b, 0x0d, 0x84, 0xb9, 0xb2, 0xbf, 0xff,
0xfd, 0x07, 0x7f, 0xd4, 0xa2, 0xa8, 0xb6, 0xb8,
0x33, 0x00, 0x9b, 0xa3, 0x11, 0x49, 0x75, 0xf7,
0x38, 0x8c, 0xb7, 0xfd, 0x6a, 0x46, 0x41, 0xac,
0xe2, 0xc6, 0x44, 0x2d, 0xa8, 0x3e, 0x24, 0xb3,
0xb6, 0x72, 0x70, 0x2d, 0x18, 0x84, 0x76, 0x1a,
0x86, 0x4a, 0x6f, 0xff, 0xf3, 0x2a, 0xc0, 0xb5,
0x11, 0x62, 0x66, 0x97, 0xe6, 0x98, 0x0f, 0xe1,
0xfe, 0x39, 0xc6, 0xad, 0xff, 0xfa, 0x34, 0xfd,
0x77, 0x99, 0xff, 0xef, 0xdf, 0xf4, 0x58, 0xd4,
0xba, 0x78, 0x5a, 0x45, 0x04, 0x1e, 0xc0, 0xe4,
0x96, 0x9d, 0xd5, 0xff, 0xfd, 0xbe, 0x65, 0xff,
0x2f, 0x90, 0x52, 0xa8, 0xd0, 0x48, 0x0a, 0x23,
0x01, 0x40, 0xdc, 0x0e, 0x00, 0x81, 0x01, 0x3c,
0xb6, 0xff, 0x43, 0xf5, 0x26, 0xc9, 0x97, 0x03,
0x2d, 0x0c, 0xb2, 0x21, 0xff, 0xf3, 0x38, 0xc0,
0xab, 0x12, 0xea, 0x6a, 0x87, 0xe6, 0x48, 0x64,
0x14, 0x65, 0x2a, 0x5f, 0x5d, 0x10, 0x6f, 0x29,
0x56, 0x88, 0xfc, 0x27, 0x37, 0xf4, 0xd1, 0xd1,
0x74, 0x88, 0x68, 0x82, 0x24, 0x8f, 0xff, 0xf4,
0xbf, 0xa9, 0xe6, 0x8f, 0xf5, 0x57, 0xf5, 0x69,
0x6e, 0xa9, 0x68, 0xe9, 0x1c, 0x39, 0x40, 0xd0,
0xa0, 0x6c, 0x88, 0xe6, 0x9a, 0x9a, 0x1a, 0x2f,
0xfc, 0x60, 0xe7, 0x7f, 0xe8, 0x66, 0xa7, 0x72,
0x3d, 0x00, 0x60, 0x0b, 0xe5, 0xd4, 0x5b, 0x85,
0x30, 0xac, 0xbf, 0xff, 0xef, 0x8d, 0x67, 0xd5,
0x59, 0x80, 0xca, 0x59, 0x45, 0x92, 0x59, 0xd1,
0x5e, 0xf2, 0x4a, 0xf2, 0xb8, 0xc2, 0xa2, 0x3c,
0xf0, 0xa2, 0x4d, 0xec, 0xb9, 0x45, 0x8c, 0xe2,
0xff, 0xf3, 0x2a, 0xc0, 0xbe, 0x11, 0xe2, 0x66,
0x83, 0xe6, 0x30, 0x66, 0x15, 0x75, 0xf0, 0xfd,
0xd9, 0xfa, 0xd5, 0x9f, 0xff, 0xf5, 0x37, 0xfd,
0xe7, 0x1d, 0xff, 0x64, 0xfa, 0xb6, 0x87, 0x33,
0x9a, 0x25, 0x00, 0x08, 0x16, 0x80, 0xb8, 0x7a,
0x74, 0xef, 0xff, 0xff, 0xff, 0xe3, 0xe1, 0xf1,
0xd3, 0x00, 0x17, 0xff, 0xfa, 0x45, 0xcc, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xf3, 0x38, 0xc0, 0xb2, 0x13, 0xda,
0x66, 0x76, 0x5e, 0x98, 0x05, 0xe2, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf3, 0x2a,
0xc0, 0xc1, 0x12, 0x8a, 0x66, 0x57, 0x8e, 0x16,
0x14, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf3,
0x38, 0xc0, 0xb2, 0x04, 0x68, 0x06, 0x30, 0x20,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00
};

View File

@@ -0,0 +1,50 @@
#ifndef _WAVE_CODE_H_
#define _WAVE_CODE_H_
#include "basic_include.h"
#include "lib/heap/av_heap.h"
#include "lib/heap/av_psram_heap.h"
#include "audio_code_ctrl.h"
#ifdef PSRAM_HEAP
#define WAVE_CODE_MALLOC av_psram_malloc
#define WAVE_CODE_ZALLOC av_psram_zalloc
#define WAVE_CODE_FREE av_psram_free
#else
#define WAVE_CODE_MALLOC av_malloc
#define WAVE_CODE_ZALLOC av_zalloc
#define WAVE_CODE_FREE av_free
#endif
#define WAVE_DEBUG(fmt, args...) //os_printf(fmt, ##args)
#define WAVE_INFO os_printf
typedef struct _riff_chunk {
uint8_t ChunkID[4];
uint32_t ChunkSize;
uint8_t Format[4];
} TYPE_RIFF_CHUNK;
typedef struct _fmt_chunk {
uint8_t FmtID[4];
uint32_t FmtSize;
uint16_t FmtTag;
uint16_t FmtChannels;
uint32_t SampleRate;
uint32_t ByteRate;
uint16_t BlockAlign;
uint16_t BitsPerSample;
} TYPE_FMT_CHUNK;
typedef struct _data_chunk {
uint8_t DataID[4];
uint32_t DataSize;
} TYPE_DATA_CHUNK;
typedef struct _wave_head {
TYPE_RIFF_CHUNK riff_chunk;
TYPE_FMT_CHUNK fmt_chunk;
TYPE_DATA_CHUNK data_chunk;
} TYPE_WAVE_HEAD;
struct msi *wave_encode_init(char *filename, uint32_t samplerate, AUENC_INIT *auenc_init);
struct msi *wave_decode_init(char *filename, uint8_t loop_mode, AUDEC_INIT *audec_init);
#endif

View File

@@ -0,0 +1,459 @@
#include "basic_include.h"
#include "csi_kernel.h"
#include "lib/multimedia/msi.h"
#include "lib/multimedia/framebuff.h"
#include "autpc_msi/autpc_msi.h"
#include "osal_file.h"
#include "wave_code.h"
#define BUFF_SIZE 1024
#define MAX_WAVE_DECODE_TXBUF 4
struct wave_decode_struct {
AUDIO_TRACK audio_track;
struct fbpool tx_pool;
struct os_event event;
struct msi *msi;
struct msi *autpc_msi;
char *msi_name;
void *task_hdl;
void *wave_fp;
uint8_t loop_mode;
uint8_t direct_to_dac;
uint8_t use_tpc;
uint8_t speed;
uint8_t pitch;
uint8_t destroy_self;
uint8_t get_wave_head;
uint8_t next_status;
uint8_t current_status;
uint8_t buf[BUFF_SIZE];
uint32_t buf_size;
TYPE_WAVE_HEAD wave_head;
};
static void get_wave_head(struct wave_decode_struct *s)
{
int32_t read_len = 0;
uint32_t offset = 0;
uint32_t head_seek = 0;
read_len = osal_fread(s->buf, 512, 1, s->wave_fp);
if(read_len <= 0) {
WAVE_INFO("wave read fail,ret:%d,line:%d!\r\n",read_len,__LINE__);
return;
}
s->buf_size = read_len;
os_memcpy((uint8_t*)(&(s->wave_head)), s->buf, sizeof(TYPE_RIFF_CHUNK)+sizeof(TYPE_FMT_CHUNK));
if(os_strncmp(&(s->wave_head.riff_chunk), "RIFF", 4) != 0) {
WAVE_INFO("wave head err!\n");
return;
}
offset = sizeof(TYPE_RIFF_CHUNK)+sizeof(TYPE_FMT_CHUNK);
while(os_strncmp(s->buf+offset, "data", 4) != 0) {
offset++;
if(offset >= s->buf_size-(sizeof(TYPE_DATA_CHUNK)-1)) {
os_memcpy(s->buf, s->buf+s->buf_size+(sizeof(TYPE_DATA_CHUNK)-1), sizeof(TYPE_DATA_CHUNK)-1);
head_seek += read_len;
read_len = osal_fread(s->buf+(sizeof(TYPE_DATA_CHUNK)-1), 512, 1, s->wave_fp);
if(read_len <= 0) {
WAVE_INFO("wave read fail,ret:%d,line:%d!\r\n",read_len,__LINE__);
return;
}
s->buf_size = read_len + (sizeof(TYPE_DATA_CHUNK)-1);
offset = 0;
}
}
head_seek += (offset+sizeof(TYPE_DATA_CHUNK));
os_memcpy((uint8_t*)(&(s->wave_head.data_chunk)), s->buf+offset, sizeof(TYPE_DATA_CHUNK));
osal_fseek(s->wave_fp, head_seek);
s->get_wave_head = 1;
}
static void wave_decode(struct wave_decode_struct *s)
{
int16_t *data = NULL;
int32_t ret = 0;
int32_t read_len = 0;
int32_t audio_temp = 0;
uint32_t once_read_size = 0;
uint32_t read_total_size = 0;
uint32_t interval_time = 0;
struct framebuff *frame_buf = NULL;
AUDIO_TRACK *audac_fiter_track = NULL;
if(s->wave_head.fmt_chunk.BitsPerSample == 24) {
once_read_size = BUFF_SIZE*8/24; //sample取整
once_read_size = once_read_size*3/4; //sample取偶
once_read_size *= 4;
}
else if(s->wave_head.fmt_chunk.BitsPerSample == 16) {
once_read_size = BUFF_SIZE;
}
else if(s->wave_head.fmt_chunk.BitsPerSample == 8) {
once_read_size = BUFF_SIZE/2;
}
while(1) {
if(s->next_status == AUCODEC_PAUSE) {
if(s->current_status == AUCODEC_RUN) {
msi_output_cmd(s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(s->audio_track)));
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_END_STREAM,(uint32_t)(&(s->audio_track)));
}
s->current_status = AUCODEC_PAUSE;
while(s->next_status == AUCODEC_PAUSE) {
os_sleep_ms(1);
}
}
if(s->next_status == AUCODEC_EXIT) {
s->current_status = AUCODEC_EXIT;
break;
}
s->current_status = AUCODEC_RUN;
frame_buf = fbpool_get(&s->tx_pool, 0, s->msi);
if(frame_buf) {
data = (int16_t*)(frame_buf->data);
if(read_total_size >= s->wave_head.data_chunk.DataSize) {
goto wave_decode_end;
}
if((read_total_size+once_read_size) > s->wave_head.data_chunk.DataSize) {
read_len = osal_fread((uint8_t*)data, 1, (s->wave_head.data_chunk.DataSize-read_total_size), s->wave_fp);
}
else
read_len = osal_fread((uint8_t*)data, 1, once_read_size, s->wave_fp);
if(read_len > 0) {
read_total_size += read_len;
if(s->wave_head.fmt_chunk.BitsPerSample == 24) {
for(uint32_t i=0; i<(read_len/3); i++) {
audio_temp = (int32_t)((*((uint8_t*)data+3*i))|(*((uint8_t*)data+3*i+1)<<8)|(*((uint8_t*)data+3*i+2))<<16)&0x00FFFFFF;
data[i] = audio_temp>>8;
}
read_len = read_len*2/3;
}
else if(s->wave_head.fmt_chunk.BitsPerSample == 8) {
os_memcpy(data+read_len/2, data, read_len);
for(uint32_t i=0; i<read_len; i++) {
data[i] = (int16_t)(*(((uint8_t*)data)+read_len+i)-128)<<8;
}
read_len = read_len*2;
}
if(s->wave_head.fmt_chunk.FmtChannels == 2) {
for(uint32_t i=0; i<(read_len/4); i++) {
data[i] = (( ((int32_t)data[2*i]) + data[2*i+1] ) >>1 );
}
read_len = read_len/2;
}
frame_buf->len = read_len;
frame_buf->mtype = F_AUDIO;
frame_buf->stype = FSTYPE_AUDIO_PCM;
s->audio_track.samplerate = s->wave_head.fmt_chunk.SampleRate;
if(s->use_tpc && !s->autpc_msi) {
s->autpc_msi = autpc_msi_init(s->audio_track.samplerate, s->speed, s->pitch, read_len/2, &(s->audio_track));
if(s->autpc_msi == NULL) {
goto wave_decode_end;
}
msi_add_output(s->msi, NULL, s->autpc_msi->name);
if(s->direct_to_dac) {
msi_add_output(s->autpc_msi, NULL, "R_AUDAC");
}
}
ret = msi_output_fb(s->msi, frame_buf);
WAVE_DEBUG("wave decode send framebuff:%p,ret:%d\r\n",frame_buf,ret);
msi_cmd("R_AUDAC", MSI_CMD_AUDAC, MSI_AUDAC_GET_FILTER_TRACK, (uint32_t)(&audac_fiter_track));
if(s->direct_to_dac && (!s->use_tpc) && (audac_fiter_track != (&(s->audio_track)))) {
interval_time = (frame_buf->len>>1)*1000/(s->wave_head.fmt_chunk.SampleRate);
os_sleep_ms(interval_time);
}
frame_buf = NULL;
}
else if(read_len <= 0 ) {
msi_delete_fb(s->msi, frame_buf);
frame_buf = NULL;
WAVE_INFO("wave read fail,ret:%d,line:%d!\r\n",read_len,__LINE__);
break;
}
}
else
os_sleep_ms(1);
}
wave_decode_end:
msi_output_cmd(s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(s->audio_track)));
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_END_STREAM,(uint32_t)(&(s->audio_track)));
if(frame_buf) {
msi_delete_fb(s->msi, frame_buf);
frame_buf = NULL;
}
}
static void wave_decode_thread(void *d)
{
struct wave_decode_struct *s = (struct wave_decode_struct *)d;
if(s->wave_fp) {
get_wave_head(s);
if(!s->get_wave_head) {
WAVE_INFO("wave head err!\n");
goto wave_decode_thread_end;
}
}
msi_get(s->msi);
if(s->direct_to_dac) {
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(s->audio_track)));
}
s->msi->enable = 1;
do {
osal_fseek(s->wave_fp, sizeof(TYPE_WAVE_HEAD));
wave_decode(s);
if(s->current_status == AUCODEC_EXIT) {
break;
}
}while(s->loop_mode);
if(s->direct_to_dac) {
s->audio_track.priority &= 0x3F;
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(s->audio_track)));
}
wave_decode_thread_end:
os_event_set(&s->event, coder_exit_event, NULL);
while((s->next_status != AUCODEC_EXIT) && (s->destroy_self == 0)) {
s->current_status = AUCODEC_END;
os_sleep_ms(5);
}
if(s->next_status != AUCODEC_EXIT)
msi_destroy(s->msi);
msi_put(s->msi);
}
static int32_t wave_decode_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
{
int32_t ret = RET_OK;
struct wave_decode_struct *wave_decode_s = (struct wave_decode_struct *)(msi->priv);
switch(cmd_id) {
case MSI_CMD_AUCODER:
{
ret = RET_ERR;
if(wave_decode_s) {
uint32_t cmd_self = (uint32_t)param1;
switch(cmd_self) {
case MSI_AUCODER_PAUSE:
{
if(wave_decode_s->current_status == AUCODEC_RUN) {
wave_decode_s->next_status = AUCODEC_PAUSE;
}
ret = RET_OK;
break;
}
case MSI_AUCODER_CONTINUE:
{
if(wave_decode_s->current_status == AUCODEC_PAUSE) {
wave_decode_s->next_status = AUCODEC_RUN;
}
ret = RET_OK;
break;
}
case MSI_AUCODER_GET_STATUS:
{
*((uint32_t*)param2) = (uint32_t)(wave_decode_s->current_status);
ret = RET_OK;
break;
}
case MSI_AUCODER_SET_SPEED:
{
wave_decode_s->speed = (uint8_t)param2;
ret = msi_output_cmd(wave_decode_s->msi,MSI_CMD_AUTPC,MSI_AUTPC_SET_SPEED,(uint32_t)(wave_decode_s->speed));
break;
}
case MSI_AUCODER_GET_SPEED:
{
*((uint32_t*)param2) = (uint32_t)(wave_decode_s->speed);
ret = RET_OK;
break;
}
case MSI_AUCODER_SET_PITCH:
{
wave_decode_s->pitch = (uint8_t)param2;
ret = msi_output_cmd(wave_decode_s->msi,MSI_CMD_AUTPC,MSI_AUTPC_SET_PITCH,(uint32_t)(wave_decode_s->pitch));
break;
}
case MSI_AUCODER_GET_PITCH:
{
*((uint32_t*)param2) = (uint32_t)(wave_decode_s->pitch);
ret = RET_OK;
break;
}
case MSI_AUCODER_DIRECT_TO_DAC:
{
uint32_t direct_to_dac = param2;
if(direct_to_dac && wave_decode_s->direct_to_dac == 0) {
wave_decode_s->direct_to_dac = 1;
if(wave_decode_s->use_tpc == 0) {
msi_add_output(msi, NULL, "R_AUDAC");
}
else if(wave_decode_s->autpc_msi) {
msi_add_output(wave_decode_s->autpc_msi, NULL, "R_AUDAC");
}
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(wave_decode_s->audio_track)));
}
else if(wave_decode_s->direct_to_dac == 1) {
wave_decode_s->direct_to_dac = 0;
if(wave_decode_s->use_tpc == 0) {
msi_del_output(msi, NULL, "R_AUDAC");
}
else if(wave_decode_s->autpc_msi) {
msi_del_output(wave_decode_s->autpc_msi, NULL, "R_AUDAC");
}
wave_decode_s->audio_track.priority &= 0x3F;
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(wave_decode_s->audio_track)));
}
break;
}
case MSI_AUCODER_DEINIT:
{
msi_destroy(msi);
ret = RET_OK;
break;
}
default:
break;
}
}
break;
}
case MSI_CMD_FREE_FB:
{
ret = RET_ERR;
if(wave_decode_s) {
struct framebuff *frame_buf = (struct framebuff *)param1;
fbpool_put(&wave_decode_s->tx_pool, frame_buf);
}
break;
}
case MSI_CMD_PRE_DESTROY:
{
if(wave_decode_s && wave_decode_s->task_hdl) {
wave_decode_s->next_status = AUCODEC_EXIT;
}
break;
}
case MSI_CMD_POST_DESTROY:
{
if(wave_decode_s) {
if(wave_decode_s->task_hdl) {
os_event_wait(&wave_decode_s->event, coder_exit_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
}
for(uint32_t i=0; i<MAX_WAVE_DECODE_TXBUF; i++) {
struct framebuff *frame_buf = (wave_decode_s->tx_pool.pool)+i;
if(frame_buf->data) {
WAVE_CODE_FREE(frame_buf->data);
frame_buf->data = NULL;
}
}
fbpool_destroy(&wave_decode_s->tx_pool);
if(wave_decode_s->event.hdl) {
os_event_del(&wave_decode_s->event);
}
if(wave_decode_s->wave_fp) {
osal_fclose(wave_decode_s->wave_fp);
wave_decode_s->wave_fp = NULL;
}
if(wave_decode_s->autpc_msi) {
autpc_msi_deinit(wave_decode_s->autpc_msi);
wave_decode_s->autpc_msi = NULL;
}
if(wave_decode_s->msi_name) {
WAVE_CODE_FREE(wave_decode_s->msi_name);
wave_decode_s->msi_name = NULL;
}
WAVE_CODE_FREE(wave_decode_s);
wave_decode_s = NULL;
}
break;
}
default:
break;
}
return ret;
}
struct msi *wave_decode_init(char *filename, uint8_t loop_mode, AUDEC_INIT *audec_init)
{
#if AUDIO_EN
char *msi_name = NULL;
msi_name = (char*)WAVE_CODE_ZALLOC(sizeof(char)*32);
if(msi_name == NULL) {
os_printf("alloc autpc msi namefail\n");
return NULL;
}
os_snprintf(msi_name, 20, "S_WAVE_DECODE_""%04d", (int)(os_jiffies()));
struct msi *msi = msi_new(msi_name, 0, NULL);
if(!msi) {
WAVE_INFO("create wave decode msi fail!\r\n");
return NULL;
}
struct wave_decode_struct *wave_decode_s = (struct wave_decode_struct *)WAVE_CODE_ZALLOC(sizeof(struct wave_decode_struct));
if(!wave_decode_s) {
WAVE_INFO("wave_decode_s malloc fail!\r\n");
goto wave_decode_init_err;
}
msi->priv = wave_decode_s;
msi->action = (msi_action)wave_decode_msi_action;
fbpool_init(&wave_decode_s->tx_pool, MAX_WAVE_DECODE_TXBUF);
for(uint32_t i=0; i<MAX_WAVE_DECODE_TXBUF; i++) {
struct framebuff *frame_buf = (wave_decode_s->tx_pool.pool)+i;
frame_buf->data = (uint8_t*)WAVE_CODE_MALLOC(BUFF_SIZE);
if(frame_buf->data == NULL) {
WAVE_INFO("wave decode malloc framebuff data fail!\r\n");
goto wave_decode_init_err;
}
frame_buf->priv = &(wave_decode_s->audio_track);
}
if(filename) {
wave_decode_s->wave_fp = osal_fopen((const char*)filename, "rb");
if(wave_decode_s->wave_fp == NULL) {
WAVE_INFO("open wave file %s fail!\r\n", filename);
goto wave_decode_init_err;
}
}
else {
WAVE_INFO("wave filename is null!\r\n");
goto wave_decode_init_err;
}
if(os_event_init(&wave_decode_s->event) != RET_OK) {
WAVE_INFO("create wave decode event fail!\r\n");
goto wave_decode_init_err;
}
wave_decode_s->msi = msi;
wave_decode_s->msi_name = msi_name;
wave_decode_s->loop_mode = loop_mode;
wave_decode_s->direct_to_dac = audec_init->direct_to_dac;
wave_decode_s->use_tpc = audec_init->use_tpc;
wave_decode_s->speed = audec_init->speed;
wave_decode_s->pitch = audec_init->pitch;
wave_decode_s->destroy_self = audec_init->destroy_self;
wave_decode_s->audio_track.priority = audec_init->priority;
wave_decode_s->audio_track.track_type = audec_init->track_type;
wave_decode_s->next_status = AUCODEC_RUN;
wave_decode_s->current_status = AUCODEC_RUN;
if(audec_init->direct_to_dac && !wave_decode_s->use_tpc) {
msi_add_output(msi, NULL, "R_AUDAC");
}
wave_decode_s->task_hdl = os_task_create("wave_decode_thread", wave_decode_thread, (void*)wave_decode_s, OS_TASK_PRIORITY_NORMAL, 0, NULL, 1024);
if(wave_decode_s->task_hdl == NULL) {
WAVE_INFO("create wave decode task fail!\r\n");
goto wave_decode_init_err;
}
return msi;
wave_decode_init_err:
msi_destroy(msi);
#endif
return NULL;
}

View File

@@ -0,0 +1,256 @@
#include "basic_include.h"
#include "csi_kernel.h"
#include "lib/multimedia/msi.h"
#include "lib/multimedia/framebuff.h"
#include "osal_file.h"
#include "wave_code.h"
#define MAX_WAVE_ENCODE_RXBUF 4
struct wave_encode_struct {
struct os_event event;
struct msi *msi;
struct msi *src_msi;
void *task_hdl;
void *wave_fp;
uint8_t destroy_self;
uint8_t next_status;
uint8_t current_status;
uint32_t samplerate;
uint32_t data_size;
TYPE_WAVE_HEAD wave_head;
};
const unsigned char wav_header[] = {
'R', 'I', 'F', 'F', // "RIFF" 标志
0, 0, 0, 0, // 文件长度
'W', 'A', 'V', 'E', // "WAVE" 标志
'f', 'm', 't', ' ', // "fmt" 标志
16, 0, 0, 0, // 过渡字节(不定)
0x01, 0x00, // 格式类别
0x01, 0x00, // 声道数
0, 0, 0, 0, // 采样率
0, 0, 0, 0, // 位速
0x01, 0x00, // 一个采样多声道数据块大小
0x10, 0x00, // 一个采样占的 bit 数
'd', 'a', 't', 'a', // 数据标记符data
0, 0, 0, 0 // 语音数据的长度比文件长度小42一般。这个是计算音频播放时长的关键参数~
};
static void wave_encode_thread(void *d)
{
uint8_t *data = NULL;
uint32_t data_len = 0;
struct wave_encode_struct *s = (struct wave_encode_struct *)d;
struct framebuff *frame_buf = NULL;
s->msi->enable = 1;
msi_get(s->msi);
while(1)
{
frame_buf = msi_get_fb(s->msi, 0);
if(frame_buf)
{
if(s->next_status == AUCODEC_PAUSE)
s->current_status = AUCODEC_PAUSE;
else {
s->current_status = AUCODEC_RUN;
data = frame_buf->data;
data_len = frame_buf->len;
osal_fwrite(data, 2, data_len/2, s->wave_fp);
s->data_size += data_len;
}
msi_delete_fb(s->msi, frame_buf);
WAVE_DEBUG("wave encode delete framebuff:%p,len:%d,\r\n",frame_buf,frame_buf->len);
frame_buf = NULL;
}
else
os_sleep_ms(1);
if(s->next_status == AUCODEC_EXIT) {
s->current_status = AUCODEC_EXIT;
s->wave_head.riff_chunk.ChunkSize = s->data_size + sizeof(TYPE_WAVE_HEAD) - 8;
s->wave_head.fmt_chunk.SampleRate = s->samplerate;
s->wave_head.fmt_chunk.ByteRate = s->samplerate*2;
s->wave_head.data_chunk.DataSize = s->data_size;
osal_fseek(s->wave_fp, 0);
osal_fwrite(&(s->wave_head), 1, sizeof(TYPE_WAVE_HEAD), s->wave_fp);
goto wave_encode_thread_end;
}
}
wave_encode_thread_end:
os_event_set(&s->event, coder_exit_event, NULL);
while((s->next_status != AUCODEC_EXIT) && (s->destroy_self == 0)) {
s->current_status = AUCODEC_END;
os_sleep_ms(5);
}
if(s->src_msi) {
msi_del_output(s->src_msi, NULL, s->msi->name);
s->src_msi = NULL;
}
if(s->next_status != AUCODEC_EXIT)
msi_destroy(s->msi);
msi_put(s->msi);
}
static int32_t wave_encode_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
{
int32_t ret = RET_OK;
struct wave_encode_struct *wave_encode_s = (struct wave_encode_struct*)(msi->priv);
switch(cmd_id) {
case MSI_CMD_AUCODER:
{
ret = RET_ERR;
if(wave_encode_s) {
uint32_t cmd_self = (uint32_t)param1;
switch(cmd_self) {
case MSI_AUCODER_PAUSE:
{
if(wave_encode_s->current_status == AUCODEC_RUN) {
wave_encode_s->next_status = AUCODEC_PAUSE;
}
ret = RET_OK;
break;
}
case MSI_AUCODER_CONTINUE:
{
if(wave_encode_s->current_status == AUCODEC_PAUSE) {
wave_encode_s->next_status = AUCODEC_RUN;
}
ret = RET_OK;
break;
}
case MSI_AUCODER_GET_STATUS:
{
*((uint32_t*)param2) = (uint32_t)(wave_encode_s->current_status);
ret = RET_OK;
break;
}
case MSI_AUCODER_SET_SRCMSI:
{
if(wave_encode_s->src_msi) {
msi_del_output(wave_encode_s->src_msi, NULL, msi->name);
}
wave_encode_s->src_msi = NULL;
ret = msi_add_output((struct msi*)param2, NULL, msi->name);
if(ret == RET_OK) {
wave_encode_s->src_msi = (struct msi*)param2;
}
break;
}
case MSI_AUCODER_DEINIT:
{
msi_destroy(msi);
ret = RET_OK;
break;
}
default:
break;
}
}
break;
}
case MSI_CMD_TRANS_FB:
{
ret = RET_ERR;
struct framebuff *frame_buf = (struct framebuff *)param1;
if(frame_buf->mtype == F_AUDIO) {
ret = RET_OK;
}
break;
}
case MSI_CMD_PRE_DESTROY:
{
if(wave_encode_s && wave_encode_s->task_hdl) {
wave_encode_s->next_status = AUCODEC_EXIT;
}
break;
}
case MSI_CMD_POST_DESTROY:
{
if(wave_encode_s) {
if(wave_encode_s->task_hdl) {
os_event_wait(&wave_encode_s->event, coder_exit_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
}
if(wave_encode_s->event.hdl) {
os_event_del(&wave_encode_s->event);
}
if(wave_encode_s->wave_fp) {
osal_fclose(wave_encode_s->wave_fp);
wave_encode_s->wave_fp = NULL;
}
WAVE_CODE_FREE(wave_encode_s);
wave_encode_s = NULL;
}
break;
}
default:
break;
}
return ret;
}
struct msi *wave_encode_init(char *filename, uint32_t samplerate, AUENC_INIT *auenc_init)
{
#if AUDIO_EN
uint8_t msi_isnew = 0;
struct msi *msi = msi_new("R_WAVE_ENCODE", MAX_WAVE_ENCODE_RXBUF, &msi_isnew);
if(!msi) {
WAVE_INFO("create wave encode msi fail!\r\n");
return NULL;
}
else if(!msi_isnew) {
WAVE_INFO("wave encode msi has been create!\r\n");
goto wave_encode_init_err;
}
struct wave_encode_struct *wave_encode_s = (struct wave_encode_struct*)WAVE_CODE_ZALLOC(sizeof(struct wave_encode_struct));
if(!wave_encode_s) {
WAVE_INFO("wave_encode_s malloc fail!\r\n");
goto wave_encode_init_err;
}
msi->priv = wave_encode_s;
msi->action = (msi_action)wave_encode_msi_action;
if(os_event_init(&wave_encode_s->event) != RET_OK) {
WAVE_INFO("create wave encode event fail!\r\n");
goto wave_encode_init_err;
}
if(filename) {
wave_encode_s->wave_fp = osal_fopen((const char*)filename, "wb+");
if(wave_encode_s->wave_fp == NULL) {
WAVE_INFO("open wave record file %s fail!\r\n", filename);
goto wave_encode_init_err;
}
}
else {
WAVE_INFO("wave record filename is null!\r\n");
goto wave_encode_init_err;
}
os_memcpy(&(wave_encode_s->wave_head), wav_header, sizeof(TYPE_WAVE_HEAD));
osal_fseek(wave_encode_s->wave_fp, sizeof(TYPE_WAVE_HEAD));
if(auenc_init->src_msi && (msi_add_output(auenc_init->src_msi, NULL, msi->name) != RET_OK)) {
goto wave_encode_init_err;
}
wave_encode_s->msi = msi;
wave_encode_s->src_msi = auenc_init->src_msi;
wave_encode_s->samplerate = samplerate;
wave_encode_s->destroy_self = auenc_init->destroy_self;
wave_encode_s->next_status = AUCODEC_RUN;
wave_encode_s->current_status = AUCODEC_RUN;
wave_encode_s->task_hdl = os_task_create("wave_encode_thread", wave_encode_thread, (void*)wave_encode_s, OS_TASK_PRIORITY_NORMAL, 0, NULL, 1024);
if(wave_encode_s->task_hdl == NULL) {
WAVE_INFO("create wave encode task fail!\r\n");
goto wave_encode_init_err;
}
return msi;
wave_encode_init_err:
msi_destroy(msi);
#endif
return NULL;
}