【问题标题】:how to convert wav file to float amplitude如何将wav文件转换为浮动幅度
【发布时间】:2011-12-07 20:55:11
【问题描述】:

所以我问了标题中的所有内容:

我有一个 wav 文件(由 PyAudio 从输入音频写入),我想将其转换为与声级(幅度)相对应的浮点数据,以进行傅立叶变换等...

有人有想法将 WAV 数据转换为浮点数吗?

【问题讨论】:

    标签: python audio wave pyaudio


    【解决方案1】:

    我已经确定了两种不错的方法。

    方法一:使用wavefile模块

    如果您不介意安装一些额外的库,这些库在我的 Mac 上有点麻烦,但在我的 Ubuntu 服务器上很容易,请使用此方法。

    https://github.com/vokimon/python-wavefile

    import wavefile
    
    # returns the contents of the wav file as a double precision float array
    def wav_to_floats(filename = 'file1.wav'):
        w = wavefile.load(filename)
        return w[1][0]
    
    signal = wav_to_floats(sys.argv[1])
    print "read "+str(len(signal))+" frames"
    print  "in the range "+str(min(signal))+" to "+str(min(signal))
    

    方法二:使用wave模块

    如果您想减少模块安装的麻烦,请使用此方法。

    从文件系统读取一个 wav 文件并将其转换为 -1 到 1 范围内的浮点数。它适用于 16 位文件,如果它们大于 1 通道,将以与在文件。对于其他位深度,请根据本页底部的表格将参数中的 'h' 更改为 struct.unpack:

    https://docs.python.org/2/library/struct.html

    它不适用于 24 位文件,因为没有 24 位的数据类型,所以没有办法告诉 struct.unpack 做什么。

    import wave
    import struct
    import sys
    
    def wav_to_floats(wave_file):
        w = wave.open(wave_file)
        astr = w.readframes(w.getnframes())
        # convert binary chunks to short 
        a = struct.unpack("%ih" % (w.getnframes()* w.getnchannels()), astr)
        a = [float(val) / pow(2, 15) for val in a]
        return a
    
    # read the wav file specified as first command line arg
    signal = wav_to_floats(sys.argv[1])
    print "read "+str(len(signal))+" frames"
    print  "in the range "+str(min(signal))+" to "+str(min(signal))
    

    【讨论】:

    • 如果你得到OSErrorwave.Error 尝试通过cli 使用ffmpeg 命令ffmpeg -i song.mp3 song.wav 来转换音频文件。它应该可以工作(src
    【解决方案2】:

    我花了几个小时试图找到这个问题的答案。解决方案非常简单: struct.unpack 就是您要寻找的。最终代码将如下所示:

    rawdata=stream.read()                  # The raw PCM data in need of conversion
    from struct import unpack              # Import unpack -- this is what does the conversion
    npts=len(rawdata)                      # Number of data points to be converted
    formatstr='%ih' % npts                 # The format to convert the data; use '%iB' for unsigned PCM
    int_data=unpack(formatstr,rawdata)     # Convert from raw PCM to integer tuple
    

    大部分功劳归于Interpreting WAV Data。唯一的技巧是获得正确的解包格式:它必须是正确的字节数和正确的格式(有符号或无符号)。

    【讨论】:

      【解决方案3】:

      大多数波形文件都是 PCM 16 位整数格式。

      你想要什么:

      • 将标头解析为已知格式(查看 Xophmeister 的链接)
      • 读取数据,获取整数值并将其转换为浮点数

      整数值的范围是-32768到32767,你需要转换成浮点数从-1.0到1.0的值。

      我没有 python 中的代码,但是在 C++ 中,如果 PCM 数据是 16 位整数,这里是代码摘录,并将其转换为浮点数(32 位):

      short* pBuffer = (short*)pReadBuffer;
      
      const float ONEOVERSHORTMAX = 3.0517578125e-5f; // 1/32768 
      unsigned int uFrameRead = dwRead / m_fmt.Format.nBlockAlign;
      
      for ( unsigned int i = 0; i < uFrameCount * m_fmt.Format.nChannels; ++i )
      {
          short i16In = pBuffer[i];
          out_pBuffer[i] = (float)i16In * ONEOVERSHORTMAX;
      }
      

      小心立体声文件,因为波形文件中的立体声 PCM 数据是交错的,这意味着数据看起来像 LRLRLRLRLRLRLRLR(而不是 LLLLLLLLRRRRRRRR)。您可能需要也可能不需要去交错,具体取决于您对数据的处理方式。

      【讨论】:

        【解决方案4】:

        此版本从文件系统中读取一个 wav 文件并将其转换为 -1 到 1 范围内的浮点数。它适用于所有样本宽度的文件,它会以与文件中相同的方式交错样本。

        import wave
        
        def read_wav_file(filename):
            def get_int(bytes_obj):
                an_int = int.from_bytes(bytes_obj, 'little',  signed=sampwidth!=1)
                return an_int - 128 * (sampwidth == 1)
            with wave.open(filename, 'rb') as file:
                sampwidth = file.getsampwidth()
                frames = file.readframes(-1)
            bytes_samples = (frames[i : i+sampwidth] for i in range(0, len(frames), sampwidth))
            return [get_int(b) / pow(2, sampwidth * 8 - 1) for b in bytes_samples]
        

        这里还有一个将浮点数转换回整数并将它们写入所需的 wav 文件的函数的链接:

        https://gto76.github.io/python-cheatsheet/#writefloatsamplestowavfile

        【讨论】:

          【解决方案5】:

          Microsoft WAVE 格式有很好的文档记录。例如,请参阅https://ccrma.stanford.edu/courses/422/projects/WaveFormat/。编写一个文件解析器来打开和解释数据以获取您需要的信息并不需要太多......也就是说,几乎可以肯定之前已经完成了,所以我相信有人会给出一个“更简单”的答案; )

          【讨论】:

            猜你喜欢
            • 2017-09-28
            • 2011-06-17
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-06-19
            • 1970-01-01
            • 2011-06-19
            • 2020-04-22
            相关资源
            最近更新 更多