Skip to content

Commit

Permalink
docs: Add initial proposal for recording & playback API.
Browse files Browse the repository at this point in the history
  • Loading branch information
microbit-carlos committed May 15, 2023
1 parent 1c3fc31 commit e635d92
Show file tree
Hide file tree
Showing 2 changed files with 151 additions and 9 deletions.
54 changes: 51 additions & 3 deletions docs/audio.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,25 @@ a speaker to pin 0 and GND on the edge connector to hear the sounds.
The ``audio`` module can be imported as ``import audio`` or accessed via
the ``microbit`` module as ``microbit.audio``.

There are three different kinds of audio sources that can be played using the
There are four different kinds of audio sources that can be played using the
:py:meth:`audio.play` function:

1. `Built in sounds <#built-in-sounds-v2>`_ (**V2**),
e.g. ``audio.play(Sound.HAPPY)``

2. `Sound Effects <#sound-effects-v2>`_ (**V2**), a way to create custom sounds
by configuring its parameters::

my_effect = audio.SoundEffect(freq_start=400, freq_end=2500, duration=500)
audio.play(my_effect)

3. `Audio Frames <#audioframe>`_, an iterable (like a list or a generator)
3. `AudioBuffer <#audiobuffer>`_ (**V2**), a generic buffer for audio that can
be used to record sound from the micro:bit V2 built-in microphone::

my_audio_buffer = microphone.record()
audio.play(my_audio_buffer)

4. `Audio Frames <#audioframe>`_, an iterable (like a list or a generator)
of Audio Frames, which are lists of 32 samples with values from 0 to 255::

square_wave = audio.AudioFrame()
Expand All @@ -40,13 +47,16 @@ Functions
Play the audio source to completion.

:param source: There are three types of data that can be used as a source:
:param source: There are four types of data that can be used as a source:

- ``Sound``: The ``microbit`` module contains a list of
built-in sounds, e.g. ``audio.play(Sound.TWINKLE)``. A full list can
be found in the `Built in sounds <#built-in-sounds-v2>`_ section.
- ``SoundEffect``: A sound effect, or an iterable of sound effects,
created via the :py:meth:`audio.SoundEffect` class
- ``AudioBuffer``: An audio buffer, or an iterable of audio buffers,
created via the :py:meth:`audio.AudioBuffer` class or
:doc:`microphone.record() </microphone/recording>` function
- ``AudioFrame``: An iterable of ``AudioFrame`` instances as described
in the `AudioFrame Technical Details <#id2>`_ section

Expand Down Expand Up @@ -215,6 +225,44 @@ Sound Effects Example
.. include:: ../examples/soundeffects.py
:code: python


Audio Buffer **V2**
===================

.. py:class::
AudioBuffer(duration=3000, rate=11000)

Create a buffer to contain audio data and its sampling rate.

The sampling rate is used by the ``microphone.record_into()`` and
``audio.play()`` functions to configure the recording and playback rates.
This value can be changed as an attribute to increase or decrease the
recording quality or the playback speed.

:param duration: Indicates in milliseconds, how much sound data the buffer
can contained at the configured ``data_rate``.
:param rate: Sampling rate of for the data in the buffer. This value is
used for recording and playback, and can be edited as an attribute.

.. py:function:: copy()
:returns: A copy of the Audio Buffer.

.. py:attribute:: rate
The sampling rate for the data inside the buffer.
TODO: Indicate range of valid values here.

Audio Buffer Example
--------------------

::

my_buffer = audio.AudioBuffer(duration=5000)
microphone.record_into(my_buffer)
audio.play(my_buffer)


AudioFrame
==========

Expand Down
106 changes: 100 additions & 6 deletions docs/microphone.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ Microphone **V2**
.. py:module:: microbit.microphone
This object lets you access the built-in microphone available on the
micro:bit **V2**. It can be used to respond to sound. The microphone input
is located on the front of the board alongside a microphone activity LED,
which is lit when the microphone is in use.
micro:bit **V2**. It can be used to record and respond to sound.
The microphone input is located on the front of the board alongside a
microphone activity LED, which is lit when the microphone is in use.

.. image:: microphone.png
:width: 300px
Expand All @@ -28,6 +28,25 @@ accessible via variables in ``microbit.SoundEvent``:
- ``microbit.SoundEvent.LOUD``: Represents the transition of sound events,
from ``quiet`` to ``loud`` like clapping or shouting.

Recording
=========

TODO:
* Describe the feature.
* Indicate how the sampling rate relates to recording quality.
* Indicate how changing the sampling rate on the fly affects playback speed.
* What happens if the user changes the sampling rate while recording?

::

from microbit import *

while True:
if button_a.is_pressed():
my_recording = microphone.record(duration=5000)
audio.play(my_recording)
sleep(200)

Functions
=========

Expand Down Expand Up @@ -70,11 +89,47 @@ Functions
* **return**: a representation of the sound pressure level in the range 0 to
255.

.. py:function:: record(duration=3000, rate=11000, wait=True)
Record sound for the amount of time indicated by ``duration`` at the
sampling rate indicated by ``rate``.

The amount of memory consumed is directly related to the length of the
recording and the sampling rate. The higher these values, the more memory
it will use.
If there isn't enough memory available a ``MemoryError`` will be raised.

:param duration: How long to record in milliseconds.
:param rate: Number of samples per second.
:returns: An ``AudioBuffer``, configured at the provided ``duration``
and ``rate``, with the sound data.

.. py:function:: record_into(buffer, wait=True)
Description.

:param buffer: An ``AudioBuffer`` to record the microphone sound.

.. py:function:: is_recording()
Example
=======
:returns: ``True`` if the microphone is currently recording sound, or
``False`` otherwise.

An example that runs through some of the functions of the microphone API::
.. py:function:: stop_recording()
Stops an on-going recording.

.. py:function:: set_sensitivity(gain)
TODO: Decide if we want to accept any value or create "3 levels".

:param gain: Description.

Examples
========

An example that runs through some of the functions of the microphone
Sound Events API::

# Basic test for microphone. This test should update the display when
# Button A is pressed and a loud or quiet sound *is* heard, printing the
Expand Down Expand Up @@ -122,3 +177,42 @@ An example that runs through some of the functions of the microphone API::
display.clear()
print(sound)
sleep(500)


An example of recording and playback with an animation::

from microbit import *

talk_open = Image(
"09090:"
"00000:"
"09990:"
"90009:"
"09990"
)
talk_closed = Image(
"09090:"
"00000:"
"00000:"
"99999:"
"00000"
)

my_recording = audio.AudioBuffer(duration=5000, rate=5500)

while True:
if button_a.is_pressed():
my_recording.rate = 5500
microphone.record_into(my_recording, wait=False)
display.show([talk_open, talk_closed], loop=True, wait=False, delay=150)
while button_a.is_pressed():
sleep(50)
display.show(mouth_open, loop=False) # workaround issue #150
display.clear()
if button_b.is_pressed():
audio.play(my_recording, wait=False)
while audio.is_playing():
x = accelerometer.get_x()
my_recording.rate = scale(x, (-1000, 1000), (2250, 11000))
sleep(50)
sleep(100)

0 comments on commit e635d92

Please sign in to comment.