介绍

fmod是一款非常优秀的c++开源框架,这次就通过这个框架来实现仿QQ的变声效果,变声效果有6种,正常,萝莉,大叔,惊悚,搞怪,空灵。关于更多的效果自己感兴趣再去探索,套路大致相同。

项目效果图及其原理

项目采用Fmod开源库,一个非常简单通用的音频引擎,对原始声音进行音效的处理即可做出变声的效果,下面是变声音频的处理

  • 原声:直接播放音频文件
  • 萝莉:对音频提高八度
  • 大叔:对音频减低八度
  • 惊悚:增加音频的颤音
  • 搞笑:增加音频的播放速度
  • 空灵:增加音频的回音

运行

如果能将上次的fmod的示例程序在Android studio中跑起来了,这次运行也没有多大的问题。
本次使用的工具是 android studio 2.3.3,

步骤

1.下载fmod

到fmod的官网注册下载相应的fmod的Android版本。解压。得到如下

这次要用到的是api/lowlevel包下的inc下的文件和lib下的库

2.新建Android项目

通过as新建Android项目,比如这次我的项目名是QQVoice_change
然后将api/lowlevel下包的lib包下的 armeabi,x86文件及其文件下的.so库,fmod.jar 拷贝到项目的libs目录下。

将api/lowlevel包下的inc文件及其文件拷贝到项目的cpp目录下拷贝完成后如图所示

不用忘了拷过去之后要将fmod.jar编译到项目中。

3.修改build.gradle和CMakeLists.txt

很多人在android studio编译c/c++文件动态库,都死在了这一步,这一步需要有gradle和Cmake编程的基础才能真正的搞明白。这一步如果弄错会发现一编译会发生很多错误。

修改Builde.gradle

1、假如build.gradle中没有配置ndk{ }。那么当编译器在编译的时候将会编译所有平台的so库。而这里只导入了armeabix86的so文件,那么在编译其他的平台的so时,将找不到其他平台so文件而报错。因此需要在build.gradle中配置ndk{ }
如果不在build.gradle中配置ndk{ },那么就需要导入所有平台的so库。

在这个例子中只导入了armeabix86的so文件,如果直接编译将会报错。所以要在build.gradle添加如下代码:

ndk { abiFilters "armeabi","x86"
}

2.这里将so文件配置在了libs文件夹下,因此要在build.gradle中配置:

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

修改后的build.gradle内容如下

