Mixing/Overlaying Python 中的 wav 音频文件
Mixing/Overlaying wav audio files in Python
我一直在寻找仅使用 wave 库的 overlaying/mixing 两个 WAV 音频文件的解决方案。
我找到了以下解决方案:Mixing two audio files together with python
其中一个答案提供了以下代码:
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)]
代码在 Python 2 中编写,ord() 在 Python 3 中贬值,因此代码看起来像这样删除了 ord() 并在 samples_avg 处加倍 //避免创建浮动
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 range(0, len(samples1), 2)]
samples2 = [samples2[i:i+2] for i in range(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 += 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 恢复为二进制字符串。这是我遇到麻烦的地方。我已经尝试使用以下代码
将以下代码添加到 bin(), chr()
samples_avg = [ chr(s) for s in samples_avg]
samples_avg = [ bin(s) + "'" for s in samples_avg]
而且我已经尝试过一百万种其他解决方案,但我太尴尬了 post 而且都失败了。
谁能帮忙完成这段代码?我认为在社区中发布这将是一个非常有用的代码,因为它只依赖于 wave 库并且可以在虚拟环境中使用。
我是 Python 的新手,也是音频处理的新手,所以对于任何愚蠢的问题和错误,我深表歉意。
只是为了澄清我所说的 mixing/overflow 的意思。如果我有两个长度为 4 秒的音频文件,我想将它们混合在一起成为一个长度为 4 秒的音频文件,同时播放两个音频文件。
因此,在经过一些尝试后,出现了一个错误并得到了@Ponkadoodle 的帮助,我成功了。它适用于我在同一台计算机上使用 quicktime 和在线 wav 转换器完成的两段录音。如果我使用来自互联网的 wav 文件,最后的样本听起来真的很糟糕,我不知道这是否是由于频率等原因造成的。
这是最终代码
import wave
import array
w1 = wave.open("path/to/file/audiofile1.wav")
w2 = wave.open("path/to/file/audiofile2.wav")
#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 range(0, len(samples1), 2)]
samples2 = [samples2[i:i+2] for i in range(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 += 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) for (s1, s2) in zip(samples1, samples2)]
samples_array = array.array('i')
samples_array.fromlist(samples_avg)
wave_out = wave.open ("out.wav", "wb")
wave_out.setnchannels(1)
wave_out.setsampwidth(2)
wave_out.setframerate(w1.getframerate()*4)
wave_out.writeframes(samples_array)
我仍然对 setframerate() 有疑问。我将它乘以 4 并且成功了,同样这可能取决于您原始录音的 frequency/framerate 等。
wave_out.setframerate(w1.getframerate()*4)
我一直在寻找仅使用 wave 库的 overlaying/mixing 两个 WAV 音频文件的解决方案。
我找到了以下解决方案:Mixing two audio files together with python
其中一个答案提供了以下代码:
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)]
代码在 Python 2 中编写,ord() 在 Python 3 中贬值,因此代码看起来像这样删除了 ord() 并在 samples_avg 处加倍 //避免创建浮动
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 range(0, len(samples1), 2)]
samples2 = [samples2[i:i+2] for i in range(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 += 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 恢复为二进制字符串。这是我遇到麻烦的地方。我已经尝试使用以下代码
将以下代码添加到 bin(), chr()samples_avg = [ chr(s) for s in samples_avg]
samples_avg = [ bin(s) + "'" for s in samples_avg]
而且我已经尝试过一百万种其他解决方案,但我太尴尬了 post 而且都失败了。
谁能帮忙完成这段代码?我认为在社区中发布这将是一个非常有用的代码,因为它只依赖于 wave 库并且可以在虚拟环境中使用。
我是 Python 的新手,也是音频处理的新手,所以对于任何愚蠢的问题和错误,我深表歉意。
只是为了澄清我所说的 mixing/overflow 的意思。如果我有两个长度为 4 秒的音频文件,我想将它们混合在一起成为一个长度为 4 秒的音频文件,同时播放两个音频文件。
因此,在经过一些尝试后,出现了一个错误并得到了@Ponkadoodle 的帮助,我成功了。它适用于我在同一台计算机上使用 quicktime 和在线 wav 转换器完成的两段录音。如果我使用来自互联网的 wav 文件,最后的样本听起来真的很糟糕,我不知道这是否是由于频率等原因造成的。
这是最终代码
import wave
import array
w1 = wave.open("path/to/file/audiofile1.wav")
w2 = wave.open("path/to/file/audiofile2.wav")
#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 range(0, len(samples1), 2)]
samples2 = [samples2[i:i+2] for i in range(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 += 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) for (s1, s2) in zip(samples1, samples2)]
samples_array = array.array('i')
samples_array.fromlist(samples_avg)
wave_out = wave.open ("out.wav", "wb")
wave_out.setnchannels(1)
wave_out.setsampwidth(2)
wave_out.setframerate(w1.getframerate()*4)
wave_out.writeframes(samples_array)
我仍然对 setframerate() 有疑问。我将它乘以 4 并且成功了,同样这可能取决于您原始录音的 frequency/framerate 等。
wave_out.setframerate(w1.getframerate()*4)