I'm trying to open a stereo stream and convert it to mono, using the wave module in python. So far I was able to write a single (left or right) channel from a 16bit stereo little endian file:
LEFT, RIGHT = 0, 1
def mono_single(cont, chan=LEFT):
a = iter(cont)
mono_cont = ''
if chan:
a.next(); a.next()
while True:
try:
mono_cont += a.next() + a.next()
a.next(); a.next()
except StopIteration:
return mono_cont
stereo = wave.open('stereofile.wav', 'rb')
mono = wave.open('monofile.wav', 'wb')
mono.setparams(stereo.getparams())
mono.setnchannels(1)
mono.writeframes(mono_single(stereo.readframes(stereo.getnframes())))
mono.close()
This works as expected. The problem comes when I try to downmix the two stereo channels to a single mono channel. I thought that a simple average between left and right would have been enough, and this is what I tried so far:
def mono_mix(cont):
a = iter(cont)
mono_cont = ''
while True:
try:
left = ord(a.next()) + (ord(a.next()) << 8)
right = ord(a.next()) + (ord(a.next()) << 8)
value = (left + right) / 2
mono_cont += chr(value & 255) + chr(value >> 8)
except StopIteration:
return mono_cont
stereo = wave.open('stereofile.wav', 'rb')
mono = wave.open('monofile.wav', 'wb')
mono.setparams(stereo.getparams())
mono.setnchannels(1)
mono.writeframes(mono_mix(stereo.readframes(stereo.getnframes())))
mono.close()
What I get from this is a "crackled" version of the source. I tried different combinations (I might have misunderstood the whole endianness thing), but with no luck so far.