Skip to content

Commit bd9aca2

Browse files
authored
Merge pull request #7862 from jepler/synthio-envelope
Synthio envelope
2 parents 2b17fda + b33c9f6 commit bd9aca2

File tree

27 files changed

+1433
-187
lines changed

27 files changed

+1433
-187
lines changed

ports/atmel-samd/boards/pewpew_m4/mpconfigboard.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ CIRCUITPY_KEYPAD_SHIFTREGISTERKEYS = 0
4848
CIRCUITPY_KEYPAD_KEYMATRIX = 0
4949
CIRCUITPY_MATH = 1
5050
CIRCUITPY_STAGE = 1
51-
CIRCUITPY_SYNTHIO = 1
51+
CIRCUITPY_SYNTHIO = 0
5252
CIRCUITPY_ZLIB = 1
5353

5454
FROZEN_MPY_DIRS += $(TOP)/frozen/circuitpython-stage/pewpew_m4

ports/stm/boards/thunderpack_v11/mpconfigboard.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ LD_FILE = boards/STM32F411_nvm.ld
1919
CIRCUITPY_AESIO = 0
2020
CIRCUITPY_BITMAPTOOLS = 0
2121
CIRCUITPY_BLEIO_HCI = 0
22+
CIRCUITPY_SYNTHIO = 0
2223
CIRCUITPY_VECTORIO = 0
2324
CIRCUITPY_ULAB = 0
2425
CIRCUITPY_ZLIB = 0

py/argcheck.c

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,11 +186,26 @@ mp_int_t mp_arg_validate_int_range(mp_int_t i, mp_int_t min, mp_int_t max, qstr
186186
return i;
187187
}
188188

