Android 之 Fmod 变音的实现

一、下载fmod库
二、创建项目(Android Studio)
三、配置项目
四、DEMO开发
五、最后介绍一下 变音参数DPS的类型

一、下载fmod库:官网地址:https://www.fmod.com/

image.png
image.png
image.png

解压完会有4个文件夹,api中是我们所需要用到的


image.png



二、创建项目(Android Studio 版本号 3.5)

1、安装NDK与CMake


image.png

2、创建项目
新建项目,输入项目名称,勾选包含支持c++


image.png

点下一步,直到下面的页面,选择 c++11


image.png

最后 finish

三、项目配置

1、拷贝Lib


image.png
image.png

一定要记得 fmod.jar 右击add

2、拷贝 c库类到 cpp下,如果是选择创建C++库时 会自动在main下面创建出cpp文件夹


image.png
image.png

里边的 changedvoice.cpp 是自己创建的cpp文件,是对声音的改变 。

image.png

主要变音参数都在这里进行参数配置

除了这个文件 还需要一个VoiceTools.h文件 (对C++不是很会,这样做的目的不是很清楚,先照猫画虎的弄上先)

/* DO NOT EDIT THIS FILE - it is machine generated */
#include "../../../../../../../Library/Android/sdk/ndk-bundle/sysroot/usr/include/jni.h"
/* Header for class com_mg_axechen_changevoice_VoiceTools */

#ifndef _Included_com_syido_fmoddemo_changevoice_VoiceTools
#define _Included_com_syido_fmoddemo_changevoice_VoiceTools
#ifdef __cplusplus

extern "C" {
#endif

extern "C" JNIEXPORT void JNICALL Java_com_syido_fmoddemo_changevoice_VoiceTools_changeVoice
  (JNIEnv *, jclass, jstring,jint);

#ifdef __cplusplus
}
#endif
#endif

以上两个文件一定要注意 包名与路径名的对应,否则在调用时无法找到方法(JNI基础)
JNIEXPORT void JNICALL Java_com_syido_fmoddemo_changevoice_VoiceTools_changeVoice
代表 changeVoice方法所在类的路径


image.png

3、配置gradle文件 主要就是对cmake的配置。只有它配置对了,NDK才可以正常使用changeVoice.cpp才能正确编译。具体百度CMAKE为何物。


image.png

配置完gradle,回来配置cmake,如果在SDK Tools中正确安装了cmake 会在目录下生成cmake.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)

find_library( log-lib
              log )

set(my_lib_path ${CMAKE_SOURCE_DIR}/libs)

# 添加三方的so库
add_library(libfmod
            SHARED
            IMPORTED )
# 指名第三方库的绝对路径
set_target_properties( libfmod
                       PROPERTIES IMPORTED_LOCATION
                       ${my_lib_path}/${ANDROID_ABI}/libfmod.so )

add_library(libfmodL
            SHARED
            IMPORTED )

set_target_properties( libfmodL
                       PROPERTIES IMPORTED_LOCATION
                       ${my_lib_path}/${ANDROID_ABI}/libfmodL.so )

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")

# 添加我们需要写代码的路径
add_library(changeVoice
            SHARED
            src/main/cpp/changeVoice.cpp )

# 导入路径,为了让编译时能够寻找到这个文件夹
include_directories(src/main/cpp/inc)

# 链接好三个路径
target_link_libraries( changeVoice
                       libfmod
                       libfmodL

                       ${log-lib} )

四、DEMO开发

1、创建JAVA变音工具类,添加加载动态库代码,添加native方法。

/**
 * Created by Wilbur on 2020/02/18
 */

public class VoiceTools {
    public static final int BAIDU_BOY = 19;

    public static final int BAIDU_GIRL = 18;

    public static final int BAIDU_MENGMEI = 20;

    public static final int BAIDU_XIAOGEGE = 21;

    public static final int MODE_BOY = 8;

    public static final int MODE_CHORUS = 15;

    public static final int MODE_CLASSROOM = 10;

    public static final int MODE_CUSTOM = 9;

    public static final int MODE_DASHU = 2;

    public static final int MODE_DISTORTION = 16;

    public static final int MODE_GAOGUAI = 4;

    public static final int MODE_HALL = 7;

    public static final int MODE_JINGSONG = 3;

