从声源定位(DOA)算法仿真到工程源码实现-第八节

一、概述

        本节我们记录在respeaker core v2 开发板上部署一个完整的声源定位(DOA)系统,演示可以看第一节中的视频。整个模块可以分为三部分,第一部分为控制开发板上的LED灯显示,这样可以实时的测试算法的效果;第二部分为从ALSA上取数据,我们这里需要取六通道的麦克风数据,加上最后两个通道的回采信号,总共八个通道;第三部分为DOA算法部分,这里主要实现了SRP-PHAT算法。LED灯的控制程序和声源定位算法程序是两个进程同时运行,进程之间通过管道来通信,声源定位算法向管道输入定位的角度信息,LED灯的控制程序从管道获取角度信息,进而控制灯的或亮或灭。

二、模块解析

2.1 整体效果

        从声源定位(DOA)算法仿真到工程源码实现-第一节-CSDN博客

2.2 LED灯控

(1)代码结构

respeaker_led
├── examples
│   └── led_show.py
└── pixel_ring└── apa102.py

(2)led_show.py

import time
import sys
import os
import timesys.path.append("../pixel_ring/")
from apa102 import APA102class HiPixelRing(object):PIXELS_N = 12def __init__(self):self.dev = APA102(num_led=self.PIXELS_N)def off(self):for i in range(self.PIXELS_N):self.dev.set_pixel(i, 0, 0, 0)self.dev.show()self.dev.show()def wakeup(self, direction=0):led_num  = (direction + 15) // 30led_num = led_num % 12#led_num = int(led_num)for i in range(self.PIXELS_N):if i != led_num:self.dev.set_pixel(i, 0, 0, 0)else:self.dev.set_pixel(i, 10, 10, 10)self.dev.show()if __name__ == '__main__':pixel_ring = HiPixelRing()direction = 0input_file = "/tmp/node2_to_node1.tmp"# 1.create fifoif not os.path.exists(input_file):os.mkfifo(input_file, 0o666)# 2.open pipeprint('init read pipe:  ' + input_file)fin = os.open(input_file, os.O_RDONLY)val = ""while True:try:#recv_str = os.read(fin, 1024).decode()[:-1]recv_str = os.read(fin, 1).decode()if recv_str != 'T':val += recv_strcontinueelse:recv_str = valval = ""print("recv:{}".format(recv_str))direction = int(recv_str)pixel_ring.wakeup(direction)#direction += 30#time.sleep(0.5)except KeyboardInterrupt:breakos.close(fin)pixel_ring.off()time.sleep(1)

(3)apa102.py

"""
from https://github.com/tinue/APA102_Pi
This is the main driver module for APA102 LEDs
"""
import spidev
from math import ceilRGB_MAP = { 'rgb': [3, 2, 1], 'rbg': [3, 1, 2], 'grb': [2, 3, 1],'gbr': [2, 1, 3], 'brg': [1, 3, 2], 'bgr': [1, 2, 3] }class APA102:"""Driver for APA102 LEDS (aka "DotStar").(c) Martin Erzberger 2016-2017My very first Python code, so I am sure there is a lot to be optimized ;)Public methods are:- set_pixel- set_pixel_rgb- show- clear_strip- cleanupHelper methods for color manipulation are:- combine_color- wheelThe rest of the methods are used internally and should not be used by theuser of the library.Very brief overview of APA102: An APA102 LED is addressed with SPI. The bitsare shifted in one by one, starting with the least significant bit.An LED usually just forwards everything that is sent to its data-in todata-out. While doing this, it remembers its own color and keeps glowingwith that color as long as there is power.An LED can be switched to not forward the data, but instead use the datato change it's own color. This is done by sending (at least) 32 bits ofzeroes to data-in. The LED then accepts the next correct 32 bit LEDframe (with color information) as its new color setting.After having received the 32 bit color frame, the LED changes color,and then resumes to just copying data-in to data-out.The really clever bit is this: While receiving the 32 bit LED frame,the LED sends zeroes on its data-out line. Because a color frame is32 bits, the LED sends 32 bits of zeroes to the next LED.As we have seen above, this means that the next LED is now readyto accept a color frame and update its color.So that's really the entire protocol:- Start by sending 32 bits of zeroes. This prepares LED 1 to updateits color.- Send color information one by one, starting with the color for LED 1,then LED 2 etc.- Finish off by cycling the clock line a few times to get all datato the very last LED on the stripThe last step is necessary, because each LED delays forwarding the dataa bit. Imagine ten people in a row. When you yell the last colorinformation, i.e. the one for person ten, to the first person inthe line, then you are not finished yet. Person one has to turn aroundand yell it to person 2, and so on. So it takes ten additional "dummy"cycles until person ten knows the color. When you look closer,you will see that not even person 9 knows its own color yet. Thisinformation is still with person 2. Essentially the driver sends additionalzeroes to LED 1 as long as it takes for the last color frame to make itdown the line to the last LED."""# ConstantsMAX_BRIGHTNESS = 0b11111 # Safeguard: Set to a value appropriate for your setupLED_START = 0b11100000 # Three "1" bits, followed by 5 brightness bitsdef __init__(self, num_led, global_brightness=MAX_BRIGHTNESS,order='rgb', bus=0, device=1, max_speed_hz=8000000):self.num_led = num_led  # The number of LEDs in the Striporder = order.lower()self.rgb = RGB_MAP.get(order, RGB_MAP['rgb'])# Limit the brightness to the maximum if it's set higherif global_brightness > self.MAX_BRIGHTNESS:self.global_brightness = self.MAX_BRIGHTNESSelse:self.global_brightness = global_brightnessself.leds = [self.LED_START,0,0,0] * self.num_led # Pixel bufferself.spi = spidev.SpiDev()  # Init the SPI deviceself.spi.open(bus, device)  # Open SPI port 0, slave device (CS) 1# Up the speed a bit, so that the LEDs are painted fasterif max_speed_hz:self.spi.max_speed_hz = max_speed_hzdef clock_start_frame(self):"""Sends a start frame to the LED strip.This method clocks out a start frame, telling the receiving LEDthat it must update its own color now."""self.spi.xfer2([0] * 4)  # Start frame, 32 zero bitsdef clock_end_frame(self):"""Sends an end frame to the LED strip.As explained above, dummy data must be sent after the last real colourinformation so that all of the data can reach its destination down the line.The delay is not as bad as with the human example above.It is only 1/2 bit per LED. This is because the SPI clock lineneeds to be inverted.Say a bit is ready on the SPI data line. The sender communicatesthis by toggling the clock line. The bit is read by the LEDand immediately forwarded to the output data line. When the clock goesdown again on the input side, the LED will toggle the clock upon the output to tell the next LED that the bit is ready.After one LED the clock is inverted, and after two LEDs it is in syncagain, but one cycle behind. Therefore, for every two LEDs, one bitof delay gets accumulated. For 300 LEDs, 150 additional bits must be fed tothe input of LED one so that the data can reach the last LED.Ultimately, we need to send additional numLEDs/2 arbitrary data bits,in order to trigger numLEDs/2 additional clock changes. This driversends zeroes, which has the benefit of getting LED one partially orfully ready for the next update to the strip. An optimized versionof the driver could omit the "clockStartFrame" method if enough zeroes havebeen sent as part of "clockEndFrame"."""self.spi.xfer2([0xFF] * 4)# Round up num_led/2 bits (or num_led/16 bytes)#for _ in range((self.num_led + 15) // 16):#    self.spi.xfer2([0x00])def clear_strip(self):""" Turns off the strip and shows the result right away."""for led in range(self.num_led):self.set_pixel(led, 0, 0, 0)self.show()def set_pixel(self, led_num, red, green, blue, bright_percent=100):"""Sets the color of one pixel in the LED stripe.The changed pixel is not shown yet on the Stripe, it is onlywritten to the pixel buffer. Colors are passed individually.If brightness is not set the global brightness setting is used."""if led_num < 0:return  # Pixel is invisible, so ignoreif led_num >= self.num_led:return  # again, invisible# Calculate pixel brightness as a percentage of the# defined global_brightness. Round up to nearest integer# as we expect some brightness unless set to 0brightness = int(ceil(bright_percent*self.global_brightness/100.0))# LED startframe is three "1" bits, followed by 5 brightness bitsledstart = (brightness & 0b00011111) | self.LED_STARTstart_index = 4 * led_numself.leds[start_index] = ledstartself.leds[start_index + self.rgb[0]] = redself.leds[start_index + self.rgb[1]] = greenself.leds[start_index + self.rgb[2]] = bluedef set_pixel_rgb(self, led_num, rgb_color, bright_percent=100):"""Sets the color of one pixel in the LED stripe.The changed pixel is not shown yet on the Stripe, it is onlywritten to the pixel buffer.Colors are passed combined (3 bytes concatenated)If brightness is not set the global brightness setting is used."""self.set_pixel(led_num, (rgb_color & 0xFF0000) >> 16,(rgb_color & 0x00FF00) >> 8, rgb_color & 0x0000FF,bright_percent)def rotate(self, positions=1):""" Rotate the LEDs by the specified number of positions.Treating the internal LED array as a circular buffer, rotate it bythe specified number of positions. The number could be negative,which means rotating in the opposite direction."""cutoff = 4 * (positions % self.num_led)self.leds = self.leds[cutoff:] + self.leds[:cutoff]def show(self):"""Sends the content of the pixel buffer to the strip.Todo: More than 1024 LEDs requires more than one xfer operation."""self.clock_start_frame()# xfer2 kills the list, unfortunately. So it must be copied first# SPI takes up to 4096 Integers. So we are fine for up to 1024 LEDs.data = list(self.leds)while data:self.spi.xfer2(data[:32])data = data[32:]self.clock_end_frame()def cleanup(self):"""Release the SPI device; Call this method at the end"""self.spi.close()  # Close SPI port@staticmethoddef combine_color(red, green, blue):"""Make one 3*8 byte color value."""return (red << 16) + (green << 8) + bluedef wheel(self, wheel_pos):"""Get a color from a color wheel; Green -> Red -> Blue -> Green"""if wheel_pos > 255:wheel_pos = 255 # Safeguardif wheel_pos < 85:  # Green -> Redreturn self.combine_color(wheel_pos * 3, 255 - wheel_pos * 3, 0)if wheel_pos < 170:  # Red -> Bluewheel_pos -= 85return self.combine_color(255 - wheel_pos * 3, 0, wheel_pos * 3)# Blue -> Greenwheel_pos -= 170return self.combine_color(0, wheel_pos * 3, 255 - wheel_pos * 3)def dump_array(self):"""For debug purposes: Dump the LED array onto the console."""print(self.leds)

