前记:

前段时间公司没事干,突发奇想想做一个语音识别系统,看起来应该非常easy的,但做起来却是各种问题,这个对电气毕业的我,却是挺为难的。谷姐已经离我们而去,感谢度娘,感谢CSDN各位大神,好歹也做的是那么回事了,尽管还是不好用,但基本功能实现了。

该软件使用VS2008C++/CLR开发,因为科大讯飞提供的是C的API接口,结果到这边就是各种不兼容,CLR是基于托管堆执行的,而这个API有是非托管堆的,使用了各种指针,原本打算使用C#来做,最后门外汉的我也没能做到C#和C指针完美结合,真怀恋单片机写代码的年代啊。还有录音方面须要directX是的支持。软件下载地址:http://download.csdn.net/detail/liucheng5037/7509003

软件执行界面例如以下图所看到的:

左边实现文字转语音,须要在文本框中输入文字,然后依据须要配置好声音,音量,速度选项,点击播放,软件会先通过讯飞的API获取语音,然后以设定的方式播放出来。

右边实现语音转文字,直接按住button说话,松开后软件通过讯飞的API将语音信息传递给语音云,最后返回文字显示在文本框。

看起来非常easy的东西折腾了我不少时间啊!!!

系统组成

该系统由4部分组成:讯飞云、语音录入、语音播放、系统控制。语音播放和讯飞云封装在一个类XunFeiSDK里面,语音录入使用的是网上找的基于DirectX的类SoundRecord,基于C#写的,本想把录入也写到讯飞云那个类里去,结果说什么非托管的类不能有基于托管堆的成员,无奈仅仅有单独出来,作为一个dll文件存在。系统控制是在form类里面。

讯飞语音云:

(先复制一段官方说法)

讯飞移动语音平台是基于讯飞公司已有的ISP 和IMS 产品,开发出的一款符合移动互联网用户使用的语音应用开发平台,提供语音合成、语音听写、语音识别、声纹识别等服务,为语音应用开发爱好者提供方便易用的开发接口,使得用户可以基于该开发接口进行多种语音应用开发。其主要功能有:

1)实现基于HTTP 协议的语音应用server,集成讯飞公司最新的语音引擎,支持语音合成、语音听写、语音识别、声纹识别等服务;

2)提供基于移动平台和PC 上的语音client子系统,内部集成音频处理和音频编解码模块,提供关于语音合成、语音听写、语音识别和声纹识别完好的API。

(复制完成)

因为仅仅想写的玩玩,没有太多时间,故直接把官方C语言写的demo复制过来,转变成一个类。官方提供了一个dll文件一个lib文件另一堆H文件。详细运行的代码时封装在dll文件中的,我们看不到,我们须要引入lib文件来间接调用语音函数。引入lib的方式例如以下:

  1. #ifdef _WIN64
  2. #pragma comment(lib,"../lib/msc_x64.lib")//x64
  3. #else
  4. #pragma comment(lib,"../lib/msc.lib")//x86
  5. #endif

然后须要include以下几个H文件:

  1. #include "../include/qisr.h"
  2. #include "../include/qtts.h"
  3. #include "../include/msp_cmn.h"
  4. #include "../include/msp_errors.h"

类XunFeiSDK不能使用ref来修饰,不然又是各种托管堆和非托管堆不能互通之类的报错。讯飞语音一个转换来回例如以下:

讯飞语音具体的说明能够到这里下载http://open.voicecloud.cn/index.php/services/voicebase?type=tts&tab_index=1

选择windowsSDK开发包,里面有一些简单的demo和说明,只是须要事先注冊才干下载。

有一点要注意的是,语音返回的音频格式是PCM这样的格式和wav非常像,一般支持WAV的播放器都支持PCM。不同的语音播放方式如普通话女声和东北话使用的语音引擎不同,详细可參考类SoundType。

登录能够在软件打开时运行,登出能够在软件关闭时运行,中间的转换每次须要运行一次,由于每次运行的sessionID不一样,每次须要又一次发起会话。

语音录入:

这一部分花的时间比較长,刚開始时什么都不知道啊,一点录入的概念都没有,全然不知道该调用什么API,用什么控件,仅仅有到处百度,试了各种办法,最后,果然CSDN是大神出没的地方,被我找到了,地址例如以下:C#中使用DirectSound录音

