当前位置: 首页 > news >正文

NDK JNI 变声器实现

Android NDK 导入 C库的开发流程学习;通过使用fmod的C库,实现变声器功能。

  1. 导入库文件

1)复制fmod的C库到cpp目录下

2)复制fmod的so库到jniLibs目录下

3)复制fmod的jar库到libs目录下

4)将声音文件复制到assets目录下

fmod库文件资源:https://wwgl.lanzout.com/ilXHP0pn7f4f

  1. 打开CMakeLists.txt导入fmod库文件

cmake_minimum_required(VERSION 3.10.2) # 最低支持的CMake版本project("whine")# TODO 第一步 导入头文件(fmod库)
include_directories("inc")# 批量导入所有文件
file(GLOB allCPP *.c *.h *.cpp)add_library(native-lib # 打包出来库的名称 libnative-lib.soSHARED # 动态库${allCPP} # 添加所有库文件
)# TODO 第二步 导入库文件(fmod库)
# ${CMAKE_CXX_FLAGS} 原先的CMake环境 +
# -L${CMAKE_SOURCE_DIR}/../jniLibs/${CMAKE_ANDROID_ARCH_ABI} 加上新的fmod库的路径
# CMAKE_SOURCE_DIR == CMakeLists.txt所在的路径
# /../ 回退到cpp目录
# jniLibs/ 进入jniLibs目录
# ${CMAKE_ANDROID_ARCH_ABI} 使用当前手机CPU系统结构对应的库 如:arm64-v8a
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/../jniLibs/${CMAKE_ANDROID_ARCH_ABI}")find_library(log-liblog # 自动寻找log库
)# TODO 第三步 链接具体的库,到 libnative-lib.so总库
target_link_libraries(native-lib${log-lib}fmod # 具体的库 链接到 libnative-lib.so里面去fmodL # 具体的库 链接到 libnative-lib.so里面去
)
  1. 打开build.gradle,指定CPU架构和依赖fmod的jar包

defaultConfig {// TODO 第四步externalNativeBuild {cmake {// cppFlags "" // 默认五大平台// 指定CPU架构,Cmake的本地库, 例如:native-lib ---> arm64-v8aabiFilters "arm64-v8a"}}// TODO 第五步// 指定CPU架构,打入APK lib/CPU平台ndk {abiFilters "arm64-v8a"}
}dependencies {// TODO 第六步:依赖fmod的jar包implementation files("libs\\fmod.jar");
}
  1. 准备工作完成,开始编写Activity代码

1)定义变声模式

/*** 定义变声模式* 0 正常; 1 萝莉; 2 大叔; 3 惊悚; 4 搞怪; 5 回声;*/
private static final int MODE_NORMAL = 0;
private static final int MODE_LUOLI = 1;
private static final int MODE_DASHU = 2;
private static final int MODE_JINGSONG = 3;
private static final int MODE_GAOGUAI = 4;
private static final int MODE_KONGLING = 5;

2)加载编译后的lib库

static {System.loadLibrary("native-lib");
}

3)初始化fmod.jar库,并在页面关闭的时候释放

@Override
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);FMOD.init(this);
}@Override
protected void onDestroy() {super.onDestroy();FMOD.close();
}

4)编写变声native层方法和变声结束后提供native调用的方法

public native void voiceChangeNative(int modeNormal, String path);private void playerEnd(String msg) {isPlaying = false;runOnUiThread(() -> Toast.makeText(this, msg, Toast.LENGTH_SHORT).show());
}

5)Activity完整代码

