学习如何修改不同类型的音频文件,.wav、.mp3等使用Python3使用wave模块。特别是.wav文件格式,在这方面针对这个问题。目前,我知道有关于音频格式的国际标准化组织标准,对于.wav文件格式的音频标准以及附带说明,对这个主题的任何参考都是非常赞赏的。
但就我的问题而言,在使用 wave模块导入的.wav文件中,忽略了RIFF,FMT headers。
是否有更有效的方法可以跳过RIFF标头和其他容器,直接到数据容器修改其内容?
这个简单的示例只是将一个双声道音频.wav文件转换为单声道音频.wav文件,同时将所有值修改为(0, 0).。
import wave
import struct
# Open Files
inf = wave.open(r"piano2.wav", 'rb')
outf = wave.open(r"output.wav", 'wb')
# Input Parameters
ip = list(inf.getparams())
print('Input Parameters:', ip)
# Example Output: Input Parameters: [2, 2, 48000, 302712, 'NONE', 'not compressed']
# Output Parameters
op = ip[:]
op[0] = 1
outf.setparams(op)
number_of_channels, sample_width, frame_rate, number_of_frames, comp_type, comp_name = ip
format = '<{}h'.format(number_of_channels)
print('# Channels:', format)
# Read >> Second
for index in range(number_of_frames):
frame = inf.readframes(1)
data = struct.unpack(format, frame)
# Here, I change data to (0, 0), testing purposes
print('Before Audio Data:', data)
print('After Modifying Audio Data', (0, 0))
# Change Audio Data
data = (0, 0)
value = data[0]
value = (value * 2) // 3
outf.writeframes(struct.pack('<h', value))
# Close In File
inf.close()
# Close Out File
outf.close()如果只是简单地修改.wav文件的数据段,是否有更好的实践或参考材料?
发布于 2021-05-09 08:33:59
性能比较
让我们检查一下读取WAVE文件的前三种方法。
最慢的单波模块
正如您可能已经注意到的,wave模块可能会非常慢。请考虑以下代码:
import wave
import struct
wavefile = wave.open('your.wav', 'r') # check e.g. freesound.org for samples
length = wavefile.getnframes()
for i in range(0, length):
wavedata = wavefile.readframes(1)
data = struct.unpack("<h", wavedata)对于如下所定义的波浪:
Input File : 'audio.wav'
Channels : 1
Sample Rate : 48000
Precision : 16-bit
Duration : 00:09:35.71 = 27634080 samples ~ 43178.2 CDDA sectors
File Size : 55.3M
Bit Rate : 768k
Sample Encoding: 16-bit Signed Integer PCM平均需要27.7秒才能加载完整的音频。wave模块的另一面是,它是现成的,可以在任何系统上工作。
方便的音效
一个更方便和更快的解决方案是例如audiofile。根据项目描述,它的重点是阅读速度。
import audiofile as af
signal, sampling_rate = af.read(audio.wav)这给了我平均33毫秒的时间来读取上述文件。
最快的一个-矮胖的
如果我们决定跳过头(就像OP要求的那样),只追求速度,那么numpy是一个很好的选择:
import numpy as np
byte_length = np.fromfile(filename, dtype=np.int32, count=1, offset=40)[0]
data = np.fromfile(filename, dtype=np.int16, count=byte_length // np.dtype(np.int16).itemsize, offset=44)标头结构(它告诉我们要使用什么offset )被定义为这里。
该代码的执行时间为6 ms,比audioread少5倍。当然,它有一个价格/先决条件:我们需要预先知道数据类型是什么。
修改音频
一旦您在numpy数组中拥有了音频,您可以随意修改它,您也可以决定流文件,而不是一次读取所有内容。但是请注意:由于声音是一种波,在一个典型的场景中,只要在任意时间注入新的数据,t就会导致音频的失真(除非是沉默)。
至于回写流,在Python中“修改容器”将非常慢。这就是为什么您应该使用数组或切换到更合适的语言(例如C)。
如果我们使用数组,我们应该注意到numpy对WAVE格式一无所知,因此我们必须自己定义标头并编写单独的字节。完全可行的运动,但笨重。幸运的是,枕骨提供了一个方便的函数,它具有numpy速度的优点(它在下面使用numpy ),同时使代码更加可读性:
from scipy.io.wavfile import write
fs = np.fromfile('audio.wav', dtype=np.int32, count=1, offset=24)[0] # we need sample rate
with open('audio_out.wav', 'a') as fout:
new_data = data.append(np.zeros(2 * fs)) # append 2 seconds of zeros
write(fout, fs, new_data) 这可以在一个循环中完成,在这个循环中,您使用numpy / scipy读取块,修改数组(data)并写入文件(使用a作为附件)。
https://stackoverflow.com/questions/67453808
复制相似问题