synthio: Factor out `synth_note_into_buffer`, start adding filter buffer

This commit is contained in:
Jeff Epler 2023-05-11 18:13:20 -05:00
parent 9d8dcf7d33
commit 62e6de8ed5
No known key found for this signature in database
GPG Key ID: D5BF15AB975AB4DE
2 changed files with 149 additions and 140 deletions

View File

@ -171,44 +171,28 @@ int16_t mix_down_sample(int32_t sample) {
return sample;
}
void synthio_synth_synthesize(synthio_synth_t *synth, uint8_t **bufptr, uint32_t *buffer_length, uint8_t channel) {
if (channel == synth->other_channel) {
*buffer_length = synth->last_buffer_length;
*bufptr = (uint8_t *)(synth->buffers[synth->other_buffer_index] + channel);
return;
}
synth->buffer_index = !synth->buffer_index;
synth->other_channel = 1 - channel;
synth->other_buffer_index = synth->buffer_index;
uint16_t dur = MIN(SYNTHIO_MAX_DUR, synth->span.dur);
synth->span.dur -= dur;
int32_t sample_rate = synth->sample_rate;
int32_t out_buffer32[dur * synth->channel_count];
memset(out_buffer32, 0, sizeof(out_buffer32));
for (int chan = 0; chan < CIRCUITPY_SYNTHIO_MAX_CHANNELS; chan++) {
static void synth_note_into_buffer(synthio_synth_t *synth, int chan, int32_t *out_buffer32, int16_t dur) {
mp_obj_t note_obj = synth->span.note_obj[chan];
if (note_obj == SYNTHIO_SILENCE) {
synth->accum[chan] = 0;
continue;
return;
}
if (synth->envelope_state[chan].level == 0) {
// note is truly finished, but we only just noticed
synth->span.note_obj[chan] = SYNTHIO_SILENCE;
continue;
return;
}
int32_t sample_rate = synth->sample_rate;
// adjust loudness by envelope
uint16_t loudness[2] = {synth->envelope_state[chan].level,synth->envelope_state[chan].level};
uint32_t dds_rate;
const int16_t *waveform = synth->waveform;
uint32_t waveform_length = synth->waveform_length;
const int16_t *waveform = synth->waveform_bufinfo.buf;
uint32_t waveform_length = synth->waveform_bufinfo.len / 2;
uint32_t ring_dds_rate = 0;
const int16_t *ring_waveform = NULL;
@ -250,7 +234,7 @@ void synthio_synth_synthesize(synthio_synth_t *synth, uint8_t **bufptr, uint32_t
if (dds_rate > lim / 2) {
// beyond nyquist, can't play note
continue;
return;
}
// can happen if note waveform gets set mid-note, but the expensive modulo is usually avoided
@ -300,7 +284,7 @@ void synthio_synth_synthesize(synthio_synth_t *synth, uint8_t **bufptr, uint32_t
if (dds_rate > lim / 2) {
// beyond nyquist, can't play note
continue;
return;
}
// can happen if note waveform gets set mid-note, but the expensive modulo is usually avoided
@ -325,6 +309,29 @@ void synthio_synth_synthesize(synthio_synth_t *synth, uint8_t **bufptr, uint32_t
}
}
void synthio_synth_synthesize(synthio_synth_t *synth, uint8_t **bufptr, uint32_t *buffer_length, uint8_t channel) {
if (channel == synth->other_channel) {
*buffer_length = synth->last_buffer_length;
*bufptr = (uint8_t *)(synth->buffers[synth->other_buffer_index] + channel);
return;
}
synth->buffer_index = !synth->buffer_index;
synth->other_channel = 1 - channel;
synth->other_buffer_index = synth->buffer_index;
uint16_t dur = MIN(SYNTHIO_MAX_DUR, synth->span.dur);
synth->span.dur -= dur;
int32_t out_buffer32[dur * synth->channel_count];
memset(out_buffer32, 0, sizeof(out_buffer32));
for (int chan = 0; chan < CIRCUITPY_SYNTHIO_MAX_CHANNELS; chan++) {
synth_note_into_buffer(synth, chan, out_buffer32, dur);
}
int16_t *out_buffer16 = (int16_t *)(void *)synth->buffers[synth->buffer_index];
// mix down audio
@ -358,8 +365,7 @@ bool synthio_synth_deinited(synthio_synth_t *synth) {
}
void synthio_synth_deinit(synthio_synth_t *synth) {
m_del(uint8_t, synth->buffers[0], synth->buffer_length);
m_del(uint8_t, synth->buffers[1], synth->buffer_length);
synth->filter_buffer = NULL;
synth->buffers[0] = NULL;
synth->buffers[1] = NULL;
}
@ -374,15 +380,19 @@ mp_obj_t synthio_synth_envelope_get(synthio_synth_t *synth) {
}
void synthio_synth_init(synthio_synth_t *synth, uint32_t sample_rate, int channel_count, mp_obj_t waveform_obj, mp_obj_t filter_obj, mp_obj_t envelope_obj) {
synthio_synth_parse_waveform(&synth->waveform_bufinfo, waveform_obj);
synthio_synth_parse_filter(&synth->filter_bufinfo, filter_obj);
mp_arg_validate_int_range(channel_count, 1, 2, MP_QSTR_channel_count);
synth->buffer_length = SYNTHIO_MAX_DUR * SYNTHIO_BYTES_PER_SAMPLE * channel_count;
synth->buffers[0] = m_malloc(synth->buffer_length, false);
synth->buffers[1] = m_malloc(synth->buffer_length, false);
if (synth->filter_bufinfo.len) {
synth->filter_buffer_length = (synth->filter_bufinfo.len + SYNTHIO_MAX_DUR) * channel_count * sizeof(int32_t);
synth->filter_buffer = m_malloc(synth->filter_buffer_length, false);
}
synth->channel_count = channel_count;
synth->other_channel = -1;
synth->waveform_obj = waveform_obj;
synthio_synth_parse_waveform(&synth->waveform_bufinfo, waveform_obj);
synthio_synth_parse_filter(&synth->filter_bufinfo, filter_obj);
synth->sample_rate = sample_rate;
synthio_synth_envelope_set(synth, envelope_obj);

View File

@ -64,12 +64,11 @@ typedef struct synthio_synth {
uint32_t sample_rate;
uint32_t total_envelope;
int16_t *buffers[2];
const int16_t *waveform;
int32_t *filter_buffer;
uint8_t channel_count;
uint16_t buffer_length;
uint16_t buffer_length, filter_buffer_length;
uint16_t last_buffer_length;
uint8_t other_channel, buffer_index, other_buffer_index;
uint16_t waveform_length;
mp_buffer_info_t waveform_bufinfo, filter_bufinfo;
synthio_envelope_definition_t global_envelope_definition;
mp_obj_t waveform_obj, filter_obj, envelope_obj;