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

Add double buffering to RawSample #9421

Merged
merged 4 commits into from
Jul 22, 2024

Conversation

timchinowsky
Copy link

This PR contains part of the changes necessary to implement the processing of live sampled audio as described in #2676. Here audiocore.RawSample is changed so that the sample can present itself either as a full-length single-buffered object or as a double-buffered object comprised of two half-length buffers.

@tannewt tannewt self-requested a review July 10, 2024 16:21
Copy link
Member

@tannewt tannewt left a comment

Choose a reason for hiding this comment

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

One question. Thanks for the PR!

shared-bindings/audiocore/RawSample.c Outdated Show resolved Hide resolved
@timchinowsky
Copy link
Author

Revised RawSample will not loop unless played with loop=True, otherwise behavior is unchanged. Test code exercises this with an audiomixer with 3 voices. Here's how you run the test for all combinations of single/double buffer and loop/not loop:

>>> mix.play(single_buffer=True, loop=True)
(200, 1, 0)
(400, 0, 1)
(100, 1, 1)
>>> mix.play(single_buffer=False, loop=True)
(200, 1, 0)
(400, 0, 1)
(100, 1, 1)
>>> mix.play(single_buffer=True, loop=False)
(200, 1, 0)
(400, 0, 1)
(100, 1, 1)
>>> mix.play(single_buffer=False, loop=False)
(200, 1, 0)
(400, 0, 1)
(100, 1, 1)

Looking at the size and timing of the buffers pulled in by audiomixer, here's what it looks like looped single-buffered transfers:

single_0

The pattern repeats every 10000 us, as you'd expect for an 80 sample audiomixer playing at 8 kHz:

single_10000

With double buffered transfers, you see twice as many transfers that are half as big (and take half the time), which makes sense:

double_0

double_10000

For the examples above, the parameters are chosen such that the audiomixer buffer length is an integer multiple of each of the sample lengths, so the length of the transfers which fill up the buffer are exactly the same each time. For the general case, partial samples will be assembled into the buffer to make up the required number of samples. Here's a plot that shows that behavior. This run used the default buffer size of 128 samples and fills the buffer every 16000 us:

Screenshot from 2024-07-16 14-26-39

Copy link
Member

@tannewt tannewt left a comment

Choose a reason for hiding this comment

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

Great! Thank you!

@tannewt tannewt merged commit 612bf20 into adafruit:main Jul 22, 2024
436 checks passed
@jepler jepler mentioned this pull request Jul 26, 2024
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.

2 participants