    public static final int MODE_KONGLING = 5;

    public static final int MODE_LIVEPERFORMANCE = 12;

    public static final int MODE_LUOLI = 1;

    public static final int MODE_MACHINE = 17;

    public static final int MODE_MINIONS = 13;

    public static final int MODE_NORMAL = 0;

    public static final int MODE_NVSHENG = 11;

    public static final int MODE_SLOWLY = 14;

    public static final int MODE_VALLEY = 6;


    public static native void  changeVoice(String path, int mode);

    static {
        System.loadLibrary("changeVoice");
        System.loadLibrary("fmod");
        System.loadLibrary("fmodL");
    }

}

使用方法

public void startChange(View view) {
        String path = Environment.getExternalStorageDirectory().getPath()+ File.separator+"voice.wav";
        Log.i("getPath",path);
        File file = new File(path);
        if (!file.exists()) {
            Log.e("Main", "没有文件");
            return;
        }
        switch (view.getId()) {
            // 普通
            case R.id.btn_normal:
                VoiceTools.changeVoice(path, VoiceTools.MODE_NORMAL);
                break;
            // 萝莉
            case R.id.btn_luoli:
                VoiceTools.changeVoice(path, VoiceTools.MODE_LUOLI);
                break;
            // 大叔
            case R.id.btn_dashu:
                VoiceTools.changeVoice(path, VoiceTools.MODE_DASHU);
                break;
            // 惊悚
            case R.id.btn_jingsong:
                VoiceTools.changeVoice(path, VoiceTools.MODE_JINGSONG);
                break;
            // 搞怪
            case R.id.btn_gaoguai:
                VoiceTools.changeVoice(path, VoiceTools.MODE_GAOGUAI);
                break;
            // 空灵
            case R.id.btn_kongling:
                VoiceTools.changeVoice(path, VoiceTools.MODE_KONGLING);
                break;
            // 山谷
            case R.id.btn_shangu:
                VoiceTools.changeVoice(path, VoiceTools.MODE_VALLEY);
                break;
            // 大堂
            case R.id.btn_datang:
                VoiceTools.changeVoice(path, VoiceTools.MODE_HALL);
                break;
            // 男生
            case R.id.btn_nansheng:
                VoiceTools.changeVoice(path, VoiceTools.MODE_BOY);
                break;



五、最后介绍一下 变音参数DPS的类型

typedef enum
{
    FMOD_DSP_TYPE_UNKNOWN, // 不知类型
    FMOD_DSP_TYPE_MIXER,   //不需要任何输入,并将它们混合在一起
    FMOD_DSP_TYPE_OSCILLATOR,   //振荡器 
    FMOD_DSP_TYPE_LOWPASS,    //低通滤波
    FMOD_DSP_TYPE_ITLOWPASS,   //特低通滤波
    FMOD_DSP_TYPE_HIGHPASS, //高通滤波
    FMOD_DSP_TYPE_ECHO,    //回声
    FMOD_DSP_TYPE_FADER,   //衰减器
    FMOD_DSP_TYPE_FLANGE,   //轮缘  对声音产生法兰效应
    FMOD_DSP_TYPE_DISTORTION, //扭曲
    FMOD_DSP_TYPE_NORMALIZE,   //归一化
    FMOD_DSP_TYPE_LIMITER,    //限幅器
    FMOD_DSP_TYPE_PARAMEQ,   //参数化
    FMOD_DSP_TYPE_PITCHSHIFT,   //频移
    FMOD_DSP_TYPE_CHORUS,     //合唱
    FMOD_DSP_TYPE_VSTPLUGIN,
    FMOD_DSP_TYPE_WINAMPPLUGIN, //温普拉普林
    FMOD_DSP_TYPE_ITECHO,    //特回声
    FMOD_DSP_TYPE_COMPRESSOR,    //压缩机
    FMOD_DSP_TYPE_SFXREVERB,   //SFX混响器
    FMOD_DSP_TYPE_LOWPASS_SIMPLE,  //低通简单
    FMOD_DSP_TYPE_DELAY,     //延迟
    FMOD_DSP_TYPE_TREMOLO,    //颤音
    FMOD_DSP_TYPE_LADSPAPLUGIN,    //拉斯帕拉金/
    FMOD_DSP_TYPE_SEND, 
    FMOD_DSP_TYPE_RETURN,
    FMOD_DSP_TYPE_HIGHPASS_SIMPLE,//高通简单
    FMOD_DSP_TYPE_PAN,
    FMOD_DSP_TYPE_THREE_EQ,   //三重均衡器
    FMOD_DSP_TYPE_FFT,     //快速傅立叶变换
    FMOD_DSP_TYPE_LOUDNESS_METER,   //劳氏流量计
    FMOD_DSP_TYPE_ENVELOPEFOLLOWER,
    FMOD_DSP_TYPE_CONVOLUTIONREVERB,   //卷积混响
    FMOD_DSP_TYPE_CHANNELMIX,    //通道混合
    FMOD_DSP_TYPE_TRANSCEIVER,
    FMOD_DSP_TYPE_OBJECTPAN,
    FMOD_DSP_TYPE_MULTIBAND_EQ,   //多频带EQ

    FMOD_DSP_TYPE_MAX,
    FMOD_DSP_TYPE_FORCEINT = 65536    /* Makes sure this enum is signed 32bit. */
} FMOD_DSP_TYPE;





以下是变音参数 并不专业 也只能仅供参考:

1.萝莉
system->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsp);
dsp->setParameterFloat(FMOD_DSP_PITCHSHIFT_PITCH, 300.0);
dsp->setParameterFloat(FMOD_DSP_PITCHSHIFT_PITCH, 2.5);
system->playSound(sound, 0, false, &channel);
channel->addDSP(0, dsp);
channel->setVolume (0, 12.0);


2.大叔
system->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsp);
dsp->setParameterFloat(FMOD_DSP_PITCHSHIFT_PITCH, 2.5);
system->playSound(sound, 0, false, &channel);
channel->addDSP(0, dsp);
float frequency = 0;
channel-> getFrequency (0, &frequency);
frequency = frequency * 0.855;
channel-> setFrequency (0, frequency);
channel->setVolume (0, 12.0);