2.3 ALSA取数据

(1)ALSA读数据及DOA算法调用

#define ALSA_PCM_NEW_HW_PARAMS_API#include <alsa/asoundlib.h>
#include <stdio.h>
#include "doa-api.h"
#define NUM_FRAMES 160
#define OUTPUT_PATH_NAME "/tmp/node2_to_node1.tmp"int main() {int fout = open(OUTPUT_PATH_NAME, O_WRONLY);char buffer2[1024];    long loops;int rc;int size;unsigned int val;int dir;char *buffer;snd_pcm_t *handle;snd_pcm_hw_params_t *params;snd_pcm_uframes_t frames;int mic_num = 6;float radius = 0.0465;int channel_num = 8;void *handle1 = api_create_doa_handle(mic_num, radius);//short *input_data = (short*)malloc(sizeof(short) * channel_num * NUM_FRAMES);float *inp_float = (float*)malloc(sizeof(float) * mic_num * NUM_FRAMES);/*以录制模式打开*//* Open PCM device for recording (capture). */rc = snd_pcm_open( &handle, "default", SND_PCM_STREAM_CAPTURE, 0);if (rc < 0) {fprintf(stderr, "unable to open pcm device");exit(EXIT_FAILURE);}/*分配一个参数对象*//* Allocate a hardware parameters object. */snd_pcm_hw_params_alloca(&params);/*初始化参数对象*//* Fill it in with default values. */rc = snd_pcm_hw_params_any(handle, params);if (rc < 0) {printf("Err\n");}/* Set the desired hardware parameters. *//*交错模式*//* Interleaved mode */rc = snd_pcm_hw_params_set_access(handle, params,SND_PCM_ACCESS_RW_INTERLEAVED);if (rc < 0) {printf("Err\n");}/*PCM格式*//* Signed 16-bit little-endian format */rc = snd_pcm_hw_params_set_format(handle, params,SND_PCM_FORMAT_S16_LE);if (rc < 0) {printf("Err\n");}/*设置通道数*//* Two channels (stereo) */rc = snd_pcm_hw_params_set_channels(handle, params, 8);if (rc < 0) {printf("Err\n");}/*设置采样率*//* 44100 bits/second sampling rate (CD quality) */val = 16000;rc = snd_pcm_hw_params_set_rate_near(handle, params,&val, &dir);if (rc < 0) {printf("Err\n");}/*没周期的帧数*//* Set period size to 32 frames. */frames = 160;rc = snd_pcm_hw_params_set_period_size_near(handle,params, &frames, &dir);if (rc < 0) {printf("Err\n");}/* Write the parameters to the driver */rc = snd_pcm_hw_params(handle, params);if (rc < 0) {fprintf(stderr,"unable to set hw parameters: %s/n",snd_strerror(rc));exit(1);}/* Use a buffer large enough to hold one period */rc = snd_pcm_hw_params_get_period_size(params,&frames, &dir);if (rc < 0) {printf("Err\n");}size = frames * 2 * 8; /* 2 bytes/sample, 2 channels */buffer = (char *) malloc(size);/* We want to loop for 5 seconds */rc = snd_pcm_hw_params_get_period_time(params, &val, &dir);loops = 5000000 / val;printf("====================:%ld\n", frames);printf("====================\n");printf("====================\n");FILE *fp = fopen("record.pcm", "wb");while (loops > 0) {//loops--;rc = snd_pcm_readi(handle, buffer, frames);if (rc == -EPIPE) {/* EPIPE means overrun */fprintf(stderr, "overrun occurred/n");//把PCM流置于PREPARED状态,这样下次我们向该PCM流中数据时,它就能重新开始处理数据。snd_pcm_prepare(handle);} else if (rc < 0) {fprintf(stderr,"error from read: %s/n",snd_strerror(rc));} else if (rc != (int)frames) {fprintf(stderr, "short read, read %d frames/n", rc);}//rc = write(1, buffer, size);short *input_data_x = (short*)buffer;for (int i = 0; i < NUM_FRAMES; i++) {for (int j = 0; j < mic_num; j++) {inp_float[i*mic_num+j] = input_data_x[i*channel_num+j];}}int angle = api_process_doa(handle1, inp_float, NUM_FRAMES);memset(buffer2, 0, sizeof(buffer2));sprintf(buffer2, "%dT", angle);if (write(fout, buffer2, strlen(buffer2)) <= 0) {break;}printf(">>> %d\n", angle);/*rc = fwrite(buffer, 1, size, fp);if (rc != size)fprintf(stderr,"short write: wrote %d bytes/n", rc);*/}//调用snd_pcm_drain把所有挂起没有传输完的声音样本传输完全rc = snd_pcm_drain(handle);//关闭该音频流,释放之前动态分配的缓冲区,退出rc = snd_pcm_close(handle);free(buffer);fclose(fp);api_destroy_doa_handle(handle1);return 0;
}