android {compileSdkVersion 26buildToolsVersion "27.0.3"defaultConfig {applicationId "com.gxl.change"minSdkVersion 15targetSdkVersion 26versionCode 1versionName "1.0"testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"externalNativeBuild {cmake {cppFlags ""}}ndk {abiFilters "armeabi","x86"}}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'}}externalNativeBuild {cmake {path "CMakeLists.txt"}}sourceSets.main {jniLibs.srcDirs = ['libs']jni.srcDirs = []}
}

修改CMakeLists.txt

由于这里编译需要fmod.so和fmodL.so,我们实现变声的cpp代码就放在native-lib.cpp中,生成的变声.so名称为changeVoice,所以CMakeLists.txt内容如下

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html# Sets the minimum version of CMake required to build the native library.cmake_minimum_required(VERSION 3.4.1)# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
#-----------------------------------------
find_library( log-liblog )set(my_lib_path ${CMAKE_SOURCE_DIR}/libs)# 添加三方的so库
add_library(libfmodSHAREDIMPORTED )# 指名第三方库的绝对路径set_target_properties( libfmodPROPERTIES IMPORTED_LOCATION${my_lib_path}/${ANDROID_ABI}/libfmod.so )add_library(libfmodLSHAREDIMPORTED )set_target_properties( libfmodLPROPERTIES IMPORTED_LOCATION${my_lib_path}/${ANDROID_ABI}/libfmodL.so )set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")#--------------------------------
add_library( # Sets the name of the library.changeVoice# Sets the library as a shared library.SHARED# Provides a relative path to your source file(s).src/main/cpp/native-lib.cpp )# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.#---------------------
# 导入路径,为了让编译时能够寻找到这个文件夹
include_directories(src/main/cpp/inc)# 链接好三个路径
target_link_libraries( changeVoicelibfmodlibfmodL${log-lib} )

可以多看看这个文件,这个文件看多了后就会发现很多c/c++的库在as下运行套路大致相同.

4.实现变声的功能

新建EffectUtils.java文件,通过这个文件来处理变声,代码如下

package com.gxl.change;/*** Created by Administrator on 2018/7/10/010.*/public class EffectUtils {//音效的类型public static final int MODE_NORMAL = 0;//正常public static final int MODE_LUOLI = 1;//萝莉public static final int MODE_DASHU = 2;//大叔public static final int MODE_JINGSONG = 3;//惊悚public static final int MODE_GAOGUAI = 4;//搞怪public static final int MODE_KONGLING = 5;//空灵/*** 变声* @param path 声音路径* @param type 变声类型*/public static native void fix(String path,int type);static{System.loadLibrary("fmodL");System.loadLibrary("fmod");System.loadLibrary("changeVoice");}
}

在android studio 2.2版本以上都可以自动生成头文件到native-lib.cpp中

5.通过c++实现功能

在native-lib中实现逻辑

#include <jni.h>
#include "inc/fmod.hpp"
#include <string>#include <unistd.h>using namespace FMOD;#define MODE_NORMAL 0
#define MODE_LUOLI 1
#define MODE_DASHU 2
#define MODE_JINGSONG 3
#define MODE_GAOGUAI 4
#define MODE_KONGLING 5#include <android/log.h>#define LOGI(FORMAT, ...) __android_log_print(ANDROID_LOG_INFO,"jason",FORMAT,##__VA_ARGS__);
#define LOGE(FORMAT, ...) __android_log_print(ANDROID_LOG_ERROR,"jason",FORMAT,##__VA_ARGS__);extern "C"
JNIEXPORT void JNICALL
Java_com_gxl_change_EffectUtils_fix(JNIEnv *env, jclass cls, jstring path_str, jint type) {//这里很多都是二级指针,但是这里可以通过定义一级指针,下面通过引用来达到同样的效果System * system;Sound * sound;Channel  *channel;DSP *dsp;bool playing= true;float frequency=1;//初始化System_Create(&system);system->init(32, FMOD_INIT_NORMAL, NULL);//将string转成char*const char* path=env->GetStringUTFChars(path_str,NULL);//创建声音system->createSound(path,FMOD_DEFAULT, 0, &sound);try {//根据类型改变声音switch (type) {case MODE_NORMAL://正常声音system->playSound(sound, 0, false, &channel);break;case MODE_LUOLI://萝莉//DSP digital signal process//dsp -> 音效 创建fmod中预定义好的音效//FMOD_DSP_TYPE_PITCHSHIFT dsp,提升或者降低音调用的一种音效system->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsp);//提高音效dsp->setParameterFloat(FMOD_DSP_TYPE_PITCHSHIFT, 2.5);//播放声音system->playSound(sound, 0, false, &channel);//将channel添加到dspchannel->addDSP(0, dsp);break;case MODE_DASHU://大叔system->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsp);//降低声音dsp->setParameterFloat(FMOD_DSP_PITCHSHIFT_PITCH, 0.8);//播放声音system->playSound(sound, 0, false, &channel);//将channel添加到dspchannel->addDSP(0, dsp);break;case MODE_JINGSONG://惊悚system->createDSPByType(FMOD_DSP_TYPE_TREMOLO, &dsp);dsp->setParameterFloat(FMOD_DSP_TREMOLO_SKEW, 0.5);system->playSound(sound, 0, false, &channel);channel->addDSP(0, dsp);break;case MODE_GAOGUAI://搞怪//提高说话的速度system->playSound(sound, 0, false, &channel);//frequency  原来的声音速度channel->getFrequency(&frequency);frequency = frequency * 1.6;channel->setFrequency(frequency);LOGI("%s", "fix gaoguai");break;case MODE_KONGLING://空灵system->createDSPByType(FMOD_DSP_TYPE_ECHO, &dsp);dsp->setParameterFloat(FMOD_DSP_ECHO_DELAY, 300);dsp->setParameterFloat(FMOD_DSP_ECHO_FEEDBACK, 20);system->playSound(sound, 0, false, &channel);channel->addDSP(0, dsp);LOGI("%s", "fix kongling");break;default:break;}}catch (...){//捕捉异常LOGE("%s","发生异常");}system->update();//释放资源//单位是微秒//每秒钟判断下是否在播放while(playing){channel->isPlaying(&playing);usleep(1000 * 1000);}//释放sound->release();system->close();system->release();env->ReleaseStringUTFChars(path_str,path);
}

上面就是关于声音的处理,可以看到套路大致相同,最难的就是改变的音效的调节,如果需要更多音效,自行百度。我也只是将老师讲的例子敲一遍,其中的如何改变成什么样的音效还是不太清楚。可能可以参考源码中的例子吧,可能会有些麻烦.

6.编写界面处理

在MainActivity.java中实现界面的点击事件

public class QQActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);FMOD.init(this);setContentView(R.layout.activity_main);}public void mFix1(View btn) {Toast.makeText(this, "变声", Toast.LENGTH_SHORT).show();String path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separatorChar + "gxl.wav";EffectUtils.fix(path, EffectUtils.MODE_NORMAL);Log.d("jason", "mFix");}public void mFix2(View btn) {Toast.makeText(this, "变声", Toast.LENGTH_SHORT).show();String path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separatorChar + "gxl.wav";EffectUtils.fix(path, EffectUtils.MODE_LUOLI);Log.d("jason", "mFix");}public void mFix3(View btn) {Toast.makeText(this, "变声", Toast.LENGTH_SHORT).show();String path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separatorChar + "gxl.wav";EffectUtils.fix(path, EffectUtils.MODE_DASHU);Log.d("jason", "mFix");}public void mFix4(View btn) {Toast.makeText(this, "变声", Toast.LENGTH_SHORT).show();String path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separatorChar + "gxl.wav";EffectUtils.fix(path, EffectUtils.MODE_JINGSONG);Log.d("jason", "mFix");}public void mFix5(View btn) {Toast.makeText(this, "变声", Toast.LENGTH_SHORT).show();String path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separatorChar + "gxl.wav";EffectUtils.fix(path, EffectUtils.MODE_GAOGUAI);Log.d("jason", "mFix");}public void mFix6(View btn) {Toast.makeText(this, "变声", Toast.LENGTH_SHORT).show();String path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separatorChar + "gxl.wav";EffectUtils.fix(path, EffectUtils.MODE_KONGLING);Log.d("jason", "mFix");}@Overrideprotected void onDestroy() {super.onDestroy();FMOD.close();}}

