回到首页 返回首页
回到顶部 回到顶部
返回上一页 返回上一页

行空板K10测评:ASR语音识别和语音合成 中等

头像 米菲爸爸 2024.09.13 66 0

在语音识别中,ASR(Automatic Speech Recognition)和大模型中的语音识别有一些区别,主要体现在以下几个方面:

1. ASR(自动语音识别):

   - ASR是一种传统的语音识别方法,通常基于统计模型和经典机器学习算法(如隐马尔可夫模型)。

   - ASR系统通常基于规则和特征工程,需要手动设计特征提取器来捕获语音信号中的关键信息。

   - ASR系统在面对复杂的语音信号、口音和噪音时可能表现不佳,需要精细的调整和优化。

 

2. 大模型中的语音识别:

   - 大模型中的语音识别指的是使用深度学习技术,如深度神经网络(DNN)和循环神经网络(RNN)等,构建的端到端的语音识别系统。

   - 这些系统通常使用深度学习模型直接从原始语音信号中学习特征,无需手动设计特征提取器。

   - 大模型中的语音识别系统能够更好地处理各种口音、噪音以及上下文信息,具有更好的泛化能力。

总的来说,大模型中的语音识别系统借助深度学习技术,能够更好地捕获语音信号中的复杂特征,取得更好的识别性能,相比传统的ASR方法有着明显的优势。

很明显在行空板K10中使用了ASR技术,所以我们不可以苛求行空板K10可以做到真正意义上的人机实时对话。也就是说我们需要预先告知行空板K10我可以接受什么样的命令,比如说:“开灯,关灯,播放音乐等“。所以我们在使用时会使用”命令式对话“而非”开放式对话“

 

例一 语音识别

必须预先定义好“关键词”目前K10最大支持200个

image.png

因为C语言下标从0开始,而ASRid是从1开始,所以代码中有+1的修正,不看代码的话也可以不关心这个。

void setup() {
  k10.begin();
  asr.asrInit(CONTINUOUS, CN_MODE, 6000);
  while(asr._asrState == 0){delay(100);}
  asr.addASRCommand(0+1, "kai deng");
  asr.addASRCommand(1+1, "guan deng");
}

 

例二 语音合成

当识别到命令后按命令执行相应的语句,这里执行的是对命令的响应,使用语音合成技术直接播放要说的话

注意:受机能所限应尽量避免中英文混合。目前在中文模式下,所有的英文单词都被拆解为字母顺序播放!

 

image.png

 

下面我们使用手动编辑模式输入一段代码。作用是识别五种命令:

开灯、关灯、听力、自我介绍、播放音乐

  asr.addASRCommand(1, "kai deng"); // 添加语音识别命令,ID为1,命令为"kai deng"

  asr.addASRCommand(2, "guan deng"); // 添加语音识别命令,ID为2,命令为"guan deng"

  asr.addASRCommand(3, "ting li"); // 添加语音识别命令,ID为3,命令为"ting li"

  asr.addASRCommand(4, "zi wo jie shao"); // 添加语音识别命令,ID为4,命令为"zi wo jie shao"

  asr.addASRCommand(5, "bo fang yin yue"); // 添加语音识别命令,ID为5,命令为"bo fang yin yue"

 

音乐文件需要存放在TF卡上指定位置

music.playTFCardAudio("S:/wav/StarWars60.wav"); // 播放音乐文件

 

截至到目前为止(2024年9月14日),行空板K10还没有开放英文ASR命令,所以要等完全板发布后再测试。

 

下面是完整代码

代码
/*!
 * MindPlus
 * esp32s3bit
 *
 */
#include "unihiker_k10.h"
#include "asr.h"


// 动态变量
uint32_t        rgbToColor(uint8_t r, uint8_t g, uint8_t b); // 定义一个函数rgbToColor,输入参数为三个8位无符号整型变量r,g,b,返回值为32位无符号整型
// 函数声明
void onButtonAPressed(); // 声明一个函数onButtonAPressed
void onButtonBPressed(); // 声明一个函数onButtonBPressed
void callAMR(); // 声明一个函数callAMR
void drawprogress(); // 声明一个函数drawprogress
// 创建对象
UNIHIKER_K10    k10; // 创建一个UNIHIKER_K10类型的对象k10
Music        music; // 创建一个Music类型的对象music
ASR asr; // 创建一个ASR类型的对象asr
bool  asr_cmd3; // 定义一个布尔型变量asr_cmd3
uint16_t lights; // 定义一个16位无符号整型变量lights

