Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancement Request: Integrate Playback Status Check into Simple play/stop API in sounddevice #507

Open
elias-jhsph opened this issue Dec 1, 2023 · 4 comments

Comments

@elias-jhsph
Copy link

Summary

This issue proposes integrating a feature for checking the playback status into the simpler play/stop API of the sounddevice module. While the module does offer more robust methods for handling audio playback, having this functionality readily available in the simpler API would greatly enhance usability for basic use cases.

Background

Currently, in my application, I use the sounddevice module's simple API for playing audio files. However, to check if the playback has finished, I have to resort to accessing a private member (_last_callback), as shown below:

import sounddevice as sd
import soundfile as sf

# ... middle of function doing other things
for loop in range(loops):
    data, fs = sf.read(file_path)
    sd.play(data, fs)
    while not sd._last_callback.event.is_set():
        if stop_event.is_set() or (added_stop_event and added_stop_event.is_set()):
            sd.stop()
            break
        if added_stop_event:
            added_stop_event.wait(timeout=.1)
        else:
            stop_event.wait(timeout=.1)

Recognizing the More Robust API

I am aware that sounddevice offers a more robust API that could potentially handle these scenarios more effectively. However, for simpler applications or for users who are not deeply versed in audio programming, the complexity of the robust API can be a barrier.

Proposal

I propose enhancing the simpler play/stop API by adding a method or property to check the playback status. This could be a method like is_playing() or a property like playback_status. This enhancement would not only make the code more readable and maintainable but also provide a more accessible way for users to handle basic audio playback tasks.

Example of Proposed Solution

With the proposed enhancement, the implementation would look like this:

import sounddevice as sd
import soundfile as sf

# ... middle of function doing other things
for loop in range(loops):
    data, fs = sf.read(file_path)
    sd.play(data, fs)
    while sd.is_playing():  # Proposed method
        if stop_event.is_set() or (added_stop_event and added_stop_event.is_set()):
            sd.stop()
            break
        if added_stop_event:
            added_stop_event.wait(timeout=.1)
        else:
            stop_event.wait(timeout=.1)

Conclusion

Integrating a playback status check into the simple play/stop API would not only cater to users seeking simplicity but also make the sounddevice module more versatile and accessible to a broader range of users, from beginners to advanced programmers.

@mgeier
Copy link
Member

mgeier commented Dec 1, 2023

What about this:

while sd.get_stream().active:
    # ...

See #69 (comment) and #70.

@elias-jhsph
Copy link
Author

That's much better than what I have currently, and maybe I'm off base... But I do think since there is a play, wait, and stop it really feels like it's intuitive to have some way to wait for a short time (maybe a timeout kwarg for wait to mirror threads approach). It just feels like this level of the api is so close to a full set.

If that is the best approach maybe it should be in an example, reason being that people that want that high level use probably need the help the most with that, though it has big readability upsides for simple uses even for more advanced developers.

@mgeier
Copy link
Member

mgeier commented Dec 2, 2023

If that is the best approach

I think it is the best approach for what you ask for in the title of this issue and in your proposal above.

However, it's not the best approach for what you are asking now:

it really feels like it's intuitive to have some way to wait for a short time (maybe a timeout kwarg for wait to mirror threads approach).

I agree, a timeout argument would be a nice addition to sd.wait().

Do you want to make a PR for this?

@elias-jhsph
Copy link
Author

Would love to!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants