Merge pull request #8186 from jepler/synthio-note-state
synthio: Add Synthesizer.note_state
This commit is contained in:
commit
9e22850d51
|
@ -12,6 +12,7 @@ LONGINT_IMPL = MPZ
|
|||
|
||||
# No I2S on SAMD51G
|
||||
CIRCUITPY_AUDIOBUSIO = 0
|
||||
CIRCUITPY_SYNTHIO = 0
|
||||
|
||||
CIRCUITPY_BITBANG_APA102 = 1
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "py/binary.h"
|
||||
#include "py/objproperty.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/enum.h"
|
||||
#include "shared-bindings/util.h"
|
||||
#include "shared-bindings/synthio/Biquad.h"
|
||||
#include "shared-bindings/synthio/Synthesizer.h"
|
||||
|
@ -256,7 +257,9 @@ MP_PROPERTY_GETTER(synthio_synthesizer_sample_rate_obj,
|
|||
(mp_obj_t)&synthio_synthesizer_get_sample_rate_obj);
|
||||
|
||||
//| pressed: NoteSequence
|
||||
//| """A sequence of the currently pressed notes (read-only property)"""
|
||||
//| """A sequence of the currently pressed notes (read-only property).
|
||||
//|
|
||||
//| This does not include notes in the release phase of the envelope."""
|
||||
//|
|
||||
STATIC mp_obj_t synthio_synthesizer_obj_get_pressed(mp_obj_t self_in) {
|
||||
synthio_synthesizer_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
|
@ -268,6 +271,23 @@ MP_DEFINE_CONST_FUN_OBJ_1(synthio_synthesizer_get_pressed_obj, synthio_synthesiz
|
|||
MP_PROPERTY_GETTER(synthio_synthesizer_pressed_obj,
|
||||
(mp_obj_t)&synthio_synthesizer_get_pressed_obj);
|
||||
|
||||
//| def note_info(self, note: Note) -> Tuple[Optional[EnvelopeState], float]:
|
||||
//| """Get info about a note's current envelope state
|
||||
//|
|
||||
//| If the note is currently playing (including in the release phase), the returned value gives the current envelope state and the current envelope value.
|
||||
//|
|
||||
//| If the note is not playing on this synthesizer, returns the tuple ``(None, 0.0)``."""
|
||||
STATIC mp_obj_t synthio_synthesizer_obj_note_info(mp_obj_t self_in, mp_obj_t note) {
|
||||
synthio_synthesizer_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
check_for_deinit(self);
|
||||
mp_float_t vol = MICROPY_FLOAT_CONST(0.0);
|
||||
envelope_state_e state = common_hal_synthio_synthesizer_note_info(self, note, &vol);
|
||||
return MP_OBJ_NEW_TUPLE(
|
||||
cp_enum_find(&synthio_note_state_type, state),
|
||||
mp_obj_new_float(vol));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(synthio_synthesizer_note_info_obj, synthio_synthesizer_obj_note_info);
|
||||
|
||||
//| blocks: List[BlockInput]
|
||||
//| """A list of blocks to advance whether or not they are associated with a playing note.
|
||||
//|
|
||||
|
@ -417,6 +437,7 @@ STATIC const mp_rom_map_elem_t synthio_synthesizer_locals_dict_table[] = {
|
|||
{ MP_ROM_QSTR(MP_QSTR_sample_rate), MP_ROM_PTR(&synthio_synthesizer_sample_rate_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_max_polyphony), MP_ROM_INT(CIRCUITPY_SYNTHIO_MAX_CHANNELS) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_pressed), MP_ROM_PTR(&synthio_synthesizer_pressed_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_note_info), MP_ROM_PTR(&synthio_synthesizer_note_info_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_blocks), MP_ROM_PTR(&synthio_synthesizer_blocks_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(synthio_synthesizer_locals_dict, synthio_synthesizer_locals_dict_table);
|
||||
|
|
|
@ -45,3 +45,4 @@ void common_hal_synthio_synthesizer_retrigger(synthio_synthesizer_obj_t *self, m
|
|||
void common_hal_synthio_synthesizer_release_all(synthio_synthesizer_obj_t *self);
|
||||
mp_obj_t common_hal_synthio_synthesizer_get_pressed_notes(synthio_synthesizer_obj_t *self);
|
||||
mp_obj_t common_hal_synthio_synthesizer_get_blocks(synthio_synthesizer_obj_t *self);
|
||||
envelope_state_e common_hal_synthio_synthesizer_note_info(synthio_synthesizer_obj_t *self, mp_obj_t note, mp_float_t *vol_out);
|
||||
|
|
|
@ -45,6 +45,32 @@
|
|||
|
||||
#include "shared-module/synthio/LFO.h"
|
||||
|
||||
//| class EnvelopeState:
|
||||
//| ATTACK: EnvelopeState
|
||||
//| """The note is in its attack phase"""
|
||||
//| DECAY: EnvelopeState
|
||||
//| """The note is in its decay phase"""
|
||||
//| SUSTAIN: EnvelopeState
|
||||
//| """The note is in its sustain phase"""
|
||||
//| RELEASE: EnvelopeState
|
||||
//| """The note is in its release phase"""
|
||||
//|
|
||||
MAKE_ENUM_VALUE(synthio_note_state_type, note_state, ATTACK, SYNTHIO_ENVELOPE_STATE_ATTACK);
|
||||
MAKE_ENUM_VALUE(synthio_note_state_type, note_state, DECAY, SYNTHIO_ENVELOPE_STATE_DECAY);
|
||||
MAKE_ENUM_VALUE(synthio_note_state_type, note_state, SUSTAIN, SYNTHIO_ENVELOPE_STATE_SUSTAIN);
|
||||
MAKE_ENUM_VALUE(synthio_note_state_type, note_state, RELEASE, SYNTHIO_ENVELOPE_STATE_RELEASE);
|
||||
|
||||
MAKE_ENUM_MAP(synthio_note_state) {
|
||||
MAKE_ENUM_MAP_ENTRY(note_state, ATTACK),
|
||||
MAKE_ENUM_MAP_ENTRY(note_state, DECAY),
|
||||
MAKE_ENUM_MAP_ENTRY(note_state, SUSTAIN),
|
||||
MAKE_ENUM_MAP_ENTRY(note_state, RELEASE),
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(synthio_note_state_locals_dict, synthio_note_state_locals_table);
|
||||
MAKE_PRINTER(synthio, synthio_note_state);
|
||||
MAKE_ENUM_TYPE(synthio, EnvelopeState, synthio_note_state);
|
||||
|
||||
#define default_attack_time (MICROPY_FLOAT_CONST(0.1))
|
||||
#define default_decay_time (MICROPY_FLOAT_CONST(0.05))
|
||||
#define default_release_time (MICROPY_FLOAT_CONST(0.2))
|
||||
|
@ -316,6 +342,7 @@ STATIC const mp_rom_map_elem_t synthio_module_globals_table[] = {
|
|||
{ MP_ROM_QSTR(MP_QSTR_MathOperation), MP_ROM_PTR(&synthio_math_operation_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_MidiTrack), MP_ROM_PTR(&synthio_miditrack_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_Note), MP_ROM_PTR(&synthio_note_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_EnvelopeState), MP_ROM_PTR(&synthio_note_state_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_LFO), MP_ROM_PTR(&synthio_lfo_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_Synthesizer), MP_ROM_PTR(&synthio_synthesizer_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_from_file), MP_ROM_PTR(&synthio_from_file_obj) },
|
||||
|
|
|
@ -29,10 +29,16 @@
|
|||
#include "py/objnamedtuple.h"
|
||||
#include "py/enum.h"
|
||||
|
||||
typedef enum {
|
||||
SYNTHIO_ENVELOPE_STATE_ATTACK, SYNTHIO_ENVELOPE_STATE_DECAY,
|
||||
SYNTHIO_ENVELOPE_STATE_SUSTAIN, SYNTHIO_ENVELOPE_STATE_RELEASE
|
||||
} envelope_state_e;
|
||||
|
||||
typedef enum synthio_bend_mode_e {
|
||||
SYNTHIO_BEND_MODE_STATIC, SYNTHIO_BEND_MODE_VIBRATO, SYNTHIO_BEND_MODE_SWEEP, SYNTHIO_BEND_MODE_SWEEP_IN
|
||||
} synthio_bend_mode_t;
|
||||
|
||||
extern const mp_obj_type_t synthio_note_state_type;
|
||||
extern const cp_enum_obj_t bend_mode_VIBRATO_obj;
|
||||
extern const mp_obj_type_t synthio_bend_mode_type;
|
||||
typedef struct synthio_synth synthio_synth_t;
|
||||
|
|
|
@ -185,6 +185,17 @@ mp_obj_t common_hal_synthio_synthesizer_get_pressed_notes(synthio_synthesizer_ob
|
|||
return MP_OBJ_FROM_PTR(result);
|
||||
}
|
||||
|
||||
envelope_state_e common_hal_synthio_synthesizer_note_info(synthio_synthesizer_obj_t *self, mp_obj_t note, mp_float_t *vol_out) {
|
||||
for (int chan = 0; chan < CIRCUITPY_SYNTHIO_MAX_CHANNELS; chan++) {
|
||||
if (self->synth.span.note_obj[chan] == note) {
|
||||
*vol_out = self->synth.envelope_state[chan].level / 32767.;
|
||||
return self->synth.envelope_state[chan].state;
|
||||
}
|
||||
}
|
||||
return (envelope_state_e) - 1;
|
||||
}
|
||||
|
||||
|
||||
mp_obj_t common_hal_synthio_synthesizer_get_blocks(synthio_synthesizer_obj_t *self) {
|
||||
return self->blocks;
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#define SYNTHIO_FREQUENCY_SHIFT (16)
|
||||
|
||||
#include "shared-module/audiocore/__init__.h"
|
||||
#include "shared-bindings/synthio/__init__.h"
|
||||
|
||||
typedef struct {
|
||||
uint16_t dur;
|
||||
|
@ -49,11 +50,6 @@ typedef struct {
|
|||
uint16_t attack_level, sustain_level;
|
||||
} synthio_envelope_definition_t;
|
||||
|
||||
typedef enum {
|
||||
SYNTHIO_ENVELOPE_STATE_ATTACK, SYNTHIO_ENVELOPE_STATE_DECAY,
|
||||
SYNTHIO_ENVELOPE_STATE_SUSTAIN, SYNTHIO_ENVELOPE_STATE_RELEASE
|
||||
} envelope_state_e;
|
||||
|
||||
typedef struct {
|
||||
int16_t level;
|
||||
uint16_t substep;
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
from synthio import Synthesizer, Note, Envelope
|
||||
from audiocore import get_buffer
|
||||
|
||||
s = Synthesizer()
|
||||
n = Note(440, envelope=Envelope())
|
||||
print("{} {:.2f}".format(*s.note_info(n)))
|
||||
s.press(n)
|
||||
print("press")
|
||||
for _ in range(9):
|
||||
print("{} {:.2f}".format(*s.note_info(n)))
|
||||
get_buffer(s)
|
||||
|
||||
s.release(n)
|
||||
print("release")
|
||||
for _ in range(11):
|
||||
print("{} {:.2f}".format(*s.note_info(n)))
|
||||
get_buffer(s)
|
|
@ -0,0 +1,23 @@
|
|||
None 0.00
|
||||
press
|
||||
synthio.EnvelopeState.ATTACK 0.23
|
||||
synthio.EnvelopeState.ATTACK 0.46
|
||||
synthio.EnvelopeState.ATTACK 0.70
|
||||
synthio.EnvelopeState.ATTACK 0.93
|
||||
synthio.EnvelopeState.DECAY 1.00
|
||||
synthio.EnvelopeState.DECAY 0.91
|
||||
synthio.EnvelopeState.DECAY 0.81
|
||||
synthio.EnvelopeState.SUSTAIN 0.80
|
||||
synthio.EnvelopeState.SUSTAIN 0.80
|
||||
release
|
||||
synthio.EnvelopeState.RELEASE 0.80
|
||||
synthio.EnvelopeState.RELEASE 0.71
|
||||
synthio.EnvelopeState.RELEASE 0.61
|
||||
synthio.EnvelopeState.RELEASE 0.52
|
||||
synthio.EnvelopeState.RELEASE 0.43
|
||||
synthio.EnvelopeState.RELEASE 0.34
|
||||
synthio.EnvelopeState.RELEASE 0.24
|
||||
synthio.EnvelopeState.RELEASE 0.15
|
||||
synthio.EnvelopeState.RELEASE 0.06
|
||||
synthio.EnvelopeState.RELEASE 0.00
|
||||
None 0.00
|
|
@ -1,7 +1,6 @@
|
|||
File cmdline/cmd_showbc.py, code block '<module>' (descriptor: \.\+, bytecode @\.\+ bytes)
|
||||
Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
|
||||
########
|
||||
\.\+63
|
||||
arg names:
|
||||
(N_STATE 3)
|
||||
(N_EXC_STACK 0)
|
||||
|
|
Loading…
Reference in New Issue