语音邮件控件的实现

Android添加语音交互 阅读详情
导读:
  最近做了一个邮件项目,其中涉及语音的部分,在网上查了很多资料,把其中遇到的一些问题写下来。想必可以对后来人有所帮助。 在网上做语音邮件,不外乎这样的几件事情:录音、回放、压缩、编码传输。
  录音是把语音通过录音设备进行PCM编码调制变成二进制数据放至内存,在录音停止后,应该可以通过回放来检查录音的效果。录音可以调用WINDOWS API来实现,windows系统中自带的录音机就是通过这种方法的。
  
  录音完的数据是否就可以直接用了呢? 当然不是,录音机一分钟通过PCM编码调制录下的数据大概有1M左右,这个数据量对于带宽有限的网络传输是无法接受的,所以还必须对原有的PCM格式数据进行压缩,windows系统中一般自带有许多种压缩算法,但有一种叫做DSP Group TrueSPeech(TM)的压缩算法的压缩比非常高(大概可以达到15:1左右,而且基本不失真,据说这是针对人的语音的特别压缩,它丢弃了一般人的声音不可以达到的频段的数据).
  
  在进行压缩以后,是否这些二进制数据就可以用了?如果是语音聊天,通过socket的方式传输,应该是可以了,但是对于语音邮件,需要以网页(post或者get)的方式传输数据到服务器端去,还必须对这些二进制数据进行编码,最常用的方式当然是base64编码,这一举两得,不仅使得编码后的数据可以直接传输,而且如果语音数据是作为附件的形式存放在服务器端的,则服务器端就省去了解码和重新编码的工作。
  
  至此为止,整个语音邮件要做的事情就全部做完了,下面就具体来介绍一下主要实现代码。
  
  一 录音部分
  
  录音处理函数:StarRec
  
  //分配录音缓存空间
  pBuffer1=(PBYTE)malloc(INP_BUFFER_SIZE);
  pBuffer2=(PBYTE)malloc(INP_BUFFER_SIZE);
  if (!pBuffer1 || !pBuffer2) {
  if (pBuffer1) free(pBuffer1);
  if (pBuffer2) free(pBuffer2);
  MessageBeep(MB_ICONEXCLAMATION);
  MessageBox("Memory erro!");
  return ;
  }
  
  //设置录音的格式
  waveform.wFormatTag=WAVE_FORMAT_PCM;
  waveform.nChannels=1;
  waveform.nSamplesPerSec= 8000;
  waveform.wBitsPerSample= 16;
  waveform.nBlockAlign= waveform.wBitsPerSample/8;
  waveform.nAvgBytesPerSec= waveform.nSamplesPerSec*waveform.nBlockAlign;
  waveform.cbSize=0;
  
  //打开录音设备
  if (waveInOpen(&hWaveIn,WAVE_MAPPER,&waveform,(DWORD)this->m_hWnd,NULL,CALLBACK_WINDOW)) {
  free(pBuffer1);
  free(pBuffer2);
  MessageBeep(MB_ICONEXCLAMATION);
  MessageBox("Audio can not be open!");
  }
  
  //为录音设备准备缓存,最好准备两个缓存,否则在缓存满时来不及清除切换可能会导致录音失真
  pWaveHdr1->lpData=(LPTSTR)pBuffer1;
  pWaveHdr1->dwBufferLength=INP_BUFFER_SIZE;
  pWaveHdr1->dwBytesRecorded=0;
  pWaveHdr1->dwUser=0;
  pWaveHdr1->dwFlags=0;
  pWaveHdr1->dwLoops=1;
  pWaveHdr1->lpNext=NULL;
  pWaveHdr1->reserved=0;
  waveInPrepareHeader(hWaveIn,pWaveHdr1,sizeof(WAVEHDR));
  pWaveHdr2->lpData=(LPTSTR)pBuffer2;
  pWaveHdr2->dwBufferLength=INP_BUFFER_SIZE;
  pWaveHdr2->dwBytesRecorded=0;
  pWaveHdr2->dwUser=0;
  pWaveHdr2->dwFlags=0;
  pWaveHdr2->dwLoops=1;
  pWaveHdr2->lpNext=NULL;
  pWaveHdr2->reserved=0;
  waveInPrepareHeader(hWaveIn,pWaveHdr2,sizeof(WAVEHDR));
  
  //为录音设备增加缓存
  waveInAddBuffer (hWaveIn, pWaveHdr1, sizeof (WAVEHDR)) ;
  waveInAddBuffer (hWaveIn, pWaveHdr2, sizeof (WAVEHDR)) ;
  
  //开始录音
  rState = RECORDING_STATE;
  waveInStart (hWaveIn);
  
  相关消息1:MM_WIM_DATA
  工作:当缓存已满或者停止录音时的消息,处理这个消息可以对缓存进行重新分配,实现不限长度录音
  消息处理函数: OnMM_WIM_DATA
  // 重新分配缓存
  pNewBuffer = (PBYTE)realloc (pSaveBuffer, dwDataLength +
  ((PWAVEHDR) lParam)->dwBytesRecorded) ;
  
  if (pNewBuffer == NULL)
  {
  waveInClose (hWaveIn) ;
  MessageBeep (MB_ICONEXCLAMATION) ;
  MessageBox("erro memory");
  return ;
  }
  
  pSaveBuffer = pNewBuffer ;
  
  // 拷贝刚录制的缓存中的内容进入保存数据区,dwDataLength为数据区中已有内容
  CopyMemory (pSaveBuffer + dwDataLength, ((PWAVEHDR) lParam)->lpData,
  ((PWAVEHDR) lParam)->dwBytesRecorded) ;
  
  dwDataLength += ((PWAVEHDR) lParam)->dwBytesRecorded ;
  
  if (stopRecByHand || timeOut) //stop record by yourselve
  {
  waveInClose (hWaveIn) ;
  return ;
  }
  //重新加入新的缓存
  waveInAddBuffer (hWaveIn, (PWAVEHDR) lParam, sizeof (WAVEHDR)) ;
  return ;
  
  相关消息2:MM_WIM_CLOSE
  工作:调用waveInReset后停止录音,当手动停止录音或者最长录音时间已到则调用该函数
  消息处理函数:OnMM_WIM_CLOSE
  KillTimer(1);
  if (0==dwDataLength) {
  return;
  }
  waveInUnprepareHeader (hWaveIn, pWaveHdr1, sizeof (WAVEHDR)) ;
  waveInUnprepareHeader (hWaveIn, pWaveHdr2, sizeof (WAVEHDR)) ;
  free (pBuffer1) ;
  free (pBuffer2) ;
  rState= RECORD_PLAY_STOPED;
  if (timeOut){
  char recordinfo[30];
  sprintf(recordinfo,"录音达到最长时限%d秒,已经终止!",m_maxTimeLength);
  MessageBox(recordinfo);
  }else{
  //MessageBox("录音结束!");
  }
  return ;
  
  二 回放部分
  回放处理函数:StartPlay
  
  if (rState==PLAYING_STATE || rState==RECORDING_STATE || rState==NO_RECORDING_STATE) {
  return;
  }
  //设置回放的格式
  waveform.wFormatTag=WAVE_FORMAT_PCM;
  waveform.nChannels=1;
  waveform.nSamplesPerSec= 8000;
  waveform.wBitsPerSample= 16;
  waveform.nBlockAlign= waveform.wBitsPerSample/8;
  waveform.nAvgBytesPerSec= waveform.nSamplesPerSec*waveform.nBlockAlign;
  waveform.cbSize=0;
  
  //打开回放设备
  if (waveOutOpen(&hWaveOut,WAVE_MAPPER,&waveform,(DWORD)this->m_hWnd,NULL,CALLBACK_WINDOW)) {
  MessageBeep(MB_ICONEXCLAMATION);
  MessageBox("Audio output erro");
  }
  return ;
  
  相关消息1:MM_WOM_OPEN
  工作:准备并开始回放
  消息处理函数:OnMM_WIM_CLOSE
  //准备回放
  pWaveHdr1->lpData = (LPTSTR)pSaveBuffer ;
  pWaveHdr1->dwBufferLength = dwDataLength ;
  pWaveHdr1->dwBytesRecorded = 0 ;
  pWaveHdr1->dwUser = 0 ;
  pWaveHdr1->dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP ;
  pWaveHdr1->dwLoops = dwRepetitions ;
  pWaveHdr1->lpNext = NULL ;
  pWaveHdr1->reserved = 0 ;
  waveOutPrepareHeader (hWaveOut, pWaveHdr1, sizeof (WAVEHDR)) ;
  
  //回放开始
  waveOutWrite (hWaveOut, pWaveHdr1, sizeof (WAVEHDR)) ;
  rState = PLAYING_STATE;
  二 压缩部分
  压缩转换处理函数:Convert
  //寻找DSPGROUP_TRUESPEECH驱动
  if (rState!=RECORD_PLAY_STOPED) return;
  convertState = false;
  findsuccess=0;
  WORD wformattag = WAVE_FORMAT_DSPGROUP_TRUESPEECH;
  HACMDRIVERID hadid = find_driver(wformattag);
  if (!(findsuccess &&hadid)) {
  MessageBox("找不到DSPGROUP驱动");
  return;
  }
  
  //打开DISP驱动
  HACMDRIVER had = NULL;
  MMRESULT mmr = acmDriverOpen(&had, hadid, 0);
  if (mmr)
  {
  MessageBox("open driver error!");
  return;
  }
  
  //准备打开流
  WAVEFORMATEX *pwfSrc = get_driver_format(hadid,WAVE_FORMAT_PCM);
  WAVEFORMATEX *pwfDrv= get_driver_format(hadid,wformattag);
  pwaveformdsp = get_driver_format(hadid,wformattag);
  
  //根据源和目标的格式创建转换流
  HACMSTREAM hstr = NULL;
  mmr = acmStreamOpen(&hstr,had, pwfSrc, pwfDrv, NULL, NULL, 0, ACM_STREAMOPENF_NONREALTIME);
  if (mmr) {
  MessageBox("can't open");
  return;
  }
  //分配目标数据
  DWORD dwDstBytes=pwfDrv->nAvgBytesPerSec*dwSrcSamples/pwfSrc->nSamplesPerSec;
  dwDstSamples = dwSrcSamples;
  dwDstBytes = dwDstBytes*3/2;
  DWORD fileBytes = dwDstBytes+12+58+12+8; //fileBytes equal dwBstBytes add head size
  pSaveConvertData = new BYTE[fileBytes];
  BYTE* pDstData = pSaveConvertData+12+58+12+8;//这是根据压缩格式算出来的
  //创建转换流的头
  ACMSTREAMHEADER shdr;
  memset(&shdr, 0, sizeof(shdr));
  shdr.cbStruct = sizeof(shdr);
  shdr.pbSrc = pSaveBuffer; //original data area
  shdr.cbSrcLength = dwDataLength;
  shdr.pbDst = pDstData;
  shdr.cbDstLength = dwDstBytes; ////dst data area
  //安装转换流的头
  mmr = acmStreamPrepareHeader(hstr, &shdr, 0);
  if (mmr) {
  MessageBox("error create covert header!");
  return;
  }
  //转换
  mmr = acmStreamConvert(hstr, &shdr, 0);
  if (mmr) {
  MessageBox("error convert!");
  return;
  }
  
  //卸载转换流头
  mmr = acmStreamUnprepareHeader(hstr, &shdr, 0);
  if (mmr) {
  MessageBox("error unprepareheader!");
  return;
  }
  
  //关闭转换流
  mmr = acmStreamClose(hstr,0);
  if (mmr) {
  MessageBox("error close");
  return;
  }
  //关闭DISP驱动
  mmr = acmDriverClose(had, 0);
  if (mmr) {
  MessageBox("error close had!");
  return;
  }
  
  //创建DISP数据的WAVE格式数据
  //convert datalength
  convertDataLength = shdr.cbDstLengthUsed+12+58+12+8;
  //write header
  //RIFF head area
  BYTE* pstr= pSaveConvertData;
  DWORD dwNumber = FCC("RIFF");
  memcpy(pstr,&dwNumber,4);
  pstr=pstr+4;
  //RIFF size area
  dwNumber = convertDataLength-8; //the filelength sub RIFF header and size
  memcpy(pstr,&dwNumber,4);
  pstr=pstr+4;
  //RIFF TYPE area
  dwNumber = FCC("WAVE");
  memcpy(pstr,&dwNumber,4);
  pstr=pstr+4;
  //fmt head area
  dwNumber = FCC("fmt ");
  memcpy(pstr, &dwNumber, 4);
  pstr=pstr+4;
  //fmt size area
  dwNumber = 50L;
  memcpy(pstr, &dwNumber,4);
  pstr=pstr+4;
  //fmt format
  memcpy(pstr, pwaveformdsp, dwNumber);
  pstr=pstr+dwNumber;
  //fact head area
  dwNumber = FCC("fact");
  memcpy(pstr, &dwNumber, 4);
  pstr=pstr+4;
  //fact data size
  dwNumber = 4L;
  memcpy(pstr, &dwNumber, 4);
  pstr=pstr+4;
  //fact data area -samples
  dwNumber = dwDstSamples;
  memcpy(pstr, &dwNumber, 4);
  pstr=pstr+4;
  //data head area
  dwNumber = FCC("data");
  memcpy(pstr, &dwNumber, 4);
  pstr=pstr+4;
  //data length area
  dwNumber = convertDataLength-90;
  memcpy(pstr, &dwNumber, 4);
  pstr=pstr+4;
  convertState = true;
  canGetData = true;
  return;
  三 编码部分
  得到编码函数:GetData
  if (rState!=RECORD_PLAY_STOPED || !convertState) return NULL;
  if (canGetData) //转换成功了,可以直接编码返回数据
  {
  Coder.Encode(pSaveConvertData,convertDataLength);
  LPCTSTR encodedmsg = (LPCTSTR)Coder.EncodedMessage();//对二进制数据进行base64编码
  BSTR base64msg=GetBSTR(encodedmsg);//非常重要,实现char * to bstr的转换
  return base64msg;
  }
  Convert();
  if (convertState)
  {
  Coder.Encode(pSaveConvertData,convertDataLength);
  LPCTSTR encodedmsg = (LPCTSTR)Coder.EncodedMessage();//对二进制数据进行base64编码
  BSTR base64msg=GetBSTR(encodedmsg);//非常重要,实现char * to bstr的转换
  return base64msg;
  }else
  {
  MessageBox("转换录音数据过程中发生错误!");
  return NULL;
  }
  
  如果您是学习之用,有充裕的时间,参考上面的代码再结合MSDN,相信您一定可以写出更灵活的代码。
  如果你时间较紧,需要现成的语音邮件控件,不妨联系我,只要花费20元便可以得到。
  如果你需要完整的源代码和参考资料,也可以联系我,只要50元左右。
  如果你需要定制语音控件之类的东西,同样可以联系我,价格面议。
  所有的这些都是一些成本费,毕竟也是花了很多时间开发的,也相信一定可以给你的开发节省许多宝贵的时间。
  
  联系电话 13852946750 或者QQ联系 15236281
 
