27人参与 • 2025-08-18 • Asp.net
跨平台能力:.net core支持windows/linux/macos。
强大生态:naudio、ffmpeg.autogen等库让音频处理变得简单。
可视化友好:wpf/winforms无缝集成图表控件(如livecharts)。
# 使用nuget安装以下库 install-package naudio # 音频输入/输出/处理 install-package livecharts # 实时波形/频谱可视化 install-package ffmpeg.autogen # 音频格式转换(可选)
// 项目目录建议 /assets // 图片/资源文件 /controllers // 音频控制逻辑 /models // 数据模型(如波形数据、频谱数据) /views // 窗体/界面 /utilities // 工具类(如fft计算、文件io)
using naudio.wave; public class audioinputmanager : idisposable { private waveinevent _wavein; private wavefilewriter _writer; private bool _isrecording = false; // 构造函数:初始化音频设备 public audioinputmanager(int deviceid = 0, int samplerate = 44100, int channels = 1) { _wavein = new waveinevent { devicenumber = deviceid, waveformat = new waveformat(samplerate, channels) }; _wavein.dataavailable += ondataavailable; } // 开始录音 public void startrecording(string outputfilepath) { _isrecording = true; _writer = new wavefilewriter(outputfilepath, _wavein.waveformat); _wavein.startrecording(); console.writeline("音频录制已启动"); } // 停止录音 public void stoprecording() { _isrecording = false; _wavein.stoprecording(); _writer.dispose(); console.writeline("音频录制已停止"); } // 处理音频数据 private void ondataavailable(object sender, waveineventargs e) { if (_isrecording) { _writer.write(e.buffer, 0, e.bytesrecorded); // 写入文件 processaudiodata(e.buffer, e.bytesrecorded); // 实时分析 } } // 实时分析音频数据(波形/频谱) private void processaudiodata(byte[] buffer, int bytesread) { // 将字节转换为短整型(16位pcm) short[] samples = new short[bytesread / 2]; buffer.blockcopy(buffer, 0, samples, 0, bytesread); // 提取波形数据(用于livecharts) models.waveformmodel.instance.addsamples(samples); // 计算频谱(fft) double[] spectrum = fft.calculatefft(samples, _wavein.waveformat.samplerate); models.spectrummodel.instance.updatespectrum(spectrum); } // 释放资源 public void dispose() { _wavein.dispose(); _writer?.dispose(); } }
public class waveformmodel { public static waveformmodel instance { get; } = new waveformmodel(); private list<double> _samples = new list<double>(); public void addsamples(short[] samples) { foreach (var sample in samples) { _samples.add(sample / 32768.0); // 归一化到[-1,1] if (_samples.count > 4096) _samples.removeat(0); // 限制最大样本数 } } public list<double> getsamples() => _samples; }
public static class fft { public static double[] calculatefft(short[] samples, int samplerate) { int n = samples.length; complex[] data = new complex[n]; // 将短整型转换为complex类型 for (int i = 0; i < n; i++) { data[i] = new complex(samples[i], 0); } // 执行快速傅里叶变换(fft) fourier.forwardfouriertransform(data, fourieroptions.noscaling); // 计算幅度谱(只取前半部分) double[] magnitude = new double[n / 2]; for (int i = 0; i < n / 2; i++) { magnitude[i] = math.sqrt(data[i].x * data[i].x + data[i].y * data[i].y); } // 转换为分贝(db)刻度 for (int i = 0; i < magnitude.length; i++) { if (magnitude[i] > 0) { magnitude[i] = 20 * math.log10(magnitude[i] / (n / 2)); } else { magnitude[i] = -100; // 避免除以0 } } return magnitude; } }
using livecharts; using livecharts.wpf; public class waveformchart : chart { public waveformchart() { series = new seriescollection { new lineseries { title = "waveform", values = new chartvalues<double>(), linesmooth = false, pointgeometry = null } }; // 自动更新数据 this.datacontext = models.waveformmodel.instance; this.bindingcontext = new binding("getsamples") { mode = bindingmode.oneway }; } }
public class spectrumchart : chart { public spectrumchart() { series = new seriescollection { new columnseries { title = "spectrum", values = new chartvalues<double>(), datalabels = false } }; // 自动更新数据 this.datacontext = models.spectrummodel.instance; this.bindingcontext = new binding("getspectrum") { mode = bindingmode.oneway }; } }
public class audiofeatures { public static double calculaterms(short[] samples) { double sum = 0; foreach (var sample in samples) { sum += sample * sample; } return math.sqrt(sum / samples.length) / 32768.0; // 归一化到[0,1] } public static double calculatezerocrossingrate(short[] samples) { int count = 0; for (int i = 1; i < samples.length; i++) { if ((samples[i - 1] >= 0 && samples[i] < 0) || (samples[i - 1] < 0 && samples[i] >= 0)) { count++; } } return count / (double)samples.length; } public static double calculatespectralcentroid(double[] spectrum, int samplerate) { double sum = 0, total = 0; for (int i = 0; i < spectrum.length; i++) { double freq = i * (samplerate / 2.0) / spectrum.length; sum += freq * spectrum[i]; total += spectrum[i]; } return total == 0 ? 0 : sum / total; } }
public partial class mainform : form { private audioinputmanager _audiomanager; public mainform() { initializecomponent(); // 初始化音频管理器 _audiomanager = new audioinputmanager(); // 绑定可视化组件 waveformchart.datasource = models.waveformmodel.instance.getsamples(); spectrumchart.datasource = models.spectrummodel.instance.getspectrum(); } private void btnstart_click(object sender, eventargs e) { _audiomanager.startrecording("output.wav"); btnstart.enabled = false; btnstop.enabled = true; } private void btnstop_click(object sender, eventargs e) { _audiomanager.stoprecording(); btnstop.enabled = false; btnstart.enabled = true; } protected override void onformclosing(formclosingeventargs e) { _audiomanager.dispose(); base.onformclosing(e); } }
audioinputmanager
开始采集音频数据。processaudiodata
函数解析波形并计算频谱。audiofeatures
类提取rms、过零率、频谱质心等参数。多线程处理:将fft计算和可视化更新放在独立线程中。
缓冲区管理:使用环形缓冲区减少内存分配。
音频格式转换:集成ffmpeg实现wav/mp3转换。
机器学习集成:使用ml.net训练音频分类模型(如语音/音乐识别)。
网络传输:通过websocket发送音频数据到web前端。
到此这篇关于一文教你从0到1搭建c#音频分析平台的文章就介绍到这了,更多相关c#音频分析内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论