音频基础知识简述 esp-sr 上手指南
此篇博客先对音频基础知识进行简要叙述,然后帮助读者入门 esp-sr SDK。
1 音频的基本概念
1.1 声音的本质
声音的本质是波在介质中的传播现象,声波的本质是一种波,是一种物理量。 两者不一样,声音是一种抽象的,是声波的传播现象,声波是物理量。
1.2 声音的三要素
- 响度:人主观上感觉声音的大小(俗称音量),由振幅和人离声源的距离决定,振幅越大响度越大,人和声源的距离越小,响度越大。
- 音调:频率的不同决定了声音的高低(高音、低音),频率越高音调越高(频率单位为 Hz,赫兹),人耳听觉范围 20~20000 Hz。20 Hz 以下称为次声波,20000 Hz 以上称为超声波)。
- 音色:由于不同对象材料的特点,声音具有不同的特性,音色本身就是抽象的东西,但波形就是把这种抽象和直观的性能。波形因音调而异,不同的音调可以通过波形来区分。
1.3 数字音频的几个基本概念
1.3.1 采样
所谓采样就是只在时间轴上对信号进行数字化。
- 根据奈奎斯特定律(也称为采样定律),按照比声音最高频率的 2 倍上进行采样。人类听觉的频率(音调)范围为 20 Hz–20 KHz 。所以至少要大于 40 kHz。采样频率一般为 44.1 kHz,这样可保证声音达到 20 kHz 也能被数字化。44.1 kHz 就是代表 1 秒会采样 44100 次。
乐鑫AI语音采用的是 16 kHz 采样率,16 kHz 的采样频率的一半合好对应人类语音的常用频段上限约 8 kHz, 此外 44.1 kHz 采样率是另一种常用的采样率,44.1 kHz 的采样频率的一半对应人耳的可听声频率上限约 20 kHz。因为在同等时间长度内,采样率越高,数据量越大,所以:通常即时通讯类的音频会采用 16 kHz 甚至更低的采样率,以保证信号传输的及时性,但是也会对音频质量造成一定损失(比如声音发闷);而主打高质量音声的记录类音频资源会采用 44.1 kHz 甚至 48 kHz 的采样率,以更多的数据存储量为代价,保证重放信号的高保真度。
因此这部分主要包含以下三个参数:
- 比特率:比特率是每秒传输的比特数。单位为比特(bps 位/秒)。
- 采样:采样是把连续的时间信号,变成离散的数字信号。
- 采样率:采样率是每秒采集多少个样本。
1.3.2 量化
量化是指在幅度轴上对信号进行数字化。如果用 16 比特位的二进制信号来表示一个采样,那么一个采样所表示的范围即为【-32768,32767】。
乐鑫 AI 语音采用的是 16 比特的量化。
1.3.3 通道数
通道数即声音的通道数目,常见的有单声道、双声道和立体声道。
-
单声道的声音只能使用一个扬声器发声,或者也可以处理成两个扬声器输出同一个声道的声音,当通过两个扬声器回放单声道信息的时候,我们可以明显感觉到声音是从两个音箱中间传递到我们耳朵里的,无法判断声源的具体位置。
-
双声道就是有两个声音通道,其原理是人们听到声音时可以根据左耳和右耳对声音相位差来判断声源的具体位置。声音在录制过程中被分配到两个独立的声道,从而达到了很好的声音定位效果。
1.3.4 音频大小的计算
如:录制一段,时间为:1 s,采样率为 16000 HZ,采样大小为 16,通道数为 2 的音频,所占用的空间大小为 : 16000 * 16 * 2 * 1 s= 500 k
2 声学前端(Audio Front-End ,AFE)
一套乐鑫 AFE 算法框架,可基于功能强大的 ESP32 和 ESP32-S3 SoC 进行声学前端处理,使用户获得高质量且稳定的音频数据,从而构建性能卓越且高性价比的智能语音产品。
2.1 声学回声消除(AEC)
声学回声消除算法通过自适应滤波的方法,消除使用麦克风输入音频时的回声。此算法适用于语音设备通过扬声器播放音频等场景。
算法最多支持双麦处理,能够有效的去除 mic 输入信号中的自身播放声音。从而可以在自身播放音乐的情况下进行很好的语音识别等应用。
2.2 盲源分离(BSS)
盲源分离算法使用多个麦克风检测传入音频的方向,并强化某个方向的音频输入。此算法在噪音环境中提高了所需音频源的声音质量。
2.3 噪声抑制(NS)
噪声抑制算法支持单通道音频信号处理,能够有效消除无用的非人声(如吸尘器或空调声),从而改善所需处理的音频信号。
3 乐鑫 AFE 支持的场景
乐鑫 AFE 的功能针对以下两种不同场景:
-
语音识别场景
-
语音通话场景
3.1 语音识别场景
模型步骤:
-
音频输入
-
AEC 进行回声消除(消除自身的音频播报,这需要回采通道)
- 硬回采:通过 IIS 直接读取写入扬声器的数据(可以和麦克风共用一路 IIS)
- 软回采:软件 copy 写入扬声器的数据(暂未支持,等待开发)
-
BSS/NS
- BSS (Blind Source Separation) 算法支持双通道处理,能够很好的将目标声源和其余干扰音进行盲源分离,从而提取出有用音频信号,保证了后级语音的质量。
- NS (Noise Suppression) 算法支持单通道处理,能够对单通道音频中的非人声噪声进行抑制,尤其针对稳态噪声,具有很好的抑制效果。
- 具体采用哪一个算法,根据配置的麦克风数量定义。
-
VAD
- VAD (Voice Activity Detection) 算法支持实时输出当前帧的语音活动状态
-
WakeNet
唤醒词
对应的流程图如下:
3.2 语音通话场景
模型步骤:
- 音频输入
- AEC 进行回声消除(消除自身的音频播报,这需要回采通道)
- 硬回采:通过 IIS 直接读取写入扬声器的数据(可以和麦克风共用一路 IIS)
- 软回采:软件 copy 写入扬声器的数据(暂未支持,等待开发)
- BSS/NS
- BSS (Blind Source Separation) 算法支持双通道处理,能够很好的将目标声源和其余干扰音进行盲源分离,从而提取出有用音频信号,保证了后级语音的质量。
- NS (Noise Suppression) 算法支持单通道处理,能够对单通道音频中的非人声噪声进行抑制,尤其针对稳态噪声,具有很好的抑制效果。
- 具体采用哪一个算法,根据配置的麦克风数量定义。
- MISO
- MISO (Multi Input Single Output) 算法支持双通道输入,单通道输出。用于在双麦场景,没有唤醒使能的情况下,选择信噪比高的一路音频输出。
- AGC
- AGC (Automatic Gain Control) 动态调整输出音频的幅值,当弱信号输入时,放大输出幅度;当输入信号达到一定强度时,压缩输出幅度。
对应的流程图如下:
3.3 配置代码参考
#define AFE_CONFIG_DEFAULT() { \.aec_init = true, \ //AEC 算法是否使能.se_init = true, \ //BSS/NS 算法是否使能.vad_init = true, \ //VAD 是否使能 ( 仅可在语音识别场景中使用 ).wakenet_init = true, \ //唤醒是否使能..voice_communication_init = false, \ //语音通话是否使能。与 wakenet_init 不能同时使能..voice_communication_agc_init = false, \ //语音通话中AGC是否使能.voice_communication_agc_gain = 15, \ //AGC的增益值,单位为dB.vad_mode = VAD_MODE_3, \ //VAD 检测的操作模式,越大越激进.wakenet_model_name = NULL, \ //选择唤醒词模型.wakenet_mode = DET_MODE_2CH_90, \ //唤醒的模式。对应为多少通道的唤醒,根据mic通道的数量选择.afe_mode = SR_MODE_LOW_COST, \ //SR_MODE_LOW_COST: 量化版本,占用资源较少。 //SR_MODE_HIGH_PERF: 非量化版本,占用资源较多。.afe_perferred_core = 0, \ //AFE 内部 BSS/NS/MISO 算法,运行在哪个 CPU 核.afe_perferred_priority = 5, \ //AFE 内部 BSS/NS/MISO 算法,运行的task优先级。.afe_ringbuf_size = 50, \ //内部 ringbuf 大小的配置.memory_alloc_mode = AFE_MEMORY_ALLOC_MORE_PSRAM, \ //绝大部分从外部psram分配.agc_mode = AFE_MN_PEAK_AGC_MODE_2, \ //线性放大喂给后续multinet的音频,峰值处为 -4dB。.pcm_config.total_ch_num = 3, \ //total_ch_num = mic_num + ref_num.pcm_config.mic_num = 2, \ //音频的麦克风通道数。目前仅支持配置为 1 或 2。.pcm_config.ref_num = 1, \ //音频的参考回路通道数,目前仅支持配置为 0 或 1。
}
4 AI语音模型
4.1 WakeNet
4.1.1 通过 menuconfig 选择模型
wn9_hiesp(最新的 wn9 都是默认 8 bit 量化): 版本 9 ,唤醒词是 hi,esp
4.2 multinet
4.2.1 通过 menuconfig 选择模型
mn4q8_cn : 版本 4 ,8 bit 量化,中文命令词
4.3 添加命令词
4.3.1 通过 menuconfig 添加命令词
-
中文命令词直接添加拼音:打开空调(da kai kong tiao),也支持多句话支持同一个 COMMAND ID , 最大风速/最高风速
添加方言命令词:添加对应的发音
-
英文命令词需要添加对应的音素,通过 python 脚本生成
4.3.2 代码中动态添加命令词
esp_mn_commands_add(i, token);
通过调用 api 实现动态添加命令词。
算法性能
仅消耗约 20% CPU, 30 KB SRAM 和 500 KB PSRAM
5 麦克风设计
5.1 麦克风性能推荐
-
麦克类型:全向型 MEMS ⻨克⻛。
-
灵敏度:
- 1 Pa 声压下模拟⻨灵敏度不低于 -38 dBV,数字⻨灵敏度要求不低于 -26 dB
- 公差控制在 ±2 dB,对于⻨克阵列推荐采⽤ ±1 dB 公差
-
信噪比
信噪⽐不低于 62 dB,推荐 >64 dB :
信噪比越高声音越保真
- Frequency response:频率响应在 50 ~16 kHz 范围内的波动在 ±3 dB 之内
- 电源抑制比(PSRR):n >55 dB(MEMS MIC)
6 结构设计建议
-
⻨克孔孔径或宽度推荐⼤于 1 mm,拾⾳管道尽量短,腔体尽可能⼩,保证⻨克和结构组件配合的谐振频 率在 9 KHz 以上。
-
拾⾳孔深度和直径⽐⼩于 2:1,壳体厚度推荐1 mm,如果壳体过厚,需增⼤开孔⾯积。
-
⻨克孔上需通过防尘⽹进⾏保护。
-
⻨克⻛与设备外壳之间必须加硅胶套或泡棉等进⾏密封和防震,需进⾏过盈配合设计,以保证⻨克的密封性。
-
⻨克孔不能被遮挡,底部拾⾳的⻨克孔需结构上增加凸起,避免⻨克孔被桌⾯等遮挡。
-
⻨克需远离喇叭等会产⽣噪⾳或振动的物体摆放,且与喇叭⾳腔之间通过橡胶垫等隔离缓冲。
7 代码讲解(CN_SPEECH_COMMANDS_RECOGNITION)
7.1 头文件
#include "esp_wn_iface.h" //唤醒词模型的一系列API
#include "esp_wn_models.h" //根据输入的模型名称得到具体的唤醒词模型
#include "esp_afe_sr_iface.h" //语音识别的音频前端算法的一系列API
#include "esp_afe_sr_models.h" //语音前端模型的声明
#include "esp_mn_iface.h" //命令词模型的一系列API
#include "esp_mn_models.h" //命令词模型的声明
#include "esp_board_init.h" //开发板硬件初始化
#include "driver/i2s.h" //i2s 驱动
#include "speech_commands_action.h" //根据识别到的 command 进行语音播报/闪烁 LED
#include "model_path.h" //从 spiffs 文件管理中返回模型路径等 API
7.2 app_main
void app_main()
{models = esp_srmodel_init("model"); //spiffs 中的所有可用模型或 model 默认是从`flash`读ESP_ERROR_CHECK(esp_board_init(AUDIO_HAL_08K_SAMPLES, 1, 16)); //Special config for dev board // ESP_ERROR_CHECK(esp_sdcard_init("/sdcard", 10)); //初始化 SD card
#if defined CONFIG_ESP32_KORVO_V1_1_BOARDled_init(); //LED 初始化
#endifafe_handle = &ESP_AFE_SR_HANDLE; afe_config_t afe_config = AFE_CONFIG_DEFAULT(); //音频前端的配置项afe_config.wakenet_model_name = esp_srmodel_filter(models, ESP_WN_PREFIX, NULL);; //从有所可用的模型中找到唤醒词模型的名字
#if defined CONFIG_ESP32_S3_BOX_BOARD || defined CONFIG_ESP32_S3_EYE_BOARDafe_config.aec_init = false;
#endif//afe_config.aec_init = false; //关闭 AEC//afe_config.se_init = false; //关闭 SE//afe_config.vad_init = false; //关闭VAD//afe_config.pcm_config.total_ch_num = 2; //设置为单麦单回采//afe_config.pcm_config.mic_num = 1; //麦克风通道一esp_afe_sr_data_t *afe_data = afe_handle->create_from_config(&afe_config);xTaskCreatePinnedToCore(&feed_Task, "feed", 4 * 1024, (void*)afe_data, 5, NULL, 0); //feed 从 i2s 拿到音频数据xTaskCreatePinnedToCore(&detect_Task, "detect", 8 * 1024, (void*)afe_data, 5, NULL, 1); //将音频数据喂给模型获取检测结果#if defined CONFIG_ESP32_S3_KORVO_1_V4_0_BOARD || defined CONFIG_ESP32_KORVO_V1_1_BOARDxTaskCreatePinnedToCore(&led_Task, "led", 2 * 1024, NULL, 5, NULL, 0); //开启LED
#endif
#if defined CONFIG_ESP32_S3_KORVO_1_V4_0_BOARD || CONFIG_ESP32_S3_KORVO_2_V3_0_BOARD || CONFIG_ESP32_KORVO_V1_1_BOARDxTaskCreatePinnedToCore(&play_music, "play", 2 * 1024, NULL, 5, NULL, 1); //开启语音播报
#endif
}
7.2 feed 操作
void feed_Task(void *arg)
{esp_afe_sr_data_t *afe_data = arg;int audio_chunksize = afe_handle->get_feed_chunksize(afe_data);int nch = afe_handle->get_channel_num(afe_data);int feed_channel = esp_get_feed_channel(); //3;int16_t *i2s_buff = malloc(audio_chunksize * sizeof(int16_t) * feed_channel);assert(i2s_buff);size_t bytes_read;while (1) {//第一种方式 //audio_chunksize:音频时间 512->32ms 256->16ms//int16_t:16位量化//feed_channel:两麦克风通道数据一回采通道数据esp_get_feed_data(i2s_buff, audio_chunksize * sizeof(int16_t) * feed_channel);//第二种方式i2s_read(I2S_NUM_1, i2s_buff, audio_chunksize * sizeof(int16_t) * feed_channel, &bytes_read, portMAX_DELAY);afe_handle->feed(afe_data, i2s_buff);}afe_handle->destroy(afe_data);vTaskDelete(NULL);
}
7.3 detect 操作
void detect_Task(void *arg)
{esp_afe_sr_data_t *afe_data = arg;int afe_chunksize = afe_handle->get_fetch_chunksize(afe_data);int nch = afe_handle->get_channel_num(afe_data);char *mn_name = esp_srmodel_filter(models, ESP_MN_PREFIX, ESP_MN_CHINESE); //从模型队列中获取命令词模型名字printf("multinet:%s\n", mn_name);esp_mn_iface_t *multinet = esp_mn_handle_from_name(mn_name); //获取命令词模型model_iface_data_t *model_data = multinet->create(mn_name, 5760); //创建esp_mn_commands_update_from_sdkconfig(multinet, model_data); // Add speech commands from sdkconfigint mu_chunksize = multinet->get_samp_chunksize(model_data);int chunk_num = multinet->get_samp_chunknum(model_data);assert(mu_chunksize == afe_chunksize);printf("------------detect start------------\n");// FILE *fp = fopen("/sdcard/out1", "w");// if (fp == NULL) printf("can not open file\n");while (1) {afe_fetch_result_t* res = afe_handle->fetch(afe_data); //获得AEF的处理结果if (!res || res->ret_value == ESP_FAIL) {printf("fetch error!\n");break;}
#if CONFIG_IDF_TARGET_ESP32if (res->wakeup_state == WAKENET_DETECTED) { printf("wakeword detected\n");play_voice = -1;detect_flag = 1;afe_handle->disable_wakenet(afe_data);printf("-----------listening-----------\n");}
#elif CONFIG_IDF_TARGET_ESP32S3if (res->wakeup_state == WAKENET_DETECTED) { printf("WAKEWORD DETECTED\n"); //如果被唤醒将唤醒标志置位True} else if (res->wakeup_state == WAKENET_CHANNEL_VERIFIED) {play_voice = -1;detect_flag = 1;printf("AFE_FETCH_CHANNEL_VERIFIED, channel index: %d\n", res->trigger_channel_id);}
#endifif (detect_flag == 1) {esp_mn_state_t mn_state = multinet->detect(model_data, res->data); //将AFE处理后的音频数据给命令词模型if (mn_state == ESP_MN_STATE_DETECTING) {continue;}if (mn_state == ESP_MN_STATE_DETECTED) {esp_mn_results_t *mn_result = multinet->get_results(model_data); //得到结果for (int i = 0; i < mn_result->num; i++) {printf("TOP %d, command_id: %d, phrase_id: %d, prob: %f\n", i+1, mn_result->command_id[i], mn_result->phrase_id[i], mn_result->prob[i]);}printf("\n-----------listening-----------\n");}if (mn_state == ESP_MN_STATE_TIMEOUT) { //超时关闭afe_handle->enable_wakenet(afe_data);detect_flag = 0;printf("\n-----------awaits to be waken up-----------\n");continue;}}}afe_handle->destroy(afe_data);vTaskDelete(NULL);
}
8 乐鑫 AI 相关 Github 参考
- esp-sr:同时可以参考 esp-sr 文档
- esp-skainet
相关文章:

音频基础知识简述 esp-sr 上手指南
此篇博客先对音频基础知识进行简要叙述,然后帮助读者入门 esp-sr SDK。 1 音频的基本概念 1.1 声音的本质 声音的本质是波在介质中的传播现象,声波的本质是一种波,是一种物理量。 两者不一样,声音是一种抽象的,是声…...

Flex弹性布局一文通【最全Flex教学】
文章目录一.Flex布局1.1 传统布局和flex布局1.1.1 传统布局1.1.2 flex弹性布局1.2 flex初步体验1.3 布局原理二.常见Flex属性2.1 常见父项属性2.2 flex-direction主轴的方向2.3 justify-content设置主轴上的子元素排列方式2.4 设置子元素是否flex-wrap换行2.5 align-itmes设置侧…...

Navicat使用教程
Navicat:一个可以对别人的数据库进行操作的软件(需要与如mysql等数据库配套使用) 1. 下载mysql MySQL :: Download MySQL Community Server (Archived Versions) 下载上面那个版本 下载下来是个压缩包,解压 2.配置mysql (1)在…...

35岁测试人该何去何从?10年工作经验的我,只不过是一年的工作经验用了10年......
如果到了这个年龄,还是初级测试,或者只会一些简单的自动化测试,那么真的是不好干了。 35的年龄,企业对员工是有另一层面的考量。 简单来说,就是年龄上去了,能力也要上去,要么是技术专家&#…...

