GEC6818科大讯飞离线语音识别

发布时间:2024年01月08日

GEC6818科大讯飞离线语音识别

一、 下载科大讯飞离线语音SDK

在下载SDK时需要注意选择Linux的版本!!

在这里插入图片描述

在官网下载离线语音的包,解压后可以得到下面的一些文件夹:

在这里插入图片描述

二、 解压文件夹后

解压后你需要知道自己命令放在下面的文件夹中
在这里插入图片描述

关于Make file文件:
在这里插入图片描述

关于asr_offline_sample.c文件:
在这里插入图片描述

asr_offline_sample.c文件是我们更改为自己的逻辑的文件,但是也不需要都了解清楚只要会改就行。

更改完asr_offline_sample.c文件后,在ubantu里面运行makefile文件后会有一些警告,这些都是定义的问题,可以不用管,但是在./asr_offline_sample运行的时候会报错找不到库,所以我们需要将资料包里面文件复制到lib目录下,具体如下:
需要移动的文件:
在这里插入图片描述

执行命令:

cp ./libmsc.so /lib

注意前面的`./libmsc.so`是相对路径,可以根据自己的当前路径进行更改,后面是移动到根目录下的lib目录下。

然后再执行就不会报错了。

三、与GEC6818开发板一起使用

3.1 使用科大讯飞的离线语音在ubantu中运行,作为服务端进行关键字的识别

需要更改的重要的两个文件就是bin/call.bnfsamples/asr_offine_sample/asr_offine_sample.c.这两个文件,第一个文件是修改我们需要识别的字眼,第二个文件是C 语言代码,可以在官方的基础上修改为自己所需要的逻辑

3.2 call.bnf–>hehe.bnf

我自己将官方自带的call.bnf复制了一份修改名字为hehe.bnf,在新的基础上进行的修改,更改了这个文件后,需要在后面的例程中的.c文件中修改这个文件。

例如:
在这里插入图片描述

注意我们这里使用对应的ID是非常重要的,因为我后后续进行语音识别后就是根据这个ID来判断识别到的内容,然后在执行相应的操作。

3.3 asr_offine_sample.c文件修改

上面有提到过的修改了离线语法文件后在.c文件中也需要修改相应的文件名
在这里插入图片描述

修改后的代码–当然也可以不用这样大幅度的修改,只是将官方的代码进行了规整。

//服务器
#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include "asr_offline_sample.h" //科大讯飞


//全局的套接字
int sockfd = -1;


//将套接字创建好  并且绑定 监听
//将ip地址和端口号传进来 端口号释放需要时间(轮询机制)
void TcpInit(const char * ipaddr,unsigned short port)
{
    //1 创建套接字 ---- 神马都是文件,因此你的网络通信也是一个文件
    sockfd = socket(AF_INET,SOCK_STREAM,0);
    if(-1 == sockfd)
    {
        perror("server socket error");
        exit(1);//没有必要运行了
    }
    //2 我们需要将服务器的IP地址绑定到套接字
    struct sockaddr_in sa;
    sa.sin_family = AF_INET;//协议族
    sa.sin_port = htons(port);//端口号  内存是小端的 我们要转大端
    sa.sin_addr.s_addr = inet_addr(ipaddr);//将我们点分式的ip地址转换为一个大端整数
    //printf("ipaddr = %x port = %x\n",inet_addr(ipaddr),htons(port));
    int r = bind(sockfd,(struct sockaddr *)&sa,sizeof(sa));
    if(-1 == r)
    {
        perror("server bind error");
        exit(2);//没有必要运行了
    }

    //3 监听连接 ---- 创建一个监听队列   建立5个10个可以了
    listen(sockfd,5);

}

//接收客户端发过来的文件内容
void SaveFile(int accceptfd,int filesize)
{
 //每一次都是重复的覆盖hehe.pcm
 int fd = open("wav/hehe.pcm",O_RDWR | O_TRUNC|O_CREAT,0644);//截短这个文件
 if(-1 == fd)
 {
  send(accceptfd,"error!!!",9,0);//失败发送这个错误
  return;
 }
 send(accceptfd,"next!!!!",9,0);//发送下一步的指令
 unsigned char buf[1024] = {0};
 int size = 0;
 //接收文件的内容
 while(1)  
 {
  int r = recv(accceptfd,buf,1024,0);
  if(-1 == r)
        {
            perror("recv error");
            break;
        }
        else if(0 == r)//客户端已经断了
        {
            printf("对方断开连接了\n");
            break;
        }
        else//接收到信息了
        {
            //将文件的内容写入到文件
   write(fd,buf,r);
   //做完之后要退出
   size += r;
   if(size >= filesize)
    break;
   
        }
 }
 
 
 
 
 close(fd);
}


//专门用于去服务一个客户的线程
void * ClinetFunction(void * arg)
{
    
    pthread_detach(pthread_self());//将其分离

    int * accceptfd = (int *)arg;
    printf(" * accceptfd = %d\n", * accceptfd);
 int filesize = 0;
    //你发什么信息过来  我就在这个信息之前加上一节 然后回发给你
    while(1)
    {
  printf("\t\t等待客户端传文件过来........\n");
        int r = recv(*accceptfd,&filesize,4,0);//阻塞等待数据过来
        if(-1 == r)
        {
            perror("recv error");
            break;
        }
        else if(0 == r)//客户端已经断了
        {
            printf("对方断开连接了\n");
            break;
        }
        else//接收到信息了
        {
            //文件大小
   
   SaveFile(* accceptfd,filesize);
   
   int id = GetFlayId();//文件接收完毕  那么我们就放过去识别即可
   //给客户端返回id
   send(* accceptfd,&id,4,0);
            
        }
    }
    close(*accceptfd);
    free(accceptfd);
 return NULL;
}

//等待客户端的连接 
void waitconnect(void)
{
    //我们要基于这个连接套接字去通信
    struct sockaddr_in sa;
    socklen_t addrlen = sizeof(sa);
    while(1)
    {
        printf("一直等待对方的连接.......\n");
        int * accceptfd = malloc(4);//避免释放 因此我们要动态内存分配才可以
        *accceptfd = accept(sockfd,(struct sockaddr *)&sa,&addrlen);
        printf("连接者为:%s %d\n",inet_ntoa(sa.sin_addr),ntohs(sa.sin_port));
        //开一个线程出去  让它去服务与我的连接
        pthread_t thread;
        if(pthread_create(&thread,NULL,ClinetFunction,(void *)accceptfd) != 0)
        {
            perror("create thread error");
            continue;
        }
    }
    
    close(sockfd);
}

//通过main函数的参数 我们将这个ip地址和端口给进去
//./a.out 192.168.31.251 8888
int main(int argc,char * argv[])
{
    if(argc < 3)
    {
        printf("参数都不齐\n");
        return -1;
    }
 
 //初始化科大讯飞的库
 FlayInit();
 
 
    TcpInit(argv[1],atoi(argv[2]));

    waitconnect();

    return 0;
}

完整的工程大家可以在我的gitee上进行下载
下载地址:GEC6818智能语音家居系统

文章来源:https://blog.csdn.net/qq_63831368/article/details/135437854
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。