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/__init__.pyi b/lang/en/typeshed/stdlib/microbit/__init__.pyi index 5e03529..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 @@ -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 - `_ - 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. @@ -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 + `_ + does not require you to make a ground connection as part of a circuit. + :param value: ``CAPACITIVE`` or ``RESISTIVE`` from the relevant pin. """ ... diff --git a/lang/en/typeshed/stdlib/microbit/audio.pyi b/lang/en/typeshed/stdlib/microbit/audio.pyi index 3b1e327..028419e 100644 --- a/lang/en/typeshed/stdlib/microbit/audio.pyi +++ b/lang/en/typeshed/stdlib/microbit/audio.pyi @@ -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. @@ -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. @@ -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). @@ -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: ... \ No newline at end of file diff --git a/lang/en/typeshed/stdlib/microbit/microphone.pyi b/lang/en/typeshed/stdlib/microbit/microphone.pyi index 68e8f3a..f7cefa3 100644 --- a/lang/en/typeshed/stdlib/microbit/microphone.pyi +++ b/lang/en/typeshed/stdlib/microbit/microphone.pyi @@ -1,8 +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 AudioRecording, AudioTrack def current_event() -> Optional[SoundEvent]: """Get the last recorded sound event @@ -53,18 +54,108 @@ 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 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. + :param value: The threshold level in the range 0-255. Values outside this range will be clamped. """ ... def sound_level() -> int: - """Get the sound pressure level. + """Get the sound pressure level in the range 0 to 255. Example: ``microphone.sound_level()`` :return: A representation of the sound pressure level in the range 0 to 255. """ ... + +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 = 11_000) -> AudioRecording: + """Record sound into an ``AudioRecording`` 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 ``AudioRecording`` with the sound samples. + """ + ... + +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. + + 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: ``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. + """ + ... + +def is_recording() -> bool: + """Checks whether the microphone is currently recording. + + 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()`` + """ + ... + +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. + + 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. + """ + ... \ No newline at end of file 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