265 lines
7.1 KiB
C
265 lines
7.1 KiB
C
|
#include "asm/includes.h"
|
||
|
#include "media/includes.h"
|
||
|
#include "system/includes.h"
|
||
|
#include "asm/audio_src.h"
|
||
|
#include "audio_enc.h"
|
||
|
#include "app_main.h"
|
||
|
#include "btstack/avctp_user.h"
|
||
|
#include "app_config.h"
|
||
|
#ifndef CONFIG_LITE_AUDIO
|
||
|
#include "aec_user.h"
|
||
|
#endif/*CONFIG_LITE_AUDIO*/
|
||
|
|
||
|
#if (TCFG_ENC_OPUS_ENABLE) || (TCFG_ENC_SPEEX_ENABLE)
|
||
|
|
||
|
extern struct audio_encoder_task *encode_task;
|
||
|
//static struct audio_encoder_task *encode_task = NULL;
|
||
|
|
||
|
#define ENC_ADC_BUF_NUM (2)
|
||
|
#define ENC_ADC_IRQ_POINTS (320)
|
||
|
#define ENC_ADC_BUFS_SIZE (ENC_ADC_BUF_NUM * ENC_ADC_IRQ_POINTS)
|
||
|
|
||
|
#define MIC_USE_MIC_CHANNEL (1)
|
||
|
#define MIC_ENC_IN_SIZE (ENC_ADC_IRQ_POINTS * 2)
|
||
|
#define MIC_ENC_OUT_SIZE (ENC_ADC_IRQ_POINTS)
|
||
|
|
||
|
struct mic_enc_hdl {
|
||
|
struct audio_encoder encoder;
|
||
|
OS_SEM pcm_frame_sem;
|
||
|
u8 output_frame[MIC_ENC_OUT_SIZE];
|
||
|
u8 pcm_frame[MIC_ENC_IN_SIZE];
|
||
|
u8 frame_size;
|
||
|
u8 in_cbuf_buf[MIC_ENC_IN_SIZE * 4];
|
||
|
cbuffer_t pcm_in_cbuf;
|
||
|
int (*mic_output)(void *priv, void *buf, int len);
|
||
|
#if mic_ENC_PACK_ENABLE
|
||
|
u16 cp_type;
|
||
|
u16 packet_head_sn;
|
||
|
#endif
|
||
|
#if MIC_USE_MIC_CHANNEL
|
||
|
struct audio_adc_output_hdl adc_output;
|
||
|
struct adc_mic_ch mic_ch;
|
||
|
s16 adc_buf[ENC_ADC_BUFS_SIZE]; //align 4Bytes
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
static struct mic_enc_hdl *mic_enc = NULL;
|
||
|
|
||
|
static void mic_enc_output_func_register(int (*output_func)(void *priv, void *buf, int len))
|
||
|
{
|
||
|
if (mic_enc) {
|
||
|
mic_enc->mic_output = output_func;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void mic_enc_resume(void)
|
||
|
{
|
||
|
if (mic_enc) {
|
||
|
os_sem_post(&mic_enc->pcm_frame_sem);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static int mic_enc_pcm_get(struct audio_encoder *encoder, s16 **frame, u16 frame_len)
|
||
|
{
|
||
|
int pcm_len = 0;
|
||
|
if (mic_enc == NULL) {
|
||
|
r_printf("mic_enc NULL\n");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* putchar('!'); */
|
||
|
if ((&mic_enc->pcm_in_cbuf)->data_len < frame_len) {
|
||
|
/* putchar('#'); */
|
||
|
os_sem_set(&mic_enc->pcm_frame_sem, 0);
|
||
|
os_sem_pend(&mic_enc->pcm_frame_sem, 5);
|
||
|
if (mic_enc == NULL) {
|
||
|
printf("mic_enc is NULL\n");
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pcm_len = cbuf_read(&mic_enc->pcm_in_cbuf, mic_enc->pcm_frame, frame_len);
|
||
|
if (pcm_len != frame_len) {
|
||
|
putchar('L');
|
||
|
}
|
||
|
/* putchar('D'); */
|
||
|
|
||
|
*frame = mic_enc->pcm_frame;
|
||
|
return pcm_len;
|
||
|
}
|
||
|
|
||
|
static void mic_enc_pcm_put(struct audio_encoder *encoder, s16 *frame)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
static const struct audio_enc_input mic_enc_input = {
|
||
|
.fget = mic_enc_pcm_get,
|
||
|
.fput = mic_enc_pcm_put,
|
||
|
};
|
||
|
|
||
|
static int mic_enc_probe_handler(struct audio_encoder *encoder)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
static int mic_enc_output_handler(struct audio_encoder *encoder, u8 *frame, int len)
|
||
|
{
|
||
|
if (encoder == NULL) {
|
||
|
r_printf("encoder NULL");
|
||
|
}
|
||
|
wdt_clear();
|
||
|
/* printf("mic frame len:%d \n",len); */
|
||
|
if (mic_enc && mic_enc->mic_output) {
|
||
|
mic_enc->mic_output(NULL, frame, len);
|
||
|
}
|
||
|
/* put_buf(frame, 16); */
|
||
|
return len;
|
||
|
}
|
||
|
|
||
|
const static struct audio_enc_handler mic_enc_handler = {
|
||
|
.enc_probe = mic_enc_probe_handler,
|
||
|
.enc_output = mic_enc_output_handler,
|
||
|
};
|
||
|
|
||
|
static void mic_enc_event_handler(struct audio_decoder *decoder, int argc, int *argv)
|
||
|
{
|
||
|
printf("mic_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;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
static void adc_mic_output_handler(void *priv, s16 *data, int len)
|
||
|
{
|
||
|
if (mic_enc) {
|
||
|
u16 wlen = cbuf_write(&mic_enc->pcm_in_cbuf, data, len);
|
||
|
if (wlen != len) {
|
||
|
putchar('@');
|
||
|
}
|
||
|
audio_encoder_resume(&mic_enc->encoder);
|
||
|
mic_enc_resume();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
#define HIGHT_COMPLEX 0
|
||
|
#define LOW_COMPLEX (BIT(4))
|
||
|
|
||
|
|
||
|
extern struct audio_adc_hdl adc_hdl;
|
||
|
int audio_mic_enc_open(int (*mic_output)(void *priv, void *buf, int len), u32 code_type, u8 ai_type)
|
||
|
{
|
||
|
int err;
|
||
|
struct audio_fmt fmt;
|
||
|
|
||
|
switch (code_type) {
|
||
|
case AUDIO_CODING_OPUS:
|
||
|
//1. quality:bitrate 0:16kbps 1:32kbps 2:64kbps
|
||
|
// quality: MSB_2:(bit7_bit6) format_mode //0:百度_无头. 1:酷狗_eng+range.
|
||
|
// quality:LMSB_2:(bit5_bit4) low_complexity //0:高复杂度,高质量.兼容之前库. 1:低复杂度,低质量.
|
||
|
//2. sample_rate sample_rate=16k ignore
|
||
|
fmt.quality = 0 | ai_type /*| LOW_COMPLEX*/;
|
||
|
fmt.sample_rate = 16000;
|
||
|
fmt.coding_type = AUDIO_CODING_OPUS;
|
||
|
break;
|
||
|
case AUDIO_CODING_SPEEX:
|
||
|
fmt.quality = 5;
|
||
|
fmt.complexity = 2;
|
||
|
fmt.sample_rate = 16000;
|
||
|
fmt.coding_type = AUDIO_CODING_SPEEX;
|
||
|
break;
|
||
|
default:
|
||
|
printf("do not support this type !!!\n");
|
||
|
return -1;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
audio_encoder_task_open();
|
||
|
/* if (!encode_task) { */
|
||
|
/* encode_task = zalloc(sizeof(*encode_task)); */
|
||
|
/* if (!encode_task) { */
|
||
|
/* printf("encode_task NULL !!!\n"); */
|
||
|
/* } */
|
||
|
/* audio_encoder_task_create(encode_task, "audio_enc"); */
|
||
|
/* } */
|
||
|
if (!mic_enc) {
|
||
|
mic_enc = zalloc(sizeof(*mic_enc));
|
||
|
if (!mic_enc) {
|
||
|
printf("mic_enc NULL !!!\n");
|
||
|
}
|
||
|
memset(mic_enc, 0x00, sizeof(*mic_enc));
|
||
|
}
|
||
|
|
||
|
mic_enc_output_func_register(mic_output);
|
||
|
cbuf_init(&mic_enc->pcm_in_cbuf, mic_enc->in_cbuf_buf, MIC_ENC_IN_SIZE * 4);
|
||
|
os_sem_create(&mic_enc->pcm_frame_sem, 0);
|
||
|
audio_encoder_open(&mic_enc->encoder, &mic_enc_input, encode_task);
|
||
|
audio_encoder_set_handler(&mic_enc->encoder, &mic_enc_handler);
|
||
|
audio_encoder_set_fmt(&mic_enc->encoder, &fmt);
|
||
|
audio_encoder_set_event_handler(&mic_enc->encoder, mic_enc_event_handler, 0);
|
||
|
audio_encoder_set_output_buffs(&mic_enc->encoder, mic_enc->output_frame,
|
||
|
sizeof(mic_enc->output_frame), 1);
|
||
|
int start_err = audio_encoder_start(&mic_enc->encoder);
|
||
|
|
||
|
#if MIC_USE_MIC_CHANNEL
|
||
|
fmt.sample_rate = 16000;
|
||
|
audio_adc_mic_open(&mic_enc->mic_ch, AUDIO_ADC_MIC_CH, &adc_hdl);
|
||
|
audio_adc_mic_set_sample_rate(&mic_enc->mic_ch, fmt.sample_rate);
|
||
|
app_var.aec_mic_gain = 15;
|
||
|
printf(">>>>>>>>>mic gain:%d \n", app_var.aec_mic_gain);
|
||
|
audio_adc_mic_set_gain(&mic_enc->mic_ch, app_var.aec_mic_gain);
|
||
|
audio_adc_mic_set_buffs(&mic_enc->mic_ch, mic_enc->adc_buf,
|
||
|
ENC_ADC_IRQ_POINTS * 2, ENC_ADC_BUF_NUM);
|
||
|
mic_enc->adc_output.handler = adc_mic_output_handler;
|
||
|
audio_adc_add_output_handler(&adc_hdl, &mic_enc->adc_output);
|
||
|
|
||
|
|
||
|
//app_audio_output_samplerate_set(44100);
|
||
|
//app_audio_output_start();
|
||
|
audio_adc_mic_start(&mic_enc->mic_ch);
|
||
|
#endif
|
||
|
|
||
|
printf("mic_enc_open ok %d\n", start_err);
|
||
|
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int audio_mic_enc_close()
|
||
|
{
|
||
|
if (!mic_enc) {
|
||
|
return -1;
|
||
|
}
|
||
|
printf("audio_mic_enc_close\n");
|
||
|
#if MIC_USE_MIC_CHANNEL
|
||
|
audio_adc_mic_close(&mic_enc->mic_ch);
|
||
|
audio_adc_del_output_handler(&adc_hdl, &mic_enc->adc_output);
|
||
|
#endif
|
||
|
mic_enc_resume();
|
||
|
audio_encoder_close(&mic_enc->encoder);
|
||
|
|
||
|
audio_encoder_task_close();
|
||
|
/* if (encode_task) { */
|
||
|
/* audio_encoder_task_del(encode_task); */
|
||
|
/* free(encode_task); */
|
||
|
/* encode_task = NULL; */
|
||
|
/* } */
|
||
|
|
||
|
free(mic_enc);
|
||
|
mic_enc = NULL;
|
||
|
|
||
|
printf("audio_mic_enc_close end\n");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
#endif
|