NDK开发实现QQ变声效果

  • 前言

本篇只讲解具体的代码实现和环境配置

  •  环境配置

开发工具:Android Studio3.4.1,运行环境,Mac,编译工具cmake

  • 下载fmod相关的C++源代码

下载地址:fmod下载地址

  •  新建一个module,配置build.gradle
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
    compileSdkVersion 28


    defaultConfig {
        applicationId "com.lee.jniqqvoice"
        minSdkVersion 15
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                cppFlags "-frtti -fexceptions"
            }
        }
        //ndk编译生成.so文件
        ndk {
            moduleName "qq_voicer"         //生成的so名字
            abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'  //输出指定三种abi体系结构下的so库。
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    externalNativeBuild {
        cmake {
            path file('src/main/cpp/CMakeLists.txt')
        }
    }

}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    implementation files('libs/fmod.jar')
}
//android {
//    compileSdkVersion 28
//    defaultConfig {
//        applicationId "com.github.fmodtest"
//        minSdkVersion 19
//        targetSdkVersion 28
//        versionCode 1
//        versionName "1.0"
//        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
//        externalNativeBuild {
//            cmake {
//                cppFlags "-frtti -fexceptions"
//            }
//        }
//        ndk {
//            abiFilters "arm64-v8a","armeabi-v7a","x86"
//        }
//    }
//    buildTypes {
//        release {
//            minifyEnabled false
//            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
//        }
//    }
//    sourceSets.main {
//        jniLibs.srcDirs = ['libs']
//        jni.srcDirs = []
//    }
//    externalNativeBuild {
//        cmake {
//            path "CMakeLists.txt"
//        }
//    }
//}
  • 在main文件夹下面新建cpp文件夹,创建CMakeLists.txt配置文件,创建native-lib.cpp文件,完成后点击右键

选择Link C++ Project With Gradle,将fmod.jar文件复制到libs文件下面

具体实现如下所示