这个类封装的非常好,就仅仅有3个函数。

SetFileName():录音文件存放位置和名称

RecStart():開始录音

RecStop():结束录音

整个录音过程是在一个单独线程上执行的,不会影响主程序执行。

C#DLL文件移植到C++的方法:

1、使用#using把文件包括进来#using "SoundRecord.dll";

2、添加命名空间usingnamespace VoiceRecord;

3、声明一个对象,注意类名不能够和命名空间名一致,这样尽管声称dll时不会出错,但编译会出错, SoundRecord^ recorder;

语音播放

该部分比較简单,直接使用了System::Media命名空间下的类SoundPlayer,在使用时直接gcnew一个对象,然后load(),然后play(),当然,load能够不要的。这个play能够支持播放PCM和WAV格式语音,其它格式未试验。

系统控制部分

在这一部分声明了一个静态的XunFeiSDK类指针,另一个录音类的托管对象,还有转换进程等。

  1. static XunFeiSDK* xunfei;
  2. static SoundRecord^ recorder;
  3. Thread^ xunfei_thread;

音频转文字部分採用了单独线程,因为子线程不能够訪问主线程的form控件,无奈又加了个定时器和标志位来检測子线程是否完毕,网上说能够採用托付的方式来訪问控件,但本人实在弄不懂托付,仅仅有放弃,这一部分做的非常单片机的style。

在文字转语音部分没有採用进程,会有在这里卡一会。

知识点

1、因为使用的是讯飞的C库,又用到了C++/CLR的form,托管堆和非托管堆的鸿沟非常麻烦。

本程序使用了微软提供的转换函数。须要include的内容:

  1. #include <windows.h>
  2. #include <string>
  3. #include <iostream>
  4. #include <sstream>
  5. include <msclr\marshal.h>

a、std::string转const char *

const char *strp=str.c_str();

b、System::String^转 string 和 const char*

Stringstd_str = (constchar*)(Marshal::StringToHGlobalAnsi(nowTime.ToString(Sys_str))).ToPointer();

c、char* 转 System::String^

Sys_str = Marshal::PtrToStringAnsi((IntPtr)char_str);

d、int 转 std::String

ostringstreamoss1;

oss1<<int_num;

std_str = oss1.str();

2、同一文件下,若一个类须要使用还有一个类,则须要在前面声明一下,这和C函数类似。

Eg:refclass SoundType;

3、在非托管类下,不能使用托管类作为成员;实例化托管对象须要使用gcnew,实例化非托管对象直接使用new。

4、对List之类的对象,能够直接加入不论什么对象,包含form上的List,比方ComboBox,显示是显示该对象的ToString方法。

TOString方法重载:

  1. virtual System::String^ ToString() override//重载ToString方法
  2. {
  3. return voice;
  4. }

5、switchcase 不支持string类型的值输入。