SpringBoot 项目中集成 Prometheus 和 Grafana
项目上线后,除了能保障正常运行以外,也需要服务运行的各个指标进行监控,例如 服务器CPU、内存使用占比,Full GC 执行时间等,针对一些指标出现异常,可以加入一些报警机制能及时反馈给开发运维。这样…...
红队APT——反朔源流量加密CSMSF证书指纹C2项目CDN域前置
目录 0x01 背景交代 0x02 常见红蓝对抗中红队面临问题 0x03 蓝队发现处置情况...

Linux环境下实现并详细分析c/cpp线程池(附源码)
一、线程池原理 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。 线程池是一种多线程处理形式,处理过程中将任务添加到…...

移动web(三)
her~~llo,我是你们的好朋友Lyle,是名梦想成为计算机大佬的男人! 博客是为了记录自我的学习历程,加强记忆方便复习,如有不足之处还望多多包涵!非常欢迎大家的批评指正。 媒体查询 目标:能够根据…...

macbook怎么运行exe文件 mac打开exe文件的三大方法
exe文件是Windows系统的可执行文件,虽然Mac系统上无法直接打开exe文件,但是你可以在Mac电脑上安装双系统或者虚拟机来实现mac电脑上运行exe文件。除了这两种方法之外,你还可以在Mac电脑上使用类虚拟机软件打开exe文件,这三种方法各…...
GoldenGate(OGG)高可用XAG部署
前言: 本文档主要描述通过Oracle Grid Infrastructure Agents (XAG)基于Oracle RAC实现GoldenGate(OGG)软件高可用的实施操作 环境信息: 源端 目标端 节点一IP 节点二IP 192.168.1.84 192.168.1.86 节点一IP 节点二IP 192.168.1.200 192.168.1.210 VIP 192.…...

