synthio: improve documentation, simplify synthio_lfo_obj_tick_scaled
This commit is contained in:
parent
a682b42180
commit
3d2db5dbe0
|
@ -37,16 +37,23 @@
|
|||
//|
|
||||
//| Every `rate` seconds, the output of the LFO cycles through its `waveform`.
|
||||
//| The output at any particular moment is ``waveform[idx] * scale + offset``.
|
||||
//| Internally, the calculation takes place in fixed point for speed.
|
||||
//|
|
||||
//| `rate`, `offset`, `scale`, and `once` can be changed at run-time.
|
||||
//| `rate`, `offset`, `scale`, and `once` can be changed at run-time. `waveform` may be mutated.
|
||||
//|
|
||||
//| An LFO only updates if it is actually associated with a playing Note,
|
||||
//| including if it is indirectly associated with the Note via an intermediate
|
||||
//| LFO.
|
||||
//| `waveform` must be a ``ReadableBuffer`` with elements of type `h` (16-bit signed integer).
|
||||
//| Internally, the elements of `waveform` are scaled so that the input
|
||||
//| range ``[-32768,32767]`` maps to ``[-1.0, 0.99996]``.
|
||||
//|
|
||||
//| An LFO only updates if it is actually associated with a playing `Synthesizer`,
|
||||
//| including indirectly via a `Note` or another intermediate LFO.
|
||||
//|
|
||||
//| Using the same LFO as an input to multiple other LFOs or Notes is OK, but
|
||||
//| the result if an LFO is tied to multiple Synthtesizer objects is undefined."""
|
||||
//| the result if an LFO is tied to multiple Synthtesizer objects is undefined.
|
||||
//|
|
||||
//| In the current implementation, LFOs are updated every 256 samples. This
|
||||
//| should be considered an implementation detail, though it affects how LFOs
|
||||
//| behave for instance when used to implement an integrator (``l.offset = l``).
|
||||
//| """
|
||||
//|
|
||||
//| def __init__(
|
||||
//| self,
|
||||
|
|
|
@ -90,9 +90,9 @@ mp_float_t synthio_lfo_obj_tick_limited(synthio_lfo_slot_t *lfo_slot, mp_float_t
|
|||
return value;
|
||||
}
|
||||
|
||||
int32_t synthio_lfo_obj_tick_scaled(synthio_lfo_slot_t *lfo_slot, mp_float_t lo, mp_float_t hi, int shift) {
|
||||
int32_t synthio_lfo_obj_tick_scaled(synthio_lfo_slot_t *lfo_slot, mp_float_t lo, mp_float_t hi) {
|
||||
mp_float_t value = synthio_lfo_obj_tick_limited(lfo_slot, lo, hi);
|
||||
return (int32_t)MICROPY_FLOAT_C_FUN(round)(MICROPY_FLOAT_C_FUN(ldexp)(value, shift));
|
||||
return (int32_t)MICROPY_FLOAT_C_FUN(round)(MICROPY_FLOAT_C_FUN(ldexp)(value, 15));
|
||||
}
|
||||
|
||||
void synthio_lfo_assign_input(mp_obj_t obj, synthio_lfo_slot_t *slot, qstr arg_name) {
|
||||
|
|
|
@ -55,8 +55,8 @@ typedef struct synthio_lfo_obj {
|
|||
mp_float_t synthio_lfo_obj_tick(synthio_lfo_slot_t *lfo_slot);
|
||||
// the same, but the output is constrained to be between lo and hi
|
||||
mp_float_t synthio_lfo_obj_tick_limited(synthio_lfo_slot_t *lfo_slot, mp_float_t lo, mp_float_t hi);
|
||||
// the same, but the output is constrained to be between lo and hi and converted to an integer with `shift` fractional bits
|
||||
int32_t synthio_lfo_obj_tick_scaled(synthio_lfo_slot_t *lfo_slot, mp_float_t lo, mp_float_t hi, int shift);
|
||||
// the same, but the output is constrained to be between lo and hi and converted to an integer with 15 fractional bits
|
||||
int32_t synthio_lfo_obj_tick_scaled(synthio_lfo_slot_t *lfo_slot, mp_float_t lo, mp_float_t hi);
|
||||
|
||||
// Assign an object (which may be a float or a synthio_lfo_obj_t) to an lfo slot
|
||||
void synthio_lfo_assign_input(mp_obj_t obj, synthio_lfo_slot_t *lfo_slot, qstr arg_name);
|
||||
|
|
|
@ -177,7 +177,7 @@ STATIC uint32_t pitch_bend(uint32_t frequency_scaled, int32_t bend_value) {
|
|||
#define ALMOST_ONE (MICROPY_FLOAT_CONST(32767.) / 32768)
|
||||
|
||||
uint32_t synthio_note_step(synthio_note_obj_t *self, int32_t sample_rate, int16_t dur, uint16_t loudness[2]) {
|
||||
int panning = synthio_lfo_obj_tick_scaled(&self->panning, -ALMOST_ONE, ALMOST_ONE, 15);
|
||||
int panning = synthio_lfo_obj_tick_scaled(&self->panning, -ALMOST_ONE, ALMOST_ONE);
|
||||
int left_panning_scaled, right_panning_scaled;
|
||||
if (panning >= 0) {
|
||||
left_panning_scaled = 32768;
|
||||
|
@ -187,18 +187,18 @@ uint32_t synthio_note_step(synthio_note_obj_t *self, int32_t sample_rate, int16_
|
|||
left_panning_scaled = 32767 + panning;
|
||||
}
|
||||
|
||||
int amplitude = synthio_lfo_obj_tick_scaled(&self->amplitude, ZERO, ALMOST_ONE, 15);
|
||||
int amplitude = synthio_lfo_obj_tick_scaled(&self->amplitude, ZERO, ALMOST_ONE);
|
||||
left_panning_scaled = (left_panning_scaled * amplitude) >> 15;
|
||||
right_panning_scaled = (right_panning_scaled * amplitude) >> 15;
|
||||
loudness[0] = (loudness[0] * left_panning_scaled) >> 15;
|
||||
loudness[1] = (loudness[1] * right_panning_scaled) >> 15;
|
||||
|
||||
if (self->ring_frequency_scaled != 0) {
|
||||
int ring_bend_value = synthio_lfo_obj_tick_scaled(&self->ring_bend, -12, 12, 15);
|
||||
int ring_bend_value = synthio_lfo_obj_tick_scaled(&self->ring_bend, -12, 12);
|
||||
self->ring_frequency_bent = pitch_bend(self->ring_frequency_scaled, ring_bend_value);
|
||||
}
|
||||
|
||||
int bend_value = synthio_lfo_obj_tick_scaled(&self->bend, -12, 12, 15);
|
||||
int bend_value = synthio_lfo_obj_tick_scaled(&self->bend, -12, 12);
|
||||
uint32_t frequency_scaled = pitch_bend(self->frequency_scaled, bend_value);
|
||||
return frequency_scaled;
|
||||
|
||||
|
|
Loading…
Reference in New Issue