3.惊悚
system->createDSPByType(FMOD_DSP_TYPE_FLANGE, &dsp);
dsp->setParameterFloat(FMOD_DSP_FLANGE_MIX, 100.0);
dsp->setParameterFloat(FMOD_DSP_FLANGE_DEPTH, 1.0);
dsp->setParameterFloat(FMOD_DSP_FLANGE_RATE, 6.0);
system->playSound(sound, 0, false, &channel);
channel->addDSP(0, dsp);
float frequency = 0;
channel-> getFrequency (0, &frequency);
frequency = frequency * 0.7;
channel-> setFrequency (0, frequency);
channel->setVolume (0, 5.0);

4.搞怪
system->playSound(sound, 0, false, &channel);
float frequency = 0;
channel-> getFrequency (0, &frequency);
frequency = frequency * 2;
channel-> setFrequency (0, frequency);
channel->setVolume (0, 12.0);

5.空灵
system->createDSPByType(FMOD_DSP_TYPE_ECHO, &dsp);
dsp->setParameterFloat(FMOD_DSP_ECHO_DELAY, 300.0);
dsp->setParameterFloat(FMOD_DSP_ECHO_FEEDBACK, 20.0);
system->playSound(sound, 0, false, &channel);
channel->addDSP(0, dsp);
channel->setVolume (0, 12.0);

6.山谷
system->createDSPByType(FMOD_DSP_TYPE_ECHO, &dsp);
dsp->setParameterFloat(FMOD_DSP_ECHO_DELAY, 500.0);
dsp->setParameterFloat(FMOD_DSP_ECHO_FEEDBACK, 22.0);
dsp->setParameterFloat(FMOD_DSP_ECHO_WETLEVEL, -15.0);
system->playSound(sound, 0, false, &channel);
channel->addDSP(0, dsp);
channel->setVolume (0, 12.0);

