audioop的"sound fragment"参数是什么类型的文件?

What type of file is the "sound fragment" parameter for audioop?

Python audioop documentation 声明大多数可用函数需要 "sound fragments."

The audioop module contains some useful operations on sound fragments. It operates on sound fragments consisting of signed integer samples 8, 16 or 32 bits wide, stored in Python strings.

声音片段到底是什么?如何将现有的 .wav 文件转换为一个?

谢谢。

您可能需要查看 wave 模块。您可能想以读取模式打开文件并使用 readframes 获取 audiooop.

所需的示例

您可以使用 wave module

open()方法打开文件,readframes(n)returns(最多)n帧音频为字节串,正是audioop想要的。

例如,假设您需要使用 audioop 的 avg() 方法。您可以这样做:

import wave
import audioop


wav = wave.open("piano2.wav")
print(audioop.avg(wav.readframes(wav.getnframes()), wav.getsampwidth()))

输出:

-2

此外,您可能对 wave 模块中的 rewind() 方法感兴趣。它将读取位置放回到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()))

要回答片段到底是什么,它是 bytes object,它只是一串字节。我相信对于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

一个声音片段表示在 bytes-like 对象中编码的一系列有符号整数声音样本。 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**152**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