部分源码例如以下:

  1. //类XunFeiSDK
  2. /*
  3. string str("hello");
  4. const char *strp=str.c_str(); string转const char*
  5. */
  6. //#using "Microsoft.DirectX.DirectSound.dll"
  7. //#using "Microsoft.DirectX.dll"
  8.  
  9. #include "../SoundTest/stdafx.h"
  10. //#include "stdafx.h"
  11. #include "stdlib.h"
  12. #include "stdio.h"
  13. #include <windows.h>
  14. #include <conio.h>
  15. #include <errno.h>
  16. #include <iostream>
  17. #include <sstream>
  18. #include <fstream>
  19. #include <time.h>
  20. #include <string>
  21. #include <msclr\marshal.h>
  22.  
  23. using namespace std;
  24.  
  25. #include "../include/qisr.h"
  26. #include "../include/qtts.h"
  27. #include "../include/msp_cmn.h"
  28. #include "../include/msp_errors.h"
  29.  
  30. #ifdef _WIN64
  31. #pragma comment(lib,"../lib/msc_x64.lib")//x64
  32. #else
  33. #pragma comment(lib,"../lib/msc.lib")//x86
  34. #endif
  35.  
  36. #define DebugPrint(str_x,msg_y) fprintf(out_file,(str_x),(msg_y))
  37.  
  38. typedef int SR_DWORD;
  39. typedef short int SR_WORD ;
  40.  
  41. //音频头部格式
  42. struct wave_pcm_hdr
  43. {
  44. char riff[4]; // = "RIFF"
  45. SR_DWORD size_8; // = FileSize - 8
  46. char wave[4]; // = "WAVE"
  47. char fmt[4]; // = "fmt "
  48. SR_DWORD dwFmtSize; // = 下一个结构体的大小: 16
  49.  
  50. SR_WORD format_tag; // = PCM : 1
  51. SR_WORD channels; // = 通道数: 1
  52. SR_DWORD samples_per_sec; // = 採样率: 8000 | 6000 | 11025 | 16000
  53. SR_DWORD avg_bytes_per_sec; // = 每秒字节数: dwSamplesPerSec * wBitsPerSample / 8
  54. SR_WORD block_align; // = 每採样点字节数: wBitsPerSample / 8
  55. SR_WORD bits_per_sample; // = 量化比特数: 8 | 16
  56.  
  57. char data[4]; // = "data";
  58. SR_DWORD data_size; // = 纯数据长度: FileSize - 44
  59. } ;
  60.  
  61. //默认音频头部数据
  62. const struct wave_pcm_hdr default_pcmwavhdr =
  63. {
  64. { 'R', 'I', 'F', 'F' },
  65. 0,
  66. {'W', 'A', 'V', 'E'},
  67. {'f', 'm', 't', ' '},
  68. 16,
  69. 1,
  70. 1,
  71. 16000,
  72. 32000,
  73. 2,
  74. 16,
  75. {'d', 'a', 't', 'a'},
  76. 0
  77. };
  78.  
  79. namespace SoundTest {
  80. using namespace System;
  81. using namespace System::Runtime::InteropServices;
  82. using namespace System::Media;
  83. using namespace msclr::interop;
  84. ref class SoundType;
  85.  
  86. public class XunFeiSDK{
  87.  
  88. private: FILE* out_file;//输出log文件
  89. string appid;
  90. int ret;
  91. string pcm_path;//存储音频文件的文件名称
  92. string user;
  93. string password;
  94. string voice_type;//语言类型
  95. string volunm;//音量0-10
  96. string engin;//引擎
  97. string voice_speed;//语速-10
  98.  
  99. public: XunFeiSDK()
  100. {
  101. DateTime nowTime = DateTime::Now;
  102. string nowTimes = (const char*)(Marshal::StringToHGlobalAnsi(nowTime.ToString("yyyy-MM-dd HH:mm:ss"))).ToPointer();
  103. fopen_s(&out_file,"log.txt","at+");
  104. if(out_file == NULL)
  105. {
  106. ret = -1;
  107. return;
  108. }
  109. fseek(out_file, 0, 2);
  110. fprintf(out_file,"begin Time:%s \n",nowTimes.c_str());
  111.  
  112. appid = "";
  113. user = "";
  114. password = "53954218";//能够上官网注冊专属自己的ID
  115. pcm_path = "PCM_SPEED.pcm";
  116. voice_type = "xiaoyan";
  117. volunm = "7";
  118. voice_speed = "5";
  119. engin = "intp65";
  120. }
  121. ~XunFeiSDK()
  122. {
  123. string nowTimes = (const char*)(Marshal::StringToHGlobalAnsi(DateTime::Now.ToString("yyyy-MM-dd HH:mm:ss"))).ToPointer();
  124. fprintf(out_file,"Time:%s end\n",nowTimes.c_str());
  125. fclose(out_file);
  126. }
  127.  
  128. public: int status()
  129. {
  130. return ret;
  131. }
  132.  
  133. bool Login()//登录
  134. {
  135. string logins = "appid = " + appid + ",work_dir = . ";
  136. ret = MSPLogin(user.c_str(), password.c_str(), logins.c_str());
  137. if ( ret != MSP_SUCCESS )
  138. {
  139. fprintf(out_file,"MSPLogin failed , Error code %d.\n",ret);
  140. return false;
  141. }
  142. return true;
  143. }
  144.  
  145. void Logout()
  146. {
  147. MSPLogout();//退出登录
  148. }
  149.  
  150. int TextToSpeed(System::String^ Ssrc_text)//字符串转音频,音频存放在PCM_SPEED.pcm下
  151. {
  152. #pragma region 字符串转音频
  153. struct wave_pcm_hdr pcmwavhdr = default_pcmwavhdr;
  154. const char* sess_id = NULL;
  155. unsigned int text_len = 0;
  156. char* audio_data = NULL;
  157. unsigned int audio_len = 0;
  158. int synth_status = MSP_TTS_FLAG_STILL_HAVE_DATA;
  159. FILE* fp = NULL;
  160. string params = "vcn=xiaoyan, spd = 50, vol = 50";//參数可參考可设置參数列表
  161. ret = -1;//失败
  162. //參数配置
  163. params = "vcn=" + voice_type + ", spd = " + voice_speed + ", vol = " + volunm + ", ent = "+engin;
  164. const char* src_text = (const char*)(Marshal::StringToHGlobalAnsi(Ssrc_text)).ToPointer();
  165.  
  166. pcm_path = "PCM_SPEED.pcm";
  167.  
  168. fprintf(out_file,"begin to synth source = %s\n",src_text);
  169. if (NULL == src_text)
  170. {
  171. fprintf(out_file,"params is null!\n");
  172. return ret;
  173. }
  174. text_len = strlen(src_text);//获取文本长度
  175.  
  176. fopen_s(&fp,pcm_path.c_str(),"wb");//打开PCM文件
  177. if (NULL == fp)
  178. {
  179. fprintf(out_file,"open PCM file %s error\n",pcm_path);
  180. return ret;
  181. }
  182.  
  183. sess_id = QTTSSessionBegin(params.c_str(), &ret);//開始一个会话
  184. if ( ret != MSP_SUCCESS )
  185. {
  186. fprintf(out_file,"QTTSSessionBegin: qtts begin session failed Error code %d.\n",ret);
  187. return ret;
  188. }
  189. fprintf(out_file,"sess_id = %s\n",sess_id);
  190. ret = QTTSTextPut(sess_id, src_text, text_len, NULL );//发送txt信息
  191. if ( ret != MSP_SUCCESS )
  192. {
  193. fprintf(out_file,"QTTSTextPut: qtts put text failed Error code %d.\n",ret);
  194. QTTSSessionEnd(sess_id, "TextPutError");//异常,结束
  195. return ret;
  196. }
  197. fwrite(&pcmwavhdr, sizeof(pcmwavhdr) ,1, fp);//把開始文件写到最前面
  198.  
  199. while (1)//循环读取音频文件并存储
  200. {
  201. const void *data = QTTSAudioGet(sess_id, &audio_len, &synth_status, &ret);
  202. if (NULL != data)
  203. {
  204. fwrite(data, audio_len, 1, fp);
  205. pcmwavhdr.data_size += audio_len;//修正pcm数据的大小
  206. }
  207. if (synth_status == MSP_TTS_FLAG_DATA_END || ret != 0)
  208. break;
  209. }//合成状态synth_status取值可參考开发文档
  210.  
  211. //修正pcm文件头数据的大小
  212. pcmwavhdr.size_8 += pcmwavhdr.data_size + 36;
  213.  
  214. //将修正过的数据写回文件头部
  215. fseek(fp, 4, 0);
  216. fwrite(&pcmwavhdr.size_8,sizeof(pcmwavhdr.size_8), 1, fp);
  217. fseek(fp, 40, 0);
  218. fwrite(&pcmwavhdr.data_size,sizeof(pcmwavhdr.data_size), 1, fp);
  219. fclose(fp);
  220.  
  221. ret = QTTSSessionEnd(sess_id, NULL);
  222. if ( ret != MSP_SUCCESS )
  223. {
  224. fprintf(out_file,"QTTSSessionEnd: qtts end failed Error code %d.\n",ret);
  225. }
  226. fprintf(out_file,"program end");
  227. return ret;
  228. #pragma endregion
  229. }
  230.  
  231. System::String^ GetPcmName()//获取音频文件路径
  232. {
  233. return gcnew String(pcm_path.c_str());
  234. }
  235.  
  236. int Play(System::String^ text)//播放音频文件
  237. {
  238. if(text == "") return -1;
  239. SoundPlayer^ player = (gcnew SoundPlayer(text));//音频播放器
  240. player->SoundLocation = text;
  241. player->Load();
  242. player->Play();
  243. return 0;
  244. }
  245.  
  246. int StartRecord()//開始录音
  247. {
  248.  
  249. }
  250.  
  251. int EndRecord()//结束录音
  252. {
  253.  
  254. }
  255.  
  256. System::String^ SpeedToText(System::String^ text)//语音转文字,输入语音文件名称,返回文字信息
  257. {
  258. System::String^ Sys_value = "No data return";
  259. const char* src_wav_filename = (const char*)(Marshal::StringToHGlobalAnsi(text)).ToPointer();
  260. //test = Marshal::PtrToStringAnsi((IntPtr)(char *)src_text);
  261. //return test;
  262. char rec_result[1024] = {0};//存放返回结果
  263. const char *sessionID = NULL;
  264. FILE *f_pcm = NULL;//
  265. char *pPCM = NULL;//存放音频文件缓存
  266. int lastAudio = 0 ;
  267. int audStat = MSP_AUDIO_SAMPLE_CONTINUE ;
  268. int epStatus = MSP_EP_LOOKING_FOR_SPEECH;
  269. int recStatus = MSP_REC_STATUS_SUCCESS ;
  270. long pcmCount = 0;
  271. long pcmSize = 0;//音频文件大小
  272. int errCode = 10 ;
  273. string param = "sub=iat,auf=audio/L16;rate=16000,aue=speex-wb,ent=sms16k,rst=plain,rse=gb2312";
  274.  
  275. fprintf(out_file,"Start iat...\n");
  276. sessionID = QISRSessionBegin(NULL, param.c_str(), &errCode);//開始一路会话
  277. fopen_s(&f_pcm,src_wav_filename, "rb");
  278. if (NULL != f_pcm) {
  279. fseek(f_pcm, 0, SEEK_END);
  280. pcmSize = ftell(f_pcm);//获取音频大小
  281. fseek(f_pcm, 0, SEEK_SET);
  282. pPCM = (char *)malloc(pcmSize);//分配内存存放音频
  283. fread((void *)pPCM, pcmSize, 1, f_pcm);
  284. fclose(f_pcm);
  285. f_pcm = NULL;
  286. }//读取音频文件,读到pPCM中
  287. else
  288. {
  289. fprintf(out_file,"media %s not found\n",src_wav_filename);
  290. return Sys_value;
  291. }
  292.  
  293. while (1) {//開始往server写音频数据
  294. unsigned int len = 6400;
  295. int ret = 0;
  296. if (pcmSize < 12800) {
  297. len = pcmSize;
  298. lastAudio = 1;//音频长度小于
  299. }
  300. audStat = MSP_AUDIO_SAMPLE_CONTINUE;//有后继音频
  301. if (pcmCount == 0)
  302. audStat = MSP_AUDIO_SAMPLE_FIRST;
  303. if (len<=0)
  304. {
  305. break;
  306. }
  307. fprintf(out_file,"csid=%s,count=%d,aus=%d,",sessionID,pcmCount/len,audStat);
  308. ret = QISRAudioWrite(sessionID, (const void *)&pPCM[pcmCount], len, audStat, &epStatus, &recStatus);//写音频
  309. fprintf(out_file,"eps=%d,rss=%d,ret=%d\n",epStatus,recStatus,errCode);
  310. if (ret != 0)
  311. break;
  312. pcmCount += (long)len;
  313. pcmSize -= (long)len;
  314. if (recStatus == MSP_REC_STATUS_SUCCESS) {
  315. const char *rslt = QISRGetResult(sessionID, &recStatus, 0, &errCode);//服务端已经有识别结果,能够获取
  316. fprintf(out_file,"csid=%s,rss=%d,ret=%d\n",sessionID,recStatus,errCode);
  317. if (NULL != rslt)
  318. strcat_s(rec_result,rslt);
  319. }
  320. if (epStatus == MSP_EP_AFTER_SPEECH)
  321. break;
  322. Sleep(150);//模拟人说话时间间隙
  323. }
  324. QISRAudioWrite(sessionID, (const void *)NULL, 0, MSP_AUDIO_SAMPLE_LAST, &epStatus, &recStatus);//写入结束
  325. free(pPCM);
  326. pPCM = NULL;
  327. while (recStatus != MSP_REC_STATUS_COMPLETE && 0 == errCode) {
  328. const char *rslt = QISRGetResult(sessionID, &recStatus, 0, &errCode);//获取结果
  329. fprintf(out_file,"csid=%s,rss=%d,ret=%d\n",sessionID,recStatus,errCode);
  330. if (NULL != rslt)
  331. {
  332. strcat_s(rec_result,rslt);
  333. }
  334. Sleep(150);
  335. }
  336. QISRSessionEnd(sessionID, NULL);
  337. fprintf(out_file,"The result is: %s\n",rec_result);
  338. if(NULL != rec_result)//不为空时返回正确值
  339. Sys_value = Marshal::PtrToStringAnsi((IntPtr)rec_result);//数值转换
  340.  
  341. return Sys_value;
  342. }
  343.  
  344. void set_tts_params(System::String^ e_voice_type , System::String^ e_engin , int e_volunm , int e_speed)
  345. {
  346. const char* src_text = (const char*)(Marshal::StringToHGlobalAnsi(e_voice_type)).ToPointer();
  347. voice_type = src_text;
  348. src_text = (const char*)(Marshal::StringToHGlobalAnsi(e_engin)).ToPointer();
  349. engin = src_text;
  350. ostringstream oss1;
  351. ostringstream oss2;
  352. oss1<<e_volunm;
  353. volunm = oss1.str();//音量
  354. oss2<<e_speed;
  355. voice_speed = oss2.str();//语速
  356. }
  357.  
  358. };
  359.  
  360. public ref class SoundType{
  361. public: System::String^ engin;//语音引擎
  362. System::String^ voice_type;//说话类型
  363. System::String^ voice;//显示
  364.  
  365. SoundType(System::String^ e_voice)//switch case 不支持string的输入
  366. {
  367. voice = e_voice;
  368.  
  369. if (e_voice == "普通话女声") {engin = "intp65";voice_type = "xiaoyan";}
  370. else if(e_voice == "普通话男声") {engin = "intp65";voice_type = "xiaoyu";}
  371. else if(e_voice == "英文女声") {engin = "intp65_en";voice_type = "Catherine";}
  372. else if(e_voice == "英文男声") {engin = "intp65_en";voice_type = "henry";}
  373. else if(e_voice == "粤语") {engin = "vivi21";voice_type = "vixm";}
  374. else if(e_voice == "台湾话") {engin = "vivi21";voice_type = "vixl";}
  375. else if(e_voice == "四川话") {engin = "vivi21";voice_type = "vixr";}
  376. else if(e_voice == "东北话") {engin = "vivi21";voice_type = "vixyun";}
  377. else {engin = "intp65";voice_type = "xiaoyan";voice = "普通话女声";}
  378.  
  379. }
  380. SoundType()
  381. {
  382. engin = "intp65";voice_type = "xiaoyan";voice = "普通话女声";
  383. }
  384.  
  385. virtual System::String^ ToString() override//重载ToString方法
  386. {
  387. return voice;
  388. }
  389.  
  390. };
  391.  
  392. }

