Skip to content

Conversation

relic-se
Copy link

The idea of audio effect/mixer chaining was theorized in one of the first audio effects PRs, #9640 (comment), but never actually implemented.

The updates in this PR are relatively simple. Instead of returning None within play(...) methods of audio objects which allow both input and output (effects and mixer), it instead returns a reference to itself.

With this minor update, rather than building audio chains the old way:

effect.play(sample)
mixer.play(effect)
dac.play(mixer)

You can instead directly chain each source into its destination:

dac.play(mixer.play(effect.play(sample)))

Note: The only method that is missing this chaining ability is audiomixer.MixerVoice.play. I felt that it made sense to allow audiomixer.Mixer.play to support this but thought it would result in confusing implementation to support MixerVoice. (ie: dac.play(mixer.voice[0].play(sample)) vs dac.play(mixer.play(sample)).

Copy link
Collaborator

@dhalbert dhalbert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have seen this kind of chaining more with properties than function calls, but it's neat how they can be stacked.

I think it would be good to document that self is returned for all these cases, using :return: and :rtype:, and probably give an example of chaining for each case

@relic-se
Copy link
Author

I think it would be good to document that self is returned for all these cases, using :return: and :rtype:, and probably give an example of chaining for each case

I've got some basic documentation in there. If you have any suggestions on the language used, I'd be happy to update. Thank you for the review!

@dhalbert
Copy link
Collaborator

@todbot You use synthio a lot, and I do not. Would you have any comment? Thanks!

@todbot
Copy link

todbot commented Sep 17, 2025

@todbot You use synthio a lot, and I do not. Would you have any comment? Thanks!

Looks neat! I remember advocating for something similar with digitalio long time ago.

I didn't realize mixer.play(playable, voice=num) existed. Is that equivalent to mixer.voice[num].play(playable)?

My only concern (as w/ everything in the core modules now) is that the added feature will push out other modules on ports that are at the limit.

Copy link
Collaborator

@dhalbert dhalbert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@todbot I'm not worried about size - the code growth should be tiny or non-existent in this case.

@dhalbert dhalbert merged commit ed58ade into adafruit:main Sep 17, 2025
503 checks passed
@relic-se relic-se deleted the audio-chaining branch September 17, 2025 16:17
@relic-se
Copy link
Author

Thanks for the review, @dhalbert and @todbot ! This update will definitely tidy up a lot of audio examples.

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

Successfully merging this pull request may close these issues.

3 participants