源码

https://github.com/iDeMonnnnnn/DeMon_Sound

FMOD

FMOD是一个强大的声音引擎框架,QQ、魔兽世界及其他很多游戏都是使用的这套框架,框架内包含几十种声音类型,还可以修改声音的频率、速度等等。

1.FMOD download

进入FMOD download,下载Android端引擎库。

2.复制代码

将下载下来的FOMD引擎库中的Jar包,so库和jni c++文件,复制到项目中。

3.编辑配置

编辑配置CMakeLists.txt

-----------------------------------------
find_library( log-liblog )set(lib_path ${CMAKE_SOURCE_DIR}/libs)
# 添加三方的so库
add_library(libfmodSHAREDIMPORTED )# 指名第三方库的绝对路径
set_target_properties( libfmodPROPERTIES IMPORTED_LOCATION${lib_path}/${ANDROID_ABI}/libfmod.so )add_library(libfmodLSHAREDIMPORTED )set_target_properties( libfmodLPROPERTIES IMPORTED_LOCATION${lib_path}/${ANDROID_ABI}/libfmodL.so )#--------------------------------
add_library( # Sets the name of the library.FmodSound# Sets the library as a shared library.SHARED# Provides a relative path to your source file(s).src/main/cpp/native-lib.cpp)#---------------------
# 导入路径,为了让编译时能够寻找到这个文件夹
include_directories(src/main/cpp/inc)# 链接好三个路径
target_link_libraries( FmodSoundlibfmodlibfmodL${log-lib} )

4.修改代码

修改native-lib.cpp,已完成项目需求,如保存变声文件的代码:

extern "C"
JNIEXPORT jint JNICALL
Java_com_demon_fmodsound_FmodSound_saveSound(JNIEnv *env, jobject cls, jstring path_jstr, jint type, jstring save_jstr) {Sound *sound;DSP *dsp;bool playing = true;float frequency = 0;System *mSystem;JNIEnv *mEnv = env;int code = 0;System_Create(&mSystem);const char *path_cstr = mEnv->GetStringUTFChars(path_jstr, NULL);LOGI("saveAiSound-%s", path_cstr)const char *save_cstr;if (save_jstr != NULL) {save_cstr = mEnv->GetStringUTFChars(save_jstr, NULL);LOGI("saveAiSound-save_path=%s", save_cstr)}try {if (save_jstr != NULL) {char cDest[200];strcpy(cDest, save_cstr);mSystem->setSoftwareFormat(8000, FMOD_SPEAKERMODE_MONO, 0); //设置采样率为8000,channel为1mSystem->setOutput(FMOD_OUTPUTTYPE_WAVWRITER); //保存文件格式为WAVmSystem->init(32, FMOD_INIT_NORMAL, cDest);mSystem->recordStart(0, sound, true);}//创建声音mSystem->createSound(path_cstr, FMOD_DEFAULT, NULL, &sound);mSystem->playSound(sound, 0, false, &channel);LOGI("saveAiSound-%s", "save_start")switch (type) {case MODE_NORMAL:LOGI("saveAiSound-%s", "save MODE_NORMAL")break;case MODE_FUNNY:LOGI("saveAiSound-%s", "save MODE_FUNNY")mSystem->createDSPByType(FMOD_DSP_TYPE_NORMALIZE, &dsp);channel->getFrequency(&frequency);frequency = frequency * 1.6;channel->setFrequency(frequency);break;case MODE_UNCLE:LOGI("saveAiSound-%s", "save MODE_UNCLE")mSystem->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsp);dsp->setParameterFloat(FMOD_DSP_PITCHSHIFT_PITCH, 0.8);channel->addDSP(0, dsp);break;case MODE_LOLITA:LOGI("saveAiSound-%s", "save MODE_LOLITA")mSystem->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsp);dsp->setParameterFloat(FMOD_DSP_PITCHSHIFT_PITCH, 1.8);channel->addDSP(0, dsp);break;case MODE_ROBOT:LOGI("saveAiSound-%s", "save MODE_ROBOT")mSystem->createDSPByType(FMOD_DSP_TYPE_ECHO, &dsp);dsp->setParameterFloat(FMOD_DSP_ECHO_DELAY, 50);dsp->setParameterFloat(FMOD_DSP_ECHO_FEEDBACK, 60);channel->addDSP(0, dsp);break;case MODE_ETHEREAL:LOGI("saveAiSound-%s", "save MODE_ETHEREAL")mSystem->createDSPByType(FMOD_DSP_TYPE_ECHO, &dsp);dsp->setParameterFloat(FMOD_DSP_ECHO_DELAY, 300);dsp->setParameterFloat(FMOD_DSP_ECHO_FEEDBACK, 20);channel->addDSP(0, dsp);break;case MODE_CHORUS:LOGI("saveAiSound-%s", "save MODE_CHORUS")mSystem->createDSPByType(FMOD_DSP_TYPE_ECHO, &dsp);dsp->setParameterFloat(FMOD_DSP_ECHO_DELAY, 100);dsp->setParameterFloat(FMOD_DSP_ECHO_FEEDBACK, 50);channel->addDSP(0, dsp);break;case MODE_HORROR:LOGI("saveAiSound-%s", "save MODE_HORROR")mSystem->createDSPByType(FMOD_DSP_TYPE_TREMOLO, &dsp);dsp->setParameterFloat(FMOD_DSP_TREMOLO_SKEW, 0.8);channel->addDSP(0, dsp);break;default:break;}mSystem->update();} catch (...) {LOGE("saveAiSound-%s", "save error!")code = 1;goto end;}while (playing) {usleep(1000);channel->isPlaying(&playing);}LOGI("saveAiSound-%s", "save over!")goto end;end:if (path_jstr != NULL) {mEnv->ReleaseStringUTFChars(path_jstr, path_cstr);}if (save_jstr != NULL) {mEnv->ReleaseStringUTFChars(save_jstr, save_cstr);}sound->release();mSystem->close();mSystem->release();return code;
}

5.原生加载SO

加载FMOD的方法,提供给Android调用:

object FmodSound {//音效的类型const val MODE_NORMAL = 0 //正常const val MODE_FUNNY = 1 //搞笑const val MODE_UNCLE = 2 //大叔const val MODE_LOLITA = 3 //萝莉const val MODE_ROBOT = 4 //机器人const val MODE_ETHEREAL = 5 //空灵const val MODE_CHORUS = 6 //混合const val MODE_HORROR = 7 //恐怖init {System.loadLibrary("fmodL")System.loadLibrary("fmod")System.loadLibrary("FmodSound")}external fun saveSound(path: String, type: Int, savePath: String): Intexternal fun playSound(path: String, type: Int = MODE_NORMAL): Intexternal fun stopPlay()external fun resumePlay()external fun pausePlay()external fun isPlaying(): Booleanfun saveSoundAsync(path: String, type: Int, savePath: String, listener: ISaveSoundListener? = null) {try {if (isPlaying()) {stopPlay()}val result = saveSound(path, type, savePath)if (result == 0) {listener?.onFinish(path, savePath, type)} else {listener?.onError("error")}} catch (e: Exception) {listener?.onError(e.message)}}interface ISaveSoundListener {//成功fun onFinish(path: String, savePath: String, type: Int)//出错fun onError(msg: String?)}}

6.原生调用

在项目中调用FMOD方法,先保存变声文件,保存成功后播放。

    override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)//初始化FMOD.init(this)binding = ActivitySoundFmodBinding.inflate(layoutInflater)setContentView(binding.root)var path = intent.getStringExtra("path") ?: ""val file = File(path)if (!file.exists()) {showToast("录音文件不存在,请重新录制!")finish()} else {if (path.endsWith(".amr")) {path = AmrToWav.makeAmrToWav(path, false)}binding.tvPath.text = "音频文件:$path"}binding.fnRG.setOnCheckedChangeListener { group, checkedId ->val pos = group.indexOfChild(group.findViewById(checkedId))Log.i(TAG, "onCreate: $pos")type = pos}binding.btnPlay.setOnClickListener {GlobalScope.launchIO {FmodSound.playSound(path, type)}}binding.btnSave.setOnClickListener {binding.tvSave.text = "开始变声..."//耗时任务,需要在子线程中执行GlobalScope.launchIO {FmodSound.saveSoundAsync(path, type, getRecordFilePath(1), object : FmodSound.ISaveSoundListener {override fun onFinish(path: String, savePath: String, type: Int) {runOnUiThread {binding.tvSave.text = "变声输出文件路径:$savePath"}FmodSound.playSound(savePath)}override fun onError(msg: String?) {Log.e(TAG, "onError: $msg")runOnUiThread {binding.tvSave.text = "变声失败:$msg"}}})}}}override fun onDestroy() {super.onDestroy()//释放FMOD.close()}

7.FMOD优缺分析

  • 优点:变声类型多,自定义功能强大,百度文档比较多。
  • 缺点:变声引擎库体积大,调用方法多,使用麻烦,保存变声文件的速度较慢。

SoundTouch

SoundTouch是一个开源音频处理库,用于更改音频流或音频文件的速度,音调和播放速率。该库还支持估算音轨的稳定每分钟节拍速率。

1.下载源码

进入SoundTouch的Gitlab仓库下载最新的源码。

2.解压编译

解压下载的源码,进入到目录soundtouch/source/Android-lib/jni,打开CMD执行ndk-build,将jni编译成so库。

注意安装NDK环境。


如果编译中遇到下图的错误:


可以在Android.mk中添加APP_ALLOW_MISSING_DEPS=true即可。

3.复制SO库

soundtouch/source/Android-lib/libs生成的so库,选择需要的平台复制到你的项目中。

由于SoundTouch已经不再支持armeabi,需要armeabi平台的,可以直接使用armeabi-v7a平台的,两个平台的so库是完全兼容的。

如果so不是放在默认的'src/main/jniLibs'目录下,需要在在build.gradle中配置。
例如放在libs目录下:

sourceSets {main {jniLibs.srcDirs = ['libs']}}

4.原生加载SO

复制source/Android-lib/src/net/surina/soundtouch/SoundTouch.java到你项目中,注意该文件需要放在包名net.surina.soundtouch下(如果你修改了soundtouch-jni.cpp中的包名,则放到自己指定的包名下即可)。

5.原生调用

在项目中调用,设置变声音调/速率,生成变声文件,并播放。

   /*** 执行变声,需要在子线程中执行** @param path 音频文件陆宇* @param savePath 变声后文件保存路径*/private fun process(path: String, savePath: String) {try {val st = SoundTouch()st.setTempo(tempo) //速度st.setSpeed(speed) //速度&音调st.setPitchSemiTones(pitch) //音调val res = st.processFile(path, savePath)//res==0 变声成功if (res == 0) {//播放savePath   } else {showToast(SoundTouch.getErrorString())}} catch (e: Exception) {e.printStackTrace()}}

6.SoundTouch优缺分析

  • 优点:so库体积小,使用方便,方法简单,生成变声文件速度快。
  • 缺点:变声选择少,只能控制音调和速率;没有现成的so库需要自己配环境编译。

参考文档

FMOD

http://blackchy.com/2018/12/10/2018-12-10-Fmod-Voice-Change/

https://www.jianshu.com/p/2e1fd3035ae1

SoundTouch

http://www.surina.net/soundtouch/README-SoundTouch-Android.html

https://gitlab.com/soundtouch/soundtouch

Android端FMODSoundTouch音频变声解决方案相关推荐

  1. 如何在3分钟内实现音频变声和趣味音效?

    在泛娱乐社交和互动游戏场景中,用户已不再满足于高清的音质体验和实时的互动效果,他们还想要增加趣味性和沉浸感,让声音变得好玩有趣.拍乐云Pano上线了音频变声接口,开发者可以通过 Pano SDK 设置 ...

  2. 怎样将音频变声?1分钟教你音频变声怎么弄!

    大家平常爱不爱刷短视频呢?不知道你们看短视频的时候有没有注意到,一些视频的配音很是搞怪,常常让人捧腹大笑!那么这些声音是怎么制作出来的呢?其实大部分的搞怪配音,都是借助软件对音频进行变音来实现的~今天 ...

  3. 如何将音频变声?试试这几个方法吧

    昨天,我在构思视频素材的时候想到可以在其中添加一个鬼畜片段,以此来提升视频的丰富度和乐趣.那么如果要添加鬼畜片段的话,首先就需要我们将音频进行变声操作,不过由于不知道怎么进行音频变声,于是我就上网搜索 ...

  4. 这三个音频变声编辑软件教你怎么给音频变声

    现如今随着我们生活的节奏越来越快,大家都爱上了短视频,每天也都有大量的短视频被创作出来.在这样的背景下,不知道有没有小伙伴也充满创意的想去尝试,但是却因为不知道怎么调整音频变声而阻挡了创作的步伐呢?其 ...

  5. 怎样将音频变声?三分钟教会你

    音频变声是一种常见的音频处理方式,可以对人声或音乐进行特殊处理,使其声音产生不同的效果.它的应用广泛,像是音乐制作人可能需要使用音频变声来改变歌手的声音,使其更加独特或与歌曲的风格相匹配.例如,将男歌 ...

  6. 音频变声的软件叫什么?这些软件值得收藏

    在今天这个数字时代,随着人们对于娱乐消费需求的不断增长,很多人开始涉足各种新领域,比如语音包.游戏配音.BGM制作等等.这些领域的共同点是需要一定的音频素材,同时也需要创意性地处理这些素材.这时,音频 ...

  7. Android 开发之 QQ变声功能实现

    1.简介 在QQ中我们使用到的一个功能就是变声,QQ是使用FMOD实现的,那么同样的我们也使用FMOD让自己的应用可以变音 2.FMOD简介 fmod Ex 声音系统是为游戏开发者准备的革命性音频引擎 ...

  8. ffmpeg 音频 变声

    记录一次ffmpeg编码变声的根本原因: 音频源采样率和ffmpeg编码时的采样率不同,音频源在采集是采样率为48000,而编码时用44100,所以播放出来的声音显得宽厚.是真.

  9. FFmpeg进阶: 音频变声滤镜

    声音最重要的两个元素就是语速和语调,改变声音的辨识度主要也是从这两方面入手.我们可以通过对音频数据进行插值或者抽值修改,以达到降低语速和增加语速的目的.同时我们也可以通过对数据进行线性拉伸来调节音调. ...

  10. 使用 fmod windows 下实现音频变声 -- 萝莉 大叔 等 特效

    将文件拖到窗口内,  点击播放可以看到变声效果. 也可以 点击输出将文件变声输出到文件. 可以在路径  https://download.csdn.net/download/w839687571/16 ...

最新文章

  1. iOS runtime实用篇:让你快速上手一个项目
  2. 使用onenote记HTML笔记,如何在Windows 10中使用OneNote做笔记
  3. 【技术好文转载】为什么AI芯片是当今热点
  4. 10丨 Redis主从同步与故障切换,有哪些坑
  5. 三、值类型与引用类型
  6. jira在linux下面的安装和配置
  7. 请先设置tkk_理光MP2014扫描至文件夹的设置方法
  8. 【服务器实战搭建】centos7下使用yum安装mysql
  9. Linux系统可卸载内核模块完全指南(上)
  10. 凉山州计算机等级考试时间,2020年四川凉山中考考试时间及科目安排(已公布)...
  11. How does RECORDLENGTH affect your exp speed?
  12. 压缩文件RAR和ZIP的区别
  13. Qt 界面美化教程 QSS QML Qt自绘方式优缺点对比
  14. 中国5G基站将带动155GWh以上锂电池需求
  15. Unity UnityWebRequest从网页加载图片并永久保存在本地
  16. java 禁用迅雷_【Java】我擦!迅雷的代码结构竟然被扒了精光~
  17. 众里寻他千百度,不如用它来搜库!
  18. 联通服务器维护破解限速,网速1mbps(联通限速1mbps解除方法)
  19. 中国天气雷达行业市场供需与战略研究报告
  20. oracle建表的时候同时创建主键,外键,注释,约束,索引

热门文章

  1. Conditional Generative Adversarial Nets(CGAN)
  2. 网站封装APP详细打包教程
  3. 实现两个路由器漫游(传统路由器做AP)
  4. in作为介词的用法_英语介词丨in、on 、at 的具体用法到底有哪些?
  5. Zabbix通过SNMP协议监控H3C交换机
  6. 20162330 第十二周 蓝墨云班课 hash
  7. 苹果笔记本电脑怎么编辑html,苹果笔记本电脑怎么操作 苹果笔记本电脑操作方法【详解】...
  8. 安防监控直播中无插件web直播方案中实现快照抓取的功能
  9. 数据科学家:人工智能领域的知识图谱理论总结
  10. 如何给PDF文件添加页码