Skip to content

Commit 0920284

Browse files
docs: Add initial proposal for recording & playback API.
1 parent 7a4cfb5 commit 0920284

File tree

2 files changed

+180
-9
lines changed

2 files changed

+180
-9
lines changed

docs/audio.rst

Lines changed: 68 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,25 @@ a speaker to pin 0 and GND on the edge connector to hear the sounds.
1212
The ``audio`` module can be imported as ``import audio`` or accessed via
1313
the ``microbit`` module as ``microbit.audio``.
1414

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

1818
1. `Built in sounds <#built-in-sounds-v2>`_ (**V2**),
1919
e.g. ``audio.play(Sound.HAPPY)``
20+
2021
2. `Sound Effects <#sound-effects-v2>`_ (**V2**), a way to create custom sounds
2122
by configuring its parameters::
2223

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

26-
3. `Audio Frames <#audioframe>`_, an iterable (like a list or a generator)
27+
3. `AudioBuffer <#audiobuffer>`_ (**V2**), a generic buffer for audio that can
28+
be used to record sound from the micro:bit V2 built-in microphone::
29+
30+
my_audio_buffer = microphone.record()
31+
audio.play(my_audio_buffer)
32+
33+
4. `Audio Frames <#audioframe>`_, an iterable (like a list or a generator)
2734
of Audio Frames, which are lists of 32 samples with values from 0 to 255::
2835

2936
square_wave = audio.AudioFrame()
@@ -40,13 +47,16 @@ Functions
4047
4148
Play the audio source to completion.
4249

43-
:param source: There are three types of data that can be used as a source:
50+
:param source: There are four types of data that can be used as a source:
4451

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

@@ -215,6 +225,61 @@ Sound Effects Example
215225
.. include:: ../examples/soundeffects.py
216226
:code: python
217227

228+
229+
Audio Buffer **V2**
230+
===================
231+
232+
.. py:class::
233+
AudioBuffer(duration=3000, rate=11000)
234+
235+
Create a buffer to contain audio data and its sampling rate.
236+
237+
The sampling rate is configured via constructor or instance attribute,
238+
and is used by the ``microphone.record_into()`` and
239+
``audio.play()`` functions to configure the recording and playback rates.
240+
241+
For audio recording, reducing the number of samples recorded per second
242+
will reduce the size of the data buffer, but also reduce the sound quality.
243+
And increasing the sampling rate increases the buffer size and sound
244+
quality.
245+
246+
For audio playback, reducing the sampling rate compared with the recording
247+
rate, will slow down the audio. And increasing the playback rate
248+
will speed it up.
249+
250+
The size of the buffer will be determined by the samples per second
251+
and the ``duration`` configured when creating a new instance.
252+
253+
:param duration: Indicates in milliseconds, how much sound data the buffer
254+
can contained at the configured ``data_rate``.
255+
:param rate: Sampling rate of for the data in the buffer. This value is
256+
used for recording and playback, and can be edited as an attribute.
257+
258+
.. py:function:: copy()
259+
260+
:returns: A copy of the Audio Buffer.
261+
262+
.. py:attribute:: rate
263+
264+
The sampling rate for the data inside the buffer.
265+
TODO: Indicate range of valid values here.
266+
267+
Audio Buffer Example
268+
--------------------
269+
270+
::
271+
272+
my_buffer = audio.AudioBuffer(duration=5000)
273+
microphone.record_into(my_buffer)
274+
audio.play(my_buffer)
275+
276+
# A smaller buffer can be generated with the same duration by using
277+
# a lower sampling rate
278+
smaller_buffer = audio.AudioBuffer(duration=5000, rate=5500)
279+
microphone.record_into(my_buffer)
280+
audio.play(my_buffer)
281+
282+
218283
AudioFrame
219284
==========
220285

docs/microphone.rst

Lines changed: 112 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ Microphone **V2**
44
.. py:module:: microbit.microphone
55
66
This object lets you access the built-in microphone available on the
7-
micro:bit **V2**. It can be used to respond to sound. The microphone input
8-
is located on the front of the board alongside a microphone activity LED,
9-
which is lit when the microphone is in use.
7+
micro:bit **V2**. It can be used to record and respond to sound.
8+
The microphone input is located on the front of the board alongside a
9+
microphone activity LED, which is lit when the microphone is in use.
1010

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

