Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
网络学习营
【7天入门RTOS网络编程】Wendell 结课 RTOS网络编程课作业☆☆
发布于 2018-10-26 18:00:50 浏览:1896
订阅该版
* 本帖最后由 san兄弟 于 2018-11-6 17:07 编辑 * 【7天入门RTOS网络编程】课程已经结束,迎来了终极大boss作业,看着很难的样子,先一点点来学习吧,边学习边记录! **1. 题目要求**(1)在板子上能够发送一段文字给[百度语音](http://yuyin.baidu.com/)合成服务,获取语音合成链接,然后下载下来。(2)然后用这一段音频或者事先录制好的一段语音,通过百度语义识别功能,获取语音识别结果,然后根据语音识别的结果来模拟实现控制 led 灯的亮灭。 **2. 完成思路**(1)学习百度语音相关知识,[语音合成](https://ai.baidu.com/docs#/TTS-API/17fc02c0)、[语音识别](https://ai.baidu.com/docs#/ASR-API/top),学习语音合成的操作步骤、API的使用及各参数含义。(2)根据百度语音要求,按照教程例程改写程序,实现语音合成和下载;由于使用开发板难度更大,因此先仍然使用qemu。(3)编写程序获取语音识别结果,并输出,模拟led的亮灭。(4)后期尝试使用开发板完成该次作业。(暂未完成,详细思路完成后补上) **3.具体步骤**百度语音合成操作步骤如下。(1)在[百度语音](http://yuyin.baidu.com/)网页依次点击“语音识别-->立即使用-->创建应用”,如下图。(提示登录的时候该注册注册,该登录登录哈!)![百度语音操作1.jpg](/uploads/201810/26/174803sgg6tc6c21tp7na7.jpg)![百度语音操作2.jpg](/uploads/201810/26/174803utortfh8t8yzhz5c.jpg)![百度语音操作3.jpg](/uploads/201810/26/174803clctsimiymyxsycc.jpg) (2)在弹出的页面中按照自己的情况填写,之后创建应用。![百度语音操作4.jpg](/uploads/201810/26/175010xbvoe5k052dptpk1.jpg) (3)创建好以后在应用列表中可以看到以下应用情况。(secret key不清楚具体为啥要打码,看到网上资料打码了就保护一下隐私)![百度语音操作6.jpg](/uploads/201810/26/175011r0hzv8htuhj2tlbu.jpg) (4)在[语音合成](https://ai.baidu.com/docs#/TTS-API/top)文档中复制以下代码,然后用自己应用中的key代替对应参数,可以在文本文档中操作。“client_id=”后面使用API Key代替,“client_secret=”后面用Secret Key代替![百度语音操作8.jpg](/uploads/201810/26/175937c55dacmcj2r19mmz.jpg) (5)替换完成以后生成的网址复制到浏览器打开,换取token。scope中含有audio_tts_post 表示有语音合成能力,没有该audio_tts_post 的token调用接口会返回502错误。![百度语音操作9.jpg](/uploads/201810/26/202805womme2vmpklkbeml.jpg) (6)使用GET调用方式,按照文档生成的地址为:```http://tsn.baidu.com/text2audio?tex=%E4%BD%A0%E5%A5%BDRT_Thread%EF%BC%8C%E8%AF%B7%E5%85%B3%E7%81%AF%EF%BC%81&lan=zh&cuid=A4-DB-30-74-3A-1F&ctp=1&aue=3&tok=24.32d07d10d1101b9c39343d5cfedcfc0e.2592000.1543137168.282335-14573176```该链接中“tex=”后面的文本为“你好RT_Thread,请关灯!”,(合成的文本,使用UTF-8编码。编码可以将地址复制到浏览器中修改“tex=”后面的文本,在url地址处修改自动生成。)“cuid=”后面是用户唯一标识,用来计算UV值。建议填写能区分用户的机器 MAC 地址或 IMEI 码,长度为60字符以内,我用的是本机mac地址。"aue=4"是为了后面的语音识别,语音合成默认为mp3格式(aue=3,可以直接在线听),不是可以语音识别的格式,aue=4为pcm-16k格式,可以语音识别。 (7)使用上面的链接可以下载合成的音频,下面就可以编写代码实现了。 耽误了好久才把代码搞定,主要一致有400 error,最后发现是因为在将文本拼接到链接的“tex=”后面是出现了问题,只要文本中有空格,就会出错,因为rt_snprintf中对于空格的处理和网页上的处理方式不一致,所以文本中不要出现空格。获取语音的代码如下,在启动qemu后输入命令baidu close或者baidu open,程序进行相应的链接拼接,并把文件名命名为close/open,之后保存获取的文件数据。(注:参考了[yukelab](https://www.rt-thread.org/qa/space-uid-10996.html)的作业代码,在此说明,要尊重版权:lol,但是我在使用全英文的时候没有出现错误。) ```#include
#include
#include "webclient.h" #include
#include
#define GET_URI "http://tsn.baidu.com/text2audio?tex=%s&lan=zh&cuid=A4-DB-30-74-3A-1F&ctp=1&aue=4&tok=24.32d07d10d1101b9c39343d5cfedcfc0e.2592000.1543137168.282335-14573176" #define COMMAND_CLOSE_LED "你好RT_Thread,请关灯!" #define COMMAND_OPEN_LED "你好RT_Thread,请开灯!" #define BAIDU_FILE_NAME "/%s.wav" #define GET_HEADER_BUFSZ 2048 //头部大小 #define GET_RESP_BUFSZ 2048 //响应缓冲区大小 #define GET_URL_LEN_MAX 1000 //GET 方式,拼接后的url总长度不多于1000个字符,不推荐长文本合成使用 static int baidu(int argc, char **argv) { struct webclient_session* session = RT_NULL; unsigned char *buffer = RT_NULL; char *baidu_url = RT_NULL; char *file_name = RT_NULL; int ret = 0; int bytes_read, resp_status; int content_length = -1; int fd; int length; baidu_url = rt_calloc(1, GET_URL_LEN_MAX); if (baidu_url == RT_NULL) { rt_kprintf("No memory for url!
"); return -1; } /* 拼接 GET 网址 */ if (strcmp(argv[1],"close")==0) { rt_snprintf(baidu_url, GET_URL_LEN_MAX, GET_URI,COMMAND_CLOSE_LED); } else if (strcmp(argv[1],"open")==0) { rt_snprintf(baidu_url, GET_URL_LEN_MAX, GET_URI,COMMAND_OPEN_LED); } else { rt_kprintf("webclient get URL failed
"); return -1; } rt_kprintf("URL:%s
", baidu_url); file_name = rt_calloc(1, 32); if (file_name == RT_NULL) { rt_kprintf("No memory for file name!
"); return -1; } /* 拼接文件名 */ rt_snprintf(file_name, 32, BAIDU_FILE_NAME, argv[1]); /* 创建会话并且设置响应的大小 */ session = webclient_session_create(GET_HEADER_BUFSZ); if (session == RT_NULL) { rt_kprintf("No memory for get header!
"); goto __exit; } /* 发送 GET 请求使用默认的头部 */ if ((resp_status = webclient_get(session, baidu_url)) != 200) { rt_kprintf("webclient GET request failed, response(%d) error.
", resp_status); goto __exit; } fd = open(file_name, O_WRONLY | O_CREAT | O_TRUNC, 0); if (fd < 0) { rt_kprintf("open file for write failed
"); } buffer = (unsigned char *) web_malloc(GET_HEADER_BUFSZ); if (buffer == RT_NULL) { rt_kprintf("no memory for receive buffer.
"); ret = -RT_ENOMEM; goto __exit; } content_length = webclient_content_length_get(session); if (content_length < 0) { do { bytes_read = webclient_read(session, buffer, GET_RESP_BUFSZ); if (bytes_read <= 0) { break; } /* 写入数据 */ length = write(fd, buffer, bytes_read); if (length != bytes_read) { rt_kprintf("write data failed
"); close(fd); break; } } while (1); rt_kprintf("
"); } else { int content_pos = 0; do { bytes_read = webclient_read(session, buffer, content_length - content_pos > GET_RESP_BUFSZ ? GET_RESP_BUFSZ : content_length - content_pos); if (bytes_read <= 0) { break; } length = write(fd, buffer, bytes_read); if (length != bytes_read) { rt_kprintf("write data failed in else
"); close(fd); break; } content_pos += bytes_read; } while (content_pos < content_length); rt_kprintf("
"); } __exit: if (session) { webclient_close(session); } if (buffer) { web_free(buffer); } if (baidu_url) { web_free(baidu_url); } if (file_name) { web_free(file_name); } if (fd > 0) { close(fd); } return ret; } MSH_CMD_EXPORT(baidu, get baidu voice);```![homework_graduate.zip](/uploads/201810/29/100052ubjm848aaoaazzii.zip)运行结果截图:![百度语音操作10.jpg](/uploads/201810/29/101310r3lzrlgdsv2duwg5.jpg) 在[yukelab](https://www.rt-thread.org/qa/space-uid-10996.html)的帮助下实现了语音识别,美中不足的是,虽然能够返回正确的结果,还是会有错误出现,暂时告一段落,把学习结果写下来。问题的解决主要是在上传语音数据之后添加了webclient_set_timeout(session, 100000);函数,延长了等待百度云返回数据的时间,因为返回数据时间和网速、百度云的处理的hi建以及数据量大小都有关系。```#include
#include
#include
#include
#include
#define POST_RESP_BUFSZ 1024 #define POST_HEADER_BUFSZ 1024 #define FILE_NAME_MAX 32 #define BAIDU_FILE_NAME "/baidu/%s.pcm" #define POST_LOCAL_URI "http://vop.baidu.com/server_api?dev_pid=1536&cuid=A4-DB-30-74-3A-1F&token=24.32d07d10d1101b9c39343d5cfedcfc0e.2592000.1543137168.282335-14573176" int webclient_post_test(int argc, char **argv) { struct webclient_session* session = RT_NULL; unsigned char *buffer = RT_NULL; char *URI = RT_NULL; int index, ret = 0; int bytes_read, resp_status; char *file_name = RT_NULL; int fd = -1, rc = WEBCLIENT_OK; int send_count = 0,content_pos=0; size_t length; file_name = rt_calloc(1, FILE_NAME_MAX); if (file_name == RT_NULL) { rt_kprintf("No memory for file name!
"); return -1; } //rt_snprintf(post_data, 1024, post_date); if (argc == 1) { rt_snprintf(file_name, FILE_NAME_MAX, BAIDU_FILE_NAME,"on1" ); } else if (argc == 2) { rt_snprintf(file_name, FILE_NAME_MAX, BAIDU_FILE_NAME,argv[1] ); } else { rt_kprintf("webclient_post_test [URI] - webclient POST request test.
"); return -1; } fd = open(file_name, O_RDONLY, 0); if (fd < 0) { LOG_D("post file failed, open file(%s) error.", file_name); rc = -WEBCLIENT_FILE_ERROR; goto __exit; } /* get the size of file */ length = lseek(fd, 0, SEEK_END); lseek(fd, 0, SEEK_SET); URI = web_strdup(POST_LOCAL_URI); if(URI == RT_NULL) { rt_kprintf("no memory for create URI buffer.
"); return -1; } buffer = (unsigned char *) web_malloc(POST_RESP_BUFSZ); if (buffer == RT_NULL) { rt_kprintf("no memory for receive response buffer.
"); ret = -RT_ENOMEM; goto __exit; } /* create webclient session and set header response size */ session = webclient_session_create(POST_HEADER_BUFSZ); if (session == RT_NULL) { ret = -RT_ENOMEM; goto __exit; } /* build header for upload */ webclient_header_fields_add(session, "Content-Length: %d
", length); webclient_header_fields_add(session, "Content-Type: audio/pcm;rate=16000
"); rt_kprintf("length=%d
",length); /* send POST request by default header */ if ((resp_status = webclient_post(session, URI, NULL)) < 0) { rt_kprintf("webclient POST request failed, response(%d) error.
", resp_status); ret = -RT_ERROR; goto __exit; } content_pos = 0; while (1) { rt_memset(buffer, 0x00, POST_RESP_BUFSZ); length = read(fd, buffer, POST_RESP_BUFSZ); if (length <= 0) { break; } ret = webclient_write(session, buffer, 1024); if (ret < 0) { rt_kprintf("webclient write error!
"); break; } rt_kprintf("read file data length %d; webclient write %d cnt!
", length, ++send_count); //rt_thread_mdelay(20); } webclient_set_timeout(session, 100000); rt_kprintf("webclient POST request response data :
"); do { bytes_read = webclient_read(session, buffer, POST_RESP_BUFSZ); if (bytes_read <= 0) { break; } for (index = 0; index < bytes_read; index++) { rt_kprintf("%c", buffer[index]); } } while (1); rt_kprintf("
"); __exit: if (buffer) { web_free(buffer); } if (URI) { web_free(URI); } return ret; } #ifdef FINSH_USING_MSH #include
MSH_CMD_EXPORT_ALIAS(webclient_post_test, web_post_test, webclient_post_test [URI] - webclient POST request test.); #endif /* FINSH_USING_MSH */```![homework_graduate_1.zip](/uploads/201811/06/170703u0fafuaqhqxx470f.zip)在sd.bin中加入了4个语音文件,open和close是百度云语音合成的,另外两个是网上下载的,百度语音合成的识别不成功,毕竟和自然的语音差别比较大,识别百度云网站上下载的16k.pcm文件没问题。启动qemu后输入 web_post_test 16k,得到如下结果:![百度语音操作11.jpg](/uploads/201811/06/170432veq2l9ihsh6bxcuh.jpg)虽然还是有错误,但是已经能够成功识别了,先把作业补全了吧:D!
查看更多
4
个回答
默认排序
按发布时间排序
wo4fisher
2018-10-29
这家伙很懒,什么也没写!
语音合成要比语音识别 接口/实现简单啊
yukelab
2018-10-29
这家伙很懒,什么也没写!
回过头来再看一下,两个的实现都比较简单。不过识别,建议不要参考webclient_file.c文件,里面的post模式,header拼接有问题:lol
san兄弟
2018-10-30
这家伙很懒,什么也没写!
>语音合成要比语音识别 接口/实现简单啊 --- 临时有事还没来得及看识别
san兄弟
2018-10-30
这家伙很懒,什么也没写!
>回过头来再看一下,两个的实现都比较简单。不过识别,建议不要参考webclient_file.c文件,里面的post模式, ... --- 多谢提醒:handshake
撰写答案
登录
注册新账号
关注者
0
被浏览
1.9k
关于作者
san兄弟
这家伙很懒,什么也没写!
提问
8
回答
36
被采纳
0
关注TA
发私信
相关问题
1
【LWIP学习营】第一关开发环境搭建
2
LWIP学习营第一周入门移植问题汇总贴
3
【LWIP学习营】f407+lan8720A小结
4
【LwIP学习营】【第一周】仅零散记录,无主题
5
【LWIP学习营】正点原子探索者F407+LAN8720第一周小结
6
【LwIP学习营】【第一周】网络通信基础及实现TCP 聊天客户端
7
【LwIP学习营】【第一周】LWIP移植
8
【LwIP学习营】【第一周】LWIP移植
9
【LwIP学习营】【第一周】开发板适配
10
【LwIP学习营】【第一周】环境搭建和配置验证
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
GD32F450 片内 flash驱动适配
2
STM32H7R7运行CherryUSB
3
RT-Smart首次线下培训,锁定2024 RT-Thread开发者大会!
4
使用RC522软件包驱动FM1722
5
常量数据类型和表达式陷阱分享
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
freemodbus
PWM
flash
cubemx
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
中断
编译报错
Debug
SFUD
rt_mq_消息队列_msg_queue
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
a1012112796
10
个答案
1
次被采纳
踩姑娘的小蘑菇
4
个答案
1
次被采纳
红枫
4
个答案
1
次被采纳
张世争
4
个答案
1
次被采纳
Ryan_CW
4
个答案
1
次被采纳
本月文章贡献
catcatbing
3
篇文章
5
次点赞
YZRD
2
篇文章
3
次点赞
qq1078249029
2
篇文章
2
次点赞
xnosky
2
篇文章
1
次点赞
Woshizhapuren
1
篇文章
5
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部