synthio: support audio outputs that need double buffering
closes #7837 tested on rp2040 pico w on pico dv shield
This commit is contained in:
parent
9679aaa0be
commit
04f4092e11
@ -156,7 +156,7 @@ uint8_t common_hal_synthio_miditrack_get_channel_count(synthio_miditrack_obj_t *
|
||||
|
||||
void synthio_miditrack_reset_buffer(synthio_miditrack_obj_t *self,
|
||||
bool single_channel_output, uint8_t channel) {
|
||||
|
||||
synthio_synth_reset_buffer(&self->synth, single_channel_output, channel);
|
||||
self->synth.span.dur = 0;
|
||||
self->next_span = 0;
|
||||
}
|
||||
@ -172,7 +172,7 @@ audioio_get_buffer_result_t synthio_miditrack_get_buffer(synthio_miditrack_obj_t
|
||||
self->synth.span = self->track[self->next_span++];
|
||||
}
|
||||
|
||||
synthio_synth_synthesize(&self->synth, buffer, buffer_length);
|
||||
synthio_synth_synthesize(&self->synth, buffer, buffer_length, single_channel_output ? 0 : channel);
|
||||
|
||||
return (self->synth.span.dur == 0 && self->next_span >= self->total_spans) ?
|
||||
GET_BUFFER_DONE : GET_BUFFER_MORE_DATA;
|
||||
|
@ -58,12 +58,13 @@ uint8_t common_hal_synthio_synthesizer_get_channel_count(synthio_synthesizer_obj
|
||||
|
||||
void synthio_synthesizer_reset_buffer(synthio_synthesizer_obj_t *self,
|
||||
bool single_channel_output, uint8_t channel) {
|
||||
synthio_synth_reset_buffer(&self->synth, single_channel_output, channel);
|
||||
}
|
||||
|
||||
audioio_get_buffer_result_t synthio_synthesizer_get_buffer(synthio_synthesizer_obj_t *self,
|
||||
bool single_channel_output, uint8_t channel, uint8_t **buffer, uint32_t *buffer_length) {
|
||||
self->synth.span.dur = SYNTHIO_MAX_DUR;
|
||||
synthio_synth_synthesize(&self->synth, buffer, buffer_length);
|
||||
synthio_synth_synthesize(&self->synth, buffer, buffer_length, single_channel_output ? channel : 0);
|
||||
return GET_BUFFER_MORE_DATA;
|
||||
}
|
||||
|
||||
|
@ -44,16 +44,27 @@ int synthio_span_count_active_channels(synthio_midi_span_t *span) {
|
||||
}
|
||||
|
||||
|
||||
void synthio_synth_synthesize(synthio_synth_t *synth, uint8_t **buffer, uint32_t *buffer_length) {
|
||||
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;
|
||||
int16_t *out_buffer = (int16_t *)(void *)synth->buffers[synth->buffer_index];
|
||||
|
||||
uint16_t dur = MIN(SYNTHIO_MAX_DUR, synth->span.dur);
|
||||
synth->span.dur -= dur;
|
||||
memset(synth->buffer, 0, synth->buffer_length);
|
||||
memset(out_buffer, 0, synth->buffer_length);
|
||||
|
||||
int32_t sample_rate = synth->sample_rate;
|
||||
int active_channels = synthio_span_count_active_channels(&synth->span);
|
||||
const int16_t *waveform = synth->waveform;
|
||||
uint32_t waveform_length = synth->waveform_length;
|
||||
int16_t *out_buffer = synth->buffer;
|
||||
if (active_channels) {
|
||||
int16_t loudness = 0x3fff / (1 + active_channels);
|
||||
for (int chan = 0; chan < CIRCUITPY_SYNTHIO_MAX_CHANNELS; chan++) {
|
||||
@ -84,27 +95,38 @@ void synthio_synth_synthesize(synthio_synth_t *synth, uint8_t **buffer, uint32_t
|
||||
}
|
||||
}
|
||||
|
||||
*buffer_length = dur * SYNTHIO_BYTES_PER_SAMPLE;
|
||||
*buffer = (uint8_t *)synth->buffer;
|
||||
*buffer_length = synth->last_buffer_length = dur * SYNTHIO_BYTES_PER_SAMPLE;
|
||||
*bufptr = (uint8_t *)out_buffer;
|
||||
}
|
||||
|
||||
void synthio_synth_reset_buffer(synthio_synth_t *synth, bool single_channel_output, uint8_t channel) {
|
||||
if (single_channel_output && channel == 1) {
|
||||
return;
|
||||
}
|
||||
synth->other_channel = -1;
|
||||
}
|
||||
|
||||
bool synthio_synth_deinited(synthio_synth_t *synth) {
|
||||
return synth->buffer == NULL;
|
||||
return synth->buffers[0] == NULL;
|
||||
}
|
||||
|
||||
void synthio_synth_deinit(synthio_synth_t *synth) {
|
||||
m_del(uint8_t, synth->buffer, synth->buffer_length);
|
||||
synth->buffer = NULL;
|
||||
m_del(uint8_t, synth->buffers[0], synth->buffer_length);
|
||||
m_del(uint8_t, synth->buffers[1], synth->buffer_length);
|
||||
synth->buffers[0] = NULL;
|
||||
synth->buffers[1] = NULL;
|
||||
}
|
||||
|
||||
void synthio_synth_init(synthio_synth_t *synth, uint16_t max_dur) {
|
||||
synth->buffer_length = MIN(SYNTHIO_MAX_DUR, max_dur) * SYNTHIO_BYTES_PER_SAMPLE;
|
||||
synth->buffer = m_malloc(synth->buffer_length, false);
|
||||
synth->buffers[0] = m_malloc(synth->buffer_length, false);
|
||||
synth->buffers[1] = m_malloc(synth->buffer_length, false);
|
||||
synth->other_channel = -1;
|
||||
}
|
||||
|
||||
void synthio_synth_get_buffer_structure(synthio_synth_t *synth, bool single_channel_output,
|
||||
bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing) {
|
||||
*single_buffer = true;
|
||||
*single_buffer = false;
|
||||
*samples_signed = true;
|
||||
*max_buffer_length = synth->buffer_length;
|
||||
*spacing = 1;
|
||||
|
@ -28,7 +28,7 @@
|
||||
|
||||
#define SYNTHIO_BITS_PER_SAMPLE (16)
|
||||
#define SYNTHIO_BYTES_PER_SAMPLE (SYNTHIO_BITS_PER_SAMPLE / 8)
|
||||
#define SYNTHIO_MAX_DUR (512)
|
||||
#define SYNTHIO_MAX_DUR (256)
|
||||
#define SYNTHIO_SILENCE (0x80)
|
||||
|
||||
#include "shared-module/audiocore/__init__.h"
|
||||
@ -40,21 +40,25 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
uint32_t sample_rate;
|
||||
int16_t *buffer;
|
||||
int16_t *buffers[2];
|
||||
const int16_t *waveform;
|
||||
uint16_t buffer_length;
|
||||
uint16_t last_buffer_length;
|
||||
uint8_t other_channel, buffer_index, other_buffer_index;
|
||||
uint16_t waveform_length;
|
||||
synthio_midi_span_t span;
|
||||
uint32_t accum[CIRCUITPY_SYNTHIO_MAX_CHANNELS];
|
||||
} synthio_synth_t;
|
||||
|
||||
void synthio_span_init(synthio_midi_span_t *span);
|
||||
void synthio_synth_synthesize(synthio_synth_t *synth, uint8_t **buffer, uint32_t *buffer_length);
|
||||
void synthio_synth_synthesize(synthio_synth_t *synth, uint8_t **buffer, uint32_t *buffer_length, uint8_t channel);
|
||||
void synthio_synth_deinit(synthio_synth_t *synth);
|
||||
bool synthio_synth_deinited(synthio_synth_t *synth);
|
||||
void synthio_synth_init(synthio_synth_t *synth, uint16_t max_dur);
|
||||
void synthio_synth_get_buffer_structure(synthio_synth_t *synth, bool single_channel_output,
|
||||
bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing);
|
||||
void synthio_synth_reset_buffer(synthio_synth_t *synth, bool single_channel_output, uint8_t channel);
|
||||
void synthio_synth_parse_waveform(mp_buffer_info_t *bufinfo_waveform, mp_obj_t waveform_obj);
|
||||
|
||||
bool synthio_span_change_note(synthio_midi_span_t *span, uint8_t old_note, uint8_t new_note);
|
||||
int synthio_span_count_active_channels(synthio_midi_span_t *span);
|
||||
|
Loading…
x
Reference in New Issue
Block a user