FORM类:

局部变量:

  1. private: static XunFeiSDK* xunfei;
  2. private: Thread^ xunfei_thread;
  3. static int end_flag;
  4. static String^ end_result;
  5. ArrayList^ voice_types;
  6. private: static SoundRecord^ recorder;
  1. #pragma region 控件触发函数
  2. private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) {
  3. xunfei = (new XunFeiSDK());
  4. end_flag = 0;
  5. if(-1 == xunfei->status())
  6. {
  7. MessageBox::Show("初始化失败");
  8. this->Close();//关闭窗口
  9. return;
  10. }
  11. if(!(xunfei->Login()))
  12. {
  13. MessageBox::Show("登录失败");
  14. this->Close();//关闭窗口
  15. return;
  16. }
  17. volunm_lab->Text = "音量 " + volunm_bar->Value;
  18. speed_lab->Text = "速度 " + speed_bar->Value;
  19. }
  20. private: System::Void Form1_FormClosing(System::Object^ sender, System::Windows::Forms::FormClosingEventArgs^ e) {
  21. xunfei->Logout();//登出
  22. delete xunfei;//必须释放才会调用析构函数
  23. delete recorder;
  24. }
  25.  
  26. private: System::Void play_tts_btn_Click(System::Object^ sender, System::EventArgs^ e) {
  27. // tts_status_lab->Text = "先转换,再播放语音";
  28. set_xunfei_param();//參数设置
  29. if(-1 == xunfei->TextToSpeed(txt_speak->Text))
  30. {
  31. MessageBox::Show("转换失败");
  32. }
  33. else
  34. {
  35. xunfei->Play(xunfei->GetPcmName());
  36. }
  37. }
  38.  
  39. private: System::Void speak_btn_MouseDown(System::Object^ sender, System::Windows::Forms::MouseEventArgs^ e) {
  40. StartRecord();//開始录音线程
  41. status_lab->Text = "录音中.....";
  42. }
  43.  
  44. private: System::Void speak_btn_MouseUp(System::Object^ sender, System::Windows::Forms::MouseEventArgs^ e) {
  45. status_lab->Text = "结束录音,转换中...";
  46. xunfei_thread = (gcnew Thread(gcnew ThreadStart(EndRecord)));
  47. xunfei_thread->Start();
  48. }
  49. private: System::Void timer1_Tick(System::Object^ sender, System::EventArgs^ e) {
  50. if(1 == end_flag)
  51. {
  52. end_flag = 0;
  53. result_box->Text = end_result;
  54. status_lab->Text = "转换结束";
  55. }
  56. }
  57. private: System::Void volunm_bar_Scroll(System::Object^ sender, System::EventArgs^ e) {
  58. volunm_lab->Text = "音量 " + volunm_bar->Value;
  59. }
  60. private: System::Void speed_bar_Scroll(System::Object^ sender, System::EventArgs^ e) {
  61. speed_lab->Text = "速度 " + speed_bar->Value;
  62. }
  63. #pragma endregion
  64.  
  65. #pragma region 自己定义函数
  66. private: void set_xunfei_param()//讯飞语音參数设置
  67. {
  68. SoundType^ sound_type;
  69.  
  70. sound_type = (SoundType^)(voice_type->SelectedItem);//获取选中的对象
  71. xunfei->set_tts_params(sound_type->voice_type , sound_type->engin , volunm_bar->Value , speed_bar->Value);
  72. }
  73. private: static void StartRecord()
  74. {
  75. recorder = (gcnew SoundRecord());
  76. recorder->SetFileName("record.wav");
  77. recorder->RecStart(); //開始录音
  78. }
  79.  
  80. private:static void EndRecord()
  81. {
  82. // String text;
  83. recorder->RecStop();
  84. delete recorder;
  85. end_result = xunfei->SpeedToText("record.wav");//录音结束,显示语音转换结果
  86. end_flag = 1;
  87. }
  88. #pragma endregion

