0

I'm looking to make a loop system (inspired by Marc Rebillet, check him out) and am struggling with getting 2 sounds to play over themselves.

I've started out using sounddevice, as it's the first audio module that I found, but I'm not sure if there's a different once that would work better.

import time

def record(duration): # records a few seconds of audio
    print('recording in:')
    print('3')
    time.sleep(1)
    print('2')
    time.sleep(1)
    print('1')
    time.sleep(1)
    print('recording')
    record = sd.rec(int(duration * fs), samplerate=48000, channels=2)
    sd.wait()
    print('done\n\n')
    return record

duration = 3.5  # seconds

recordOne = record(duration)
recordTwo = record(duration)

while True: # repeats both pieces of audio
    sd.play(recordOne, fs)
    sd.play(recordTwo, fs)
    sd.wait()

This code ended up only playing the recordTwo, and doesn't layer them over eachother. Again, I'd like to be able to play multiple sounds at the same time. Thank you for any help!

jon_groth34
  • 43
  • 1
  • 2
  • 6
  • 1
    Possible duplicate of [Is it possible to play two notes at once with pyaudio?](https://stackoverflow.com/questions/23001846/is-it-possible-to-play-two-notes-at-once-with-pyaudio) –  Aug 25 '19 at 05:04
  • 1
    `play()` and `rec()` are convenience functions for playing single NumPy arrays, for example in an interactive Python session. If you `play()` a second time, the first one is stopped. That's by design. You should create a `sd.Stream` and implement a callback function that does the recording and playback logic. You should have a look at the examples. – Matthias Aug 26 '19 at 08:28

1 Answers1

0

Have you tried a multi-thread solution?

import time
import threading


def record(duration): # records a few seconds of audio
    print('recording in:')

    for t in range(3, 0, -1):
        print(t)
        time.sleep(1)

    print('recording')
    print("mock record process...")
    start = time.time()
    time.sleep(10)
    print(f'done, {time.time() - start} seconds total.\n\n')
    return record


duration = 3.5  # seconds
recordOne = record(duration)
recordTwo = record(duration)


def play(record_piece):
    print("paly the sound")
    time.sleep(duration)


while True: # repeats both pieces of audio
    t1 = threading.Thread(target=play, args=(recordOne,))
    t2 = threading.Thread(target=play, args=(recordTwo,))
    t1.start()
    t2.start()
    t1.join()
    t2.join()

or you can try to find some library that can combine the two audio tracks before you play them.

I read the doc of sounddevice, it provides a playback method, have you tried it?

playback

enter image description here

  • Did you try this solution yourself? The `sd.play()` method was already used in the code of the OP, and it doesn't seem to work. Only the second audio is played. I don't see why calling the (non-blocking) methods from two different threads would help. I cannot find any hard evidence in the documentation, but I assume the PortAudio library does not do any software mixing, but just updates the raw audio buffer. You'll probably have to do the mixing yourself, as answered in an [earlier question](https://stackoverflow.com/questions/23001846/is-it-possible-to-play-two-notes-at-once-with-pyaudio). – wovano Aug 26 '19 at 05:04
  • @wovano Actually, I'm not... I failed to install the PortAudio on my wsl environment. I'll be back to check this later on my windows platform. You shall be a good tutor :) thanks for what u point out! – Xu_shan_shan Aug 26 '19 at 12:19