AIVoice 示例

AIVoice Full Flow 离线示例

该例子通过一条提前录制的三通道音频演示如何使用 AIVoice 的全流程,在开发板启动后仅运行一次。 未整合录音、播放等音频功能。

示例代码在 ${aivoice_example_dir}/full_flow_offline 目录下。

AIVoice 使用步骤

  1. 选择需要的 aivoice 流程或模块。如果使用 full_flow 、 afe_kws 或 afe_kws_vad 流程,需要指定 KWS 模式为单路或多路模式。

    /* 步骤 1:
     * 选择需要的 aivoice 流程.
     * 参考 aivoice_interface.h 文件末尾查看支持的流程
     */
    const struct rtk_aivoice_iface *aivoice = &aivoice_iface_full_flow_v1;
    rtk_aivoice_set_multi_kws_mode();
    
  2. 准备配置参数。

    /* 步骤 2:
     * 按需修改默认配置。
     * 您可以修改 afe/vad/kws/...的 0 个或多个配置项
     */
    struct aivoice_config config;
    memset(&config, 0, sizeof(config));
    
    /*
     * 这里使用 afe_res_2mic50mm 作为示例。
     * 可以根据实际使用的 afe 资源修改这些配置。
     * 详情请参考 aivoce_afe_config.h;
     *
     * afe_config.mic_array 必须与您链接的 afe 资源匹配
     */
    struct afe_config afe_param = AFE_CONFIG_ASR_DEFAULT_2MIC50MM; // 根据链接的 afe 资源修改此项
    config.afe = &afe_param;
    
    /*
     * 仅在完全理解参数含义时修改这些设置。
     * 如果不了解这些参数的含义,
     * 建议使用默认配置
     */
    struct vad_config vad_param = VAD_CONFIG_DEFAULT();
    vad_param.left_margin = 300; // 可根据需要修改配置
    config.vad = &vad_param;    // 可设置为 NULL
    
    struct kws_config kws_param = KWS_CONFIG_DEFAULT();
    config.kws = &kws_param;    // 可设置为 NULL
    
    struct asr_config asr_param = ASR_CONFIG_DEFAULT();
    config.asr = &asr_param;    // 可设置为 NULL
    
    struct aivoice_sdk_config aivoice_param = AIVOICE_SDK_CONFIG_DEFAULT();
    aivoice_param.no_cmd_timeout = 10;
    config.common = &aivoice_param; // 可设置为 NULL
    
  3. 使用 create() 和指定配置来创建并初始化 aivoice 实例。

    /* 步骤 3:
     * 创建 aivoice 实例
     */
    void *handle = aivoice->create(&config);
    if (!handle) {
        return;
    }
    
  4. 注册回调函数。

    /* 步骤 4:
     * 注册一个回调函数。
     * 在本示例中,您可能只会接收到部分 aivoice_out_event_type 事件类型,
     * 具体取决于您使用的流程。
     * */
    
    rtk_aivoice_register_callback(handle, aivoice_callback_process, NULL);
    

    回调函数可以按实际使用需求进行修改:

    static int aivoice_callback_process(void *userdata,
                                        enum aivoice_out_event_type event_type,
                                        const void *msg, int len)
    {
    
        (void)userdata;
        struct aivoice_evout_vad *vad_out;
        struct aivoice_evout_afe *afe_out;
    
        switch (event_type) {
        case AIVOICE_EVOUT_VAD:
                vad_out = (struct aivoice_evout_vad *)msg;
                printf("[user] vad. status = %d, offset = %d\n", vad_out->status, vad_out->offset_ms);
                break;
    
        case AIVOICE_EVOUT_WAKEUP:
                printf("[user] wakeup. %.*s\n", len, (char *)msg);
                break;
    
        case AIVOICE_EVOUT_ASR_RESULT:
                printf("[user] asr. %.*s\n", len, (char *)msg);
                break;
    
        case AIVOICE_EVOUT_ASR_REC_TIMEOUT:
                printf("[user] asr timeout\n");
                break;
    
        case AIVOICE_EVOUT_AFE:
                afe_out = (struct aivoice_evout_afe *)msg;
    
                // afe 每帧都会输出音频
                // 本示例中,为了让日志清晰仅打印一次
                static int afe_out_printed = false;
                if (!afe_out_printed) {
                        afe_out_printed = true;
                        printf("[user] afe output %d channels raw audio, others: %s\n",
                                   afe_out->ch_num, afe_out->out_others_json ? afe_out->out_others_json : "null");
                }
    
                // 按需处理 afe 输出的音频
                break;
    
        default:
                break;
        }
    
        return 0;
    }
    
  5. 使用 feed() 给 aivoice 输入音频数据。

    /* 在芯片上运行时,通常使用麦克风采集的实时音频流,
     * 本示例中使用一条固定音频
     * */
    
    const char *audio = (const char *)get_test_wav();
    int len = get_test_wav_len();
    int audio_offset = 44;
    int mics_num = 2;
    int afe_frame_bytes = (mics_num + afe_param.ref_num) * afe_param.frame_size * sizeof(short);
    while (audio_offset <= len - afe_frame_bytes) {
            /* step 5:
             * Feed the audio to the aivoice instance.
             * */
    
            aivoice->feed(handle,
                          (char *)audio + audio_offset,
                          afe_frame_bytes);
    
            audio_offset += afe_frame_bytes;
    }
    
  6. (可选) 如果需要重置状态,使用 reset()

  7. 如果不再需要 aivoice,使用 destroy() 销毁实例。

    /* 步骤 6:
    * 销毁 aivoice 实例 */
    
    aivoice->destroy(handle);
    

