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 ...
随机推荐
- PHP基础知识之————匿名函数(Anonymous functions)
匿名函数(Anonymous functions),也叫闭包函数(closures),允许 临时创建一个没有指定名称的函数.最经常用作回调函数(callback)参数的值.当然,也有其它应用的情况. ...
- zookeeper系列之:独立模式部署zookeeper服务
一.简述 独立模式是部署zookeeper服务的三种模式中最简单和最基础的模式,只需一台机器即可,独立模式仅适用于学习,开发和生产都不建议使用独立模式.本文介绍以独立模式部署zookeeper服务器的 ...
- jQuery合并单元格以及还原重置
一.合并rowspan jQuery.fn.rowspan = function(colIdx) { return this.each(function(){ var that; $('tr', th ...
- python 操作excel格式化及outlook正文,发送邮件
import requests import time import os import arrow import pandas as pd import pandas.io.formats.exce ...
- CPU字节序
小端存储:低对低,高对高(低位存储在低地址,高位存储在高地址) 大端存储:低对高,高对低(低位存储在高地址,高位存储在低地址) 小端字节序: x86体系结构,arm指令只支持小端,数据支持大小端 ...
- ashx误删后,未能创建类型
描述 今天,因为临时有事儿,需要去一趟其他城市,项目比较赶.所以只能在车上继续敲代码,倒霉的触摸板让我误删一个ashx一般处理程序.好死不死的这个文件的代码还很长. 我的做法是[垃圾桶]→[还原]→V ...
- ubuntu 开机自动挂在windows下的分区
最近装了Ubuntu14.04 + windows7 的双系统,启动Ubuntu的时候,不会自动挂载win7的分区,只有我点击相应的硬盘符号时才会挂载/media下面.本着折腾到底的原则,在网上搜了搜 ...
- 重写Java Object对象的hashCode和equals方法实现集合元素按内容判重
Java API提供的集合框架中Set接口下的集合对象默认是不能存储重复对象的,这里的重复判定是按照对象实例句柄的地址来判定的,地址相同则判定为重复,地址不同不管内容如何都判定为不重复,这有时与需求不 ...
- aarch64_j2
js-yui2-2.9.0-10.fc24.noarch.rpm 2016-09-25 07:06 1.2M fedora Mirroring Project js-yui2-jenkins-2.9. ...
- redis从入门到放弃 -> 简介&概念
一.redis简介 Redis是一款开源的.高性能的键-值存储.它常被称作是一款数据结构服务器. 当值支持的主要数据类型为:字符串(strings)类型,括哈希(hashes).列表(lists).集 ...