最近做了一个变声语音的项目,里面涉及到很多音频相关的知识,怕时间久了记不住,写下来备忘。

1. 语音的编码

语音录制的时候要选择一个编码格式,因为移动端的原因,这个编码格式需要满足压缩比高、声音质量较好(至少变声后能听得清说什么),同时还要编码难度小。

我们前期选择了几种格式:amr、speex、aac、wav。 说下几种编码的优缺点。

首先amr 是最常用于语音的编码,特别是在移动端上,优点是压缩比相当高,60s 的语音采用8K 采样率、16bit的样本大小,可以达到35K-90K的文件大小。缺点就是 iOS原生是不支持的,需要借助第三方库来实现编解码,比如著名的OpenCore-AMR。(实际开发中还发现 网上能搜到的只有8K采样率的编解码器,16K的只有编码,没有解码,32K以上的搜不到)

然后是speex, 这种编码格式是专门用于speex这个开源库的,好处之一是开源,而且里面实现了语音的降噪、回音消除等功能,特别适合于VOIP的开发。不过缺点就是整个框架是一体的,单独拆开某个模块来使用可能不太容易,而我们录制和播放的过程中有其他的处理,并不想使用他的那一套代码。而且貌似speex已经不维护了,现在更名为 opus。这个就没有仔细去研究了。

aac 这种格式是iOS原生支持的,而且据说声音效果很好,但是缺点就是文件有点大,而且安卓原生sdk也不支持。如果是要做一个iOS本地的语音app,我觉得还是挺不错的。

wav 就不用多说了,用过windows的都知道,微软自家的,苹果对他的支持也不错,缺点嘛,跟aac一样,太大,只适合在本地录制和播放,不适合移动网络下的传输。

为了兼容安卓,并且考虑到移动网络的带宽,我们最终选定了amr -nb作为传输格式, 也就是amr 8Khz采样率的编码格式。(其实这里还有一个坑,后面再说)本地的播放我们采用 wav,因为wav是无损的,可以在录制的时候变声,而且可以很方便的转换到amr。

2. 录制和播放

选择好编码后,就是录制语音。网上有很多开源的代码,我们选择的是官方的SpeakHere,技术上用的是AudioQueueService 来录制和播放。SpeakHere的代码很久没更新了,有些不兼容 ios7 的,我们下载之后解决了很多warning,才开始用起来。 关于AudioQueueService的相关知识,可以自行谷歌百度,总得来说就是通过一个异步队列去获取麦克风的数据(录制) 或者是即将输出的数据(播放),属于CoreAudio框架的一部分。  语音录制还有AudioUnit, AudioFileStream等方案, AudioUnit相对来讲复杂一些,需要自己设定inputBus,outBus,设的不好就什么都听不到。AudioFileStream 是用于音频流的解析,可以获取音频的格式信息,解析音频帧,跟AudioQueue配合使用可以实现音频的seek等功能。

从项目开发的角度上来看,AudioQueue是最适合的,所以我们果断选择了AudioQueue。

3. 转码

前面讲到wav跟amr的转换,我们采用的就是先解码wav,将wav的头部信息去除掉,然后读出pcm的音频数据,同时打开一个新的文件,写入amr的头部信息,再将pcm一帧一帧的转换成amr的数据,写入到amr文件中。反之亦然。

原理挺简单,但是真正做起来还是碰到很多问题。 首先就是录音时候的分辨率跟转码时候的分辨率、变声的分辨率都要一致,否则就会出现声音走样,或者根本不能播放的问题。然后在32位和64位机器上,wav的编码有一点点不一样,主要是32位上采样率和声道数以十六进制写进去的时候需要去掉低字节,至于原因,我也不是很清楚,可能是OC与C++混编导致的吧,这种混编能避免就尽量避免,否则一些莫名奇妙的问题真的不好解决。还有一个就是原本安卓是支持直接编解码amr的,但是由于我们需要做变声处理,不能直接录制完就存起来,而安卓本身MideaPlayer和AudioPlayer封装的很死,没有提供转换编码的方法,所以只能再去源码中提取OpenCore这个库,重新编译so文件。安卓的同学有么有感觉特别坑爹啊~~

4. 变声

变声我们采用的soundTouch的开源库,现在做变声基本都是用这个。这个库可以做到变调、变速的自己组合,使用起来很简单,先初始化一个soundTouch的实例,然后把录音获取的数据 调用putSamples 方法传进去,然后调用receiveSamples 再传出来,然后再写到自己的文件里。需要注意的是,soundTouch里面的sampleType是根据你的样本大小来定的,如果是16bit的大小,就对应short类型,如果是32bit的大小,就对应float或者int。

5. 下载和播放逻辑

下载这块其实跟音频关系不大,但是项目中也碰到了不少问题,所以还是提一下。

我们的音频文件都是按消息中带的Id去服务器拉取的,然后下载到本地再按顺序播放,所以需要一个队列去控制这块的逻辑。最开始我们是把下载跟播放完全分开,下载模块就管理下载的队列,播放模块只管理播放的队列。但是后面发现不行,因为下载是异步的,而播放是同步的,所以还需要一个中间的controller去协调。

队列控制我们采用的是NSOperationQueue,这里有个问题,就是ios7以后, isConcurrent不能用了,取而代之的是一个叫isAsynchorized的方法,按官方文档的说法,isAsynchorized设为NO,应该就是同步的,但是实测发现完全不靠谱,还是并发的下载,而且有多少个operation,就有多少个线程!难道是我理解错了,同步跟非并发不能对等? 没办法,我们只能再增加一个 maxConcurrentOperationCount = 1 的限制,这才变成了同步的下载。

