10

Python audioop 文档指出,大多数可用函数都需要“声音片段”。

audioop 模块包含一些对声音片段有用的操作。它对由 8、16 或 32 位宽的有符号整数样本组成的声音片段进行操作,存储在 Python 字符串中。

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

谢谢。

4

5 回答 5

7

您可以通过使用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()))
于 2015-06-03T23:10:32.100 回答
3

您可能想查看该wave模块。您可能希望以读取模式打开文件并用于readframes获取所需的样本audiooop.

于 2015-06-03T22:54:24.707 回答
1

要回答片段到底是什么,它是一个字节对象,它只是一串字节。我相信对于 8 位音频文件,8 位音频每帧一个字节,16 位音频每帧两个字节,32 位音频每帧四个字节。

于 2018-01-06T23:39:34.987 回答
1
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
于 2020-09-02T18:48:45.803 回答
1

声音片段表示在字节类对象中编码的有符号整数声音样本序列。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
于 2020-10-03T16:59:35.673 回答