• C# NAudio 音频库


    NAudio安装

    项目=>NuGet包管理器 搜索NAudio点击安装,自动安装依赖库。
    在这里插入图片描述
    安装成功后工具箱会新增NAudio.WinForms控件
    在这里插入图片描述

    NAudio简述

    NAudio为.NET平台下的开源库,采用ML-PL协议,开源地址:https://github.com/naudio/NAudio支持多种音频操作,可实现多种API播放与录制、多种不同音频格式、音频格式转换(重采样、位深、声道等)、音频编码、多通道播放、音频效果处理等等。

    快速入门
    深入研究

    常用类:

    • WaveIn 表示波形输入, 继承了 IWaveIn, 例如麦克风输入, 或者计算机正在播放的音频流。
    • WaveOut 表示波形输出, 继承了 IWavePlayer, 用来播放音频, 以 IWaveProvider 作为播放源播放音频, 通过拓展方法也支持以 ISampleProvider 作为播放源播放音频。
    • WaveStream 表示波形流, 它继承了 IWaveProvider, 可以用来作为播放源。
    • WaveFileReader 继承了 WaveStream, 用来读取波形文件。
    • WaveFileWriter 继承了Stream, 用来写入文件, 常用于保存音频录制的数据。
    • AudioFileReader 通用的音频文件读取器, 可以读取波形文件, 也可以读取其他类型的音频文件例如 Aiff, MP3

    常用接口:

    • IWaveProvider 波形提供者, 上面已经提到, 是音频播放的提供者, 通过拓展方法可以转换为 ISampleProvider。
    • ISampleProvider 采样提供者, 上面已经提到, 通过拓展方法可以作为 WaveOut 的播放源。

    简单示例1

    自定义录音机类:Recorder.cs

    using NAudio.Wave;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace NAudioDemo
    {
        internal class Recorder
        {
            public WaveIn mWaveIn;
            public WaveFileWriter mWaveFileWriter;
            public int secondsRecorded;
    
            /// 
            /// 开始录音
            /// 
            /// 
            public void RecorderStart(string filePath)
            {
                // 创建WaveIn对象
                mWaveIn = new WaveIn();
    
                // 添加DataAvailable事件处理回调
                mWaveIn.DataAvailable += OnDataAvailable;
    
                // 创建WaveFileWriter对象
                mWaveFileWriter = new WaveFileWriter(filePath, mWaveIn.WaveFormat);
    
                // 开始录音
                mWaveIn.StartRecording();
            }
    
            /// 
            /// 停止录音
            /// 
            public void RecorderStop()
            {
                mWaveIn?.StopRecording();
    
                mWaveIn?.Dispose();
    
                mWaveFileWriter?.Close();
                mWaveFileWriter = null;
            }
    
    
            /// 
            /// 录音数据回调
            /// 
            /// 
            /// 
            private void OnDataAvailable(object sender, WaveInEventArgs e)
            {
                // 写入录音数据
                mWaveFileWriter.Write(e.Buffer, 0, e.BytesRecorded);           
    
                // 计算已录制的秒数
                secondsRecorded = (int)mWaveFileWriter.Length / mWaveFileWriter.WaveFormat.AverageBytesPerSecond;
            }
      
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    
    using System.IO;
    using NAudio.Wave;
    using System.Drawing.Text;
    using System.Media;
    using NAudio.Dsp;
    
    namespace NAudioDemo
    {
        public partial class Form1 : Form
        {             
            // 创建录音机类实例
            Recorder recorder = new Recorder();
            
            public Form1()
            {
                InitializeComponent();
            }
                    
            private void Form1_Load(object sender, EventArgs e)
            {
                
            }
       
            private void button1_Click(object sender, EventArgs e)
            {
                button1.Enabled = false;
                button2.Enabled = true;
                recorder.RecorderStart(@"D:\1.wav");
            }
    
            private void button2_Click(object sender, EventArgs e)
            {
                button1.Enabled = true;
                button2.Enabled = false;
                recorder.RecorderStop();
            }
    
            private void button3_Click(object sender, EventArgs e)
            {
                SoundPlayer player = new SoundPlayer(@"D:\1.wav");
                player.Play();           
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    在这里插入图片描述

    录制麦克风

    • 借助 WaveIn 类, 我们可以轻易的捕获麦克风输入, 在每一次录制到数据时, 将数据写入到文件或其他流, 这就实现了保存录音

    • 在保存波形文件时需要借助 WaveFileWriter, 当然, 如果你想保存为其他格式, 也可以使用其它的 Writer, 例如 CurWaveFileWriter 以及AiffFileWriter, 美中不足的是没有直接写入到 MP3 的 FileWriter

    • 需要注意的是, 桌面程序可以直接使用 WaveIn, 其回调基于 Windows 消息, 所以无法在控制台应用中使用 WaveIn

    • 如果要在控制台应用中实现录音, 只需要使用 WaveInEvent, 它的回调基于事件而不是 Windows 消息, 所以可以通用

    • 示例代码:
      WaveIn cap = new WaveIn(); // cap, capture
      WaveFileWriter writer = new WaveFileWriter();
      cap.DataAvailable += (s, args) => writer.Write(args.Buffer, 0, args.BytesRecorded); // 订阅事件
      cap.StartRecording(); // 开始录制
      cap.StopRecording(); // 停止录制
      writer.Close(); // 关闭 FileWriter, 保存数据

    • 另外, 除了使用 WaveIn, 你还可以使用 WasapiCapture, 它与 WaveIn 的使用方式是一致的, 可以用来录制麦克风

    • Wasapi 全称 Windows Audio Session Application Programming Interface (Windows音频会话应用编程接口)

    • 具体 WaveIn, WaveInEvent, WasapiCapture 的性能, 笔者还没有测试过, 但估计不会有太大差异.

    • 提示: WasapiCapture 和 WasapiLoopbackCapture 位于 NAudio.Wave 命名空间下

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    using NAudio;
    using NAudio.Wave;
    
    
    namespace NAudioDemo2
    {
        public partial class Form2 : Form
        {
    
            private WaveIn waveIn = null;
            private WaveFileWriter writer = null;
    
    
            public Form2()
            {
                InitializeComponent();
                button2.Enabled = false;
                button3.Enabled = false;
            }
    
            /// 
            /// 设置保存文件名称
            /// 
            /// 
            /// 
            private void button1_Click(object sender, EventArgs e)
            {
                saveFileDialog1.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
                saveFileDialog1.Filter = "audio files (*.wav)|*.wav| all files (*.*)|*.*"; // 文件类型过滤
                saveFileDialog1.DefaultExt = "*.wav"; // 默认文件扩展名
                //saveFileDialog1.FileName = "1.wav"; // 默认文件名
    
                if (saveFileDialog1.ShowDialog() == DialogResult.OK)
                { 
                    string fName = saveFileDialog1.FileName; // 获取文件名
                    textBox1.Text = fName;
                    button2.Enabled = true;
                }
            }
    
            /// 
            /// 开始录音
            /// 
            /// 
            /// 
            private void button2_Click(object sender, EventArgs e)
            {
                          
                //waveIn = new WaveIn { WaveFormat = new WaveFormat(44100, 1) };
                waveIn = new WaveIn();
                waveIn.WaveFormat = new WaveFormat(44100, 1);
               
                writer = new WaveFileWriter(textBox1.Text.Trim(), waveIn.WaveFormat);
    
                waveIn.DataAvailable += (s, args) => writer.Write(args.Buffer, 0, args.BytesRecorded);
    
                waveIn.StartRecording();
    
                button2.Enabled = false;
                button3.Enabled = true;
            }
    
            /// 
            /// 停止录音
            /// 
            /// 
            /// 
            private void button3_Click(object sender, EventArgs e)
            {
                waveIn.StopRecording();
                waveIn.Dispose();
                waveIn = null;
    
                writer.Flush();
                writer.Close();
                writer.Dispose();
    
                button2.Enabled = true;
                button3.Enabled = false;
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94

    录制系统声卡

    录制声卡输出, 也就是录制计算机正在播放的声音, 借助 WasapiLoopbackCapture 即可简单实现, 使用方式与 WasapiCapture 无异
    WasapiLoopbackCapture cap = new WasapiLoopbackCapture();
    WaveFileWriter writer = new WaveFileWriter();
    cap.DataAvailable += (s, args) => writer.Write(args.Buffer, 0, args.BytesRecorded);
    cap.StartRecording();

    using NAudio.Wave;
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace NAudioDemo2
    {
        public partial class Form3 : Form
        {
            private WasapiLoopbackCapture loopCap = new WasapiLoopbackCapture();
            private WaveFileWriter fileWriter;
    
            public Form3()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                SaveFileDialog saveFileDialog = new SaveFileDialog();
                saveFileDialog.Filter = "wave file *.wav|*.wav|all filse *.*|*.*";
                saveFileDialog.DefaultExt = ".wav";
    
                if (saveFileDialog.ShowDialog() == DialogResult.OK)
                {
                    string fName = saveFileDialog.FileName;
                    textBox1.Text = fName;            
                }
            }
    
            /// 
            /// 录制声卡开始
            /// 
            /// 
            /// 
            private void button2_Click(object sender, EventArgs e)
            {
                fileWriter = new WaveFileWriter(textBox1.Text.Trim(), loopCap.WaveFormat) ;
                loopCap.DataAvailable += (s, args) => fileWriter.Write(args.Buffer, 0, args.BytesRecorded);
    
                loopCap.StartRecording();
            }
    
            /// 
            /// 录制声卡停止
            /// 
            /// 
            /// 
            private void button3_Click(object sender, EventArgs e)
            {
                loopCap.StopRecording();
                fileWriter.Flush();
                fileWriter.Close();
                fileWriter.Dispose();
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64

    WAV格式播放

    NAudio 中, 通过 WaveFileReader 来读取波形数据, 在实例化时, 你可以指定文件名或者是输入流, 这意味着你可以读取内存流中的音频数据.
    WaveFileReader reader = new WaveFileReader(filepath);
    WaveOut wout = new WaveOut();
    wout.Init(reader); // 通过 IWaveProvider 为音频输出初始化
    wout.Play(); // 至此, wout 将从指定的 reader 中提供的数据进行播放

    using NAudio.Wave;
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace NAudioDemo2
    {
        public partial class Form4 : Form
        {
            private WaveOut wout_wav;
            WaveFileReader reader;
    
            public Form4()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                OpenFileDialog ofd = new OpenFileDialog();
                ofd.Filter = "audio file *.wav|*.wav";
                ofd.DefaultExt = "*.wav";
                if (ofd.ShowDialog() == DialogResult.OK)
                {
                    string fName = ofd.FileName;
                    textBox1.Text = fName;
                }
            }
    
            private void button2_Click(object sender, EventArgs e)
            {
                reader = new WaveFileReader(textBox1.Text.Trim());
                wout_wav = new WaveOut();
                wout_wav.Init(reader);
                wout_wav.Play();
            }
    
            private void button3_Click(object sender, EventArgs e)
            {
                wout_wav.Pause();
            }
    
            private void button4_Click(object sender, EventArgs e)
            {
                wout_wav.Resume();
            }
    
            private void button5_Click(object sender, EventArgs e)
            {
                wout_wav.Stop();
                wout_wav.Dispose();
                reader.Close();
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

    MP3格式播放

    播放 MP3 音乐其实与播放波形音乐没有太大区别, 只不过将 WaveFileReader 换成Mp3FileReader 罢了
    Mp3FileReader reader = new Mp3FileReader(filepath);
    WaveOut wout = new WaveOut();
    wout.Init(reader);
    wout.Play();

    using NAudio.Wave;
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace NAudioDemo2
    {
        public partial class Form5 : Form
        {
            Mp3FileReader reader;
            WaveOut wout_mp3;
    
            public Form5()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                OpenFileDialog ofd = new OpenFileDialog();
                ofd.Filter = "audio file *.mp3|*.mp3";
                ofd.DefaultExt = "*.mp3";
    
                if (ofd.ShowDialog() == DialogResult.OK)
                { 
                    string fName = ofd.FileName;
                    textBox1.Text = fName;
                }
            }
    
            private void button2_Click(object sender, EventArgs e)
            {
                reader = new Mp3FileReader(textBox1.Text);
                wout_mp3 = new WaveOut();
                wout_mp3.Init(reader);
                wout_mp3.Play();
            }
    
            private void button3_Click(object sender, EventArgs e)
            {
                wout_mp3.Pause();
            }
    
            private void button4_Click(object sender, EventArgs e)
            {
                wout_mp3.Resume();
            }
    
            private void button5_Click(object sender, EventArgs e)
            {
                wout_mp3.Stop();
                wout_mp3.Dispose();
                reader.Close();
                reader.Dispose();
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64

    AudioFileReader读取播放音频

    通过AudioFileReader读取音频文件可以播放.mp3, .wav, .flac等多种格式
    AudioFileReader reader = new AudioFileReader (@“d:\1.mp3”);
    WaveOut wout = new WaveOut ();
    wout.Init(reader );
    wout.Play();
    wout.Pause();
    wout.Resume();
    wout.Stop();

    using NAudio.Wave;
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace NAudioDemo2
    {
        public partial class Form6 : Form
        {
            AudioFileReader reader;
            WaveOut wout;
    
            public Form6()
            {
                InitializeComponent();
            }
    
            private void Form6_Load(object sender, EventArgs e)
            {
            
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                OpenFileDialog ofd = new OpenFileDialog();
                ofd.Filter = "audio file *.mp3|*.mp3|all files *.*|*.*";
                if (ofd.ShowDialog() == DialogResult.OK)
                { 
                    string fName = ofd.FileName;
                    textBox1.Text = fName; 
                }
            }
    
            private void button2_Click(object sender, EventArgs e)
            {
                reader = new AudioFileReader(textBox1.Text.Trim());
                wout = new WaveOut();
                wout.Init(reader);
                wout.Play();
    
            }
    
            private void button3_Click(object sender, EventArgs e)
            {
                wout.Pause();  
            }
    
            private void button4_Click(object sender, EventArgs e)
            {
                wout.Resume();
            }
    
            private void button5_Click(object sender, EventArgs e)
            {
                wout.Stop();
                wout.Dispose();
                reader.Close();
                reader.Dispose();
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68

    MediaFoundationReader 读取播放音频

    通过MediaFoundationReader 读取音频文件可以播放.mp3, .wav, .flac等多种格式
    MediaFoundationReader reader = new MediaFoundationReader (@“d:\1.mp3”);
    WaveOut wout = new WaveOut ();
    wout.Init(reader );
    wout.Play();
    wout.Pause();
    wout.Resume();
    wout.Stop();

    using NAudio.Wave;
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace NAudioDemo2
    {
        public partial class Form7 : Form
        {
            MediaFoundationReader reader;
            WaveOut wout;
    
            public Form7()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                OpenFileDialog  ofd = new OpenFileDialog();
                ofd.Filter = "audio file *.mp3|*.mp3|all files *.*|*.*";
                ofd.DefaultExt = "*.mp3";
    
                if (ofd.ShowDialog() == DialogResult.OK)
                {
                    string fName = ofd.FileName;
                    textBox1.Text = fName;
                }
            }
    
            private void button2_Click(object sender, EventArgs e)
            {
                reader = new MediaFoundationReader(textBox1.Text.Trim());
                wout = new WaveOut();
                wout.Init(reader);
                wout.Play();
            }
    
            private void button3_Click(object sender, EventArgs e)
            {
                wout.Pause();
            }
    
            private void button4_Click(object sender, EventArgs e)
            {
                wout.Resume();
            }
    
            private void button5_Click(object sender, EventArgs e)
            {
                wout.Stop();
                wout.Dispose();
                reader.Close();
                reader.Dispose();
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
  • 相关阅读:
    Tendis(Redis)冷热混合存储怎么解决缓存击穿、雪崩、一致性3大难题
    C# 实现 Linux 视频聊天、远程桌面(源码,支持信创国产化环境,银河麒麟,统信UOS)
    SpringBoot常见组件集成
    【第48篇】MaxViT:多轴视觉转换器
    在vue项目中使用electron
    斯特林数行列求解
    wireshark过滤CAN报文小技巧
    【Spring之底层核心架构概念解析】
    【YOLO系列】YOLOv1
    vue 插槽Slots
  • 原文地址:https://blog.csdn.net/u013420428/article/details/134442675