2980|2

1381

帖子

2

TA的资源

五彩晶圆(初级)

楼主
 

【ESP32-Korvo测评】(8)语音识别用法测试 [复制链接]

 

  ESP-Skainet 提供了一个免费的离线语音识别算法,可以对自定义的若干个关键词(短语)进行识别。离线意思就是识别过程真正在 ESP32 中处理完成,不需要连网。虽然这种语音识别的功能单一,毕竟是提供了比按键操作高级得多的交互手段,恰当运用可以极大提升作品的用户体验。
  再回顾一下 get_started 例子中语音识别是怎么调用的:
 

while (1) {
    rb_read(agc_rb, (uint8_t *)buffer, audio_chunksize * sizeof(int16_t), portMAX_DELAY);
    if (detect_flag == 0) {
        int r = wakenet->detect(model_data, buffer);
        if (r) {
            float ms = (chunks * audio_chunksize * 1000.0) / frequency;
            printf("%.2f: %s DETECTED.\n", (float)ms / 1000.0, wakenet->get_word_name(model_data, r));
            detect_flag = 1;
            printf("-----------------LISTENING-----------------\n\n");
            rb_reset(rec_rb);
            rb_reset(ns_rb);
            rb_reset(agc_rb);
        }
    } else {
        int command_id = multinet->detect(model_data_mn, buffer);
        mn_chunks++;
        if (mn_chunks == chunk_num || command_id > -1) {
            mn_chunks = 0;
            detect_flag = 0;
            if (command_id > -1) {
                speech_commands_action(command_id);
            } else {
                printf("can not recognize any speech commands\n");
            }

            printf("\n-----------awaits to be waken up-----------\n");
            rb_reset(rec_rb);
            rb_reset(ns_rb);
            rb_reset(agc_rb);
        }
    }
    chunks++;
}

  这个循环在不断地获取声音,然后调用识别算法。根据 detect_flag 标志分为两种情况:一是识别唤醒词,另一种是唤醒后识别命令词。用的算法也不同,前者是 wakenet, 后者是 multinet. 因为识别的复杂度不同,设计两个分开的算法也是有道理的。

 

  int r = wakenet->detect(model_data, buffer);

这一个调用是识别是否有唤醒词。buffer 是采集的语音数据片段,model_data 来自 wakenetTask() 任务的参数。再看主函数中如何生成它:
  model_iface_data_t *model_data = wakenet->create(model_coeff_getter, DET_MODE_90);
   实际上用的是已经定义好的东西:
static const esp_wn_iface_t *wakenet = &WAKENET_MODEL;
static const model_coeff_getter_t *model_coeff_getter = &WAKENET_COEFF;

  在 esp-sr/wake_word_engine/include/esp_wn_models.h 中找到 WAKENET_MODEL 和 WAKENET_COEFF 的定义出处——它们都是根据配置文件从预定义的常量中选择。这些常量在库文件里面,对应到选择的算法和不同的唤醒词。算法的实现过程以及训练后的模型数据是什么样就无从分析了。

 

  int command_id = multinet->detect(model_data_mn, buffer);
  这个调用则需要返回识别到哪一个命令词。除了 multinet 是来自 MULTINET_MODEL (也是通过配置选择库中的几个版本之一)外,其参数 model_data_mn 是全局变量,在主程序中由
    model_data_mn = multinet->create(&MULTINET_COEFF, 4000);
创建。在 esp_mn_models.h 中有这段预处理代码

#if CONFIG_SR_CHINESE && CONFIG_SINGLE_RECOGNITION
#include "multinet1_ch.h"
#define MULTINET_MODEL esp_sr_multinet1_quantized_cn
#define MULTINET_COEFF get_coeff_multinet1_ch
#elif CONFIG_SR_ENGLISH && CONFIG_SINGLE_RECOGNITION
#include "multinet1_en.h"
#define MULTINET_MODEL esp_sr_multinet1_quantized_en
#define MULTINET_COEFF get_coeff_multinet1_en
#elif CONFIG_SR_CHINESE && CONFIG_CONTINUOUS_RECOGNITION
#include "multinet1_ch.h"
#define MULTINET_MODEL esp_sr_multinet2_quantized_cn
#define MULTINET_COEFF get_coeff_multinet1_ch
#else
#error No valid wake word selected.
#endif

也就是意味着,命令词识别的形式有中文单次、英文单次和中文连续,这三种。

 

  在 mn_process_commands.c 中写了一个 get_id_name() 函数:

