【问题标题】:How to Encode a 16 Bit WAV file in 8 bit in Python?如何在 Python 中以 8 位编码 16 位 WAV 文件?
【发布时间】:2020-09-11 08:08:35
【问题描述】:

我正在尝试从锯齿波中播放声音。我在 Python 中创建了波形并能够将其保存为 WAV 文件,但是当我尝试播放它时,它说文件无法播放,因为文件类型不受支持、文件扩展名不正确或文件已损坏。我使用了这个人的教程 (https://thehackerdiary.wordpress.com/2017/06/09/it-is-ridiculously-easy-to-generate-any-audio-signal-using-python/),他们通过在 Audacity 中将原始波形从 16 位编码到 8 位来解决这个问题。仅使用 Python 怎么能做到这一点?

import soundfile

data, samplerate = soundfile.read('sawtooth_100_hz.wav')
soundfile.write('sawtooth_100_hz_8bit.wav', data, samplerate, subtype='PCM_S8')

^^ 我试过这个并得到以下错误: ValueError: Invalid combination of format, subtype and endian

【问题讨论】:

    标签: python audio wav


    【解决方案1】:

    我认为编写本教程的人走了很长的路。有一种更简单的方法可以将 NumPy 数组转换为 wav 文件,该文件在下面用于生成与教程中生成的相同的 wav 文件:

    import numpy as np
    from scipy.io import wavfile
    
    sampling_rate = 44100
    freq = 440
    samples = 44100
    
    x = np.arange(samples)
    y = 100*np.sin(2 * np.pi * freq * x / sampling_rate)
    
    wavfile.write("test.wav", sampling_rate, y)
    

    你可以使用wavfile.read()方法来读取这个文件没有问题

    【讨论】:

    • 感谢您提供更简单的代码。但是,我仍然无法将 test.wav 文件作为声音播放。如何使用 wavfile.read() 实际播放声音?
    • 不,您可以使用任何应用程序玩test.wav。当您想将此 wav 文件作为数组读取时,请使用 wavfile.read()
    【解决方案2】:

    令人惊讶的是,底层 libsndfile 库不支持带有 已签名 8 位样本(仅无符号)的 WAV 文件,请参阅 http://www.mega-nerd.com/libsndfile/#Features

    您也可以使用soundfile 模块进行检查:

    >>> import soundfile as sf
    >>> sf.available_subtypes('wav')
    {'PCM_16': 'Signed 16 bit PCM', 'PCM_24': 'Signed 24 bit PCM', 'PCM_32': 'Signed 32 bit PCM', 'PCM_U8': 'Unsigned 8 bit PCM', 'FLOAT': '32 bit float', 'DOUBLE': '64 bit float', 'ULAW': 'U-Law', 'ALAW': 'A-Law', 'IMA_ADPCM': 'IMA ADPCM', 'MS_ADPCM': 'Microsoft ADPCM', 'GSM610': 'GSM 6.10', 'G721_32': '32kbs G721 ADPCM'}
    

    您可以尝试使用 AIFF 或 FLAC 代替吗?

    或者您可以创建一个 RAW 文件(即一个不包含有关其自身数据格式的信息的无头文件),这就是他们在您提到的教程中所做的(注意他们正在使用这些选项:-t raw -e signed -b 8) .

    有关创建和播放信号的更多信息,请参阅:

    【讨论】:

      【解决方案3】:

      听起来您只是想从 Python 中生成样本和回放?

      如果是这样,看起来库“sounddevice”可以让您将样本直接写入您的音频设备:

      https://python-sounddevice.readthedocs.io/en/0.3.15/usage.html#playback

      我现在不在 python 环境中,所以还没有测试,但是将它与您的示例代码混合只是:

      import sounddevice as sd
      import numpy as np
      
      sampling_rate = 44100
      freq = 440
      samples = 44100
      
      x = np.arange(samples)
      y = 100*np.sin(2 * np.pi * freq * x / sampling_rate)
      
      sd.play(y, sampling_rate)
      

      Sounddevice 的作者在 SO,请参阅他对类似问题的回复:https://stackoverflow.com/a/34179010/1339735

      您可能需要进行一些缩放 - 不确定它是否像大多数浮点播放一样接受从 -1 到 1 的值,或者像您的示例中那样接受 +/- 100。

      【讨论】:

        【解决方案4】:

        以上所有答案都很有帮助,但最终我从这个帖子中找到了解决我的问题的方法:How to generate audio from a numpy array?

        这是我的代码:

        import numpy as np
        from scipy.io.wavfile import write
        from scipy import signal as sg
        
        #data = np.random.uniform(-1,1,44100) # 44100 random samples between -1 and 1
        sampling_rate = 44100                    ## Sampling Rate
        freq = 150                               ## Frequency (in Hz)
        duration = 3   # in seconds, may be float
        
        t = np.linspace(0, duration, sampling_rate*duration) # Creating time vector
        data = sg.sawtooth(2 * np.pi * freq * t, 0)          # Sawtooth signal
        
        '''
        Scaling data to 16 bit. Divide each number by max number in array to get
        fraction and multiply data by 32767 because that is the max value a 16 bit
        integer can take
        '''
        scaled = np.int16(data/np.max(np.abs(data)) * 32767) 
        write('test.wav', 44100, scaled) # Write to file. Can be overridden
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-10-24
          • 1970-01-01
          • 2017-01-09
          • 2011-10-08
          • 2013-07-01
          • 1970-01-01
          相关资源
          最近更新 更多