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 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 left_panning_scaled, right_panning_scaled;
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;
}
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;
right_panning_scaled = (right_panning_scaled * amplitude) >> 15;
loudness[0] = (loudness[0] * left_panning_scaled) >> 15;

View File

@ -55,6 +55,6 @@ typedef struct synthio_note_obj {
} synthio_note_obj_t;
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);
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;
}
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];
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;
}
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) {
for (size_t i = 0; i < dur; i++) {
*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;
}
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)) {
// for some other reason, such as being above nyquist, note

View File

@ -3,8 +3,8 @@ from synthnotehelper import *
@synth_test
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]
n = Note(128, amplitude=l)
n = Note(8, amplitude=l)
synth.press(n)
yield 1 / 4
yield 2

File diff suppressed because it is too large Load Diff