NDK开发QQ语音变声
一、下载fmod三方引擎sdk
去fmod官网下载Engine -> Android下的sdk
二、定义原生方法
2.1、拷贝sdk
新建AndroidStudio Native工程
1,拷贝sdk的lib包到androidstudio工程的lib目录下,并右键add as library
2,拷贝inc头文件到main/cpp目录下
2.2、绘制页面
在MainActivity的xml中绘制几个按钮如下,ui可以完全自定义。
2.3、定义点击事件
MainActivity定义点击事件如下
class MainActivity : AppCompatActivity() {private lateinit var binding: ActivityMainBindingoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding = ActivityMainBinding.inflate(layoutInflater)setContentView(binding.root)// tempCreateFilePath()}fun tempCreateFilePath() {val file = getExternalFilesDir("/zhanglei.m4a")if (file?.exists() == false) {file.mkdirs()}}fun mFix(btn: View) {val file = getExternalFilesDir("/zhanglei.m4a")val path = file?.path.toString()if (!File(path).exists()) {Toast.makeText(this, "文件不存在", Toast.LENGTH_SHORT).show()return;}lifecycleScope.launch(Dispatchers.IO) {when (btn.id) {R.id.btn_normal -> EffectUtils.fix(path, EffectUtils.MODE_NORMAL)R.id.btn_luoli -> EffectUtils.fix(path, EffectUtils.MODE_LUOLI)R.id.btn_dashu -> EffectUtils.fix(path, EffectUtils.MODE_DASHU)R.id.btn_jingsong -> EffectUtils.fix(path, EffectUtils.MODE_JINGSONG)R.id.btn_gaoguai -> EffectUtils.fix(path, EffectUtils.MODE_GAOGUAI)R.id.btn_kongling -> EffectUtils.fix(path, EffectUtils.MODE_KONGLING)}}}override fun onDestroy() {super.onDestroy()FMOD.close()}
}
2.4、配置kotlin携程
这里用到了携程需要配置Gradle
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.2'
implementation "androidx.activity:activity-ktx:1.1.0"
2.5、抽出Native工具类
定义Native方法fix方法的工具类EffectUtils
object EffectUtils {//音效的类型const val MODE_NORMAL = 0const val MODE_LUOLI = 1const val MODE_DASHU = 2const val MODE_JINGSONG = 3const val MODE_GAOGUAI = 4const val MODE_KONGLING = 5external fun fix(path: String, type: Int)init {System.loadLibrary("qqvoicechange")}
}
2.6、拷贝音频文件到SD卡目录
拷贝一段你录制的音频文件到SD卡app/file/目录下,我这里测试.mp3、.m4a都可以。也可以使用文末demo中的录音文件。
三、实现native方法
3.1、配置CMakeLists.txt文件
cmake_minimum_required(VERSION 3.18.1)project("qqvoicechange")set(libs_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs)add_library(fmodSHAREDIMPORTED)set_target_properties(fmodPROPERTIESIMPORTED_LOCATION ${libs_DIR}/${ANDROID_ABI}/libfmod.so)add_library(fmodLSHAREDIMPORTED)set_target_properties(fmodLPROPERTIESIMPORTED_LOCATION ${libs_DIR}/${ANDROID_ABI}/libfmodL.so)add_library(qqvoicechangeSHAREDnative-lib.cpp)#头文件
target_include_directories(qqvoicechange PRIVATE ./inc/)target_link_libraries(qqvoicechangefmodfmodLlog)
3.2、实现fix方法
#include <jni.h>
#include "inc/fmod.hpp"
#include <unistd.h>#include <android/log.h>#define LOGI(FORMAT, ...) __android_log_print(ANDROID_LOG_INFO,"jason",FORMAT,##__VA_ARGS__);
#define LOGE(FORMAT, ...) __android_log_print(ANDROID_LOG_ERROR,"jason",FORMAT,##__VA_ARGS__);#define MODE_NORMAL 0
#define MODE_LUOLI 1
#define MODE_DASHU 2
#define MODE_JINGSONG 3
#define MODE_GAOGUAI 4
#define MODE_KONGLING 5using namespace FMOD;extern "C"
JNIEXPORT void JNICALL
Java_com_example_qqvoicechange_EffectUtils_fix(JNIEnv *env, jobject thiz, jstring path_jstr,jint type) {const char *path_cstr = env->GetStringUTFChars(path_jstr, nullptr);LOGI("%s", path_cstr);System *system;Sound *sound;Channel *channel;DSP *dsp;float frequency = 0;bool playing = true;try {//初始化System_Create(&system);system->init(32, FMOD_INIT_NORMAL, nullptr);//创建声音system->createSound(path_cstr, FMOD_DEFAULT, nullptr, &sound);switch (type) {//原生播放case MODE_NORMAL:system->playSound(sound, nullptr, false, &channel);LOGI("%s", "fix normal");break;case MODE_LUOLI://萝莉//DSP digital signal process//dsp -> 音效 创建fmod中预定义好的音效//FMOD_DSP_TYPE_PITCHSHIFT dsp,提升或者降低音调用的一种音效system->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsp);//设置音调的参数dsp->setParameterFloat(FMOD_DSP_PITCHSHIFT_PITCH, 2.5);system->playSound(sound, nullptr, false, &channel);//添加到channelchannel->addDSP(0, dsp);LOGI("%s","fix luoli");break;case MODE_DASHU://大叔system->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsp);//设置音调的参数dsp->setParameterFloat(FMOD_DSP_PITCHSHIFT_PITCH, 0.8);system->playSound(sound, nullptr, false, &channel);//添加到channelchannel->addDSP(0, dsp);LOGI("%s","fix dashu");break;case MODE_GAOGUAI://搞怪//提高说话的速度system->playSound(sound, nullptr, false, &channel);channel->getFrequency(&frequency);frequency = frequency * 1.6;channel->setFrequency(frequency);LOGI("%s","fix gaoguai");break;case MODE_KONGLING://空灵system->createDSPByType(FMOD_DSP_TYPE_ECHO, &dsp);dsp->setParameterFloat(FMOD_DSP_ECHO_DELAY, 300);dsp->setParameterFloat(FMOD_DSP_ECHO_FEEDBACK, 20);system->playSound(sound, nullptr, false, &channel);channel->addDSP(0, dsp);LOGI("%s","fix kongling");break;}} catch (...) {LOGE("%s", "发生异常");goto end;}system->update();//单位是微秒//每秒钟判断下是否在播放while (playing) {channel->isPlaying(&playing);usleep(1000 * 1000);}goto end;end://释放资源sound->release();system->close();system->release();env->ReleaseStringUTFChars(path_jstr, path_cstr);
}
四、运行效果
由于博客不支持MP4视频的展示,这里把demo和演示效果压缩放到一块了
NDK开发QQ语音变声相关推荐
- 仿QQ语音变声功能实现
版权声明:转载必须注明本文转自张鹏辉的博客: http://blog.csdn.net/qingtiangg 大家好,这是我从业以来第一篇博客,给大家拜个晚年,祝大家鸡年大吉,幸福美满.事业有成.好了 ...
- Android应用---基于NDK的samples例程hello-jni学习NDK开发
Android应用---基于NDK的samples例程hello-jni学习NDK开发 NDK下载地址:http://developer.android.com/tools/sdk/ndk/index ...
- NDK 开发实战 - 封装 java 层 sdk 模型
关于 Ndk 开发,网上的资料比较少,这方面的书籍也不多.因为其涉及的知识非常广,时常有哥们问我,东西那么多到底要学到什么程度呢?到底应该怎么学?这期我给大家来做一个简单回答,首先单纯站在 Andro ...
- NDK撩妹三部曲(四)—NDK 开发如何优雅的定位 Native 异常,看这篇就够了
NDK 开发如何优雅的定位 Native 异常,看这篇就够了 从何说起? 摘要 案例实操 aaddr2line objdump ndk-stack 1.假设我们已经通过 adb logcat 拿到了程 ...
- Android studio下JNI(NDK)开发
玩智能手机的都说android手机体验.流畅差苹果太远了,一方面是苹果的硬件确实牛逼,另一个原因在于开发语言上的选择,苹果使用了Objective-C来开发,而android使用了java.程序员都知 ...
- ndk开发app!靠这份Android知识点PDF成功跳槽,再不刷题就晚了!
前言 对于android开发,我们大部分工作都是在应用层,但为了体现"技术含量",以及"知其所以然",以便在遇到具体问题时不至于束手无策,因此有必要了解底层的工 ...
- android fmod,Android ndk开发:fmod语音学习(二)
在上一篇文章中,介绍以及搭建了FMOD的Android示例,这篇文章是在上一篇文章的基础上写的.所以建议首先读一下我的这篇文章. 本文使用FMOD来实现变声效果,直接使用<Android ndk ...
- NDK开发 - C/C++ 访问 Java 变量和方法
上一篇有提到 JNI 访问引用数组,涉及了 C/C++ 访问 Java 实例的方法和变量.虽然在之前的开发中,并没有用到 C/C++ 范围 Java 层数据,但是这部分内容还是很有用的. 传送门:ND ...
- android ndk怎样加载o文件_JNI初探之NDK 开发环境配置
安装 CMake.LLDB与NDK 开发工具包 CMake 简介 CMake 是一款比make更强大的编译自动配置工具,它可以根据不同平台.不同的编译器,并通过CMakeLists.txt文件中简单的 ...
最新文章
- div与span区别及用法
- 精通JavaScript攻击框架:AttackAPI
- 23 Refs的应用场景与选用思考
- Gallery with Video
- (软件工程复习核心重点)第一章软件工程概论-第四节:软件过程及相关模型
- mount 需要同时设置 noatime 和 nodiratime 吗?
- Docker Compose如何与SkyEye完美结合
- 8880 e7 v2配什么主板_MATX主板配什么机箱好?曜越Tt启航者A3装机记
- 给浪费时间找种方法?
- matlab中李亚普诺夫方程,李亚普诺夫函数.ppt
- HSpice中的测量语句(I)
- Centos安装Docker的详细安装步骤
- GPU版TensorFlow设置CPU运行的办法
- 在使用firefly的RK3308的SDK使用buildroot构造文件系统时,遇到OEM分区和userdata不能挂在成功的问题
- Codeforces Round #643 (Div. 2) E. Restorer Distance 题解(三分)
- Involution:新神经网络算子(CVPR2021 论文速读)
- 动态链接--打桩机制
- IP 地址与整数之间的互相转换详解
- 优思学院|取得六西格玛黑带经验谈
- 国庆中秋长假游玩攻略:来自汇智人的第一手出行避坑指南