static int step = 0;//进度条
uint8_t radius = 6;//进度条圆的半径
uint8_t gap = 40;//进度条间隙
uint8_t yPos = 160;//进度条纵向位置进度条起点
uint8_t xPosStart = 60;//进度条起点

const uint16_t screenWidth = 240; // 定义一个常量screenWidth,值为240
const uint16_t screenHeight = 320; // 定义一个常量screenHeight,值为320
const uint16_t squareSize = 150; // 定义一个常量squareSize,值为150
const uint16_t circleRadius = 10; // 定义一个常量circleRadius,值为10
uint16_t mark_acce = 0; // 定义一个16位无符号整型变量mark_acce,初始值为0
uint16_t squareX = (screenWidth - squareSize) / 2; // 定义一个16位无符号整型变量squareX,值为(screenWidth - squareSize) / 2
uint16_t squareY = 10; // 定义一个16位无符号整型变量squareY,值为10
uint16_t circleX = squareX + squareSize / 2; // 定义一个16位无符号整型变量circleX,值为squareX + squareSize / 2
uint16_t circleY = squareY + squareSize / 2; // 定义一个16位无符号整型变量circleY,值为squareY + squareSize / 2
uint16_t newCircleX = circleX; // 定义一个16位无符号整型变量newCircleX,值为circleX
uint16_t newCircleY = circleY; // 定义一个16位无符号整型变量newCircleY
uint16_t targetCircleX = 0; // 定义一个16位无符号整型变量targetCircleX,初始值为0
uint16_t targetCircleY = 0; // 定义一个16位无符号整型变量targetCircleY,初始值为0
bool circleReached = false; // 定义一个布尔型变量circleReached,初始值为false
void generateNewTargetCircle(); // 声明一个函数generateNewTargetCircle

// 主程序开始
void setup() { // 定义一个函数setup
  k10.begin(); // 初始化k10对象

  k10.initScreen(2); // 初始化屏幕
  asr.asrInit(CONTINUOUS, CN_MODE, 5000); // 初始化语音识别,模式为连续识别,语言模式为中文,识别时间为5000毫秒
  while(asr._asrState == 0){delay(100);} // 等待语音识别初始化完成
  k10.initBgCamerImage(); // 初始化背景相机图像
  k10.setBgCamerImage(false); // 设置背景相机图像为false
  k10.creatCanvas(); // 创建画布

  k10.setScreenBackground(0xFFFFFF); // 设置屏幕背景为白色
  k10.rgb->brightness(round(2)); // 设置RGB灯的亮度
  asr.setAsrSpeed(3); // 设置语音识别速度为3

  asr.addASRCommand(1, "kai deng"); // 添加语音识别命令,ID为1,命令为"kai deng"
  asr.addASRCommand(2, "guan deng"); // 添加语音识别命令,ID为2,命令为"guan deng"
  asr.addASRCommand(3, "ting li"); // 添加语音识别命令,ID为3,命令为"dong hua"
  asr.addASRCommand(4, "zi wo jie shao"); // 添加语音识别命令,ID为4,命令为"gu shi"
  asr.addASRCommand(5, "bo fang yin yue"); // 添加语音识别命令,ID为5,命令为"bo fang yin yue"
  // asr.addASRCommand(6, "wen du");
  k10.buttonA->setPressedCallback(onButtonAPressed); // 设置按钮A按下时的回调函数为onButtonAPressed
  k10.buttonB->setPressedCallback(onButtonBPressed); // 设置按钮B按下时的回调函数为onButtonBPressed
  
  k10.canvas->updateCanvas(); // 更新画布

  callAMR(); // 切换模式
}

void loop() { // 定义一个函数loop
 
  if (asr.isWakeUp() && asr_cmd3==0) {
    drawprogress(); // 绘制进度条
    // k10.canvas->canvasRectangle(50, 153, 140, 14, 0xFFFFFF, 0xFFFFFF, true);
    k10.canvas->updateCanvas(); // 更新画布
  }
  //语音识别
    if (asr.isDetectCmdID(1)) {//开灯
      asr_cmd3 = 0;
      k10.canvas->canvasRectangle(10, 0, 220, 150, 0xFFFFFF, 0xFFFFFF, true); // 清除指定区域
      k10.canvas->updateCanvas(); // 更新画布
      k10.rgb->write(0, 0x00FF00); // 设置RGB灯的颜色
      k10.rgb->write(1, 0xFFFF00); // 设置RGB灯的颜色
      k10.rgb->write(2, 0xFF0000); // 设置RGB灯的颜色
    }
    if (asr.isDetectCmdID(2)) {//关灯
      asr_cmd3 = 0;
      k10.canvas->canvasRectangle(10, 0, 220, 150, 0xFFFFFF, 0xFFFFFF, true); // 清除指定区域

      k10.canvas->updateCanvas(); // 更新画布
      k10.rgb->write(-1, 0x000000); // 设置RGB灯的颜色
    }
    if (asr.isDetectCmdID(3)) {//播放听力
      asr_cmd3 = 0;
      k10.initSDFile(); // 初始化SD卡文件系统
      k10.canvas->canvasRectangle(10, 0, 220, 150, 0xFFFFFF, 0xFFFFFF, true); // 清除指定区域
      music.playTFCardAudio("S:/wav/gettysburg.wav"); // 播放音乐文件
    }
    if (asr.isDetectCmdID(4)) {//自我介绍
      asr_cmd3 = 0;
      k10.canvas->canvasRectangle(10, 0, 220, 150, 0xFFFFFF, 0xFFFFFF, true); // 清除指定区域
      k10.canvas->updateCanvas(); // 更新画布
      asr.speak(",您好,,我的名字是行空板K10,,我来自Df.");
    }
    if (asr.isDetectCmdID(5)) {//播放音乐
      asr_cmd3 = 0;
      k10.initSDFile(); // 初始化SD卡文件系统
      k10.canvas->canvasRectangle(10, 0, 220, 150, 0xFFFFFF, 0xFFFFFF, true); // 清除指定区域
      music.playTFCardAudio("S:/wav/StarWars60.wav"); // 播放音乐文件
    }
  
  if(asr_cmd3 == 1){
    k10.rgb->write(0, 0x0000FF);
  }
}
// 事件回调函数
void onButtonAPressed() {
  asr_cmd3 = 0;
  callAMR(); // 切换模式
}
void onButtonBPressed() {
  asr_cmd3 = 0;
  callAMR(); // 切换模式
}
void callAMR() {
    k10.setBgCamerImage(false); // 设置背景为黑色

    k10.canvas->canvasClear(); // 清除画布
    for (int i = 0; i < 4; i++) {
        k10.canvas->canvasCircle(xPosStart + i * gap, yPos, radius, 0x81C784, 0x81C784, true); // 显示小圆
    }
    k10.canvas->canvasText("请说\"你好小新\"唤醒我", 60, 180, 0x626E041, k10.canvas->eCNAndENFont16, 50 ,0);
    k10.canvas->canvasText("唤醒后右上角绿灯常亮", 60, 200, 0x626E041, k10.canvas->eCNAndENFont16, 50 ,0);
    k10.canvas->canvasText("这时您可以说", 80, 220, 0x626E041, k10.canvas->eCNAndENFont16, 50 ,0);
    k10.canvas->canvasText("\"开灯、关灯、听力、自我介绍、播放音乐\"", 10, 240, 0x626E041, k10.canvas->eCNAndENFont16, 50 ,0);

    k10.canvas->updateCanvas(); // 更新画布
}

// 生成新的目标空心圆
void generateNewTargetCircle() {
    targetCircleX = random(squareX + circleRadius+5, squareX + squareSize - circleRadius-5);
    targetCircleY = random(squareY + circleRadius+5, squareY + squareSize - circleRadius-5);
    circleReached = false; // 重置状态
}

// 绘制进度函数
void drawprogress() {   
  k10.canvas->canvasSetLineWidth(1); // 设置线宽
  // 绘制4个小圆
  for (int i = 0; i < 4; i++) {
    k10.canvas->canvasCircle(xPosStart + i * gap, yPos, radius, 0x81C784, 0x81C784, true); // 显示小圆
  }
  // 绘制4个小圆,并在每次绘制后延时100ms
  for (int i = 0; i < 4; i++) {
    k10.canvas->canvasCircle(xPosStart + i * gap, yPos, radius, 0x388E3C, 0x388E3C, true); // 显示小圆
    delay(100);
    k10.canvas->updateCanvas(); // 更新画布
  }   
  // 更新步数
  step = (step + 1) % 5; 
}
// 将RGB颜色转换为32位颜色值的函数
uint32_t rgbToColor(uint8_t r, uint8_t g, uint8_t b)
{
  // 将r、g、b的值左移16位、8位和0位,然后进行或运算,得到32位颜色值
  return (uint32_t)((((uint32_t)r<<16) | ((uint32_t)g<<8)) | (uint32_t)b);
}

评论

user-avatar