基于科大讯飞语音云windows平台开发的更多相关文章

  1. Windows平台开发Mapreduce程序远程调用运行在Hadoop集群—Yarn调度引擎异常

    共享原因:虽然用一篇博文写问题感觉有点奢侈,但是搜索百度,相关文章太少了,苦苦探寻日志才找到解决方案. 遇到问题:在windows平台上开发的mapreduce程序,运行迟迟没有结果. Mapredu ...

  2. ROS语音交互(三)科大讯飞语音在ROS平台下使用

    以上节tts语音输出为例 下载sdk链接:http://www.xfyun.cn/sdk/dispatcher 1.下载SDK,解压: 2.在ROS工作空间下创建一个Package: catkin_c ...

  3. 基于PHP的微信公众平台开发(TOKEN验证,消息回复)

    微信公众平台开发 实现步骤: 第一步:填写服务器配置 登录微信公众平台官网后,在公众平台后台管理页面 - 开发者中心页,点击“修改配置”按钮,填写服务器地址(URL).Token和EncodingAE ...

  4. 转:基于科大讯飞语音API语音识别开发详解

    原文来自于: http://www.52wulian.org/android_voice/ 最近项目需要用到android语音识别,立马就想到科大讯飞,结合官方实例及阅读API文档,初步的完成了And ...

  5. 64 位 Windows 平台开发注意要点之文件系统重定向

    Program Files 的重定向 很多开发人员都知道,在 64 位 Windows 系统上,32 位程序是无法获取得到 C:\Program Files 的完整路径的,只能获取到 C:\Progr ...

  6. 64 位 Windows 平台开发注意要点之注册表重定向

    Window 系统错误代码 ERROR_SUCCESS,本博客中一律使用 NO_ERROR 代替.虽然 ERROR_SUCCESS 与 NO_ERROR 是完全等价的,都代表成功,但是后者却和其他错误 ...

  7. 【开篇】基于C#+EmguCV的机器视觉平台开发

    市面上关于通用的机器视觉平台已有不少,一些大的视觉产品.设备制造商都有开发自己的一套系统.其通用性也都有一些行业局限,难以囊括所有可能性,一些需要经过二次开发,这也是难以攻克的问题.本人水平有限,再加 ...

  8. 基于bmob后端云小程序开发——口袋吉他

    人的一生90%的时间都在做着无聊的事情,社会的发展使得我们的闲暇时间越来越多,我们把除了工作的其他时间放在各种娱乐活动上. 程序员有点特殊,他们把敲代码看成娱乐活动的一部分,以此打发时间的不占少数.这 ...

  9. Azure云 windows平台 搭建ftp服务器注意事项

    1.iis设置防火墙支持端口(1-65535自定义端口,一般3-5个都行) 2.客户端连接使用被动链接模式 3.endpoint终结点添加20,21,以及你自定义的防火墙支持端口. 4.本地防火墙添加 ...

