@@ -24,7 +24,22 @@ There are three different kinds of audio sources that can be played using the
2424 my_effect = audio.SoundEffect(freq_start=400, freq_end=2500, duration=500)
2525 audio.play(my_effect)
2626
27- 3. `Audio Frames <#audioframe >`_, an instance or an iterable (like a list or
27+ 3. `Audio Recordings <#audiorecording-audiotrack-v2 >`_, an object that can
28+ be used to record audio from the microphone::
29+
30+ recording = audio.AudioRecording(duration=4000)
31+ microphone.record_into(recording)
32+ audio.play(recording)
33+
34+ 4. `Audio Tracks <#audiorecording-audiotrack-v2 >`_, a way to point to a portion
35+ of the data in an ``AudioRecording `` or a ``bytearray `` and/or modify it::
36+
37+ recording = audio.AudioRecording(duration=4000)
38+ microphone.record(recording)
39+ track = AudioTrack(recording)[1000:3000]
40+ audio.play(track)
41+
42+ 5. `Audio Frames <#audioframe >`_, an instance or an iterable (like a list or
2843 generator) of Audio Frames, which are lists of samples with values
2944 from 0 to 255::
3045
@@ -49,6 +64,10 @@ Functions
4964 be found in the `Built in sounds <#built-in-sounds-v2 >`_ section.
5065 - ``SoundEffect ``: A sound effect, or an iterable of sound effects,
5166 created via the :py:meth: `audio.SoundEffect ` class
67+ - ``AudioRecording ``: An instance of ``AudioRecording `` as described
68+ in the `AudioRecording <#audiorecording-audiotrack-v2 >`_ section
69+ - ``AudioTrack ``: An instance of ``AudioTrack `` as described in the
70+ `AudioTrack <#audiorecording-audiotrack-v2 >`_ section
5271 - ``AudioFrame ``: An instance or an iterable of ``AudioFrame ``
5372 instances as described in the
5473 `AudioFrame Technical Details <#technical-details >`_ section
@@ -226,47 +245,159 @@ Sound Effects Example
226245 :code: python
227246
228247
229- AudioFrame
230- ==========
248+ AudioRecording & AudioTrack ** V2 **
249+ ==================================
231250
232- .. py : class ::
233- AudioFrame(duration=-1, rate=7812)
251+ There are two classes that can contain (or point to) audio data
252+ and an associated sampling rate:
234253
235- An ``AudioFrame `` object is a list of samples, each of which is an unsigned
236- byte (whole number between 0 and 255).
254+ - ``AudioRecording `` contains its own buffer, it's initialised with a size
255+ defined in time, and it's the object type that ``microphone.record() ``
256+ returns.
257+ - ``AudioTrack `` does not hold its own buffer and instead points to a buffer
258+ externally created. This buffer could be an ``AudioRecording ``, or a basic
259+ type like a ``bytearray ``. It's similar to a
260+ `memoryview <https://docs.micropython.org/en/v1.9.3/pyboard/reference/speed_python.html#arrays >`_
261+ and it can be used to easily chop a portion of the audio data in the
262+ ``AudioRecording `` or to modify its contents.
237263
238- The number of samples in an AudioFrame will depend on the
239- ``rate `` (number of samples per second) and ``duration `` parameters.
240- The total number of samples will always be a round up multiple of 32.
264+ AudioRecording
265+ --------------
266+
267+ .. py :class ::
268+ AudioRecording(duration, rate=7812)
269+
270+ The ``AudioRecording `` object contains audio data and the sampling rate
271+ associated to it.
241272
242- On micro:bit V1 the constructor does not take any arguments,
243- and an AudioFrame instance is always 32 bytes .
273+ The size of the internal buffer will depend on the `` rate ``
274+ (number of samples per second) and `` duration `` parameters .
244275
245- :param duration: (** V2 **) Indicates how many milliseconds of audio this
276+ :param duration: Indicates how many milliseconds of audio this
246277 instance can store.
247- :param rate: (** V2 **) The sampling rate at which data will be stored
278+ :param rate: The sampling rate at which data will be stored
248279 via the microphone, or played via the ``audio.play() `` function.
249280
250281 .. py :function :: set_rate(sample_rate)
251282
252- (**V2 only **) Configure the sampling rate associated with the data
253- in the ``AudioFrame `` instance.
283+ Configure the sampling rate associated with the data in the
284+ ``AudioRecording `` instance.
285+
286+ :param sample_rate: The sample rate to set.
287+
288+ .. py :function :: get_rate()
289+
290+ Return the configured sampling rate for this
291+ ``AudioRecording `` instance.
292+
293+ :return: The configured sample rate.
294+
295+ .. py :function :: track(start_ms = 0 , end_ms = - 1 )
296+
297+ Create an `AudioTrack <#audio.AudioTrack >`_ instance from a portion of
298+ the data in this ``AudioRecording `` instance.
299+
300+ :param start_ms: Where to start of the track in milliseconds.
301+ :param end_ms: The end of the track in milliseconds.
302+ If the default value of ``-1 `` is provided it will end the track
303+ at the end of the AudioRecording.
304+
305+ When an AudioRecording is used to record data from the microphone,
306+ increasing the sampling rate increases the sound quality,
307+ but it also increases the amount of memory used.
308+
309+ During playback, increasing the sampling rate speeds up the sound
310+ and decreasing the sample rate slows it down.
311+
312+ AudioTrack
313+ ----------
314+
315+ An ``AudioTrack `` can be created from an ``AudioRecording `` or ``bytearray ``
316+ and individual bytes can be accessed and modified like elements in a list.
317+
318+ This class is useful to modify the audio data in an ``AudioRecording `` or
319+ to create precisely sized audio data buffers for sending and receiving them
320+ via communication protocols like radio or serial.
321+
322+ .. py :class ::
323+ AudioTrack(buffer, rate=7812)
324+
325+ The ``AudioTrack `` object points to the data provided by the input buffer,
326+ which can be an ``AudioRecording ``, or a buffer-like object like a
327+ ``bytearray ``.
328+ It also contains its own sampling rate, so multiple ``AudioTrack ``
329+ instances pointing to the same buffer can have different rates and won't
330+ affect the rate of the original buffer.
254331
255- For recording from the microphone, increasing the sampling rate
256- increases the sound quality, but reduces the length of audio it
257- can store.
258- During playback, increasing the sampling rate speeds up the sound
259- and decreasing it slows it down.
332+ :param buffer: The buffer containing the audio data.
333+ :param rate: The sampling rate at which data will be stored
334+ via the microphone, or played via the ``audio.play() `` function.
335+
336+ .. py :function :: set_rate(sample_rate)
337+
338+ Configure the sampling rate associated with the data in the
339+ ``AudioTrack `` instance.
260340
261341 :param sample_rate: The sample rate to set.
262342
263343 .. py :function :: get_rate()
264344
265- (** V2 only **) Return the configured sampling rate for this
266- ``AudioFrame `` instance.
345+ Return the configured sampling rate for this
346+ ``AudioTrack `` instance.
267347
268348 :return: The configured sample rate.
269349
350+ .. py :function :: copyfrom(other)
351+
352+ Overwrite the data in this ``AudioTrack `` with the data from another
353+ ``AudioTrack ``, ``AudioRecording `` or buffer-like object like
354+ a ``bytes `` or ``bytearray `` instance.
355+
356+ :param other: Buffer-like instance from which to copy the data.
357+
358+ Example
359+ -------
360+
361+ ::
362+
363+ from microbit import *
364+
365+ # An AudioRecording holds the audio data
366+ recording = audio.AudioRecording(duration=4000)
367+
368+ # AudioTracks point to a portion of the data in the AudioRecording
369+ # We can obtain the an AudioTrack from the AudioRecording.track() method
370+ first_half = recording.track(end_ms=2000)
371+ # Or we can create an AudioTrack from an AudioRecording and slice it
372+ full_track = audio.AudioTrack(recording)
373+ second_half = full_track[full_track.length() // 2:]
374+
375+ while True:
376+ if button_a.is_pressed():
377+ # We can record directly inside the AudioRecording
378+ microphone.record(recording)
379+ if button_b.is_pressed():
380+ audio.play(recording, wait=False)
381+ # The rate can be changed while playing
382+ first_half.set_rate(
383+ scale(accelerometer.get_x(), from_=(-1000, 1000), to=(3_000, 30_000))
384+ )
385+ if pin_logo.is_touched():
386+ # We can also play the AudioTrack pointing to the AudioRecording
387+ audio.play(first_half)
388+
389+
390+ AudioFrame
391+ ==========
392+
393+ .. py :class ::
394+ AudioFrame
395+
396+ An ``AudioFrame `` object is a list of 32 samples each of which is an unsigned byte
397+ (whole number between 0 and 255).
398+
399+ It takes just over 4 ms to play a single frame.
400+
270401 .. py :function :: copyfrom(other)
271402
272403 Overwrite the data in this ``AudioFrame `` with the data from another
@@ -281,21 +412,13 @@ Technical Details
281412 You don't need to understand this section to use the ``audio `` module.
282413 It is just here in case you wanted to know how it works.
283414
284- The ``audio.play() `` function can consume an instance or iterable
285- (sequence, like list or tuple, or generator) of ``AudioFrame `` instances,
286- The ``AudioFrame `` default playback rate is 7812 Hz, and can be configured
287- at any point with the ``AudioFrame.set_rate() `` method.
288- The ``AudioFrame.set_rate() `` also works while the ``AudioFrame `` is being
289- played, which will affect the playback speed.
290-
291- Each ``AudioFrame `` instance is 32 samples by default, but it can be
292- configured to a different size via constructor parameters.
293-
294- So, for example, playing 32 samples at 7812 Hz takes just over 4 milliseconds
415+ The ``audio `` module can consumes an iterable (sequence, like list or tuple, or
416+ generator) of ``AudioFrame `` instances, each 32 samples at 7812.5 Hz,
417+ which take just over 4 milliseconds to play each frame
295418(1/7812.5 * 32 = 0.004096 = 4096 microseconds).
296419
297- The function ``play() `` fully copies all data from each ``AudioFrame `` before
298- it calls ``next() `` for the next frame, so a sound source can use the same
420+ The function ``play `` fully copies all data from each ``AudioFrame `` before it
421+ calls ``next() `` for the next frame, so a sound source can use the same
299422``AudioFrame `` repeatedly.
300423
301424The ``audio `` module has an internal 64 sample buffer from which it reads
0 commit comments