如何使用Docker容器部署O2OA(翱途)开发平台与OnlyOffice的集成版本?
O2OA(翱途)开发平台[下称O2OA平台或者O2OA]默认可以和OnlyOffice进行集成来实现在线文档编辑以及流程集成。开发者可以直接安装O2OA官网的OnlyOfficeO2Server的Docker版本用于体验。本文将详细介绍如何安装O2OA OnlyOffice的Docker版本。OnlyOffice Docs Sever可以单独安装,O2…...

springboot复习(黑马)(持续更新)
学习目标基于SpringBoot框架的程序开发步骤熟练使用SpringBoot配置信息修改服务器配置基于SpringBoot的完成SSM整合项目开发一、SpringBoot简介1. 入门案例问题导入SpringMVC的HelloWord程序大家还记得吗?SpringBoot是由Pivotal团队提供的全新框架,其设计…...

K_A16_001 基于STM32等单片机驱动HX711称重模块 串口与OLED0.96双显示
K_A16_001 基于STM32等单片机驱动HX711称重模块 串口与OLED0.96双显示一、资源说明二、基本参数参数引脚说明三、驱动说明对应程序:四、部分代码说明1、接线引脚定义1.1、STC89C52RCHX711称重模块1.2、STM32F103C8T6HX711称重模块五、基础知识学习与相关资料下载六、视频效果展…...

