KT25-0812_82A-UART/cpu/br25/audio_enc/audio_enc.c
2025-08-12 18:09:23 +08:00

451 lines
12 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "asm/includes.h"
#include "media/includes.h"
#include "system/includes.h"
#include "aec_user.h"
#include "asm/audio_src.h"
#include "audio_enc.h"
#include "app_main.h"
#include "app_action.h"
#include "clock_cfg.h"
#include "classic/hci_lmp.h"
/* #include "encode/encode_write.h" */
extern struct adc_platform_data adc_data;
extern int sbc_encoder_init();
extern int msbc_encoder_init();
extern int cvsd_encoder_init();
extern int mp3_encoder_init();
extern int adpcm_encoder_init();
extern int opus_encoder_preinit();
extern int speex_encoder_preinit();
struct audio_adc_hdl adc_hdl;
struct esco_enc_hdl *esco_enc = NULL;
struct audio_encoder_task *encode_task = NULL;
#define ESCO_ADC_BUF_NUM 3
#define ESCO_ADC_IRQ_POINTS 256
#define ESCO_ADC_BUFS_SIZE (ESCO_ADC_BUF_NUM * ESCO_ADC_IRQ_POINTS)
struct esco_enc_hdl {
struct audio_encoder encoder;
struct audio_adc_output_hdl adc_output;
struct adc_mic_ch mic_ch;
//OS_SEM pcm_frame_sem;
s16 output_frame[30]; //align 4Bytes
int pcm_frame[60]; //align 4Bytes
s16 adc_buf[ESCO_ADC_BUFS_SIZE]; //align 4Bytes
};
static void adc_mic_output_handler(void *priv, s16 *data, int len)
{
//printf("buf:%x,data:%x,len:%d",esco_enc->adc_buf,data,len);
audio_aec_inbuf(data, len);
}
static void adc_mic_output_handler_downsr(void *priv, s16 *data, int len)
{
//printf("buf:%x,data:%x,len:%d",esco_enc->adc_buf,data,len);
u16 i;
s16 temp_buf[128];
for (i = 0; i < len / 4; i++) {
temp_buf[i] = data[i * 2];
}
audio_aec_inbuf(temp_buf, len / 2);
}
__attribute__((weak)) int audio_aec_output_read(s16 *buf, u16 len)
{
return 0;
}
void esco_enc_resume(void)
{
if (esco_enc) {
//os_sem_post(&esco_enc->pcm_frame_sem);
audio_encoder_resume(esco_enc);
}
}
static int esco_enc_pcm_get(struct audio_encoder *encoder, s16 **frame, u16 frame_len)
{
int rlen = 0;
if (encoder == NULL) {
r_printf("encoder NULL");
}
struct esco_enc_hdl *enc = container_of(encoder, struct esco_enc_hdl, encoder);
if (enc == NULL) {
r_printf("enc NULL");
}
while (1) {
rlen = audio_aec_output_read(enc->pcm_frame, frame_len);
if (rlen == frame_len) {
/*esco编码读取数据正常*/
#if (RECORDER_MIX_EN)
recorder_mix_sco_data_write(enc->pcm_frame, frame_len);
#endif/*RECORDER_MIX_EN*/
break;
} else if (rlen == 0) {
/*esco编码读不到数,返回0*/
return 0;
/*esco编码读不到数pend住*/
/* int ret = os_sem_pend(&enc->pcm_frame_sem, 100);
if (ret == OS_TIMEOUT) {
r_printf("esco_enc pend timeout\n");
break;
} */
} else {
/*通话结束aec已经释放*/
printf("audio_enc end:%d\n", rlen);
rlen = 0;
break;
}
}
*frame = enc->pcm_frame;
return rlen;
}
static void esco_enc_pcm_put(struct audio_encoder *encoder, s16 *frame)
{
}
static const struct audio_enc_input esco_enc_input = {
.fget = esco_enc_pcm_get,
.fput = esco_enc_pcm_put,
};
static int esco_enc_probe_handler(struct audio_encoder *encoder)
{
return 0;
}
static int esco_enc_output_handler(struct audio_encoder *encoder, u8 *frame, int len)
{
lmp_private_send_esco_packet(NULL, frame, len);
//printf("frame:%x,out:%d\n",frame, len);
return len;
}
const static struct audio_enc_handler esco_enc_handler = {
.enc_probe = esco_enc_probe_handler,
.enc_output = esco_enc_output_handler,
};
static void esco_enc_event_handler(struct audio_decoder *decoder, int argc, int *argv)
{
printf("esco_enc_event_handler:0x%x,%d\n", argv[0], argv[0]);
switch (argv[0]) {
case AUDIO_ENC_EVENT_END:
puts("AUDIO_ENC_EVENT_END\n");
break;
}
}
int esco_enc_open(u32 coding_type, u8 frame_len)
{
int err;
struct audio_fmt fmt;
printf("esco_enc_open: %d,frame_len:%d\n", coding_type, frame_len);
fmt.channel = 1;
fmt.frame_len = frame_len;
if (coding_type == AUDIO_CODING_MSBC) {
fmt.sample_rate = 16000;
fmt.coding_type = AUDIO_CODING_MSBC;
clock_add(ENC_MSBC_CLK);
} else if (coding_type == AUDIO_CODING_CVSD) {
fmt.sample_rate = 8000;
fmt.coding_type = AUDIO_CODING_CVSD;
clock_add(ENC_CVSD_CLK);
} else {
/*Unsupoport eSCO Air Mode*/
}
#if (RECORDER_MIX_EN)
recorder_mix_pcm_set_info(fmt.sample_rate, fmt.channel);
#endif/*RECORDER_MIX_EN*/
/* if (!encode_task) { */
/* encode_task = zalloc(sizeof(*encode_task)); */
/* audio_encoder_task_create(encode_task, "audio_enc"); */
/* } */
audio_encoder_task_open();
if (!esco_enc) {
esco_enc = zalloc(sizeof(*esco_enc));
}
//os_sem_create(&esco_enc->pcm_frame_sem, 0);
audio_encoder_open(&esco_enc->encoder, &esco_enc_input, encode_task);
audio_encoder_set_handler(&esco_enc->encoder, &esco_enc_handler);
audio_encoder_set_fmt(&esco_enc->encoder, &fmt);
audio_encoder_set_event_handler(&esco_enc->encoder, esco_enc_event_handler, 0);
audio_encoder_set_output_buffs(&esco_enc->encoder, esco_enc->output_frame,
sizeof(esco_enc->output_frame), 1);
audio_encoder_start(&esco_enc->encoder);
printf("esco sample_rate: %d,mic_gain:%d\n", fmt.sample_rate, app_var.aec_mic_gain);
#if 0
audio_adc_mic_open(&esco_enc->mic_ch, AUDIO_ADC_MIC_CH, &adc_hdl);
audio_adc_mic_set_sample_rate(&esco_enc->mic_ch, fmt.sample_rate);
audio_adc_mic_set_gain(&esco_enc->mic_ch, app_var.aec_mic_gain);
audio_adc_mic_set_buffs(&esco_enc->mic_ch, esco_enc->adc_buf,
ESCO_ADC_IRQ_POINTS * 2, ESCO_ADC_BUF_NUM);
esco_enc->adc_output.handler = adc_mic_output_handler;
audio_adc_add_output_handler(&adc_hdl, &esco_enc->adc_output);
audio_adc_mic_start(&esco_enc->mic_ch);
#else
#if TCFG_MIC_EFFECT_ENABLE
if (fmt.sample_rate != MIC_EFFECT_SAMPLERATE) {
esco_enc->adc_output.handler = adc_mic_output_handler_downsr;
} else {
esco_enc->adc_output.handler = adc_mic_output_handler;
}
audio_mic_open(&esco_enc->mic_ch, MIC_EFFECT_SAMPLERATE, app_var.aec_mic_gain);
#else
esco_enc->adc_output.handler = adc_mic_output_handler;
audio_mic_open(&esco_enc->mic_ch, fmt.sample_rate, app_var.aec_mic_gain);
#endif
audio_mic_add_output(&esco_enc->adc_output);
audio_mic_start(&esco_enc->mic_ch);
#endif
clock_set_cur();
return 0;
}
void esco_enc_close()
{
printf("esco_enc_close\n");
if (!esco_enc) {
printf("esco_enc NULL\n");
return;
}
if (esco_enc->encoder.fmt.coding_type == AUDIO_CODING_MSBC) {
clock_remove(ENC_MSBC_CLK);
} else if (esco_enc->encoder.fmt.coding_type == AUDIO_CODING_CVSD) {
clock_remove(ENC_CVSD_CLK);
}
#if 0
audio_adc_mic_close(&esco_enc->mic_ch);
//os_sem_post(&esco_enc->pcm_frame_sem);
audio_encoder_close(&esco_enc->encoder);
audio_adc_del_output_handler(&adc_hdl, &esco_enc->adc_output);
#else
audio_mic_close(&esco_enc->mic_ch, &esco_enc->adc_output);
audio_encoder_close(&esco_enc->encoder);
#endif
local_irq_disable();
free(esco_enc);
esco_enc = NULL;
local_irq_enable();
audio_encoder_task_close();
/* if (encode_task) { */
/* audio_encoder_task_del(encode_task); */
/* local_irq_disable(); */
/* free(encode_task); */
/* encode_task = NULL; */
/* local_irq_enable(); */
/* } */
clock_set_cur();
}
struct __encoder_task {
u8 init_ok;
atomic_t used;
OS_MUTEX mutex;
};
static struct __encoder_task enc_task = {0};
int audio_encoder_task_open(void)
{
local_irq_disable();
if (enc_task.init_ok == 0) {
atomic_set(&enc_task.used, 0);
os_mutex_create(&enc_task.mutex);
enc_task.init_ok = 1;
}
local_irq_enable();
os_mutex_pend(&enc_task.mutex, 0);
if (!encode_task) {
encode_task = zalloc(sizeof(*encode_task));
audio_encoder_task_create(encode_task, "audio_enc");
}
atomic_inc_return(&enc_task.used);
os_mutex_post(&enc_task.mutex);
return 0;
}
void audio_encoder_task_close(void)
{
os_mutex_pend(&enc_task.mutex, 0);
if (encode_task) {
if (atomic_dec_and_test(&enc_task.used)) {
audio_encoder_task_del(encode_task);
//local_irq_disable();
free(encode_task);
encode_task = NULL;
//local_irq_enable();
}
}
os_mutex_post(&enc_task.mutex);
}
/**************************mic ladc 接口***************************************************/
#define MIC_ADC_BUF_NUM 2
#if TCFG_MIC_EFFECT_ENABLE
#define MIC_ADC_IRQ_POINTS 64 //不能随便更改
#else
#define MIC_ADC_IRQ_POINTS 256
#endif
#define MIC_ADC_BUFS_SIZE (MIC_ADC_BUF_NUM * MIC_ADC_IRQ_POINTS)
typedef struct {
struct audio_adc_hdl *p_adc_hdl;
struct adc_mic_ch mic_ch;
atomic_t used;
/* s16 adc_buf[MIC_ADC_BUFS_SIZE]; //align 4Bytes */
s16 *adc_buf;
OS_MUTEX mutex;
u8 init_flag: 2;
u8 states: 4;
u16 sample_rate;
} audio_mic_t;
static audio_mic_t mic_var = {.init_flag = 1};
int audio_mic_open(struct adc_mic_ch *mic, u16 sample_rate, u8 gain)
{
if (mic_var.init_flag) {
log_i("\n mic init_flag \n\n\n\n");
mic_var.init_flag = 0;
atomic_set(&mic_var.used, 0);
os_mutex_create(&mic_var.mutex);
mic_var.adc_buf = (s16 *)zalloc(MIC_ADC_BUFS_SIZE * 2);
mic_var.states = 0;
}
os_mutex_pend(&mic_var.mutex, 0);
if (!mic_var.adc_buf) {
log_i("\n mic malloc \n\n\n\n");
mic_var.adc_buf = (s16 *)zalloc(MIC_ADC_BUFS_SIZE * 2);
}
if (mic_var.states == 0) {
atomic_inc_return(&mic_var.used);
audio_adc_mic_open(mic, AUDIO_ADC_MIC_CH, &adc_hdl);
audio_adc_mic_set_sample_rate(mic, sample_rate);
audio_adc_mic_set_gain(mic, gain);
audio_adc_mic_set_buffs(mic, mic_var.adc_buf,
MIC_ADC_IRQ_POINTS * 2, MIC_ADC_BUF_NUM);
mic_var.sample_rate = sample_rate;
mic_var.states = 1;
} else {
if (mic_var.sample_rate != sample_rate) {
log_e("err: mic is on,sample_rate not match \n");
os_mutex_post(&mic_var.mutex);
return -1;
}
atomic_inc_return(&mic_var.used);
mic->hdl = &adc_hdl;
}
log_i("mic open success \n");
os_mutex_post(&mic_var.mutex);
return 0;
}
void audio_mic_add_output(struct audio_adc_output_hdl *output)
{
audio_adc_add_output_handler(&adc_hdl, output);
}
void audio_mic_start(struct adc_mic_ch *mic)
{
if (!mic || mic->hdl != &adc_hdl) {
log_i("\n adc_mic_ch not open \n");
return;
}
os_mutex_pend(&mic_var.mutex, 0);
if (adc_hdl.state != LADC_STATE_START) {
audio_adc_mic_start(mic);
}
os_mutex_post(&mic_var.mutex);
}
void audio_mic_close(struct adc_mic_ch *mic, struct audio_adc_output_hdl *output)
{
audio_adc_del_output_handler(&adc_hdl, output);
if (!mic || mic->hdl != &adc_hdl) {
log_i("\n adc_mic_ch not open \n");
return;
}
os_mutex_pend(&mic_var.mutex, 0);
if (atomic_dec_and_test(&mic_var.used)) {
log_i("\n audio_adc_mic_close \n");
audio_adc_mic_close(mic);
free(mic_var.adc_buf);
mic_var.adc_buf = NULL;
/* mic_var.init_flag =1; */
mic_var.states = 0;
}
os_mutex_post(&mic_var.mutex);
}
extern void audio_adc_set_mic_gain(struct audio_adc_hdl *adc, u8 gain);
void audio_mic_set_gain(u8 gain)
{
audio_adc_set_mic_gain(&adc_hdl, gain);
}
/*****************************************************************************/
//////////////////////////////////////////////////////////////////////////////
int g726_encoder_init();
int audio_enc_init()
{
printf("audio_enc_init\n");
#if TCFG_ENC_CVSD_ENABLE
cvsd_encoder_init();
#endif
#if TCFG_ENC_MSBC_ENABLE
msbc_encoder_init();
#endif
#if TCFG_ENC_MP3_ENABLE
mp3_encoder_init();
#endif
#if TCFG_ENC_ADPCM_ENABLE
adpcm_encoder_init();
#endif
#if TCFG_ENC_OPUS_ENABLE
opus_encoder_preinit();
#endif
#if TCFG_ENC_SPEEX_ENABLE
speex_encoder_preinit();
#endif
audio_adc_init(&adc_hdl, &adc_data);
#if TCFG_ENC_SBC_ENABLE
sbc_encoder_init();
#endif
return 0;
}