基于科大讯飞语音云windows平台开发

本文介绍了一款基于科大讯飞API的语音识别系统的开发过程,包括文字转语音和语音转文字的功能实现。系统使用VS2008 C++/CLR开发,并解决了C++托管与非托管代码间的兼容问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载自:http://blog.youkuaiyun.com/liucheng5037/article/details/31773841?utm_source=tuicool&utm_medium=referral

前记:

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

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

软件运行界面如下图所示:


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

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

看起来很简单的东西折腾了我不少时间啊!!!

系统组成

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

讯飞语音云:

(先复制一段官方说法)

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

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

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

(复制完毕)

由于只想写的玩玩,没有太多时间,故直接把官方C语言写的demo复制过来,转变成一个类。官方提供了一个dll文件一个lib文件还有一堆H文件。具体执行的代码时封装在dll文件里的,我们看不到,我们需要引入lib文件来间接调用语音函数。引入lib的方式如下:

  1. #ifdef_WIN64
  2. #pragmacomment(lib,"../lib/msc_x64.lib")//x64
  3. #else
  4. #pragmacomment(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,用什么控件,只有到处百度,试了各种办法,最后,果然优快云是大神出没的地方,被我找到了,地址如下: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. staticXunFeiSDK*xunfei;
  2. staticSoundRecord^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:refclassSoundType;

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

4、对List之类的对象,可以直接添加任何对象,包括form上的List,比如ComboBox,显示是显示该对象的ToString方法。

TOString方法重载:


  1. virtualSystem::String^ToString()override//重载ToString方法
  2. {
  3. returnvoice;
  4. }

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