package com.whine;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;
import android.view.View;
import android.widget.Toast;import org.fmod.FMOD;/*** TODO Android NDK 导入 C库,开发流程 之 变声器*/
public class MainActivity extends AppCompatActivity {/*** 定义变声模式* 0 正常; 1 萝莉; 2 大叔; 3 惊悚; 4 搞怪; 5 回声;*/private static final int MODE_NORMAL = 0;private static final int MODE_LUOLI = 1;private static final int MODE_DASHU = 2;private static final int MODE_JINGSONG = 3;private static final int MODE_GAOGUAI = 4;private static final int MODE_KONGLING = 5;/*** 声音路径*/private String soundPath;private boolean isPlaying = false;static {System.loadLibrary("native-lib");}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// TODO 第七步 初始化FMOD库FMOD.init(this);initData();}private void initData() {soundPath = "file:///android_asset/sound.mp3";}// 点击事件public void onFix(View view) {switch (view.getId()) {case R.id.btn_normal:voiceChange(MODE_NORMAL, soundPath); // 真实开发中,必须子线程  JNI线程(很多坑)break;case R.id.btn_luoli:voiceChange(MODE_LUOLI, soundPath);break;case R.id.btn_dashu:voiceChange(MODE_DASHU, soundPath);break;case R.id.btn_jingsong:voiceChange(MODE_JINGSONG, soundPath);break;case R.id.btn_gaoguai:voiceChange(MODE_GAOGUAI, soundPath);break;case R.id.btn_kongling:voiceChange(MODE_KONGLING, soundPath);break;}}@Overrideprotected void onDestroy() {super.onDestroy();FMOD.close();}private void voiceChange(int modeNormal, String path) {if (isPlaying) {Toast.makeText(this, "正在播放,请稍后!", Toast.LENGTH_SHORT).show();return;}isPlaying = true;new Thread(() -> voiceChangeNative(modeNormal, path)).start();}/*** 给C++(native)层调用的函数* JNI 调用 Java函数的时候,忽略掉 私有、公开 等** @param msg*/private void playerEnd(String msg) {isPlaying = false;runOnUiThread(() -> Toast.makeText(this, msg, Toast.LENGTH_SHORT).show());}/*** 变声native层方法** @param modeNormal* @param path*/public native void voiceChangeNative(int modeNormal, String path);
}
  1. 编写native层头文件(声明文件)

1)导入需要使用到的头文件

#include <jni.h>
#include <fmod.hpp>
#include <string>
#include <android/log.h>

2)定义log宏

#define TAG "NDK"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)

3)定义变声模式宏

#undef com_whine_MainActivity_MODE_NORMAL
#define com_whine_MainActivity_MODE_NORMAL 0L
#undef com_whine_MainActivity_MODE_LUOLI
#define com_whine_MainActivity_MODE_LUOLI 1L
#undef com_whine_MainActivity_MODE_DASHU
#define com_whine_MainActivity_MODE_DASHU 2L
#undef com_whine_MainActivity_MODE_JINGSONG
#define com_whine_MainActivity_MODE_JINGSONG 3L
#undef com_whine_MainActivity_MODE_GAOGUAI
#define com_whine_MainActivity_MODE_GAOGUAI 4L
#undef com_whine_MainActivity_MODE_KONGLING
#define com_whine_MainActivity_MODE_KONGLING 5L

4)头文件完整代码

// TODO 第八步 编写头文件(声明文件)
#include <jni.h>
// 导入FMOD的头文件
#include <fmod.hpp>
#include <string>
// 导入log库
#include <android/log.h>extern "C" {// log宏
#define TAG "NDK"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)// 创建变声模式宏
#undef com_whine_MainActivity_MODE_NORMAL
#define com_whine_MainActivity_MODE_NORMAL 0L
#undef com_whine_MainActivity_MODE_LUOLI
#define com_whine_MainActivity_MODE_LUOLI 1L
#undef com_whine_MainActivity_MODE_DASHU
#define com_whine_MainActivity_MODE_DASHU 2L
#undef com_whine_MainActivity_MODE_JINGSONG
#define com_whine_MainActivity_MODE_JINGSONG 3L
#undef com_whine_MainActivity_MODE_GAOGUAI
#define com_whine_MainActivity_MODE_GAOGUAI 4L
#undef com_whine_MainActivity_MODE_KONGLING
#define com_whine_MainActivity_MODE_KONGLING 5L
JNIEXPORT void JNICALL Java_com_whine_MainActivity_voiceChangeNative(JNIEnv *, jobject, jint, jstring);
}
  1. 编写native层实现文件