本文转自
http://blog.youkuaiyun.com/cz_hyf/archive/2006/08/27/1127419.aspx
PC端语音识别简介 语音识别:        语音识别技术就是让机器通过识别和理解过程把语音信号转变为相应的文本或命令的高技术。它主要包括特征提取技术、模式匹配准则及模型训练技术三个方面。语音识别区别于声纹识别,后者尝试识别或确认发出语音的说话人而非其中所包含的词汇内容。语音识别技术的发展可参考http://baike.baidu.com/view/652891.htm。        以下主要介绍PC端 阅读详情

相关推荐

MFC验证码控件使用与实现指南

MFC(Microsoft Foundation Classes)是一个用于构建Windows应用程序的C++库,由微软推出,目的在于简化Windows API的复杂性。它的设计利用了面向对象编程的原则,通过封装大量Windows API函数,提供了一组丰富的C++类。MFC框架以文档/视图结构(Document/View Architecture)为核心,将程序分为几个主要部分:应用框架、视图类、文档类。这种结构使得MFC程序能够轻松处理数据和数据显示。

weixin_42668301的博客 546

轻松发送语音邮件

轻松发送语音邮件 作者:阎皓 现在比较流行语音邮件,跟传统邮件相比,语音邮件更容易向好友表达清楚来意。但是具有语音邮件的电子邮箱不是很多,如何在不提供语音邮件的电子邮件中加入语音邮件呢?最常用的方法是先将声音进行录制,然后通过附件的形式发送,这样不是很方便。如果想给朋友发语音邮件,那么不妨去Vocaroo网站看看,在这个网站中可以发送语音邮件,而无需邮箱具备这个功能。 先登录Vo...

