Java SourceDataLine 播放音频 显示频谱

news/发布时间2024/5/14 22:09:59

Java SourceDataLine 播放MP3音频 显示频谱

  • 1 添加依赖
  • 2 快速傅里叶变换
    • 2.1 FFT.java
    • 2.2 Complex.java
  • 3 音频播放
    • 3.1 Player.java
    • 3.1 XPlayer.java
  • 4 显示频谱
  • 5 结果

项目Value
音频格式 添加依赖
*.wav(JDK 原生支持)
*.pcm(JDK 原生支持)
*.au(JDK 原生支持)
*.aiff(JDK 原生支持)
*.mp3mp3spi.jar
*.flacjflac-codec.jar

1 添加依赖

<dependency><groupId>com.googlecode.soundlibs</groupId><artifactId>mp3spi</artifactId><version>1.9.5.4</version>
</dependency><!-- 如果需要解码播放flac文件则引入这个jar包 -->
<dependency><groupId>org.jflac</groupId><artifactId>jflac-codec</artifactId><version>1.5.2</version>
</dependency>

2 快速傅里叶变换

2.1 FFT.java

package com.xu.music.player.fft;import java.util.stream.Stream;public class FFT {/*** compute the FFT of x[], assuming its length is a power of 2** @param x* @return*/public static Complex[] fft(Complex[] x) {int n = x.length;// base caseif (n == 1) {return new Complex[]{x[0]};}// radix 2 Cooley-Tukey FFTif (n % 2 != 0) {throw new RuntimeException("N is not a power of 2");}// fft of even termsComplex[] even = new Complex[n / 2];for (int k = 0; k < n / 2; k++) {even[k] = x[2 * k];}Complex[] q = fft(even);// fft of odd termsComplex[] odd = even; // reuse the arrayfor (int k = 0; k < n / 2; k++) {odd[k] = x[2 * k + 1];}Complex[] r = fft(odd);// combineComplex[] y = new Complex[n];for (int k = 0; k < n / 2; k++) {double kth = -2 * k * Math.PI / n;Complex wk = new Complex(Math.cos(kth), Math.sin(kth));y[k] = q[k].plus(wk.times(r[k]));y[k + n / 2] = q[k].minus(wk.times(r[k]));}return y;}/*** compute the inverse FFT of x[], assuming its length is a power of 2** @param x* @return*/public static Complex[] ifft(Complex[] x) {int n = x.length;Complex[] y = new Complex[n];// take conjugatefor (int i = 0; i < n; i++) {y[i] = x[i].conjugate();}// compute forward FFTy = fft(y);// take conjugate againfor (int i = 0; i < n; i++) {y[i] = y[i].conjugate();}// divide by Nfor (int i = 0; i < n; i++) {y[i] = y[i].scale(1.0 / n);}return y;}/*** compute the circular convolution of x and y** @param x* @param y* @return*/public static Complex[] cconvolve(Complex[] x, Complex[] y) {// should probably pad x and y with 0s so that they have same length and are powers of 2if (x.length != y.length) {throw new RuntimeException("Dimensions don't agree");}int n = x.length;// compute FFT of each sequence,求值Complex[] a = fft(x);Complex[] b = fft(y);// point-wise multiply,点值乘法Complex[] c = new Complex[n];for (int i = 0; i < n; i++) {c[i] = a[i].times(b[i]);}// compute inverse FFT,插值return ifft(c);}/*** compute the linear convolution of x and y** @param x* @param y* @return*/public static Complex[] convolve(Complex[] x, Complex[] y) {Complex zero = new Complex(0, 0);// 2n次数界,高阶系数为0.Complex[] a = new Complex[2 * x.length];for (int i = 0; i < x.length; i++) {a[i] = x[i];}for (int i = x.length; i < 2 * x.length; i++) {a[i] = zero;}Complex[] b = new Complex[2 * y.length];for (int i = 0; i < y.length; i++) {b[i] = y[i];}for (int i = y.length; i < 2 * y.length; i++) {b[i] = zero;}return cconvolve(a, b);}/*** Complex[] to double array for MusicPlayer** @param x* @return*/public static Double[] array(Complex[] x) {//for MusicPlayerint len = x.length;//修正幅过小 输出幅值 * 2 / length * 50return Stream.of(x).map(a -> a.abs() * 2 / len * 50).toArray(Double[]::new);}/*** display an array of Complex numbers to standard output** @param x* @param title*/public static void show(Double[] x, String... title) {for (String s : title) {System.out.print(s);}System.out.println();System.out.println("-------------------");for (int i = 0, len = x.length; i < len; i++) {System.out.println(x[i]);}System.out.println();}/*** display an array of Complex numbers to standard output** @param x* @param title*/public static void show(Complex[] x, String title) {System.out.println(title);System.out.println("-------------------");for (int i = 0, len = x.length; i < len; i++) {// 输出幅值需要 * 2 / lengthSystem.out.println(x[i].abs() * 2 / len);}System.out.println();}/*** 将数组数据重组成2的幂次方输出** @param data* @return*/public static Double[] pow2DoubleArr(Double[] data) {// 创建新数组Double[] newData = null;int dataLength = data.length;int sumNum = 2;while (sumNum < dataLength) {sumNum = sumNum * 2;}int addLength = sumNum - dataLength;if (addLength != 0) {newData = new Double[sumNum];System.arraycopy(data, 0, newData, 0, dataLength);for (int i = dataLength; i < sumNum; i++) {newData[i] = 0d;}} else {newData = data;}return newData;}/*** 去偏移量** @param originalArr 原数组* @return 目标数组*/public static Double[] deskew(Double[] originalArr) {// 过滤不正确的参数if (originalArr == null || originalArr.length <= 0) {return null;}// 定义目标数组Double[] resArr = new Double[originalArr.length];// 求数组总和Double sum = 0D;for (int i = 0; i < originalArr.length; i++) {sum += originalArr[i];}// 求数组平均值Double aver = sum / originalArr.length;// 去除偏移值for (int i = 0; i < originalArr.length; i++) {resArr[i] = originalArr[i] - aver;}return resArr;}}

2.2 Complex.java

package com.xu.music.player.fft;import java.util.Objects;public class Complex {private final double re; // the real partprivate final double im; // the imaginary part// create a new object with the given real and imaginary partspublic Complex(double real, double imag) {re = real;im = imag;}// a static version of pluspublic static Complex plus(Complex a, Complex b) {double real = a.re + b.re;double imag = a.im + b.im;Complex sum = new Complex(real, imag);return sum;}// sample client for testingpublic static void main(String[] args) {Complex a = new Complex(3.0, 4.0);Complex b = new Complex(-3.0, 4.0);System.out.println("a            = " + a);System.out.println("b            = " + b);System.out.println("Re(a)        = " + a.re());System.out.println("Im(a)        = " + a.im());System.out.println("b + a        = " + b.plus(a));System.out.println("a - b        = " + a.minus(b));System.out.println("a * b        = " + a.times(b));System.out.println("b * a        = " + b.times(a));System.out.println("a / b        = " + a.divides(b));System.out.println("(a / b) * b  = " + a.divides(b).times(b));System.out.println("conj(a)      = " + a.conjugate());System.out.println("|a|          = " + a.abs());System.out.println("tan(a)       = " + a.tan());}// return a string representation of the invoking Complex object@Overridepublic String toString() {if (im == 0) {return re + "";}if (re == 0) {return im + "i";}if (im < 0) {return re + " - " + (-im) + "i";}return re + " + " + im + "i";}// return abs/modulus/magnitudepublic double abs() {return Math.hypot(re, im);}// return angle/phase/argument, normalized to be between -pi and pipublic double phase() {return Math.atan2(im, re);}// return a new Complex object whose value is (this + b)public Complex plus(Complex b) {Complex a = this; // invoking objectdouble real = a.re + b.re;double imag = a.im + b.im;return new Complex(real, imag);}// return a new Complex object whose value is (this - b)public Complex minus(Complex b) {Complex a = this;double real = a.re - b.re;double imag = a.im - b.im;return new Complex(real, imag);}// return a new Complex object whose value is (this * b)public Complex times(Complex b) {Complex a = this;double real = a.re * b.re - a.im * b.im;double imag = a.re * b.im + a.im * b.re;return new Complex(real, imag);}// return a new object whose value is (this * alpha)public Complex scale(double alpha) {return new Complex(alpha * re, alpha * im);}// return a new Complex object whose value is the conjugate of thispublic Complex conjugate() {return new Complex(re, -im);}// return a new Complex object whose value is the reciprocal of thispublic Complex reciprocal() {double scale = re * re + im * im;return new Complex(re / scale, -im / scale);}// return the real or imaginary partpublic double re() {return re;}public double im() {return im;}// return a / bpublic Complex divides(Complex b) {Complex a = this;return a.times(b.reciprocal());}// return a new Complex object whose value is the complex exponential of// thispublic Complex exp() {return new Complex(Math.exp(re) * Math.cos(im), Math.exp(re) * Math.sin(im));}// return a new Complex object whose value is the complex sine of thispublic Complex sin() {return new Complex(Math.sin(re) * Math.cosh(im), Math.cos(re) * Math.sinh(im));}// return a new Complex object whose value is the complex cosine of thispublic Complex cos() {return new Complex(Math.cos(re) * Math.cosh(im), -Math.sin(re) * Math.sinh(im));}// return a new Complex object whose value is the complex tangent of thispublic Complex tan() {return sin().divides(cos());}// See Section 3.3.@Overridepublic boolean equals(Object x) {if (x == null) {return false;}if (this.getClass() != x.getClass()) {return false;}Complex that = (Complex) x;return (this.re == that.re) && (this.im == that.im);}// See Section 3.3.@Overridepublic int hashCode() {return Objects.hash(re, im);}
}

3 音频播放

3.1 Player.java

package com.xu.music.player.player;import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioFormat.Encoding;
import javax.sound.sampled.AudioInputStream;import java.io.File;
import java.net.URL;/*** Java 音频播放** @author hyacinth* @date 2019年10月31日19:06:39*/
public interface Player {/*** Java Music 加载音频** @param url 音频文件url* @throws Exception 异常* @date 2019年10月31日19:06:39*/void load(URL url) throws Exception;/*** Java Music 加载音频** @param file 音频文件* @throws Exception 异常* @date 2019年10月31日19:06:39*/void load(File file) throws Exception;/*** Java Music 加载音频** @param path 文件路径* @throws Exception 异常* @date 2019年10月31日19:06:39*/void load(String path) throws Exception;/*** Java Music 加载音频** @param stream 音频文件输入流* @throws Exception 异常* @date 2019年10月31日19:06:39*/void load(AudioInputStream stream) throws Exception;/*** Java Music 加载音频** @param encoding Encoding* @param stream   AudioInputStream* @throws Exception 异常* @date 2019年10月31日19:06:39*/void load(Encoding encoding, AudioInputStream stream) throws Exception;/*** Java Music 加载音频** @param format AudioFormat* @param stream AudioInputStream* @throws Exception 异常* @date 2019年10月31日19:06:39*/void load(AudioFormat format, AudioInputStream stream) throws Exception;/*** Java Music 暂停播放** @date 2019年10月31日19:06:39*/void pause();/*** Java Music 继续播放** @date 2019年10月31日19:06:39*/void resume();/*** Java Music 开始播放** @throws Exception 异常* @date 2019年10月31日19:06:39*/void play() throws Exception;/*** Java Music 结束播放** @description: Java Music 结束播放* @date 2019年10月31日19:06:39*/void stop();}

3.1 XPlayer.java

package com.xu.music.player.player;import cn.hutool.core.io.IoUtil;
import cn.hutool.core.text.CharSequenceUtil;
import javazoom.spi.mpeg.sampled.file.MpegAudioFileReader;import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.SourceDataLine;import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.LinkedList;/*** Java 音频播放** @author hyacinth* @date 2019年10月31日19:06:39*/
public class XPlayer implements Player {private static SourceDataLine data = null;private static AudioInputStream audio = null;public static volatile LinkedList<Double> deque = new LinkedList<>();public void put(Double v) {synchronized (deque) {deque.add(Math.abs(v));if (deque.size() > 90) {deque.removeFirst();}}}private XPlayer() {}public static XPlayer createPlayer() {return XPlayer.SingletonHolder.player;}private static class SingletonHolder {private static final XPlayer player = new XPlayer();}@Overridepublic void load(URL url) throws Exception {load(AudioSystem.getAudioInputStream(url));}@Overridepublic void load(File file) throws Exception {String name = file.getName();if (CharSequenceUtil.endWithIgnoreCase(name, ".mp3")) {AudioInputStream stream = new MpegAudioFileReader().getAudioInputStream(file);AudioFormat format = stream.getFormat();format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, format.getSampleRate(), 16, format.getChannels(),format.getChannels() * 2, format.getSampleRate(), false);stream = AudioSystem.getAudioInputStream(format, stream);load(stream);} else if (CharSequenceUtil.endWithIgnoreCase(name, ".flac")) {AudioInputStream stream = AudioSystem.getAudioInputStream(file);AudioFormat format = stream.getFormat();format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, format.getSampleRate(), 16, format.getChannels(),format.getChannels() * 2, format.getSampleRate(), false);stream = AudioSystem.getAudioInputStream(format, stream);load(stream);} else {load(AudioSystem.getAudioInputStream(file));}}@Overridepublic void load(String path) throws Exception {load(new File(path));}@Overridepublic void load(AudioInputStream stream) throws Exception {DataLine.Info info = new DataLine.Info(SourceDataLine.class, stream.getFormat(), AudioSystem.NOT_SPECIFIED);data = (SourceDataLine) AudioSystem.getLine(info);data.open(stream.getFormat());audio = stream;}@Overridepublic void load(AudioFormat.Encoding encoding, AudioInputStream stream) throws Exception {load(AudioSystem.getAudioInputStream(encoding, stream));}@Overridepublic void load(AudioFormat format, AudioInputStream stream) throws Exception {load(AudioSystem.getAudioInputStream(format, stream));}@Overridepublic void pause() {}@Overridepublic void resume() {}@Overridepublic void play() throws IOException {if (null == audio || null == data) {return;}data.start();byte[] buf = new byte[4];int channels = audio.getFormat().getChannels();float rate = audio.getFormat().getSampleRate();while (audio.read(buf) != -1) {if (channels == 2) {//立体声if (rate == 16) {put((double) ((buf[1] << 8) | buf[0]));//左声道//put((double) ((buf[3] << 8) | buf[2]));//右声道} else {put((double) buf[1]);//左声道put((double) buf[3]);//左声道//put((double) buf[2]);//右声道//put((double) buf[4]);//右声道}} else {//单声道if (rate == 16) {put((double) ((buf[1] << 8) | buf[0]));put((double) ((buf[3] << 8) | buf[2]));} else {put((double) buf[0]);put((double) buf[1]);put((double) buf[2]);put((double) buf[3]);}}data.write(buf, 0, 4);}}@Overridepublic void stop() {if (null == audio || null == data) {return;}IoUtil.close(audio);data.stop();IoUtil.close(data);}}

4 显示频谱

package com.xu.music.player.test;import cn.hutool.core.collection.CollUtil;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;import java.io.File;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;import com.xu.music.player.fft.Complex;
import com.xu.music.player.fft.FFT;
import com.xu.music.player.player.Player;
import com.xu.music.player.player.XPlayer;/*** SWT Composite 绘画** @date 2024年2月2日19点27分* @since V1.0.0.0*/
public class SwtDraw {private Shell shell = null;private Display display = null;private Composite composite = null;private final Random random = new Random();private final List<Integer> spectrum = new LinkedList<>();public static void main(String[] args) {SwtDraw test = new SwtDraw();test.open();}/*** 测试播放*/public void play() {try {Player player = XPlayer.createPlayer();player.load(new File("D:\\Kugou\\梦涵 - 加减乘除.mp3"));new Thread(() -> {try {player.play();} catch (Exception e) {throw new RuntimeException(e);}}).start();} catch (Exception e) {}}/*** 打开 SWT 界面** @date 2024年2月2日19点27分* @since V1.0.0.0*/public void open() {display = Display.getDefault();createContents();shell.open();shell.layout();play();task();while (!shell.isDisposed()) {if (!display.readAndDispatch()) {display.sleep();}}}/*** 设置 SWT Shell内容** @date 2024年2月2日19点27分* @since V1.0.0.0*/protected void createContents() {shell = new Shell(display);shell.setSize(900, 500);shell.setLayout(new FillLayout(SWT.HORIZONTAL));// 创建一个Compositecomposite = new Composite(shell, SWT.NONE);// 添加绘图监听器composite.addPaintListener(listener -> {GC gc = listener.gc;int width = listener.width;int height = listener.height;int length = width / 25;if (spectrum.size() >= length) {for (int i = 0; i < length; i++) {draw(gc, i * 25, height, 25, spectrum.get(i));}}});}/*** 模拟 需要绘画的数据 任务** @date 2024年2月2日19点27分* @since V1.0.0.0*/public void task() {Timer timer = new Timer(true);timer.scheduleAtFixedRate(new TimerTask() {@Overridepublic void run() {display.asyncExec(() -> {if (!composite.isDisposed()) {// 在这里调用你更新数据的方法updateData();// 重绘composite.redraw();}});}}, 0, 100);}/*** 模拟 更新绘画的数据** @date 2024年2月2日19点27分* @since V1.0.0.0*/public void updateData() {spectrum.clear();if (CollUtil.isEmpty(XPlayer.deque)) {return;}Complex[] x = new Complex[XPlayer.deque.size()];for (int i = 0; i < x.length; i++) {try {x[i] = new Complex(XPlayer.deque.get(i), 0);} catch (Exception e) {x[i] = new Complex(0, 0);}}Double[] value = FFT.array(x);for (double v : value) {spectrum.add((int) v);}}/*** Composite 绘画** @param gc     GC* @param x      x坐标* @param y      y坐标* @param width  宽度* @param height 高度* @date 2024年2月2日19点27分* @since V1.0.0.0*/private void draw(GC gc, int x, int y, int width, int height) {// 设置条形的颜色Color color = new Color(display, random.nextInt(255), random.nextInt(255), random.nextInt(255));gc.setBackground(color);// 绘制条形Rectangle draw = new Rectangle(x, y, width, -height);gc.fillRectangle(draw);// 释放颜色资源color. Dispose();}}

5 结果

请添加图片描述

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

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

相关文章

一命通关动态规划dp

前言 这篇文章详细概括了动态规划的所有题型&#xff0c;以及各个题型的解决公式方法。如果看完这篇动态规划还是不会做题&#xff0c;我来给你补&#xff0c;我爱说点实话。 动态规划 何为动态规划&#xff1f; 动态规划&#xff0c;有一点暴力求解的感觉。用最通俗的语言来…

《穿越科技的前沿:计算机专业必看的电影盛宴》

文章目录 每日一句正能量前言电影推荐推荐一&#xff1a;《黑客帝国》推荐二&#xff1a;《社交网络》推荐三&#xff1a;《源代码》推荐四&#xff1a;《谍影重重》系列推荐五&#xff1a;《旋转木马》 技术与主题后记 每日一句正能量 一个人的一生&#xff0c;就是一座有了年…

【PX4学习笔记】06.PID控制原理

目录 文章目录 目录PID控制原理PID算法的基本形式PID算法的连续系统离散化&#xff08;位置式&#xff09;PID算法的连续系统离散化&#xff08;增量式&#xff09;PID算法的实际应用的举例 PID代码验证PID算法的连续系统离散化&#xff08;位置式&#xff09;的程序实现 其他 …

计算机网络——多媒体网络

前些天发现了一个巨牛的人工智能学习网站 通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家&#xff0c; 跳转到网站 小程一言 我的计算机网络专栏&#xff0c;是自己在计算机网络学习过程中的学习笔记与心得&#xff0c;在参考相关教材&#xff0c;网络搜素…

SpringBoot + Nacos + K8s 优雅停机

1 概念 2 用案例说话 案例前&#xff1a;k8s 停机流程 k8s springboot nacos 案例 案例优化 3 再次优化 mq 和 定时任务 流量控制 4 小结 1 概念 优雅停机是什么&#xff1f;网上说的优雅下线、无损下线&#xff0c;都是一个意思。 优雅停机&#xff0c;通常是指在设…

ros自定义action记录

文章目录 自定义action1. 定义action文件2. 修改 package.xml3. 修改 CMakeLists.txt4. 运行 catkin build4. simple_action_server.py5. simple_action_client.py 测试 自定义action ros 版本&#xff1a;kinetic 自定义test包的文件结构如下 |-- test | |-- CMakeLists.t…

纯血鸿蒙来画龙!基于HarmonyOS ArkTS来操作SVG图片

大家好&#xff0c;龙年报喜&#xff0c;大地回春&#xff0c;作为程序员&#xff0c;以代码之名&#xff0c;表达对于龙年的祝福。本节将演示如何在基于HarmonyOS ArkTS的Image组件来实现画一条中国龙&#xff0c;祝大家“码”上“鸿”福到&#xff01; 本文涉及的所有源码&a…

7.CSS属性的计算过程

CSS 属性的计算过程 经典真题 请简述 CSS 中属性的计算过程是怎样的 CSS 属性的计算过程 首先&#xff0c;让我们从最简单的代码开始&#xff0c;例如&#xff1a; <p>this is a test</p>p{color : red; }上面是一段很简单的代码&#xff0c;就一个段落&#…

Spring Bean 的生命周期了解么?

Spring Bean 的生命周期基本流程 一个Spring的Bean从出生到销毁的全过程就是他的整个生命周期, 整个生命周期可以大致分为3个大的阶段 : 创建 使用 销毁 还可以分为5个小步骤 : 实例化(Bean的创建) , 初始化赋值, 注册Destruction回调 , Bean的正常使用 以及 Bean的销毁 …

js设计模式:依赖注入模式

作用: 在对象外部完成两个对象的注入绑定等操作 这样可以将代码解耦,方便维护和扩展 vue中使用use注册其他插件就是在外部创建依赖关系的 示例: class App{constructor(appName,appFun){this.appName appNamethis.appFun appFun}}class Phone{constructor(app) {this.nam…

list链表

1. list基本概念 功能&#xff1a;将数据进行链式存储 链表&#xff08;list&#xff09;是一种物理存储单元上非连续的存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的指针链接实现的 链表的组成&#xff1a;链表由一系列结点组成 结点的组成&#xff1a;一个是存储数据…

【力扣hot100】刷题笔记Day9

前言 阴天睡得还挺舒服&#xff0c;9点半才醒&#xff0c;用刷题开启美好新一天&#xff01; 141. 环形链表 - 力扣&#xff08;LeetCode&#xff09; 哈希表 class Solution:def hasCycle(self, head: Optional[ListNode]) -> bool:seen set() # 哈希集合# seen {} #…

Django数据库配置+迁移

目录 配置settings.py 在项目下新建bookstore应用 将新建应用添加到项目中 创建模型 执行数据库信息迁移 新增或修改数据库的信息 配置settings.py 找到项目同名文件夹下的settings.py文件&#xff0c;将原有的django默认配置修改为下图 引擎只需要将最后一部分改为对应…

外包干了3个月,技术倒退2年。。。

先说情况&#xff0c;大专毕业&#xff0c;18年通过校招进入湖南某软件公司&#xff0c;干了接近6年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试&#xf…

尾矿库排洪系统结构仿真APP助力尾矿库本质安全

1、背景介绍 尾矿库作为重大危险源之一&#xff0c;在国际灾害事故排名中位列第18位&#xff0c;根据中国钼业2019年8月刊《中国尾矿库溃坝与泄漏事故统计及成因分析》的统计&#xff0c;在46起尾矿库泄漏事故中&#xff0c;由于排洪设施导致的尾矿泄漏事故占比高达1/3&#x…

HTML的特殊字符

HTML的特殊字符 有些特殊的字符在 html 文件中是不能直接表示的&#xff0c;例如: 空格&#xff0c;小于号(<)&#xff0c;大于号(>)&#xff0c;按位与(&)。 空格 示例代码&#xff1a; 运行结果&#xff1a; 由于html 标签就是用 < > 表示的&#xff0…

如何做代币分析:以 BNB 币为例

作者&#xff1a;lesleyfootprint.network 数据源&#xff1a;BNB Coin Dashboard &#xff08;仅包括以太坊数据&#xff09; 在加密货币和数字资产领域&#xff0c;代币分析起着至关重要的作用。代币分析指的是深入研究与代币相关的数据和市场行为的过程。这是一个详细的过…

Cesium 问题:加载 gltf 格式的模型之后太小,如何让相机视角拉近

文章目录 问题分析问题 刚加载的模型太小,如何拉近视角放大 分析 在这里有两种方式进行拉近视角, 一种是点击复位进行视角拉近一种是刚加载就直接拉近视角// 模型三加载 this.damModel = new Cesium.Entity({name: "gltf模型",position:</

矩阵置零

73. 矩阵置零 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,1,1],[1,0,1],[1,1,1]] 输出&#xff1a;[[1,0,1],[0,0,0],[1,0,1]]示例 2&#xf…

滚动加载react-infinite-scroll-component

react-infinite-scroll-component 当请求数据量过大时&#xff0c;接口返回数据时间会很长&#xff0c;数据回显时间长&#xff0c;Dom 的渲染会有很大的性能压力。 antd的List组件中有提到一个滚动加载的组件库react-infinite-scroll-component 实现滚动加载 Antd&#xff1…
推荐文章