由于AudioQueue的回调函数本身是异步执行的,所以当把播放的operation加到队列里面之后,又出现一个问题,就是播放了一两秒之后,就会停下来。这是因为operation结束了,AudioQueue的回调函数就终止了。要解决这个问题,还得再一个runloop去阻塞线程,并且监听AudioQueue 的运行状态,当最后一帧播放完成后,AudioQueue会将running属性置为false,这时候再结束播放的线程就OK了。

按正常情况来说,语音到这里其实也就差不多了,但是要做的事情其实很有很多。由于iPhone麦克风的问题,会将很多杂音录制进来,所以还需要降噪、自动增益,然后还有语音的播放模式问题(听筒跟扬声器的切换)等等,后面抽时间再写吧。

iOS变声语音项目总结相关推荐

  1. 如何基于 ZEGO SDK 实现 iOS 变声/混响/立体声

    1 功能简介 在直播.语聊房.K 歌房场景中,为增加趣味性和互动性,玩家可以通过变声来搞怪,通过混响烘托气氛,通过立体声使声音更具立体感.ZegoExpress SDK 提供了多种预设的变声.混响.混 ...

  2. [项目总结]在ios中使用soundtouch库实现变声

    这篇文章是项目总结了. 做了段时间的项目,过程中也遇到了很多麻烦,但是好在终于都解决了,这里是这里是项目之后凭着记忆总结出来,大家有遇到同样的问题,希望能参考了,但是我记忆可能不太好了,要是实践中有什 ...

  3. 汉字转拼音,文字转语音tts (语音技术、语音识别),Asr/tts,变声

    语音识别,语音合成.语音技术主要分两块:一块是语音转文字,即语音识别:另一块是文字转语音,即语音合成.   语音相关技术研发 语音合成技术整体解决方案.一系列语音技术的相关专利,包括文本处理.韵律预测 ...

  4. 仿QQ语音变声功能实现

    版权声明:转载必须注明本文转自张鹏辉的博客: http://blog.csdn.net/qingtiangg 大家好,这是我从业以来第一篇博客,给大家拜个晚年,祝大家鸡年大吉,幸福美满.事业有成.好了 ...

  5. android变声后的文件,仿QQ语音变声功能实现(二)---移植到android studio 并解决部分问题...

    版权声明:转载必须注明本文转自张鹏辉的博客: http://blog.csdn.net/qingtiangg 大家好,距离上一篇博客半年过去了,关于上一篇博客很多人加我QQ留言问了几个问题,最近不忙决 ...

  6. 在ios中使用soundtouch库实现变声

    这篇文章是项目总结了. 做了段时间的项目,过程中也遇到了很多麻烦,但是好在终于都解决了,这里是这里是项目之后凭着记忆总结出来,大家有遇到同样的问题,希望能参考了,但是我记忆可能不太好了,要是实践中有什 ...

  7. 【开源项目】AI Vtuber 一个由多LLM驱动的虚拟主播,可以在Bilibili/抖音 直播中与观众实时互动或本地聊天。使用多种TTS技术并可进行AI变声。通过特定指令协同SD绘图。并有循环文案

    AI Vtuber ✨ AI Vtuber ✨ AI Vtuber是一个由 ChatterBot/GPT/Claude/langchain本地or云端/chatglm/text-generation- ...

  8. 仿QQ语音变声功能实现(二)---移植到android studio 并解决部分问题

    版权声明:转载必须注明本文转自张鹏辉的博客: http://blog.csdn.net/qingtiangg 大家好,距离上一篇博客半年过去了,关于上一篇博客很多人加我QQ留言问了几个问题,最近不忙决 ...

  9. 实时语音趣味变声,大叔变声“妙音娘子”Get一下

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯游戏云 发表于云+社区专栏 游戏社交化是近年来游戏行业发展的重要趋势,如何提高游戏的社交属性已成为各大游戏厂商游戏策划的重要组成部 ...

最新文章

  1. MySQL解压版安装
  2. 数据结构与算法 / 队列(queue)
  3. ElasticSearch集群部署【windows+Linux双系统搭建】
  4. require(),include(),require_once()和include_once()区别
  5. Java剪切板操作大全
  6. 验证曲线和学习曲线_如何击败技术学习曲线的怪物
  7. python网络爬虫基础day01
  8. twisted系列教程十一 — 一个twisted 的服务端
  9. 错过血亏!一文搞懂Oracle锁相关视图及相关操作
  10. 调整地面材质_【C4DtoA 13】Arnold渲染器(材质七): Shadow Matte Shader
  11. word度量单位无效_ABBYY FineReader 12的具体使用方法和word排版设置
  12. 【自我救赎--牛客网Top101 4天刷题计划】 第四天 登峰造极
  13. HttpRequest 和HttpWebRequest的区别
  14. 逻辑回归:详细建模流程与例子代码
  15. 数二用书推荐以及避雷
  16. java readpassword_Java Password.readPassword方法代碼示例
  17. 微信小程序连接蓝牙打印机打印快递面单
  18. cobar mysql5.6_Cobar init error
  19. 结构光三维重建之光栅图像相位解算(MATLAB)
  20. 自媒体平台为什么总在强调垂直度,这里有你想要的答案!

热门文章

  1. 数据传输:同一网络内传输文件软件
  2. 科研太忙无法顾家?陈婷:人生不能只有一个支点
  3. 创建一个swarm集群
  4. Idle Mystic预售教程
  5. 阿里巴巴增持菜鸟,未来五年再投1000亿建设全球物流网络
  6. 180.CSS火焰动画
  7. 【chatGPT】和chatGPT结对编程的6小时
  8. 报名投票评选微信小程序的设计与实现
  9. 联想R9000P笔记本系统故障无法启动怎么重装系统?
  10. ABAP 二分法查找与SORT排序