单例模式之饿汉式
目录 1 单例模式的程序结构 2 饿汉式单例模式的实现 3 饿汉式线程安全 4 防止反射破坏单例 5 总结 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。所谓单例就是在系统中只有一个该类的实例,并且提供一个访问该实例的全局…...

软件测试培训三个月,找到工作了11K,面试总结分享给大家
功能方面:问的最多的就是测试流程,测试计划包含哪些内容,公司人员配置,有bug开发认为不是 bug怎么处理,怎样才算是好的用例,测试用例设计方法(等价类,边界值等概念方法)&…...

Hbase备份与恢复工具Snapshot的基本概念与工作原理
数据库都有相对完善的备份与恢复功能。备份与恢复功能是数据库在数据意外丢失、损坏下的最后一根救命稻草。数据库定期备份、定期演练恢复是当下很多重要业务都在慢慢接受的最佳实践,也是数据库管理者推荐的一种管理规范。HBase数据库最核心的备份与恢复工具——Sna…...

RTOS中事件集的实现原理以及实用应用
事件集的原理 RTOS中事件集的实现原理是通过位掩码来实现的。事件集是一种用于在任务之间传递信号的机制。在RTOS中,事件集通常是一个32位的二进制位向量。每个位都代表一个特定的事件,例如信号、标志、定时器等。 当一个任务等待一个或多个事件时&…...