编程开发资料库 403

Delphi环境下的CTI语音系统开发实战

计算机电话集成(Computer Telephony Integration,CTI)技术是将传统电话系统与计算机系统结合,实现数据和语音的双向传输和交互的技术。其核心是通过集成方式,实现电话与计算机系统的高效协同工作,以增强客户服务质量,提高企业工作效率,是呼叫中心、客户服务等业务中的重要支撑技术。Delphi,由Embarcadero Technologies公司开发,是一款功能强大的集成开发环境(IDE),用于创建跨平台应用程序。

weixin_35509395的博客 878

android+邮箱删除邮件,在Android上删除烦人的语音邮件通知 | MOS86

即使您取消了语音信箱,手机仍会说您有新的语音信箱吗? 此快速修复解决了该问题。Android具有常规功能,可在新语音邮件到达时提醒用户,但并非没有怪癖。 即使没有语音邮件,有时也会显示通知。 有时它的出现只是因为语音邮件未被服务提供商标记为已读。 在某些Android智能手机上,您可以关闭该图标,而只能听到在下次电话重启/关机时语音邮件正在等您的声音提示。 如果您厌倦了此通知,这是摆脱它的快速技巧...

weixin_42365401的博客 4214

ASP.NET验证码控件实现与应用演示

验证码(Completely Automated Public Turing test to tell Computers and Humans Apart)是一种广泛应用于Web应用中的安全机制,用于区分人类用户和自动化程序(通常被称为机器人或爬虫)。它的核心思想是通过一个用户易于通过但自动脚本难以解决的测试来实现身份验证。最常见的验证码形式包括文本验证码、图像验证码等。