2.4 DOA算法

(1)代码结构

doa
├── CMakeLists.txt
├── bin
│   ├── CMakeLists.txt
│   ├── alsa-doa.c
│   └── test-doa.c
├── build
│   ├── CMakeCache.txt
│   ├── CMakeFiles
│   │   ├── 3.22.1
│   │   │   ├── CMakeCCompiler.cmake
│   │   │   ├── CMakeCXXCompiler.cmake
│   │   │   ├── CMakeDetermineCompilerABI_C.bin
│   │   │   ├── CMakeDetermineCompilerABI_CXX.bin
│   │   │   ├── CMakeSystem.cmake
│   │   │   ├── CompilerIdC
│   │   │   │   ├── CMakeCCompilerId.c
│   │   │   │   ├── a.out
│   │   │   │   └── tmp
│   │   │   └── CompilerIdCXX
│   │   │       ├── CMakeCXXCompilerId.cpp
│   │   │       ├── a.out
│   │   │       └── tmp
│   │   ├── CMakeDirectoryInformation.cmake
│   │   ├── CMakeOutput.log
│   │   ├── CMakeTmp
│   │   ├── Makefile.cmake
│   │   ├── Makefile2
│   │   ├── TargetDirectories.txt
│   │   ├── cmake.check_cache
│   │   └── progress.marks
│   ├── Makefile
│   ├── bin
│   │   ├── CMakeFiles
│   │   │   ├── CMakeDirectoryInformation.cmake
│   │   │   ├── alsa-doa.dir
│   │   │   │   ├── DependInfo.cmake
│   │   │   │   ├── alsa-doa.c.o
│   │   │   │   ├── alsa-doa.c.o.d
│   │   │   │   ├── build.make
│   │   │   │   ├── cmake_clean.cmake
│   │   │   │   ├── compiler_depend.make
│   │   │   │   ├── compiler_depend.ts
│   │   │   │   ├── depend.make
│   │   │   │   ├── flags.make
│   │   │   │   ├── link.txt
│   │   │   │   └── progress.make
│   │   │   ├── progress.marks
│   │   │   └── test-doa.dir
│   │   │       ├── DependInfo.cmake
│   │   │       ├── build.make
│   │   │       ├── cmake_clean.cmake
│   │   │       ├── compiler_depend.make
│   │   │       ├── compiler_depend.ts
│   │   │       ├── depend.make
│   │   │       ├── flags.make
│   │   │       ├── link.txt
│   │   │       ├── progress.make
│   │   │       ├── test-doa.c.o
│   │   │       └── test-doa.c.o.d
│   │   ├── Makefile
│   │   ├── alsa-doa
│   │   ├── cmake_install.cmake
│   │   └── test-doa
│   ├── cmake_install.cmake
│   └── src
│       ├── CMakeFiles
│       │   ├── CMakeDirectoryInformation.cmake
│       │   ├── mouse-doa.dir
│       │   │   ├── DependInfo.cmake
│       │   │   ├── build.make
│       │   │   ├── cmake_clean.cmake
│       │   │   ├── cmake_clean_target.cmake
│       │   │   ├── compiler_depend.make
│       │   │   ├── compiler_depend.ts
│       │   │   ├── depend.make
│       │   │   ├── doa-api.c.o
│       │   │   ├── doa-api.c.o.d
│       │   │   ├── doa-blocker.c.o
│       │   │   ├── doa-blocker.c.o.d
│       │   │   ├── doa-complex.c.o
│       │   │   ├── doa-complex.c.o.d
│       │   │   ├── doa-fft.c.o
│       │   │   ├── doa-fft.c.o.d
│       │   │   ├── doa-impl.c.o
│       │   │   ├── doa-impl.c.o.d
│       │   │   ├── doa-matrix.c.o
│       │   │   ├── doa-matrix.c.o.d
│       │   │   ├── fft4g.c.o
│       │   │   ├── fft4g.c.o.d
│       │   │   ├── flags.make
│       │   │   ├── link.txt
│       │   │   ├── progress.make
│       │   │   ├── ring_buffer.c.o
│       │   │   └── ring_buffer.c.o.d
│       │   └── progress.marks
│       ├── Makefile
│       ├── cmake_install.cmake
│       └── libmouse-doa.a
├── src
│   ├── CMakeLists.txt
│   ├── doa-api.c
│   ├── doa-api.h
│   ├── doa-blocker.c
│   ├── doa-blocker.h
│   ├── doa-complex.c
│   ├── doa-complex.h
│   ├── doa-fft.c
│   ├── doa-fft.h
│   ├── doa-impl.c
│   ├── doa-impl.h
│   ├── doa-matrix.c
│   ├── doa-matrix.h
│   ├── doa-types.h
│   ├── fft4g.c
│   ├── fft4g.h
│   ├── ring_buffer.c
│   └── ring_buffer.h
└── test└── 120du-180du.pcm

(2)doa-api.c

