文章目录
- 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}fmodfmodL)
链接库
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代码。我们才能调用fmodSystem.loadLibrary("native-lib");}private String path;@Overrideprotected 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();}@Overrideprotected 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);
}