Skip to content

Commit 04f4092

Browse files
committed
synthio: support audio outputs that need double buffering
closes #7837 tested on rp2040 pico w on pico dv shield
1 parent 9679aaa commit 04f4092

File tree

4 files changed

+43
-16
lines changed

4 files changed

+43
-16
lines changed

shared-module/synthio/MidiTrack.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ uint8_t common_hal_synthio_miditrack_get_channel_count(synthio_miditrack_obj_t *
156156

157157
void synthio_miditrack_reset_buffer(synthio_miditrack_obj_t *self,
158158
bool single_channel_output, uint8_t channel) {
159-
159+
synthio_synth_reset_buffer(&self->synth, single_channel_output, channel);
160160
self->synth.span.dur = 0;
161161
self->next_span = 0;
162162
}
@@ -172,7 +172,7 @@ audioio_get_buffer_result_t synthio_miditrack_get_buffer(synthio_miditrack_obj_t
172172
self->synth.span = self->track[self->next_span++];
173173
}
174174

175-
synthio_synth_synthesize(&self->synth, buffer, buffer_length);
175+
synthio_synth_synthesize(&self->synth, buffer, buffer_length, single_channel_output ? 0 : channel);
176176

177177
return (self->synth.span.dur == 0 && self->next_span >= self->total_spans) ?
178178
GET_BUFFER_DONE : GET_BUFFER_MORE_DATA;

shared-module/synthio/Synthesizer.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,13 @@ uint8_t common_hal_synthio_synthesizer_get_channel_count(synthio_synthesizer_obj
5858

5959
void synthio_synthesizer_reset_buffer(synthio_synthesizer_obj_t *self,
6060
bool single_channel_output, uint8_t channel) {
61+
synthio_synth_reset_buffer(&self->synth, single_channel_output, channel);
6162
}
6263

6364
audioio_get_buffer_result_t synthio_synthesizer_get_buffer(synthio_synthesizer_obj_t *self,
6465
bool single_channel_output, uint8_t channel, uint8_t **buffer, uint32_t *buffer_length) {
6566
self->synth.span.dur = SYNTHIO_MAX_DUR;
66-
synthio_synth_synthesize(&self->synth, buffer, buffer_length);
67+
synthio_synth_synthesize(&self->synth, buffer, buffer_length, single_channel_output ? channel : 0);
6768
return GET_BUFFER_MORE_DATA;
6869
}
6970

shared-module/synthio/__init__.c

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,16 +44,27 @@ int synthio_span_count_active_channels(synthio_midi_span_t *span) {
4444
}
4545

4646

47-
void synthio_synth_synthesize(synthio_synth_t *synth, uint8_t **buffer, uint32_t *buffer_length) {
47+
void synthio_synth_synthesize(synthio_synth_t *synth, uint8_t **bufptr, uint32_t *buffer_length, uint8_t channel) {
48+
49+
if (channel == synth->other_channel) {
50+
*buffer_length = synth->last_buffer_length;
51+
*bufptr = (uint8_t *)(synth->buffers[synth->other_buffer_index] + channel);
52+
return;
53+
}
54+
55+
synth->buffer_index = !synth->buffer_index;
56+
synth->other_channel = 1 - channel;
57+
synth->other_buffer_index = synth->buffer_index;
58+
int16_t *out_buffer = (int16_t *)(void *)synth->buffers[synth->buffer_index];
59+
4860
uint16_t dur = MIN(SYNTHIO_MAX_DUR, synth->span.dur);
4961
synth->span.dur -= dur;
50-
memset(synth->buffer, 0, synth->buffer_length);
62+
memset(out_buffer, 0, synth->buffer_length);
5163

5264
int32_t sample_rate = synth->sample_rate;
5365
int active_channels = synthio_span_count_active_channels(&synth->span);
5466
const int16_t *waveform = synth->waveform;
5567
uint32_t waveform_length = synth->waveform_length;
56-
int16_t *out_buffer = synth->buffer;
5768
if (active_channels) {
5869
int16_t loudness = 0x3fff / (1 + active_channels);
5970
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
8495
}
8596
}
8697

87-
*buffer_length = dur * SYNTHIO_BYTES_PER_SAMPLE;
88-
*buffer = (uint8_t *)synth->buffer;
98+
*buffer_length = synth->last_buffer_length = dur * SYNTHIO_BYTES_PER_SAMPLE;
99+
*bufptr = (uint8_t *)out_buffer;
100+
}
101+
102+
void synthio_synth_reset_buffer(synthio_synth_t *synth, bool single_channel_output, uint8_t channel) {
103+
if (single_channel_output && channel == 1) {
104+
return;
105+
}
106+
synth->other_channel = -1;
89107
}
90108

91109
bool synthio_synth_deinited(synthio_synth_t *synth) {
92-
return synth->buffer == NULL;
110+
return synth->buffers[0] == NULL;
93111
}
94112

95113
void synthio_synth_deinit(synthio_synth_t *synth) {
96-
m_del(uint8_t, synth->buffer, synth->buffer_length);
97-
synth->buffer = NULL;
114+
m_del(uint8_t, synth->buffers[0], synth->buffer_length);
115+
m_del(uint8_t, synth->buffers[1], synth->buffer_length);
116+
synth->buffers[0] = NULL;
117+
synth->buffers[1] = NULL;
98118
}
99119

100120
void synthio_synth_init(synthio_synth_t *synth, uint16_t max_dur) {
101121
synth->buffer_length = MIN(SYNTHIO_MAX_DUR, max_dur) * SYNTHIO_BYTES_PER_SAMPLE;
102-
synth->buffer = m_malloc(synth->buffer_length, false);
122+
synth->buffers[0] = m_malloc(synth->buffer_length, false);
123+
synth->buffers[1] = m_malloc(synth->buffer_length, false);
124+
synth->other_channel = -1;
103125
}
104126

105127
void synthio_synth_get_buffer_structure(synthio_synth_t *synth, bool single_channel_output,
106128
bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing) {
107-
*single_buffer = true;
129+
*single_buffer = false;
108130
*samples_signed = true;
109131
*max_buffer_length = synth->buffer_length;
110132
*spacing = 1;

shared-module/synthio/__init__.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929
#define SYNTHIO_BITS_PER_SAMPLE (16)
3030
#define SYNTHIO_BYTES_PER_SAMPLE (SYNTHIO_BITS_PER_SAMPLE / 8)
31-
#define SYNTHIO_MAX_DUR (512)
31+
#define SYNTHIO_MAX_DUR (256)
3232
#define SYNTHIO_SILENCE (0x80)
3333

3434
#include "shared-module/audiocore/__init__.h"
@@ -40,21 +40,25 @@ typedef struct {
4040

4141
typedef struct {
4242
uint32_t sample_rate;
43-
int16_t *buffer;
43+
int16_t *buffers[2];
4444
const int16_t *waveform;
4545
uint16_t buffer_length;
46+
uint16_t last_buffer_length;
47+
uint8_t other_channel, buffer_index, other_buffer_index;
4648
uint16_t waveform_length;
4749
synthio_midi_span_t span;
4850
uint32_t accum[CIRCUITPY_SYNTHIO_MAX_CHANNELS];
4951
} synthio_synth_t;
5052

5153
void synthio_span_init(synthio_midi_span_t *span);
52-
void synthio_synth_synthesize(synthio_synth_t *synth, uint8_t **buffer, uint32_t *buffer_length);
54+
void synthio_synth_synthesize(synthio_synth_t *synth, uint8_t **buffer, uint32_t *buffer_length, uint8_t channel);
5355
void synthio_synth_deinit(synthio_synth_t *synth);
5456
bool synthio_synth_deinited(synthio_synth_t *synth);
5557
void synthio_synth_init(synthio_synth_t *synth, uint16_t max_dur);
5658
void synthio_synth_get_buffer_structure(synthio_synth_t *synth, bool single_channel_output,
5759
bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing);
60+
void synthio_synth_reset_buffer(synthio_synth_t *synth, bool single_channel_output, uint8_t channel);
5861
void synthio_synth_parse_waveform(mp_buffer_info_t *bufinfo_waveform, mp_obj_t waveform_obj);
62+
5963
bool synthio_span_change_note(synthio_midi_span_t *span, uint8_t old_note, uint8_t new_note);
6064
int synthio_span_count_active_channels(synthio_midi_span_t *span);

0 commit comments

Comments
 (0)