部分源代码如下:

  1. //类XunFeiSDK
  2. /*
  3. stringstr("hello");
  4. constchar*strp=str.c_str();string转constchar*
  5. */
  6. //#using"Microsoft.DirectX.DirectSound.dll"
  7. //#using"Microsoft.DirectX.dll"
  8. #include"../SoundTest/stdafx.h"
  9. //#include"stdafx.h"
  10. #include"stdlib.h"
  11. #include"stdio.h"
  12. #include<windows.h>
  13. #include<conio.h>
  14. #include<errno.h>
  15. #include<iostream>
  16. #include<sstream>
  17. #include<fstream>
  18. #include<time.h>
  19. #include<string>
  20. #include<msclr\marshal.h>
  21. usingnamespacestd;
  22. #include"../include/qisr.h"
  23. #include"../include/qtts.h"
  24. #include"../include/msp_cmn.h"
  25. #include"../include/msp_errors.h"
  26. #ifdef_WIN64
  27. #pragmacomment(lib,"../lib/msc_x64.lib")//x64
  28. #else
  29. #pragmacomment(lib,"../lib/msc.lib")//x86
  30. #endif
  31. #defineDebugPrint(str_x,msg_y)fprintf(out_file,(str_x),(msg_y))
  32. typedefintSR_DWORD;
  33. typedefshortintSR_WORD;
  34. //音频头部格式
  35. structwave_pcm_hdr
  36. {
  37. charriff[4];//="RIFF"
  38. SR_DWORDsize_8;//=FileSize-8
  39. charwave[4];//="WAVE"
  40. charfmt[4];//="fmt"
  41. SR_DWORDdwFmtSize;//=下一个结构体的大小:16
  42. SR_WORDformat_tag;//=PCM:1
  43. SR_WORDchannels;//=通道数:1
  44. SR_DWORDsamples_per_sec;//=采样率:8000|6000|11025|16000
  45. SR_DWORDavg_bytes_per_sec;//=每秒字节数:dwSamplesPerSec*wBitsPerSample/8
  46. SR_WORDblock_align;//=每采样点字节数:wBitsPerSample/8
  47. SR_WORDbits_per_sample;//=量化比特数:8|16
  48. chardata[4];//="data";
  49. SR_DWORDdata_size;//=纯数据长度:FileSize-44
  50. };
  51. //默认音频头部数据
  52. conststructwave_pcm_hdrdefault_pcmwavhdr=
  53. {
  54. {'R','I','F','F'},
  55. 0,
  56. {'W','A','V','E'},
  57. {'f','m','t',''},
  58. 16,
  59. 1,
  60. 1,
  61. 16000,
  62. 32000,
  63. 2,
  64. 16,
  65. {'d','a','t','a'},
  66. 0
  67. };
  68. namespaceSoundTest{
  69. usingnamespaceSystem;
  70. usingnamespaceSystem::Runtime::InteropServices;
  71. usingnamespaceSystem::Media;
  72. usingnamespacemsclr::interop;
  73. refclassSoundType;
  74. publicclassXunFeiSDK{
  75. private:FILE*out_file;//输出log文件
  76. stringappid;
  77. intret;
  78. stringpcm_path;//存储音频文件的文件名
  79. stringuser;
  80. stringpassword;
  81. stringvoice_type;//语言类型
  82. stringvolunm;//音量0-10
  83. stringengin;//引擎
  84. stringvoice_speed;//语速-10
  85. public:XunFeiSDK()
  86. {
  87. DateTimenowTime=DateTime::Now;
  88. stringnowTimes=(constchar*)(Marshal::StringToHGlobalAnsi(nowTime.ToString("yyyy-MM-ddHH:mm:ss"))).ToPointer();
  89. fopen_s(&out_file,"log.txt","at+");
  90. if(out_file==NULL)
  91. {
  92. ret=-1;
  93. return;
  94. }
  95. fseek(out_file,0,2);
  96. fprintf(out_file,"beginTime:%s\n",nowTimes.c_str());
  97. appid="";
  98. user="";
  99. password="53954218";//可以上官网注册专属自己的ID
  100. pcm_path="PCM_SPEED.pcm";
  101. voice_type="xiaoyan";
  102. volunm="7";
  103. voice_speed="5";
  104. engin="intp65";
  105. }
  106. ~XunFeiSDK()
  107. {
  108. stringnowTimes=(constchar*)(Marshal::StringToHGlobalAnsi(DateTime::Now.ToString("yyyy-MM-ddHH:mm:ss"))).ToPointer();
  109. fprintf(out_file,"Time:%send\n",nowTimes.c_str());
  110. fclose(out_file);
  111. }
  112. public:intstatus()
  113. {
  114. returnret;
  115. }
  116. boolLogin()//登录
  117. {
  118. stringlogins="appid="+appid+",work_dir=.";
  119. ret=MSPLogin(user.c_str(),password.c_str(),logins.c_str());
  120. if(ret!=MSP_SUCCESS)
  121. {
  122. fprintf(out_file,"MSPLoginfailed,Errorcode%d.\n",ret);
  123. returnfalse;
  124. }
  125. returntrue;
  126. }
  127. voidLogout()
  128. {
  129. MSPLogout();//退出登录
  130. }
  131. intTextToSpeed(System::String^Ssrc_text)//字符串转音频,音频存放在PCM_SPEED.pcm下
  132. {
  133. #pragmaregion字符串转音频
  134. structwave_pcm_hdrpcmwavhdr=default_pcmwavhdr;
  135. constchar*sess_id=NULL;
  136. unsignedinttext_len=0;
  137. char*audio_data=NULL;
  138. unsignedintaudio_len=0;
  139. intsynth_status=MSP_TTS_FLAG_STILL_HAVE_DATA;
  140. FILE*fp=NULL;
  141. stringparams="vcn=xiaoyan,spd=50,vol=50";//参数可参考可设置参数列表
  142. ret=-1;//失败
  143. //参数配置
  144. params="vcn="+voice_type+",spd="+voice_speed+",vol="+volunm+",ent="+engin;
  145. constchar*src_text=(constchar*)(Marshal::StringToHGlobalAnsi(Ssrc_text)).ToPointer();
  146. pcm_path="PCM_SPEED.pcm";
  147. fprintf(out_file,"begintosynthsource=%s\n",src_text);
  148. if(NULL==src_text)
  149. {
  150. fprintf(out_file,"paramsisnull!\n");
  151. returnret;
  152. }
  153. text_len=strlen(src_text);//获取文本长度
  154. fopen_s(&fp,pcm_path.c_str(),"wb");//打开PCM文件
  155. if(NULL==fp)
  156. {
  157. fprintf(out_file,"openPCMfile%serror\n",pcm_path);
  158. returnret;
  159. }
  160. sess_id=QTTSSessionBegin(params.c_str(),&ret);//开始一个会话
  161. if(ret!=MSP_SUCCESS)
  162. {
  163. fprintf(out_file,"QTTSSessionBegin:qttsbeginsessionfailedErrorcode%d.\n",ret);
  164. returnret;
  165. }
  166. fprintf(out_file,"sess_id=%s\n",sess_id);
  167. ret=QTTSTextPut(sess_id,src_text,text_len,NULL);//发送txt信息
  168. if(ret!=MSP_SUCCESS)
  169. {
  170. fprintf(out_file,"QTTSTextPut:qttsputtextfailedErrorcode%d.\n",ret);
  171. QTTSSessionEnd(sess_id,"TextPutError");//异常,结束
  172. returnret;
  173. }
  174. fwrite(&pcmwavhdr,sizeof(pcmwavhdr),1,fp);//把开始文件写到最前面
  175. while(1)//循环读取音频文件并存储
  176. {
  177. constvoid*data=QTTSAudioGet(sess_id,&audio_len,&synth_status,&ret);
  178. if(NULL!=data)
  179. {
  180. fwrite(data,audio_len,1,fp);
  181. pcmwavhdr.data_size+=audio_len;//修正pcm数据的大小
  182. }
  183. if(synth_status==MSP_TTS_FLAG_DATA_END||ret!=0)
  184. break;
  185. }//合成状态synth_status取值可参考开发文档
  186. //修正pcm文件头数据的大小
  187. pcmwavhdr.size_8+=pcmwavhdr.data_size+36;
  188. //将修正过的数据写回文件头部
  189. fseek(fp,4,0);
  190. fwrite(&pcmwavhdr.size_8,sizeof(pcmwavhdr.size_8),1,fp);
  191. fseek(fp,40,0);
  192. fwrite(&pcmwavhdr.data_size,sizeof(pcmwavhdr.data_size),1,fp);
  193. fclose(fp);
  194. ret=QTTSSessionEnd(sess_id,NULL);
  195. if(ret!=MSP_SUCCESS)
  196. {
  197. fprintf(out_file,"QTTSSessionEnd:qttsendfailedErrorcode%d.\n",ret);
  198. }
  199. fprintf(out_file,"programend");
  200. returnret;
  201. #pragmaendregion
  202. }
  203. System::String^GetPcmName()//获取音频文件路径
  204. {
  205. returngcnewString(pcm_path.c_str());
  206. }
  207. intPlay(System::String^text)//播放音频文件
  208. {
  209. if(text=="")return-1;
  210. SoundPlayer^player=(gcnewSoundPlayer(text));//音频播放器
  211. player->SoundLocation=text;
  212. player->Load();
  213. player->Play();
  214. return0;
  215. }
  216. intStartRecord()//开始录音
  217. {
  218. }
  219. intEndRecord()//结束录音
  220. {
  221. }
  222. System::String^SpeedToText(System::String^text)//语音转文字,输入语音文件名,返回文字信息
  223. {
  224. System::String^Sys_value="Nodatareturn";
  225. constchar*src_wav_filename=(constchar*)(Marshal::StringToHGlobalAnsi(text)).ToPointer();
  226. //test=Marshal::PtrToStringAnsi((IntPtr)(char*)src_text);
  227. //returntest;
  228. charrec_result[1024]={0};//存放返回结果
  229. constchar*sessionID=NULL;
  230. FILE*f_pcm=NULL;//
  231. char*pPCM=NULL;//存放音频文件缓存
  232. intlastAudio=0;
  233. intaudStat=MSP_AUDIO_SAMPLE_CONTINUE;
  234. intepStatus=MSP_EP_LOOKING_FOR_SPEECH;
  235. intrecStatus=MSP_REC_STATUS_SUCCESS;
  236. longpcmCount=0;
  237. longpcmSize=0;//音频文件大小
  238. interrCode=10;
  239. stringparam="sub=iat,auf=audio/L16;rate=16000,aue=speex-wb,ent=sms16k,rst=plain,rse=gb2312";
  240. fprintf(out_file,"Startiat...\n");
  241. sessionID=QISRSessionBegin(NULL,param.c_str(),&errCode);//开始一路会话
  242. fopen_s(&f_pcm,src_wav_filename,"rb");
  243. if(NULL!=f_pcm){
  244. fseek(f_pcm,0,SEEK_END);
  245. pcmSize=ftell(f_pcm);//获取音频大小
  246. fseek(f_pcm,0,SEEK_SET);
  247. pPCM=(char*)malloc(pcmSize);//分配内存存放音频
  248. fread((void*)pPCM,pcmSize,1,f_pcm);
  249. fclose(f_pcm);
  250. f_pcm=NULL;
  251. }//读取音频文件,读到pPCM中
  252. else
  253. {
  254. fprintf(out_file,"media%snotfound\n",src_wav_filename);
  255. returnSys_value;
  256. }
  257. while(1){//开始往服务器写音频数据
  258. unsignedintlen=6400;
  259. intret=0;
  260. if(pcmSize<12800){
  261. len=pcmSize;
  262. lastAudio=1;//音频长度小于
  263. }
  264. audStat=MSP_AUDIO_SAMPLE_CONTINUE;//有后继音频
  265. if(pcmCount==0)
  266. audStat=MSP_AUDIO_SAMPLE_FIRST;
  267. if(len<=0)
  268. {
  269. break;
  270. }
  271. fprintf(out_file,"csid=%s,count=%d,aus=%d,",sessionID,pcmCount/len,audStat);
  272. ret=QISRAudioWrite(sessionID,(constvoid*)&pPCM[pcmCount],len,audStat,&epStatus,&recStatus);//写音频
  273. fprintf(out_file,"eps=%d,rss=%d,ret=%d\n",epStatus,recStatus,errCode);
  274. if(ret!=0)
  275. break;
  276. pcmCount+=(long)len;
  277. pcmSize-=(long)len;
  278. if(recStatus==MSP_REC_STATUS_SUCCESS){
  279. constchar*rslt=QISRGetResult(sessionID,&recStatus,0,&errCode);//服务端已经有识别结果,可以获取
  280. fprintf(out_file,"csid=%s,rss=%d,ret=%d\n",sessionID,recStatus,errCode);
  281. if(NULL!=rslt)
  282. strcat_s(rec_result,rslt);
  283. }
  284. if(epStatus==MSP_EP_AFTER_SPEECH)
  285. break;
  286. Sleep(150);//模拟人说话时间间隙
  287. }
  288. QISRAudioWrite(sessionID,(constvoid*)NULL,0,MSP_AUDIO_SAMPLE_LAST,&epStatus,&recStatus);//写入结束
  289. free(pPCM);
  290. pPCM=NULL;
  291. while(recStatus!=MSP_REC_STATUS_COMPLETE&&0==errCode){
  292. constchar*rslt=QISRGetResult(sessionID,&recStatus,0,&errCode);//获取结果
  293. fprintf(out_file,"csid=%s,rss=%d,ret=%d\n",sessionID,recStatus,errCode);
  294. if(NULL!=rslt)
  295. {
  296. strcat_s(rec_result,rslt);
  297. }
  298. Sleep(150);
  299. }
  300. QISRSessionEnd(sessionID,NULL);
  301. fprintf(out_file,"Theresultis:%s\n",rec_result);
  302. if(NULL!=rec_result)//不为空时返回正确值
  303. Sys_value=Marshal::PtrToStringAnsi((IntPtr)rec_result);//数值转换
  304. returnSys_value;
  305. }
  306. voidset_tts_params(System::String^e_voice_type,System::String^e_engin,inte_volunm,inte_speed)
  307. {
  308. constchar*src_text=(constchar*)(Marshal::StringToHGlobalAnsi(e_voice_type)).ToPointer();
  309. voice_type=src_text;
  310. src_text=(constchar*)(Marshal::StringToHGlobalAnsi(e_engin)).ToPointer();
  311. engin=src_text;
  312. ostringstreamoss1;
  313. ostringstreamoss2;
  314. oss1<<e_volunm;
  315. volunm=oss1.str();//音量
  316. oss2<<e_speed;
  317. voice_speed=oss2.str();//语速
  318. }
  319. };
  320. publicrefclassSoundType{
  321. public:System::String^engin;//语音引擎
  322. System::String^voice_type;//说话类型
  323. System::String^voice;//显示
  324. SoundType(System::String^e_voice)//switchcase不支持string的输入
  325. {
  326. voice=e_voice;
  327. if(e_voice=="普通话女声"){engin="intp65";voice_type="xiaoyan";}
  328. elseif(e_voice=="普通话男声"){engin="intp65";voice_type="xiaoyu";}
  329. elseif(e_voice=="英文女声"){engin="intp65_en";voice_type="Catherine";}
  330. elseif(e_voice=="英文男声"){engin="intp65_en";voice_type="henry";}
  331. elseif(e_voice=="粤语"){engin="vivi21";voice_type="vixm";}
  332. elseif(e_voice=="台湾话"){engin="vivi21";voice_type="vixl";}
  333. elseif(e_voice=="四川话"){engin="vivi21";voice_type="vixr";}
  334. elseif(e_voice=="东北话"){engin="vivi21";voice_type="vixyun";}
  335. else{engin="intp65";voice_type="xiaoyan";voice="普通话女声";}
  336. }
  337. SoundType()
  338. {
  339. engin="intp65";voice_type="xiaoyan";voice="普通话女声";
  340. }
  341. virtualSystem::String^ToString()override//重载ToString方法
  342. {
  343. returnvoice;
  344. }
  345. };
  346. }


