Josef
Josef

Reputation: 147

PyAudio Play multiple sounds at once

How can I mix two sounds with PyAudio into one. I browsed all over internet but nobody answered this question. I was also thinking about using audiolab or swMixer, but they dont support Python 3.4... I was thinking about converting they byte string into numpy array, merging it with another, and converting back to by string. Is that possible?

wf1 = wave.open("YYY.wav", 'rb')
wf1 = wave.open("XXX.wav", 'rb')

p = pyaudio.PyAudio()

def callback(in_data, frame_count, time_info, status):
    data1 = wf1.readframes(frame_count)
    data2 = wf2.readframes(frame_count)

    #Here i need to mix these two byte strings together

    return (data, pyaudio.paContinue)

You are my last hope, thank you for any advance!

Upvotes: 4

Views: 5335

Answers (2)

Chris P
Chris P

Reputation: 2357

With base Josef's answer i post an updated version which checks if sound times are not the same.

def callback(in_data, frame_count, time_info, status):
    data1 = wf.readframes(frame_count)
    data2 = wf_2.readframes(frame_count)
    decodeddata1 = numpy.fromstring(data1, numpy.int16)
    decodeddata2 = numpy.fromstring(data2, numpy.int16)

    if(int(decodeddata1.size)==0):
        newdata = (decodeddata2).astype(numpy.int16)
        return (newdata.tostring(), pyaudio.paContinue)     

    if(int(decodeddata2.size)==0):
        newdata = (decodeddata1).astype(numpy.int16)
        return (newdata.tostring(), pyaudio.paContinue)     

    if(int(decodeddata1.size)>int(decodeddata2.size)):
        rest = int(decodeddata1.size)-int(decodeddata2.size)
        for i in range(1,rest+1):
            decodeddata2 = numpy.append(decodeddata2,0)

    if(int(decodeddata1.size)<int(decodeddata2.size)):
        rest = int(decodeddata2.size)-int(decodeddata1.size)
        for i in range(1,rest+1):
            decodeddata1 = numpy.append(decodeddata1,0)


    newdata = (decodeddata1 + decodeddata2).astype(numpy.int16)
    return (newdata.tostring(), pyaudio.paContinue)

Upvotes: 1

Josef
Josef

Reputation: 147

I found the solution by myself and it was pretty simple. So I will post my code here to help others:

wf1 = wave.open("YYY.wav", 'rb')
wf1 = wave.open("XXX.wav", 'rb')

def callback(in_data, frame_count, time_info, status):
    data1 = wf.readframes(frame_count)
    data2 = wf1.readframes(frame_count)
    decodeddata1 = numpy.fromstring(data1, numpy.int16)
    decodeddata2 = numpy.fromstring(data2, numpy.int16)
    newdata = (decodeddata1 * 0.5 + decodeddata2* 0.5).astype(numpy.int16)
    return (result.tostring(), pyaudio.paContinue)

Upvotes: 6

Related Questions