3. WIFI_STORY_MACHINE 工程说明

3.1. wifi_story_machine工程简介

  • 该工程方案具有绘本故事机和WIFI智能音箱的应用

  • 绘本故事机应用于儿童类绘本识别故事机用于给儿童进行故事绘本、课本等书物叙述,儿童与家长进行设备与手机公众号的微聊聊天,儿童进行打断唤醒的交互交流,小程序的资源点播学习

  • 智能WIFI音箱应用于连接WIFI进行网络资源播放或连接蓝牙进行蓝牙播放,也可进行FLASH、SD卡和U盘播放

  • 该工程具有的功能有蓝牙EDR功能、BLE功能、音频播放功能、录音功能、音效处理、配网功能和接入第三方SDK功能,具体功能如下图所示

3.2. wifi_story_machine工程操作说明

  • 查看快速入门文档中的开发准备说明、开发环境安装说明、SDK工程编译与下载和SDK应用开发说明

  • 工程打开路径: apps/wifi_story_machine/board/wl82/AC791N_WIFI_STORY_MACHINE.cbp

  • 打开工程后SDK中选择开发板对应的板级: Headers/apps/wifi_story_machine/board/wl82/board_config.h 中选择对应的板级宏打开,如下图以打开7916开源学习板级为例

/*
*  板级配置选择,需要删去app_config.h中前面跟此头文件重复的宏定义,不然此头文件宏定义无效
*/

// #define CONFIG_BOARD_7911B
// #define CONFIG_BOARD_7911D
// #define CONFIG_BOARD_7912D
// #define CONFIG_BOARD_7913A
#define CONFIG_BOARD_7916A

// #define CONFIG_BOARD_DUI
// #define CONFIG_BOARD_DEMO
#define CONFIG_BOARD_DEVELOP
  • 在app_config.h中选择需要使用的功能和平台将其宏打开

  • 进行编译烧录使用

  • 按键操作说明:
    • K1:短按打开/关闭麦克风;长按开/关机

    • K2:短按进入/退出绘本识别模式;长按进入/退出混响模式

    • K3:短按进入翻译模式/智能聊天模式;长按进入按键唤醒

    • K4:短按提示音长按进入聊天;长按收集语音信息松开发送到微信小程序

    • K5:短按打开/关闭蓝牙;长按进入配网模式,再次长按连接记忆过的wifi

    • K6:短按进行本地flash播放模式/SD卡播放模式/U盘播放模式/FM模式/网络播放模式切换;长按进行下一个文件夹播放

    • K7:短按暂停/播放,长按蓝牙发射器主/从机模式切换

    • K8:增大音量

    • K9:减小音量

3.3. wifi_story_machine工程代码流程重点讲解

  • 1.app_mian.c:app_main()入口:使能故事机主工程,创建故事机app_music的app_state_machine_test_task任务,当使能蓝牙功能并且WIFI功能未打开时初始化蓝牙功能模块。

/*
* 应用程序主函数
*/
void app_main()
{
    struct intent it;

    puts("------------- wifi_story_machine app main-------------\n");

    init_intent(&it);
    it.name = "app_music";
    it.action = ACTION_MUSIC_PLAY_MAIN;
    start_app(&it);

#if defined CONFIG_BT_ENABLE && !defined CONFIG_WIFI_ENABLE
    extern void bt_ble_module_init(void);
    bt_ble_module_init();
#endif
}
  • 2.app_music.c:app_music_state_machine():app状态机选择app_main()应用程序主函数中选择的的action运行进入app_music_main函数。