1)转换Java层传递的声音路径jstring -> char *

const char *pathChar = env->GetStringUTFChars(path, NULL);

2)定义和初始化音效引擎系统

// 定义音效引擎系统 指针
System *system = 0;
// 声音
Sound *sound = 0;
// 音轨
Channel *channel = 0;
// 数字信号处理  指针
DSP *dsp = 0;
// 创建系统
System_Create(&system);
// 初始化系统 参数1:最大音轨数,参数2:系统初始化标记,参数3:额外数据
system->init(32, FMOD_INIT_NORMAL, 0);
// 创建声音  参数1:路径,  参数2:声音初始化标记, 参数3:额外数据, 参数4:声音指针
system->createSound(pathChar, FMOD_DEFAULT, 0, &sound);
// 播放声音,并赋值通道 参数1:声音,参数2:分组音轨,参数3:控制,参数4:通道
system->playSound(sound, 0, false, &channel);

3)判断变声模式,调节音效

switch (mode_normal) {case com_whine_MainActivity_MODE_NORMAL:resultChar = "原生,播放完毕!";break;case com_whine_MainActivity_MODE_LUOLI:resultChar = "萝莉,播放完毕!";// 音调高 -- 萝莉 2.0// 1.创建DSP类型的Pitch 音调条件system->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsp);// 2.设置Pitch音调调节2.0dsp->setParameterFloat(FMOD_DSP_PITCHSHIFT_PITCH, 3.0f);// 3.添加音效进去 第一个音轨channel->addDSP(0, dsp);break;case com_whine_MainActivity_MODE_DASHU:resultChar = "大叔,播放完毕!";// 音调低 -- 大叔 0.7// 1.创建DSP类型的Pitch 音调条件system->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsp);// 2.设置Pitch音调调节0.7dsp->setParameterFloat(FMOD_DSP_PITCHSHIFT_PITCH, 0.7f);// 3.添加音效进去 第一个音轨channel->addDSP(0, dsp);break;case com_whine_MainActivity_MODE_GAOGUAI:resultChar = "搞怪小黄人,播放完毕!";// 小黄人声音 频率快// 1.从音轨拿 当前 频率float frequency;channel->getFrequency(&frequency);// 2.加快频率加快  小黄人的声音channel->setFrequency(frequency * 1.5f);break;case com_whine_MainActivity_MODE_JINGSONG:resultChar = "惊悚,播放完毕!";// 惊悚音效:特点:很多声音的拼接// TODO 1.音调低// 音调低 -- 大叔 0.7// 1.创建DSP类型的Pitchsystem->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsp);// 2.设置Pitch音调调节0.7dsp->setParameterFloat(FMOD_DSP_PITCHSHIFT_PITCH, 0.7f);// 3.添加音效进去 第一个音轨channel->addDSP(0, dsp);// TODO 2.回声// 回音 ECHO// 1.创建DSP类型的ECHOsystem->createDSPByType(FMOD_DSP_TYPE_ECHO, &dsp);// 2.设置回音 延时 to 5000.  Default = 500.dsp->setParameterFloat(FMOD_DSP_ECHO_DELAY, 200);// 3.设置回音 衰减度 Default = 50   0 完全衰减了dsp->setParameterFloat(FMOD_DSP_ECHO_FEEDBACK, 10);// 4.添加音效进去 第二个音轨channel->addDSP(1, dsp);// TODO 3.颤抖// Tremolo 颤抖音// 1.创建DSP类型的Tremolosystem->createDSPByType(FMOD_DSP_TYPE_TREMOLO, &dsp);// 2.设置颤抖 正常 5,非常颤抖 20dsp->setParameterFloat(FMOD_DSP_TREMOLO_FREQUENCY, 20);// 3.dsp->setParameterFloat(FMOD_DSP_TREMOLO_SKEW, 0.8f);// 4.第三个音轨channel->addDSP(2, dsp);break;case com_whine_MainActivity_MODE_KONGLING:resultChar = "空灵,播放完毕!";// 回音 ECHO// 1.创建DSP类型的ECHO 音调条件system->createDSPByType(FMOD_DSP_TYPE_ECHO, &dsp);// 2.设置回音 延时 to 5000.  Default = 500.dsp->setParameterFloat(FMOD_DSP_ECHO_DELAY, 200);// 3.设置回音 衰减度 Default = 50   0 完全衰减了dsp->setParameterFloat(FMOD_DSP_ECHO_FEEDBACK, 10);// 4.添加音效进去 第一个音轨channel->addDSP(0, dsp);break;
}

