- 前言
本篇只讲解具体的代码实现和环境配置
- 环境配置
开发工具:Android Studio 3.5.3,运行环境,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();
}
配置成功后文件夹如图所示
- 编写工具类,生成相关的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代码,实现功能