From 791689a80027e04ec96baf4632a08f58f66743d7 Mon Sep 17 00:00:00 2001
From: Matt Hillsdon <matt.hillsdon@microbit.org>
Date: Tue, 19 Mar 2024 17:09:00 +0000
Subject: [PATCH 01/25] Add was_touched

I think the docs PRs are missing get_touches too but will revisit that.
---
 lang/en/typeshed/stdlib/microbit/__init__.pyi | 33 +++++++++++--------
 1 file changed, 20 insertions(+), 13 deletions(-)

diff --git a/lang/en/typeshed/stdlib/microbit/__init__.pyi b/lang/en/typeshed/stdlib/microbit/__init__.pyi
index 5e03529..163df7f 100644
--- a/lang/en/typeshed/stdlib/microbit/__init__.pyi
+++ b/lang/en/typeshed/stdlib/microbit/__init__.pyi
@@ -278,24 +278,19 @@ 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 set_touch_mode(self, value: int) -> None:
         """Set the touch mode for the pin.
 
@@ -304,6 +299,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.
         """
         ...

From 506c92f533fa54c7683cb9b2036664a8a6ac8611 Mon Sep 17 00:00:00 2001
From: Grace <grace@microbit.org>
Date: Wed, 20 Mar 2024 09:45:12 +0000
Subject: [PATCH 02/25] Add `get_touches` method docs

---
 lang/en/typeshed/stdlib/microbit/__init__.pyi | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/lang/en/typeshed/stdlib/microbit/__init__.pyi b/lang/en/typeshed/stdlib/microbit/__init__.pyi
index 163df7f..08ed2d1 100644
--- a/lang/en/typeshed/stdlib/microbit/__init__.pyi
+++ b/lang/en/typeshed/stdlib/microbit/__init__.pyi
@@ -290,6 +290,15 @@ class MicroBitTouchPin(MicroBitAnalogDigitalPin):
         :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.

From 92215207e039ce69f14a075c8f7f885239fa2008 Mon Sep 17 00:00:00 2001
From: Matt Hillsdon <matt.hillsdon@microbit.org>
Date: Wed, 20 Mar 2024 11:41:22 +0000
Subject: [PATCH 03/25] WIP recording playback APIs

These are not final and we have outstanding queries.
---
 lang/en/typeshed/stdlib/microbit/audio.pyi    | 49 +++++++++++++--
 .../typeshed/stdlib/microbit/microphone.pyi   | 63 +++++++++++++++++++
 2 files changed, 107 insertions(+), 5 deletions(-)

