概述
這次記錄的是NDK的使用實(shí)例,使用 fmod 來(lái)處理變聲。有著上一次 Android NDK的使用實(shí)例——增量更新實(shí)戰(zhàn) 的實(shí)踐經(jīng)驗(yàn),一開(kāi)始還想著不會(huì)特別麻煩。實(shí)戰(zhàn)以后才發(fā)現(xiàn),連demo也不是簡(jiǎn)單導(dǎo)入就能夠跑起來(lái)的,為此也踩了不少坑。這次先記錄下如何成功跑起官方的demo。
fmod是什么?這是fmod的官網(wǎng) https://www.fmod.com。fmod是音效引擎游戲開(kāi)發(fā)革命引擎。很多著名游戲如魔獸都使用到該音效引擎,游戲開(kāi)發(fā)引擎Cocos2D、Unity3D更是直接內(nèi)置封裝了這個(gè)庫(kù)。正如Android也在Library層內(nèi)置封裝了OpenGL ES、SQLite等優(yōu)秀的庫(kù)。像fmod這種優(yōu)秀的C/C++庫(kù),有了NDK的支持,自然也可以應(yīng)用到Android應(yīng)用程序中,開(kāi)發(fā)類(lèi)似于QQ變聲等功能。
下載官方文件
官網(wǎng)注冊(cè)后,下載api解壓后打開(kāi),看到下圖所示。這里有一些文檔,其實(shí)我們只是想要跑Android的demo的話,只需要看到 api/lowlevel 低版本的api里面就能看我們熟悉的一些文件,比如 example/org.fmod.example/MainActivity、libfmod.so庫(kù)、fmod.jar包等。
如何使用
如何運(yùn)行這個(gè)demo?也查找了很多資料,看了很多文檔,而且這種問(wèn)題簡(jiǎn)單通俗的資料也不多。文末有參考博客。這里其實(shí)是運(yùn)行了一個(gè)播放聲音的demo,點(diǎn)擊不同的按鈕就播放不同的聲音。UI操作如下:
新建一個(gè)C++ support工程,這里還是使用CMake的方式。既然這里要使用的功能就是播放聲音,看下載的文件發(fā)現(xiàn)有個(gè) play_sound.cpp 的類(lèi),copy進(jìn)來(lái),編譯,隨之發(fā)現(xiàn)引用到的其他幾個(gè)頭文件、源文件也是需要一起copy進(jìn)來(lái)。最終的軟件工程目錄是這樣的。
需要注意的地方
1、添加權(quán)限
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
2、修改 include 路徑
因?yàn)槲覀冎苯觕opy了整個(gè) inc 文件夾,有幾個(gè)文件 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 里面修改相應(yīng)的方法名,按照J(rèn)NI的命名規(guī)范。
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" */
預(yù)編譯so庫(kù)
修改 CMakeLists.txt,這個(gè)才是這次記錄的重點(diǎn)。因?yàn)閒mod的很多源代碼并沒(méi)有全部開(kāi)源出來(lái),很多都是以so庫(kù)的形式存在fmod.so、fmodL.so里面,因此,我們需要預(yù)編譯這些so庫(kù),不然無(wú)法編譯通過(guò)。
# 設(shè)置構(gòu)建這個(gè)so庫(kù)所需要的最小CMake版本
cmake_minimum_required(VERSION 3.4.1)
# 設(shè)置一個(gè)變量path_project,后面預(yù)編譯so庫(kù)的時(shí)候會(huì)使用到
set(path_project /document/workandroid/NdkTest6_fmod)
# 添加默認(rèn)需要生成的so庫(kù)
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).
# 這里最好把相關(guān)的cpp源文件都添加進(jìn)來(lái)
src/main/cpp/play_sound.cpp
src/main/cpp/common.cpp
src/main/cpp/common_platform.cpp
src/main/cpp/native-lib.cpp )
# 注意:這里添加兩個(gè)需要預(yù)編譯的so庫(kù)fmod.so、fmodL.so,也就是上面的cpp源文件的部分源代碼
# 是在so庫(kù)里面,并沒(méi)有全部開(kāi)源出來(lái),我們要先預(yù)編譯so庫(kù),才能編譯通過(guò)
add_library(
fmod
SHARED
IMPORTED )
# 設(shè)置預(yù)編譯的so庫(kù)的路徑,這里要使用絕對(duì)路徑,不然會(huì)鏈接錯(cuò)誤,
# 測(cè)試了使用相對(duì)路徑編譯通過(guò),但運(yùn)行崩潰。
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內(nèi)置的log庫(kù),用于打印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 )
# 這里需要把預(yù)編譯的so庫(kù),鏈接到默認(rèn)生成的native-lib.so庫(kù)中
# 后續(xù)System.loadLibrary("native-lib")就可以包含預(yù)編譯的so庫(kù)了。
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");
就可以,因?yàn)樵?CMakeLists.txt 已經(jīng)將預(yù)編譯的fmod.so、fmodL.so鏈接到該so庫(kù)中了。
構(gòu)建通過(guò),運(yùn)行demo。
總結(jié)
這里再理一下整個(gè)過(guò)程。首先要知道的是,這個(gè)demo提供的是一個(gè)播放聲音方法。所以需要引入 play_sound.cpp,以及相對(duì)應(yīng)的其他cpp文件、jar包。然后需要將這些文件構(gòu)建成so庫(kù),而構(gòu)建這個(gè)so庫(kù)要需要其他的so庫(kù)fmod.so、fmodL.so,這就是涉及到CMake的使用,如何預(yù)編譯其他依賴(lài)的so庫(kù)。將相關(guān)的so庫(kù),頭文件,源文件都準(zhǔn)備好之后,通過(guò)CMake構(gòu)建腳本,就可以構(gòu)建出目標(biāo)的so庫(kù) native-lib.so,然后就可以執(zhí)行播放聲音了。
下一次將要使用這個(gè)庫(kù)來(lái)制作變聲效果。
Demo代碼已上傳至我的 GitHub
感謝
FMOD
Android NDK開(kāi)發(fā)之旅25--NDK--模仿QQ變聲特效
Android Studio NDK開(kāi)發(fā)(九):變聲特效