4)检测声音是否播放完毕

bool isPlay = true;
while (isPlay) {// 如果真的播放完成了,音轨是知道的,内部会修改isPlayer=falsechannel->isPlaying(&isPlay);// 休眠100mSusleep(100 * 1000);
}

5)回收C层资源

sound->release();
system->close();
system->release();
env->ReleaseStringUTFChars(path, pathChar);

6)播放完毕,通知java层(调用Java层的播放完成方法)

jclass jClazz = env->GetObjectClass(thiz);
jmethodID methodId = env->GetMethodID(jClazz, "playerEnd", "(Ljava/lang/String;)V");
jstring value = env->NewStringUTF(resultChar);
env->CallVoidMethod(thiz, methodId, value);

7)实现文件完整代码

#include <unistd.h>
#include "whine.h"using namespace FMOD; // fmod的命名空间extern "C"
JNIEXPORT void JNICALL
Java_com_whine_MainActivity_voiceChangeNative(JNIEnv *env, jobject thiz, jint mode_normal,jstring path) {// 定义一个结果字符串返回char *resultChar = "播放完毕!";// 转换路径jstring -> char *const char *pathChar = env->GetStringUTFChars(path, NULL);// 定义音效引擎系统 指针System *system = 0;// 声音Sound *sound = 0;// 音轨Channel *channel = 0;// 数字信号处理  指针DSP *dsp = 0;// 创建系统System_Create(&system);// 初始化系统 参数1:最大音轨数,参数2:系统初始化标记,参数3:额外数据system->init(32, FMOD_INIT_NORMAL, 0);// 创建声音  参数1:路径,  参数2:声音初始化标记, 参数3:额外数据, 参数4:声音指针system->createSound(pathChar, FMOD_DEFAULT, 0, &sound);// 播放声音,并赋值通道 参数1:声音,参数2:分组音轨,参数3:控制,参数4:通道system->playSound(sound, 0, false, &channel);LOGI("init done");// 判断模式,增加特效switch (mode_normal) {case com_whine_MainActivity_MODE_NORMAL:resultChar = "原生,播放完毕!";break;case com_whine_MainActivity_MODE_LUOLI:resultChar = "萝莉,播放完毕!";// 音调高 -- 萝莉 2.0// 1.创建DSP类型的Pitch 音调条件system->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsp);// 2.设置Pitch音调调节2.0dsp->setParameterFloat(FMOD_DSP_PITCHSHIFT_PITCH, 3.0f);// 3.添加音效进去 第一个音轨channel->addDSP(0, dsp);break;case com_whine_MainActivity_MODE_DASHU:resultChar = "大叔,播放完毕!";// 音调低 -- 大叔 0.7// 1.创建DSP类型的Pitch 音调条件system->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsp);// 2.设置Pitch音调调节0.7dsp->setParameterFloat(FMOD_DSP_PITCHSHIFT_PITCH, 0.7f);// 3.添加音效进去 第一个音轨channel->addDSP(0, dsp);break;case com_whine_MainActivity_MODE_GAOGUAI:resultChar = "搞怪小黄人,播放完毕!";// 小黄人声音 频率快// 1.从音轨拿 当前 频率float frequency;channel->getFrequency(&frequency);// 2.加快频率加快  小黄人的声音channel->setFrequency(frequency * 1.5f);break;case com_whine_MainActivity_MODE_JINGSONG:resultChar = "惊悚,播放完毕!";// 惊悚音效:特点:很多声音的拼接// TODO 1.音调低// 音调低 -- 大叔 0.7// 1.创建DSP类型的Pitchsystem->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsp);// 2.设置Pitch音调调节0.7dsp->setParameterFloat(FMOD_DSP_PITCHSHIFT_PITCH, 0.7f);// 3.添加音效进去 第一个音轨channel->addDSP(0, dsp);// TODO 2.回声// 回音 ECHO// 1.创建DSP类型的ECHOsystem->createDSPByType(FMOD_DSP_TYPE_ECHO, &dsp);// 2.设置回音 延时 to 5000.  Default = 500.dsp->setParameterFloat(FMOD_DSP_ECHO_DELAY, 200);// 3.设置回音 衰减度 Default = 50   0 完全衰减了dsp->setParameterFloat(FMOD_DSP_ECHO_FEEDBACK, 10);// 4.添加音效进去 第二个音轨channel->addDSP(1, dsp);// TODO 3.颤抖// Tremolo 颤抖音// 1.创建DSP类型的Tremolosystem->createDSPByType(FMOD_DSP_TYPE_TREMOLO, &dsp);// 2.设置颤抖 正常 5,非常颤抖 20dsp->setParameterFloat(FMOD_DSP_TREMOLO_FREQUENCY, 20);// 3.dsp->setParameterFloat(FMOD_DSP_TREMOLO_SKEW, 0.8f);// 4.第三个音轨channel->addDSP(2, dsp);break;case com_whine_MainActivity_MODE_KONGLING:resultChar = "空灵,播放完毕!";// 回音 ECHO// 1.创建DSP类型的ECHO 音调条件system->createDSPByType(FMOD_DSP_TYPE_ECHO, &dsp);// 2.设置回音 延时 to 5000.  Default = 500.dsp->setParameterFloat(FMOD_DSP_ECHO_DELAY, 200);// 3.设置回音 衰减度 Default = 50   0 完全衰减了dsp->setParameterFloat(FMOD_DSP_ECHO_FEEDBACK, 10);// 4.添加音效进去 第一个音轨channel->addDSP(0, dsp);break;}// 等待播放完毕 再回收bool isPlay = true;while (isPlay) {// 如果真的播放完成了,音轨是知道的,内部会修改isPlayer=falsechannel->isPlaying(&isPlay);// 休眠100mSusleep(100 * 1000);}LOGI("play done");// 回收资源sound->release();system->close();system->release();env->ReleaseStringUTFChars(path, pathChar);// 通知java层jclass jClazz = env->GetObjectClass(thiz);jmethodID methodId = env->GetMethodID(jClazz, "playerEnd", "(Ljava/lang/String;)V");jstring value = env->NewStringUTF(resultChar);env->CallVoidMethod(thiz, methodId, value);
}