diff --git a/lang/en/typeshed/stdlib/microbit/audio.pyi b/lang/en/typeshed/stdlib/microbit/audio.pyi
index 3b1e327..d537ff3 100644
--- a/lang/en/typeshed/stdlib/microbit/audio.pyi
+++ b/lang/en/typeshed/stdlib/microbit/audio.pyi
@@ -5,16 +5,16 @@ from ..microbit import MicroBitDigitalPin, Sound, pin0
 from typing import ClassVar, Iterable, Union
 
 def play(
-    source: Union[Iterable[AudioFrame], Sound, SoundEffect],
+    source: Union[AudioFrame, Iterable[AudioFrame], 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 using ``AudioFrame``.
 
     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`` 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.
@@ -136,10 +136,18 @@ class SoundEffect:
         """
 
 class AudioFrame:
-    """An ``AudioFrame`` object is a list of 32 samples each of which is a unsigned byte
+    """An ``AudioFrame`` object is a list of samples, each of which is an unsigned byte
     (whole number between 0 and 255).
 
-    It takes just over 4 ms to play a single frame.
+    The number of samples in an AudioFrame will depend on the
+    ``rate`` (number of samples per second) and ``duration`` parameters.
+    The total number of samples will always be a round up multiple of 32.
+
+    On micro:bit V1 the constructor does not take any arguments,
+    and an AudioFrame instance is always 32 bytes.
+
+    For example, playing 32 samples at 7812 Hz takes just over 4 milliseconds
+    (1/7812.5 * 32 = 0.004096 = 4096 microseconds).
 
     Example::
 
@@ -148,6 +156,37 @@ class AudioFrame:
             frame[i] = 252 - i * 8
     """
 
+    def __init__(
+        self,
+        duration: int = -1,
+        rate: int = 7812
+    ):
+        """Create a new ``AudioFrame``.
+
+        Example: ``my_recording = AudioFrame(duration=5000)``
+
+        :param duration: Indicates how many milliseconds of audio this instance can store (V2 only).
+        :param rate: The sampling rate at which data will be stored via the microphone, or played via the ``audio.play()`` function (V2 only).
+        """
+
+    def set_rate(self, sample_rate: int) -> None:
+        """Configure the sampling rate associated with the data in the
+        ``AudioFrame`` instance (V2 only).
+
+        For recording from the microphone, increasing the sampling rate
+        increases the sound quality, but reduces the length of audio it
+        can store.
+        During playback, increasing the sampling rate speeds up the sound
+        and decreasing it slows it down.
+        """
+
+    def get_rate(self) -> int:
+        """Get the sampling rate associated with the data in the
+        ``AudioFrame`` instance (V2 only).
+
+         :returns: The configured sampling rate for this ``AudioFrame`` instance.
+        """
+
     def copyfrom(self, other: AudioFrame) -> None:
         """Overwrite the data in this ``AudioFrame`` with the data from another ``AudioFrame`` instance.
 
diff --git a/lang/en/typeshed/stdlib/microbit/microphone.pyi b/lang/en/typeshed/stdlib/microbit/microphone.pyi
index 68e8f3a..5dc255e 100644
--- a/lang/en/typeshed/stdlib/microbit/microphone.pyi
+++ b/lang/en/typeshed/stdlib/microbit/microphone.pyi
@@ -3,6 +3,7 @@
 
 from typing import Optional, Tuple
 from ..microbit import SoundEvent
+from ..microbit.audio import AudioFrame
 
 def current_event() -> Optional[SoundEvent]:
     """Get the last recorded sound event
@@ -68,3 +69,65 @@ def sound_level() -> int:
     :return: A representation of the sound pressure level in the range 0 to 255.
     """
     ...
+
+def record(duration: int = 3000, rate: int = 7812) -> AudioFrame:
+    """Record sound into an ``AudioFrame`` 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.
+
+    A lower sampling rate will reduce both memory consumption and sound
+    quality.
+
+    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 to capture per second.
+    :returns: An ``AudioFrame`` with the sound samples.
+    """
+    ...
+
+def record_into(buffer: AudioFrame, rate: int = 7812, wait: bool = True) -> None:
+    """Record sound into an existing ``AudioFrame`` until it is filled,
+    or the ``stop_recording()`` function is called.
+
+    :param buffer: An ``AudioFrame`` to record sound.
+    :param rate: Number of samples to capture per second.
+    :param wait: When set to ``True`` it blocks until the recording is
+        done, if it is set to ``False`` it will run in the background.
+    """
+    ...
+
+def is_recording() -> bool:
+    """Checks whether the microphone is currently recording.
+
+    :returns: ``True`` if the microphone is currently recording sound, or
+   ``False`` otherwise.
+    """
+    ...
+
+def stop_recording() -> None:
+    """Stops a recording running in the background.
+    """
+    ...
+
+SENSITIVITY_LOW: float;
+"""Low microphone sensitivity."""
+
+SENSITIVITY_MEDIUM: float;
+"""Medium microphone sensitivity."""
+
+SENSITIVITY_HIGH: float;
+"""High microphone sensitivity."""
+
+
+def set_sensitivity(gain: float) -> None:
+    """Configure the microphone sensitivity.
+
+    The default sensitivity is ``microphone.SENSITIVITY_MEDIUM``.
+
+    :param gain: The microphone gain. Use ``microphone.SENSITIVITY_LOW``, ``microphone.SENSITIVITY_MEDIUM``, ``microphone.SENSITIVITY_HIGH``, or a value between these levels.
+    """
+    ...
\ No newline at end of file

From 12a25f1e0ca0764b7e679a8ee686ab8825209ce1 Mon Sep 17 00:00:00 2001
From: Grace <grace@microbit.org>
Date: Wed, 20 Mar 2024 11:53:41 +0000
Subject: [PATCH 04/25] Change :returns: -> :return:

---
 lang/en/typeshed/stdlib/microbit/audio.pyi      | 2 +-
 lang/en/typeshed/stdlib/microbit/microphone.pyi | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/lang/en/typeshed/stdlib/microbit/audio.pyi b/lang/en/typeshed/stdlib/microbit/audio.pyi
index d537ff3..fe64689 100644
--- a/lang/en/typeshed/stdlib/microbit/audio.pyi
+++ b/lang/en/typeshed/stdlib/microbit/audio.pyi
@@ -184,7 +184,7 @@ class AudioFrame:
         """Get the sampling rate associated with the data in the
         ``AudioFrame`` instance (V2 only).
 
-         :returns: The configured sampling rate for this ``AudioFrame`` instance.
+         :return: The configured sampling rate for this ``AudioFrame`` instance.
         """
 
     def copyfrom(self, other: AudioFrame) -> None:
diff --git a/lang/en/typeshed/stdlib/microbit/microphone.pyi b/lang/en/typeshed/stdlib/microbit/microphone.pyi
index 5dc255e..19cb2dd 100644
--- a/lang/en/typeshed/stdlib/microbit/microphone.pyi
+++ b/lang/en/typeshed/stdlib/microbit/microphone.pyi
@@ -85,7 +85,7 @@ def record(duration: int = 3000, rate: int = 7812) -> AudioFrame:
 
     :param duration: How long to record in milliseconds.
     :param rate: Number of samples to capture per second.
-    :returns: An ``AudioFrame`` with the sound samples.
+    :return: An ``AudioFrame`` with the sound samples.
     """
     ...
 
@@ -103,7 +103,7 @@ def record_into(buffer: AudioFrame, rate: int = 7812, wait: bool = True) -> None
 def is_recording() -> bool:
     """Checks whether the microphone is currently recording.
 
-    :returns: ``True`` if the microphone is currently recording sound, or
+    :return: ``True`` if the microphone is currently recording sound, or
    ``False`` otherwise.
     """
     ...

From d9b3ffb02020a4cfe63ee01e5b17154cabc7fef5 Mon Sep 17 00:00:00 2001
From: Grace <grace@microbit.org>
Date: Wed, 20 Mar 2024 12:33:53 +0000
Subject: [PATCH 05/25] Add examples

---
 lang/en/typeshed/stdlib/microbit/audio.pyi      |  5 +++++
 lang/en/typeshed/stdlib/microbit/microphone.pyi | 13 +++++++++++--
 2 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/lang/en/typeshed/stdlib/microbit/audio.pyi b/lang/en/typeshed/stdlib/microbit/audio.pyi
index fe64689..3ae4510 100644
--- a/lang/en/typeshed/stdlib/microbit/audio.pyi
+++ b/lang/en/typeshed/stdlib/microbit/audio.pyi
@@ -173,9 +173,12 @@ class AudioFrame:
         """Configure the sampling rate associated with the data in the
         ``AudioFrame`` instance (V2 only).
 
+        Example: ``my_frame.set_rate(7812)``
+
         For recording from the microphone, increasing the sampling rate
         increases the sound quality, but reduces the length of audio it
         can store.
+
         During playback, increasing the sampling rate speeds up the sound
         and decreasing it slows it down.
         """
@@ -184,6 +187,8 @@ class AudioFrame:
         """Get the sampling rate associated with the data in the
         ``AudioFrame`` instance (V2 only).
 
+        Example: ``current_rate = my_frame.get_rate()``
+
          :return: The configured sampling rate for this ``AudioFrame`` instance.
         """
 
diff --git a/lang/en/typeshed/stdlib/microbit/microphone.pyi b/lang/en/typeshed/stdlib/microbit/microphone.pyi
index 19cb2dd..fbd91a0 100644
--- a/lang/en/typeshed/stdlib/microbit/microphone.pyi
+++ b/lang/en/typeshed/stdlib/microbit/microphone.pyi
@@ -74,6 +74,8 @@ def record(duration: int = 3000, rate: int = 7812) -> AudioFrame:
     """Record sound into an ``AudioFrame`` for the amount of time indicated by
     ``duration`` at the sampling rate indicated by ``rate``.
 
+    Example: ``my_frame = microphone.record()``
+
     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.
@@ -93,6 +95,8 @@ def record_into(buffer: AudioFrame, rate: int = 7812, wait: bool = True) -> None
     """Record sound into an existing ``AudioFrame`` until it is filled,
     or the ``stop_recording()`` function is called.
 
+    Example: ``microphone.record_into()``
+
     :param buffer: An ``AudioFrame`` to record sound.
     :param rate: Number of samples to capture per second.
     :param wait: When set to ``True`` it blocks until the recording is
@@ -103,13 +107,16 @@ def record_into(buffer: AudioFrame, rate: int = 7812, wait: bool = True) -> None
 def is_recording() -> bool:
     """Checks whether the microphone is currently recording.
 
-    :return: ``True`` if the microphone is currently recording sound, or
-   ``False`` otherwise.
+    Example: ``is_recording = microphone.is_recording()``
+
+    :return: ``True`` if the microphone is currently recording sound, otherwise returns ``False``.
     """
     ...
 
 def stop_recording() -> None:
     """Stops a recording running in the background.
+
+    Example: ``microphone.stop_recording()``
     """
     ...
 
@@ -126,6 +133,8 @@ SENSITIVITY_HIGH: float;
 def set_sensitivity(gain: float) -> None:
     """Configure the microphone sensitivity.
 
+    Example: ``microphone.set_sensitivity(microphone.SENSITIVITY_HIGH)``
+
     The default sensitivity is ``microphone.SENSITIVITY_MEDIUM``.
 
     :param gain: The microphone gain. Use ``microphone.SENSITIVITY_LOW``, ``microphone.SENSITIVITY_MEDIUM``, ``microphone.SENSITIVITY_HIGH``, or a value between these levels.

From 44af467e4e3a69083268ca86aad57d4e16d917f4 Mon Sep 17 00:00:00 2001
From: Grace <grace@microbit.org>
Date: Wed, 20 Mar 2024 12:41:00 +0000
Subject: [PATCH 06/25] Tweak

---
 lang/en/typeshed/stdlib/microbit/__init__.pyi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lang/en/typeshed/stdlib/microbit/__init__.pyi b/lang/en/typeshed/stdlib/microbit/__init__.pyi
index 08ed2d1..ea08cb4 100644
--- a/lang/en/typeshed/stdlib/microbit/__init__.pyi
+++ b/lang/en/typeshed/stdlib/microbit/__init__.pyi
@@ -296,7 +296,7 @@ class MicroBitTouchPin(MicroBitAnalogDigitalPin):
 
         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.
+        :return: The number of times the pin was touched since the device started or since the last time this method was called.
         """
         ...
 

From 5ff1eb7aaaec8816ac9b0451ea889a6b98013a3b Mon Sep 17 00:00:00 2001
From: Grace <grace@microbit.org>
Date: Wed, 20 Mar 2024 12:53:43 +0000
Subject: [PATCH 07/25] Update to deep_sleep doc

To match changes in docs: Update Power Mgm to change run_every behaviour #769
---
 lang/ca/typeshed/stdlib/power.pyi | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/lang/ca/typeshed/stdlib/power.pyi b/lang/ca/typeshed/stdlib/power.pyi
index 2be8b27..64be646 100644
--- a/lang/ca/typeshed/stdlib/power.pyi
+++ b/lang/ca/typeshed/stdlib/power.pyi
@@ -43,8 +43,9 @@ def deep_sleep(
     when the USB cable is inserted.
 
     When the ``run_every`` parameter is set to ``True`` (the default), any
-    function scheduled with ``run_every`` will momentarily wake up the board
-    to run and when it finishes it will go back to sleep.
+    function scheduled with :py:meth:`microbit.run_every<microbit.run_every>`
+    will momentarily wake up the board to run and when it finishes it will go
+    back to sleep.
 
     :param ms: A time in milliseconds to wait before it wakes up.
     :param wake_on: A single instance or a tuple of pins and/or buttons to wake up the board, e.g. ``deep_sleep(wake_on=button_a)`` or ``deep_sleep(wake_on=(pin0, pin2, button_b))``.

From 6190ec7ee41f55c0468b7fa271b70ef7c716fdc6 Mon Sep 17 00:00:00 2001
From: Grace <grace@microbit.org>
Date: Wed, 20 Mar 2024 13:08:37 +0000
Subject: [PATCH 08/25] Update run_every microbit doc

To match PR docs: Add missing days parameter to microbit.run_every. (#767)
---
 lang/en/typeshed/stdlib/microbit/__init__.pyi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lang/en/typeshed/stdlib/microbit/__init__.pyi b/lang/en/typeshed/stdlib/microbit/__init__.pyi
index ea08cb4..d1e039e 100644
--- a/lang/en/typeshed/stdlib/microbit/__init__.pyi
+++ b/lang/en/typeshed/stdlib/microbit/__init__.pyi
@@ -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
 

From 9704523fe86bfb8ea2b0e35851f0793ce27a6127 Mon Sep 17 00:00:00 2001
From: Grace <grace@microbit.org>
Date: Wed, 20 Mar 2024 13:21:09 +0000
Subject: [PATCH 09/25] Change the en/typeshed instead of welsh typeshed

---
 lang/en/typeshed/stdlib/power.pyi | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lang/en/typeshed/stdlib/power.pyi b/lang/en/typeshed/stdlib/power.pyi
index 2be8b27..7d3da44 100644
--- a/lang/en/typeshed/stdlib/power.pyi
+++ b/lang/en/typeshed/stdlib/power.pyi
@@ -43,8 +43,8 @@ def deep_sleep(
     when the USB cable is inserted.
 
     When the ``run_every`` parameter is set to ``True`` (the default), any
-    function scheduled with ``run_every`` will momentarily wake up the board
-    to run and when it finishes it will go back to sleep.
+    function scheduled with ``run_every`` will momentarily wake up the board to 
+    run and when it finishes it will go back to sleep.
 
     :param ms: A time in milliseconds to wait before it wakes up.
     :param wake_on: A single instance or a tuple of pins and/or buttons to wake up the board, e.g. ``deep_sleep(wake_on=button_a)`` or ``deep_sleep(wake_on=(pin0, pin2, button_b))``.

From e0a459368cc26705c1e6dbdfc66ad75c7446b191 Mon Sep 17 00:00:00 2001
From: Grace <grace@microbit.org>
Date: Wed, 20 Mar 2024 13:21:55 +0000
Subject: [PATCH 10/25] Revert "Update to deep_sleep doc"

This reverts commit 5ff1eb7aaaec8816ac9b0451ea889a6b98013a3b.
Accidentally changed lang/ca/typeshed (Welsh one) instead of en.
---
 lang/ca/typeshed/stdlib/power.pyi | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/lang/ca/typeshed/stdlib/power.pyi b/lang/ca/typeshed/stdlib/power.pyi
index 64be646..2be8b27 100644
--- a/lang/ca/typeshed/stdlib/power.pyi
+++ b/lang/ca/typeshed/stdlib/power.pyi
@@ -43,9 +43,8 @@ def deep_sleep(
     when the USB cable is inserted.
 
     When the ``run_every`` parameter is set to ``True`` (the default), any
-    function scheduled with :py:meth:`microbit.run_every<microbit.run_every>`
-    will momentarily wake up the board to run and when it finishes it will go
-    back to sleep.
+    function scheduled with ``run_every`` will momentarily wake up the board
+    to run and when it finishes it will go back to sleep.
 
     :param ms: A time in milliseconds to wait before it wakes up.
     :param wake_on: A single instance or a tuple of pins and/or buttons to wake up the board, e.g. ``deep_sleep(wake_on=button_a)`` or ``deep_sleep(wake_on=(pin0, pin2, button_b))``.

From b7f91ec288a7ca64cddead3204286ffb7d3c8106 Mon Sep 17 00:00:00 2001
From: Grace <grace@microbit.org>
Date: Wed, 20 Mar 2024 13:24:07 +0000
Subject: [PATCH 11/25] Revert "Change the en/typeshed instead of welsh
 typeshed"

This reverts commit 9704523fe86bfb8ea2b0e35851f0793ce27a6127.
---
 lang/en/typeshed/stdlib/power.pyi | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lang/en/typeshed/stdlib/power.pyi b/lang/en/typeshed/stdlib/power.pyi
index 7d3da44..2be8b27 100644
--- a/lang/en/typeshed/stdlib/power.pyi
+++ b/lang/en/typeshed/stdlib/power.pyi
@@ -43,8 +43,8 @@ def deep_sleep(
     when the USB cable is inserted.
 
     When the ``run_every`` parameter is set to ``True`` (the default), any
-    function scheduled with ``run_every`` will momentarily wake up the board to 
-    run and when it finishes it will go back to sleep.
+    function scheduled with ``run_every`` will momentarily wake up the board
+    to run and when it finishes it will go back to sleep.
 
     :param ms: A time in milliseconds to wait before it wakes up.
     :param wake_on: A single instance or a tuple of pins and/or buttons to wake up the board, e.g. ``deep_sleep(wake_on=button_a)`` or ``deep_sleep(wake_on=(pin0, pin2, button_b))``.

From 79b44b618321cc2e4d69fe107e070de6f2c58634 Mon Sep 17 00:00:00 2001
From: Grace <grace@microbit.org>
Date: Wed, 3 Apr 2024 10:45:07 +0100
Subject: [PATCH 12/25] ticks_cpu doc

---
 lang/en/typeshed/stdlib/time.pyi | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/lang/en/typeshed/stdlib/time.pyi b/lang/en/typeshed/stdlib/time.pyi
index 598c483..d4da912 100644
--- a/lang/en/typeshed/stdlib/time.pyi
+++ b/lang/en/typeshed/stdlib/time.pyi
@@ -56,6 +56,16 @@ def ticks_us() -> int:
     """
     ...
 
+def ticks_cpu() -> int:
+    """
+    Similar to ticks_ms and ticks_us, but with higher resolution in CPU cycles.
+
+    Example: ``time.ticks_cpu()``
+
+    :return: The counter value in CPU cycles.
+    """
+    ...
+
 def ticks_add(ticks: int, delta: int) -> int:
     """
     Offset ticks value by a given number, which can be either positive or

From b90c4862b0eabb8b03261dfef0912f0be9deabdf Mon Sep 17 00:00:00 2001
From: Grace <grace@microbit.org>
Date: Wed, 3 Apr 2024 11:43:48 +0100
Subject: [PATCH 13/25] Add WIP audio.sound_level stub

To be updated once there is a doc for it.
---
 lang/en/typeshed/stdlib/microbit/audio.pyi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/lang/en/typeshed/stdlib/microbit/audio.pyi b/lang/en/typeshed/stdlib/microbit/audio.pyi
index 3ae4510..99334bb 100644
--- a/lang/en/typeshed/stdlib/microbit/audio.pyi
+++ b/lang/en/typeshed/stdlib/microbit/audio.pyi
@@ -28,6 +28,14 @@ def is_playing() -> bool:
     :return: ``True`` if audio is playing, otherwise ``False``."""
     ...
 
+def sound_level() -> int:
+    """Returns the average intensity of the sound played.
+
+    Example: ``audio.sound_level()``
+
+    :return: A number between 0 and 254, being the average intensity of the sound played from the most recent chunk of data."""
+    ...
+
 def stop() -> None:
     """Stop all audio playback.
 

From 609444fa9cb14649ce666978ec018f0d440bc954 Mon Sep 17 00:00:00 2001
From: Matt Hillsdon <matt.hillsdon@microbit.org>
Date: Wed, 3 Apr 2024 12:03:56 +0100
Subject: [PATCH 14/25] Add stubs for AudioFrame operations

---
 lang/en/typeshed/stdlib/microbit/audio.pyi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/lang/en/typeshed/stdlib/microbit/audio.pyi b/lang/en/typeshed/stdlib/microbit/audio.pyi
index 99334bb..4cd2ac4 100644
--- a/lang/en/typeshed/stdlib/microbit/audio.pyi
+++ b/lang/en/typeshed/stdlib/microbit/audio.pyi
@@ -210,3 +210,9 @@ class AudioFrame:
     def __len__(self) -> int: ...
     def __setitem__(self, key: int, value: int) -> None: ...
     def __getitem__(self, key: int) -> int: ...
+    def __add__(self, v: AudioFrame) -> AudioFrame: ...
+    def __iadd__(self, v: AudioFrame) -> AudioFrame: ...
+    def __sub__(self, v: AudioFrame) -> AudioFrame: ...
+    def __isub__(self, v: AudioFrame) -> AudioFrame: ...
+    def __mul__(self, v: float) -> AudioFrame: ...
+    def __imul__(self, v: float) -> AudioFrame: ...

From 7cb527747cbcd98f733268808ff208fca8d18100 Mon Sep 17 00:00:00 2001
From: Matt Hillsdon <matt.hillsdon@microbit.org>
Date: Wed, 3 Apr 2024 13:20:15 +0100
Subject: [PATCH 15/25] Duration doesn't have a default in practice

I've flagged this in the docs - it's possible the implementation will be
corrected instead.
---
 lang/en/typeshed/stdlib/microbit/microphone.pyi | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/lang/en/typeshed/stdlib/microbit/microphone.pyi b/lang/en/typeshed/stdlib/microbit/microphone.pyi
index fbd91a0..47d4786 100644
--- a/lang/en/typeshed/stdlib/microbit/microphone.pyi
+++ b/lang/en/typeshed/stdlib/microbit/microphone.pyi
@@ -70,11 +70,11 @@ def sound_level() -> int:
     """
     ...
 
-def record(duration: int = 3000, rate: int = 7812) -> AudioFrame:
+def record(duration: int, rate: int = 7812) -> AudioFrame:
     """Record sound into an ``AudioFrame`` for the amount of time indicated by
     ``duration`` at the sampling rate indicated by ``rate``.
 
-    Example: ``my_frame = microphone.record()``
+    Example: ``my_frame = microphone.record(3000)``
 
     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
@@ -95,7 +95,7 @@ def record_into(buffer: AudioFrame, rate: int = 7812, wait: bool = True) -> None
     """Record sound into an existing ``AudioFrame`` until it is filled,
     or the ``stop_recording()`` function is called.
 
-    Example: ``microphone.record_into()``
+    Example: ``microphone.record_into(my_frame)``
 
     :param buffer: An ``AudioFrame`` to record sound.
     :param rate: Number of samples to capture per second.

From f5ca4aaf4f75db225cb50cd2c1b90e7b7487d46e Mon Sep 17 00:00:00 2001
From: Grace <grace@microbit.org>
Date: Fri, 12 Apr 2024 16:54:53 +0100
Subject: [PATCH 16/25] Update set_threshold doc to copy micropython doc

---
 lang/en/typeshed/stdlib/microbit/microphone.pyi | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/lang/en/typeshed/stdlib/microbit/microphone.pyi b/lang/en/typeshed/stdlib/microbit/microphone.pyi
index 47d4786..08f8a79 100644
--- a/lang/en/typeshed/stdlib/microbit/microphone.pyi
+++ b/lang/en/typeshed/stdlib/microbit/microphone.pyi
@@ -54,10 +54,18 @@ def set_threshold(event: SoundEvent, value: int) -> None:
 
     Example: ``microphone.set_threshold(SoundEvent.LOUD, 250)``
 
-    A high threshold means the event will only trigger if the sound is very loud (>= 250 in the example).
+    The ``SoundEvent.LOUD`` event will be triggered when the sound level
+    crosses this threshold upwards (from "quiet" to "loud"),
+    and ``SoundEvent.QUIET`` event is triggered when crossing the threshold
+    downwards (from "loud" to "quiet").
+
+    If the ``SoundEvent.LOUD`` value set is lower than ``SoundEvent.QUIET``,
+    then "quiet" threshold will be decreased to one unit below the "loud"
+    threshold. If the ``SoundEvent.QUIET`` value is set higher than
+    ``SoundEvent.LOUD``, then the "loud" threshold will be set one unit above.
 
     :param event: A sound event, such as ``SoundEvent.LOUD`` or ``SoundEvent.QUIET``.
-    :param value: The threshold level in the range 0-255.
+    :param value: The threshold level in the range 0-255. Values outside this range will be clamped.
     """
     ...
 

From 936b1723bb85541d66b82e3976a4477e1c7e1322 Mon Sep 17 00:00:00 2001
From: Grace <grace@microbit.org>
Date: Fri, 12 Apr 2024 17:13:59 +0100
Subject: [PATCH 17/25] Suggested ammendments for set_threshold doc

---
 .../typeshed/stdlib/microbit/microphone.pyi   | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/lang/en/typeshed/stdlib/microbit/microphone.pyi b/lang/en/typeshed/stdlib/microbit/microphone.pyi
index 08f8a79..0f68887 100644
--- a/lang/en/typeshed/stdlib/microbit/microphone.pyi
+++ b/lang/en/typeshed/stdlib/microbit/microphone.pyi
@@ -54,15 +54,16 @@ def set_threshold(event: SoundEvent, value: int) -> None:
 
     Example: ``microphone.set_threshold(SoundEvent.LOUD, 250)``
 
-    The ``SoundEvent.LOUD`` event will be triggered when the sound level
-    crosses this threshold upwards (from "quiet" to "loud"),
-    and ``SoundEvent.QUIET`` event is triggered when crossing the threshold
-    downwards (from "loud" to "quiet").
-
-    If the ``SoundEvent.LOUD`` value set is lower than ``SoundEvent.QUIET``,
-    then "quiet" threshold will be decreased to one unit below the "loud"
-    threshold. If the ``SoundEvent.QUIET`` value is set higher than
-    ``SoundEvent.LOUD``, then the "loud" threshold will be set one unit above.
+    The ``SoundEvent.LOUD`` event is triggered when the sound level crosses the 
+    threshold from "quiet" to "loud", and the ``SoundEvent.QUIET`` event is 
+    triggered when the sound level crosses from "loud" to "quiet".
+
+    If the ``SoundEvent.LOUD`` threshold is set lower than the 
+    ``SoundEvent.QUIET`` threshold, then the ``SoundEvent.QUIET`` threshold 
+    will decrease by one unit below the ``SoundEvent.LOUD`` threshold. If the 
+    ``SoundEvent.QUIET`` threshold is set higher than the ``SoundEvent.LOUD``
+    threshold, then the ``SoundEvent.LOUD`` threshold will increase by one unit 
+    above the ``SoundEvent.QUIET`` threshold.
 
     :param event: A sound event, such as ``SoundEvent.LOUD`` or ``SoundEvent.QUIET``.
     :param value: The threshold level in the range 0-255. Values outside this range will be clamped.

From 70578370697bcf25df0aa857184efcfe2f8b2c52 Mon Sep 17 00:00:00 2001
From: Grace <grace@microbit.org>
Date: Mon, 15 Apr 2024 12:52:55 +0100
Subject: [PATCH 18/25] Update audio.sound_level doc

---
 lang/en/typeshed/stdlib/microbit/audio.pyi | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lang/en/typeshed/stdlib/microbit/audio.pyi b/lang/en/typeshed/stdlib/microbit/audio.pyi
index 4cd2ac4..3dc244a 100644
--- a/lang/en/typeshed/stdlib/microbit/audio.pyi
+++ b/lang/en/typeshed/stdlib/microbit/audio.pyi
@@ -29,11 +29,11 @@ def is_playing() -> bool:
     ...
 
 def sound_level() -> int:
-    """Returns the average intensity of the sound played.
+    """Returns the sound pressure level produced by audio currently being played.
 
     Example: ``audio.sound_level()``
 
-    :return: A number between 0 and 254, being the average intensity of the sound played from the most recent chunk of data."""
+    :return: A representation of the output sound pressure level in the range 0 to 255."""
     ...
 
 def stop() -> None:

From f4c9898bfb9c77aeb74056b9f47b6f6706842bb9 Mon Sep 17 00:00:00 2001
From: Grace <grace@microbit.org>
Date: Fri, 3 May 2024 15:37:20 +0100
Subject: [PATCH 19/25] Add microphone sound_level_db doc

---
 lang/en/typeshed/stdlib/microbit/microphone.pyi | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/lang/en/typeshed/stdlib/microbit/microphone.pyi b/lang/en/typeshed/stdlib/microbit/microphone.pyi
index 0f68887..368e5dc 100644
--- a/lang/en/typeshed/stdlib/microbit/microphone.pyi
+++ b/lang/en/typeshed/stdlib/microbit/microphone.pyi
@@ -71,7 +71,7 @@ def set_threshold(event: SoundEvent, value: int) -> None:
     ...
 
 def sound_level() -> int:
-    """Get the sound pressure level.
+    """Get the sound pressure level in the range 0 to 255.
 
     Example: ``microphone.sound_level()``
 
@@ -79,6 +79,15 @@ def sound_level() -> int:
     """
     ...
 
+def sound_level_db() -> int:
+    """Get the sound pressure level in decibels.
+
+    Example: ``microphone.sound_level_db()``
+
+    :return: A representation of the sound pressure level in decibels (dB).
+    """
+    ...
+
 def record(duration: int, rate: int = 7812) -> AudioFrame:
     """Record sound into an ``AudioFrame`` for the amount of time indicated by
     ``duration`` at the sampling rate indicated by ``rate``.

From 263b68946ec04f62be71ed673c253f838cd5c257 Mon Sep 17 00:00:00 2001
From: Matt Hillsdon <matt.hillsdon@microbit.org>
Date: Tue, 20 Aug 2024 17:52:10 +0100
Subject: [PATCH 20/25] Initial stubs updates

We'll have to do something about dunder docs as they're really key to
this API
---
 lang/en/typeshed/stdlib/audio.pyi          |   2 +
 lang/en/typeshed/stdlib/microbit/audio.pyi | 166 ++++++++++++++++-----
 2 files changed, 130 insertions(+), 38 deletions(-)

diff --git a/lang/en/typeshed/stdlib/audio.pyi b/lang/en/typeshed/stdlib/audio.pyi
index b1d39c7..be1d13d 100644
--- a/lang/en/typeshed/stdlib/audio.pyi
+++ b/lang/en/typeshed/stdlib/audio.pyi
@@ -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,
 )
diff --git a/lang/en/typeshed/stdlib/microbit/audio.pyi b/lang/en/typeshed/stdlib/microbit/audio.pyi
index 3dc244a..5a625cf 100644
--- a/lang/en/typeshed/stdlib/microbit/audio.pyi
+++ b/lang/en/typeshed/stdlib/microbit/audio.pyi
@@ -2,7 +2,7 @@
 """
 
 from ..microbit import MicroBitDigitalPin, Sound, pin0
-from typing import ClassVar, Iterable, Union
+from typing import ClassVar, Iterable, Optional, Union
 
 def play(
     source: Union[AudioFrame, Iterable[AudioFrame], Sound, SoundEffect],
@@ -143,63 +143,159 @@ class SoundEffect:
         :return: A copy of the SoundEffect.
         """
 
-class AudioFrame:
-    """An ``AudioFrame`` object is a list of samples, each of which is an unsigned byte
-    (whole number between 0 and 255).
 
-    The number of samples in an AudioFrame will depend on the
-    ``rate`` (number of samples per second) and ``duration`` parameters.
-    The total number of samples will always be a round up multiple of 32.
+class AudioRecording:
+    """The ``AudioRecording`` object contains audio data and the sampling rate
+    associated to it (V2 only).
 
-    On micro:bit V1 the constructor does not take any arguments,
-    and an AudioFrame instance is always 32 bytes.
+    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.
 
-    For example, playing 32 samples at 7812 Hz takes just over 4 milliseconds
-    (1/7812.5 * 32 = 0.004096 = 4096 microseconds).
-
-    Example::
+    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.
 
-        frame = AudioFrame()
-        for i in range(len(frame)):
-            frame[i] = 252 - i * 8
+    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 = 7812
+        rate: int = 11_000
     ):
-        """Create a new ``AudioFrame``.
+        """Create a new ``AudioRecording``.
 
-        Example: ``my_recording = AudioFrame(duration=5000)``
+        Example: ``my_recording = AudioRecording(duration=5000)``
 
-        :param duration: Indicates how many milliseconds of audio this instance can store (V2 only).
-        :param rate: The sampling rate at which data will be stored via the microphone, or played via the ``audio.play()`` function (V2 only).
+        :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) -> None:
+        """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``.
+        """
+    def __len__(self) -> int: ...
+    def __setitem__(self, key: int, value: int) -> None: ...
+    def __getitem__(self, key: int) -> int: ...
+    def __add__(self, v: AudioRecording) -> AudioRecording: ...
+    def __iadd__(self, v: AudioRecording) -> AudioRecording: ...
+    def __sub__(self, v: AudioRecording) -> AudioRecording: ...
+    def __isub__(self, v: AudioRecording) -> AudioRecording: ...
+    def __mul__(self, v: float) -> AudioRecording: ...
+    def __imul__(self, v: float) -> AudioRecording: ...
+
+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
-        ``AudioFrame`` instance (V2 only).
+        ``AudioTrack`` instance.
 
-        Example: ``my_frame.set_rate(7812)``
 
-        For recording from the microphone, increasing the sampling rate
-        increases the sound quality, but reduces the length of audio it
-        can store.
+        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.
 
-        During playback, increasing the sampling rate speeds up the sound
-        and decreasing it slows it down.
+        Example: ``my_track.set_rate(22_000)``
         """
 
     def get_rate(self) -> int:
         """Get the sampling rate associated with the data in the
-        ``AudioFrame`` instance (V2 only).
+        ``AudioRecording`` instance.
 
-        Example: ``current_rate = my_frame.get_rate()``
+        Example: ``current_rate = my_track.get_rate()``
 
-         :return: The configured sampling rate for this ``AudioFrame`` instance.
+         :return: The configured sample rate.
         """
 
+
+    def __len__(self) -> int: ...
+    def __setitem__(self, key: int, value: int) -> None: ...
+    def __getitem__(self, key: int) -> int: ...
+    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).
+
+    It takes just over 4 ms to play a single frame.
+
+    Example::
+
+        frame = AudioFrame()
+        for i in range(len(frame)):
+            frame[i] = 252 - i * 8
+    """
+
     def copyfrom(self, other: AudioFrame) -> None:
         """Overwrite the data in this ``AudioFrame`` with the data from another ``AudioFrame`` instance.
 
@@ -209,10 +305,4 @@ class AudioFrame:
         """
     def __len__(self) -> int: ...
     def __setitem__(self, key: int, value: int) -> None: ...
-    def __getitem__(self, key: int) -> int: ...
-    def __add__(self, v: AudioFrame) -> AudioFrame: ...
-    def __iadd__(self, v: AudioFrame) -> AudioFrame: ...
-    def __sub__(self, v: AudioFrame) -> AudioFrame: ...
-    def __isub__(self, v: AudioFrame) -> AudioFrame: ...
-    def __mul__(self, v: float) -> AudioFrame: ...
-    def __imul__(self, v: float) -> AudioFrame: ...
+    def __getitem__(self, key: int) -> int: ...
\ No newline at end of file

From 3826bceb0e8f287455bf60f0bf195bf7be5353ef Mon Sep 17 00:00:00 2001
From: Matt Hillsdon <matt.hillsdon@microbit.org>
Date: Wed, 21 Aug 2024 09:56:45 +0100
Subject: [PATCH 21/25] Corrections

---
 lang/en/typeshed/stdlib/microbit/audio.pyi | 11 +----------
 1 file changed, 1 insertion(+), 10 deletions(-)

diff --git a/lang/en/typeshed/stdlib/microbit/audio.pyi b/lang/en/typeshed/stdlib/microbit/audio.pyi
index 5a625cf..6badf18 100644
--- a/lang/en/typeshed/stdlib/microbit/audio.pyi
+++ b/lang/en/typeshed/stdlib/microbit/audio.pyi
@@ -187,7 +187,7 @@ class AudioRecording:
         :return: A copy of the ``AudioRecording``.
         """
 
-    def track(self, start_ms: int = 0, end_ms: int = -1) -> None:
+    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)``
@@ -196,15 +196,6 @@ class AudioRecording:
         :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``.
         """
-    def __len__(self) -> int: ...
-    def __setitem__(self, key: int, value: int) -> None: ...
-    def __getitem__(self, key: int) -> int: ...
-    def __add__(self, v: AudioRecording) -> AudioRecording: ...
-    def __iadd__(self, v: AudioRecording) -> AudioRecording: ...
-    def __sub__(self, v: AudioRecording) -> AudioRecording: ...
-    def __isub__(self, v: AudioRecording) -> AudioRecording: ...
-    def __mul__(self, v: float) -> AudioRecording: ...
-    def __imul__(self, v: float) -> AudioRecording: ...
 
 class AudioTrack:
     """ The ``AudioTrack`` object points to the data provided by the input buffer,

From 6dcc5ab49ef16006547f3e77b549448e13f264a9 Mon Sep 17 00:00:00 2001
From: Matt Hillsdon <matt.hillsdon@microbit.org>
Date: Wed, 21 Aug 2024 13:38:15 +0100
Subject: [PATCH 22/25] Corrections

---
 lang/en/typeshed/stdlib/microbit/audio.pyi | 23 +++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/lang/en/typeshed/stdlib/microbit/audio.pyi b/lang/en/typeshed/stdlib/microbit/audio.pyi
index 6badf18..e385d71 100644
--- a/lang/en/typeshed/stdlib/microbit/audio.pyi
+++ b/lang/en/typeshed/stdlib/microbit/audio.pyi
@@ -2,7 +2,7 @@
 """
 
 from ..microbit import MicroBitDigitalPin, Sound, pin0
-from typing import ClassVar, Iterable, Optional, Union
+from typing import ClassVar, Iterable, Optional, Union, overload
 
 def play(
     source: Union[AudioFrame, Iterable[AudioFrame], Sound, SoundEffect],
@@ -262,10 +262,27 @@ class AudioTrack:
          :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: ...
-    def __setitem__(self, key: int, value: int) -> None: ...
-    def __getitem__(self, key: int) -> 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: ...

From fc8537799543fb924b5c5813cb6ff30a73c7df88 Mon Sep 17 00:00:00 2001
From: Matt Hillsdon <matt.hillsdon@microbit.org>
Date: Wed, 21 Aug 2024 17:38:55 +0100
Subject: [PATCH 23/25] Microphone stubs

---
 .../typeshed/stdlib/microbit/microphone.pyi   | 27 ++++++++++---------
 1 file changed, 14 insertions(+), 13 deletions(-)

diff --git a/lang/en/typeshed/stdlib/microbit/microphone.pyi b/lang/en/typeshed/stdlib/microbit/microphone.pyi
index 368e5dc..f7cefa3 100644
--- a/lang/en/typeshed/stdlib/microbit/microphone.pyi
+++ b/lang/en/typeshed/stdlib/microbit/microphone.pyi
@@ -1,9 +1,9 @@
 """Respond to sound using the built-in microphone (V2 only).
 """
 
-from typing import Optional, Tuple
+from typing import Optional, Tuple, Union
 from ..microbit import SoundEvent
-from ..microbit.audio import AudioFrame
+from ..microbit.audio import AudioRecording, AudioTrack
 
 def current_event() -> Optional[SoundEvent]:
     """Get the last recorded sound event
@@ -88,12 +88,10 @@ def sound_level_db() -> int:
     """
     ...
 
-def record(duration: int, rate: int = 7812) -> AudioFrame:
-    """Record sound into an ``AudioFrame`` for the amount of time indicated by
+def record(duration: int, rate: int = 11_000) -> AudioRecording:
+    """Record sound into an ``AudioRecording`` for the amount of time indicated by
     ``duration`` at the sampling rate indicated by ``rate``.
 
-    Example: ``my_frame = microphone.record(3000)``
-
     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.
@@ -105,20 +103,23 @@ def record(duration: int, rate: int = 7812) -> AudioFrame:
 
     :param duration: How long to record in milliseconds.
     :param rate: Number of samples to capture per second.
-    :return: An ``AudioFrame`` with the sound samples.
+    :returns: An ``AudioRecording`` with the sound samples.
     """
     ...
 
-def record_into(buffer: AudioFrame, rate: int = 7812, wait: bool = True) -> None:
-    """Record sound into an existing ``AudioFrame`` until it is filled,
-    or the ``stop_recording()`` function is called.
+def record_into(buffer: Union[AudioRecording, AudioTrack], wait: bool = True) -> AudioTrack:
+    """Record sound into an existing ``AudioRecording`` or ``AudioTrack``
+    until it is filled, or the ``stop_recording()`` function is called.
 
-    Example: ``microphone.record_into(my_frame)``
+    This function also returns an ``AudioTrack`` created from the provided
+    input buffer, which length matches the recording duration.
+    This is useful when recording with ``wait`` set to ``False``, and the
+    recording is stopped before the input buffer is filled.
 
-    :param buffer: An ``AudioFrame`` to record sound.
-    :param rate: Number of samples to capture per second.
+    :param buffer: ``AudioRecording`` or ``AudioTrack`` to record sound into.
     :param wait: When set to ``True`` it blocks until the recording is
         done, if it is set to ``False`` it will run in the background.
+    :returns: An ``AudioTrack`` which ends where the recording ended.
     """
     ...
 

From 69aaab7945dcf34c8469cac2db3f6646b8f0e4c3 Mon Sep 17 00:00:00 2001
From: Matt Hillsdon <matt.hillsdon@microbit.org>
Date: Wed, 21 Aug 2024 17:43:12 +0100
Subject: [PATCH 24/25] Update play stubs

---
 lang/en/typeshed/stdlib/microbit/audio.pyi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lang/en/typeshed/stdlib/microbit/audio.pyi b/lang/en/typeshed/stdlib/microbit/audio.pyi
index e385d71..ae4bd95 100644
--- a/lang/en/typeshed/stdlib/microbit/audio.pyi
+++ b/lang/en/typeshed/stdlib/microbit/audio.pyi
@@ -5,7 +5,7 @@ from ..microbit import MicroBitDigitalPin, Sound, pin0
 from typing import ClassVar, Iterable, Optional, Union, overload
 
 def play(
-    source: Union[AudioFrame, 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,

From 91eb337c312c18043da4c05dd61dc3c63f81139d Mon Sep 17 00:00:00 2001
From: Matt Hillsdon <matt.hillsdon@microbit.org>
Date: Wed, 21 Aug 2024 17:46:21 +0100
Subject: [PATCH 25/25] Docs for audio.play

---
 lang/en/typeshed/stdlib/microbit/audio.pyi | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lang/en/typeshed/stdlib/microbit/audio.pyi b/lang/en/typeshed/stdlib/microbit/audio.pyi
index ae4bd95..028419e 100644
--- a/lang/en/typeshed/stdlib/microbit/audio.pyi
+++ b/lang/en/typeshed/stdlib/microbit/audio.pyi
@@ -10,11 +10,11 @@ def play(
     pin: MicroBitDigitalPin = pin0,
     return_pin: Union[MicroBitDigitalPin, None] = None,
 ) -> None:
-    """Play a built-in sound, sound effect or audio samples using ``AudioFrame``.
+    """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 ``AudioFrame`` object or 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.