KDocs 研发资料库
  • 音频技术应用文档入口汇总
  • 杰理WINDOWS环境安装及其他事项
  • LINUX安装和编译
  • Linux环境编译SDK教程(ubuntu18.04)
  • 音频类补丁汇总表
  • 认证资料获取汇总(最新资料后台会更新)
  • 《Hi-Res申请指南v1.0》
  • FreeRTOS 开源协议版本
  • uCOS 开源协议版本信息
  • 各个模块关键资料汇总
  • 软件调试方法
  • Makefile编译
  • 提bug的规范
  • 常规设备使用指导
  • 对外特别发布开发注意点信息汇总
  • AD697X软件问题整理
  • AC700N软件问题整理
  • AC701X耳机软件问题整理
  • 951&961软件问题整理
  • AC104X软件问题整理
  • AC128N问题整理文档
  • 可视化工具调试问题整理
  • 耳机资料汇总
  • AC704N、 AC705N相关应用
  • AC695N&AC696N&AC608N音箱问题整理
  • JL701N音箱问题整理
  • AC692X软件问题整理
  • AC706N音箱问题整理
  • JL701N音箱问题整理(可视化工具SDK)
  • JL703N音箱问题整理
  • JL709N(JL689N)音箱问题整理
  • JL7094系列-入门到进阶开发指导
  • AC210N音箱问题整理
  • 无线麦系列版本支持指南
  • AW32N无线麦问题整理
  • lAD697X&JL701X 无线麦软件共性问题整理
  • AC706N无线麦问题整理
  • AW36N无线麦问题整理
  • AC710X无线麦问题整理
  • 唤醒源获取及唤醒IO设置
  • 电源
  • LVD
  • 长按复位配置方法
  • 低功耗应用
  • TIMER
  • UART
  • SPI
  • 内部FLASH空间添加用户自定义区域
  • IIC
  • GPIO
  • MCPWM
  • SD&U盘
  • 时钟&晶振
  • GPCNT
  • IO口crossbar映射功能
  • 文件系统使用总结
  • 复用应用
  • LINEIN_AUX相关应用
  • IIS音频接口应用
  • SPDIF模式相关(HDMI_ARC、光纤、同轴)
  • PDM LINK
  • 外设相关应用
  • 蓝牙相关
  • 杰理蓝牙距离调试文档
  • TWS耳机配对方式使用及生产把控指南
  • GFP谷歌快连及其认证流程指引
  • 蓝牙发射器(bt_emitter)相关
  • BLE应用
  • 关于提升BLE传输速率说明
  • BLE测试数据
  • MUSIC 模式相关应用
  • MIDI音乐实现
  • PC相关应用
  • FM相关应用
  • AC695N_AC696N FM天线ESD静电防护措施说明V2.0_20250107
  • fm应用详细设计说明书
  • 杰理FM硬件指南-20230315
  • ADC模块
  • AUDIO相关应用
  • 新Tools的音效调试使用
  • 混响应用使用说明
  • 音效调式
  • 音箱耳机低音小音量增强实现方法
  • DAC输出功率调试
  • DAC性能测试指南
  • 针对各类底噪、电流声分析流程
  • 录音相关应用
  • OPUS编解码相关
  • RTC相关应用
  • 升级相关
  • UI相关应用
  • 通话调试流程指南
  • 通话相关应用
  • 省电容mic使用手册
  • 如何测试验证手表通话系统的语音失真 V1.0
  • AC695X_AC696X_AD697X 常见通话问题处理参考资料
  • 通话调试问题确定步骤
  • 内置触摸调试指南
  • 低功耗内置触摸介绍V2.2
  • 触摸相关文档
  • AC697X、AC698X内置触摸调试及整改方法V1.0
  • 产测相关应用
  • AC63X BLE DUT测试介绍
  • 兆华序列使用简易说明
  • JL_1T2蓝牙测试盒音频文件更换说明
  • ENC相关应用入口汇总
  • ANC相关应用入口汇总
  • JL DMS通话调试手册-V3.9.4
  • ANC-ENC结构设计要点-20240407
  • 半入耳式ANC耳机器件选型与结构设计指南V1.0
  • JL 耳道自适应调试指南
  • ANC相关问题处理
  • ANC调试文档
  • 评估蓝牙耳机通话上行降噪性能的方法 V1.0 (2)
  • FCC 或者 BQB 认证相关应用
  • BQB profile 测试中常遇到的问题点汇总
  • 蓝牙参数整理20210811
  • 杰理科技认证问题参考
  • 无线音频产品开发指南
  • 无线麦系列从入门到进阶开发指导
  • 量产烧录相关说明
  • 一拖八烧录器远程过程调用说明
  • 量产相关建议
  • EffectTool(eq)调试工具说明文档
  • AC897AD697系列的EQ调试方法-V3
  • 杰理调音指南-20220622
  • 音效模块总结
  • 简要调音步骤指引(可视化)
  • 耳机充电与通信调试指南
  • 充电仓硬件调试指南
  • 充电仓软件问题整理
  • AC951常用说明
  • AC951_AC961_开发板使用说明V1.0
  • 彩屏仓AC982 入门指导及FAQ
  • 蓝牙音频APP相关应用
  • 手机APP的简介和开发流程
  • 蓝牙音频系列-硬件设计指南
  • 静电测试及整改方法-20220706
  • TWS耳机底噪整改指南V1.2
  • 杰理蓝牙距离调试文档
  • 蓝牙RF硬件设计与调试V1.1-20250219
  • AC695N_AC696N FM天线ESD静电防护措施说明V2.0_20241228
  • 音效调试指南
  • 无线话筒K歌音箱标准开发流程
  • 杰理科技 700N TWS耳机产品标准-202303
  • 杰理科技 701N 广播产品标准-202303
  • JL-HAT ANC高效产测自适应
  • 无线话筒测试板使用介绍
  • 一拖八频偏校准使用说明
  • 领夹麦产测工具使用介绍
  • Dongle量产测试说明
  • Dongle+Tws或头戴式 SDK通过工具绑定配对功能说明文档
  • 双麦ENC产测宏配置验证方法 V1.0
  • JL耳机方案麦克风声学测试指令_V1.0
  • JL耳机方案麦克风声学测试指令_V2.0
  • JL_ENC自动测试命令_V0.0.1
  • JL蓝牙测试盒用例说明
  • LDAC自测环境搭建_ubuntu
  • 延迟小板使用手册
  • 杰理库文件的制作及添加实现过程
  • 关于 AC635N&AC636N系列免晶振兼容性补丁 说明
  • 关于 AC63系列VM兼容性修复补丁_20250224 说明
  • 关于 AC632N &AE632N_ 蓝牙& 低功耗兼容性修复补丁 说明
  • AD698N和AC638N电压优化补丁V3说明
  • 关于 AC635N&AC636N漏电和E&G版兼容联合补丁 说明
  • AD698N和AC638N电压优化补丁V2说明
  • 702相关应用
  • 2024-4-30 发布歌词显示SDK开发注意事项
  • BQB RF & FCC 认证测试固件问题汇总及源码
  • BQB profile 测试中常遇到的问题点汇总
  • 进dut测试模式方法及固件
  • 704-频偏修改bin文件合集
  • 701手表BQB PROFILE认证注意事项
  • 认证的干扰规避整改
  • 海外CRA认证报告生成说明
  • JL700N可视化工具问题处理文档
  • JL701X可视化工具问题处理文档
  • JL701N_earphone_release_v1.6.0_ANC 低功耗问题补丁
  • JL708X可视化工具问题处理文档
  • JL709N可视化工具问题处理文档
  • JLstudio可视化工具使用说明
  • 一拖二-串口_蓝牙_app在线EQ、通话参数及调试方式和内置触摸调试
  • 可视化JL701M_DONGLE_SDK添加MIC为发射源
  • 可视化JL701M_DONGLE_SDK添加按键切换usb audio与MIC发射源
  • JL701M_DONGLE_SDK_1.0.0_dongle输入linein输出dac
  • 701可视化_a2dp_to_le_demo说明
  • 耳机系列demo汇总
  • JL7018F&JL7006F_7003F AUX IIS
  • 一键连接应用
  • 普通SDK动态开关一拖二功能
  • 蓝牙分析仪(EllisysBluetoothAnalyzer)抓包例程
  • TWS配对常见应用
  • APP自定义按键的demo
  • AC700N 播歌双EQ DEMO示例及说明
  • AC698V164 MIC与蓝牙音乐共同输出DAC demo
  • 添加第三方算法以及多算法授权流程
  • 空间音频配置方法
  • 普通高低电平TWS耳机控制通讯
  • 入耳检测状态更新demo解析
  • 资源优化(非可视化的SDK)
  • 资源优化(可视化SDK)
  • 翻译耳机、语音识别应用demo
  • 耳机抗干扰问题排查和优化
  • AC698D2 抗干扰优化
  • AC696X软件问题整理
  • AC695X软件问题整理
  • AC695X软件问题整理_1722249702
  • AC608X软件问题整理
  • JL701N_2T1_DUPLEX 应用软件问题汇总
  • le_audio_1.0.0_patch05 以及之前的版本IRkey 功能异常修改
  • AC706N-le_audio-200SDK有线_无线麦录音demo
  • jl701n_le_audio_v200patch02 IO串口升级修改串口单次发送字节长度的修改办法
  • 703创建IIS 输入dac输出音频流demo
  • 703将媒体流音频同时上传PC_mic录音demo实现
  • 703四路IIS输入输出demo
  • 底噪调试
  • AW328A烧录说明
  • 文档合集
  • AC706N_wireless_mic_release_PATCH_20240712 补丁 说明
  • AC706N_wireless_mic_release_PATCH_20240726 补丁 说明
  • AC706N_wireless_mic_release_V1.0.0、1.0.1、1.0.2 补丁 说明
  • AC706N_wireless_mic_release_V1.1.2 中的2T1应用 RX端不绑定配对,TX端实现绑定配对的修改方法
  • 各系列省晶振实现方法
  • iis tx rx说明文档
  • spdif信号
  • 蓝牙电话本
  • 安卓手机同步时间补丁
  • CDC配置
  • PC模式下增加Teams唤起功能
  • 杰理HDMIARC开发实现过程
  • AC701N patch06之前的版本用第三方算法节点实现新版本的pcm delay节点功能
  • (K歌音箱)各SDK音效配置相关说明
  • 长文件录音
  • 点阵屏歌词字库相关(蓝牙歌词,普通歌词)
  • 字模提取工具说明
  • 音箱可视化彩屏-入门到进阶开发指导
  • 彩屏LVGL UI设计及工具使用
  • 使用内部UI框架进行UI调试的系列步骤
  • AD101C使用强制升级工具spi 烧录不了问题处理(测试版本)
  • AD161扩展灯板说明文档
  • 歌词显示器开发注意项
  • 使用硬件数字增益控制通话下行音量(可视化)
  • 杰理小牛产测资料
  • ENC配置说明
  • 通话调试流程指引
  • ANC相关功能demo
  • 无线麦硬件资料汇总
  • 无线麦相关应用
  • 无线麦复杂功能补丁包汇总
  • 无线话筒形态SDK程序&开发经验&问题点分享
  • 双模式结合应用问题汇总
  • 无线麦距离优化案例
  • 无线麦系列中的双工形态(duplex)演变开发对讲机方案开发资料
  • 音箱入门到进阶指导文档(编写中)
  • 蓝牙耳机品控和生产技巧
  • 982过_欠压标志获取异常
  • 如何获取最新涂鸦SDK及库文件
  • 无线话筒K歌音响-调音标准流程
  • 无线话筒产测流程

AC698V164 MIC与蓝牙音乐共同输出DAC demo

📎 原始文档:https://www.kdocs.cn/l/cbvN1xXOohjD AC698V164 MIC与蓝牙音乐共同输出DAC demo

  1. 板级配置文件加入A2DP_OUT_MIXER_MIC,A2DP输出混合mic控制宏 image
  2. 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
  1. 使用按键控制mic数据流的开关
  2. key_event_deal.h加入新的按键事件id image
  3. 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;
  1. 板级配置.c文件加入按键事件id,KEY0单击控制(根据实际需求) image

  2. 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;

本文档包含以下子页面

Prev
AC700N 播歌双EQ DEMO示例及说明
Next
添加第三方算法以及多算法授权流程