weixin_42173218的博客 1825

C#项目中FreeTextBox与验证码控件的应用实践

本文还有配套的精品资源,点击获取 简介:C#作为.NET框架中的一种广泛使用的编程语言,其第三方控件极大地扩展了开发能力。本文重点介绍了FreeTextBox这一富文本编辑器控件和验证码控件。FreeTextBox提供了类似Word的文本编辑体验,支持多种文本格式和插件扩展,同时注重安全防护,如防止XSS攻击。而验证码控件则是Web开发中的安全组件,包括图像、滑动、声音和行...

weixin_42527589的博客 1586

Android7.0 Voicemail (1) Voicemail的下载流程

今天接到一个任务,需要解决同事在美国测试Voicemail功能时,出现的下载失败问题。目前,国内的运营商似乎没有支持Voicemail功能,因此资料相对较少。自己以前对这块流程也不太熟悉,没有解决过相应的bug。 不得已,只好根据同事提供的截图,从界面开始一步一步分析整个Voicemail的下载流程。

橡果生长记的博客 6703

实验四 基于IDEA+SpringBoot+Maven+Thymeleaf的系统实现实验目的

通过这次实验,我学习了如何成功进行IDEA+SpringBoot+maven的系统实现,搭建好IDEA+SpringBoot+maven的系统环境,成功地安装并配置了maven的运行环境,学会了创建springboot的三种方式,并且能将之前的实验结合起来运用。pom.xml中引入thymeleaf依赖,在classpath:/templates/下新建HTML页面(可采用实验一创建的页面),新建controller进行测试,访问页面后返回success成功数据。同时掌握和thymeleaf的基本语法。