189+
mp_float_t mp_arg_validate_type_float(mp_obj_t obj, qstr arg_name) {
190+
mp_float_t a_float;
191+
if (!mp_obj_get_float_maybe(obj, &a_float)) {
192+
mp_raise_TypeError_varg(translate("%q must be of type %q, not %q"), arg_name, MP_QSTR_float, mp_obj_get_type(obj)->name);
193+
}
194+
return a_float;
195+
}
196+
197+
void mp_arg_validate_obj_float_range(mp_obj_t float_in, mp_int_t min, mp_int_t max, qstr arg_name) {
198+
const mp_float_t f = mp_arg_validate_type_float(float_in, arg_name);
199+
if (f < (mp_float_t)min || f > (mp_float_t)max) {
200+
mp_raise_ValueError_varg(translate("%q must be %d-%d"), arg_name, min, max);
201+
}
202+
}
203+
189204
mp_float_t mp_arg_validate_obj_float_non_negative(mp_obj_t float_in, mp_float_t default_for_null, qstr arg_name) {
190205
const mp_float_t f = (float_in == MP_OBJ_NULL)
191206
? default_for_null
192-
: mp_obj_get_float(float_in);
193-
if (f <= (mp_float_t)0.0) {
207+
: mp_arg_validate_type_float(float_in, arg_name);
208+
if (f < (mp_float_t)0.0) {
194209
mp_raise_ValueError_varg(translate("%q must be >= %d"), arg_name, 0);
195210
}
196211
return f;

py/objarray.c

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131

3232
#include "py/runtime.h"
3333
#include "py/binary.h"
34+
#include "py/objproperty.h"
3435
#include "py/objstr.h"
3536
#include "py/objarray.h"
3637

@@ -270,15 +271,13 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(memoryview_cast_obj, memoryview_cast);
270271
#endif
271272

272273
#if MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE
273-
STATIC void memoryview_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
274-
if (dest[0] != MP_OBJ_NULL) {
275-
return;
276-
}
277-
if (attr == MP_QSTR_itemsize) {
278-
mp_obj_array_t *self = MP_OBJ_TO_PTR(self_in);
279-
dest[0] = MP_OBJ_NEW_SMALL_INT(mp_binary_get_size('@', self->typecode & TYPECODE_MASK, NULL));
280-
}
274+
STATIC mp_obj_t memoryview_itemsize_get(mp_obj_t self_in) {
275+
mp_obj_array_t *self = MP_OBJ_TO_PTR(self_in);
276+
return MP_OBJ_NEW_SMALL_INT(mp_binary_get_size('@', self->typecode & TYPECODE_MASK, NULL));
281277
}
278+
MP_DEFINE_CONST_FUN_OBJ_1(memoryview_itemsize_get_obj, memoryview_itemsize_get);
279+
280+
MP_PROPERTY_GETTER(memoryview_itemsize_obj, (mp_obj_t)&memoryview_itemsize_get_obj);
282281
#endif
283282

284283
#endif
@@ -785,9 +784,14 @@ const mp_obj_type_t mp_type_bytearray = {
785784

786785
#if MICROPY_PY_BUILTINS_MEMORYVIEW
787786

788-
#if MICROPY_CPYTHON_COMPAT
787+
#if MICROPY_CPYTHON_COMPAT || MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE
789788
STATIC const mp_rom_map_elem_t memoryview_locals_dict_table[] = {
789+
#if MICROPY_CPYTHON_COMPAT
790790
{ MP_ROM_QSTR(MP_QSTR_cast), MP_ROM_PTR(&memoryview_cast_obj) },
791+
#endif
792+
#if MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE
793+
{ MP_ROM_QSTR(MP_QSTR_itemsize), MP_ROM_PTR(&memoryview_itemsize_obj) },
794+
#endif
791795
};
792796

793797
STATIC MP_DEFINE_CONST_DICT(memoryview_locals_dict, memoryview_locals_dict_table);
@@ -798,12 +802,9 @@ const mp_obj_type_t mp_type_memoryview = {
798802
.flags = MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_EXTENDED,
799803
.name = MP_QSTR_memoryview,
800804
.make_new = memoryview_make_new,
801-
#if MICROPY_CPYTHON_COMPAT
805+
#if MICROPY_CPYTHON_COMPAT || MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE
802806
.locals_dict = (mp_obj_dict_t *)&memoryview_locals_dict,
803807
#endif
804-
#if MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE
805-
.attr = memoryview_attr,
806-
#endif
807808
MP_TYPE_EXTENDED_FIELDS(
808809
.getiter = array_iterator_new,
809810
.unary_op = array_unary_op,

py/runtime.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ mp_int_t mp_arg_validate_int_max(mp_int_t i, mp_int_t j, qstr arg_name);
103103
mp_int_t mp_arg_validate_int_range(mp_int_t i, mp_int_t min, mp_int_t max, qstr arg_name);
104104
#if MICROPY_PY_BUILTINS_FLOAT
105105
mp_float_t mp_arg_validate_obj_float_non_negative(mp_obj_t float_in, mp_float_t default_for_null, qstr arg_name);
106+
void mp_arg_validate_obj_float_range(mp_obj_t float_in, mp_int_t min, mp_int_t max, qstr arg_name);
107+
mp_float_t mp_arg_validate_type_float(mp_obj_t obj, qstr arg_name);
106108
#endif
107109
mp_uint_t mp_arg_validate_length_min(mp_uint_t length, mp_uint_t min, qstr arg_name);
108110
mp_uint_t mp_arg_validate_length_max(mp_uint_t length, mp_uint_t max, qstr arg_name);

shared-bindings/audiocore/__init__.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <stdint.h>
2828

2929
#include "py/obj.h"
30+
#include "py/gc.h"
3031
#include "py/runtime.h"
3132

3233
#include "shared-bindings/audiocore/__init__.h"
@@ -46,8 +47,23 @@ STATIC mp_obj_t audiocore_get_buffer(mp_obj_t sample_in) {
4647
mp_obj_t result[2] = {mp_obj_new_int_from_uint(gbr), mp_const_none};
4748

4849
if (gbr != GET_BUFFER_ERROR) {
50+
bool single_buffer, samples_signed;
51+
uint32_t max_buffer_length;
52+
uint8_t spacing;
53+
54+
uint8_t bits_per_sample = audiosample_bits_per_sample(sample_in);
55+
audiosample_get_buffer_structure(sample_in, false, &single_buffer, &samples_signed, &max_buffer_length, &spacing);
4956
// copies the data because the gc semantics of get_buffer are unclear
50-
result[1] = mp_obj_new_bytes(buffer, buffer_length);
57+
void *result_buf = gc_alloc(buffer_length, 0, false);
58+
memcpy(result_buf, buffer, buffer_length);
59+
char typecode =
60+
(bits_per_sample == 8 && samples_signed) ? 'b' :
61+
(bits_per_sample == 8 && !samples_signed) ? 'B' :
62+
(bits_per_sample == 16 && samples_signed) ? 'h' :
63+
(bits_per_sample == 16 && !samples_signed) ? 'H' :
64+
'b';
65+
size_t nitems = buffer_length / (bits_per_sample / 8);
66+
result[1] = mp_obj_new_memoryview(typecode, nitems, result_buf);
5167
}
5268

5369
return mp_obj_new_tuple(2, result);

shared-bindings/synthio/MidiTrack.c

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@
4444
//| tempo: int,
4545
//| *,
4646
//| sample_rate: int = 11025,
47-
//| waveform: ReadableBuffer = None
47+
//| waveform: Optional[ReadableBuffer] = None,
48+
//| envelope: Optional[Envelope] = None,
4849
//| ) -> None:
4950
//| """Create a MidiTrack from the given stream of MIDI events. Only "Note On" and "Note Off" events
5051
//| are supported; channel numbers and key velocities are ignored. Up to two notes may be on at the
@@ -54,6 +55,7 @@
5455
//| :param int tempo: Tempo of the streamed events, in MIDI ticks per second
5556
//| :param int sample_rate: The desired playback sample rate; higher sample rate requires more memory
5657
//| :param ReadableBuffer waveform: A single-cycle waveform. Default is a 50% duty cycle square wave. If specified, must be a ReadableBuffer of type 'h' (signed 16 bit)
58+
//| :param Envelope envelope: An object that defines the loudness of a note over time. The default envelope provides no ramping, voices turn instantly on and off.
5759
//|
5860
//| Simple melody::
5961
//|
@@ -72,12 +74,13 @@
7274
//| print("stopped")"""
7375
//| ...
7476
STATIC mp_obj_t synthio_miditrack_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
75-
enum { ARG_buffer, ARG_tempo, ARG_sample_rate, ARG_waveform };
77+
enum { ARG_buffer, ARG_tempo, ARG_sample_rate, ARG_waveform, ARG_envelope };
7678
static const mp_arg_t allowed_args[] = {
7779
{ MP_QSTR_buffer, MP_ARG_OBJ | MP_ARG_REQUIRED },
7880
{ MP_QSTR_tempo, MP_ARG_INT | MP_ARG_REQUIRED },
7981
{ MP_QSTR_sample_rate, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 11025} },
8082
{ MP_QSTR_waveform, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none } },
83+
{ MP_QSTR_envelope, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none } },
8184
};
8285
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
8386
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
@@ -96,7 +99,9 @@ STATIC mp_obj_t synthio_miditrack_make_new(const mp_obj_type_t *type, size_t n_a
9699
args[ARG_tempo].u_int,
97100
args[ARG_sample_rate].u_int,
98101
bufinfo_waveform.buf,
99-
bufinfo_waveform.len / 2);
102+
bufinfo_waveform.len / 2,
103+
args[ARG_envelope].u_obj
104+
);
100105

101106
return MP_OBJ_FROM_PTR(self);
102107
}
@@ -133,7 +138,7 @@ STATIC mp_obj_t synthio_miditrack_obj___exit__(size_t n_args, const mp_obj_t *ar
133138
}
134139
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(synthio_miditrack___exit___obj, 4, 4, synthio_miditrack_obj___exit__);
135140

136-
//| sample_rate: Optional[int]
141+
//| sample_rate: int
137142
//| """32 bit value that tells how quickly samples are played in Hertz (cycles per second)."""
138143
//|
139144
STATIC mp_obj_t synthio_miditrack_obj_get_sample_rate(mp_obj_t self_in) {
@@ -146,6 +151,23 @@ MP_DEFINE_CONST_FUN_OBJ_1(synthio_miditrack_get_sample_rate_obj, synthio_miditra
146151
MP_PROPERTY_GETTER(synthio_miditrack_sample_rate_obj,
147152
(mp_obj_t)&synthio_miditrack_get_sample_rate_obj);
148153

154+
//| error_location: Optional[int]
155+
//| """Offset, in bytes within the midi data, of a decoding error"""
156+
//|
157+
STATIC mp_obj_t synthio_miditrack_obj_get_error_location(mp_obj_t self_in) {
158+
synthio_miditrack_obj_t *self = MP_OBJ_TO_PTR(self_in);
159+
check_for_deinit(self);
160+
mp_int_t location = common_hal_synthio_miditrack_get_error_location(self);
161+
if (location >= 0) {
162+
return MP_OBJ_NEW_SMALL_INT(location);
163+
}
164+
return mp_const_none;
165+
}
166+
MP_DEFINE_CONST_FUN_OBJ_1(synthio_miditrack_get_error_location_obj, synthio_miditrack_obj_get_error_location);
167+
168+
MP_PROPERTY_GETTER(synthio_miditrack_error_location_obj,
169+
(mp_obj_t)&synthio_miditrack_get_error_location_obj);
170+
149171
STATIC const mp_rom_map_elem_t synthio_miditrack_locals_dict_table[] = {
150172
// Methods
151173
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&synthio_miditrack_deinit_obj) },
@@ -154,6 +176,7 @@ STATIC const mp_rom_map_elem_t synthio_miditrack_locals_dict_table[] = {
154176

155177
// Properties
156178
{ MP_ROM_QSTR(MP_QSTR_sample_rate), MP_ROM_PTR(&synthio_miditrack_sample_rate_obj) },
179+
{ MP_ROM_QSTR(MP_QSTR_error_location), MP_ROM_PTR(&synthio_miditrack_error_location_obj) },
157180
};
158181
STATIC MP_DEFINE_CONST_DICT(synthio_miditrack_locals_dict, synthio_miditrack_locals_dict_table);
159182

shared-bindings/synthio/MidiTrack.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,19 @@
2424
* THE SOFTWARE.
2525
*/
2626

27-
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_SYNTHIO_MIDITRACK_H
28-
#define MICROPY_INCLUDED_SHARED_BINDINGS_SYNTHIO_MIDITRACK_H
27+
#pragma once
2928

3029
#include "shared-module/synthio/MidiTrack.h"
3130

3231
extern const mp_obj_type_t synthio_miditrack_type;
3332

3433
void common_hal_synthio_miditrack_construct(synthio_miditrack_obj_t *self,
35-
const uint8_t *buffer, uint32_t len, uint32_t tempo, uint32_t sample_rate, const int16_t *waveform, uint16_t waveform_len);
34+
const uint8_t *buffer, uint32_t len, uint32_t tempo, uint32_t sample_rate, const int16_t *waveform, uint16_t waveform_len,
35+
mp_obj_t envelope);
3636

3737
void common_hal_synthio_miditrack_deinit(synthio_miditrack_obj_t *self);
3838
bool common_hal_synthio_miditrack_deinited(synthio_miditrack_obj_t *self);
3939
uint32_t common_hal_synthio_miditrack_get_sample_rate(synthio_miditrack_obj_t *self);
4040
uint8_t common_hal_synthio_miditrack_get_bits_per_sample(synthio_miditrack_obj_t *self);
4141
uint8_t common_hal_synthio_miditrack_get_channel_count(synthio_miditrack_obj_t *self);
42-
43-
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_SYNTHIO_MIDITRACK_H
42+
mp_int_t common_hal_synthio_miditrack_get_error_location(synthio_miditrack_obj_t *self);

shared-bindings/synthio/Synthesizer.c

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,24 +37,29 @@
3737
#include "supervisor/shared/translate/translate.h"
3838

3939
//| class Synthesizer:
40-
//| def __init__(self, *, sample_rate: int = 11025, waveform: ReadableBuffer = None) -> None:
40+
//| def __init__(
41+
//| self,
42+
//| *,
43+
//| sample_rate: int = 11025,
44+
//| waveform: Optional[ReadableBuffer] = None,
45+
//| envelope: Optional[Envelope] = None,
46+
//| ) -> None:
4147
//| """Create a synthesizer object.
4248
//|
4349
//| This API is experimental.
4450
//|
45-
//| At least 2 simultaneous notes are supported. mimxrt10xx and rp2040 platforms support up to
46-
//| 12 notes.
47-
//|
4851
//| Notes use MIDI note numbering, with 60 being C4 or Middle C, approximately 262Hz.
4952
//|
5053
//| :param int sample_rate: The desired playback sample rate; higher sample rate requires more memory
51-
//| :param ReadableBuffer waveform: A single-cycle waveform. Default is a 50% duty cycle square wave. If specified, must be a ReadableBuffer of type 'h' (signed 16 bit). It is permitted to modify this buffer during synthesis. This can be used, for instance, to control the overall volume or timbre of the notes.
54+
//| :param ReadableBuffer waveform: A single-cycle waveform. Default is a 50% duty cycle square wave. If specified, must be a ReadableBuffer of type 'h' (signed 16 bit)
55+
//| :param Optional[Envelope] envelope: An object that defines the loudness of a note over time. The default envelope, `None` provides no ramping, voices turn instantly on and off.
5256
//| """
5357
STATIC mp_obj_t synthio_synthesizer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
54-
enum { ARG_sample_rate, ARG_waveform };
58+
enum { ARG_sample_rate, ARG_waveform, ARG_envelope };
5559
static const mp_arg_t allowed_args[] = {
5660
{ MP_QSTR_sample_rate, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 11025} },
5761
{ MP_QSTR_waveform, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none } },
62+
{ MP_QSTR_envelope, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none } },
5863
};
5964
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
6065
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
@@ -68,7 +73,9 @@ STATIC mp_obj_t synthio_synthesizer_make_new(const mp_obj_type_t *type, size_t n
6873
common_hal_synthio_synthesizer_construct(self,
6974
args[ARG_sample_rate].u_int,
7075
bufinfo_waveform.buf,
71-
bufinfo_waveform.len / 2);
76+
bufinfo_waveform.len / 2,
77+
args[ARG_envelope].u_obj);
78+
7279

