AC698V164 MIC与蓝牙音乐共同输出DAC demo
📎 原始文档:https://www.kdocs.cn/l/cbvN1xXOohjD AC698V164 MIC与蓝牙音乐共同输出DAC demo
- 板级配置文件加入A2DP_OUT_MIXER_MIC,A2DP输出混合mic控制宏

- audio_dec.c文件添加下列代码 【金山文档】 AC698V164MIC与蓝牙音乐共同输出DAC demo.c
https://kdocs.cn/l/cp2cBg3KPWEm
【金山文档】 ad698n_earphone_release_v1.6.4_add_mic2dac
https://kdocs.cn/l/cvoN5k52xvsA
//adc解码结构体及宏定义
#if A2DP_OUT_MIXER_MIC
#define ADC_DEC_BUF_NUM 2
#define ADC_DEC_IRQ_POINTS 256
#define ADC_DEC_BUFS_SIZE (ADC_DEC_BUF_NUM * ADC_DEC_IRQ_POINTS)
struct adc_dec_handle {
u8 start;
u8 remain;
u8 adc_2_sbuff;
struct adc_mic_ch mic_ch;
u8 output_buf[1024*4];
cbuffer_t output_cbuf;
//s16 adc_buf[ADC_DEC_BUFS_SIZE]; //align 4Bytes
//s16 adc_sbuff[ADC_DEC_BUFS_SIZE];
struct audio_adc_output_hdl adc_output;
struct audio_res_wait wait;
struct audio_decoder decoder;
#if AUDIO_OUT_MIXER_ENABLE
struct audio_mixer_ch mix_ch;
#endif
};
static struct adc_dec_handle *adc_dec;
//获取adc buff
static int adc_fread(struct audio_decoder *decoder, void *buf, u32 len)
{
//printf("adc_fread len:%d\n",len);
//s16 *data = (s16*)buf;
local_irq_disable();
if (!adc_dec)
{
printf("adc_fread close now");
local_irq_enable();
return -EINVAL;
}
u16 rlen = cbuf_read(&adc_dec->output_cbuf, buf, len);
//printf("buf:%d %d %d %d\n",data[0],data[1],data[2],data[3]);
if (rlen == 0) {
putchar('N');
rlen = len;
}
local_irq_enable();
return rlen;
}
//解码输入源
static const struct audio_dec_input adc_input = {
.coding_type = AUDIO_CODING_PCM,
.data_type = AUDIO_INPUT_FILE,
.ops = {
.file = {
.fread = adc_fread,
}
}
};
static int adc_wait_res_handler(struct audio_res_wait *wait, int event)
{
int err = 0;
if (event == AUDIO_RES_GET) {
printf("adc_wait_res_handler\n");
err = adc_dec_start();
} else if (event == AUDIO_RES_PUT) {
}
return err;
}
static void adc_mic_to_dec_output(void *priv, s16 *data, int len)
{
putchar('o');
//printf("adc_mic_to_dec_output len:%d\n",len);
if (adc_dec && adc_dec->adc_2_sbuff)
{
u16 wlen = cbuf_write(&adc_dec->output_cbuf, data, len);
audio_decoder_resume(&adc_dec->decoder);
//printf("adc_mic_to_dec_output wlen:%d\n",wlen);
//printf("adc_mic_to_dec_output data=%d %d %d %d\n",data[0],data[1],data[2],data[3]);
}
//printf("adc:%x,len:%d\n",data,len);
//printf("wlen:%d\n",wlen);
}
void audio_adc_mic_to_music_open(u8 adc_2_sbuff)
{
if (adc_dec)
{
printf("open adc mic channel\n");
audio_adc_mic_open(&adc_dec->mic_ch, AUDIO_ADC_MIC_CH, &adc_hdl);
audio_adc_mic_set_sample_rate(&adc_dec->mic_ch, 44100);
audio_adc_mic_set_gain(&adc_dec->mic_ch, 10);
audio_adc_mic_set_buffs(&adc_dec->mic_ch, adc_dec->output_buf, 256 * 2, 2);
adc_dec->adc_output.handler = adc_mic_to_dec_output;
audio_adc_add_output_handler(&adc_hdl, &adc_dec->adc_output);
audio_adc_mic_start(&adc_dec->mic_ch);
}
adc_dec->adc_2_sbuff = adc_2_sbuff;
}
void audio_adc_mic_to_music_close()
{
if (adc_dec) {
audio_adc_del_output_handler(&adc_hdl, &adc_dec->adc_output);
audio_adc_mic_close(&adc_dec->mic_ch);
free(adc_dec);
adc_dec = NULL;
}
}
//打开解码
int adc_dec_open(void)
{
if(adc_dec)
{
adc_dec_close();
if (adc_dec)
{
return 0;
}
}
int err = 0;
printf("adc_dec_open\n");
adc_dec = zalloc(sizeof(*adc_dec));
if (!adc_dec) {
printf("adc_dec zalloc failed");
return -ENOMEM;
}
//开mic
adc_dec->wait.priority = 0;
adc_dec->wait.preemption = 0;
adc_dec->wait.handler = adc_wait_res_handler;
audio_decoder_task_add_wait(&decode_task, &adc_dec->wait);
if(adc_dec && (adc_dec->start==0))
{
err = adc_dec_start();
}
return err;
}
//释放资源
static void adc_dec_release()
{
audio_adc_mic_to_music_close();
}
//关闭解码
int adc_dec_close(void)
{
if (!adc_dec)
{
printf("!adc_dec\n");
return 0;
}
printf("adc_dec_close\n");
audio_decoder_close(&adc_dec->decoder);
#if AUDIO_OUT_MIXER_ENABLE
audio_mixer_ch_close(&adc_dec->mix_ch);
#else
audio_output_close(NULL);
#endif
audio_codec_clock_del(AUDIO_A2DP_MODE);
audio_decoder_task_del_wait(&decode_task,&adc_dec->wait);
adc_dec_release();
return 0;
}
//解码处理
static int adc_dec_probe_handler(struct audio_decoder *decoder)
{
int channel = audio_dac_get_channel(&dac_hdl) == DAC_OUTPUT_LR ? 2 : 1;
int sample_rate = audio_mixer_get_sample_rate(&mixer);
if (sample_rate == 0)
{
sample_rate = 44100;
}
//printf("ADC_DEC: %d, %d\n", sample_rate, channel);
#if AUDIO_OUT_MIXER_ENABLE
audio_mixer_ch_set_sample_rate(&adc_dec->mix_ch, sample_rate);
#endif
return 0;
}
//解码输出
static int adc_dec_output_handler(struct audio_decoder *decoder, s16 *data, int len, void *priv)
{
//printf("adc_dec_output_handler\n");
//putchar('u');
#if AUDIO_OUT_MIXER_ENABLE
int wlen = audio_mixer_ch_write(&adc_dec->mix_ch, data, len);
#else
int wlen = audio_output_data(data, len);
#endif
if (wlen != len) {
adc_dec->remain = 1;
} else {
adc_dec->remain = 0;
}
return wlen;
}
static int adc_dec_post_handler(struct audio_decoder *decoder)
{
return 0;
}
//解码回调
const struct audio_dec_handler adc_dec_handler = {
.dec_probe = adc_dec_probe_handler,
.dec_output = adc_dec_output_handler,
.dec_post = adc_dec_post_handler,
};
//解码事件处理
static void adc_dec_event_handler(struct audio_decoder *decoder, int argc, int *argv)
{
printf("adc_dec_event_handler:%x", argv[0]);
switch (argv[0]) {
case AUDIO_DEC_EVENT_END:
case AUDIO_DEC_EVENT_ERR:
printf("adc_dec err\n");
adc_dec_close();
break;
default:
return;
}
}
//开始解码
int adc_dec_start()
{
if (!adc_dec) {
printf("!adc_dec\n");
return -EINVAL;
}
if (adc_dec->start) {
printf("adc_dec->start = 1\n");
return 0;
}
printf("adc_dec_start\n");
//cbuf 初始化
cbuf_init(&adc_dec->output_cbuf, adc_dec->output_buf, sizeof(adc_dec->output_buf));
int err;
int decode_task_state;
struct audio_fmt f;
err = audio_decoder_open(&adc_dec->decoder, &adc_input, &decode_task);
if (err) {
return err;
}
//设置格式
f.coding_type = AUDIO_CODING_PCM;
f.sample_rate = 44100;
f.channel = 1;
audio_decoder_set_fmt(&adc_dec->decoder,&f);
printf("fmt->channel = %d\n",f.channel);
printf("fmt->sample_rate = %d\n",f.sample_rate);
printf("fmt->coding_type = %d\n",f.coding_type);
audio_codec_clock_set(AUDIO_A2DP_MODE, AUDIO_CODING_SBC, adc_dec->wait.preemption);
audio_decoder_set_handler(&adc_dec->decoder, &adc_dec_handler);
audio_decoder_set_event_handler(&adc_dec->decoder, adc_dec_event_handler, 0);
//设置音量
app_audio_state_switch(APP_AUDIO_STATE_MUSIC, get_max_sys_vol());
app_audio_set_volume(APP_AUDIO_STATE_MUSIC, 16, 1);
#if AUDIO_OUT_MIXER_ENABLE
audio_mixer_ch_open(&adc_dec->mix_ch, &mixer);
audio_mixer_ch_set_resume_handler(&adc_dec->mix_ch, (void *)&adc_dec->decoder, (void (*)(void *))audio_decoder_resume);
#else
audio_output_open(NULL, 44100);
#endif
//开mic
audio_adc_mic_to_music_open(1);
err = audio_decoder_start(&adc_dec->decoder);
if (err) {
printf("adc_dec->decoder err\n");
goto __err1;
}
adc_dec->start = 1;
return 0;
__err1:
#if AUDIO_OUT_MIXER_ENABLE
audio_mixer_ch_close(&adc_dec->mix_ch);
#else
audio_output_close(NULL);
#endif
}
#endif
- 使用按键控制mic数据流的开关
- key_event_deal.h加入新的按键事件id