//......
case APP_STA_START:
        if (!it) {
            break;
        }
        switch (it->action) {
        case ACTION_MUSIC_PLAY_MAIN:
            app_music_main();
            break;
//......

3.4. wifi_story_machine工程功能配置说明

  • 1.音频播放部分:编解码流程可参考“音频部分”文档中“音频编码”和“音频解码”
    • 1.1本地播放可选择FLASH、SD卡和U盘之间切换,通过扫描文件和搜索音频格式进行选择解码播放。想要添加FLASH播放歌曲, 可以在对应的app_music.c文件中加入数组, 然后在 cpu\wl82\tools\audlogo 路径下添加相应的音频。

    //释放资源,切换播放源设备
    static int local_music_switch_local_device(const char *path)
    {//SD卡、U盘切换
        log_i("local_music_switch_local_device\n");
    
        if (__this->dir_list) {//搜索文件夹
            fscan_release(__this->dir_list);
            __this->dir_list = NULL;
        }
        if (__this->fscan) {//扫描文件
            fscan_release(__this->fscan);
            __this->fscan = NULL;
        }
        if (__this->wait_sd) {//等待SD卡挂载
            wait_completion_del(__this->wait_sd);
            __this->wait_sd = 0;
        }
        if (__this->wait_udisk) {//等待U盘挂载
            wait_completion_del(__this->wait_udisk);
            __this->wait_udisk = 0;
        }
    
        local_music_dec_stop();//播放结束
    
        if (path == NULL) {
            return -1;
        }
    
        __this->local_path = path;//播放路径
    
        local_music_dec_switch_dir(FSEL_FIRST_FILE);//本地播放选择文件夹
    
        return 0;
    }
    
    • 1.2网络播歌:可进行网络音频资源播放或使用DLNA功能:将同局域网内可进行DLNA投播的设备音频投放到设备上播放。通过将网络文件数据缓存在网络缓存区后进行读取播放。

    • 1.3FM电台:具体FM电台说明可参考“应用示例”中FM电台文档

    //app_config.h:
    #define CONFIG_FM_DEV_ENABLE                1        //打开外挂FM模块功能
    #define CONFIG_FM_LINEIN_ADC_GAIN           100
    #define CONFIG_FM_LINEIN_ADC_CHANNEL        3        //FM音频流回采AD通道
    #define TCFG_FM_QN8035_ENABLE               1
    #define TCFG_FM_BK1080_ENABLE               0
    #define TCFG_FM_RDA5807_ENABLE              0
    
    //board.c 板级iic配置,使用硬件iic0
    { "iic1",  &iic_dev_ops, (void *)&sw_iic0_data },
    { "iic0",  &iic_dev_ops, (void *)&hw_iic1_data },
    
  • 2.蓝牙播歌和蓝牙通话部分及蓝牙发射器
    • 2.1需在app_conifg中配置开启蓝牙功能宏(选择下图中需要宏打开),短按K5按键打开蓝牙,可使用蓝牙播歌和通话功能:bt_ble_module_init()入口:调用bt_function_select_init()函数进行蓝牙功能初始化,包括音量、连接自动播放、更新电量、回连搜索、蓝牙加密等级和蓝牙设备类型等功能。调用bredr_handle_register()函数进行功能任务注册,包括蓝牙传输数据、蓝牙音乐和通话音量同步、电量显示获取电量的接口、被测试盒链接上进入快速测试回调、样机进入dut被测试仪器链接上回调、获取远端设备蓝牙名字回调、获取歌曲信息回调、发射器设置回调等。调用btstack_init()函数进行蓝牙协议栈初始化。

    //*********************************************************************************//
    //                                  BT_BLE配置                                     //
    //*********************************************************************************//
    #ifdef CONFIG_BT_ENABLE
    
    #define BT_EMITTER_EN     1
    #define BT_RECEIVER_EN    2
    
    #if defined CONFIG_CPU_WL82 && defined CONFIG_ASR_ALGORITHM && defined CONFIG_VIDEO_ENABLE
    #define CONFIG_BT_RX_BUFF_SIZE  (10 * 1024 + 512)
    #define CONFIG_BT_TX_BUFF_SIZE  (6 * 1024)
    #else
    #define CONFIG_BT_RX_BUFF_SIZE  (12 * 1024)
    #define CONFIG_BT_TX_BUFF_SIZE  (6 * 1024)
    #endif
    
    #define CONFIG_POWER_ON_ENABLE_BT                 0     //开机自动打开经典蓝牙
    #define CONFIG_POWER_ON_ENABLE_BLE                0     //开机自动打开BLE
    #define TCFG_BD_NUM                                                       1
    #define TCFG_USER_BT_CLASSIC_ENABLE               1     //经典蓝牙功能
    #define TCFG_USER_TWS_ENABLE                      0     //tws功能使能
    #define TCFG_USER_BLE_ENABLE                      1     //BLE功能使能
    #define TCFG_USER_EDR_ENABLE                      0     //EDR用户自定义协议功能
    #define TCFG_USER_EMITTER_ENABLE                  1     //蓝牙发射功能
    #ifdef CONFIG_LOW_POWER_ENABLE
    #define TCFG_BT_SNIFF_ENABLE                      1
    #else
    #define TCFG_BT_SNIFF_ENABLE                      0
    #endif
    #define BT_SUPPORT_MUSIC_VOL_SYNC                 0     //音量同步
    #define BT_SUPPORT_DISPLAY_BAT                    1     //电池电量同步显示功能
    #define BT_SUPPORT_EMITTER_AUTO_A2DP_START        1     //发射器连上后自动打开A2DP流
    
     void bt_ble_module_init(void)
    {
        bt_function_select_init();
        bredr_handle_register();
        btstack_init();
    }
    
    static void bt_function_select_init(void)
    {
        /* __set_a2dp_auto_play_flag(1); */
        __set_user_ctrl_conn_num(TCFG_BD_NUM);
        __set_support_msbc_flag(1);
        __set_support_aac_flag(0);
    #if BT_SUPPORT_DISPLAY_BAT
        __bt_set_update_battery_time(60);
    #else
        __bt_set_update_battery_time(0);
    #endif
        __set_page_timeout_value(8000); /*回连搜索时间长度设置,可使用该函数注册使用,ms单位,u16*/
        __set_super_timeout_value(8000); /*回连时超时参数设置。ms单位。做主机有效*/
    
        __set_simple_pair_flag(1); //是否打开简易配对功能,打开后不需要输入pincode
        ////设置蓝牙加密的level
        //io_capabilities ; /*0: Display only 1: Display YesNo 2: KeyboardOnly 3: NoInputNoOutput*/
        //authentication_requirements: 0:not protect  1 :protect
        __set_simple_pair_param(3, 0, 2);
    
    #if (USER_SUPPORT_PROFILE_PBAP==1)
        ////设置蓝牙设备类型
        __change_hci_class_type(BD_CLASS_CAR_AUDIO);
    #endif
    
    #if (TCFG_BT_SNIFF_ENABLE == 0)
        void lmp_set_sniff_disable(void);
        lmp_set_sniff_disable();
    #endif
    
    #if TCFG_USER_BLE_ENABLE
        u8 tmp_ble_addr[6];
        extern const u8 *bt_get_mac_addr(void);
        extern void lib_make_ble_address(u8 * ble_address, u8 * edr_address);
        extern int le_controller_set_mac(void *addr);
    #if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_ADV)
        memcpy(tmp_ble_addr, (u8 *)bt_get_mac_addr(), 6);
    #else
        lib_make_ble_address(tmp_ble_addr, (u8 *)bt_get_mac_addr());
    #endif //
        le_controller_set_mac((void *)tmp_ble_addr);
        printf("\n-----edr + ble 's address-----");
        put_buf((void *)bt_get_mac_addr(), 6);
        put_buf((void *)tmp_ble_addr, 6);
    #if BT_NET_CENTRAL_EN || TRANS_MULTI_BLE_MASTER_NUMS
        extern void ble_client_config_init(void);
        ble_client_config_init();
    #endif
    #endif
    }
    
    static void bredr_handle_register(void)
    {
    #if USER_SUPPORT_PROFILE_SPP
        extern void user_spp_data_handler(u8 packet_type, u16 ch, u8 * packet, u16 size);
        spp_data_deal_handle_register(user_spp_data_handler);
    #endif
    
    #if BT_SUPPORT_MUSIC_VOL_SYNC
        ///蓝牙音乐和通话音量同步
        music_vol_change_handle_register(bt_set_music_device_volume, phone_get_device_vol);
    #endif
    #if BT_SUPPORT_DISPLAY_BAT
        ///电量显示获取电量的接口
        get_battery_value_register(bt_get_battery_value);   /*电量显示获取电量的接口*/
    #endif
        ///被测试盒链接上进入快速测试回调
        /* bt_fast_test_handle_register(bt_fast_test_api); */
    
        ///样机进入dut被测试仪器链接上回调
        bt_dut_test_handle_register(bt_dut_api);
    
        ///获取远端设备蓝牙名字回调
        read_remote_name_handle_register(bt_read_remote_name);
    
        ////获取歌曲信息回调
        /* bt_music_info_handle_register(user_get_bt_music_info); */
    
    #if TCFG_USER_EMITTER_ENABLE
        ////发射器设置回调等
        inquiry_result_handle_register(emitter_search_result);
    #endif
    }
    
    • 2.2蓝牙发射功能:需在app_conifg中配置开启蓝牙发射器功能宏(如上2.1图)#define TCFG_USER_EMITTER_ENABLE 1 //蓝牙发射功能,蓝牙发射搜索设备没有名字的设备,放进需要获取名字链表,蓝牙发射搜索结果回调处理,蓝牙设备搜索结果,可以做名字/地址过滤,也可以保存搜到的所有设备在选择一个进行连接,获取其他你要的操作。发射器设置回调包括设备名字name、设备名字长度len、设备类型class和设备信号强度rssi等。

    • 长按KEY_OK(K7)进行蓝牙发射器切换到主机模式

    static int app_music_key_long(struct key_event *key)
    {
        switch (key->value) {
        case KEY_OK:
    #if TCFG_USER_EMITTER_ENABLE
            if (__this->bt_music_enable) {
                if (__this->bt_emitter_enable) {
                    app_music_play_voice_prompt("BtClose.mp3", bt_emitter_switch_to_receiver);
                } else {
                    app_music_play_voice_prompt("BtOpen.mp3", bt_emitter_enable);
                    bt_connection_disable();
                }
            }
    #endif
            break;
    //......
    
    static int bt_emitter_switch_to_receiver(int priv)
    {
        __this->bt_emitter_enable = 0;
        lmp_set_sniff_establish_by_remote(0);
        emitter_or_receiver_switch(BT_RECEIVER_EN);
    #ifdef CONFIG_NET_ENABLE
        switch_rf_coexistence_config_table(0);
    #endif
        bt_connection_enable();
        __this->dec_ops->dec_breakpoint(0);
        return 0;
    }
    
    • bt_emitter.c写入主动搜索连接的从机设备蓝牙名称进行连接。

    #if (SEARCH_LIMITED_MODE == SEARCH_BD_NAME_LIMITED)
    #if 0
    static const u8 bd_name_filt[][32] = {
        "BeMine",
        "EDIFIER CSR8635",/*CSR*/
        "JL-BT-SDK",/*Realtek*/
        "I7-TWS",/*ZKLX*/
        "TWS-i7",/*ZKLX*/
        "I9",/*ZKLX*/
        "小米小钢炮蓝牙音箱",/*XiaoMi*/
        "小米蓝牙音箱",/*XiaoMi*/
        "XMFHZ02",/*XiaoMi*/
        "JBL GO 2",
        "i7mini",/*JL tws AC690x*/
        "S08U",
        "AI8006B_TWS00",
        "S046",/*BK*/
        "AirPods",
        "CSD-TWS-01",
        "AC692X_wh",
        "JBL GO 2",
        "JBL Flip 4",
        "BT Speaker",
        "CSC608",
        "QCY-QY19",
        "Newmine",
        "HT1+",
        "S-35",
        "T12-JL",
        "Redmi AirDots_R",
        "Redmi AirDots_L",
        "AC69_Bluetooth",
        "FlyPods 3",
        "MNS",
        "Jam Heavy Metal",
        "Bluedio",
        "HR-686",
        "BT MUSIC",
        "BW-USB-DONGLE",
        "S530",
        "XPDQ7",
        "MICGEEK Q9S",
        "S10_H",
        "S10",/*JL AC690x*/
        "S11",/*JL AC460x*/
        "HBS-730",
        "SPORT-S9",
        "Q5",
        "IAEB25",
        "T5-JL",
        "MS-808",
        "LG HBS-730",
        "NG-BT07"
    };
    #else
    static const u8 bd_name_filt[][30] = {
        "JL-AC79XX-AF0B",
        "JL-AC79XX-FFAA",
        "JL-AC79XX-AAFF",
    };
    #endif
    /*----------------------------------------------------------------------------*/
    /**@brief    蓝牙发射搜索通过名字过滤
    @param    无
    @return   无
    @note
    */
    /*----------------------------------------------------------------------------*/
    u8 search_bd_name_filt(const char *data, u8 len, u32 dev_class, char rssi)
    {
        char bd_name[64] = {0};
    
        if ((len > (sizeof(bd_name))) || (len == 0)) {
            return FALSE;
        }
    
        memcpy(bd_name, data, len);
        log_i("name:%s,len:%d,class %x ,rssi %d\n", bd_name, len, dev_class, rssi);
    
        for (u8 i = 0; i < (sizeof(bd_name_filt) / sizeof(bd_name_filt[0])); i++) {
            if (memcmp(data, bd_name_filt[i], len) == 0) {
                log_i("\n*****find dev ok******\n");
                return TRUE;
            }
        }
    
        return FALSE;
    }
    #endif
    
    • bt_emitter.c写入主动搜索连接的从机设备蓝牙MAC地址进行连接。

    #if (SEARCH_LIMITED_MODE == SEARCH_BD_ADDR_LIMITED)
    static const u8 bd_addr_filt[][6] = {
        {0x8E, 0xA7, 0xCA, 0x0A, 0x5E, 0xC8}, /*S10_H*/
        {0xA7, 0xDD, 0x05, 0xDD, 0x1F, 0x00}, /*ST-001*/
        {0xE9, 0x73, 0x13, 0xC0, 0x1F, 0x00}, /*HBS 730*/
        {0x38, 0x7C, 0x78, 0x1C, 0xFC, 0x02}, /*Bluetooth*/
    };
    
    /*----------------------------------------------------------------------------*/
    /**@brief    蓝牙发射搜索通过地址过滤
    @param    无
    @return   无
    @note
    */
    /*----------------------------------------------------------------------------*/
    static u8 search_bd_addr_filt(const u8 *addr)
    {
        log_i("bd_addr:");
        put_buf(addr, 6);
    
        for (u8 i = 0; i < (sizeof(bd_addr_filt) / sizeof(bd_addr_filt[0])); i++) {
            if (memcmp(addr, bd_addr_filt[i], 6) == 0) {
                /* printf("bd_addr match:%d\n", i); */
                return TRUE;
            }
        }
        /*log_i("bd_addr not match\n"); */
        return FALSE;
    }
    #endif
    
  • 3.设备配网及使用第三方平台
    • 3.1配网:app_config.h:打开宏#define CONFIG_WIFI_ENABLE 使能无线WIFI。例如使用图灵平台,如下打开宏#define CONFIG_TURING_SDK_ENABLE //使用图灵平台

    #ifdef CONFIG_NET_ENABLE
    #define CONFIG_WIFI_ENABLE                                      /* 无线WIFI */
    #define WIFI_COLD_START_FAST_CONNECTION //启用WIFI冷启动快连
    // #define CONFIG_IPERF_ENABLE                                  // iperf测试
    // #define CONFIG_WIFIBOX_ENABLE                //WIFI测试盒性能测试
    #define CONFIG_SERVER_ASSIGN_PROFILE            //第三方平台的profile由杰理服务器分配
    // #define CONFIG_PROFILE_UPDATE                                //每次开机都从杰理服务器获取第三方平台的profile,不读flash
    // #define CONFIG_STATIC_IPADDR_ENABLE          //记忆路由器分配的IP,下次直接使用记忆IP节省DHCP时间
    #define CONFIG_ASSIGN_MACADDR_ENABLE        //第一次开机连上外网后,使用杰理服务器分配WIFI模块的MAC地址, 关闭则使用<蓝牙地址更新工具*.exe>或者随机数作为MAC地址
    #define CONFIG_TURING_SDK_ENABLE             //使用图灵平台
    // #define CONFIG_DEEPBRAIN_SDK_ENABLE                  //使用义语平台
    // #define CONFIG_DUER_SDK_ENABLE                               //使用百度平台
    // #define CONFIG_ECHO_CLOUD_SDK_ENABLE                 //使用回声云平台
    // #define CONFIG_DUI_SDK_ENABLE                    //使用思必驰DUI平台
    // #define CONFIG_ALI_SDK_ENABLE                    //使用天猫精灵平台
    // #define CONFIG_TVS_SDK_ENABLE                    //使用腾讯云平台
    // #define CONFIG_TELECOM_SDK_ENABLE            //电信云平台
    // #define CONFIG_JL_CLOUD_SDK_ENABLE           //打开使用杰理云平台
    // #define CONFIG_DLNA_SDK_ENABLE               //打开DLNA音乐播放功能
    // #define CONFIG_DOWNLOAD_SAVE_FILE            //保存网络下载的音乐文件
    // #define PAYMENT_AUDIO_SDK_ENABLE                             //打开语音播报功能
    // #define CONFIG_SCAN_PEN_ENABLE               //扫描笔图像拼接
    
    • 例如使用图灵平台,需使用图灵的配网小程序进行配网。未选用第三方平台时,可使用杰理机器人配网工具进行配网

    • 通过长按K5进入配网模式,使用图灵小程序使用声波、蓝牙和二维码三种方式都可进行配置网络,配网时手机与选择配置的网络必须为同一网络。

    //app_config.h使能蓝牙配网
    #ifdef CONFIG_TURING_SDK_ENABLE
    #define BT_NET_CFG_TURING_EN                      1     //从机 图灵配网专用
    #else
    #define BT_NET_CFG_TURING_EN                      0     //从机 图灵配网专用
    #endif
    
    #define CONFIG_ACOUSTIC_COMMUNICATION_ENABLE    //声波配网
    #define CONFIG_QR_CODE_NET_CFG                                  //二维码配网
    
    • 3.2绘本识别功能:app_config.h中打开图灵平台使用绘本识别服务器,使能图灵翻页算法,需要配合图灵绘本平台使用

    #ifdef CONFIG_VIDEO_ENABLE
    /*************绘本识别服务器*************/
    #ifdef CONFIG_TURING_SDK_ENABLE
    #define CONFIG_TURING_PAGE_TURNING_DET_ENABLE   //图灵翻页算法,需要配合图灵绘本平台使用
    #endif
    
    • app_music.c :进入绘本模式app_music_enter_picture_mode()

    /*
    * ****************************绘本识别*************************************
    */
    #if defined CONFIG_VIDEO_ENABLE && defined CONFIG_NET_ENABLE
    
    static void app_music_enter_picture_mode(void)
    {
    #ifdef CONFIG_PAGE_TURNING_DET_ENABLE
        extern int user_video_rec0_open(void);
        user_video_rec0_open();
        extern int page_turning_det_init(void);
        page_turning_det_init();
    #endif
    
    #ifdef CONFIG_TURING_PAGE_TURNING_DET_ENABLE
        extern int page_turning_det_init(void);
        page_turning_det_init();
    #endif
    
    #ifdef CONFIG_SCAN_PEN_ENABLE
        printf(">>>>>>>>>>>>run spi_video_task_create OKOKOK");
        extern void scan_pen_task_init(void);
        scan_pen_task_init();// 该线程用于初始化拼接算法 接收线程中处理好的摄像头数据
    #endif
    
    #ifdef CONFIG_WT_SDK_ENABLE
        union ai_req req = {0};
        if (__this->ai_server) {
            req.evt.event   = AI_EVENT_RUN_START;
            req.evt.ai_name = "wt";
            ai_server_request(__this->ai_server, AI_REQ_EVENT, &req);
        }
    #endif
    }
    
    • 3.3打断唤醒

    • 打断唤醒可参考“音频部分”中“打断唤醒”文档,可在app_config.h中开启打断唤醒宏#define CONFIG_ASR_ALGORITHM

    #define AISP_ALGORITHM 1 //思必驰双mic唤醒,未授权版本只支持运行10分钟
    #define ROOBO_ALGORITHM 2 //ROOBO 单/双MIC唤醒 ROOBO_DUAL_MIC_ALGORITHM ,,,测试版本只支持运行10分钟
    #define WANSON_ALGORITHM 3 //华镇算法,测试版只能够正确识别1000次
    #define JLASP_ALGORITHM 4 //杰理算法,现阶段仅用于测试效果
    #define CONFIG_ASR_ALGORITHM  AISP_ALGORITHM    //本地打断唤醒算法选择
    
    • 3.4微聊功能:用于设备与图灵手机公众号之间的语音消息传送聊天

    • app_music.c:app_music_ai_listen_start()

    static int app_music_ai_listen_start(u8 voice_mode, u8 enable_vad)
    {
        int err;
        union ai_req req = {0};
    
        __this->rec_again = 0;
        __this->wechat_flag = 0;
    
        if (__this->listening != LISTEN_STATE_STOP) {
            return -1;
        }
    
        if (!__this->ai_connected || !__this->net_connected) {
            if (WECHAT_MODE == voice_mode) {
                app_music_play_voice_prompt("SendMsgFail.mp3", __this->dec_ops->dec_breakpoint);
            } else if (AI_MODE == voice_mode) {
                app_music_play_voice_prompt("AiAsrFail.mp3", __this->dec_ops->dec_breakpoint);
            } else if (TRANSLATE_MODE == voice_mode) {
                app_music_play_voice_prompt("AiTransFail.mp3", __this->dec_ops->dec_breakpoint);
            }
            return -1;
        }
    
        if (__this->mode == BT_MUSIC_MODE) {
            __this->dec_ops->dec_stop(-1);
        } else {
            __this->dec_ops->dec_stop(1);
        }
    
        app_music_play_voice_prompt("rec.mp3", NULL);
    
        os_time_dly(30);
    
        if (enable_vad && voice_mode != WECHAT_MODE) {
            voice_mode |= VAD_ENABLE;       //enable local vad
        }
    
        //voice_mode:(bit0_bit1) 交互模式   0:智能聊天   1:中英翻译    2:微聊   3:口语评测
        //voice_mode:(bit3_bit6) 采样源选择 0:AUDIO_ADC不是四路全开时使用0   1-4:AUDIO_ADC四路全开时代表具体使用的ADC通道
        //voice_mode:(bit3_bit6) 采样源选择 5:plnk0    6:plnk1    7:iis0     8:iis1
        //voice_mode:(bit7)                 0:关闭VAD    1:打开VAD
    #if CONFIG_AUDIO_ENC_SAMPLE_SOURCE != AUDIO_ENC_SAMPLE_SOURCE_MIC
        req.lis.arg = voice_mode | ((CONFIG_AUDIO_ENC_SAMPLE_SOURCE + 4) << 3);
    #else
    #ifdef CONFIG_ALL_ADC_CHANNEL_OPEN_ENABLE
        req.lis.arg = voice_mode | ((CONFIG_ASR_CLOUD_ADC_CHANNEL + 1) << 3);
    #else
        req.lis.arg = voice_mode;
    #endif
    #endif
        req.lis.cmd = AI_LISTEN_START;
        err = ai_server_request(__this->ai_server, AI_REQ_LISTEN, &req);
        if (err == 0) {
            __this->listening = LISTEN_STATE_START;
            if (voice_mode == WECHAT_MODE) {
                __this->wechat_flag = 1;
            }
            os_time_dly(30);
        }
    
        return 0;
    }
    
    • 3.5进行第三方平台资源点播,例如使用图灵平台,使用MQTT协议进行请求,创建turing_mqtt_task线程和wechat_api_task线程实现:

    void *turing_mqtt_init(void)//图灵mqtt初始化
    {
        __this->mqtt = calloc(1, sizeof(struct dev_mqtt_hdl));//分配连续空间
        if (!__this->mqtt) {
            return NULL;
        }
    
        __this->iot_hdl = turing_iot_init();//图灵iot初始化
        if (!__this->iot_hdl) {
            free(__this->mqtt);
            __this->mqtt = NULL;
            return NULL;
        }
    
        __this->close = 0;
    
        thread_fork("turing_mqtt_task", 21, 1536, 0, &__this->MqttTaskPid, turing_mqtt_task, __this->mqtt);//创建turing_mqtt_task
        thread_fork("wechat_api_task",  14, 1536, 64, &__this->WechatTaskPid, wechat_api_task, __this->iot_hdl);创建wechat_api_task
    
        return __this->iot_hdl;
    }
    
    struct dev_mqtt_hdl *mqtt; //mqtt操作句柄指针
    struct dev_mqtt_hdl { //mqtt操作句柄
    Client c; //用户
    Network n;//网络
    u8 stu;//开关状态
    
    unsigned char sendbuf[MQTT_SEND_BUF_LEN];//mqtt发送buf长度
    unsigned char recvbuf[MQTT_READ_BUF_LEN];//mqtt读取buf长度
    
    const char *username;//用户名
    const char *password;//密码
    const char *clientid;//客户端id
    const char *topic;//主题
    u32 timeout;//超时
    };
    
    • turing_iot_init图灵iot初始化入口:

    void *turing_iot_init(void)
    {
        struct turing_info *f = (struct turing_info *)calloc(sizeof(struct turing_info), 1);
        if (!f) {
            return NULL;
        }
    
        if (!os_mutex_valid(&iot_mutex)) {
            os_mutex_create(&iot_mutex);
        }
        turing_iot_close_flag = 0;
    
        return f;
    }
    
    struct turing_info *f;         //图灵信息指针
    struct turing_info {           //图灵信息
        httpcli_ctx ctx;           //http客户端指针
        const char *api_key;       //申请授权秘钥
        const char *device_id;     //设备id
        u8   auth_flag;            //认证标志位
        char client_id[65];        //客户端id
        char topic[129];           //主题
        char res_media_id[65];     //媒体id
        int  song_id;              //歌曲id
        char song_url[1024];       //歌曲url
        char song_title[256];      //歌曲标题
    };
    
    • 注册wechat事件到ai_server平台:

    REGISTER_AI_SDK(wechat_sdk_api) = {
    .name           = "wechat",
    .connect        = wechat_sdk_connect,
    .disconnect     = wechat_sdk_disconnect,
    .state_check    = wechat_sdk_check,
    .do_event       = wechat_sdk_do_event,
    };
    
  • 4.音效处理
    • 4.1EQ均衡器:具体EQ工具说明可参考“音频部分”中“音效算法”的“EQ”说明文档

    //*********************************************************************************//
    //                                  EQ配置                                         //
    //*********************************************************************************//
    #define CONFIG_VOLUME_TAB_TEST_ENABLE             0     //音量表测试
    //EQ配置,使用在线EQ时,EQ文件和EQ模式无效。有EQ文件时,默认不用EQ模式切换功能
    #define TCFG_EQ_ENABLE                            1     //支持EQ功能
    #define TCFG_EQ_ONLINE_ENABLE                     1     //支持在线EQ调试
    #define TCFG_HW_SOFT_EQ_ENABLE                    1     //前3段使用软件运算
    #if __FLASH_SIZE__ > (1 * 1024 * 1024)
    #define TCFG_LIMITER_ENABLE                       1     //限幅器
    #else
    #define TCFG_LIMITER_ENABLE                       0     //限幅器
    #endif
    #define TCFG_EQ_FILE_ENABLE                       1     //从bin文件读取eq配置数据
    #define TCFG_DRC_ENABLE                           TCFG_LIMITER_ENABLE
    #define TCFG_ONLINE_ENABLE                        TCFG_EQ_ONLINE_ENABLE
    
    • 4.2混响功能、叠音功能和变调变速功能

    • app_config.h:

    #define CONFIG_REVERB_MODE_ENABLE            //打开混响功能
    #define CONFIG_AUDIO_MIX_ENABLE              //打开叠音功能
    #define CONFIG_AUDIO_PS_ENABLE               //打开变调变速功能