gpt4 book ai didi

c# - 如何从音频文件(.wav)分离频率

转载 作者:行者123 更新时间:2023-12-03 01:45:01 35 4
gpt4 key购买 nike

我想将低频,中频和高频与.wav文件分开。
为此,我使用FFT将数据从时域转换到频域。

用于读取文件并在NAudio的帮助下应用快速傅立叶变换的代码就像

OpenFileDialog file = new OpenFileDialog();
file.ShowDialog();
WaveFileReader reader = new WaveFileReader(file.FileName);
int samepleRate = reader.WaveFormat.SampleRate;
double ts = 1.0 / samepleRate;
int _fftLength = 4096;
double time = reader.TotalTime.TotalSeconds;
int channels = reader.WaveFormat.Channels;
int _m = (int)Math.Log(_fftLength, 2.0);
float fileSize = (float)reader.Length / 1048576;
if (fileSize < 2)
window = 8;
else if (fileSize > 2 && fileSize < 4)
window = 16;
else if (fileSize > 4 && fileSize < 8)
window = 32;
else if (fileSize > 8 && fileSize < 12)
window = 128;
else if (fileSize > 12 && fileSize < 20)
window = 256;
else if (fileSize > 20 && fileSize < 30)
window = 512;
else
window = 2048;


byte[] readBuffer = new byte[reader.Length];

reader.Read(readBuffer,0,readBuffer.Length);
float[] data = ConvertByteToFloat(readBuffer,readBuffer.Length);

Complex[] fftBuffer= new Complex[_fftLength];
int fftPos = 0;
for (int i = 0; i < _fftLength; i++)
{
fftBuffer[fftPos].X = (float)(data[i] * NAudio.Dsp.FastFourierTransform.HammingWindow(i,_fftLength));
fftBuffer[fftPos].Y = 0;
fftPos++;
}
NAudio.Dsp.FastFourierTransform.FFT(true, _m, fftBuffer);

private float[] ConvertByteToFloat(byte[] array, int length)
{
int samplesNeeded = length / 4;
float[] floatArr = new float[samplesNeeded];

for (int i = 0; i < samplesNeeded; i++)
{
floatArr[i] = (float)BitConverter.ToInt32(array, i * 4);
}

return floatArr;
}

//ZedGraph code
GraphPane myPane = zedGraphControl1.GraphPane;
myPane.Title.Text = "Frequency domain output";
PointPairList list1 = new PointPairList();
PointPairList list2 = new PointPairList();
for (int i = 0; i < fftBuffer.Length; i++)
{
list1.Add(i, fftBuffer[i].Y);
}
list2.Add(0, 0);
//list2.Add(time, 0);uncomment this and remove below to plot time domain graph
var maxIndex = -1;
var maxValue = 0f;
for (var j = 0; j < _fftLength / 2; j++)
{
var value = fftBuffer[j].X * fftBuffer[j].X
+ fftBuffer[j].Y * fftBuffer[j].Y;

if (value > maxValue)
{
maxIndex = j;
maxValue = value;
}
var freq = maxIndex == -1 ? 0
: (ushort)Math.Round((_fftLength - maxIndex) / (_fftLength * ts));
list2.Add(freq, 0);
}
if (myCurve1 != null && myCurve2 != null)
{
myCurve1.Clear();
myCurve2.Clear();
}

myCurve1 = myPane.AddCurve(null, list1, Color.Blue, SymbolType.None);
myCurve1.IsX2Axis = true;
myCurve2 = myPane.AddCurve(null, list2, Color.Black, SymbolType.None);
myPane.XAxis.Scale.MaxAuto = true;
myPane.XAxis.Scale.MinAuto = true;
myPane.YAxis.Title.Text = "Amplitude";
myPane.XAxis.Title.Text = "Frequency";
zedGraphControl1.AxisChange();
zedGraphControl1.Invalidate();

现在,我获得了频域数据,并将其绘制在ZedGraph上,其中Y轴为振幅,X轴为频率。
FFT output on ZedGraph

现在,随着FFT的出现,我有了复杂的数据,但是如何将下面列出的频率与给定的数据分开,以及如何生成或播放该特定频率的文件。
  • 低-20Hz至500Hz
  • Mid-500Hz至4KHz
  • 高-4KHz至20KHz

  • 任何建议或指导将不胜感激..!

    最佳答案

    如果您只想过滤音频流,那么您将面临一种计算量大的方法。 FFT非常适合识别频谱特征。但是,如果您想从时间到频率再回到时间,那将是很多数字上的紧缩(而且您很可能不喜欢听到的声音)。如果保留当前指定的路径,则需要在频域中进行某种形式的屏蔽,然后转换回时间。当您转换回时间(一个真实的产品)时,听起来会很“脏”(您将需要实现某种形式的想象到真实的合并)。在您的代码中,您将形成一个平方的平方,以返回到实时序列(请注意-这将为您提供整流信号-听起来有些嘶哑)。

    如果要隔离特定频带,请从某种形式的FIR带通滤波器开始。如果您想在开发过程中听到结果,请查看有关如何使用Android AudioTrack类的示例。

    关于c# - 如何从音频文件(.wav)分离频率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44325685/

    35 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com