7.大堂
system->createDSPByType(FMOD_DSP_TYPE_TREMOLO, &dsp);
dsp->setParameterFloat(FMOD_DSP_TREMOLO_FREQUENCY, 20.0);
dsp->setParameterFloat(FMOD_DSP_TREMOLO_SKEW, 0.7);
system->playSound(sound, 0, false, &channel);
channel->addDSP(0, dsp);
system->createDSPByType(FMOD_DSP_TYPE_SFXREVERB, &dsp);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_DECAYTIME, 4300.0);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_EARLYDELAY, 20.0);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_LATEDELAY, 40.0);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_HFREFERENCE, 5000.0);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_HFDECAYRATIO, 59.0);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_DIFFUSION, 100.0);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_DENSITY, 100.0);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_LOWSHELFFREQUENCY, 250.0);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_LOWSHELFGAIN, 0.0);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_HIGHCUT, 5850.0);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_EARLYLATEMIX, 64.0);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_WETLEVEL, -11.7);
system->playSound(sound, 0, false, &channel);
channel->addDSP(0, dsp);
channel->setVolume (0, 12.0);

8.男生
system->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsp);
dsp->setParameterFloat(FMOD_DSP_PITCHSHIFT_PITCH, 0.7888);
system->playSound(sound, 0, false, &channel);
channel->addDSP(0, dsp);
channel->setVolume (0, 12.0);


10.教室
system->createDSPByType(FMOD_DSP_TYPE_SFXREVERB, &dsp);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_DECAYTIME, 400.0);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_EARLYDELAY, 2.0);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_LATEDELAY, 3.0);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_HFREFERENCE, 5000.0);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_HFDECAYRATIO, 83.0);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_DIFFUSION, 100.0);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_DENSITY, 100.0);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_LOWSHELFFREQUENCY, 250.0);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_LOWSHELFGAIN, 0.0);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_HIGHCUT, 6050.0);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_EARLYLATEMIX, 88.0);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_WETLEVEL, -9.4);
system->playSound(sound, 0, false, &channel);
channel->addDSP(0, dsp);
channel->setVolume (0, 12.0);

11.女声
system->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsp);
dsp->setParameterFloat(FMOD_DSP_PITCHSHIFT_PITCH, 1.55); 
system->playSound(sound, 0, false, &channel);
channel->addDSP(0, dsp);
channel->setVolume (0, 12.0);

12.强电流
system->createDSPByType(FMOD_DSP_TYPE_SFXREVERB, &dsp);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_DECAYTIME, 3900.0);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_EARLYDELAY, 20.0);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_LATEDELAY, 29.0);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_HFREFERENCE, 5000.0);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_HFDECAYRATIO, 70.0);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_DIFFUSION, 100.0);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_DENSITY, 100.0);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_LOWSHELFFREQUENCY, 250.0);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_LOWSHELFGAIN, 0.0);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_HIGHCUT, 5650.0);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_EARLYLATEMIX, 80.0);
dsp->setParameterFloat(FMOD_DSP_SFXREVERB_WETLEVEL, -9.8);
system->playSound(sound, 0, false, &channel);
channel->addDSP(0, dsp);
channel->setVolume (0, 12.0);

13.小黄人
system->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsp);
dsp->setParameterFloat(FMOD_DSP_PITCHSHIFT_PITCH, 1.8);
system->playSound(sound, 0, false, &channel);
channel->addDSP(0, dsp);
float frequency = 0;
channel-> getFrequency (0, &frequency);
frequency = frequency * 1.2;
channel-> setFrequency (0, frequency);
channel->setVolume (0, 12.0);

14.慢吞吞
system->playSound(sound, 0, false, &channel);
float frequency = 0;
channel-> getFrequency (0, &frequency);
frequency = frequency * 0.5;
channel-> setFrequency (0, frequency);
channel->setVolume (0, 12.0);

15.现场
system->createDSPByType(FMOD_DSP_TYPE_CHORUS, &dsp);
dsp->setParameterFloat(FMOD_DSP_CHORUS_DEPTH, 20.0);
dsp->setParameterFloat(FMOD_DSP_CHORUS_RATE, 10.0);
system->playSound(sound, 0, false, &channel);
channel->addDSP(0, dsp);
channel->setVolume (0, 12.0);

17.外国人
system->createDSPByType(FMOD_DSP_TYPE_FLANGE, &dsp);
dsp->setParameterFloat(FMOD_DSP_FLANGE_MIX, 100.0);
dsp->setParameterFloat(FMOD_DSP_FLANGE_DEPTH, 1.0);
dsp->setParameterFloat(FMOD_DSP_FLANGE_RATE, 4.0);
system->playSound(sound, 0, false, &channel);
channel->addDSP(0, dsp);
channel->setVolume (0, 5.0);
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容