音频文件读取用于FFT

4

虽然我一直在访问,但这是我第一次提问。

问题如下:

我目前正在尝试分离包含以下属性的WAVE数据文件中信号的基频:

  • PCM音频格式即线性量化
  • 8000 Hz采样率
  • 每个样本16位
  • 16000字节速率

仅有一个通道,没有交错。

获取字节值:

System.IO.FileStream WaveFile = System.IO.File.OpenRead(@"c:\tet\fft.wav");
        byte[] data = new byte[WaveFile.Length];
        WaveFile.Read(data,0,Convert.ToInt32(WaveFile.Length));

将其转换为Double类型的数组:

 for (int i = 0; i < 32768; i++)//this is only for a relatively small chunk of the file 
        {
           InReal[i] =BitConverter.ToDouble(data, (i + 1) * 8 + 44);
        }

最后将其传递给转换函数。
       FFT FftObject = new FFT();
       FftObject.Transform(InReal, InImg, 0, 32768, out outReal, out outImg, false);

现在的第一个问题是,我理解wav文件的PCM值应该在-1和1之间,但是当转换为Double时,我得到了这些值:
 2.65855908666825E-235
 2.84104982662944E-285
-1.58613492930337E+235
-1.25617351166869E+264
 1.58370933499389E-242
 6.19284549187335E-245
-2.92969500042228E+254
-5.90042665390976E+226
 3.11954507295188E-273
 3.06831908609091E-217
 NaN
 2.77113146323761E-302
 6.76597919848376E-306
-1.55843653898344E+291

这些是数组的前几个,剩余的数组也在这些限制之内。

我的结论是我有某种代码故障,但似乎找不到它。任何帮助都将不胜感激。

第二个问题是,因为我只向FFT算法提供响应向量中的真实数据,所以我只能期望得到真实部分数据吗?

非常感谢您。


你的意思是每个样本16位,速率为16 kbits/s而不是字节吗? - huon
1
@vlad_d26 嗯,我对WAV格式不是很了解,但16位采样应该大多数情况下被转换为short(ToInt16),而不是double。此外,如果我没记错的话,BitConverter的字节序取决于它运行的CPU,所以要小心不要出现问题。 - Joachim Isaksson
我在Intel机器上运行它,Intel处理器是小端字节序,并尝试处理字节的重要性,对于转换ToSingle更像它,但还是谢谢。 - Vladimir
@JoachimIsaksson 转换为 Single 将返回一个单精度浮点数,其大小为 4 字节,与数据在 wav 文件中存储的方式完全相同。如果我在这里使用整数,将会丢失数字的小数部分。 - Vladimir
@vlad_d26 Float(单精度浮点数)确实是可以存储在WAV中的有效类型,但它需要每个样本32位,而您的问题说明了16位。我建议您仔细检查所包含的类型,这可能是您的问题所在。 - Joachim Isaksson
显示剩余4条评论
1个回答

2

我终于找到了问题出在哪里。似乎是在数据表示中没有考虑到信号的脉冲编码调制。由于在处理用于傅里叶变换的波形文件时,我在这里找到了许多未解答的问题,因此这里提供了一个函数的代码以准备波形文件。

public static Double[] prepare(String wavePath, out int SampleRate)

    {
        Double[] data;
        byte[] wave;
        byte[] sR= new byte[4];
        System.IO.FileStream WaveFile = System.IO.File.OpenRead(wavePath);
        wave = new byte[WaveFile.Length];
        data = new Double[(wave.Length - 44) / 4];//shifting the headers out of the PCM data;
        WaveFile.Read(wave,0,Convert.ToInt32(WaveFile.Length));//read the wave file into the wave variable
        /***********Converting and PCM accounting***************/
        for (int i = 0; i < data.Length - i * 4; i++)
        {
            data[i] = (BitConverter.ToInt32(wave, (1 + i) * 4)) / 65536.0;
            //65536.0.0=2^n,       n=bits per sample;
        }
        /**************assigning sample rate**********************/
        for (int i = 24; i < 28; i++)
        {
            sR[i-24]= wave[i];
        }
        SampleRate = BitConverter.ToInt32(sR,0);
        return data;
    }

现在你需要做的就是将采样率和返回结果发送给FFT算法。代码未处理,根据需要自行处理。已经测试过电话录音中的忙音、振铃和语音,它可以正确地运行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接