预期结果

在开发板上烧录固件,运行后,日志会打印算法结果如下:

[AIVOICE] set multi kws mode
---------------------SPEECH COMMANDS---------------------
Command ID1, 打开空调
Command ID2, 关闭空调
Command ID3, 制冷模式
Command ID4, 制热模式
Command ID5, 加热模式
Command ID6, 送风模式
Command ID7, 除湿模式
Command ID8, 调到十六度
Command ID9, 调到十七度
Command ID10, 调到十八度
Command ID11, 调到十九度
Command ID12, 调到二十度
Command ID13, 调到二十一度
Command ID14, 调到二十二度
Command ID15, 调到二十三度
Command ID16, 调到二十四度
Command ID17, 调到二十五度
Command ID18, 调到二十六度
Command ID19, 调到二十七度
Command ID20, 调到二十八度
Command ID21, 调到二十九度
Command ID22, 调到三十度
Command ID23, 开高一度
Command ID24, 开低一度
Command ID25, 高速风
Command ID26, 中速风
Command ID27, 低速风
Command ID28, 增大风速
Command ID29, 减小风速
Command ID30, 自动风
Command ID31, 最大风量
Command ID32, 中等风量
Command ID33, 最小风量
Command ID34, 自动风量
Command ID35, 左右摆风
Command ID36, 上下摆风
Command ID37, 播放音乐
Command ID38, 暂停播放
Command ID39, 接听电话
Command ID40, 挂断电话
---------------------------------------------------------

[AIVOICE] rtk_aivoice version: v1.5.0#S0825120#N1ed33d6#A6c25e38
[AIVOICE] rtk_aivoice_model afe version: afe_2mic_asr_v1.3.1_AfePara_2mic50_v2.0_bf_v0.0_20250401
[AIVOICE] rtk_aivoice_model vad version: vad_v7_opt
[AIVOICE] rtk_aivoice_model kws version: kws_xqxq_v4.1_opt
[AIVOICE] rtk_aivoice_model asr version: asr_cn_v8_opt
[AIVOICE] rtk_aivoice_log_format version: v2
[user] afe output 1 channels raw audio, others: {"abnormal_flag":0,"ssl_angle":-10}
[AIVOICE] [KWS] result: {"id":2,"keyword":"ni-hao-xiao-qiang","score":0.7746397852897644}
[user] wakeup. {"id":2,"keyword":"ni-hao-xiao-qiang","score":0.7746397852897644}
[user] voice angle 90.0
[user] vad. status = 1, offset = 385
[user] vad. status = 0, offset = 1865
[AIVOICE] [ASR] result: {"type":0,"commands":[{"rec":"打开空调","id":1}]}
[user] asr. {"type":0,"commands":[{"rec":"打开空调","id":1}]}
[user] voice angle 90.0
[user] vad. status = 1, offset = 525
[AIVOICE] [KWS] result: {"id":2,"keyword":"ni-hao-xiao-qiang","score":0.750707507133484}
[user] wakeup. {"id":2,"keyword":"ni-hao-xiao-qiang","score":0.750707507133484}
[user] voice angle 90.0
[user] vad. status = 1, offset = 445
[user] vad. status = 0, offset = 1765
[AIVOICE] [ASR] result: {"type":0,"commands":[{"rec":"播放音乐","id":37}]}
[user] asr. {"type":0,"commands":[{"rec":"播放音乐","id":37}]}
[user] voice angle 90.0

编译示例

  1. 切换到 SDK 的 GCC 项目目录

    cd {SDK}/amebadplus_gcc_project
    
  2. 运行 menuconfig.py 进入配置界面

    ./menuconfig.py
    
  3. 导航至以下菜单路径开启 TFLM 库和 AIVoice

    --------MENUCONFIG FOR General---------
    CONFIG TrustZone  --->
    ...
    CONFIG APPLICATION  --->
       GUI Config  --->
       ...
       AI Config  --->
          [*] Enable TFLITE MICRO
          [*] Enable AIVoice
    
  4. 编译固件

    ./build.py -a full_flow_offline