相关文章:

NDK JNI 变声器实现

Android NDK 导入 C库的开发流程学习&#xff1b;通过使用fmod的C库&#xff0c;实现变声器功能。导入库文件1&#xff09;复制fmod的C库到cpp目录下2&#xff09;复制fmod的so库到jniLibs目录下3&#xff09;复制fmod的jar库到libs目录下4&#xff09;将声音文件复制到assets目…...

VMLogin防关联指纹浏览器的主帐号和子账号区别介绍

VMLogin主账户管理子账户&#xff0c;主要用于团队协作&#xff0c;分账户登录使用&#xff0c;主账户相当于老板&#xff0c;子账户相当于员工。 主账户创建并管理子账户&#xff1b; 主账户可以修改子账户的密码&#xff1b; 主账户可以设置子账户是否有创建配置文件权限&a…...

Apache DolphinScheduler GitHub Star 突破 10000!

点击蓝字 关注我们今天&#xff0c;Apache DolphinScheduler GitHub Star 突破 10000&#xff0c;项目迎来一个重要里程碑。这表明 Apache DolphinScheduler 已经在全球的开发者和用户中获得了广泛的认可和使用。DolphinScheduler 旨在解决公司日常运营中的大数据处理工作流调度…...

程序员中的女性力量——做不被定义的自己

