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

[DO NOT MERGE] Update for forthcoming beta MicroPython #97

Draft
wants to merge 25 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
791689a
Add was_touched
microbit-matt-hillsdon Mar 19, 2024
506c92f
Add `get_touches` method docs
microbit-grace Mar 20, 2024
9221520
WIP recording playback APIs
microbit-matt-hillsdon Mar 20, 2024
12a25f1
Change :returns: -> :return:
microbit-grace Mar 20, 2024
d9b3ffb
Add examples
microbit-grace Mar 20, 2024
44af467
Tweak
microbit-grace Mar 20, 2024
5ff1eb7
Update to deep_sleep doc
microbit-grace Mar 20, 2024
6190ec7
Update run_every microbit doc
microbit-grace Mar 20, 2024
9704523
Change the en/typeshed instead of welsh typeshed
microbit-grace Mar 20, 2024
e0a4593
Revert "Update to deep_sleep doc"
microbit-grace Mar 20, 2024
b7f91ec
Revert "Change the en/typeshed instead of welsh typeshed"
microbit-grace Mar 20, 2024
79b44b6
ticks_cpu doc
microbit-grace Apr 3, 2024
b90c486
Add WIP audio.sound_level stub
microbit-grace Apr 3, 2024
609444f
Add stubs for AudioFrame operations
microbit-matt-hillsdon Apr 3, 2024
7cb5277
Duration doesn't have a default in practice
microbit-matt-hillsdon Apr 3, 2024
f5ca4aa
Update set_threshold doc to copy micropython doc
microbit-grace Apr 12, 2024
936b172
Suggested ammendments for set_threshold doc
microbit-grace Apr 12, 2024
7057837
Update audio.sound_level doc
microbit-grace Apr 15, 2024
f4c9898
Add microphone sound_level_db doc
microbit-grace May 3, 2024
263b689
Initial stubs updates
microbit-matt-hillsdon Aug 20, 2024
3826bce
Corrections
microbit-matt-hillsdon Aug 21, 2024
6dcc5ab
Corrections
microbit-matt-hillsdon Aug 21, 2024
fc85377
Microphone stubs
microbit-matt-hillsdon Aug 21, 2024
69aaab7
Update play stubs
microbit-matt-hillsdon Aug 21, 2024
91eb337
Docs for audio.play
microbit-matt-hillsdon Aug 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lang/en/typeshed/stdlib/audio.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ from .microbit.audio import (
is_playing as is_playing,
play as play,
stop as stop,
AudioRecording as AudioRecording,
AudioTrack as AudioTrack,
AudioFrame as AudioFrame,
SoundEffect as SoundEffect,
)
44 changes: 30 additions & 14 deletions lang/en/typeshed/stdlib/microbit/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def run_every(

As a Decorator - placed on top of the function to schedule. For example::

@run_every(h=1, min=20, s=30, ms=50)
@run_every(days=1, h=1, min=20, s=30, ms=50)
def my_function():
# Do something here

Expand Down Expand Up @@ -278,24 +278,28 @@ class MicroBitTouchPin(MicroBitAnalogDigitalPin):

Example: ``pin0.is_touched()``

The default touch mode for the pins on the edge connector is ``resistive``.
The default for the logo pin **V2** is ``capacitive``.
:return: ``True`` if the pin is being touched with a finger, otherwise return ``False``.
"""
...

**Resistive touch**
This test is done by measuring how much resistance there is between the
pin and ground. A low resistance gives a reading of ``True``. To get
a reliable reading using a finger you may need to touch the ground pin
with another part of your body, for example your other hand.
def was_touched(self) -> bool:
"""Check if the pin was touched since the last time this method was called.

**Capacitive touch**
This test is done by interacting with the electric field of a capacitor
using a finger as a conductor. `Capacitive touch
<https://www.allaboutcircuits.com/technical-articles/introduction-to-capacitive-touch-sensing>`_
does not require you to make a ground connection as part of a circuit.
Example: ``pin0.was_touched()``

:return: ``True`` if the pin is being touched with a finger, otherwise return ``False``.
:return: ``True`` or ``False`` to indicate if the pin was touched since the device started or since the last time this method was called.
"""
...

def get_touches(self) -> int:
"""Get the number of times the pin was touched since the last time this method was called.

Example: ``pin0.get_touches()``

:return: The number of times the pin was touched since the device started or since the last time this method was called.
"""
...

def set_touch_mode(self, value: int) -> None:
"""Set the touch mode for the pin.

Expand All @@ -304,6 +308,18 @@ class MicroBitTouchPin(MicroBitAnalogDigitalPin):
The default touch mode for the pins on the edge connector is
``resistive``. The default for the logo pin **V2** is ``capacitive``.

**Resistive touch**
This test is done by measuring how much resistance there is between the
pin and ground. A low resistance gives a reading of ``True``. To get
a reliable reading using a finger you may need to touch the ground pin
with another part of your body, for example your other hand.

**Capacitive touch**
This test is done by interacting with the electric field of a capacitor
using a finger as a conductor. `Capacitive touch
<https://www.allaboutcircuits.com/technical-articles/introduction-to-capacitive-touch-sensing>`_
does not require you to make a ground connection as part of a circuit.

:param value: ``CAPACITIVE`` or ``RESISTIVE`` from the relevant pin.
"""
...
Expand Down
166 changes: 161 additions & 5 deletions lang/en/typeshed/stdlib/microbit/audio.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@
"""

from ..microbit import MicroBitDigitalPin, Sound, pin0
from typing import ClassVar, Iterable, Union
from typing import ClassVar, Iterable, Optional, Union, overload

def play(
source: Union[Iterable[AudioFrame], Sound, SoundEffect],
source: Union[AudioFrame, Iterable[AudioFrame], AudioRecording, AudioTrack, Sound, SoundEffect],
wait: bool = True,
pin: MicroBitDigitalPin = pin0,
return_pin: Union[MicroBitDigitalPin, None] = None,
) -> None:
"""Play a built-in sound, sound effect or custom audio frames.
"""Play a built-in sound, sound effect or audio samples.

Example: ``audio.play(Sound.GIGGLE)``

:param source: A built-in ``Sound`` such as ``Sound.GIGGLE``, a ``SoundEffect`` or sample data as an iterable of ``AudioFrame`` objects.
:param source: A built-in ``Sound`` such as ``Sound.GIGGLE``, a ``SoundEffect`` or sample data as an ``AudioFrame``, ``AudioRecording`` or ``AudioTrack`` object or an iterable of ``AudioFrame`` objects.
:param wait: If ``wait`` is ``True``, this function will block until the sound is complete.
:param pin: An optional argument to specify the output pin can be used to override the default of ``pin0``. If we do not want any sound to play we can use ``pin=None``.
:param return_pin: Specifies a differential edge connector pin to connect to an external speaker instead of ground. This is ignored for the **V2** revision.
Expand All @@ -28,6 +28,14 @@ def is_playing() -> bool:
:return: ``True`` if audio is playing, otherwise ``False``."""
...

def sound_level() -> int:
"""Returns the sound pressure level produced by audio currently being played.

Example: ``audio.sound_level()``

:return: A representation of the output sound pressure level in the range 0 to 255."""
...

def stop() -> None:
"""Stop all audio playback.

Expand Down Expand Up @@ -135,6 +143,154 @@ class SoundEffect:
:return: A copy of the SoundEffect.
"""


class AudioRecording:
"""The ``AudioRecording`` object contains audio data and the sampling rate
associated to it (V2 only).

The size of the internal buffer will depend on the ``rate``
(number of samples per second) and ``duration`` parameters.
The larger these values are, the more memory that will be used.

When an ``AudioRecording`` is used to record data from the microphone,
a higher sampling rate produces better sound quality,
but it also uses more memory.

During playback, increasing the sampling rate speeds up the sound
and decreasing the sample rate slows it down.

The data inside an ``AudioRecording`` is not easy to modify, so the
``AudioTrack`` class is provided to help access the audio data like a list.
The method ``AudioRecording.track()`` can be used to create an ``AudioTrack``,
and its arguments ``start_ms`` and ``end_ms`` can be used to slice portions
of the data.
"""

def __init__(
self,
duration: int = -1,
rate: int = 11_000
):
"""Create a new ``AudioRecording``.

Example: ``my_recording = AudioRecording(duration=5000)``

:param duration: Indicates how many milliseconds of audio this instance can store.
:param rate: The sampling rate at which data will be stored via the microphone, or played via the ``audio.play()`` function.
"""

def copy(self) -> None:
"""Create a copy of the ``AudioRecording``.

Example: ``copy = my_recording.copy()``

:return: A copy of the ``AudioRecording``.
"""

def track(self, start_ms: int = 0, end_ms: int = -1) -> AudioTrack:
"""Create an ``AudioTrack`` instance from a portion of the data in this ``AudioRecording`` instance.

Example: ``first_second = my_recording.track(0, 1000)``

:param start_ms: (default=0) Where to start of the track in milliseconds.
:param end_ms: (default=-1) The end of the track in milliseconds. If the default value of ``-1`` is provided it will end the track at the end of the AudioRecording.
:return: An ``AudioTrack`` backed by the sample data between ``start_ms`` and ``end_ms``.
"""

class AudioTrack:
""" The ``AudioTrack`` object points to the data provided by the input buffer,
which can be an ``AudioRecording``, another ``AudioTrack``,
or a buffer-like object like a ``bytearray`` (V2 only).
"""

def __init__(
self,
buffer: Union[bytearray, AudioRecording, AudioTrack],
rate: Optional[int] = None
):
"""Create a new ``AudioTrack``.

When the input buffer has an associated rate (e.g. an ``AudioRecording``
or ``AudioTrack``), the rate is copied. If the buffer object does not have
a rate, the default value of 11_000 is used.

Example: ``my_track = AudioTrack(bytearray(4096))``

An ``AudioTrack`` can be created from an ``AudioRecording``, another
``AudioTrack``, or a ``bytearray`` and individual bytes can be accessed and
modified like elements in a list::

my_track = AudioTrack(bytearray(100))
# Create a square wave
half_length = len(my_track) // 2
for i in range(half_length):
my_track[i] = 255
for i in range(half_length, len(my_track)):
my_track[i] = 0

Or smaller AudioTracks can be created using slices, useful to send them
via radio or serial::

recording = microphone.record(duration=2000)
track = AudioTrack(recording)
packet_size = 32
for i in range(0, len(track), packet_size):
radio.send_bytes(track[i:i+packet_size])

:param buffer: The buffer containing the audio data.
:param rate: (default=None) The sampling rate at which data will be stored via the microphone, or played via the ``audio.play()`` function.
"""

def set_rate(self, sample_rate: int) -> None:
"""Configure the sampling rate associated with the data in the
``AudioTrack`` instance.


Changes to an ``AudioTrack`` rate won't affect the original source rate,
so multiple instances pointing to the same buffer can have different
rates and the original buffer rate would stay unmodified.

Example: ``my_track.set_rate(22_000)``
"""

def get_rate(self) -> int:
"""Get the sampling rate associated with the data in the
``AudioRecording`` instance.

Example: ``current_rate = my_track.get_rate()``

:return: The configured sample rate.
"""

def copyfrom(self, other: Union[bytearray, AudioRecording, AudioTrack]) -> None:
"""Overwrite the data in this ``AudioTrack`` with the data from another
``AudioTrack``, ``AudioRecording``, or buffer-like object like a
``bytearray`` instance.

If the input buffer is smaller than the available space in this
instance, the rest of the data is left untouched.
If it is larger, it will stop copying once this instance is filled.

:param other: Buffer-like instance from which to copy the data.
"""

def __len__(self) -> int: ...


@overload
def __getitem__(self, i: int) -> int: ...
@overload
def __getitem__(self, s: slice) -> AudioTrack: ...
def __setitem__(self, i: int, x: int) -> None: ...

def __add__(self, v: AudioTrack) -> AudioTrack: ...
def __iadd__(self, v: AudioTrack) -> AudioTrack: ...
def __sub__(self, v: AudioTrack) -> AudioTrack: ...
def __isub__(self, v: AudioTrack) -> AudioTrack: ...
def __mul__(self, v: float) -> AudioTrack: ...
def __imul__(self, v: float) -> AudioTrack: ...


class AudioFrame:
"""An ``AudioFrame`` object is a list of 32 samples each of which is a unsigned byte
(whole number between 0 and 255).
Expand All @@ -157,4 +313,4 @@ class AudioFrame:
"""
def __len__(self) -> int: ...
def __setitem__(self, key: int, value: int) -> None: ...
def __getitem__(self, key: int) -> int: ...
def __getitem__(self, key: int) -> int: ...
Loading
Loading