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 ...
随机推荐
- 6 Easy Steps to Learn Naive Bayes Algorithm (with code in Python)
6 Easy Steps to Learn Naive Bayes Algorithm (with code in Python) Introduction Here’s a situation yo ...
- LintCode 388: Kth Permutation
LintCode 388: Kth Permutation 题目描述 给定 n 和 k,求123..n组成的排列中的第 k 个排列. 样例 对于 n = 3, 所有的排列如下: 123 132 213 ...
- bzoj1485 有趣的数列
传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=1485 [题解] Catalan数,注意不能直接用逆元,需要分解质因数. # include ...
- python概念-各类绑定的概念和property的变态一面
# 编辑者:闫龙 # 1.什么是绑定到对象的方法,如何定义,如何调用,给谁用?有什么特性 #在类中定义的(self)方法都是绑定到对象的方法 #定义 class a: def b(self):#绑定到 ...
- D. Sum in the tree(树形+贪心)
题目链接;http://codeforces.com/contest/1099/problem/D 题目大意:给出一棵树,每个节点到根节点的路径上经过的所有点的权值之和,其深度为偶数的节点的信息全部擦 ...
- 文件读取 FILE
需要了解的概念 [数据流][缓冲区(Buffer)][文件类型][文件存取方式][借助文件指针读写文件] 需要理解的知识点包括:数据流.缓冲区.文件类型.文件存取方式 1.1 数据流: 指程序与数据的 ...
- shell脚本实现分日志级别输出
shell脚本如何优雅的记录日志信息,下面让我们一步一步,让shell脚本的日志也变得高端起来,实现如下功能 ①设定日志级别,实现可以输出不同级别的日志信息,方便调试 ②日志格式类似为:[日志级别] ...
- aarch64_l3
librdmacm-utils-1.1.0-4.fc26.aarch64.rpm 2017-02-12 07:12 87K fedora Mirroring Project libreadline-j ...
- 【Android开发】之Fragment开发1
一直知道Fragment很强大,但是一直都没有去学习,现在有些空闲的时间,所以就去学习了一下Fragment的简单入门.我也会把自己的学习过程写下来,如果有什么不足的地方希望大牛指正,共同进步! 一. ...
- 【Andorid开发框架学习】之Volley入门
Volley是Android平台上的网络通信库,能使网络通信更快,更简单,更健壮.Volley特别适合数据量不大但是通信频繁的场景.在listView显示图片这方面,使用volley也是比较好的,不必 ...