随机推荐

  1. 基于Gsoap 的ONVIF C++ 库

    https://github.com/xsmart/onvifcpplib 该库支持ProfileS 和ProfileG,目前正在开发哪些,现拥有支持Event 下面是一个client样本 int _ ...

  2. cocos2d-html5基金会

    1 环境结构 版本号Cocos2d-html5-v2.2,tomcat7.0 构造tomcat.然后直接解压Cocos2d-html5-v2.2.zip.解压后根文件访问的文件夹index.html你 ...

  3. Catalan数总结

    财产: 前20条目:1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, 9694845, ...

  4. HDU 2414 Chessboard Dance (力模拟)

    主题链接:HDU 2414 Chessboard Dance 意甲冠军:鉴于地图,>,<,^,v的方向,字母相当于是箱子,箱子能够推出边界.人保证不会做出边界.以下输入指令,依照指令走,输 ...

  5. MVC 定义JsonpResult实现跨域请求

    MVC 定义JsonpResult实现跨域请求 1:原理 在js中,XMLHttpRequest是不能请求不同域的数据,但是script标签却可以,所以可以用script标签实现跨域请求.具体是定义一 ...

  6. git fetch, merge, pull, push需要注意的地方(转)

    在git操作中,我们经常会用到fetch, merge, pull和push等命令,以下是一些我们需要注意的地方. 给大家准备了参考资料: 1. Whatʼs a Fast Forward Merge ...

  7. about greenplum collection tool

    three collection tool for greenplum:pstack.strace.gcore.                                            ...

  8. 看德日进,凯文·凯利与Kurzweil老师?

    生命从哪里来.要到那里去.生命存在的意义是什么.这些差点儿是人类可以探究的最深层次问题.基督教给出的答案是毁灭和审判.佛学给出的答案是无常,科学的达尔文进化论给出了生命的起点和进化的过程,对于未来.达 ...

  9. C面试题

    1.sizeof()和strlen()使用? 答案: 1.从功能定义,strlen功能,要查找字符串的长度,sizeof功能是用来寻找指定的变量或变量类型的存储器占用 尺寸: 2.sizeof是运算符 ...

  10. ENode框架初始化

    ENode框架初始化 前言 Conference案例是使用ENode框架来开发的.之前我没有介绍过ENode框架是如何启动的,以及启动时要注意的一些点,估计很多人对ENode框架的初始化这一块感觉很复 ...