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架构指令

在这里插入图片描述

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/294115.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

前端常用的几种算法的特征、复杂度、分类及用法示例演示

算法(Algorithm)可以理解为有基本运算及规定的运算顺序所构成的完整的解题步骤,或者看成按照要求设计好的有限的确切的计算序列,并且这样的步骤和序列可以解决一类问题。算法代表着用系统的方法描述解决问题的策略机制&#xff0c…

两整数之和 -- 位运算

个人主页:Lei宝啊 愿所有美好如期而遇 本题链接 力扣(LeetCode) 输入描述 输入两个要相加的数,a和b 输出描述 返回a和b的和,这里其实直接return ab; 直接就过了,但是人题目要求还是给点面子~ 算法…

mariadb实现主从同步

准备两台服务器 Mariadb-Master:192.168.44.150 Mariadb-Backup:192.168.44.148 安装mariadb: https://blog.csdn.net/qq_50247813/article/details/135402502?spm1001.2014.3001.5502 组从复制原理如下 修改主数据库配置如下 vi /etc/my.…

钼铁,需求量将推动市场进入新一轮发展浪潮

钼铁是一种重要的冶金原料,广泛用于制造高速钢、不锈钢、合金钢、特殊钢等钢材,并且被广泛应用于核工业、电子工业、航空航天等高技术产业领域。随着钢铁市场的不断发展,钼铁市场也逐渐壮大,下面将从全球市场和中国市场分析其发展…

自学 c++ 要掌握哪些技巧和方法?

自学 c 要掌握哪些技巧和方法? 在开始前我有一些资料,是我根据网友给的问题精心整理了一份「C的资料从专业入门到高级教程」, 点个关注在评论区回复“888”之后私信回复“888”,全部无偿共享给大家!!&…

大模型在现代应用中的多元实例

目录 前言1 GPT-3、GPT-3.5、GPT-4:自然语言处理的新纪元1.1 GPT-3与传统NLP方法的区别1.2 GPT-3.5 和 GPT-4 的进展1.3 技术背后的革新 2 自然语言转换为Python代码2.1 简介2.2 技术原理2.3 应用和优势 3 DALL-E 2(5B)图像生成3.1 简介3.2 技…

LauraGPT

git:https://github.com/alibaba-damo-academy/FunCodec 文章目录 model archAudioTokenizermodel init model arch text-embedding 用千问的模型参数初始化;AudioEncoder用asr-conformer的参数初始化;所有的参数都参与更新,除了C…

【动态规划】C++算法:115.不同的子序列

作者推荐 【动态规划】【字符串】扰乱字符串 本文涉及的基础知识点 动态规划 LeetCode115 不同的子序列 给你两个字符串 s 和 t ,统计并返回在 s 的 子序列 中 t 出现的个数,结果需要对 109 7 取模。 示例 1: 输入:s “rab…

如何让CHAT使用python绘制概率密度图像?

问CHAT:用python绘制概率密度图像 CHAT回复:你可以使用Python的matplotlib库和numpy库进行概率密度的绘制。 以下是一个简单的例子: python import numpy as np import matplotlib.pyplot as plt #随机生成1000个正态分布的数 data np.rand…

无法开机报 不可恢复的错误:securityagent无法创建所要求的机制Teamviewerauthplugin:start

无法开机报 不可恢复的错误:securityagent无法创建所要求的机制Teamviewerauthplugin:start 初步判断很有可能是TeamViewer的某个启动项或者签名书没有, 导致在预加载的时候无法加载TeamViewer。 然后出现这个情况有一个前提,那就是你用了第三…

Linux_CentOS_7.9配置时区及NTPdate同步之简易记录

前言:ntpdate命令来自英文词组”NTPdate“的拼写,其功能是用于设置日期和时间。ntpdate命令能够基于NTP协议设置Linux系统的本地日期和时间,利用NTP服务的时钟过滤器来选择最优方案,大大提高了可靠性和精度,让系统时间…

【RabbitMQ】1 消息中间件MQ概述

目录 什么是消息中间件为什么使用消息中间件流量削峰应用解耦异步处理 主流消息中间件及选型选取原则RabbitMQRocketMQKafka如何选择 消息中间件应用场景电商秒杀案例拉勾B端C端数据同步案例支付宝购买电影票 什么是消息中间件 维基百科对消息中间件的解释:面向消息…

宽压输入1.5KV隔离直流高压输出电源模块

GRC系列低成本小体积宽电压输入隔离高压模块电源,是一款业界的隔离稳压型DC-DC高电压转换器,可在宽范围波动的不稳定电压输入环境中运行,通过模块的内部调整电路可以生成隔离稳压的直流高电压输出。产品外壳采用铝壳喷塑防腐设计,…

栈的数据结构实验报告

一、实验目的: 1、理解栈的定义; 2、利用栈处理实际问题。 二、实验内容(实验题目与说明) 利用栈实现数据的分类,将输入的整数以奇偶为标准分别存放到两个栈中,并最终从栈1和栈2输出偶数和奇数序列。 …

如何培养学生的创造性思维

在当下这个时代,创造力的重要性不言而喻。如何在日常教育中潜移默化地培养孩子的创造性思维呢? 一、激发好奇心,让思维自由飞翔 孩子天生就有一颗好奇的心,作为老师,要鼓励他们提问,鼓励他们去探索。好奇…

风车模型与代码

这个模型使用NetLogo乌龟来重复绘制圆圈,定期转动,以便显示出类似万花筒或风车的效果。这是一个演示,展示了一组简单的代理规则如何产生复杂而美丽的图案。 内部工作原理非常简单。创建了许多乌龟,它们的笔都是放下的&#xff08…

电子化学品,预计2025年会增长到4302亿美元

电子化学品市场是一个庞大的细分市场,它包括了广泛的化学品种类,如涂料、塑料、精细化学品、农药和医药等。这个市场的发展相当迅速,下面我们将从全球市场和中国市场两个方面对其发展趋势进行分析。全球市场分析: 从全球市场的角度…

【HBase】——优化

1 RowKey设计 重要:一条数据的唯一标识就是 rowkey,那么这条数据存储于哪个分区,取决于 rowkey 处于 哪个一个预分区的区间内,设计 rowkey的主要目的 ,就是让数据均匀的分布于所有的 region 中,在一定程度…

Java重修第二天—学习”方法“

通过学习本篇文章可以掌握如下知识 1、方法的定义 2、方法在计算机中的执行流程。 3、方法使用时常见问题 4、Java中方法的参数传递机制 5、方法重载 1 方法是什么 方法是一种语法结构,它可以把一段代码实现的某种功能封装起来,以便重复利用。 方…

杰发科技AC7801——IO模拟IIC注意事项

7801的参考手册没有说清楚 7840说明了用开漏 使用办法