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

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

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

SoundTouch类提供了许多方法,其中最重要的就是setPitch,setRate这几个调节声音参数的方法,具体使用时自行设置参数。

但是在使用前需要预先设置一下其中的几个函数的参数如下:

1
2
3
4
5
6
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);

 然后设置需要的参数

1
2
3
4
5
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数据。因为数据是一块一块的进来的,每使用完一次缓冲器才会调用一次回调函数,可以直接在回调函数里面进行播放。

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

转载于:https://www.cnblogs.com/feiyiban588/p/5596432.html

IOS和Android音频开发总结相关推荐

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

    2019独角兽企业重金招聘Python工程师标准>>> 无论是文字.图像还是声音,都必须以一定的格式来组织和存储起来,这样播放器才知道以怎样的方式去解析这一段数据,例如,对于原始的图 ...

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

    本文重点关注如何在Android平台上播放一帧音频数据.阅读本文之前,建议先读一下<Android音频开发(1):基础知识>,因为音频开发过程中,经常要涉及到这些基础知识,掌握了这些重要的 ...

  3. Android音频开发(六)音频编解码之初识MediaCodec上

    前五篇我们介绍了关于音频的基础知识,今天来讲述一下音频的重点和难点部分,这一节依然是分上下俩个节点,深入讲述Android音频开发的编解码技术. 1.MediaCodec 介绍 MediaCodeC是 ...

  4. Android 音频开发(四) 如何播放一帧音频数据下

    再看这一篇文章前,如果你是小白,我建议你先看一下Android 音频开发(一) 基础入门篇这一篇.今天继续讲解如何通过Android SDK自带API实现播放一帧音频数据. 我们都知道,Android ...

  5. Android 音频开发(二) 采集一帧音频数据

    这一节主要介绍如何采集一帧音频数据,如果你对音频的基础概念比较陌生,建议看我的上一篇Android 音频开发(一) 基础入门篇.因为音频开发过程中,经常要涉及到这些基础知识,掌握了这些重要的基础知识后 ...

  6. Android 音频开发(一) 基础入门篇

    今天主要讲解下Android音频开发的入门知识,希望对想入门却不知如何下手的朋友有所帮助,同时希望能得到高手的指点和帮助. 深入细化基础技能知识点 大致细化如下10个知识点. 音频开发的主要应用有哪些 ...

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

    本文重点关注如何在Android平台上采集一帧音频数据.阅读本文之前,建议先读一下我的上一篇文章<Android音频开发(1):基础知识>,因为音频开发过程中,经常要涉及到这些基础知识,掌 ...

  8. 一次搞懂 Android 音频开发

    在接触Android音频开发后,陆陆续续的看了不少的文章,如果说查缺补漏把这些文章梳理清楚,然后逐个整合,那么确实也能完整的推导出音频开发需要掌握的技术.但是对于初学者来说,可能在开发中产生很多障碍以 ...

  9. android 音乐 简书,Android音频开发(7):音乐可视化-FFT频谱图

    Android 音频开发 目录 一.演示 image 二.实现 实现流程: 使用MediaPlayer播放传入的音乐,并拿到mediaPlayerId 使用Visualizer类拿到拿到MediaPl ...

最新文章

  1. 大家都说 Java 反射效率低,为什么呢?
  2. python异常处理(基础)
  3. 机器学习入门--进阶资料和流程建议
  4. 使用Java操作汉字编码的一个例子
  5. docker初级操作
  6. QQ 二十年沉浮起落,黑产从未缺席
  7. shell编程基础(三): 位置参数与shell脚本的输入输出
  8. 在Win2016上安装SVNServer21步骤
  9. 匈牙利算法(指派问题)
  10. 内存卡 android 刷机教程,怎样用卡刷包刷机?安卓手机通用刷机包卡刷教程
  11. AUTOCAD——Excel表格导入CAD、CAD合并两兄弟
  12. 程序员毕业五年他年薪百万,他月薪一万
  13. 区块链需要c语言和linux嘛,区块链技术如何运作?使用什么开发语言?
  14. UNREAL 多人在綫更换pawn(possess pawn)
  15. matlab求球的体积,【matlab计算不规则物体体积资讯】matlab计算不规则物体体积足球知识与常识 - 足球百科 - 599比分...
  16. Mac系统入门之怎么切换输入法
  17. 2022跨考华中科技大学计算机学院学硕上岸经验分享
  18. SpringCloud(6) 分布式事务【概念、常见框架选择 - tx-lcn】
  19. vim替换所有字符串
  20. 简单明了的LSTM/GRU应用实例(Tensorflow版)

热门文章

  1. 如何定义一个类对象并用next()的方法使用_深入理解-可迭代对象、迭代器(20个为什么)...
  2. 传递对象_看懂Xlua实现原理——从宏观到微观(1)传递c#对象到Lua
  3. mybatis的增删改操作及需要注意的问题
  4. android gps 锁屏更新坐标_MIUI内测版更新日志解析,以及动画解说!
  5. python编译成exe有意义吗_python工程编译成EXE
  6. Kafka坑 - Couldn't find leaders for Set(kafka重启)
  7. centos文件服务器软件,seafile服务器端的centos8的快速部署
  8. 盗贼之海3月22服务器维护,盗贼之海3月29日更新公告_3月29日更新了什么_52pk单机游戏...
  9. js 数组过滤_JS之 开发技巧
  10. php 生成密码字典,密码字典生成工具crunch的简单使用