以导入fmod为例
fmod官网:https://www.fmod.com/
fmod包下载:https://share.weiyun.com/1KtqEUlA
(头文件:api\lowlevel\inc下、库文件:api\lowlevel\lib下)
创建一个空项目
配置ndk路径
导入fmod的头文件
把inc整个目录(头文件:api\lowlevel\inc)拷贝到项目的 \app\src\main\cpp 下
include_directories("inc")
批量导入源文件
默认是只导入native-lib.cpp,可以继续追加一些源文件,但避免遗漏,批量导入
add_library(
native-lib
SHARED
native-lib.cpp)
批量导入:
file(GLOB allCPP *.c *.h *.cpp)
add_library(
native-lib
SHARED
${allCPP})
导入fmod的库文件
在目录 \app\src\main 下创建 jniLibs 目录
将fmod文件中的api\lowlevel\lib 下的cpu架构拷贝到jniLibs目录下
# 导入库文件
# CMAKE_SOURCE_DIR 等于 CMakeLists.txt所在的地址目录
# CMAKE_ANDROID_ARCH_ABI 等于 当前手机的CPU架构
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/../jniLibs/${CMAKE_ANDROID_ARCH_ABI}")
链接具体的库
默认是 这样设置了别名再链接,像这里的 log ,对应的就是
C:\xxxxxx\Android\Sdk\ndk\20.0.5594570\platforms\android-23\arch-arm64\usr\lib\liblog.so
即,刚开始配置ndk的路径下的
find_library(
log-lib
log)
target_link_libraries(
native-lib
${log-lib})
修改成如下:
target_link_libraries(
native-lib
log
fmod
fmodL
)
导入fmod.jar
将fmod中 api\core\lib\fmod.jar导入
// 导入fmod.jar
implementation files("libs\\fmod.jar")
生成头文件
MainActivity.java
private static final int MODE_NORMAL = 0;
private static final int MODE_LUOLI = 1;
private static final int MODE_DASHU = 2;
private static final int MODE_JINGSONG = 3;
private static final int MODE_GAOGUAI = 4;
private static final int MODE_KONGLING = 5;
String path;
static {
System.loadLibrary("native-lib");
}
private void playerEnd(String msg){
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
private native void voiceChange(int mode, String path);
在目录 app\src\main\java 下执行: javah com.example.fmod_test.MainActivity
将头文件放到 \app\src\main\cpp 下
导入fmod的头文件
实现文件 native-lib.cpp
#include <unistd.h>
#include "com_example_fmod_test_MainActivity.h"
extern "C" JNIEXPORT void JNICALL Java_com_example_fmod_1test_MainActivity_voiceChange
(JNIEnv * env, jobject thiz, jint mode, jstring path){
const char * path_ = env->GetStringUTFChars(path, NULL);
// FMOD
FMOD::System * system = 0; // 音效引擎
FMOD::Sound * sound = 0; // 声音
FMOD::Channel * channel = 0; // 通道
FMOD::DSP * dsp = 0; // DSP digital signal process 数字信号处理
FMOD::System_Create(&system); // 创建系统
system->init(32,FMOD_INIT_NORMAL, 0); // 系统的初始化
system->createSound(path_, FMOD_DEFAULT, 0, &sound);// 创建声音
system->playSound(sound, 0, false, &channel); // 播放
switch (mode) {
case com_example_fmod_test_MainActivity_MODE_NORMAL:
break;
case com_example_fmod_test_MainActivity_MODE_LUOLI:
system->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsp);
dsp->setParameterFloat(FMOD_DSP_PITCHSHIFT_PITCH, 2.0f);
channel->addDSP(0, dsp);
break;
case com_example_fmod_test_MainActivity_MODE_DASHU:
system->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsp);
dsp->setParameterFloat(FMOD_DSP_PITCHSHIFT_PITCH, 0.7f);
channel->addDSP(0, dsp);
break;
case com_example_fmod_test_MainActivity_MODE_GAOGUAI:
float mFrequency;
channel->getFrequency(&mFrequency);
channel->setFrequency(mFrequency * 1.5f);
break;
case com_example_fmod_test_MainActivity_MODE_KONGLING:
system->createDSPByType(FMOD_DSP_TYPE_ECHO, &dsp);
dsp->setParameterFloat(FMOD_DSP_ECHO_DELAY, 200);
dsp->setParameterFloat(FMOD_DSP_ECHO_FEEDBACK, 10);
channel->addDSP(0, dsp);
break;
case com_example_fmod_test_MainActivity_MODE_JINGSONG:
system->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsp);
dsp->setParameterFloat(FMOD_DSP_PITCHSHIFT_PITCH, 0.7f);
channel->addDSP(0, dsp);
system->createDSPByType(FMOD_DSP_TYPE_ECHO, &dsp);
dsp->setParameterFloat(FMOD_DSP_ECHO_DELAY, 200);
dsp->setParameterFloat(FMOD_DSP_ECHO_FEEDBACK, 10);
channel->addDSP(1, dsp);
system->createDSPByType(FMOD_DSP_TYPE_TREMOLO, &dsp);
dsp->setParameterFloat(FMOD_DSP_TREMOLO_FREQUENCY, 20);
dsp->setParameterFloat(FMOD_DSP_TREMOLO_SKEW, 0.8f);
channel->addDSP(2, dsp);
break;
}
bool isPlayer = true;
while (isPlayer) {
channel->isPlaying(&isPlayer);
usleep(1000 * 1000);
}
// 释放
sound->release();
system->close();
system->release();
env->ReleaseStringUTFChars(path, path_);
// 调用java的方法
jclass cls = env->GetObjectClass(thiz);
jmethodID playerEndMethod = env->GetMethodID(cls, "playerEnd", "(Ljava/lang/String;)V");
jstring msg = env->NewStringUTF("播放完毕");
env->CallVoidMethod(thiz, playerEndMethod, msg);
}
遗留问题:通过 fmod 播放完mp3文件后,会延迟一段时间isPlaying才返回false,不知道什么原因!