m0_73502929的博客 1380

语音报警系统说明

本语音报警系统基于自研OCX控件基础上二次开发,基本实现了语音实时报警,报表数据记录,以及邮件提醒(微信小程序提示)功能。 1.语音实时报警 本功能是该语音报警系统最重要的实现功能。该功能主要实现对工艺生产数据超标,设备故障等生产问题实现实时语音报警提示,真正实现了对生产工艺的智能化监控管理。 功能效果如图: 2.报表数据记录 报表数据记录功能是语音报警系统的基础,它能...

cash.yuan 3699

告别CAPL编程!用Matlab/Simulink+CANoe实现复杂ECU仿真的5个技巧

本文介绍了如何利用Matlab/Simulink与CANoe进行联合仿真,以替代复杂的CAPL编程,高效实现复杂ECU仿真。文章分享了5个核心技巧,涵盖信号映射、模型编译集成、实时参数调整、性能优化及数据分析,帮助算法工程师构建稳定强大的仿真环境,显著提升开发与测试效率。

rgv234567的博客 296

open-mmlab / mmpose安装、使用教程

mmpose安装、使用教程mmpose安装教程1. 安装mmcv-full2. 安装MMPose2. 安装mmdet使用教程1. 预测图片2. 预测视频 mmpose mmpose是商汤旗下有又一款好用的工具箱,主要是针对姿态识别任务开发的,包括人体姿态识别和动物姿态识别。里面继承很多现成的网络可以供大家使用,并且提供了训练好的权重。用户可以更具自己的需求训练自己的数据,或者直接应用他们的结果,反正就是很全面啦!!!! github连接:https://github.com/open-mmlab/mmpos

