IOS和Android音频开发总结

最近因为项目需要对声音进行变声,所以边学习边做,发现音频的处理思路并不难,但是做起来还是有些繁琐的(比预期的)

趁着脑子还发热,赶紧把思路总结一下,记录下来。

主要讲三个部分

1,如何变声2,安卓实现变声3,ios实现变声

1.

要想自己写一个变声的函数或者库出来,谈何容易,所以采用了大家普遍采用的库SoundTouch。

该库可以实现改变声音的速度,节拍,音调(这个最重要,可以把声音的音调调高调低,使之变成男生女生,可以参照汤姆猫)

使用的思路为把整个库放到不同平台的底层,使用时只需包含头文件soundtouch.h即可.

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。

具体的使用方法相关资料较多,官方文档也比较详细。大致思路就是先初始化:

        //initilize     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);
        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);

这里因为不同设备支持的参数可能不同,需要是可以写一个循环把所有可能的参数全试一遍。

之后是录音和播放,可以分别放到两个线程里面。一般来说都是把录音数据保存到文件中,然后再进行播放,这样可以应付一般的录音需求。但不足之处在于,录音时间久了,文件会很大,如果在网络上实时播放的话这样肯定不行。解决方法就是将录音的数据传到一个缓冲区,然后播放时直接从缓冲区取走数据即可。这个缓冲区可以考虑用循环队列或者在java里面可以直接用一个LinkedList实现。

然后是变声部分,安卓里面要想用c++库的话,只能通过jni来实现,可以写几个函数。

                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类提供的对应函数实现,比较简单,通过这几个函数即可实现声音的变声。

l变量是LinkedList(代码中的byteArray)的长度,当小于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数据。因为数据是一块一块的进来的,每使用完一次缓冲器才会调用一次回调函数,可以直接在回调函数里面进行播放。

以上就是两个平台上实现录音和实时播放的简单介绍,这里面的东西还是蛮多的,值得深入研究。

  

时间: 2024-10-19 15:53:01

IOS和Android音频开发总结的相关文章

Android音频开发之——如何播放一帧音频

本文重点关注如何在Android平台上播放一帧音频数据.阅读本文之前,建议先读一下<Android音频开发(1):基础知识>,因为音频开发过程中,经常要涉及到这些基础知识,掌握了这些重要的概念后,开发过程中的很多参数和流程就会更加容易理解. Android SDK 提供了3套音频播放的API,分别是:MediaPlayer,SoundPool,AudioTrack,关于它们的区别可以看这篇文章:<Intro to the three Android Audio APIs>,简单来说

Android音频开发(2):如何采集一帧音频

本文重点关注如何在Android平台上采集一帧音频数据.阅读本文之前,建议先读一下我的上一篇文章<Android音频开发(1):基础知识>,因为音频开发过程中,经常要涉及到这些基础知识,掌握了这些重要的概念后,开发过程中的很多参数和流程就会更加容易理解. Android SDK 提供了两套音频采集的API,分别是:MediaRecorder 和 AudioRecord,前者是一个更加上层一点的API,它可以直接把手机麦克风录入的音频数据进行编码压缩(如AMR.MP3等)并存成文件,而后者则更接

Android音频开发(4):如何存储和解析wav文件

无论是文字.图像还是声音,都必须以一定的格式来组织和存储起来,这样播放器才知道以怎样的方式去解析这一段数据,例如,对于原始的图像数据,我们常见的格式有 YUV.Bitmap,而对于音频来说,最简单常见的格式就是 wav 格式了. wav 格式,与 bitmap 一样,都是微软开发的一种文件格式规范,它们都有一个相似之处,就是整个文件分为两部分,第一部分是"文件头",记录重要的参数信息,对于音频而言,就包括:采样率.通道数.位宽等等,对于图像而言,就包括:图像的宽高.色彩位数等等:第二部

Android音频开发(3):如何播放一帧音频

本文重点关注如何在Android平台上播放一帧音频数据.阅读本文之前,建议先读一下<Android音频开发(1):基础知识>,因为音频开发过程中,经常要涉及到这些基础知识,掌握了这些重要的概念后,开发过程中的很多参数和流程就会更加容易理解. Android SDK 提供了3套音频播放的API,分别是:MediaPlayer,SoundPool,AudioTrack,关于它们的区别可以看这篇文章:<Intro to the three Android Audio APIs>,简单来说

Android音频开发(7):使用 OpenSL ES API(下)

本文是我的<Android音频开发>系列的第七篇文章,上一篇文章总整体上介绍了 Android OpenSL ES API 的基本概况,告诉了大家这个框架有什么特性,可以做什么,不能做什么.本文则重点介绍 OpenSL ES 框架及其API接口的一些关键的设计和概念,只有理解了它们,你才能更好地读懂 OpenSL ES 的相关代码.示例代码则放到了文章的最后,相信大家理解了这些基本的概念后,就能很容易地读懂这些代码的细节了. 1. 面向对象的 C 语言接口 OpenSL ES 虽然是 C 语言

Android音频开发(6):使用 OpenSL ES API(上)

前面几篇文章介绍了如何在 Java 层,利用 Android 提供的 AudioRecord 采集音频,利用 AudioTrack 播放音频,利用 MediaCodec 来编解码,这些 API 均是 Android 提供的 Java 层 API,无论是采集.播放还是编解码,这些 API 接口都需要将音频数据从 Java 拷贝到 native 层,或者从 native 层拷贝到 Java,如果希望减少拷贝,开发更加高效的 Android 音频应用,则建议使用 Android NDK 提供的 Ope

Android音频开发(5):音频数据的编解码

前面四篇文章分别介绍了音频开发必备的基础知识.如何采集一帧音频.如何播放一帧音频.如何存储和解析wav格式的文件,建议有兴趣的小伙伴们先读一读,本文则重点关注如何对一帧音频数据进行编码和解码. 1. Android 官方的 MediaCodec API 首先,我们了解一下 Android 官方提供的音频编解码的 API,即 MediaCodec 类,该 API 是在 Andorid 4.1 (API 16) 版本引入的,因此只能工作于 Android 4.1 以上的手机上. 1.1 MediaC

Android音频开发(1):基础知识

先来点闲言碎语,前段时间我有一段感悟:Android开发,本身并不是一个可以走得多远的方向,它只是一个平台,提供了许多封装好的API,让大家能够快速开发出针对特定业务的应用. 真正有价值的地方就在于Android与具体的业务方向结合,比如:Android与音视频技术,Android与智能硬件交互,Android与前端技术的融合与探索,Android信息安全,Android源码深度定制等等. 我一直比较看好音视频/多媒体方向,希望在此能够深入积累和探索,前段时间我发布了一款Android VoIP

Android IOS WebRTC 音视频开发总结(十六)

本节主要分享视频通话中android和ios上操作音频设备的方式,如调解音量大小,启用扬声器(本系列文章转载请说明出处,博客园RTC.Blacker). 先看看webrtc中处理音频设备代码的目录结构: 第一种方式就是直接调用Android或ObjectC的API,代码如下(WebRtcAudioTrack.java): 通过调用Android提供的AudioManager类来操作音频设备(webrtc是用C++写的,通过JNI来调用这些JAVA方法). 下面是IOS中操作音频设备的方式(aud