python - 在Python中混合/叠加WAV音频文件

标签 python audio wav wave mixing

我一直在寻找一种仅使用wave库将两个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]

而且我尝试了100万种其他解决方案,这些解决方案我都太尴尬了,以致于都失败了。

谁能帮忙完成这段代码?我认为在社区中使用这将是一个非常有用的代码,因为它仅取决于wave库并且可以在虚拟环境中使用。

我是Python的新手,还是音频处理的新手,所以对于任何愚蠢的问题和错误我深表歉意。

只是为了澄清我的意思是混合/溢出。如果我有两个长度为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即可正常工作,这又可能取决于原始录音的频率/帧率等。
wave_out.setframerate(w1.getframerate()*4) 

关于python - 在Python中混合/叠加WAV音频文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51320665/

相关文章:

python - Pymongo GridFS 输入类型/属性错误

python - docker 中的 Nginx、fastapi 和 streamlit - 反向代理不适用于 streamlit

php - 进行实时、可扩展的音频处理的最佳策略?

Android - 同时将两个或多个 WAV 文件合并(合并)为一个(混合)

python - 为什么用美汤解析这个标签是空的?

python - 在 CentOS 与 python 2.6 上针对 information_schema 执行 "SELECT"语句时,psycopg2 挂起

android - 在Android上将FloatArray音频缓冲区保存到WAV文件

php - 是否可以在PHP中将WAV文件转换为AIFF,反之亦然?

java - SoundPool 只停止一次

audio - HTML5 <audio> Safari 直播 vs 不直播