synthio: Perform vibrato in pitch, not as frequency ratio
Now the vibrato 'units' are 1.0 = one octave, 1/12 = one semitone, 1/1200 = one cent. Before, the units were somewhat arbitrary and were not perceptually "symmetrical" around the base frequency. For vibrato_depth = 1/12 and base frequency of 440, before: pitch from 403.33 to 476.67Hz, not corresponding to any notes after: pitch from 415.30 to 466.16Hz, corresponding to G# and A#
This commit is contained in:
parent
a53c0ed066
commit
9a9f3229fa
@ -118,7 +118,12 @@ MP_PROPERTY_GETSET(synthio_note_amplitude_obj,
|
||||
|
||||
|
||||
//| tremolo_depth: float
|
||||
//| """The tremolo depth of the note, from 0 to 1"""
|
||||
//| """The tremolo depth of the note, from 0 to 1
|
||||
//|
|
||||
//| A depth of 0 disables tremolo. A nonzero value enables tremolo,
|
||||
//| with the maximum decrease in amplitude being equal to the tremolo
|
||||
//| depth. A note with a tremolo depth of 1 will fade out to nothing, while
|
||||
//| a tremolo depth of 0.1 will give a minimum amplitude of 0.9."""
|
||||
STATIC mp_obj_t synthio_note_get_tremolo_depth(mp_obj_t self_in) {
|
||||
synthio_note_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
return mp_obj_new_float(common_hal_synthio_note_get_tremolo_depth(self));
|
||||
@ -154,7 +159,12 @@ MP_PROPERTY_GETSET(synthio_note_tremolo_rate_obj,
|
||||
(mp_obj_t)&synthio_note_set_tremolo_rate_obj);
|
||||
|
||||
//| vibrato_depth: float
|
||||
//| """The vibrato depth of the note, from 0 to 1"""
|
||||
//| """The vibrato depth of the note, from 0 to 1
|
||||
//|
|
||||
//| A depth of 0 disables vibrato. A depth of 1 corresponds to a vibrato of ±1
|
||||
//| octave. A depth of (1/12) = 0.833 corresponds to a vibrato of ±1 semitone,
|
||||
//| and a depth of .00833 corresponds to one musical cent.
|
||||
//| """
|
||||
STATIC mp_obj_t synthio_note_get_vibrato_depth(mp_obj_t self_in) {
|
||||
synthio_note_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
return mp_obj_new_float(common_hal_synthio_note_get_vibrato_depth(self));
|
||||
|
@ -151,10 +151,35 @@ uint32_t synthio_note_envelope(synthio_note_obj_t *self) {
|
||||
return self->amplitude_scaled;
|
||||
}
|
||||
|
||||
// Perform a pitch bend operation
|
||||
//
|
||||
// bend_value is in the range [0, 65535]. "no change" is 32768. The bend unit is 32768/octave.
|
||||
//
|
||||
// compare to (frequency_scaled * pow(2, (bend_value-32768)/32768))
|
||||
// a 13-entry pitch table
|
||||
#define BEND_SCALE (32768)
|
||||
#define BEND_OFFSET (BEND_SCALE)
|
||||
|
||||
STATIC uint16_t pitch_bend_table[] = { 0, 1948, 4013, 6200, 8517, 10972, 13573, 16329, 19248, 22341, 25618, 29090, 32768 };
|
||||
|
||||
STATIC uint32_t pitch_bend(uint32_t frequency_scaled, uint16_t bend_value) {
|
||||
bool down = (bend_value < 32768);
|
||||
if (!down) {
|
||||
bend_value -= 32768;
|
||||
}
|
||||
uint32_t bend_value_semitone = (uint32_t)bend_value * 24; // 65536/semitone
|
||||
uint32_t semitone = bend_value_semitone >> 16;
|
||||
uint32_t fractone = bend_value_semitone & 0xffff;
|
||||
uint32_t f_lo = pitch_bend_table[semitone];
|
||||
uint32_t f_hi = pitch_bend_table[semitone + 1]; // table has 13 entries, indexing with semitone=12 is OK
|
||||
uint32_t f = ((f_lo * (65535 - fractone) + f_hi * fractone) >> 16) + BEND_OFFSET;
|
||||
return (frequency_scaled * (uint64_t)f) >> (15 + down);
|
||||
}
|
||||
|
||||
uint32_t synthio_note_step(synthio_note_obj_t *self, int32_t sample_rate, int16_t dur, uint16_t *loudness) {
|
||||
int tremolo_value = synthio_lfo_step(&self->tremolo_state, dur);
|
||||
int vibrato_value = synthio_lfo_step(&self->vibrato_state, dur);
|
||||
*loudness = (*loudness * tremolo_value) >> 15;
|
||||
uint32_t frequency_scaled = ((uint64_t)self->frequency_scaled * vibrato_value) >> 15;
|
||||
uint32_t frequency_scaled = pitch_bend(self->frequency_scaled, vibrato_value);
|
||||
return frequency_scaled;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user