cmake_minimum_required(VERSION 3.4.1)
set(SOURCES)
file(GLOB_RECURSE SOURCES ${CMAKE_SOURCE_DIR}/*.cpp ${CMAKE_SOURCE_DIR}/*.c)
# 把系统的log库导入进来
find_library( log-lib
        log )

set(distribution_DIR ../../../../libs)

# 把libfmod.so预加载进来
add_library( fmod
        SHARED
        IMPORTED)
set_target_properties( fmod
        PROPERTIES IMPORTED_LOCATION
        ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libfmod.so)

# 把libfmodL.so预加载进来
add_library( fmodL
        SHARED
        IMPORTED)
set_target_properties( fmodL
        PROPERTIES IMPORTED_LOCATION
        ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libfmodL.so)

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


add_library( # Sets the name of the library.
        qq_voicer

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        ${SOURCES})

include_directories(src/main/cpp/inc)

target_link_libraries( qq_voicer
        fmod
        fmodL
        ${log-lib} )

#cmake_minimum_required(VERSION 3.4.1)
#
#
#find_library( # Sets the name of the path variable.
#        log-lib
#        log )
#
#set(distribution_DIR ${CMAKE_SOURCE_DIR}/libs)
#
#add_library( fmod
#        SHARED
#        IMPORTED )
#set_target_properties( fmod
#        PROPERTIES IMPORTED_LOCATION
#        ${distribution_DIR}/${ANDROID_ABI}/libfmod.so )
#add_library( fmodL
#        SHARED
#        IMPORTED )
#set_target_properties( fmodL
#        PROPERTIES IMPORTED_LOCATION
#        ${distribution_DIR}/${ANDROID_ABI}/libfmodL.so )
#add_library( sound
#        SHARED
#        src/main/cpp/sound.cpp )
#
#include_directories(src/main/cpp/inc)
#
#target_link_libraries( sound fmod fmodL
#        ${log-lib} )

#方式二
#cmake_minimum_required(VERSION 3.4.1)
#
## 把系统的log库导入进来
#find_library( log-lib
#        log )
#
#set(distribution_DIR ../../../../libs)
#
## 把libfmod.so预加载进来
#add_library( fmod
#        SHARED
#        IMPORTED)
#set_target_properties( fmod
#        PROPERTIES IMPORTED_LOCATION
#        ${distribution_DIR}/${ANDROID_ABI}/libfmod.so)
#
## 把libfmodL.so预加载进来
#add_library( fmodL
#        SHARED
#        IMPORTED)
#set_target_properties( fmodL
#        PROPERTIES IMPORTED_LOCATION
#        ${distribution_DIR}/${ANDROID_ABI}/libfmodL.so)
#
##set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11"
#
#
#add_library( native-lib
#        SHARED
#        src/main/cpp/native-lib.cpp )
#
#include_directories(src/main/cpp/inc)
#
#target_link_libraries( native-lib
#        fmod
#        fmodL
#        ${log-lib} )

native-lib.cpp的源代码如下所示

#include <jni.h>
#include <string>
#include <cstdlib>
#include <android/log.h>
#include <unistd.h>
#include "inc/fmod.hpp"


//#define LOGI(FORMAT, ...) __android_log_print(ANDROID_LOG_INFO,"hhh",FORMAT,__VA_ARGS_)
//#define LOGE(FORMAT, ...) __android_log_print(ANDROID_LOG_INFO,"hhh",FORMAT,__VA_ARGS_)
using namespace std;
#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__);

//#define MODE_NORMAL 0
#define MODE_NORMAL 0
#define MODE_LUOLI 1
#define MODE_DASHU 2
#define MODE_JINGSONG 3
#define MODE_GAOGUAI 4
#define MODE_KONGLING 5


using namespace FMOD;
extern "C"
JNIEXPORT void JNICALL
Java_com_lee_jniqqvoice_EffectUtils_fix(JNIEnv *env, jclass clazz, jstring path_jstr, jint type) {
//    System *system;
//    Sound *sound;
//    Channel *channel;
//    DSP *dsp;
//
//    //初始化
//    System_Create(&system);
//    system->init(32, FMOD_INIT_NORMAL, nullptr);
//
//    const char *path_cstr = env->GetStringUTFChars(path_jstr, nullptr);
//    //创建声音
//    system->createSound(path_cstr, FMOD_DEFAULT, nullptr, &sound);
//    switch (type) {
//        case MODE_NORMAL:
//            //原生播放
//            LOGI("%s", path_cstr);
//            system->playSound(sound, 0, false, &channel);
//            LOGI("%s", "fix normal");
//
//            break;
//        default:
//            break;
//    }
//    system->update();
//
//    //释放资源,微秒
//    usleep(5*1000*1000);
//    env->ReleaseStringUTFChars(path_jstr, path_cstr);
//
//    sound->release();
//    system->close();
//    system->release();
//声音引擎
    System *system;
    //声音
    Sound *sound;
    //数字处理(音效)
    DSP *dsp;
    //正在播放
    bool playing = true;
    //音乐轨道
    Channel *channel = NULL;
    //播放速度
    float frequency = 0;
    //音频地址
    const char *path_cstr = env->GetStringUTFChars(path_jstr, NULL);

    System_Create(&system);
    system->init(32, FMOD_INIT_NORMAL, NULL);

    try {
        //创建声音
        system->createSound(path_cstr, FMOD_DEFAULT, NULL, &sound);
        switch (type) {
            case MODE_NORMAL:
                //原生播放
                system->playSound(sound, 0, false, &channel);
                break;
            case MODE_LUOLI:
                //提升或者降低音调的一种音效
                system->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsp);
                //设置音调的参数
                dsp->setParameterFloat(FMOD_DSP_PITCHSHIFT_PITCH, 1.8);
                //添加进到channel,添加进轨道
                system->playSound(sound, 0, false, &channel);
                channel->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->addDSP(0, dsp);
                break;
            case MODE_JINGSONG:
                system->createDSPByType(FMOD_DSP_TYPE_TREMOLO, &dsp);
                dsp->setParameterFloat(FMOD_DSP_TREMOLO_SKEW, 0.8);
                system->playSound(sound, 0, false, &channel);
                channel->addDSP(0, dsp);
                break;
            case MODE_GAOGUAI:
                //提高说话的速度
                system->playSound(sound, 0, false, &channel);
                channel->getFrequency(&frequency);
                frequency = frequency * 2;
                channel->setFrequency(frequency);
                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);
                break;
        }
    } catch (...) {
        LOGE("%s", "发生异常");
        goto end;
    }
    system->update();

    //单位是微妙
    //每秒钟判断下是否是播放
    while (playing) {
        channel->isPlaying(&playing);
        usleep(1000);
    }
    goto end;

    //释放资源
    end:
    env->ReleaseStringUTFChars(path_jstr, path_cstr);
    sound->release();
    system->close();
    system->release();
}

配置成功后文件夹如图所示

111

  • 编写工具类,生成相关的native方法
package com.lee.jniqqvoice;

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 native static void fix(String path, int type);

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

}
  • 编写相关的kotlin代码,实现功能
发布了17 篇原创文章 · 获赞 3 · 访问量 5356

猜你喜欢

转载自blog.csdn.net/qq_29342787/article/details/104173405