Android开发,jni,ndk开发,调用fmod音频库,音效引擎库

文章目录

  • Android开发,jni,ndk开发,调用fmod音频库,音效引擎库
    • 1.fmod介绍
    • 2.cmake
    • 3.C++代码实践

Android开发,jni,ndk开发,调用fmod音频库,音效引擎库

1.fmod介绍

https://www.fmod.com/

手机cpu架构指令

Android开发,jni,ndk开发,调用fmod音频库,音效引擎库_第1张图片

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
        )

链接库

Android开发,jni,ndk开发,调用fmod音频库,音效引擎库_第2张图片

        externalNativeBuild {
            cmake {
//                cppFlags ""
            abiFilters "armeabi-v7a"
            }
        }

只处理armeabi-v7a平台,ndk下面这个是会把so库编译进apk里

ndk{
    
    abiFilters "armeabi-v7a"
}

3.C++代码实践

资源目录

Android开发,jni,ndk开发,调用fmod音频库,音效引擎库_第3张图片

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,

Android开发,jni,ndk开发,调用fmod音频库,音效引擎库_第4张图片

Android开发,jni,ndk开发,调用fmod音频库,音效引擎库_第5张图片

声音

Android开发,jni,ndk开发,调用fmod音频库,音效引擎库_第6张图片

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);
}

你可能感兴趣的:(Android进阶训练营,android,音视频,python)