已解决
C#获取声音信号并通过FFT得到声音频谱
来自网友在路上 163863提问 提问时间:2023-09-19 18:08:07阅读次数: 63
最佳答案 问答题库638位专家为你答疑解惑
最近研究了下用C#通过麦克风获取声音信号,再通过快速傅里叶变换,得到声音的频谱。
想应用到实际的led灯上,放歌曲,led灯展示频谱,现在用C#先模拟实现下,如下图。
上面的表展示的是声音的电压信号,下图是频谱信息
一、获取声音信号
通过麦克风获取声音用的是NAudio这个库,可以通过NuGet获取
具体使用方式是:
private NAudio.Wave.WaveIn sourceStream = null;private NAudio.Wave.DirectSoundOut waveOut = null;
获取麦克风列表
List<NAudio.Wave.WaveInCapabilities> sources = new List<NAudio.Wave.WaveInCapabilities>();
for (int i = 0; i < NAudio.Wave.WaveIn.DeviceCount; i++)
{sources.Add(NAudio.Wave.WaveIn.GetCapabilities(i));
}
sourceListView.Items.Clear();
foreach (var source in sources)
{ListViewItem item = new ListViewItem(source.ProductName);item.SubItems.Add(new ListViewItem.ListViewSubItem(item, source.Channels.ToString()));sourceListView.Items.Add(item);
}
初始化麦克风
if (sourceListView.SelectedItems.Count == 0) return;int deviceNumber = sourceListView.SelectedItems[0].Index;sourceStream = new NAudio.Wave.WaveIn();sourceStream.DeviceNumber = deviceNumber;int a=WaveIn.GetCapabilities(0).Channels;sourceStream.WaveFormat = new NAudio.Wave.WaveFormat(9600, 16, 1);sourceStream.DataAvailable += new EventHandler<NAudio.Wave.WaveInEventArgs>(sourceStream_DataAvailable);sourceStream.BufferMilliseconds = 20;sourceStream.StartRecording();
回调函数,lastBuffer就存储的是声音信号
private void sourceStream_DataAvailable(object sender, WaveInEventArgs e)
{ int samplesRecord = e.BytesRecorded / 2;if (lastBuffer is null||lastBuffer.Length!=samplesRecord)lastBuffer = new double[samplesRecord];for (int i = 0; i < samplesRecord; i++)lastBuffer[i] = BitConverter.ToInt16(e.Buffer, i * 2);}
二、FFT变换
FFT变换原理之前文章我用C++写过
C++实现二维快速傅里叶变换(FFT)_c++ fft-CSDN博客
这里我用C#再实现下,复数可以直接using System.Numerics里面的Complex,而不用自己定义了。
FFT源码如下:
int ReverseBin(int a, int n)
{int ret = 0;for (int i = 0; i < n; i++){if ((a & (1 << i)) != 0) ret |= (1 << (n - 1 - i));}return ret;
}public void FFT(ref Complex[] a, int log2_N, int opt)
{int index;int length = 1 << log2_N;Complex[] tempA = new Complex[length];for (int i = 0; i < length; i++){index = ReverseBin(i, log2_N);tempA[i] = a[index];}//生成WN表,减少重复计算Complex[] WN = new Complex[length / 2];for (int i = 0; i < length / 2; i++){WN[i] = new Complex(Math.Cos(2 * Math.PI * i / length), opt * -1 * Math.Sin(2 * Math.PI*i / length));}//蝶形运算int Index0, Index1;Complex temp;for (int steplenght = 2; steplenght <= length; steplenght *= 2){for (int step = 0; step < length / steplenght; step++){for (int i = 0; i < steplenght / 2; i++){Index0 = steplenght * step + i;Index1 = steplenght * step + i + steplenght / 2;temp = tempA[Index1] * WN[length / steplenght * i];tempA[Index1] = tempA[Index0] - temp;tempA[Index0] = tempA[Index0] + temp;}}}for (int i = 0; i < length; i++){if (opt == -1){a[i] = tempA[i] / length;}else{a[i] = tempA[i];}}}
三、总结
这样可以实时得到了一段声音信号,可以加个汉明窗处理下,再FFT下,就得到声音的频谱信息了。后续计划,可以通过这种方式,控制led灯,展示音乐的频谱跳动。
查看全文
99%的人还看了
相似问题
猜你感兴趣
版权申明
本文"C#获取声音信号并通过FFT得到声音频谱":http://eshow365.cn/6-9475-0.html 内容来自互联网,请自行判断内容的正确性。如有侵权请联系我们,立即删除!
- 上一篇: 科技抗老新突破,香港美容仪品牌内地重磅上市
- 下一篇: AI绘制流程图