- key_event_deal.c的app_earphone_key_event_handler中增加按键事件处理函数
bool mic_on_flag = 0;//全局变量
//按键开关mic事件处理
case KEY_MIC_ON_OFF:
#if A2DP_OUT_MIXER_MIC
printf("KEY_MIC_ON\n");
//clk_set("sys",120*1000000L);
if(mic_on_flag == 0)
{
adc_dec_open();
mic_on_flag =1;
}
else
{
adc_dec_close();
mic_on_flag = 0;
}
#endif
break;
板级配置.c文件加入按键事件id,KEY0单击控制(根据实际需求)

earphone.c中bt_connction_status_event_handler中更改播歌处理流程
//蓝牙播歌流程
case BT_STATUS_A2DP_MEDIA_START:
log_info(" BT_STATUS_A2DP_MEDIA_START:0x%x", bt->value);
#if A2DP_OUT_MIXER_MIC
extern mic_on_flag;
if(mic_on_flag == 0)
{
//mic没开,直接播音乐
a2dp_dec_open(bt->value);
}
else
{
//mic开了,关mic再开音乐再开mic,防止解码抢占,造成播歌无声
adc_dec_close();
a2dp_dec_open(bt->value);
adc_dec_open();
}
#else
a2dp_dec_open(bt->value);
#endif
break;