在Python中混合/叠加wav音频文件

2024-09-29 19:27:52 发布

您现在位置:Python中文网/ 问答频道 /正文

我一直在寻找一个解决方案,覆盖/混合两个WAV音频文件在一起只使用wave库。在

我找到了以下解决方案: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)]

代码是用python2编写的,ord()在python3中是折旧的,所以代码看起来像这样,去掉ord()并在samples_avg处加倍//以避免创建浮点

^{pr2}$

代码只是部分的。缺少的是将samples_avg还原为二进制字符串。这就是我遇到麻烦的地方。我用下面的代码尝试了bin(),chr()的以下代码

samples_avg = [ chr(s) for s in samples_avg]

samples_avg = [ bin(s) + "'" for s in samples_avg]

我也尝试过上百万个其他的解决方案,但都失败了。在

有人能帮忙完成这段代码吗?我认为这是一个非常有用的代码,因为它只依赖于wave库,并且可以在虚拟环境中使用。在

我对Python比较陌生,对音频处理也完全陌生,所以对于任何愚蠢的问题和错误,我深表歉意。在

只是为了澄清我所说的混合/溢出是什么意思。如果我有两个音频文件,每个文件的长度为4秒,我想把它们混合到一个长度为4秒的单个音频文件中,两个音频文件同时播放。在


Tags: theto代码inforbinaswave
1条回答
网友
1楼 · 发布于 2024-09-29 19:27:52

经过一段时间的尝试,一个错误和@ponkadodle的帮助我成功了。我在同一台电脑上用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就行了,这可能取决于你原始录音的频率/帧率等。在

^{pr2}$

相关问题 更多 >

    热门问题