界面如下
activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent" ><LinearLayoutandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:orientation="vertical"android:background="#FFF"android:paddingBottom="20dp" ><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="horizontal"android:layout_marginTop="20dp"><LinearLayout android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical"><ImageViewandroid:id="@+id/btn_record"style="@style/AudioImgStyle"android:src="@drawable/record"android:onClick="mFix1"/><TextView style="@style/AudioTextStyle"android:text="原声"/></LinearLayout><LinearLayout android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical"><ImageViewandroid:id="@+id/btn_luoli"style="@style/AudioImgStyle"android:src="@drawable/luoli"android:onClick="mFix2"/><TextView style="@style/AudioTextStyle"android:text="萝莉"/></LinearLayout><LinearLayout android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical"><ImageViewandroid:id="@+id/btn_dashu"style="@style/AudioImgStyle"android:src="@drawable/dashu"android:onClick="mFix3"/><TextView style="@style/AudioTextStyle"android:text="大叔"/></LinearLayout></LinearLayout><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="horizontal"android:layout_marginTop="20dp"><LinearLayout android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical"><ImageViewandroid:id="@+id/btn_jingsong"style="@style/AudioImgStyle"android:src="@drawable/jingsong"android:onClick="mFix4"/><TextView style="@style/AudioTextStyle"android:text="惊悚"/></LinearLayout><LinearLayout android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical"><ImageViewandroid:id="@+id/btn_gaoguai"style="@style/AudioImgStyle"android:src="@drawable/gaoguai"android:onClick="mFix5"/><TextView style="@style/AudioTextStyle"android:text="搞怪"/></LinearLayout><LinearLayout android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical"><ImageViewandroid:id="@+id/btn_kongling"style="@style/AudioImgStyle"android:src="@drawable/kongling" android:onClick="mFix6"/><TextView style="@style/AudioTextStyle"android:text="空灵"/></LinearLayout></LinearLayout></LinearLayout></RelativeLayout>