计及新能源出力不确定性的电气设备综合能源系统协同优化(Matlab代码实现)
运行视频及运行结果: 计及碳排放成本的电-气-热综合能源系纷充节点能价计算方法研究(Matlab代码实现)目录 第一部分 文献一《计及新能源出力不确定性的电气设备综合能源系统协同优化》 0 引言 1 新能源出力不确定性处理 1.1 新…...

推荐几个超实用的开源自动化测试框架
有什么好的开源自动化测试框架可以推荐?为了让大家看文章不蒙圈,文章我将围绕3个方面来阐述: 1、通用自动化测试框架介绍 2、Java语言下的自动化测试框架 3、Python语言下的自动化测试框架 随着计算机技术人员的大量增加,通过编写…...
Mac 上解压缩 RAR 文件
RAR 在十几年前的互联网曾叱咤风云般的存在。在那时,你所能见到的压缩文件几乎都是 RAR 格式,大家在 Windows 上使用的压缩、解压缩软件基本都是 WinRAR。虽然这些年使用 RAR 格式的压缩包的情况在逐渐减少,但是你还是经常能在国内各种网站下…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...

Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...

如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的
修改bug思路: 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑:async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...

【笔记】WSL 中 Rust 安装与测试完整记录
#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统:Ubuntu 24.04 LTS (WSL2)架构:x86_64 (GNU/Linux)Rust 版本:rustc 1.87.0 (2025-05-09)Cargo 版本:cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化
缓存架构 代码结构 代码详情 功能点: 多级缓存,先查本地缓存,再查Redis,最后才查数据库热点数据重建逻辑使用分布式锁,二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...

Web后端基础(基础知识)
BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。 优点:维护方便缺点:体验一般 CS架构:Client/Server,客户端/服务器架构模式。需要单独…...
深入浅出Diffusion模型:从原理到实践的全方位教程
I. 引言:生成式AI的黎明 – Diffusion模型是什么? 近年来,生成式人工智能(Generative AI)领域取得了爆炸性的进展,模型能够根据简单的文本提示创作出逼真的图像、连贯的文本,乃至更多令人惊叹的…...