7380
return MP_OBJ_FROM_PTR(self);
7481
}
@@ -92,7 +99,20 @@ STATIC mp_obj_t synthio_synthesizer_press(mp_obj_t self_in, mp_obj_t press) {
9299
return mp_const_none;
93100
}
94101
STATIC MP_DEFINE_CONST_FUN_OBJ_2(synthio_synthesizer_press_obj, synthio_synthesizer_press);
95-
//
102+
//| def release(self, /, release: Sequence[int] = ()) -> None:
103+
//| """Turn some notes off. Notes use MIDI numbering, with 60 being middle C, approximately 262Hz.
104+
//|
105+
//| Releasing a note that was already released has no effect.
106+
//|
107+
//| :param Sequence[int] release: Any sequence of integer notes."""
108+
STATIC mp_obj_t synthio_synthesizer_release(mp_obj_t self_in, mp_obj_t release) {
109+
synthio_synthesizer_obj_t *self = MP_OBJ_TO_PTR(self_in);
110+
check_for_deinit(self);
111+
common_hal_synthio_synthesizer_release(self, release);
112+
return mp_const_none;
113+
}
114+
STATIC MP_DEFINE_CONST_FUN_OBJ_2(synthio_synthesizer_release_obj, synthio_synthesizer_release);
115+
96116
//| def release_then_press(
97117
//| self, release: Sequence[int] = (), press: Sequence[int] = ()
98118
//| ) -> None:
@@ -178,6 +198,28 @@ STATIC mp_obj_t synthio_synthesizer_obj___exit__(size_t n_args, const mp_obj_t *
178198
return mp_const_none;
179199
}
180200
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(synthio_synthesizer___exit___obj, 4, 4, synthio_synthesizer_obj___exit__);
201+
202+
//| envelope: Optional[Envelope]
203+
//| """The envelope to apply to all notes. `None`, the default envelope, instantly turns notes on and off. The envelope may be changed dynamically, but it affects all notes (even currently playing notes)"""
204+
STATIC mp_obj_t synthio_synthesizer_obj_get_envelope(mp_obj_t self_in) {
205+
synthio_synthesizer_obj_t *self = MP_OBJ_TO_PTR(self_in);
206+
check_for_deinit(self);
207+
return synthio_synth_envelope_get(&self->synth);
208+
}
209+
MP_DEFINE_CONST_FUN_OBJ_1(synthio_synthesizer_get_envelope_obj, synthio_synthesizer_obj_get_envelope);
210+
211+
STATIC mp_obj_t synthio_synthesizer_obj_set_envelope(mp_obj_t self_in, mp_obj_t envelope) {
212+
synthio_synthesizer_obj_t *self = MP_OBJ_TO_PTR(self_in);
213+
check_for_deinit(self);
214+
synthio_synth_envelope_set(&self->synth, envelope);
215+
return mp_const_none;
216+
}
217+
MP_DEFINE_CONST_FUN_OBJ_2(synthio_synthesizer_set_envelope_obj, synthio_synthesizer_obj_set_envelope);
218+
219+
MP_PROPERTY_GETSET(synthio_synthesizer_envelope_obj,
220+
(mp_obj_t)&synthio_synthesizer_get_envelope_obj,
221+
(mp_obj_t)&synthio_synthesizer_set_envelope_obj);
222+
181223
//| sample_rate: int
182224
//| """32 bit value that tells how quickly samples are played in Hertz (cycles per second)."""
183225
STATIC mp_obj_t synthio_synthesizer_obj_get_sample_rate(mp_obj_t self_in) {
@@ -210,6 +252,7 @@ MP_PROPERTY_GETTER(synthio_synthesizer_pressed_obj,
210252
STATIC const mp_rom_map_elem_t synthio_synthesizer_locals_dict_table[] = {
211253
// Methods
212254
{ MP_ROM_QSTR(MP_QSTR_press), MP_ROM_PTR(&synthio_synthesizer_press_obj) },
255+
{ MP_ROM_QSTR(MP_QSTR_release), MP_ROM_PTR(&synthio_synthesizer_release_obj) },
213256
{ MP_ROM_QSTR(MP_QSTR_release_all), MP_ROM_PTR(&synthio_synthesizer_release_all_obj) },
214257
{ MP_ROM_QSTR(MP_QSTR_release_then_press), MP_ROM_PTR(&synthio_synthesizer_release_then_press_obj) },
215258
{ MP_ROM_QSTR(MP_QSTR_release_all_then_press), MP_ROM_PTR(&synthio_synthesizer_release_all_then_press_obj) },
@@ -218,6 +261,7 @@ STATIC const mp_rom_map_elem_t synthio_synthesizer_locals_dict_table[] = {
218261
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&synthio_synthesizer___exit___obj) },
219262

220263
// Properties
264+
{ MP_ROM_QSTR(MP_QSTR_envelope), MP_ROM_PTR(&synthio_synthesizer_envelope_obj) },
221265
{ MP_ROM_QSTR(MP_QSTR_sample_rate), MP_ROM_PTR(&synthio_synthesizer_sample_rate_obj) },
222266
{ MP_ROM_QSTR(MP_QSTR_max_polyphony), MP_ROM_INT(CIRCUITPY_SYNTHIO_MAX_CHANNELS) },
223267
{ MP_ROM_QSTR(MP_QSTR_pressed), MP_ROM_PTR(&synthio_synthesizer_pressed_obj) },

shared-bindings/synthio/Synthesizer.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@
3232
extern const mp_obj_type_t synthio_synthesizer_type;
3333

3434
void common_hal_synthio_synthesizer_construct(synthio_synthesizer_obj_t *self,
35-
uint32_t sample_rate, const int16_t *waveform, uint16_t waveform_len);
36-
35+
uint32_t sample_rate, const int16_t *waveform, uint16_t waveform_length,
36+
mp_obj_t envelope);
3737
void common_hal_synthio_synthesizer_deinit(synthio_synthesizer_obj_t *self);
3838
bool common_hal_synthio_synthesizer_deinited(synthio_synthesizer_obj_t *self);
3939
uint32_t common_hal_synthio_synthesizer_get_sample_rate(synthio_synthesizer_obj_t *self);

0 commit comments

Comments
 (0)