首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Python3正确修改wav音频数据

Python3正确修改wav音频数据
EN

Stack Overflow用户
提问于 2021-05-09 02:34:04
回答 1查看 590关注 0票数 2

学习如何修改不同类型的音频文件,.wav.mp3等使用Python3使用wave模块。特别是.wav文件格式,在这方面针对这个问题。目前,我知道有关于音频格式的国际标准化组织标准,对于.wav文件格式的音频标准以及附带说明,对这个主题的任何参考都是非常赞赏的。

但就我的问题而言,在使用 wave模块导入的.wav文件中,忽略了RIFF,FMT headers。

是否有更有效的方法可以跳过RIFF标头和其他容器,直接到数据容器修改其内容?

这个简单的示例只是将一个双声道音频.wav文件转换为单声道音频.wav文件,同时将所有值修改为(0, 0).

代码语言:javascript
运行
复制
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文件的数据段,是否有更好的实践或参考材料?

  • 如果你真的想在一个特定的时间戳上添加一个声音,那将是我的问题的一个更合适的结果。
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-05-09 08:33:59

性能比较

让我们检查一下读取WAVE文件的前三种方法。

最慢的单波模块

正如您可能已经注意到的,wave模块可能会非常慢。请考虑以下代码:

代码语言:javascript
运行
复制
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)

对于如下所定义的波浪:

代码语言:javascript
运行
复制
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。根据项目描述,它的重点是阅读速度。

代码语言:javascript
运行
复制
import audiofile as af

signal, sampling_rate = af.read(audio.wav)

这给了我平均33毫秒的时间来读取上述文件。

最快的一个-矮胖的

如果我们决定跳过头(就像OP要求的那样),只追求速度,那么numpy是一个很好的选择:

代码语言:javascript
运行
复制
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 ),同时使代码更加可读性:

代码语言:javascript
运行
复制
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作为附件)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67453808

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档