synthio: allow negative amplitudes

Previously, negative amplitudes were clamped to zero.
Now, they are allowed to range from -ALMOST_ONE to +ALMOST_ONE.
This is useful in certain circumstances, such as using synthio
to create CV-like outputs that can be positive or negative, by
using the amplitude property of the note.
This commit is contained in:
Jeff Epler 2023-11-21 08:44:26 -06:00
parent 383f79718a
commit c92ad33a9c
No known key found for this signature in database
GPG Key ID: D5BF15AB975AB4DE
5 changed files with 16137 additions and 2057 deletions

View File

@ -214,7 +214,7 @@ STATIC uint32_t pitch_bend(uint32_t frequency_scaled, int32_t bend_value) {
#define ONE MICROPY_FLOAT_CONST(1.) #define ONE MICROPY_FLOAT_CONST(1.)
#define ALMOST_ONE (MICROPY_FLOAT_CONST(32767.) / 32768) #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]) { uint32_t synthio_note_step(synthio_note_obj_t *self, int32_t sample_rate, int16_t dur, int16_t loudness[2]) {
int panning = synthio_block_slot_get_scaled(&self->panning, -ALMOST_ONE, ALMOST_ONE); int panning = synthio_block_slot_get_scaled(&self->panning, -ALMOST_ONE, ALMOST_ONE);
int left_panning_scaled, right_panning_scaled; int left_panning_scaled, right_panning_scaled;
if (panning >= 0) { if (panning >= 0) {
@ -225,7 +225,7 @@ uint32_t synthio_note_step(synthio_note_obj_t *self, int32_t sample_rate, int16_
left_panning_scaled = 32767 + panning; left_panning_scaled = 32767 + panning;
} }
int amplitude = synthio_block_slot_get_scaled(&self->amplitude, ZERO, ALMOST_ONE); int amplitude = synthio_block_slot_get_scaled(&self->amplitude, -ALMOST_ONE, ALMOST_ONE);
left_panning_scaled = (left_panning_scaled * amplitude) >> 15; left_panning_scaled = (left_panning_scaled * amplitude) >> 15;
right_panning_scaled = (right_panning_scaled * amplitude) >> 15; right_panning_scaled = (right_panning_scaled * amplitude) >> 15;
loudness[0] = (loudness[0] * left_panning_scaled) >> 15; loudness[0] = (loudness[0] * left_panning_scaled) >> 15;

View File

@ -55,6 +55,6 @@ typedef struct synthio_note_obj {
} synthio_note_obj_t; } synthio_note_obj_t;
void synthio_note_recalculate(synthio_note_obj_t *self, int32_t sample_rate); void synthio_note_recalculate(synthio_note_obj_t *self, int32_t sample_rate);
uint32_t synthio_note_step(synthio_note_obj_t *self, int32_t sample_rate, int16_t dur, uint16_t loudness[2]); uint32_t synthio_note_step(synthio_note_obj_t *self, int32_t sample_rate, int16_t dur, int16_t loudness[2]);
void synthio_note_start(synthio_note_obj_t *self, int32_t sample_rate); void synthio_note_start(synthio_note_obj_t *self, int32_t sample_rate);
bool synthio_note_playing(synthio_note_obj_t *self); bool synthio_note_playing(synthio_note_obj_t *self);

View File

@ -172,7 +172,7 @@ int16_t mix_down_sample(int32_t sample) {
return sample; return sample;
} }
static bool synth_note_into_buffer(synthio_synth_t *synth, int chan, int32_t *out_buffer32, int16_t dur, uint16_t loudness[2]) { static bool synth_note_into_buffer(synthio_synth_t *synth, int chan, int32_t *out_buffer32, int16_t dur, int16_t loudness[2]) {
mp_obj_t note_obj = synth->span.note_obj[chan]; mp_obj_t note_obj = synth->span.note_obj[chan];
int32_t sample_rate = synth->sample_rate; int32_t sample_rate = synth->sample_rate;
@ -298,7 +298,7 @@ STATIC mp_obj_t synthio_synth_get_note_filter(mp_obj_t note_obj) {
return mp_const_none; return mp_const_none;
} }
STATIC void sum_with_loudness(int32_t *out_buffer32, int32_t *tmp_buffer32, uint16_t loudness[2], size_t dur, int synth_chan) { STATIC void sum_with_loudness(int32_t *out_buffer32, int32_t *tmp_buffer32, int16_t loudness[2], size_t dur, int synth_chan) {
if (synth_chan == 1) { if (synth_chan == 1) {
for (size_t i = 0; i < dur; i++) { for (size_t i = 0; i < dur; i++) {
*out_buffer32++ += (*tmp_buffer32++ *loudness[0]) >> 16; *out_buffer32++ += (*tmp_buffer32++ *loudness[0]) >> 16;
@ -344,7 +344,7 @@ void synthio_synth_synthesize(synthio_synth_t *synth, uint8_t **bufptr, uint32_t
continue; continue;
} }
uint16_t loudness[2] = {synth->envelope_state[chan].level, synth->envelope_state[chan].level}; int16_t loudness[2] = {synth->envelope_state[chan].level, synth->envelope_state[chan].level};
if (!synth_note_into_buffer(synth, chan, tmp_buffer32, dur, loudness)) { if (!synth_note_into_buffer(synth, chan, tmp_buffer32, dur, loudness)) {
// for some other reason, such as being above nyquist, note // for some other reason, such as being above nyquist, note

View File

@ -3,8 +3,8 @@ from synthnotehelper import *
@synth_test @synth_test
def gen(synth): def gen(synth):
l = LFO(bend_out, offset=0.2, scale=0.8, rate=4, once=True) l = LFO(sine, offset=0.2, scale=0.8, rate=2)
yield [l] yield [l]
n = Note(128, amplitude=l) n = Note(8, amplitude=l)
synth.press(n) synth.press(n)
yield 1 / 4 yield 2

File diff suppressed because it is too large Load Diff