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

Should microphone.record_into() have an additional duration and/or buffer_offset parameters? #197

Closed
microbit-carlos opened this issue Apr 12, 2024 · 2 comments
Labels
enhancement New feature or request
Milestone

Comments

@microbit-carlos
Copy link
Contributor

microbit-carlos commented Apr 12, 2024

duration parameter

Currently, if we want to record a couple of seconds into a larger AudioFrame the way to do it would be:

my_audio = audio.AudioFrame(duration=4000)
microphone.record_into(my_audio, wait=False)
sleep(2000)
microphone.stop()

This works, but this is likely not very time-accurate (specially since uBit.sleep() can round to the 4ms of the CODAL ticker), and there currently isn't a way to check how much audio ended up recorded (#196).

Providing a duration parameter, (record_into(buffer, duration, rate, wait)) that by default fills the buffer, could provide a more accurate way to record a fraction of the AudioFrame:

my_audio = audio.AudioFrame(duration=4000)
microphone.record_into(my_audio, duration=2000)

This also has the advantage of mirroring a bit more the record(duration, rate) function signature, so it's a more obvious way to achieve this than using the wait=False+stop().

But this is no enabling any new functionality or possibilities, it's a simplification and improvement of the current option, so this fall more into the "nice to have" basket.

buffer_offset parameter

As discussed in https://github.com/bbcmicrobit/micropython/pull/791/files#r1360487346 microphone.record_into() always starts recording from the beginning of the AudioFrame buffer. I agree that this is the right approach, as continuing playback from where it left off could be confusing as it's not obvious from the function name, or a behaviour shared by any of the other read_into()-like methods available. So if we wanted to be able to record multiple audio clips inside the same AudioFrame we would need to have an extra parameter to indicate a buffer offset to start recording.

However, this is not really needed to achieve this kind of functionality, as audio.play() can consume a list of AudioFrames to achieve the same.

So the change would be from something like this:

TOTAL_AUDIO = 4000
SAMPLE_SIZE = 500
audio_frames = []
for _ in range(0, TOTAL_AUDIO / SAMPLE_SIZE):
    audio_frames.append(microphone.record(duration=SAMPLE_SIZE))
audio.play(audio_frames)

To something like this:

SAMPLE_SIZE = 500
my_audio = audio.AudioFrame(duration=4000)
for i in range(0, len(my_audio), SAMPLE_SIZE):
    microphone.record_into(my_audio, duration=SAMPLE_SIZE, buffer_offset=i)
audio.play(my_audio)

So, in the end it is very similar. Some advantages are less fragmentation (specially if doing this continuously in the background), and slightly better memory consumption

In the case we'd want to add this parameter, having access to the internal marker (#196) would be quite useful as well:

microphone.record_into(my_audio, duration=SAMPLE_SIZE, buffer_offset=my_audio.get_position())

Similar to the duration parameter, this might be in the "nice to have" basket, but I do wonder if using reusing the same AudioFrame constantly, without all the allocations, might be more significant in long running programmes.

Also, the name is a bit long, any suggestions welcomed.

@microbit-carlos
Copy link
Contributor Author

Both of these proposal could be covered via:

@microbit-carlos
Copy link
Contributor Author

The wait=False + microphone.stop() method is good enough and the way to record to offsets would be using the feature described in:

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

No branches or pull requests

1 participant