Python audioop 文档指出,大多数可用函数都需要“声音片段”。
audioop 模块包含一些对声音片段有用的操作。它对由 8、16 或 32 位宽的有符号整数样本组成的声音片段进行操作,存储在 Python 字符串中。
究竟什么是声音片段?如何将现有的 .wav 文件转换为一个?
谢谢。
Python audioop 文档指出,大多数可用函数都需要“声音片段”。
audioop 模块包含一些对声音片段有用的操作。它对由 8、16 或 32 位宽的有符号整数样本组成的声音片段进行操作,存储在 Python 字符串中。
究竟什么是声音片段?如何将现有的 .wav 文件转换为一个?
谢谢。
您可以通过使用wave 模块来做到这一点
该open()
方法打开文件并readframes(n)
返回(最多)n 帧音频作为字节串,这正是 audioop 想要的。
例如,假设您需要使用avg()
来自 audioop 的方法。你可以这样做:
import wave
import audioop
wav = wave.open("piano2.wav")
print(audioop.avg(wav.readframes(wav.getnframes()), wav.getsampwidth()))
输出:
-2
此外,您可能对rewind()
wave 模块中的方法感兴趣。它将读取位置放回到 wav 文件的开头。
如果你需要通读你的 wav 文件两次,你可以这样写:
wav = wave.open("piano2.wav")
print(audioop.avg(wav.readframes(wav.getnframes()), wav.getsampwidth()))
# if you don't call rewind, next readframes() call
# will return nothing and audioop will fail
wav.rewind()
print(audioop.max(wav.readframes(wav.getnframes()), wav.getsampwidth()))
或者,您可以缓存字符串:
wav = wave.open("piano2.wav")
string_wav = wav.readframes(wav.getnframes())
print(audioop.avg(string_wav, wav.getsampwidth()))
# wav.rewind()
print(audioop.max(string_wav, wav.getsampwidth()))
您可能想查看该wave
模块。您可能希望以读取模式打开文件并用于readframes
获取所需的样本audiooop.
要回答片段到底是什么,它是一个字节对象,它只是一串字节。我相信对于 8 位音频文件,8 位音频每帧一个字节,16 位音频每帧两个字节,32 位音频每帧四个字节。
import audioop
import wave
read = wave.open("C:/Users/Pratik/sampy/cat.wav")
string_wav = read.readframes(read.getnframes())
a = audioop.lin2alaw(string_wav,read.getsampwidth())
print(a)
----------------------------------------------------------
how to convert wav file to alaw
声音片段表示在字节类对象中编码的有符号整数声音样本序列。audioop
支持每个样本 1、2、3 或 4 个字节的表示。
单个样本可以转换为struct.pack
(我们以 0、1、2、-1、42 为例):
from struct import pack
for sample in [0, 1, 2, -1, 42]:
print(f'sample value {sample}, 1 byte/sample:', pack('b', sample))
print(f' {sample}, 2 byte/sample:', pack('h', sample))
print(f' {sample}, 4 byte/sample:', pack('i', sample))
这打印:
sample value 0, 1 byte/sample: b'\x00'
0, 2 byte/sample: b'\x00\x00'
0, 4 byte/sample: b'\x00\x00\x00\x00'
sample value 1, 1 byte/sample: b'\x01'
1, 2 byte/sample: b'\x01\x00'
1, 4 byte/sample: b'\x01\x00\x00\x00'
sample value 2, 1 byte/sample: b'\x02'
2, 2 byte/sample: b'\x02\x00'
2, 4 byte/sample: b'\x02\x00\x00\x00'
sample value -1, 1 byte/sample: b'\xff'
-1, 2 byte/sample: b'\xff\xff'
-1, 4 byte/sample: b'\xff\xff\xff\xff'
sample value 42, 1 byte/sample: b'*'
42, 2 byte/sample: b'*\x00'
42, 4 byte/sample: b'*\x00\x00\x00'
假设我们想将 Python(有符号)整数表示中的一些声音样本转换为一个声音片段,每个样本使用 2 个字节(允许输入样本值在 -32768 到 32767 之间;即) -2**15
,2**15-1
就像在音频 CD 中使用的那样:
import audioop
import array
samples = [0, 1000, 32767, 1, -1, -32768, -1000] # 7 samples of "music"
fragment = array.array('h', samples).tobytes()
print(f'Fragment {fragment} of length {len(fragment)}')
# convert back with audioop function
print([audioop.getsample(fragment, 2, i) for i in range(len(fragment) // 2)])
这打印:
Fragment b'\x00\x00\xe8\x03\xff\x7f\x01\x00\xff\xff\x00\x80\x18\xfc' of length 14
[0, 1000, 32767, 1, -1, -32768, -1000]
作为最后一个示例,将 3 秒立体声正弦波写入.wav
文件并再次读取:
import audioop
import wave
from array import array
from math import sin, pi
bytes_per_sample = 2
duration = 3. # seconds
sample_rate = 16000. # Hz
frequency = 440. # Hz
max_amplitude = 2**(bytes_per_sample * 8 - 1) - 1
amp = max_amplitude * 0.8
time = [i / sample_rate for i in range(int(sample_rate * duration))]
samples = [int(round(amp * sin(2 * pi * frequency * t))) for t in time]
fragment_mono = array('h', samples).tobytes()
fragment_stereo = audioop.tostereo(fragment_mono, bytes_per_sample, 1, 1)
with wave.open('sine_440hz_stereo.wav', 'wb') as wav:
wav.setnchannels(2) # stereo
wav.setsampwidth(bytes_per_sample)
wav.setframerate(sample_rate)
wav.writeframes(fragment_stereo)
# read wave file again
with wave.open('sine_440hz_stereo.wav', 'rb') as wav:
fragment = wav.readframes(wav.getnframes())
# test whether written fragment and read fragment are same
assert fragment == fragment_stereo