@@ -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,163 @@ 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+ --------------
241266
242- On micro:bit V1 the constructor does not take any arguments,
243- and an AudioFrame instance is always 32 bytes.
267+ .. py :class ::
268+ AudioRecording(duration, rate=7812)
269+
270+ The ``AudioRecording `` object contains audio data and the sampling rate
271+ associated to it.
244272
245- :param duration: (**V2 **) Indicates how many milliseconds of audio this
273+ The size of the internal buffer will depend on the ``rate ``
274+ (number of samples per second) and ``duration `` parameters.
275+
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 :: copy()
296+
297+ :returns: a copy of the ``AudioRecording ``.
298+
299+ .. py :function :: track(start_ms = 0 , end_ms = - 1 )
300+
301+ Create an `AudioTrack <#audio.AudioTrack >`_ instance from a portion of
302+ the data in this ``AudioRecording `` instance.
303+
304+ :param start_ms: Where to start of the track in milliseconds.
305+ :param end_ms: The end of the track in milliseconds.
306+ If the default value of ``-1 `` is provided it will end the track
307+ at the end of the AudioRecording.
308+
309+ When an AudioRecording is used to record data from the microphone,
310+ increasing the sampling rate increases the sound quality,
311+ but it also increases the amount of memory used.
312+
313+ During playback, increasing the sampling rate speeds up the sound
314+ and decreasing the sample rate slows it down.
315+
316+ AudioTrack
317+ ----------
318+
319+ An ``AudioTrack `` can be created from an ``AudioRecording `` or ``bytearray ``
320+ and individual bytes can be accessed and modified like elements in a list.
321+
322+ This class is useful to modify the audio data in an ``AudioRecording `` or
323+ to create precisely sized audio data buffers for sending and receiving them
324+ via communication protocols like radio or serial.
325+
326+ .. py :class ::
327+ AudioTrack(buffer, rate=7812)
328+
329+ The ``AudioTrack `` object points to the data provided by the input buffer,
330+ which can be an ``AudioRecording ``, or a buffer-like object like a
331+ ``bytearray ``.
332+ It also contains its own sampling rate, so multiple ``AudioTrack ``
333+ instances pointing to the same buffer can have different rates and won't
334+ affect the rate of the original buffer.
335+
336+ :param buffer: The buffer containing the audio data.
337+ :param rate: The sampling rate at which data will be stored
338+ via the microphone, or played via the ``audio.play() `` function.
254339
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.
340+ .. py :function :: set_rate(sample_rate)
341+
342+ Configure the sampling rate associated with the data in the
343+ ``AudioTrack `` instance.
260344
261345 :param sample_rate: The sample rate to set.
262346
263347 .. py :function :: get_rate()
264348
265- (** V2 only **) Return the configured sampling rate for this
266- ``AudioFrame `` instance.
349+ Return the configured sampling rate for this
350+ ``AudioTrack `` instance.
267351
268352 :return: The configured sample rate.
269353
354+ .. py :function :: copyfrom(other)
355+
356+ Overwrite the data in this ``AudioTrack `` with the data from another
357+ ``AudioTrack ``, ``AudioRecording `` or buffer-like object like
358+ a ``bytes `` or ``bytearray `` instance.
359+
360+ :param other: Buffer-like instance from which to copy the data.
361+
362+ Example
363+ -------
364+
365+ ::
366+
367+ from microbit import *
368+
369+ # An AudioRecording holds the audio data
370+ recording = audio.AudioRecording(duration=4000)
371+
372+ # AudioTracks point to a portion of the data in the AudioRecording
373+ # We can obtain the an AudioTrack from the AudioRecording.track() method
374+ first_half = recording.track(end_ms=2000)
375+ # Or we can create an AudioTrack from an AudioRecording and slice it
376+ full_track = audio.AudioTrack(recording)
377+ second_half = full_track[full_track.length() // 2:]
378+
379+ while True:
380+ if button_a.is_pressed():
381+ # We can record directly inside the AudioRecording
382+ microphone.record(recording)
383+ if button_b.is_pressed():
384+ audio.play(recording, wait=False)
385+ # The rate can be changed while playing
386+ first_half.set_rate(
387+ scale(accelerometer.get_x(), from_=(-1000, 1000), to=(3_000, 30_000))
388+ )
389+ if pin_logo.is_touched():
390+ # We can also play the AudioTrack pointing to the AudioRecording
391+ audio.play(first_half)
392+
393+
394+ AudioFrame
395+ ==========
396+
397+ .. py :class ::
398+ AudioFrame
399+
400+ An ``AudioFrame `` object is a list of 32 samples each of which is an unsigned byte
401+ (whole number between 0 and 255).
402+
403+ It takes just over 4 ms to play a single frame.
404+
270405 .. py :function :: copyfrom(other)
271406
272407 Overwrite the data in this ``AudioFrame `` with the data from another
@@ -281,21 +416,13 @@ Technical Details
281416 You don't need to understand this section to use the ``audio `` module.
282417 It is just here in case you wanted to know how it works.
283418
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
419+ The ``audio `` module can consumes an iterable (sequence, like list or tuple, or
420+ generator) of ``AudioFrame `` instances, each 32 samples at 7812.5 Hz,
421+ which take just over 4 milliseconds to play each frame
295422(1/7812.5 * 32 = 0.004096 = 4096 microseconds).
296423
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
424+ The function ``play `` fully copies all data from each ``AudioFrame `` before it
425+ calls ``next() `` for the next frame, so a sound source can use the same
299426``AudioFrame `` repeatedly.
300427
301428The ``audio `` module has an internal 64 sample buffer from which it reads
0 commit comments