记录与分享
WSL 使用 adb
wsl使用adb 版本问题 可能是版本问题,将wsl中的adb的版本和windows的adb版本统一 使用usbipd 连接 USB 设备 | Microsoft Learn usbip windows 使用,挂载远程usb设备 | ZhouZhou Blog 根据文档下载usbipd 注意windows版本和wsl版本 管理员模式运行powershell usbipd list usbipd bind --busid 1-4 # 可能需要重启 # 打开一个wsl窗口 usbipd attach --wsl --busid 1-4 在wsl lsusb 需要断开,在win usbipd detach --busid <busid> 问题 正常情况下,网络断开的 usbip 设备能够自动恢复,例如关闭wifi、关机等操作。然而如果直接拔掉 windows 电源。设备会一直处于一个挂载状态,无法再被开机自动挂载。 此时必须执行 usbip unbind --busid=xxx 取消绑定,然后再次执行 usbip bind --busid=xxx 才行 usbipd unbind --busid 1-4 usbipd bind --busid 1-4
lin2db & db2lin
lin2db & db2lin lin2db 计算方式 $$ y = 20 \times \log_{10}x $$查表代码 static float log2lut_base_float[8] = { 0, 0.169925001442312f, 0.321928094887362f, 0.459431618637297f, 0.584962500721156f, 0.700439718141092f, 0.807354922057604f, 0.906890595608519f }; static float log2lut_frac_float[8] = { 0.169925001442312f, 0.152003093445050f, 0.137503523749935f, 0.125530882083859f, 0.115477217419936f, 0.106915203916512f, 0.0995356735509144f, 0.0931094043914815f }; inline float lin2dbLut(float x) { //10*log10(x) 3.0103*log2(x) float M, result; int xi = *(int*)&x;//interpret float as raw int number int E = (xi >> 23) - 127;//float point, the 30~23bit is exponent xi &= 0x007FFFFF;//extract the mantissa bit 22~0bit xi |= ((int)127 << 23);//set the exponent bit to 127, which actuall is 0 M = *(float*)&xi - 1;//interpret the mantissa as float M = M * 8; result = (E + log2lut_base_float[(int)M] + (M - (int)M) * log2lut_frac_float[(int)M]) * 6.020599913279624; return result; // return (log2lut(x)*6.020599913279624); } 快速计算 ...
wav音频格式解析
wav音频格式解析 本文参考: WAVE文件格式解析 - Tocy - 博客园 (cnblogs.com) Wave File Specifications (mcgill.ca) 简介 WAV文件是一种常见的音频文件格式,其结构遵循RIFF(Resource Interchange File Format)规范,这种规范来源于微软和IBM,我们可以在参考博客中找到相关规范文档。 WAV文件是由chunk组成的,这些chunk通常由ckID、cksize、chunk data组成。 文件结构 首先是很经典的结构图: 这张图中有很多值得注意的地方: 在最左边表明了当前的字段的编码属于小端模式还是大端模式。 图中以不同的颜色区分了不同的chunk,而其中的subchunk表明了这些chunk之间的关系。 每个chunk都有其承载的信息内容,这些信息的组织也有相关规范。 接下来分别分析其中的chunk 本文中分析hex文件的截图来源于HexEd.it — 基于浏览器的十六进制编辑器 RIFF RIFF字段是每个WAV文件都有的部分 field Length Contents ckid 4 “RIFF” cksize 4 4+n WAVEID 4 “WAVE” WAVE chunks n 包括格式信息和数据块 这张表列出了RIFFchunk的结构,从中可知: 其他的信息都在WAVE chunk中,即开始的图中的subchunk部分。 同时,我们也知道这里的4+n指的是WAVEID的4字节和WAVE chunks的n字节,不包括ckid和cksize。 RIFF和WAVE属于固定的内容,是不会变的。 上图是对一个wav的文件放入16进制编辑器分析的截图,我们可以很容易看到转化为ASCII的RIFF和WAV字段。 fmt chunk fmt块是一个可选的块,但是其中包含很多重要的信息,包括channels、sample pre seconds、bits per sample等,所以一般的文件都会有这个块,没有这部分信息很多的播放器会无法解析播放。 Field Length Contents ckID 4 “fmt " cksize 4 16/18/40 wFormatTag 2 Format code 对应不同的音频编码 nChannels 4 声道数 nSamplePreSecond 4 采样率 nAvgBytesPerSec 4 音频码率 nBlockAlign 2 音频数据块大小 wBitsPerSample 2 量化位数,比如8bit、16bit cbSize 2 extension扩展块的大小(0 or 22) wValidBitsPerSample 2 有效位数 dwChannelMask 4 声道掩码,比如左声道、右声道 SubFormat 16 GUID,数据格式码 该表格中表示了许多重要信息,我们要注意以下几点: ...
JNI 总结
JNI JNI是指Java Native Interface,在编写Java程序时需要使用本地代码(C/C++)可以使用这一技术。 通常来说,要使用的本地代码有两种:C/C++源代码和经过编译的库(用在Android应用上的是.so库,需要根据运行的设备编译对应版本)。 使用JNI要做的几个部分有:确定接口,编写Java和cpp文件,编写cmake文件,加载库,使用函数。这几个步骤理论上没有顺序,按照我的实践结果,有的步骤按逻辑来执行比较方便。 前期配置 我的开发IDE是Android Studio,需要在项目中先配置好NDK和cmake插件。 在开发时,我选择了新建一个模块作为JNI部分,虽然多了一层的封装,但是自己看起来比较清楚。这里有一个小问题,在gradle版本为4.1.1时,会出现新建native Lib模块不能编译的问题,我将gradle版本升级到7.4.2解决了这个问题。如果选择新建moudle,还要在app的build.gradle中加入引用 ... dependencies { ... implementation project(path : ':nativeLib') } 如果选择在app中直接加入也很简单,在Java同级目录下创建cpp目录,并在cpp文件夹中创建CMakeLists.txt等文件就可以。 当然,以上两种都可以在创建app或模块时就选择native lab,IED会自动创建相关目录和文件。 确定接口 这里的接口指的是在Java中会调用的接口。在Java文件中,要加入native。 public static native int init(); 这里的接口也对应要编写的cpp文件。 Java文件加载库 在Java代码中除了要处理接口,还要引入库,我们编写的cpp文件也会编译成库,不要忘记加上这个库。 // cpp文件的库 System.loadLibrary("nativeLib"); // 其他库,对应名称libexample.lib System.loadLibrary("example"); 编写cpp文件 生成接口定义 Java中确定的native接口也需要在cpp中实现。 Java确定cpp文件中的函数名称有一套规则:Java_{package_and_classname}_{function_name}(JNI arguments)。包名中的点换成单下划线。需要说明的是生成函数中的两个参数: JNIEnv *:这是一个指向JNI运行环境的指针,后面我们会看到,我们通过这个指针访问JNI函数 jobject:这里指代java中的this对象 我不推荐按照这个规则直接去写,有两种方法可以生成Java能找到的cpp函数名: 将javah.exe加入环境变量并使用以下命令 javac -h . nativeLab.java java nativeLib.java javah -jni nativeLib.java 使用Android Studio 外部工具,将javah.exe作为外部工具直接使用生成头文件。 我们可以直接参照生成的头文件来编写cpp文件,在编译中,这个头文件不是必要的。 函数内容 java会将一些参数传给cpp,所以这些参数需要我们进行处理的转化。 原始类型 jint, jbyte, jshort, jlong, jfloat, jdouble, jchar, jboolean这些分别对应这java的int, byte, short, long, float, double, char and boolean。 ...
Ubuntu 安装 TP-WN823N 免驱无线网卡驱动
Ubuntu 安装 TP-WN823N 免驱无线网卡驱动 参考 GitHub - BrightX/rtl8192fu: Realtek 8192FU Linux USB无线网卡驱动 ubuntu20.04 安装usb无线网卡 腾达u6 (rtl8192fu)过程记录-CSDN博客 usb驱动也加载了,怎么还是没有呢-论坛-深度科技 (deepin.org) 免驱不是linux免驱 京东、淘宝客服都说linux不能用 Ubuntu版本20.04 内核版本5.15 无线网卡版本tp-wn823n v2 免驱 官网的版本不能成功编译 具体步骤 看接口信息,确定设备ID 0bda:a192 lsusb 这里我直接搜了设备ID就有很多教程了,大部分说的是使用rtl8192fu对应的驱动(我在这一步识别到的是disk,就切换了usbmode,所以发现设备ID变了……或许先编译驱动再改就不会像我一样没有驱动) 切换usbmode sudo usb_modeswitch -KW -v 0bda -p a192 这个时候设备ID已经变成 2357:0135了…… 下载https://github.com/BrightX/rtl8192fu 根据链接中的readme操作,其中主要操作: make -j$(nproc) sudo make install sudo modprobe 8192fu 看接口信息 lsusb usb-devices 驱动安装成功Driver=rtl8192fu T: Bus=03 Lev=01 Prnt=01 Port=01 Cnt=02 Dev#= 5 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=0bda ProdID=f192 Rev=02.00 S: Manufacturer=Realtek S: Product=802.11n WLAN Adapter S: SerialNumber=60EE5CBDFDE9 C: #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=500mA I: If#= 0 Alt= 0 #EPs= 8 Cls=ff(vend.) Sub=ff Prot=ff Driver=rtl8192fu 驱动安装失败Driver=(none) T: Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 3 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=0bda ProdID=f192 Rev=02.00 S: Manufacturer=Realtek S: Product=802.11n WLAN Adapter S: SerialNumber=60EE5CBDFDE9 C: #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=500mA I: If#=0x0 Alt= 0 #EPs= 8 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) 如果失败,就卸载驱动 sudo modprobe -r 8192fu cd rtl8192fu/ sudo make uninstall 修改os_dep\linux\usb_intf.c,大约在250行位置 #ifdef CONFIG_RTL8192F / _=== Realtek demoboard ===_ / {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDER_ID_REALTEK, 0xF192, 0xff, 0xff, 0xff), .driver_info = RTL8192F}, /* 8192FU 2_2 _/ {USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0135, 0xff, 0xff, 0xff), .driver_info = RTL8192F}, /_ 增加这行 _/ {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDER_ID_REALTEK, 0xA725, 0xff, 0xff, 0xff), .driver_info = RTL8192F}, /_ 8725AU 2_2 */ #endif 重新编译和安装驱动 make -j$(nproc) sudo make install sudo modprobe 8192fu # sudo usb_modeswitch -KW -v 0bda -p a192 usb-devices 总结 可以直接搜设备ID,找到对应的驱动,比搜产品名字好用 我是先修改usb_mode再编译驱动的,或许直接编译并应用再改模式就不用改代码了,如果直接编译不行的话,就试试先改usb_mode,再改代码的方法
加解密、签名验证总结
加解密、签名验证总结 因为做试用期的小功能,实际使用了一下这方面的框架,总结一下。 我选择的方案是用python加密和签名,在Java端解密和验证。这里有个重要的点就是两方的方案包括参数要对的上。 对称加密(加解密) 比较简单,大部分能找到的代码都是可以直接用的。 我选用的方法是AES,需要注意的地方是我这里symmetric_key是Base64编码的,如果从文件读取,需要先解码。 生成密钥 import base64 import os def generate_symmetric_key(): return os.urandom(32) # 生成 256-bit 对称密钥 def encode_key_to_base64(key): return base64.b64encode(key).decode('utf-8') def save_key_to_file(key, filename): with open(filename, 'w') as f: f.write(encode_key_to_base64(key)) key = generate_symmetric_key() save_key_to_file(key, 'symmetric_key.key') 加密 def encrypt(data: str, symmetric_key: bytes) -> str: # 生成 12 字节的随机 noncenonce = os.urandom(12) cipher = AES.new(symmetric_key, AES.MODE_GCM, nonce=nonce) encrypted_data, tag = cipher.encrypt_and_digest(data.encode()) # 返回 nonce 和加密数据(包括 GCM tag) return base64.b64encode(nonce + encrypted_data + tag).decode('utf-8') 解密(Java) public static String decrypt(String data, byte[] symmetricKey) throws Exception { byte[] encryptedData = Base64.getDecoder().decode(data); byte[] nonce = new byte[12]; byte[] tag = new byte[16]; byte[] ciphertext = new byte[encryptedData.length - 12]; System.arraycopy(encryptedData, 0, nonce, 0, 12); System.arraycopy(encryptedData, encryptedData.length - 16, tag, 0, 16); System.arraycopy(encryptedData, 12, ciphertext, 0, ciphertext.length); Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); SecretKeySpec keySpec = new SecretKeySpec(symmetricKey, "AES"); cipher.init(Cipher.DECRYPT_MODE, keySpec, new GCMParameterSpec(128, nonce)); byte[] decryptedData = cipher.doFinal(ciphertext); return new String(decryptedData, StandardCharsets.UTF_8); } 非对称加密(签名验证) 我选用的是RSA-PSS签名方案,具体的过程是使用private_key签名,使用public_key验证。 这里注意的地方是使用cryptography有可能在Java上无法验证成功,我换了pycryptodome才成功。具体可以看Frequently Asked Questions — PyCryptodome 3.210b0 documentation ,在用pycryptodome时,使用的命名空间是Crypto,可能与其他的库发生冲突,需要先卸载。 另外一个问题是在android中的,在java - BouncyCastleProvider not picked for Signature object - Stack Overflow和java - Change “salt length” parameter in PSS parameters for Bouncycastle - Stack Overflow提到的问题,Android可能需要在加载pss参数之前就init. 同样的,我们在验证的时候也要注意输入的data是原始的未hash过的数据,签名的数据和公钥都是Base64编码的,要注意解码。 生成密钥 ...
编译 libtensorflowlite_c.so
编译libtensorflowlite_c.so 环境:wsl/linux 需要充足的内存和硬盘空间 安装基础工具 python版本 >= 3.9 可以使用虚拟环境 sudo apt-get update sudo apt-get install build-essential git unzip python3 python3-pip 安装bazel 编译最新的tensorflow源码需要版本 >= 7.1.4 下载安装脚本,并运行。命令行太慢,建议直接在浏览器里下载Releases · bazelbuild/bazel · GitHub curl -L https://github.com/bazelbuild/bazel/releases/download/7.1.4/bazel-7.1.4-installer-linux-x86_64.sh -o bazel-installer.sh chmod +x bazel-installer.sh ./bazel-installer.sh --user 下载ndk 版本 >= 25 NDK 下载 | Android NDK | Android Developers unzip android-ndk-r25b-linux.zip -d ~/ echo 'export ANDROID_NDK_HOME="$HOME/android-ndk-r25b"' >> ~/.bashrc echo 'export PATH="$ANDROID_NDK_HOME:$PATH"' >> ~/.bashrc source ~/.bashrc 下载android sdk 直接下载android studio 或者用命令行 先下载java,最好选17 sudo apt update sudo apt install openjdk-17-jdk 下载sdk,如果下载慢可以直接从浏览器下载下载 Android Studio 和应用工具 - Android 开发者 | Android Developers mkdir -p ~/Android/Sdk/cmdline-tools cd ~/Android/Sdk/cmdline-tools # 下载并解压(替换为实际版本号) wget https://dl.google.com/android/repository/commandlinetools-linux-10406996_latest.zip unzip commandlinetools-linux-10406996_latest.zip mv cmdline-tools latest # 重命名为 `latest` # 配置环境变量 nano ~/.bashrc export ANDROID_HOME="$HOME/Android/Sdk" export PATH="$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools:$ANDROID_HOME/emulator:$PATH" # ctrl + x 退出保存 source ~/.bashrc # 安装组件 sdkmanager --update sdkmanager "platform-tools" "build-tools;34.0.0" "platforms;android-34" "emulator" 下载tensorflow源码 git clone https://github.com/tensorflow/tensorflow.git cd tensorflow git checkout r2.14 # 切换到指定版本 运行交互式配置脚本 ./configure 按需配置 编译 通用编译(ARM64 架构) bazel build -c opt \ --config=android_arm64 \ --cxxopt='--std=c++17' \ //tensorflow/lite/c:libtensorflowlite_c.so 生成文件 生成库位于 ...