/**@author : aflyingwolf*@date   : 2025.3.20*@file   : doa-api.c* */
#include "doa-api.h"
#include "doa-blocker.h"
#include "doa-fft.h"
#include "doa-types.h"
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>static float mouse_FloatS16ToFloat(float v) {static const float kMaxInt16Inverse = 1.0 / 32767;static const float kMinInt16Inverse = 1.0 / -32768;return v * (v > 0 ? kMaxInt16Inverse : -kMinInt16Inverse);
}/*
static float mouse_FloatToFloatS16(float v) {return v * (v > 0 ? 32767.0 : 32768.0);
}*/typedef struct mouse_DoaHandle_ {mouse_blocker *blocker_;float **in_buf_;int mic_num_;mouse_doa *doa_inst_;
} mouse_DoaHandle;void *api_create_doa_handle(int mic_num, float radius) {mouse_doa *doa_inst = mouse_doa_instance(kSampleRate,mic_num,radius);//hamming windowsfloat window[512] = {0.08,0.08003477,0.08013909,0.08031292,0.08055626,0.08086906,0.08125127,0.08170284,0.0822237,0.08281376,0.08347295,0.08420116,0.08499828,0.08586418,0.08679875,0.08780184,0.08887329,0.09001294,0.09122063,0.09249617,0.09383936,0.09525001,0.09672789,0.0982728,0.09988448,0.10156271,0.10330722,0.10511775,0.10699403,0.10893578,0.1109427,0.11301448,0.11515082,0.11735139,0.11961586,0.12194389,0.12433512,0.12678919,0.12930573,0.13188437,0.13452471,0.13722635,0.13998888,0.14281189,0.14569495,0.14863762,0.15163946,0.15470002,0.15781883,0.16099542,0.16422931,0.16752001,0.17086702,0.17426984,0.17772796,0.18124085,0.18480797,0.1884288,0.19210278,0.19582935,0.19960796,0.20343803,0.20731899,0.21125024,0.2152312,0.21926125,0.2233398,0.22746622,0.2316399,0.23586019,0.24012646,0.24443807,0.24879437,0.25319469,0.25763837,0.26212475,0.26665313,0.27122284,0.27583319,0.28048347,0.28517299,0.28990103,0.29466689,0.29946984,0.30430915,0.3091841,0.31409394,0.31903793,0.32401534,0.32902539,0.33406735,0.33914043,0.34424389,0.34937694,0.35453881,0.35972872,0.36494588,0.37018951,0.37545881,0.38075299,0.38607124,0.39141277,0.39677676,0.4021624,0.40756889,0.41299539,0.4184411,0.42390518,0.42938682,0.43488518,0.44039943,0.44592874,0.45147227,0.45702919,0.46259865,0.46817981,0.47377183,0.47937386,0.48498506,0.49060458,0.49623157,0.50186517,0.50750453,0.51314881,0.51879715,0.5244487,0.5301026,0.53575799,0.54141402,0.54706984,0.55272459,0.55837742,0.56402747,0.56967389,0.57531582,0.58095241,0.58658281,0.59220616,0.59782163,0.60342835,0.60902548,0.61461218,0.6201876,0.62575089,0.63130122,0.63683774,0.64235963,0.64786604,0.65335614,0.6588291,0.6642841,0.66972031,0.67513691,0.68053307,0.68590799,0.69126085,0.69659084,0.70189716,0.707179,0.71243557,0.71766606,0.72286969,0.72804568,0.73319324,0.73831159,0.74339995,0.74845757,0.75348367,0.75847749,0.76343829,0.7683653,0.77325778,0.77811501,0.78293623,0.78772072,0.79246776,0.79717663,0.80184662,0.80647702,0.81106714,0.81561627,0.82012373,0.82458885,0.82901093,0.83338932,0.83772336,0.84201238,0.84625575,0.85045281,0.85460293,0.8587055,0.86275987,0.86676546,0.87072163,0.87462781,0.8784834,0.88228781,0.88604048,0.88974082,0.89338829,0.89698234,0.90052241,0.90400798,0.90743851,0.91081349,0.91413241,0.91739477,0.92060007,0.92374783,0.92683757,0.92986882,0.93284114,0.93575406,0.93860715,0.94139997,0.94413211,0.94680315,0.94941269,0.95196032,0.95444568,0.95686838,0.95922805,0.96152434,0.9637569,0.9659254,0.9680295,0.97006889,0.97204326,0.97395231,0.97579575,0.97757331,0.97928471,0.98092969,0.98250802,0.98401944,0.98546374,0.98684068,0.98815007,0.98939171,0.9905654,0.99167097,0.99270826,0.99367711,0.99457736,0.99540889,0.99617157,0.99686528,0.99748992,0.99804539,0.99853161,0.99894851,0.99929602,0.99957409,0.99978268,0.99992176,0.99999131,0.99999131,0.99992176,0.99978268,0.99957409,0.99929602,0.99894851,0.99853161,0.99804539,0.99748992,0.99686528,0.99617157,0.99540889,0.99457736,0.99367711,0.99270826,0.99167097,0.9905654,0.98939171,0.98815007,0.98684068,0.98546374,0.98401944,0.98250802,0.98092969,0.97928471,0.97757331,0.97579575,0.97395231,0.97204326,0.97006889,0.9680295,0.9659254,0.9637569,0.96152434,0.95922805,0.95686838,0.95444568,0.95196032,0.94941269,0.94680315,0.94413211,0.94139997,0.93860715,0.93575406,0.93284114,0.92986882,0.92683757,0.92374783,0.92060007,0.91739477,0.91413241,0.91081349,0.90743851,0.90400798,0.90052241,0.89698234,0.89338829,0.88974082,0.88604048,0.88228781,0.8784834,0.87462781,0.87072163,0.86676546,0.86275987,0.8587055,0.85460293,0.85045281,0.84625575,0.84201238,0.83772336,0.83338932,0.82901093,0.82458885,0.82012373,0.81561627,0.81106714,0.80647702,0.80184662,0.79717663,0.79246776,0.78772072,0.78293623,0.77811501,0.77325778,0.7683653,0.76343829,0.75847749,0.75348367,0.74845757,0.74339995,0.73831159,0.73319324,0.72804568,0.72286969,0.71766606,0.71243557,0.707179,0.70189716,0.69659084,0.69126085,0.68590799,0.68053307,0.67513691,0.66972031,0.6642841,0.6588291,0.65335614,0.64786604,0.64235963,0.63683774,0.63130122,0.62575089,0.6201876,0.61461218,0.60902548,0.60342835,0.59782163,0.59220616,0.58658281,0.58095241,0.57531582,0.56967389,0.56402747,0.55837742,0.55272459,0.54706984,0.54141402,0.53575799,0.5301026,0.5244487,0.51879715,0.51314881,0.50750453,0.50186517,0.49623157,0.49060458,0.48498506,0.47937386,0.47377183,0.46817981,0.46259865,0.45702919,0.45147227,0.44592874,0.44039943,0.43488518,0.42938682,0.42390518,0.4184411,0.41299539,0.40756889,0.4021624,0.39677676,0.39141277,0.38607124,0.38075299,0.37545881,0.37018951,0.36494588,0.35972872,0.35453881,0.34937694,0.34424389,0.33914043,0.33406735,0.32902539,0.32401534,0.31903793,0.31409394,0.3091841,0.30430915,0.29946984,0.29466689,0.28990103,0.28517299,0.28048347,0.27583319,0.27122284,0.26665313,0.26212475,0.25763837,0.25319469,0.24879437,0.24443807,0.24012646,0.23586019,0.2316399,0.22746622,0.2233398,0.21926125,0.2152312,0.21125024,0.20731899,0.20343803,0.19960796,0.19582935,0.19210278,0.1884288,0.18480797,0.18124085,0.17772796,0.17426984,0.17086702,0.16752001,0.16422931,0.16099542,0.15781883,0.15470002,0.15163946,0.14863762,0.14569495,0.14281189,0.13998888,0.13722635,0.13452471,0.13188437,0.12930573,0.12678919,0.12433512,0.12194389,0.11961586,0.11735139,0.11515082,0.11301448,0.1109427,0.10893578,0.10699403,0.10511775,0.10330722,0.10156271,0.09988448,0.0982728,0.09672789,0.09525001,0.09383936,0.09249617,0.09122063,0.09001294,0.08887329,0.08780184,0.08679875,0.08586418,0.08499828,0.08420116,0.08347295,0.08281376,0.0822237,0.08170284,0.08125127,0.08086906,0.08055626,0.08031292,0.08013909,0.08003477,0.08};mouse_blocker *blocker = mouse_blocker_instance(160,512,mic_num,window,128,mouse_doa_process_block,doa_inst);mouse_DoaHandle *handle = (mouse_DoaHandle*)malloc(sizeof(mouse_DoaHandle));handle->blocker_ = blocker;handle->doa_inst_ = doa_inst;handle->in_buf_ = (float**)malloc(sizeof(float*) * mic_num);handle->mic_num_ = mic_num;for (int i = 0; i < mic_num; i++) {handle->in_buf_[i] = (float*)malloc(sizeof(float) * 160);}return (void*)handle;
}void api_destroy_doa_handle(void *handle) {mouse_DoaHandle *handle_ = (mouse_DoaHandle *)handle;mouse_doa_destroy(handle_->doa_inst_);mouse_blocker_destroy(handle_->blocker_);for (int i = 0; i < handle_->mic_num_; i++) {free(handle_->in_buf_[i]);}free(handle_->in_buf_);free(handle_);
}int api_start_doa(void *handle) {return 0;
}int api_process_doa(void *handle, float *input_data, int chunk_size) {mouse_DoaHandle *handle_ = (mouse_DoaHandle *)handle;for (int j = 0; j < chunk_size; j++) {for (int i = 0; i < handle_->mic_num_; i++) {handle_->in_buf_[i][j] = mouse_FloatS16ToFloat(input_data[j*handle_->mic_num_ + i]);}}int angle = mouse_blocker_process_chunk(handle_->blocker_,handle_->in_buf_,chunk_size,handle_->mic_num_);return angle;
}
int api_end_doa(void *handle) {return 0;
}

(3)doa-blocker.c

/**@author : aflyingwolf*@date   : 2025.3.20*@file   : doa-blocker.c* */#include "doa-blocker.h"
#include "doa-impl.h"#include <string.h>
#include <stdlib.h>
#include <assert.h>// Pointwise multiplies each channel of |frames| with |window|. Results are
// stored in |frames|.
static void mouse_ApplyWindow(const float* window,size_t num_frames,int num_channels,float* const* frames) {for (int i = 0; i < num_channels; ++i) {for (size_t j = 0; j < num_frames; ++j) {frames[i][j] = frames[i][j] * window[j];}}
}static size_t mouse_gcd(size_t a, size_t b) {size_t tmp;while (b) {tmp = a;a = b;b = tmp % b;}return a;
}mouse_blocker *mouse_blocker_instance(size_t chunk_size,size_t block_size,int num_input_channels,const float* window,size_t shift_amount,mouse_CallbackDoa callback,mouse_doa *doa_inst) {mouse_blocker *inst = (mouse_blocker*)malloc(sizeof(mouse_blocker));inst->chunk_size_ = chunk_size;inst->block_size_ = block_size;inst->num_input_channels_ = num_input_channels;inst->initial_delay_ = block_size - mouse_gcd(chunk_size, shift_amount);inst->frame_offset_ = 0;inst->input_buffer_ = (RingBuffer**)malloc(sizeof(RingBuffer*) * num_input_channels);for (int i = 0; i < num_input_channels; i++) {inst->input_buffer_[i] = WebRtc_CreateBuffer(inst->chunk_size_ + inst->initial_delay_, sizeof(float));}inst->input_block_ = (float**)malloc(sizeof(float*) * num_input_channels);for (int i = 0; i < num_input_channels; i++) {inst->input_block_[i] = (float*)malloc(sizeof(float) * block_size);}inst->window_ = (float*)malloc(sizeof(float) * block_size);inst->shift_amount_ = shift_amount;memcpy(inst->window_, window, block_size * sizeof(float));for (int i = 0; i < num_input_channels; i++) {int moved = WebRtc_MoveReadPtr(inst->input_buffer_[i], -inst->initial_delay_);assert(moved == -inst->initial_delay_);}inst->fft_inst_ = mouse_fft_instance(inst->block_size_);inst->fft_input_block_ = (mouse_complex_f**)malloc(sizeof(mouse_complex_f*) * num_input_channels);for (int i = 0; i < num_input_channels; i++) {inst->fft_input_block_[i] = (mouse_complex_f*)malloc(sizeof(mouse_complex_f) * inst->fft_inst_->complex_length_);}inst->callback_ = callback;inst->doa_inst_ = doa_inst;return inst;
}// destroy a blocker.
void mouse_blocker_destroy(mouse_blocker *inst) {for (int i = 0; i < inst->num_input_channels_; i++) {WebRtc_FreeBuffer(inst->input_buffer_[i]);}free(inst->input_buffer_);for (int i = 0; i < inst->num_input_channels_; i++) {free(inst->input_block_[i]);}free(inst->input_block_);free(inst->window_);mouse_fft_destroy(inst->fft_inst_);for (int i = 0; i < inst->num_input_channels_; i++) {free(inst->fft_input_block_[i]);}free(inst->fft_input_block_);free(inst);
}//process a chunk data.
int mouse_blocker_process_chunk(mouse_blocker *inst,float** input,size_t chunk_size,int num_input_channels) {for (size_t i = 0; i < num_input_channels; ++i) {WebRtc_WriteBuffer(inst->input_buffer_[i], input[i], chunk_size);}size_t first_frame_in_block = inst->frame_offset_;// Loop through blocks.while (first_frame_in_block < inst->chunk_size_) {for (int i = 0; i < inst->num_input_channels_; i++) {WebRtc_ReadBuffer(inst->input_buffer_[i], NULL, inst->input_block_[i], inst->block_size_);WebRtc_MoveReadPtr(inst->input_buffer_[i], -(inst->block_size_ - inst->shift_amount_));}mouse_ApplyWindow(inst->window_, inst->block_size_, inst->num_input_channels_, inst->input_block_);for (int i = 0; i < inst->num_input_channels_; i++) {mouse_fft_forward(inst->fft_inst_, inst->input_block_[i], inst->fft_input_block_[i]);}inst->doa_angle_ = inst->callback_(inst->doa_inst_, inst->fft_input_block_, inst->num_input_channels_, kNumFreqBins);first_frame_in_block += inst->shift_amount_;}// Calculate new starting frames.inst->frame_offset_ = first_frame_in_block - inst->chunk_size_;return inst->doa_angle_;
}

(4)doa-impl.c