她是office lady&#xff0c;亦是程序媛&#xff0c;程序员界的靓丽色彩&#xff0c;不可或缺。 “只有那些疯狂到以为自己能够改变世界的人——才能真正改变世界。” 女性该如何定义自己&#xff1f;程序媛怎么发挥自己最大的价值。 争取自己做选择&#xff0c;经济和思想都独…...

pb中Datawindow中每页打印固定行

Datawindow中每页打印固定行 第一步: 增加一个计算列,此计算列必须放在Detail段,Expression中输入:ceiling(getrow()/20),这里20还可以用全局函数取代,这样可以允许用户任意设置每页打印多少行。 第二步: 定义分组,选择菜单Rows->Create Group...按计算列字段…...

华为OD机试 - 内存池(C 语言解题)【独家】

最近更新的博客 华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南)华为od机试,独家整理 已参加机试人员的实战技巧文章目录 使用说明本期题目:内存池题…...

SaaS简介

SaaS 简介 SaaS被认为是云计算的一部分&#xff0c;其他包括基础设施即服务(IaaS)、平台即服务(PaaS)、桌面即服务(DaaS)、托管软件即服务(MSaaS)、移动后端即服务(MBaaS)、数据中心即服务(DCaaS)、集成平台即服务(iPaaS)和信息技术管理即服务(ITMaaS) SaaS应用程序通常由web浏…...

unity 实现使用三张图片来表达车速,通过传值达到车速

//速度 public Image SpeedNums_Unit; public Image SpeedNums_Ten; //public Image SpeedNums_Hundred; //kw public Image MileageNums_Unit; public Image MileageNums_Ten; /// /// 仪表速度UI /// private void SpeedUI(string speedStr) {if (SpeedNums_Unit == null) …...

程序员看过都说好的资源网站,你值得拥有。

程序员必备的相关资源网站一.技术社区1.GitHub2.Gitee&#xff08;码云&#xff09;3.稀土掘金4.OSCHINA开源中国5.CSDN6.博客园7.SegmentFault&#xff08;思否&#xff09;8.Stack Overflow9.Golang中文社区10.ChinaUnix11.51CTO12.Ruby China二.技术教程1.Devdocs2.码农教程…...

【MySQL高级篇】第03章 用户与权限管理

第03章 用户与权限管理 1. 用户管理 1.1 登录MySQL服务器 启动MySQL服务后&#xff0c;可以通过mysql命令来登录MySQL服务器&#xff0c;命令如下&#xff1a; mysql –h hostname|hostIP –P port –u username –p DatabaseName –e "SQL语句"-h参数后面接主机…...

MySQL的分库分表?通俗易懂

1- 为什么要分库分表 如果一个网站业务快速发展&#xff0c;那这个网站流量也会增加&#xff0c;数据的压力也会随之而来&#xff0c;比如电商系统来说双十一大促对订单数据压力很大&#xff0c;Tps十几万并发量&#xff0c;如果传统的架构&#xff08;一主多从&#xff09;&a…...

elasticsearch 查询语法

