c# - 如何使用 NAudio 实时计算 FFT(ASIO 输出)

标签 c# fft naudio asio

我正在编写吉他( fiddle )Hero 的克隆程序作为本学年的期末项目。

我的想法是从我的电 fiddle 获取输入,通过 FFT 对其进行分析,进行一些逻辑和绘图,然后通过扬声器输出。也许是并行线程中的一些步骤。

我已经实现了 Asio 低延迟输入输出,但我在实现实时 FFT 时遇到了很大的问题。

这是一段设置 asioOut 和 sampleAggregator 的代码。样本聚合器应存储每次调用 AudioAvailable() 时添加的样本,并在样本数超过 fftLength 时触发 FFT 计算。

private static int fftLength = 8192;
private SampleAggregator sampleAggregator = new SampleAggregator(fftLength);

void asioStartPlaying(object sender, EventArgs e)
{
    sampleAggregator.PerformFFT = true;
    sampleAggregator.FftCalculated += new EventHandler<FftEventArgs>(FftCalculated);
    var asioOut = new AsioOut();
    BufferedWaveProvider wavprov = new BufferedWaveProvider(new WaveFormat(48000, 1));
    asioOut.AudioAvailable += new EventHandler<AsioAudioAvailableEventArgs> (asio_DataAvailable);
    asioOut.InitRecordAndPlayback(wavprov, 1, 25);
    asioOut.Play();
}

void asio_DataAvailable(object sender, AsioAudioAvailableEventArgs e)
{
    byte[] buf = new byte[e.SamplesPerBuffer*4];

    for (int i = 0; i < e.InputBuffers.Length; i++)
    {
        Marshal.Copy(e.InputBuffers[i], buf, 0, e.SamplesPerBuffer*4);
        Marshal.Copy(buf, 0, e.OutputBuffers[i], e.SamplesPerBuffer*4);
    }

    for (int i = 0; i < buf.Length; i=i+4)
    {
        float sample32 = BitConverter.ToSingle(buf, i);
        sampleAggregator.Add(sample32);
    }

    e.WrittenToOutputBuffers = true;
}

SampleAggregator 是取自 NAudio fft result gives intensity on all frequencies C# 的类.

Asio 以 Int32LSB 样本类型输出数据。在 buf 中有从 0 到 255 的值。

这是计算 fft 时应调用的函数(从 SampleAggregator 类触发)。

void FftCalculated(object sender, FftEventArgs e)
{
    for (var i = 0; i < e.Result.Length; i++)
    {
        Debug.WriteLine("FFT output.");
        Debug.WriteLine(e.Result[i].X);
        Debug.WriteLine(e.Result[i].Y);
    }
}

但 FFT 结果总是输出 NaN。

我认为转换为 float 有问题。

有人能给我指出正确的方向吗?

EDIT_1:我将 DataAvailable() 中的循环更改为

for (int i = 0; i < e.SamplesPerBuffer * 4; i++)
{
    float sample32 = Convert.ToSingle(buf[i]);
    sampleAggregator.Add(sample32);
}

现在 FFT 输出数据。但我认为他们是不正确的。 错误一定是在asio 样本和浮点值之间的转换。但我对字节操作不太满意。

e.GetAsInterleavedSamples 能以某种方式提供帮助吗?

FFT 原始数据样本: X:-5,304741 Y:-0,7160959 X: 6,270798 Y:-0,4169312 X:-8,851931 Y:-0,4485725

我注意到,FFT 原始数据中的前几个和最后几个值在某种程度上比其他数据大。使震级的计算变得棘手。

最佳答案

问题正如我所想的那样,在关于来自 Asio 的样本数据(buf 数组中一行 4 个字节)与 fft 的 float 之间的转换中。 BitConvertor 应该可以解决问题,但在我的例子中,它以某种方式使 fft 输出 NaN。所以我尝试了这种转换。

for (int i = 0; i < e.SamplesPerBuffer * 4; i += 4)
{
    float sample = Convert.ToSingle(buf[i] + buf[i + 1] + buf[i + 2] + buf[i + 3]);
    sampleAggregator.Add(sample);
}

而且效果很好。即使采样率为 192 000。

关于c# - 如何使用 NAudio 实时计算 FFT(ASIO 输出),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24016477/

相关文章:

c# - 带有 NAudio 和 WPFSoundVisualizationLib 的频谱分析仪

c# - 如何操作 Html.ActionLink 以显示到另一个 Controller 的链接?

javascript - 在不使用 Form 标签的情况下在页面上放置秒表?

r - 检测 R 中的季节性

c++ - Kiss FFT 似乎将数据乘以它转换的点数

c# - 使用 WPF 播放 MIDI 文件并与视觉同步时间

C# .NET4 WPF - 从字符串中设置组合框选择项

c# - 如何在 C# 中使用 Newtonsoft 反序列化

c# - 如何使用 naudio 将音频录制到 byte[] 而不是文件中

c# - 在WPF C#中使用NAudio录制音频