У меня есть два wav файла, которые я хочу объединить вместе, чтобы сформировать один wav файл. Они имеют одинаковый формат и т.д....
Долгое время искал google.
Я бы предпочел сделать это, используя волновой модуль в python.
Как это можно сделать?
У меня есть два wav файла, которые я хочу объединить вместе, чтобы сформировать один wav файл. Они имеют одинаковый формат и т.д....
Долгое время искал google.
Я бы предпочел сделать это, используя волновой модуль в python.
Как это можно сделать?
Вы можете использовать библиотеку pydub (легкую обертку, которую я написал вокруг модуля волны python в std lib), чтобы сделать это довольно просто:
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')
Решение python, которое требует как numpy, так и аудиолаба, но быстро и просто:
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
Если частота дискретизации (fs *) или кодировка (enc *) различны, вам может потребоваться некоторая обработка звука (утверждение строго говорит слишком сильно, поскольку wavread может обрабатывать некоторые случаи прозрачно).
это очень зависит от формата, в котором они находятся. Здесь пример того, как это сделать, предполагая 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)]
И теперь все, что осталось сделать, это преобразовать samples_avg
обратно в двоичную строку и записать ее в файл с помощью wave.writeframes
. Это просто обратное тому, что мы только что делали, поэтому не должно быть слишком сложно понять. Для вашей функции int_to_bin вы, вероятно, сможете использовать функцию chr(code)
, которая возвращает символ с кодом символа code
(напротив ord)
Вам, ребята, нравится 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 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()
Попробуйте API-интерфейс Remix Echo Nest:
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)
Если он жалуется на кодеки, проверьте https://superuser.com/questions/196857/how-to-install-libmp3lame-for-ffmpeg.
ЛИБРОСА РЕШЕНИЕ
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))