将两个音频文件与python混合在一起

jam*_*mes 19 python

我有两个wav文件,我想混合在一起形成一个wav文件.它们都是相同的样本格式等...

一直在无休止地搜索谷歌.

我更喜欢在python中使用wave模块.

如何才能做到这一点?

Jia*_*aro 25

您可以使用pydub库(我在std lib中围绕python wave模块编写的一个光包装器)来完成它:

from pydub import AudioSegment

sound1 = AudioSegment.from_file("/path/to/my_sound.wav")
sound2 = AudioSegment.from_file("/path/to/another_sound.wav")

combined = sound1.overlay(sound2)

combined.export("/path/to/combined.wav", format='wav')
Run Code Online (Sandbox Code Playgroud)


Mar*_*ani 10

利布罗萨解决方案

import librosa
import IPython as ip

y1, sample_rate1 = librosa.load(audio1, mono=True)
y2, sample_rate2 = librosa.load(audio2, mono=True)

# MERGE
librosa.display.waveplot((y1+y2)/2, sr=int((sample_rate1+sample_rate2)/2))

# REPRODUCE
ip.display.Audio((y1+y2)/2, rate=int((sample_rate1+sample_rate2)/2))
Run Code Online (Sandbox Code Playgroud)


Jus*_*Jus 9

你们喜欢numpy,不是吗?下面是一个依赖于wave和 的解决方案numpy。添加两个文件“./file1.wav”和“./file2.wav”中的原始字节。在转换回 int-16 (不包括在内)之前np.clip应用它可能会很好。mix

import wave
import numpy as np
# load two files you'd like to mix
fnames =["./file1.wav", "./file2.wav"]
wavs = [wave.open(fn) for fn in fnames]
frames = [w.readframes(w.getnframes()) for w in wavs]
# here's efficient numpy conversion of the raw byte buffers
# '<i2' is a little-endian two-byte integer.
samples = [np.frombuffer(f, dtype='<i2') for f in frames]
samples = [samp.astype(np.float64) for samp in samples]
# mix as much as possible
n = min(map(len, samples))
mix = samples[0][:n] + samples[1][:n]
# Save the result
mix_wav = wave.open("./mix.wav", 'w')
mix_wav.setparams(wavs[0].getparams())
# before saving, we want to convert back to '<i2' bytes:
mix_wav.writeframes(mix.astype('<i2').tobytes())
mix_wav.close()
Run Code Online (Sandbox Code Playgroud)


Dav*_*eau 7

一个python解决方案,需要numpy和audiolab,但是快速而简单:

import numpy as np
from scikits.audiolab import wavread

data1, fs1, enc1 = wavread("file1.wav")
data2, fs2, enc2 = wavread("file2.wav")

assert fs1 == fs2
assert enc1 == enc2
result = 0.5 * data1 + 0.5 * data2
Run Code Online (Sandbox Code Playgroud)

如果采样率(fs*)或编码(enc*)不同,则可能需要一些音频处理(断言严格来说太强,因为wavread可以透明地处理某些情况).


Pon*_*dle 4

这很大程度上取决于它们的格式。以下是假设 2 字节宽、小尾数法样本的示例:

import wave

w1 = wave.open("/path/to/wav/1")
w2 = wave.open("/path/to/wav/2")

#get samples formatted as a string.
samples1 = w1.readframes(w1.getnframes())
samples2 = w2.readframes(w2.getnframes())

#takes every 2 bytes and groups them together as 1 sample. ("123456" -> ["12", "34", "56"])
samples1 = [samples1[i:i+2] for i in xrange(0, len(samples1), 2)]
samples2 = [samples2[i:i+2] for i in xrange(0, len(samples2), 2)]

#convert samples from strings to ints
def bin_to_int(bin):
    as_int = 0
    for char in bin[::-1]: #iterate over each char in reverse (because little-endian)
        #get the integer value of char and assign to the lowest byte of as_int, shifting the rest up
        as_int <<= 8
        as_int += ord(char) 
    return as_int

samples1 = [bin_to_int(s) for s in samples1] #['\x04\x08'] -> [0x0804]
samples2 = [bin_to_int(s) for s in samples2]

#average the samples:
samples_avg = [(s1+s2)/2 for (s1, s2) in zip(samples1, samples2)]
Run Code Online (Sandbox Code Playgroud)

现在剩下要做的就是转换samples_avg回二进制字符串并使用wave.writeframes. 这与我们刚刚所做的相反,所以应该不难理解。对于 int_to_bin 函数,您可能会使用该函数chr(code),该函数返回字符代码为code(与 ord 相反)的字符