FORM类:

局部变量:

  1. private:staticXunFeiSDK*xunfei;
  2. private:Thread^xunfei_thread;
  3. staticintend_flag;
  4. staticString^end_result;
  5. ArrayList^voice_types;
  6. private:staticSoundRecord^recorder;

  1. #pragmaregion控件触发函数
  2. private:System::VoidForm1_Load(System::Object^sender,System::EventArgs^e){
  3. xunfei=(newXunFeiSDK());
  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::VoidForm1_FormClosing(System::Object^sender,System::Windows::Forms::FormClosingEventArgs^e){
  21. xunfei->Logout();//登出
  22. deletexunfei;//必须释放才会调用析构函数
  23. deleterecorder;
  24. }
  25. private:System::Voidplay_tts_btn_Click(System::Object^sender,System::EventArgs^e){
  26. //tts_status_lab->Text="先转换,再播放语音";
  27. set_xunfei_param();//参数设置
  28. if(-1==xunfei->TextToSpeed(txt_speak->Text))
  29. {
  30. MessageBox::Show("转换失败");
  31. }
  32. else
  33. {
  34. xunfei->Play(xunfei->GetPcmName());
  35. }
  36. }
  37. private:System::Voidspeak_btn_MouseDown(System::Object^sender,System::Windows::Forms::MouseEventArgs^e){
  38. StartRecord();//开始录音线程
  39. status_lab->Text="录音中.....";
  40. }
  41. private:System::Voidspeak_btn_MouseUp(System::Object^sender,System::Windows::Forms::MouseEventArgs^e){
  42. status_lab->Text="结束录音,转换中...";
  43. xunfei_thread=(gcnewThread(gcnewThreadStart(EndRecord)));
  44. xunfei_thread->Start();
  45. }
  46. private:System::Voidtimer1_Tick(System::Object^sender,System::EventArgs^e){
  47. if(1==end_flag)
  48. {
  49. end_flag=0;
  50. result_box->Text=end_result;
  51. status_lab->Text="转换结束";
  52. }
  53. }
  54. private:System::Voidvolunm_bar_Scroll(System::Object^sender,System::EventArgs^e){
  55. volunm_lab->Text="音量"+volunm_bar->Value;
  56. }
  57. private:System::Voidspeed_bar_Scroll(System::Object^sender,System::EventArgs^e){
  58. speed_lab->Text="速度"+speed_bar->Value;
  59. }
  60. #pragmaendregion
  61. #pragmaregion自定义函数
  62. private:voidset_xunfei_param()//讯飞语音参数设置
  63. {
  64. SoundType^sound_type;
  65. sound_type=(SoundType^)(voice_type->SelectedItem);//获取选中的对象
  66. xunfei->set_tts_params(sound_type->voice_type,sound_type->engin,volunm_bar->Value,speed_bar->Value);
  67. }
  68. private:staticvoidStartRecord()
  69. {
  70. recorder=(gcnewSoundRecord());
  71. recorder->SetFileName("record.wav");
  72. recorder->RecStart();//开始录音
  73. }
  74. private:staticvoidEndRecord()
  75. {
  76. //Stringtext;
  77. recorder->RecStop();
  78. deleterecorder;
  79. end_result=xunfei->SpeedToText("record.wav");//录音结束,显示语音转换结果
  80. end_flag=1;
  81. }
  82. #pragmaendregion


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值