CharmsLUO的博客 1万+

h5邮件的邮箱 支持_人工智能应用:邮件系统的语音识别

人工智能是目前火得不能再火的话题。无论什么系统,与 AI 扯上关系就是"最先进的"生产力。笔者主要从事协作领域的工作,协作领域有很多 AI 的应用场景,例如智能会议系统可以自动做会议纪要(不只是语音识别哦)。在本文中,笔者考虑把 AI 集成到邮件系统中,做一个智能的语音邮件查询功能。主要应用场景是在用户不方便输入文字时,对邮件进行快速查询。要实现语音查询,我们需做到以下几点:语音录音与上...

weixin_35070925的博客 499

通过Scrapy爬虫抓取Deep Learning领域的论文数据

然而,大部分高质量的deep learning研究论文都是通过国际顶尖学术会议(如neurips、iclr、icml等)发表的,而这些论文的获取难度较大。在本文中,我们选择抓取arXiv的数据。arXiv是一个管理科学论文的网站,其中包括了许多领域的论文,也包括了Deep Learning领域的论文。同时,arXiv网站还提供了方便的API接口,使得我们的爬虫程序可以很方便地获取论文数据。通过结合其他的数据处理技术,我们可以对这些数据进行更深入的研究和分析,从而推动Deep Learning领域的发展。

Ob2024的博客 609

ABTO VoIP SIP SDK 电话语音控件

ABTO VoIP SIP SDK 电话语音控件 适用于Windows的ABTO软件VoIP SIP SDK提供了构建自定义SIP软电话的功能,支持多线路语音/视频通话和视频会议,IM聊天,多个SIP帐户,状态和语音邮件,或将VoIP功能添加到自定义IVR / 对讲机/ CRM软件。 ...

控件与插件之大全 1174

课设报告-超市收银系统 javaweb(附源代码)

超市收银系统由收银员输入顾客的会员卡卡号(若有卡),所购买的货号。从数据库中取出有关价格信息,在把这些信息返回给收银台,同时把收银台的销售总量和有关种类商品的剩余量以及该持卡顾客的消费情况交数据库存储以供查询。另外,对没有卡的消费不记录该顾客的消费情况扥个人信息,如果一个未持卡顾客一次购买满200元,可围棋发放一张会员卡,以后在该商场购物可享受9折优惠。

m0_71106830的博客 2975

Oracle数据库安装及配置(Oracle19c)

Windows 10安装Oracle 19c教程

weixin_69200200的博客 2万+

iOS 语音技术

http://open.voicecloud.cn/developer.php 您好,欢迎来到语音云开放平台! 请登录 免费注册 科大讯飞 | 语音云官方网站 |  其他产品 首页平台介绍在线演示开发者专区下载专区应用推荐语音通行证论坛 首页 > 开发者专区 新手指引· 如何注册账号· 如何申请Ap

The Life with iOS 1162

小红书x-mini签名逆向实战:Frida动态Hook与算法还原

