文章目录
- Android开发,jni,ndk开发,调用fmod音频库,音效引擎库
- 1.fmod介绍
- 2.cmake
- 3.C++代码实践
Android开发,jni,ndk开发,调用fmod音频库,音效引擎库
1.fmod介绍
https://www.fmod.com/
手机cpu架构指令
2.cmake
作用:把fmod的代码导入到动态库中
导入头文件:
导入库文件:
// Used to load the 'native-lib' library on application startup.
static {
// System.loadLibrary("native-lib");
// libnative-lib.so 包含fmod。才能调用fmod,把fmod集成到libnative-lib.so动态库里面就可以调用了
//apk lib平台libnative-lib.so里面的代码
System.loadLibrary("native-lib");
}
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)
#批量导入所有的cpp文件
file(GLOB allCPP *.c *.h *.cpp)
#导入头文件
include_directories(inc) #相对CMakeLists的路径
#导入库文件,c++环境变量
#CMAKE_SOURCE_DIR CMakeLists的路径
#CMAKE_ANDROID_ARCH 获取手机的四大平台
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/../jniLibs/${CMAKE_ANDROID_ARCH_ABI}")
# 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.
add_library( # Sets the name of the library.
native-lib #//libnative-lib.so的生成
# Sets the library as a shared library.
SHARED #//动态库
# Provides a relative path to your source file(s).
native-lib.cpp #//源文件
${allCPP}
)
# 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.
#日志打印的库
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
# 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.
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
${log-lib}
fmod
fmodL
)
链接库
externalNativeBuild {
cmake {
// cppFlags ""
abiFilters "armeabi-v7a"
}
}
只处理armeabi-v7a平台,ndk下面这个是会把so库编译进apk里
ndk{
abiFilters "armeabi-v7a"
}
3.C++代码实践
资源目录
java代码
public class MainActivity extends AppCompatActivity {
libnative-lib.so 动态库 libnative-lib.a 静态库
static {
// libnative-lib.so 必须包含fmod代码。我们才能调用fmod
System.loadLibrary("native-lib");
}
private String path;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
path = "file:///android_asset/test.mp3";
FMOD.init(this);
}
public void onClick(View view) {
switch (view.getId()) {
case R.id.btn_kongling:
voiceChangeNative(MODE_KONGLING, path);
break;
}
}
private native void voiceChangeNative(int mode, String path);
public native String stringFromJNI();
//jni调用的一个方法
private void playerEnd(String msg) {
Toast.makeText(this, "" +msg, Toast.LENGTH_SHORT).show();
}
@Override
protected void onDestroy() {
super.onDestroy();
FMOD.close();
}
}
导入头文件,可以在fmod官方库获取
hpp后缀 C++,ndk,
声音
Demo JNI
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_voiceChangeNative(JNIEnv *env, jobject thiz, jint mode,
jstring path) {
char * testString = "结束";
//c语言字符串
const char *path1 = env->GetStringUTFChars(path, NULL);
//fmod引擎系统指针
System *system1 = nullptr;
//音效指针
Sound *sound = nullptr;
//音轨指针
Channel *channel = nullptr;
//数字信号处理指针
DSP *dsp = nullptr;
System_Create(&system1);
//初始化
system1->init(20, FMOD_INIT_NORMAL, 0);
//创建声音音轨
system1->createSound(path1, FMOD_DEFAULT, 0, &sound);
system1->playSound(sound, 0, false, &channel);
switch (mode) {
case com_example_myapplication_MainActivity_MODE_NORMAL:
testString = "MODE_NORMAL 播放结束";
break;
case com_example_myapplication_MainActivity_MODE_GAOGUAI:
testString = "MODE_GAOGUAI 播放结束";
//音轨中获取频率
float mFrequency;
channel->getFrequency(&mFrequency);
// 修改 帧率
channel->setFrequency(mFrequency * 1.9f);
break;
case com_example_myapplication_MainActivity_MODE_LUOLI:
testString = "MODE_LUOLI 播放完毕";
//Dsp pitch,创建音调
system1->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsp);
//设置音调
dsp->setParameterFloat(FMOD_DSP_PITCHSHIFT_PITCH, 2.0f);
// 设置音效到音轨里面
channel->addDSP(0, dsp);
break;
}
//监听
bool isPlay = 1;
while (isPlay){
channel->isPlaying(&isPlay);
usleep(1000 * 1000);
}
//
sound->release();
system1->close();
system1->release();
env->ReleaseStringUTFChars(path, path1);
//通知java层的playerEnd函数
jclass mainCls = env->GetObjectClass(thiz);
jmethodID endMethod = env->GetMethodID(mainCls, "playerEnd", "(Ljava/lang/String;)V");
jstring value = env->NewStringUTF(testString);
env->CallVoidMethod(thiz, endMethod, value);
}