Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
73 changes: 73 additions & 0 deletions shared-bindings/usb_audio/USBMicrophone.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,75 @@ MP_DEFINE_CONST_FUN_OBJ_1(usb_audio_usbmicrophone_get_paused_obj, usb_audio_usbm
MP_PROPERTY_GETTER(usb_audio_usbmicrophone_paused_obj,
(mp_obj_t)&usb_audio_usbmicrophone_get_paused_obj);

//| host_mute: bool
//| """True when the host has muted this microphone. (read-only)"""
//|
static mp_obj_t usb_audio_usbmicrophone_obj_get_host_mute(mp_obj_t self_in) {
usb_audio_usbmicrophone_obj_t *self = MP_OBJ_TO_PTR(self_in);
check_for_deinit(self);
return mp_obj_new_bool(usb_audio_host_mute(USB_AUDIO_DIR_MICROPHONE));
}
MP_DEFINE_CONST_FUN_OBJ_1(usb_audio_usbmicrophone_get_host_mute_obj,
usb_audio_usbmicrophone_obj_get_host_mute);

MP_PROPERTY_GETTER(usb_audio_usbmicrophone_host_mute_obj,
(mp_obj_t)&usb_audio_usbmicrophone_get_host_mute_obj);

//| host_volume: float
//| """The volume the host has set, in decibels from ``-60.0`` to ``0.0``. (read-only)"""
//|
static mp_obj_t usb_audio_usbmicrophone_obj_get_host_volume(mp_obj_t self_in) {
usb_audio_usbmicrophone_obj_t *self = MP_OBJ_TO_PTR(self_in);
check_for_deinit(self);
return mp_obj_new_float(usb_audio_host_volume(USB_AUDIO_DIR_MICROPHONE));
}
MP_DEFINE_CONST_FUN_OBJ_1(usb_audio_usbmicrophone_get_host_volume_obj,
usb_audio_usbmicrophone_obj_get_host_volume);

MP_PROPERTY_GETTER(usb_audio_usbmicrophone_host_volume_obj,
(mp_obj_t)&usb_audio_usbmicrophone_get_host_volume_obj);

//| host_gain: float
//| """`host_volume` and `host_mute` as a linear factor from ``0.0`` to ``1.0``. (read-only)"""
//|
static mp_obj_t usb_audio_usbmicrophone_obj_get_host_gain(mp_obj_t self_in) {
usb_audio_usbmicrophone_obj_t *self = MP_OBJ_TO_PTR(self_in);
check_for_deinit(self);
return mp_obj_new_float(usb_audio_host_gain(USB_AUDIO_DIR_MICROPHONE));
}
MP_DEFINE_CONST_FUN_OBJ_1(usb_audio_usbmicrophone_get_host_gain_obj,
usb_audio_usbmicrophone_obj_get_host_gain);

MP_PROPERTY_GETTER(usb_audio_usbmicrophone_host_gain_obj,
(mp_obj_t)&usb_audio_usbmicrophone_get_host_gain_obj);

//| apply_host_volume: bool
//| """Whether the board scales the samples it sends by `host_gain` itself.
//| `False` by default, leaving the level to your code; `True` makes the host's
//| recording level and mute work on their own."""
//|
//|
static mp_obj_t usb_audio_usbmicrophone_obj_get_apply_host_volume(mp_obj_t self_in) {
usb_audio_usbmicrophone_obj_t *self = MP_OBJ_TO_PTR(self_in);
check_for_deinit(self);
return mp_obj_new_bool(usb_audio_apply_host_volume(USB_AUDIO_DIR_MICROPHONE));
}
MP_DEFINE_CONST_FUN_OBJ_1(usb_audio_usbmicrophone_get_apply_host_volume_obj,
usb_audio_usbmicrophone_obj_get_apply_host_volume);

static mp_obj_t usb_audio_usbmicrophone_obj_set_apply_host_volume(mp_obj_t self_in, mp_obj_t value) {
usb_audio_usbmicrophone_obj_t *self = MP_OBJ_TO_PTR(self_in);
check_for_deinit(self);
usb_audio_set_apply_host_volume(USB_AUDIO_DIR_MICROPHONE, mp_obj_is_true(value));
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(usb_audio_usbmicrophone_set_apply_host_volume_obj,
usb_audio_usbmicrophone_obj_set_apply_host_volume);

MP_PROPERTY_GETSET(usb_audio_usbmicrophone_apply_host_volume_obj,
(mp_obj_t)&usb_audio_usbmicrophone_get_apply_host_volume_obj,
(mp_obj_t)&usb_audio_usbmicrophone_set_apply_host_volume_obj);

static const mp_rom_map_elem_t usb_audio_usbmicrophone_locals_dict_table[] = {
// Methods
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&usb_audio_usbmicrophone_deinit_obj) },
Expand All @@ -167,6 +236,10 @@ static const mp_rom_map_elem_t usb_audio_usbmicrophone_locals_dict_table[] = {
// Properties
{ MP_ROM_QSTR(MP_QSTR_playing), MP_ROM_PTR(&usb_audio_usbmicrophone_playing_obj) },
{ MP_ROM_QSTR(MP_QSTR_paused), MP_ROM_PTR(&usb_audio_usbmicrophone_paused_obj) },
{ MP_ROM_QSTR(MP_QSTR_host_mute), MP_ROM_PTR(&usb_audio_usbmicrophone_host_mute_obj) },
{ MP_ROM_QSTR(MP_QSTR_host_volume), MP_ROM_PTR(&usb_audio_usbmicrophone_host_volume_obj) },
{ MP_ROM_QSTR(MP_QSTR_host_gain), MP_ROM_PTR(&usb_audio_usbmicrophone_host_gain_obj) },
{ MP_ROM_QSTR(MP_QSTR_apply_host_volume), MP_ROM_PTR(&usb_audio_usbmicrophone_apply_host_volume_obj) },
};
static MP_DEFINE_CONST_DICT(usb_audio_usbmicrophone_locals_dict, usb_audio_usbmicrophone_locals_dict_table);

Expand Down
69 changes: 69 additions & 0 deletions shared-bindings/usb_audio/USBSpeaker.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,71 @@ MP_DEFINE_CONST_FUN_OBJ_1(usb_audio_usbspeaker_get_connected_obj, usb_audio_usbs
MP_PROPERTY_GETTER(usb_audio_usbspeaker_connected_obj,
(mp_obj_t)&usb_audio_usbspeaker_get_connected_obj);

//| host_mute: bool
//| """True when the host has muted this speaker. (read-only)"""
//|
static mp_obj_t usb_audio_usbspeaker_obj_get_host_mute(mp_obj_t self_in) {
usb_audio_usbspeaker_obj_t *self = MP_OBJ_TO_PTR(self_in);
check_for_deinit(self);
return mp_obj_new_bool(usb_audio_host_mute(USB_AUDIO_DIR_SPEAKER));
}
MP_DEFINE_CONST_FUN_OBJ_1(usb_audio_usbspeaker_get_host_mute_obj, usb_audio_usbspeaker_obj_get_host_mute);

MP_PROPERTY_GETTER(usb_audio_usbspeaker_host_mute_obj,
(mp_obj_t)&usb_audio_usbspeaker_get_host_mute_obj);

//| host_volume: float
//| """The volume the host has set, in decibels from ``-60.0`` to ``0.0``. (read-only)"""
//|
static mp_obj_t usb_audio_usbspeaker_obj_get_host_volume(mp_obj_t self_in) {
usb_audio_usbspeaker_obj_t *self = MP_OBJ_TO_PTR(self_in);
check_for_deinit(self);
return mp_obj_new_float(usb_audio_host_volume(USB_AUDIO_DIR_SPEAKER));
}
MP_DEFINE_CONST_FUN_OBJ_1(usb_audio_usbspeaker_get_host_volume_obj, usb_audio_usbspeaker_obj_get_host_volume);

MP_PROPERTY_GETTER(usb_audio_usbspeaker_host_volume_obj,
(mp_obj_t)&usb_audio_usbspeaker_get_host_volume_obj);

//| host_gain: float
//| """`host_volume` and `host_mute` as a linear factor from ``0.0`` to ``1.0``. (read-only)"""
//|
static mp_obj_t usb_audio_usbspeaker_obj_get_host_gain(mp_obj_t self_in) {
usb_audio_usbspeaker_obj_t *self = MP_OBJ_TO_PTR(self_in);
check_for_deinit(self);
return mp_obj_new_float(usb_audio_host_gain(USB_AUDIO_DIR_SPEAKER));
}
MP_DEFINE_CONST_FUN_OBJ_1(usb_audio_usbspeaker_get_host_gain_obj, usb_audio_usbspeaker_obj_get_host_gain);

MP_PROPERTY_GETTER(usb_audio_usbspeaker_host_gain_obj,
(mp_obj_t)&usb_audio_usbspeaker_get_host_gain_obj);

//| apply_host_volume: bool
//| """Whether the board scales the samples it receives by `host_gain` itself.
//| `False` by default, leaving the level to your code; `True` makes the host's
//| volume slider and mute work on their own."""
//|
static mp_obj_t usb_audio_usbspeaker_obj_get_apply_host_volume(mp_obj_t self_in) {
usb_audio_usbspeaker_obj_t *self = MP_OBJ_TO_PTR(self_in);
check_for_deinit(self);
return mp_obj_new_bool(usb_audio_apply_host_volume(USB_AUDIO_DIR_SPEAKER));
}
MP_DEFINE_CONST_FUN_OBJ_1(usb_audio_usbspeaker_get_apply_host_volume_obj,
usb_audio_usbspeaker_obj_get_apply_host_volume);

static mp_obj_t usb_audio_usbspeaker_obj_set_apply_host_volume(mp_obj_t self_in, mp_obj_t value) {
usb_audio_usbspeaker_obj_t *self = MP_OBJ_TO_PTR(self_in);
check_for_deinit(self);
usb_audio_set_apply_host_volume(USB_AUDIO_DIR_SPEAKER, mp_obj_is_true(value));
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(usb_audio_usbspeaker_set_apply_host_volume_obj,
usb_audio_usbspeaker_obj_set_apply_host_volume);

MP_PROPERTY_GETSET(usb_audio_usbspeaker_apply_host_volume_obj,
(mp_obj_t)&usb_audio_usbspeaker_get_apply_host_volume_obj,
(mp_obj_t)&usb_audio_usbspeaker_set_apply_host_volume_obj);

//| sample_rate: int
//| """The sample rate negotiated with the host in ``boot.py``. (read-only)"""
//|
Expand All @@ -148,6 +213,10 @@ static const mp_rom_map_elem_t usb_audio_usbspeaker_locals_dict_table[] = {

// Properties
{ MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&usb_audio_usbspeaker_connected_obj) },
{ MP_ROM_QSTR(MP_QSTR_host_mute), MP_ROM_PTR(&usb_audio_usbspeaker_host_mute_obj) },
{ MP_ROM_QSTR(MP_QSTR_host_volume), MP_ROM_PTR(&usb_audio_usbspeaker_host_volume_obj) },
{ MP_ROM_QSTR(MP_QSTR_host_gain), MP_ROM_PTR(&usb_audio_usbspeaker_host_gain_obj) },
{ MP_ROM_QSTR(MP_QSTR_apply_host_volume), MP_ROM_PTR(&usb_audio_usbspeaker_apply_host_volume_obj) },
AUDIOSAMPLE_FIELDS,
};
static MP_DEFINE_CONST_DICT(usb_audio_usbspeaker_locals_dict, usb_audio_usbspeaker_locals_dict_table);
Expand Down
15 changes: 13 additions & 2 deletions shared-bindings/usb_audio/__init__.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,21 @@
//| Audio Class (UAC2) microphone: the board is the audio *source* and streams
//| samples to the host over a USB isochronous IN endpoint.
//|
//| This mode requires 2 IN endpoints and 2 interfaces.
//| A microphone takes one isochronous IN endpoint and two interfaces, a speaker
//| one isochronous OUT endpoint and two interfaces, and a headset one of each
//| and three interfaces.
//| Generally, microcontrollers have a limit on the number of endpoints. If you exceed the number
//| of endpoints, CircuitPython will automatically enter Safe Mode. Even in this case, you may be
//| able to enable USB audio by also disabling other USB functions, such as
//| `usb_hid` or `usb_midi`.
//|
//| The host's mute and volume are reported by ``host_mute``, ``host_volume`` and
//| ``host_gain`` on `usb_microphone` and `usb_speaker`, and are not applied to the
//| samples unless you ask for it. Either follow ``host_gain`` yourself, for
//| instance by assigning it to an `audiomixer.MixerVoice` level, or set
//| ``apply_host_volume`` to `True` to have the board scale the samples, which is
//| how a plain sound card behaves.
//|
//| To enable this mode, you must configure the audio format in ``boot.py`` and then
//| use the `usb_microphone` singleton instance in ``code.py``.
//|
Expand Down Expand Up @@ -110,7 +119,9 @@ static mp_obj_t usb_audio_enable(size_t n_args, const mp_obj_t *pos_args, mp_map
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);

mp_int_t sample_rate = mp_arg_validate_int_range(args[ARG_sample_rate].u_int, 1, USB_AUDIO_MAX_SAMPLE_RATE, MP_QSTR_sample_rate);
// The microphone hands the host one millisecond of audio at a time, so a
// rate below 1 kHz would give it nothing to send.
mp_int_t sample_rate = mp_arg_validate_int_range(args[ARG_sample_rate].u_int, 1000, USB_AUDIO_MAX_SAMPLE_RATE, MP_QSTR_sample_rate);
mp_int_t channel_count = mp_arg_validate_int_range(args[ARG_channel_count].u_int, 1, USB_AUDIO_N_CHANNELS, MP_QSTR_channel_count);
bool microphone = args[ARG_microphone].u_bool;
bool speaker = args[ARG_speaker].u_bool;
Expand Down
Loading
Loading