在移动App协议分析中,请求签名机制是保障接口安全的核心技术,其本质是客户端对请求参数、时间戳、设备指纹等要素进行加密认证的过程。理解签名原理需掌握Native层加密流程、JNI调用机制及密钥动态派生逻辑。Frida作为主流动态插桩工具,能绕过符号剥离、字符串加密和控制流混淆等反分析手段,在函数执行瞬间捕获寄存器状态、内存数据与调用上下文,实现签名算法的完整还原。该技术广泛应用于合规内容监测、API自动化调用与竞品协议研究等工程场景。本文聚焦小红书x-mini签名这一典型样本,详解从JNI_OnLoad定位

weixin_31264565的博客 457

基于Android的文本语音朗读器的设计与实现(有声小说APP)

摘要:本文设计了一款基于Android平台的智能文本语音朗读系统,旨在解决传统阅读方式对视力负担及视障群体获取信息不便的问题。系统采用Java开发,整合TTS语音合成技术,实现文本导入、多语言切换、语速调节等核心功能,支持背景音乐智能匹配。通过需求分析、架构设计(包括MVC框架和MyBatis数据库交互)及功能测试,验证了系统的实用性和用户体验。研究展望了AI语音合成技术的优化方向,为移动端无障碍阅读提供了有效解决方案。 关键词:Android;语音合成;TTS;无障碍阅读;智能推荐

毕业作品网站 5234

MATLAB算法实战应用案例精讲-【数模应用】校准曲线(附MATLAB、python和R语言代码实现)

模型校准曲线(Calibration Curve),也称为可靠性曲线(Reliability Curve)或概率校准曲线(Probability Calibration Curve),是一种评估分类模型输出概率准确性的图形工具。它可以帮助我们理解模型的预测概率是否与实际标签的分布一致。校准曲线通常包括以下步骤:计算模型预测概率:对于测试集中的每个样本,模型会输出一个概率值,表示样本属于正类的概率。将数据分桶:将这些概率值分成若干个等宽的桶(例如10个桶),每个桶中的样本具有相似的预测概率。

qq_36130719的博客 559

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

无障碍辅助:OpenClaw+Qwen3-32B实现语音控制电脑

本文介绍了如何在星图GPU平台上自动化部署Qwen3-32B-Chat 私有部署镜像(RTX4090D 24G 显存 CUDA12.4 优化版),实现无障碍语音控制电脑功能。该方案结合OpenClaw框架,使视障用户通过自然语言指令即可完成文件管理、邮件发送等日常操作,显著提升数字设备使用体验。

weixin_42522857的博客 425

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Intouch/ifix语音报警系统制作(4-自动发送邮件提醒)

在近期项目完成后,有遇到情况:类似于语音报警后,中控室人员未及时报告给我们造成了事件的危害升级,以及造成很不好的影响。针对这个情况特此添加语音报警后,自动发送邮件提醒,完善现有的报警机制。 1.函数编写(选自网友脚本) Option Explicit '需要引用 Microsoft CDO for Windows 2000 Library和 Mic...

weixin_30706691的博客 491

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

文字转化为语音Android中TextToSpeech类的简单使用

TTS(从文本到语音(TextToSpeech)) TTS是Text To Speech的缩写,即“从文本到语音”,是人机对话的一部分,让机器能够说话。 它是同时运用语言学和心理学的杰出之作,在内置芯片的支持之下,通过神经网络的设计,把文字智能地转化为自然语音流。TTS技术对文本文件进行实时转换,转换时间之短可以秒计算。在其特有智能语音控制器作用下,文本输出的语音音律流畅,使得听者在听取信息时感觉自然,毫无机器语音输出的冷漠与生涩感。TTS语音合成技术 [1] 即将覆盖国标一、二级汉字,具有英文接口,自

hdhhd的博客 1703

h5打电话发短信写邮件怎么实现

// 一、打电话<a href="tel:0755-10086">打电话给:0755-10086</a>// 二、发短信,winphone系统无效<a href="sms:10086">发短信给: 10086</a>// 三、写邮件//注:在添加这些功能时,第一个功能以"?"开头,后面的以"&"开头//

THINK_OF_的博客 1244
上一篇: RichEdit控件在处理EM_REPLACESEL消息中有bug?附一种解决办法
下一篇: PE知识学习,连载----------------------1,2
zk520
博客等级 码龄20年 0粉丝 28原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值