02.使用fmod实现QQ变声效果相关推荐

  1. android fmod,Android利用Fmod仿QQ变声音效

    看到QQ一些变声音效,这些声音效果可以采用SoundTouch,Fmod去处理.这篇文章我们用Fmod去实现变声音效的处理.fmod官网https://www.fmod.com/,fmod Ex 声音 ...

  2. NDK开发——Android Studio+CMake实现QQ变声效果

    项目演示 Github:https://github.com/AndroidHensen/NDKVoice 项目分析 项目采用Fmod开源库,一个非常简单通用的音频引擎,对原始声音进行音效的处理即可做 ...

  3. 08.Eclipse下Ndk开发(使用fmod实现QQ变声功能)

    (创建于2017/12/30) 1.编写native package org.fmod.example;public class EffectUtils {//音效的类型public static f ...

  4. 自学体验使用fmod 以及 仿QQ变声 fmod

    模块一 体验使用fmod 到 https://www.fmod.com/download 上下载fmod android版本的 这里我们用的是别人生成的so库 libfmod.so库 libfmodL ...

  5. 仿QQ变声功能的实现

    Android ndk开发之QQ变声 要做出QQ变声的效果,用Android系统自带的MediaPlayer是无法实现的,只能另想他法了.听说汤姆猫是用SoundTouch实现的,而QQ是用FMOD实 ...

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

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

  7. Web Audio API实现简单变声效果

    前言 想在网页中实现实时音频变声效果该如何实现呢,之前遇到这种处理音视频的需求,可能会想到需要借助C代码实现.但是现在随着浏览器性能的提升.web API的丰富,通过浏览器原生的API也可以操作音频数 ...

  8. NDK开发(四):仿QQ变声

    效果 相关资料:fmod官网https://www.fmod.com/download下载需要的资源库 构建项目 首先构建支持C++的android工程,将需要的c库考入工程 这里只需要inc文件下的 ...

  9. Android NDK开发之旅25 NDK 模仿QQ变声特效

    ###前言 我们这次用到的是fmod这个库,fmod是音效引擎游戏开发革命引擎,著名的游戏开发引擎CosCos2D.U3D都封装了这个库. 学习NDK的目的就是为了让我们的APP能够使用C/C++开源 ...

  10. NDK开发—仿QQ变声器

    1.实现功能前的准备 这是我学习NDK的一个练手项目.虽然最后实现的结果并不是非常专业,但是确实能改变声音的音色,这是非常适合NDK新手的项目. 1.1.主要原理 通过修改声音的属性来实现声音音色的变 ...

最新文章

  1. 微信应用号开发知识贮备之altjs官方实例初探
  2. 16位汇编相关寄存器
  3. 第八节:EF Core连接MySql和Sqlite数据库
  4. MYSQL分页优化查询
  5. 超音速 启动_从根本上讲超音速亚原子Enterprise Java
  6. c# 正则获取html标签内容,c# – 使用正则表达式在多个HTML标记之间获取文本
  7. win10饥荒服务器未响应,win10系统玩饥荒联机很卡如何解决[多图]
  8. php图像处理原生函数,php图像处理函数imagecopyresampled的用法
  9. c开头英文语言,C开头的考研英语词汇
  10. 解决Weblogic与Hibernate的jar冲突
  11. 原生ajax接收json字符串(简单介绍)
  12. idea报错:Lambda expressions are not supported at language level '7'
  13. Oracle P6培训系列:07设置项目详情
  14. 深入理解计算机系统(第三版)家庭作业 第七章
  15. 视频号怎么添加商品带货扩展链接规则
  16. 背景动态星空H5特效源代码
  17. 无盘服务器接几根网线,设置无线路由器需要几根网线_安装路由器需要几根网线?-192路由网...
  18. 起始2021-01-15
  19. (R)机器学习--学习笔记--第四章节学习笔记
  20. linux服务器上的回收站,为linux系统实现回收站

热门文章

  1. keil 生成三角波dac0832_怎么样利用南方CASS三角网法和方格网法进行土方量计算...
  2. 计算机桌面图标变白色,桌面图标变白色文档该怎么办?-电脑自学网
  3. java内存图解_java内存模型及GC原理 和 图解JVM在内存中申请对象及垃圾回收流程...
  4. 多模态知识问答:MMCoQA: Conversational Question Answering over Text, Tables, and Images
  5. 论文-Estimation–Action–Reflection: Towards Deep Interaction Between Conversational and Recommender Sys
  6. 乐嘉首档脱口秀《夜问》开播变身“犀利帝”
  7. 5G学习笔记之NG-RAN系统架构(2)
  8. js检测PDF插件 Adobe Reader是否安装
  9. 基于rrweb框架对web 页面录制与回放
  10. (zotero+坚果云+pdf expert+欧陆词典)实现PC平板同步阅读管理科研文献(完美教程)