获取 WAV 文件的 PCM 值

Posted

技术标签:

【中文标题】获取 WAV 文件的 PCM 值【英文标题】:Getting PCM values of WAV files 【发布时间】:2013-07-01 12:51:28 【问题描述】:

我有一个 .wav 单声道文件(16 位,44.1kHz),我使用下面的代码。如果我没有错,这会给我一个介于 -1 和 1 之间的值的输出,我可以应用 FFT(稍后转换为频谱图)。但是,我的输出与 -1 和 1 相差无几。

这是我输出的一部分

7.01214599609375  
17750.2552337646  
8308.42733764648  
0.000274658203125  
1.00001525878906  
0.67291259765625  
1.3458251953125  
16.0000305175781  
24932  
758.380676269531  
0.0001068115234375    

这是我从另一个帖子中得到的代码编辑 1:

 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 += 2)
        
             data[i] = BitConverter.ToInt16(wave, i) / 32768.0;
        


        /**************assigning sample rate**********************/
        for (int i = 24; i < 28; i++)
        
            sR[i - 24] = wave[i];
        
        SampleRate = BitConverter.ToInt16(sR, 0);
        return data;
      

编辑 2:我每第二个数字输出 0

0.009002685546875 0 0.009613037109375 0 0.0101318359375 0 0.01080322265625 0 0.01190185546875 0 0.01312255859375 0 0.014068603515625

【问题讨论】:

该代码过于简单和错误。简单化:这取决于 WAV 文件的比特率如何执行转换。错误:它读取四个字节并使用 UInt16.MaxValue 而不是 Int32.MaxValue 对其进行规范化。 如果在那之前没有人回答,我可以在几个小时内提供详细的答案。如果您仍然需要帮助并且我没有提供答案,请在 7 小时内通过评论记住我。 是的,希望您能提供详细的答复。我对音频处理有点陌生,所以请多多包涵。我应该录制一个声音并对其应用 FFT 并将其转换为频谱图,以便我能够设置采样率和否。通过 Naudio lib 的 wav 文件的通道。谢谢 正如 Daniel 指出的那样,您的主要问题是您通过除以“UInt16.MaxValue”来规范化 32 位值。您需要除以 Int.MaxValue,这将为您提供 -1 .. 1 范围内的值。此外,您可以使用 for (int i = 0; i &lt; data.Length; i += 4) 简化代码,并删除索引中的乘法。 或者......很难说,因为你的代码很混乱。如果您使用的是单声道声音(即一个通道),那么您的样本应该是 16 位的,因此您应该使用 BitConverter.ToInt16,并且在循环中只增加 2。 【参考方案1】:

如果您的样本是 16 位(似乎是这种情况),那么您希望使用 Int16。样本数据的每 2 个字节是一个带符号的 16 位整数,范围为 -32768 .. 32767(含)。

如果要将带符号的Int16 转换为从-1 到1 的浮点值,则必须除以Int16.MaxValue + 1(等于32768)。因此,您的代码变为:

for (int i = 0; i < data.Length; i += 2)

    data[i] = BitConverter.ToInt16(wave, i) / 32768.0;

我们在这里使用 32768,因为这些值是有符号的。

所以 -32768/32768 会给出 -1.0,而 32767/32768 会给出 0.999969482421875。

如果您使用 65536.0,那么您的值将仅在 -0.5 .. 0.5 范围内。

【讨论】:

嗨,非常感谢,我能够获得介于 -1 和 1 范围内的值。如果我使用 16 位样本,我需要将 SampleRate = BitConverter.ToInt32(sR,0) 更改为 SampleRate = BitConverter.ToInt16(sR,0)?还是没关系?我提供的代码是否需要更多编辑,因为我不确定此代码是否显示最佳结果。

以上是关于获取 WAV 文件的 PCM 值的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 java 从 pcm 字节数组 .wav 文件中获取频率和音高?

[概念]PCM文件&WAV文件头

wav音频文件解析读取 定点转浮点分析 幅值提取(C语言实现)

SoundPlayer 不播放任何捆绑的 Windows 声音 PCM wav 文件

wav格式和pcm格式怎么相互转换?

如何将wav音频文件格式为pcm转化为ima adpcm格式