/**@author : aflyingwolf*@date   : 2025.3.20*@file   : doa-impl.c* */
#include "doa-impl.h"
#include <stdlib.h>
#include <math.h>mouse_doa *mouse_doa_instance(int sample_rate_hz,int mic_num,float radius) {mouse_doa *inst = (mouse_doa*)malloc(sizeof(mouse_doa));inst->sample_rate_hz_ = sample_rate_hz;inst->num_input_channels_ = mic_num;inst->radius_ = radius;inst->step_ = 30;inst->num_direction_ = 360.0 / inst->step_;inst->mic_angle_ = (float*)malloc(sizeof(float)*inst->num_input_channels_);inst->mic_angle_[0] = 300;inst->mic_angle_[1] = 0;inst->mic_angle_[2] = 60;inst->mic_angle_[3] = 120;inst->mic_angle_[4] = 180;inst->mic_angle_[5] = 240;inst->smooth_len_ = 20;inst->P_ = (float**)malloc(sizeof(float*) * inst->num_direction_);for (int i = 0; i < inst->num_direction_; i++) {inst->P_[i] = (float*)malloc(sizeof(float) * inst->smooth_len_);for (int j = 0; j < inst->smooth_len_; j++) {inst->P_[i][j] = 0.0;}}inst->H_ = (mouse_complex_matrix_f*)malloc(sizeof(mouse_complex_matrix_f) * inst->num_direction_);for (int i = 0; i < inst->num_direction_; i++) {mouse_complex_matrix_init(&(inst->H_[i]), inst->num_input_channels_, kNumFreqBins);float direction = i * inst->step_;mouse_complex_f **mat_els = inst->H_[i].elements_;for (int j = 0; j < inst->num_input_channels_; j++) {float tao = inst->radius_ * sin(90.0 * M_PI / 180.0) * cos((direction - inst->mic_angle_[j]) * M_PI / 180.0) / 340.0;for (int k = 0; k < kNumFreqBins; k++) {float omega = 2.0 * M_PI * k * inst->sample_rate_hz_ / kFftSize;float x = -1.0 * omega * tao;mat_els[j][k].real_ = cos(x);mat_els[j][k].imag_ = sin(x);}}}inst->data_abs_ = (float**)malloc(sizeof(float*) * inst->num_input_channels_);inst->mid_res_ = (mouse_complex_f**)malloc(sizeof(mouse_complex_f*) * inst->num_input_channels_);for (int k = 0; k < inst->num_input_channels_; k++) {inst->data_abs_[k] = (float*)malloc(sizeof(float) * kNumFreqBins);inst->mid_res_[k] = (mouse_complex_f*)malloc(sizeof(mouse_complex_f) * kNumFreqBins);}inst->frame_id_ = 0;inst->start_ = 0;inst->end_ = 128;return inst;
}void mouse_doa_destroy(mouse_doa *inst) {free(inst->mic_angle_);for (int i = 0; i < inst->num_direction_; i++) {free(inst->P_[i]);}free(inst->P_);for (int i = 0; i < inst->num_direction_; i++) {mouse_complex_matrix_free(&(inst->H_[i]));}free(inst->H_);for (int i = 0; i < inst->num_input_channels_; i++) {free(inst->data_abs_[i]);free(inst->mid_res_[i]);}free(inst->data_abs_);free(inst->mid_res_);free(inst);
}void mouse_doa_reset(mouse_doa *inst) {return;
}int mouse_doa_process_block(mouse_doa *inst,mouse_complex_f** input,int num_input_channels,size_t num_freq_bins) {for (int j = 0; j < inst->num_input_channels_; j++) {for (int k = inst->start_; k < inst->end_; k++) {inst->data_abs_[j][k] = sqrt(input[j][k].real_ * input[j][k].real_ + input[j][k].imag_ * input[j][k].imag_);}}//return 45;int max_id = 0;float max_val = 0.0;for (int i = 0; i < inst->num_direction_; i++) {mouse_complex_f **mat_els = inst->H_[i].elements_;for (int j = 0; j < inst->num_input_channels_; j++) {for (int k = inst->start_; k < inst->end_; k++) {inst->mid_res_[j][k] = mouse_complex_mul(mat_els[j][k], input[j][k]);inst->mid_res_[j][k].real_ /= inst->data_abs_[j][k];inst->mid_res_[j][k].imag_ /= inst->data_abs_[j][k];}}for (int j = 1; j < inst->num_input_channels_; j++) {for (int k = inst->start_; k < inst->end_; k++) {inst->mid_res_[0][k] = mouse_complex_add(inst->mid_res_[0][k], inst->mid_res_[j][k]);}}//continue;for (int k = inst->start_; k < inst->end_; k++) {inst->mid_res_[0][k].real_ /= inst->num_input_channels_;inst->mid_res_[0][k].imag_ /= inst->num_input_channels_;}float energy = 0.0;for (int k = inst->start_; k < inst->end_; k++) {energy += inst->mid_res_[0][k].real_ * inst->mid_res_[0][k].real_ + inst->mid_res_[0][k].imag_ * inst->mid_res_[0][k].imag_;}//energy *= energy;inst->frame_id_ = inst->frame_id_ % inst->smooth_len_;inst->P_[i][inst->frame_id_] = energy;float smooth_val = 0.0;for (int k = 0; k < inst->smooth_len_; k++) {smooth_val += inst->P_[i][k];}if (i == 0) {max_id = i;max_val = smooth_val;} else {if (smooth_val > max_val) {max_id = i;max_val = smooth_val;}}}inst->frame_id_ += 1; int angle = max_id * inst->step_; return angle;
}

(5)doa-complex.c

/**@author : aflyingwolf*@date   : 2025.3.20*@file   : doa-complex.c* */#include "doa-complex.h"mouse_complex_f mouse_complex_mul(mouse_complex_f a, mouse_complex_f b) {mouse_complex_f c;c.real_ = a.real_ * b.real_ - a.imag_ * b.imag_;c.imag_ = a.real_ * b.imag_ + a.imag_ * b.real_;return c;
}mouse_complex_f mouse_complex_add(mouse_complex_f a, mouse_complex_f b) {mouse_complex_f c;c.real_ = a.real_ + b.real_;c.imag_ = a.imag_ + b.imag_;return c;
}mouse_complex_f mouse_complex_conj(mouse_complex_f a) {mouse_complex_f ret;ret.real_ = a.real_;ret.imag_ = -1 * a.imag_;return ret;
}

(6)doa-matrix.c