match_all 查询所有 GET test/_search {"query": {"match_all": {}} }match 单字段匹配查询 GET test/_search {"query":{"match":{"name":"zhangsan"}} }multi_match 多字段匹配查询 GET test/_search {"…...

深入剖析MVC模型与三层架构

MVC&#xff08;Model-View-Controller&#xff09;模型和三层架构都是常见的软件架构模式&#xff0c;用于实现大型应用程序和软件系统。下面是对它们的深入剖析&#xff1a; MVC模型 MVC模型是一种将应用程序分成三个主要组件的软件架构模式&#xff0c;分别是模型&#xf…...

使用 Wall 搭建个人照片墙和视频墙

下载 Github:https://github.com/super-tongyao/wall 国内仓库&#xff08;不推荐&#xff0c;只做加速访问&#xff0c;无编译包和发行版&#xff0c;以github仓库为准&#xff09;&#xff1a;https://gitee.com/Super_TongYao/wall 推荐github仓库&#xff0c;下载最新版…...

03_Linux压缩解压,用户用户组,文件权限

目录 Linux下常用的压缩格式 gzip 压缩工具 gzip 对文件夹进行压缩 bzip2 压缩工具 tar打包工具 对.tar.bz2 进行压缩和解压缩 对.tar.gz 进行压缩和解压缩 rar格式 zip格式 Linux用户 Linux用户组 创建用户和用户组 Linux文件权限 Linux文件权限修改 Linux下常用…...

硬盘分区数据恢复?这些方法助您解忧

案例&#xff1a;分区把电脑文件丢了&#xff0c;数据还能恢复吗&#xff1f; “急急急&#xff01;&#xff01;&#xff01;本人电脑小白&#xff0c;在使用磁盘管理合并E、F分区的时候&#xff0c;不小心把D分区给删除了&#xff0c;D分区里面存放了很多重要的数据与文件&a…...

高校竞赛信息管理系统

摘要随着当今社会的发展&#xff0c;时代的进步&#xff0c;各行各业也在发生着变化&#xff0c;比如高校竞赛信息管理这一方面&#xff0c;利用网络已经逐步进入人们的生活。传统的高校竞赛信息管理&#xff0c;都是学生去学校查看竞赛信息然后再进行报名&#xff0c;这种传统…...

还是要学好数学啊

有一个无穷大的二维网格图&#xff0c;一开始所有格子都未染色。给你一个正整数 n &#xff0c;表示你需要执行以下步骤 n 分钟&#xff1a;第一分钟&#xff0c;将任一格子染成蓝色。之后的每一分钟&#xff0c;将与蓝色格子相邻的 所有 未染色格子染成蓝色。下图分别是 1、2、…...

ActiveMQ反序列化漏洞原理+复现

ActiveMQ反序列化漏洞 ActiveMQ ActiveMQ是开源消息总线&#xff0c;消息中间件 工作原理 通过使用消息队列&#xff0c;实现服务的异步处理&#xff0c;主要目的是减少请求响应时间和解耦合。 消息队列&#xff0c;服务器A将客户发起的请求放入服务器B的消息队列中&#…...

layui框架实战案例(19):layui-table模块表格综合应用(筛选查询、导入导出、群发短信、一键审核、照片展示、隐私加密)

系列文章目录 layui动态表格翻页和搜索的代码分析layui框架实战案例(3)&#xff1a;layui上传错误请求上传接口出现异常解决方案layui框架实战案例(9)&#xff1a;layPage 静态数据分页组件layui框架实战案例(10)&#xff1a;短信验证码60秒倒计时layui框架实战案例(11)&#…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

【位运算】消失的两个数字(hard)

消失的两个数字&#xff08;hard&#xff09; 题⽬描述&#xff1a;解法&#xff08;位运算&#xff09;&#xff1a;Java 算法代码&#xff1a;更简便代码 题⽬链接&#xff1a;⾯试题 17.19. 消失的两个数字 题⽬描述&#xff1a; 给定⼀个数组&#xff0c;包含从 1 到 N 所有…...

UDP(Echoserver)

网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法&#xff1a;netstat [选项] 功能&#xff1a;查看网络状态 常用选项&#xff1a; n 拒绝显示别名&#…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

OpenLayers 分屏对比(地图联动)

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能&#xff0c;和卷帘图层不一样的是&#xff0c;分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

初学 pytest 记录

安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

Golang——7、包与接口详解

包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...

Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成

一个面向 Java 开发者的 Sring-Ai 示例工程项目&#xff0c;该项目是一个 Spring AI 快速入门的样例工程项目&#xff0c;旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计&#xff0c;每个模块都专注于特定的功能领域&#xff0c;便于学习和…...

二维FDTD算法仿真

二维FDTD算法仿真&#xff0c;并带完全匹配层&#xff0c;输入波形为高斯波、平面波 FDTD_二维/FDTD.zip , 6075 FDTD_二维/FDTD_31.m , 1029 FDTD_二维/FDTD_32.m , 2806 FDTD_二维/FDTD_33.m , 3782 FDTD_二维/FDTD_34.m , 4182 FDTD_二维/FDTD_35.m , 4793...