char *get_id_name(int i)
{
    if (i == 0)
        return MN_SPEECH_COMMAND_ID0;
    else if (i == 1)
        return MN_SPEECH_COMMAND_ID1;
    else if (i == 2)
        return MN_SPEECH_COMMAND_ID2;
    else if (i == 3)
        return MN_SPEECH_COMMAND_ID3;
    else if (i == 4)
        return MN_SPEECH_COMMAND_ID4;

而这些宏定义,源头来自配置文件,也就是自定义的要识别的命令词了。在前面的实验中,我为了填加命令词,导致整个工程呀重新编译。那么直接改这个文件(虽然它不属于库里面的)应该容易些。我猜想在 multinet->create() 调用的时候,这个 get_id_name() 函数会被调用很多次。

 

  修改一下:

char *get_id_name(int i)
{
	printf("get_id_name(%d) ",i);
	switch(i)
	{
		case 0: return "ling";
		case 1: return "yi"; 
		case 2: return "er"; 
		case 3: return "san";
		case 4: return "si"; 
		case 5: return "wu"; 
		case 6: return "liu";
		case 7: return "qi"; 
		case 8: return "ba"; 
		case 9: return "jiu";
		case 10:return "shi";
		default: return "";
	}
}

然后重新编译,下载。运行,可以看到终端打印的命令词信息部分,如我所料。

I (1610) MN: ---------------------SPEECH COMMANDS---------------------
get_id_name(0) I (1610) MN: Command ID0, phrase 0: ling
get_id_name(1) I (1620) MN: Command ID1, phrase 1: yi
get_id_name(2) I (1630) MN: Command ID2, phrase 2: er
get_id_name(3) I (1630) MN: Command ID3, phrase 3: san
get_id_name(4) I (1640) MN: Command ID4, phrase 4: si
get_id_name(5) I (1640) MN: Command ID5, phrase 5: wu
get_id_name(6) I (1650) MN: Command ID6, phrase 6: liu
get_id_name(7) I (1650) MN: Command ID7, phrase 7: qi
get_id_name(8) I (1660) MN: Command ID8, phrase 8: ba
get_id_name(9) I (1670) MN: Command ID9, phrase 9: jiu
get_id_name(10) I (1670) MN: Command ID10, phrase 10: shi
get_id_name(11) get_id_name(12) get_id_name(13) get_id_name(14) get_id_name(15) get_id_name(16) get_id_name(17) get_id_name(18) get_id_name(19) get_id_name(20) get_id_name(21) get_id_name(22) get_id_name(23) get_id_name(24) get_id_name(25) get_id_name(26) get_id_name(27) get_id_name(28) get_id_name(29) get_id_name(30) get_id_name(31) get_id_name(32) get_id_name(33) get_id_name(34) get_id_name(35) get_id_name(36) get_id_name(37) get_id_name(38) get_id_name(39) get_id_name(40) get_id_name(41) get_id_name(42) get_id_name(43) get_id_name(44) get_id_name(45) get_id_name(46) get_id_name(47) get_id_name(48) get_id_name(49) get_id_name(50) get_id_name(51) get_id_name(52) get_id_name(53) get_id_name(54) get_id_name(55) get_id_name(56) get_id_name(57) get_id_name(58) get_id_name(59) get_id_name(60) get_id_name(61) get_id_name(62) get_id_name(63) get_id_name(64) get_id_name(65) get_id_name(66) get_id_name(67) get_id_name(68) get_id_name(69) get_id_name(70) get_id_name(71) get_id_name(72) get_id_name(73) get_id_name(74) get_id_name(75) get_id_name(76) get_id_name(77) get_id_name(78) get_id_name(79) get_id_name(80) get_id_name(81) get_id_name(82) get_id_name(83) get_id_name(84) get_id_name(85) get_id_name(86) get_id_name(87) get_id_name(88) get_id_name(89) get_id_name(90) get_id_name(91) get_id_name(92) get_id_name(93) get_id_name(94) get_id_name(95) get_id_name(96) get_id_name(97) get_id_name(98) get_id_name(99) I (1800) MN: ---------------------------------------------------------

 

  按上面这么定的语音命令(0~10的读音)测试,识别效果还不能令我满意。最难识别的是"liu":极少成功,其次"ling","er"和 "wu"也难识别。"jiu"更容易识别成7, 不知何故。还能遇到识别中 ESP32 重起的情况。

最新回复

感谢分享,感觉挺好的,离线语音识别也够一些基础测试用了!   详情 回复 发表于 2021-3-13 19:55

赞赏

1

查看全部赞赏

点赞(1) 关注
 
 

回复
举报

1704

帖子

0

TA的资源

五彩晶圆(初级)

沙发
 

奇怪这些"liu""ling","er"和 "wu"为什难以识别,与硬件还是软件有关

 
 
 

回复

1942

帖子

3

TA的资源

版主

板凳
 

感谢分享,感觉挺好的,离线语音识别也够一些基础测试用了!

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表