/**@author : aflyingwolf*@date   : 2025.3.20*@file   : doa-matrix.c* */#include "doa-matrix.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>void mouse_complex_matrix_init(mouse_complex_matrix_f *mat, size_t row, size_t col) {mat->num_rows_ = row;mat->num_cols_ = col;mat->data_ = (mouse_complex_f*)malloc(row * col * sizeof(mouse_complex_f));memset(mat->data_, 0, row * col * sizeof(mouse_complex_f));mat->elements_ = (mouse_complex_f**)malloc(row * sizeof(mouse_complex_f*));for(int i = 0; i < row; i++) {mat->elements_[i] = &mat->data_[i * col];}
}void mouse_complex_matrix_free(mouse_complex_matrix_f *mat) {if (mat->data_) {free(mat->data_);free(mat->elements_);}
}
void mouse_complex_matrix_reset(mouse_complex_matrix_f *mat, size_t row, size_t col) {if (mat->data_ != NULL) {free(mat->data_);free(mat->elements_);}mouse_complex_matrix_init(mat, row, col);
}void mouse_complex_matrix_copy_from_column(mouse_complex_matrix_f *mat, size_t column_index, mouse_complex_f **src) {for (int i = 0; i < mat->num_cols_; ++i) {mat->data_[i] = src[i][column_index];}
}void mouse_complex_matrix_copy(mouse_complex_matrix_f *mat, mouse_complex_matrix_f *src) {mouse_complex_matrix_reset(mat, src->num_rows_, src->num_cols_);for (int i = 0; i < mat->num_cols_* mat->num_rows_; ++i) {mat->data_[i] = src->data_[i];}
}float mouse_SumAbs(mouse_complex_matrix_f *mat) {float sum_abs = 0.0;mouse_complex_f **mat_els = mat->elements_;for (int i = 0; i < mat->num_rows_; ++i) {for (int j = 0; j < mat->num_cols_; ++j) {sum_abs += sqrt(mat_els[i][j].real_ * mat_els[i][j].real_ + mat_els[i][j].imag_ * mat_els[i][j].imag_);}}return sum_abs;
}float mouse_SumSquares(mouse_complex_matrix_f *mat) {float sum_squares = 0.f;for (int i = 0; i < mat->num_rows_ * mat->num_cols_; i++) {sum_squares += mat->data_[i].real_ * mat->data_[i].real_ + mat->data_[i].imag_ * mat->data_[i].imag_;}return sum_squares;
}mouse_complex_f mouse_ConjugateDotProduct(mouse_complex_matrix_f *lhs, mouse_complex_matrix_f *rhs) {assert(lhs->num_rows_ == 1);assert(rhs->num_rows_ == 1);assert(rhs->num_cols_ == lhs->num_cols_);mouse_complex_f result;result.real_ = 0.0;result.imag_ = 0.0;mouse_complex_f **lhs_elements = lhs->elements_;mouse_complex_f **rhs_elements = rhs->elements_;for (int i = 0; i < lhs->num_cols_; i++) {mouse_complex_f tmp = mouse_complex_mul(mouse_complex_conj(lhs_elements[0][i]), rhs_elements[0][i]);result = mouse_complex_add(result, tmp);}return result;
}float mouse_Norm(mouse_complex_matrix_f *mat, mouse_complex_matrix_f *norm_mat) {mouse_complex_f first_product, second_product;first_product.real_ = 0.0;first_product.imag_ = 0.0;second_product.real_ = 0.0;second_product.imag_ = 0.0;mouse_complex_f **mat_els = mat->elements_;mouse_complex_f **norm_mat_els = norm_mat->elements_;for (int i = 0; i < norm_mat->num_cols_; i++) {for (int j = 0; j < norm_mat->num_cols_; j++) {first_product = mouse_complex_add(first_product, mouse_complex_mul(mouse_complex_conj(norm_mat_els[0][j]), mat_els[j][i]));}second_product = mouse_complex_add(second_product, mouse_complex_mul(first_product, norm_mat_els[0][i]));first_product.real_ = 0.0;first_product.imag_ = 0.0;}float ret = second_product.real_;if (ret < 0.f) {ret = 0.f;}return ret;
}void mouse_complex_matrix_scale(mouse_complex_matrix_f *mat, mouse_complex_f scale) {int size = mat->num_cols_ * mat->num_rows_;for (int i = 0; i < size; i++) {mat->data_[i] = mouse_complex_mul(mat->data_[i], scale);}
}void mouse_TransposedConjugatedProduct(mouse_complex_matrix_f *in, mouse_complex_matrix_f *out) {assert(in->num_rows_ == 1);assert(out->num_rows_ == in->num_cols_);assert(out->num_cols_ == in->num_cols_);mouse_complex_f* in_elements = in->elements_[0];mouse_complex_f** out_elements = out->elements_;for (int i = 0; i < out->num_rows_; ++i) {for (int j = 0; j < out->num_cols_; ++j) {out_elements[i][j] = mouse_complex_mul(in_elements[i], mouse_complex_conj(in_elements[j]));}}
}mouse_complex_f mouse_Trace(mouse_complex_matrix_f *mat) {assert(mat->num_rows_ == mat->num_cols_);mouse_complex_f trace;trace.real_ = 0.0;trace.imag_ = 0.0;for (int i = 0; i < mat->num_rows_; ++i) {trace = mouse_complex_add(trace, mat->elements_[i][i]);}return trace;
}void mouse_Transpose(mouse_complex_matrix_f *in, mouse_complex_matrix_f *out) {for (int i = 0; i < out->num_rows_; ++i) {for (int j = 0; j < out->num_cols_; ++j) {out->elements_[i][j] = in->elements_[j][i];}}
}void mouse_PointwiseConjugate(mouse_complex_matrix_f *mat) {for (int i = 0; i < mat->num_rows_; ++i) {for (int j = 0; j < mat->num_cols_; ++j) {mat->elements_[i][j].imag_ *= -1;}}
}void mouse_ComplexMatrixMultiply(mouse_complex_matrix_f *interf_cov_vector_transposed, mouse_complex_matrix_f *interf_cov_vector, mouse_complex_matrix_f *mat) {for (int row = 0; row < interf_cov_vector_transposed->num_rows_; ++row) {for (int col = 0; col < interf_cov_vector->num_cols_; ++col) {mouse_complex_f cur_element;cur_element.real_ = 0.0;cur_element.imag_ = 0.0;for (int i = 0; i < interf_cov_vector->num_rows_; ++i) {cur_element = mouse_complex_add(cur_element, mouse_complex_mul(interf_cov_vector_transposed->elements_[row][i], interf_cov_vector->elements_[i][col]));}mat->elements_[row][col] = cur_element;}}
}void mouse_ComplexMatrixAdd(mouse_complex_matrix_f *src1, mouse_complex_matrix_f *src2, mouse_complex_matrix_f *mat) {for (size_t i = 0; i < src1->num_cols_ * src1->num_rows_; ++i) {mat->data_[i] = mouse_complex_add(src1->data_[i], src2->data_[i]);}
}

三、系统部署方式

3.1 运行LED控制进程

3.2 运行数据获取及算法执行进行

四、总结

        以上基本上完整记录了整个系统的代码及部署方式。由于篇幅限制,完整代码可以进入https://t.zsxq.com/qgmoN 获取。注意部署时先启动LED控制程序。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在linux部署网站

在Linux部署网站&#xff0c;需要准备一个纯净的系统 一、系统环境准备 1.设置静态IP地址 ‌ 2.关闭默认防火墙 systemctl disable firewalld --now ‌ 3.配置SSH密钥登录 4.yum update -y && reboot # 更新系统内核 5.yum install -y wget curl unzip # 安装…

Java后端API限流秘籍:高并发的防护伞与实战指南

目录导航 📜 🛡️ 为什么需要API限流?🧠 主流限流算法大解析👩‍💻 阿里巴巴的限流实践📏 四大黄金定律🤼 限流策略组合拳🏆 限流场景实战💻 技术实现方案🌟 最佳实践分享📈 结语与展望📚 推荐阅读 1. 🛡️ 为什么需要API限流? 在高并发环境中,未…

OpenGL ES 2.0与OpenGL ES 3.1的区别

如果硬件支持且需要更高质量的图形效果&#xff0c;推荐3.1&#xff1b;如果兼容性和开发简便更重要&#xff0c;且效果需求不高&#xff0c;2.0更合适。不过现代车载系统可能越来越多支持3.x版本&#xff0c;所以可能倾向于使用3.1&#xff0c;但具体情况还需调查目标平台的硬…

