spatialaudio / python-sounddevice

:sound: Play and Record Sound with Python :snake:
https://python-sounddevice.readthedocs.io/
MIT License
980 stars 145 forks source link

Does sd.wait() block all other threads? #535

Closed ShawnHymel closed 1 month ago

ShawnHymel commented 1 month ago

I'm working on a multithreaded application. One thread puts wav binaries into a queue, and my playback thread plays them:

def start_sound_thread(sound_q, sound_semaphore):
    """
    Wait for sound binary in queue, then play it through the speaker.
    """

    # Thread main loop
    while True:

        # Get message from queue
        while not sound_q.empty():
            wav = sound_q.get()

            # Notify main thread that we're done
            if wav is None:
                sound_semaphore.release()
                continue

            if DEBUG:
                print("Starting sound play")

            # Play the sound
            sd.play(wav, samplerate=AUDIO_OUTPUT_SAMPLE_RATE, device=AUDIO_OUTPUT_INDEX)
            sd.wait()

            if DEBUG:
                print("Done sound play")

        # Let the thread rest
        time.sleep(0.1)

Does sd.wait() hold onto the global interpreter lock (i.e. preventing other threads from running), or does it use a sleep call to let other threads run? If the former, is there a way to make this thread play nicely with others? For example, I would love to have something like:

            # Play the sound
            sd.play(wav, samplerate=AUDIO_OUTPUT_SAMPLE_RATE, device=AUDIO_OUTPUT_INDEX)
            if not sd.is_playing():
                time.sleep(0.1)
ShawnHymel commented 1 month ago

A little more digging, and I would have answered my own question. It looks like sd.wait() is based on Event.wait(), which only blocks the current thread (allowing others to run as needed).