用python将两个音频文件混合在一起
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4039158/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Mixing two audio files together with python
提问by james
I have two wav files that I want to mix together to form one wav file. They are both the same samples format etc...
我有两个 wav 文件,我想将它们混合在一起形成一个 wav 文件。它们都是相同的样本格式等...
Been searching google endlessly.
一直在无休止地搜索谷歌。
I would prefer to do it using the wave module in python.
我更愿意使用 python 中的 wave 模块来完成。
How can this be done?
如何才能做到这一点?
回答by Ponkadoodle
this is very dependent of the format these are in. Here's an example of how to do it assuming 2 byte wide, little-endian samples:
这非常依赖于它们所在的格式。下面是一个示例,说明如何假设 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)]
And now all that's left to do is convert samples_avgback to a binary string and write that to a file using wave.writeframes. That's just the inverse of what we just did, so it shouldn't be too hard to figure out. For your int_to_bin function, you'll probably what to make use of the function chr(code), which returns the character with the character code of code(opposite of ord)
现在剩下要做的就是转换samples_avg回二进制字符串并使用wave.writeframes. 这与我们刚刚所做的相反,所以应该不难弄清楚。对于您的 int_to_bin 函数,您可能会使用该函数chr(code),该函数返回字符代码为code(与 ord 相对)的字符
回答by David Cournapeau
A python solution which requires both numpy and audiolab, but is fast and simple:
一个 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
If sampling rate (fs*) or encoding (enc*) are different, you may need some audio processing (the assert are strictly speaking too strong, as wavread can handle some cases transparantly).
如果采样率 (fs*) 或编码 (enc*) 不同,则可能需要进行一些音频处理(断言严格来说太强了,因为 wavread 可以透明地处理某些情况)。
回答by TTT
Try the Echo Nest Remix API:
试试 Echo Nest Remix API:
from echonest import audio
from util import *
def mixSound(fname1,fname2,f_out_name):
f1 = audio.AudioData(fnem1)
f2 = audio.AudioData(fnem2)
f_out = audio.mix(f1,f2)
f_out.encode(foutnem, True)
If it complains about codecs, check https://superuser.com/questions/196857/how-to-install-libmp3lame-for-ffmpeg.
如果它抱怨编解码器,请检查https://superuser.com/questions/196857/how-to-install-libmp3lame-for-ffmpeg。
回答by Jiaaro
You can use the pydublibrary (a light wrapper I wrote around the python wave module in the std lib) to do it pretty simply:
您可以使用pydub库(我在 std 库中围绕 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')
回答by Jus
You guys like numpy, no? Below is a solution that depends on waveand numpy. Raw bytes in two files './file1.wav' and './file2.wav' are added. It's probably good to apply np.clipto mixbefore converting back to int-16 (not included).
你们喜欢numpy,不是吗?下面是一个依赖于wave和的解决方案numpy。添加了两个文件“./file1.wav”和“./file2.wav”中的原始字节。这可能是很好的适用np.clip于mix转换回INT-16之前(不包括在内)。
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()
回答by Marco Cerliani
LIBROSA SOLUTION
利布萨解决方案
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))