k8s存储介绍(五)PV与PVC

在 Kubernetes&#xff08;k8s&#xff09;中&#xff0c;持久化存储&#xff08;Persistent Storage&#xff09;是一个非常重要的概念&#xff0c;因为 Pod 本身是无状态的&#xff0c;重启后会丢失数据。为了支持有状态应用&#xff0c;Kubernetes 提供了持久化存储的机制&a…

ORA-00600 [2662]

一、数据库启动报ORA-00600[2662] [oraclenode1 ora11g]$ sqlplus / as sysdbaSQL*Plus: Release 11.2.0.3.0 Production on Thu Dec 22 14:37:00 2011Copyright (c) 1982, 2011, Oracle. All rights reserved.Connected to an idle instance.SQL> startup ORACLE instanc…

WebSocket接入SSL证书

目录 碎碎念解决方法创建 HTTPS WebSocket 服务器创建系统服务启动服务 碎碎念 在访问网站时&#xff0c;使用 HTTPS 非常重要。HTTPS 协议不仅可以确保数据传输的安全性&#xff0c;还可以防止中间人攻击和数据篡改等安全问题。任何没有 SSL 证书的内容都可能会被拒绝访问。因…

c#在work线程中怎样更新UI控件

最近笔者调试修改项目&#xff0c;碰到了c#在work线程中怎样更新UI控件中的场景&#xff0c;简单总结了下&#xff0c;主要有两个方法&#xff1a; 方法1&#xff1a;通过System.Windows.Application.Current.Dispatcher.Invoke来更新UI控件 System.Windows.Application.Curre…

数据结构每日一题day3(顺序表)★★★★★

题目描述&#xff1a;顺序表L的元素递增有序排列&#xff0c;设计一个算法在插入元素x后保持该顺序表仍然递增有序排列,插入成功后返回插入元素所在位置,不成功返回-1 算法思想&#xff1a;在递增有序的顺序表中插入元素 x 并保持有序性&#xff0c;步骤如下&#xff1a; 合法…

MyBatis中mapper.xml 的sql映射规则

一、SQL 映射文件核心元素 MyBatis 映射文件的顶级元素&#xff08;按定义顺序&#xff09;&#xff1a; cache&#xff1a;命名空间的缓存配置。cache-ref&#xff1a;引用其他命名空间的缓存。resultMap&#xff1a;自定义结果集映射。sql&#xff1a;可重用的 SQL 片段。i…

【计算机网络】计算机网络协议、接口与服务全面解析——结合生活化案例与图文详解

协议、接口与服务 导读一、协议1.1 定义1.2 组成 二、接口三、服务3.1 定义3.2 服务与协议的区别3.3 分类3.3.1 面向连接服务于无连接服务3.3.2 可靠服务和不可靠服务3.3.3 有应答服务和无应答服务 结语 导读 大家好&#xff0c;很高兴又和大家见面啦&#xff01;&#xff01;…

Ubuntu服务器中Swapper如何与虚拟内存配合

在Ubuntu服务器中&#xff0c;Swapper和虚拟内存是操作系统中重要的概念&#xff0c;它们共同协作以提高系统的内存管理效率。当物理内存不足时&#xff0c;Swapper会帮助系统将不活跃的数据从内存转移到磁盘上的交换空间(Swap)&#xff0c;以释放内存给需要更多资源的进程。下…

SQL Server 中常见的数据类型及其详细解释、内存占用和适用场景

以下是 SQL Server 中常见的数据类型及其详细解释、内存占用和适用场景&#xff1a; 数据类型类别数据类型解释内存占用适用场景整数类型bigint用于存储范围较大的整数&#xff0c;范围是 -2^63 (-9,223,372,036,854,775,808) 到 2^63-1 (9,223,372,036,854,775,807)8 字节需要…

vue数字公式篇 Tinymce结合使用(二)

继上一篇的数字公式 &#xff0c; 这次的功能是将公式能插入编辑器以及修改 1、Tinymce 自定义 LateX 按钮&#xff0c;打开公式编辑器窗口 LateX.vue window.tinymce.init({...//基础配置这里我就不写了setup(ed) {//自定义 LateX 按钮ed.ui.registry.addButton(LateX, {text:…

python数据增强和转换

数据增强和转换 固定转换随机转换概率控制的转换 固定转换 边缘补充像素(Pad)尺寸变换(Resize)中心截取(CenterCrop)顶角及中心截取(FiveCrop)尺灰度变换(GrayScale) 概率控制的转换 随机垂直翻转(RandomVerticalFlip)随机应用(RandomApply) # -*- coding: utf-8 -*- fro…

Ubuntu下UEFI安全启动安装Nvdia驱动

简介 众所周知&#xff0c;Ubuntu默认使用Nouveau开源驱动&#xff0c;其性能受限&#xff0c;因此我们需要安装Nvidia专用驱动。 安装专用驱动的一般方法非常简单&#xff0c;只需要sudo ubuntu-drivers devices && sudo ubuntu-drivers autoinstall即可&#xff0c…

05_循环结构三目运算符

目录 一、双重for循环 练习 二、break关键字 三、continue 关键字 练习 四、三元运算 / 三目运算 一、双重for循环 外层循环 循环一次&#xff0c;&#xff0c;&#xff0c;内层循环 循环一圈&#xff01;&#xff01;&#xff01; 循环里嵌套循环&#xff1a; for(var…

数据结构初阶-二叉树链式

目录 1.概念与结构 2.二叉数链式的实现 2.1遍历规则 2.2申请内存空间 2.3手动构建一棵二叉树 2.4二叉树结点的个数 2.5二叉树叶子结点的个数 2.6二叉树第K层结点个数 2.7二叉树的高度 2.8二叉树中查找值为x的结点 2.9二叉树的销毁 3.层序遍历 3.1概念 3.2层序遍历…

鸿蒙HarmonyOS NEXT之无感监听

鸿蒙中存在一些无感监听&#xff0c;这些监听经过系统API封装使用很简单&#xff0c;但是对实际业务开发中有很重要&#xff0c;例如埋点业务、数据统计、行为上报、切面拦截等。 Navigation的页面切换 在鸿蒙中Navigation被用来作为路由栈进行页面跳转&#xff0c;如果你想知…

批量处理word里面表格的空白行

1&#xff0c;随便打开一个word文档。 2&#xff0c;按下Alt F11 VBA编辑器,在左侧的「工程资源管理器」窗口中找到Normal 项目,右键选择插入->模块。 弹出一下弹窗 3&#xff0c;输入一下代码 代码&#xff1a; Sub RemoveEmptyTableRows()Dim tbl As TableDim row As R…

3ds Max 2026 新功能全面解析

一、视口性能与交互体验升级 1. Hydra 2.0 视口渲染引擎 3ds Max 2026 引入了 Hydra 2.0&#xff0c;大幅优化了视口渲染性能&#xff0c;尤其是在处理复杂场景和高质量实时预览时&#xff0c;流畅度提升显著。 支持USD&#xff08;通用场景描述&#xff09;格式&#xff0c…