概述
这次记录的是NDK的使用实例,使用 fmod 来处理变声。有着上一次 Android NDK的使用实例——增量更新实战 的实践经验,一开始还想着不会特别麻烦。实战以后才发现,连demo也不是简单导入就能够跑起来的,为此也踩了不少坑。这次先记录下如何成功跑起官方的demo。
fmod是什么?这是fmod的官网 https://www.fmod.com。fmod是音效引擎游戏开发革命引擎。很多著名游戏如魔兽都使用到该音效引擎,游戏开发引擎Cocos2D、Unity3D更是直接内置封装了这个库。正如Android也在Library层内置封装了OpenGL ES、SQLite等优秀的库。像fmod这种优秀的C/C++库,有了NDK的支持,自然也可以应用到Android应用程序中,开发类似于QQ变声等功能。
下载官方文件
官网注册后,下载api解压后打开,看到下图所示。这里有一些文档,其实我们只是想要跑Android的demo的话,只需要看到 api/lowlevel 低版本的api里面就能看我们熟悉的一些文件,比如 example/org.fmod.example/MainActivity、libfmod.so库、fmod.jar包等。
如何使用
如何运行这个demo?也查找了很多资料,看了很多文档,而且这种问题简单通俗的资料也不多。文末有参考博客。这里其实是运行了一个播放声音的demo,点击不同的按钮就播放不同的声音。UI操作如下:
新建一个C++ support工程,这里还是使用CMake的方式。既然这里要使用的功能就是播放声音,看下载的文件发现有个 play_sound.cpp 的类,copy进来,编译,随之发现引用到的其他几个头文件、源文件也是需要一起copy进来。最终的软件工程目录是这样的。
需要注意的地方
1、添加权限
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
2、修改 include 路径
因为我们直接copy了整个 inc 文件夹,有几个文件 play_sound.cpp、common.cpp、common.h 就需要修改 include 的路径了
#include "inc/fmod.hpp"
#include "inc/fmod_errors.h"
3、修改JNI方法定义
这里的MainActivity的包名最好保证是 org.fmod.example,要么就到
common_platform.cpp 里面修改相应的方法名,按照JNI的命名规范。
extern "C"
{
jstring Java_org_fmod_example_MainActivity_getButtonLabel(JNIEnv *env, jobject thiz, jint index)
{
return env->NewStringUTF(Common_BtnStr((Common_Button)index));
}
void Java_org_fmod_example_MainActivity_buttonDown(JNIEnv *env, jobject thiz, jint index)
{
gDownButtons |= (1 << index);
}
......
void Java_org_fmod_example_MainActivity_main(JNIEnv *env, jobject thiz)
{
gJNIEnv = env;
gMainActivityObject = thiz;
FMOD_Main();
}
} /* extern "C" */
预编译so库
修改 CMakeLists.txt,这个才是这次记录的重点。因为fmod的很多源代码并没有全部开源出来,很多都是以so库的形式存在fmod.so、fmodL.so里面,因此,我们需要预编译这些so库,不然无法编译通过。
# 设置构建这个so库所需要的最小CMake版本
cmake_minimum_required(VERSION 3.4.1)
# 设置一个变量path_project,后面预编译so库的时候会使用到
set(path_project /document/workandroid/NdkTest6_fmod)
# 添加默认需要生成的so库
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
# 这里最好把相关的cpp源文件都添加进来
src/main/cpp/play_sound.cpp
src/main/cpp/common.cpp
src/main/cpp/common_platform.cpp
src/main/cpp/native-lib.cpp )
# 注意:这里添加两个需要预编译的so库fmod.so、fmodL.so,也就是上面的cpp源文件的部分源代码
# 是在so库里面,并没有全部开源出来,我们要先预编译so库,才能编译通过
add_library(
fmod
SHARED
IMPORTED )
# 设置预编译的so库的路径,这里要使用绝对路径,不然会链接错误,
# 测试了使用相对路径编译通过,但运行崩溃。
set_target_properties(
fmod
PROPERTIES IMPORTED_LOCATION
${path_project}/app/src/main/jniLibs/${ANDROID_ABI}/libfmod.so )
add_library(
fmodL
SHARED
IMPORTED )
set_target_properties(
fmodL
PROPERTIES IMPORTED_LOCATION
${path_project}/app/src/main/jniLibs/${ANDROID_ABI}/libfmodL.so )
# 找到Android内置的log库,用于打印log
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 )
# 这里需要把预编译的so库,链接到默认生成的native-lib.so库中
# 后续System.loadLibrary("native-lib")就可以包含预编译的so库了。
target_link_libraries( # Specifies the target library.
native-lib
fmod
fmodL
# Links the target library to the log library
# included in the NDK.
${log-lib} )
注意:在MainActivity中只需要
System.loadLibrary("native-lib");
就可以,因为在 CMakeLists.txt 已经将预编译的fmod.so、fmodL.so链接到该so库中了。
构建通过,运行demo。
总结
这里再理一下整个过程。首先要知道的是,这个demo提供的是一个播放声音方法。所以需要引入 play_sound.cpp,以及相对应的其他cpp文件、jar包。然后需要将这些文件构建成so库,而构建这个so库要需要其他的so库fmod.so、fmodL.so,这就是涉及到CMake的使用,如何预编译其他依赖的so库。将相关的so库,头文件,源文件都准备好之后,通过CMake构建脚本,就可以构建出目标的so库 native-lib.so,然后就可以执行播放声音了。
下一次将要使用这个库来制作变声效果。
Demo代码已上传至我的 GitHub
感谢
FMOD
Android NDK开发之旅25--NDK--模仿QQ变声特效
Android Studio NDK开发(九):变声特效