IOS和Android音频开发总结
最近因为项目需要对声音进行变声,所以边学习边做,发现音频的处理思路并不难,但是做起来还是有些繁琐的(比预期的)
趁着脑子还发热,赶紧把思路总结一下,记录下来。
主要讲三个部分
1,如何变声2,安卓实现变声3,ios实现变声
1.如何变声?
要想自己写一个变声的函数或者库出来,谈何容易,所以采用了大家普遍采用的库SoundTouch。
该库可以实现改变声音的速度,节拍,音调(这个最重要,可以把声音的音调调高调低,使之变成男生女生,可以参照汤姆猫),该库中对外提供方法的类为SoundTouch类,该类提供了许多方法,其中最重要的就是setPitch,setRate这几个调节声音参数的方法,可以通过设置参数大小实现各种效果,该类在使用前需要初始化一下,设置预制参数如下:
mSoundTouchInstance->setSetting(SETTING_USE_QUICKSEEK, 0);
mSoundTouchInstance->setSetting(SETTING_USE_AA_FILTER, !(0));
mSoundTouchInstance->setSetting(SETTING_AA_FILTER_LENGTH, 32);
mSoundTouchInstance->setSetting(SETTING_SEQUENCE_MS, 40);
mSoundTouchInstance->setSetting(SETTING_SEEKWINDOW_MS, 16);
mSoundTouchInstance->setSetting(SETTING_OVERLAP_MS, 8);
然后设置音频参数实现效果:
mSoundTouchInstance->setChannels(2);
mSoundTouchInstance->setSampleRate(8000);
mSoundTouchInstance->setPitch(2);
这里解释一下音频处理的几个参数,很重要。
声道:channals,可以是单声道和双声道,分别对应1,2
采样率:SampleRate 8000-44100不等,一般是常用的几个值,安卓里面好像44100是所有设备都支持的,所以设置成44100比较保险吧
每个声道的位数:bitsPerChannel 一般设置为16
每个帧的声道数 ChannelsPerFrame 对于pcm数据来说,这个是1
还有几个参数,对于安卓和ios可能说法不太一样,以上几个是都要用到的,比较重要,必须得掌握
2.Android中实现变声
因为项目要求录音要实时播放,所以需要采用读取音频数据流(PCM格式)来播放,采用的api是AudioRecorder和AudioTrack。这两个类相关资料较多,官方文档也比较详细。难点是Android中调用c++库需要使用到jni技术,这里就需要花一些力气将SoundTouch编成so库来使用了。对于这方面可以参考我的上一篇关于JNI的博客,也可以参考网上的资料,将SoundTouch类的几个重要函数对应到java层的Native函数,然后在java层调用。
以下是我写的代码的一部分
首先初始化AudioTrack和AudioRecord:
//初始化AudioTrack
int trbusize=AudioTrack.getMinBufferSize(RECORDER_SAMPLERATE,AudioFormat.CHANNEL_OUT_STEREO,
AudioFormat.ENCODING_PCM_16BIT);
mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,RECORDER_SAMPLERATE,
AudioFormat.CHANNEL_IN_STEREO,
AudioFormat.ENCODING_PCM_16BIT,
trbusize,
AudioTrack.MODE_STREAM);
//初始化AudioRecord
int rebusize = AudioRecord.getMinBufferSize(RECORDER_SAMPLERATE,
AudioFormat.CHANNEL_IN_STEREO,AudioFormat.ENCODING_PCM_16BIT);
mAudioRecord= new AudioRecord(MediaRecorder.AudioSource.MIC,RECORDER_SAMPLERATE,
AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT, rebusize);
各项参数的含义可以参考api文档,需要注意的是,因为不同设备支持的参数可能不同,需要时可以写一个循环把所有可能的参数遍历一遍。
之后是录音和播放,可以分别放到两个线程里面。一般来说都是把录音数据保存到文件中,然后再进行播放,这样可以应付一般的录音需求。但不足之处在于,录音时间久了,文件会很大,如果在网络上实时播放的话这样肯定不行。解决方法就是将录音的数据传到一个缓冲区,然后播放时直接从缓冲区取走数据即可。这个缓冲区可以考虑用循环队列或者在java里面可以直接用一个LinkedList实现。
然后是变声部分:
while(isInstancePlaying){
if(l<21){
byte[] mbyte=new byte[64];
mAudioRecord.read(mbyte,0,64);
SoundTouch.getSoundTouch().putSamples(mbyte,0,INPUT_LENGTH);
SoundTouch.getSoundTouch().setPitchSemiTones(pitchTone);
SoundTouch.getSoundTouch().receiveSamples(mbyte,INPUT_LENGTH);
byteArray.add(mbyte);
l=byteArray.size();
}
else{
mAudioTrack.write(byteArray.getFirst(),0,64);
byteArray.removeFirst();
l=byteArray.size();
}
代码中加粗的三个函数putSamples,setPitchSemiTones,receiveSamples.这三个都是native方法,在SoundTouch库中分别通过SoundTouch类提供的对应函数实现,
通过put和receive两个函数,mbyte这个数据块中的音频数据就实现了变声,变声的效果是通过中间的函数setPitchSemiTones()设置的。这里为了实现实时变声,我采用
了LinkedList作为一个缓冲区,l是其长度,当小于20时添加到byteArray的末尾,同时AudioTrack不断读取数组中的第一个元素来播放然后删除该元素,这样实现了实时的播放。
最后播放完要记得释放mAudioTrack和mAudioRecorder。通过stop和release方法实现。
3.IOS实现变声
因为本人之前没接触过ios所以做起来遇到了不少问题,还好最后解决了。
ios里面的音频处理比起安卓来说感觉要麻烦一些,用到的核心api就是AudioQueue,正在使用之前一定要好好理解一下它的原理,跟安卓不同的是ios播放和录音都是用的这个api。就相当于它一个东西实现了安卓中AudioRecorder和AudioTrack的功能,只不过在播放和录音过程中内部的流程有所变化。
核心思想:
Audio里面有自带的一个队列,首先用户创建若干个(3-6个左右都行)缓冲器用来装填音频数据,在自带队列中播放或录音完后使用用户自定义的回调函数进行处理,使得缓冲器能够被重新利用,并且可以在回调函数中实现用户自定义的一些功能,比如变声,写入文件等等操作。官方给了说明图比较详细,需要着重理解一下。
首先是录音的流程图:
然后是播放的流程图:
如何变声呢?
ios的变声不需要安卓的jni,因为oc语言可以和c++混编,所以这点相对来说要简单许多。流程如下:
首先在你的程序中实例化一个SoundTouch类,然后在初始化时将它的参数设置好(setSetting),之后在上面所述的回调函数里面就可以将录音得到的数据流进行处理然后选择保存到文件或者直接播放。思路就是这样,但是里面的函数的参数相对还是比较繁琐的,前面原理没理解的话这边就很难做下去了。
实时播放?
思路同Android,可以写一个循环队列用来缓存音频数据,然后边录音往里面传数据边播放,跟安卓不同的是这些操作需要放到相应的回调函数里面来实现,有个简单的办法是在录音的回调函数里面直接播放pcm数据。因为数据是一块一块的进来的,每使用完一次缓冲器才会调用一次回调函数,可以直接在回调函数里面进行播放。
以上就是两个平台上实现录音和实时播放的简单介绍,这里面的东西还是蛮多的,值得深入研究。
IOS和Android音频开发总结的更多相关文章
- Android音频开发之——如何播放一帧音频
本文重点关注如何在Android平台上播放一帧音频数据.阅读本文之前,建议先读一下<Android音频开发(1):基础知识>,因为音频开发过程中,经常要涉及到这些基础知识,掌握了这些重要的 ...
- Android音频开发(1):基础知识
Android音频开发(1):基础知识 导读 人的说话频率基本上为300Hz~3400Hz,但是人耳朵听觉频率基本上为20Hz~20000Hz. 对于人类的语音信号而言,实际处理一般经过以下步骤: 人 ...
- Vue项目用于Ios和Android端开发
起因 前公司商城App项目使用的是H5开发,有微信公众号.Ios和Android三个版本,H5版本是自己写的一套框架,已经用了有些年头了,承载不下不断涌现出的新需求.而Ios和Android端通过we ...
- Android Multimedia框架总结(十七)音频开发基础知识
请尊重分享成果,转载请注明出处,本文来自逆流的鱼yuiop,原文链接:http://blog.csdn.net/hejjunlin/article/details/53078828 近年来,唱吧,全民 ...
- 《React Native 精解与实战》书籍连载「配置 iOS 与 Android 开发环境」
此文是我的出版书籍<React Native 精解与实战>连载分享,此书由机械工业出版社出版,书中详解了 React Native 框架底层原理.React Native 组件布局.组件与 ...
- char的定义在iOS和Android下是不同的
char is different in iOS and Android!跨平台开发时很容易忽略的非常坑爹的一个区别. 我的需求是实现一个算法,这个算法在iOS和Android下需要保持一致的结果,很 ...
- Android IOS WebRTC 音视频开发总结(十六)-- 音频设备操作之opensl与jni
本节主要分享视频通话中android和ios上操作音频设备的方式,如调解音量大小,启用扬声器(本系列文章转载请说明出处,博客园RTC.Blacker). 先看看webrtc中处理音频设备代码的目录结构 ...
- Android IOS WebRTC 音视频开发总结(二九)-- 安卓噪声消除交流
Android上的音质一直被大家所困扰和诟病,这里面有很多原因, 下面是最近一位前UC同行发邮件跟我交流的一些记录,供参考,支持原创,文章来自博客园RTC.Blacker,转载请说明出处. 以下文字来 ...
- Android IOS WebRTC 音视频开发总结(六)-- iOS开发之含泪经验
前段时间在搞webrtc iOS开发,所以将标题改为了Android IOS WebRTC 音视频开发总结, 下面都是开发过程中的经验总结,转载请说明出处(博客园RTC.Blacker): 1. IO ...
随机推荐
- Spring AOP注解为什么失效?90%Java程序员不知道
使用Spring Aop注解的时候,如@Transactional, @Cacheable等注解一般需要在类方法第一个入口的地方加,不然不会生效. 如下面几种场景 1.Controller直接调用Se ...
- mysql的force index
MSQL中使用order by 有个坑,会默认走order by 后面的索引.而不走where条件里应该走的索引.大家在使用时要绕过此坑. 如下语句因为order by 走了settle_id这个主键 ...
- TI的H264 SOC方案
TI的H264 SOC方案是目前常用的视讯解决方案,TI针对视频会议,视频监控,视频存储等场景细化需求并优化了H264技术. 1. TI H.264背景 如今视频压缩技术在视频领域有非常多的应用需求. ...
- transform动画效果
transform动画效果 transform :移动,旋转.倾斜.缩放. transform:translate(0,300px); x代表的是水平的偏移距离,y代表垂直的. t ...
- D. GCD Counting(树上dp)
题目链接:http://codeforces.com/contest/1101/problem/D 题目大意:给你n个点,每个点都有权值,然后给你边的关系,问你树上的最大距离.(这里的最大距离指的是这 ...
- python collection 中的队列
认识中的队列 在以前的认知里,队列是先进先出,就是一头进,一头出,Queue.而无意间看到了deque 双向队列. 即从该队列的头或者尾部都能插入和移除元素.而起时间复杂度竟然是一样的!O(1),是不 ...
- CertUtil.exe被利用来下载恶意软件
1.前言 经过国外文章信息,CertUtil.exe下载恶意软件的样本. 2.实现原理 Windows有一个名为CertUtil的内置程序,可用于在Windows中管理证书.使用此程序可以在Windo ...
- Linux configure关于交叉编译的参数设置【转】
转自:http://blog.csdn.net/darennet/article/details/9003005 configure的参数众多,一般包括如下 --srcdir=DIR 这个选项对安装没 ...
- 【驱动】USB驱动实例·串口驱动·键盘驱动【转】
转自:http://www.cnblogs.com/lcw/p/3159370.html Preface USB体系支持多种类型的设备. 在 Linux内核,所有的USB设备都使用 usb_drive ...
- mysql -> 索引_07
索引与sql语句优化 压力测试对比