31+
Recording
32+
=========
33+
34+
TODO:
35+
* Describe the feature.
36+
* Indicate how the sampling rate relates to recording quality.
37+
* Indicate how changing the sampling rate on the fly affects playback speed.
38+
* What happens if the user changes the sampling rate while recording?
39+
40+
::
41+
42+
from microbit import *
43+
44+
while True:
45+
if button_a.is_pressed():
46+
my_recording = microphone.record(duration=5000)
47+
audio.play(my_recording)
48+
sleep(200)
49+
3150
Functions
3251
=========
3352

@@ -91,11 +110,60 @@ Functions
91110

92111
:return: A representation of the sound pressure level in the range 0 to 255.
93112

113+
.. py:function:: record(duration=3000, rate=11000, wait=True)
114+
115+
Record sound for the amount of time indicated by ``duration`` at the
116+
sampling rate indicated by ``rate``.
117+
118+
The amount of memory consumed is directly related to the length of the
119+
recording and the sampling rate. The higher these values, the more memory
120+
it will use.
121+
122+
A lower sampling rate will reduce memory consumption and sound quality.
123+
124+
If there isn't enough memory available a ``MemoryError`` will be raised.
125+
126+
:param duration: How much time to record in milliseconds.
127+
:param rate: Number of samples to capture per second.
128+
:param wait: When set to ``True`` it blocks until the recording is
129+
done, if it is set to ``False`` it will run in the background.
130+
:returns: An ``AudioBuffer``, configured at the provided ``duration``
131+
and ``rate``, with the sound data.
132+
133+
.. py:function:: record_into(buffer, rate=11000, wait=True)
134+
135+
Record sound into an existing ``AudioBuffer``.
136+
137+
:param buffer: An ``AudioBuffer`` to record the microphone sound.
138+
:param rate: Number of samples to capture per second.
139+
:param wait: When set to ``True`` it blocks until the recording is
140+
done, if it is set to ``False`` it will run in the background.
94141

95-
Example
96-
=======
142+
.. py:function:: is_recording()
97143
98-
An example that runs through some of the functions of the microphone API::
144+
:returns: ``True`` if the microphone is currently recording sound, or
145+
``False`` otherwise.
146+
147+
.. py:function:: stop_recording()
148+
149+
Stops an a recording running in the background.
150+
151+
.. py:function:: set_sensitivity(gain)
152+
153+
Configure the microphone sensitivity to one of these three levels:
154+
``microphone.SENSITIVITY_LOW``, ``microphone.SENSITIVITY_MEDIUM``,
155+
``microphone.SENSITIVITY_HIGH``.
156+
157+
These constants correspond to a number, and any values between these
158+
constants are valid arguments
159+
160+
:param gain: Microphone gain.
161+
162+
Examples
163+
========
164+
165+
An example that runs through some of the functions of the microphone
166+
Sound Events API::
99167

100168
# Basic test for microphone. This test should update the display when
101169
# Button A is pressed and a loud or quiet sound *is* heard, printing the
@@ -143,3 +211,41 @@ An example that runs through some of the functions of the microphone API::
143211
display.clear()
144212
print(sound)
145213
sleep(500)
214+
215+
216+
An example of recording and playback with a display animation::
217+
218+
from microbit import *
219+
220+
talk_open = Image(
221+
"09090:"
222+
"00000:"
223+
"09990:"
224+
"90009:"
225+
"09990"
226+
)
227+
talk_closed = Image(
228+
"09090:"
229+
"00000:"
230+
"00000:"
231+
"99999:"
232+
"00000"
233+
)
234+
235+
my_recording = audio.AudioBuffer(duration=5000, rate=5500)
236+
237+
while True:
238+
if button_a.is_pressed():
239+
microphone.record_into(my_recording, rate=5500, wait=False)
240+
display.show([talk_open, talk_closed], loop=True, wait=False, delay=150)
241+
while button_a.is_pressed():
242+
sleep(50)
243+
display.show(mouth_open, loop=False) # workaround issue #150
244+
display.clear()
245+
if button_b.is_pressed():
246+
audio.play(my_recording, wait=False)
247+
while audio.is_playing():
248+
x = accelerometer.get_x()
249+
my_recording.rate = scale(x, (-1000, 1000), (2250, 11000))
250+
sleep(50)
251+
sleep(100)

0 commit comments

Comments
 (0)