我的程序准备好进行 FFT 了吗?

Is my program ready for FFT?

我必须制作一个简单的模块,在其中获取长度最多为 3 秒的 .wav 文件,然后我必须首先从该文件中提取振幅和频率。 我这样做是通过创建波形文件流,然后读取数据并将其同时添加到列表中(但将其命名为 arr),如下所示:

    do                                                                                          
    { i = wav.ReadByte(); if (i != -1) { arr.Add(i); } }                                         
    while (i != -1); Console.WriteLine(arr.Count); Console.ReadLine();   

然后从第 44 位开始,我要么在控制台上打印此信息,要么将其转储到文本文件中。现在我看到的是 0-255 范围内的整数。我知道为了获得频率,我必须使用快速傅立叶变换 (FFT) 将数据从时域转换到频域。 现在我的困惑是:

  1. 我的列表中的数据以其当前形式表示什么?
  2. 我读了很多关于首先对信号进行采样的内容,但是由于文件已经是数字格式,所以我应该担心采样,因为我认为它只在 ADC 期间完成。另一方面,如果它仍然需要完成,那么我为什么要这样做,因为我已经在使用整个文件。
  3. 当前形式的数据是否已准备好用于 FFT?
  4. 我现在在为 FFT 准备数据时缺少什么?

现在我只需要一种简单的方法来获取频率。如果需要的话,稍后我会添加更详细的数据提取。

我一直在研究声音处理的理论部分。但是没有一本书或文章准确地说明了 FFT 的数据准备。 我发现的一些有用的链接是:
Importing a .wav file in c# and extracting the signal an array of doubles
How to get sound data sample value in c#
Storing a wav file in an array

这篇文章支持我的逻辑,即仅在 ADC 期间需要采样
http://www.relisoft.com/science/physics/sampling.html

下面的代码不适合 PUBLIC 查看,因为现在它包含大量冗余,我在不同的点引入了这些冗余,以便可视化每个步骤的输出。

class MyClass
{
  static void Main(string[] args)
  {
    string path = @"C:\wav_samples\"; 
    Console.WriteLine("Select a song between 1 to 10");
    string choice = Console.ReadLine();
    string finalpath = path + choice+".wav";
    //Creating a Stream for my .WAV File
    FileStream wav = new FileStream(finalpath , FileMode.Open);

    /*Declaring the ints & the list for the storage of bytes from the Stream for FFT */
    int i;
    List<double> arr = new List<double>();



    ///////////////////////////////////////////////////////////////////////////////////////////////
    /*Reading Bytes from the .WAV File & then printing out the corresponding integer values */
    do                                                                                          
    { i = wav.ReadByte(); 
        if (i != -1)                                                                                            
        { arr.Add(i); } }                                                                       
    while (i != -1); Console.WriteLine(arr.Count); Console.ReadLine();                          
    ////////////////////////////////////////////////////////////////////////////////

    //*Removing first 44 bytes of data as they include header information & other metadata*/
    arr.RemoveRange(0, 44);

    /*No method to find the size of list hence copying the data of list to a new array*/
    double[] storage = new double[arr.Count];
    arr.CopyTo(storage);
    Console.WriteLine(storage.LongLength);

    //Dumping results on screen or in a text file
    Console.WriteLine("Do you want to get results on the screen, press 1 for yes or 2 for dumping this in a text_file in wav_sample folder");
    int a = Convert.ToInt16(Console.ReadLine());
    if (a == 1) 
    {
        for (int limit = 0; limit < storage.LongLength; limit++ )
            Console.WriteLine(arr[limit]);
    }
    if (a == 2)
    {
        System.IO.StreamWriter file = new System.IO.StreamWriter(path +            "Results.txt", true);
        for (int limit = 0; limit < storage.LongLength; limit++ )
        { file.WriteLine( storage[limit] ); }
    }
    Console.ReadLine();
  }
}
  1. What does the data in my List is representing in its current form?

在当前形式中,您将从文件中获取原始字节序列,但您要明确删除的 header 除外。原始字节和对应的数据样本值之间的映射一般是non-trivial,根据选择的编码方案不同而不同。有关详细信息,请参阅 this wave file specification

  1. I read a lot about Sampling the signal first, but since the file is already in a digital format so should I be worried about sampling because I think it is done during ADC only. On the other hand if it is still needed to be done, then why should I be doing that as I'm already using the whole file.

事实上,波形文件包含数字采样数据,因此您无需担心对这些数据进行采样。然而,您很可能需要知道这些数据是如何采样的,尤其是所使用的采样率。该信息包含在 wav 文件中 header.

  1. Is the data in its current form ready for the FFT?

简单地说,没有。正如我在上面指出的,数据仍然是原始字节形式,使用 CopyTo 尝试将原始字节转换为 double 的数组并没有削减它。

  1. What are the things I'm missing right now for preparing the data for FFT?

您需要将原始字节序列转换为数据样本值。如果您自己执行此操作,则必须考虑每个样本的位数、通道数(如果您不处理单声道,则对通道进行去交织)和编码格式(PCM、IEEE float、 ETC。)。 幸运的是有几个库(例如 NAudio) which can perform this decoding for you. Alternatively you may want to have a look at answers this post.