13

我想使用 Python 2.7 从 -1 到 1 之间的浮点值数组生成一个 24 位 WAV 格式的音频文件。我不能使用scipy.io.wavfile.write因为它只支持 16 位或 32 位。Python 自己的wave模块的文档没有指定它采用什么格式的数据。

那么有可能在 Python 中做到这一点吗?

4

7 回答 7

5

2 年前我已经提交了这个问题的答案,我推荐了 scikits.audiolab

与此同时,情况发生了变化,现在有一个更易于使用且更易于安装的库,它甚至带有自己的用于 Windows 和 OSX 的libsndfile库副本(在 Linux 上无论如何都易于安装): PySoundFile

如果您安装了 CFFI 和 NumPy,您只需运行即可安装 PySoundFile

pip install soundfile --user

编写 24 位 WAV 文件很容易:

import soundfile as sf
sf.write('my_24bit_file.wav', my_audio_data, 44100, 'PCM_24')

在此示例中,必须my_audio_data是带有dtype 'float64'、或的 NumPy 数组。'float32''int32''int16'

顺便说一句,我创建了一个概述页面,尝试比较许多可用的 Python 库以读取/写入声音文件。

于 2015-09-02T08:32:26.433 回答
3

试试这个wave模块:

In [1]: import wave

In [2]: w = wave.open('foo.wav', 'w') # open for writing

In [3]: w.setsampwidth(3) # 3 bytes/sample

Python 只能打包 2 和 4 位大小的整数。因此,您可以在 int32 上使用具有 dtype 的 numpy 数组,并使用列表推导来获取每个整数的 3/4 字节:

In [14]: d = np.array([1,2,3,4], dtype=np.int32)

In [15]: d
Out[15]: array([1, 2, 3, 4], dtype=int32)

In [16]: [d.data[i:i+3] for i in range(0,len(d)*d.dtype.itemsize, d.dtype.itemsize)]
Out[16]: ['\x01\x00\x00', '\x02\x00\x00', '\x03\x00\x00', '\x04\x00\x00']
于 2013-05-27T06:23:59.243 回答
3

另一个选项在wavio(也在 PyPI 上:https : //pypi.python.org/pypi/wavio )中可用,这是我创建的一个小模块,用于解决 scipy 尚不支持 24 位 WAV 文件的问题。该文件wavio.py包含函数write,它将一个 numpy 数组写入 WAV 文件。要写入 24 位文件,请使用参数sampwidth=3. 的唯一依赖wavio是 numpy; wavio使用标准库wave处理 WAV 文件格式。

例如,

In [21]: import numpy as np

In [22]: import wavio

In [23]: rate = 22050             # samples per second

In [24]: T = 3                    # sample duration (seconds)

In [25]: f = 440.0                # sound frequency (Hz)

In [26]: t = np.linspace(0, T, T*rate, endpoint=False)

In [27]: sig = np.sin(2 * np.pi * f * t)

In [28]: wavio.write("sine24.wav", sig, rate, sampwidth=3)
于 2015-02-04T04:17:33.067 回答
2

使用该wave模块,该Wave_write.writeframes函数期望 WAV 数据以 little-endian 格式打包成一个 3 字节的字符串。以下代码可以解决问题:

import wave
from contextlib import closing
import struct

def wavwrite_24(fname, fs, data):
    data_as_bytes = (struct.pack('<i', int(samp*(2**23-1))) for samp in data)
    with closing(wave.open(fname, 'wb')) as wavwriter:
        wavwriter.setnchannels(1)
        wavwriter.setsampwidth(3)
        wavwriter.setframerate(fs)
        for data_bytes in data_as_bytes:
            wavwriter.writeframes(data_bytes[0:3])
于 2013-05-27T06:34:53.693 回答
2

您应该尝试scikits.audiolab

import numpy as np
from scikits.audiolab import Sndfile, Format

sig = np.array([0, 1, 0, -1, 0], dtype=np.float32)
f = Sndfile('test_pcm24.wav', 'w', Format('wav', 'pcm24'), 1, 44100)
f.write_frames(sig)
f.close()  # use contextlib.closing in real code

再读一遍:

f = Sndfile('test_pcm24.wav')
sig = f.read_frames(f.nframes, dtype=np.float32)
f.close()  # use contextlib.closing in real code

scikits.audiolab使用libsndfile,所以除了 WAV 文件之外,还可以使用 FLAC、OGG 等一些文件格式。

于 2013-07-03T08:43:01.803 回答
0

这是一个更新版本scipy.io.wavfile,增加了:

  • 24 位 .wav 文件支持读/写,
  • 访问提示标记,
  • 提示标记标签,
  • 其他一些元数据,如音高(如果已定义)等。

wavfile.py(增强)

于 2016-12-11T19:17:34.830 回答
0

利用 ffmpeg 在 wav 编解码器之间进行交换,下面是示例代码

command = "ffmpeg -i input.wav -ar 22050 output.wav"
subprocess.call(command, shell=True)
于 2019-02-01T06:05:19.650 回答