audiocore: remove support for "single buffer"

This is only needed on samd51, and most of the complexity can be
implemented just once instead of in each audio sample type.

This saves 968 bytes flash on feather rp2350. More importantly,
it'll save some fraction as much on samd21 where stereo audio output
is not supported at all (but savings will be less overall because
fewer audiosample types are available)

Other builds besides raspberrypi are broken & raspberrypi is not even
tested.
This commit is contained in:
Jeff Epler 2024-12-09 09:18:59 -06:00
parent 80dff32543
commit 775addafd3
24 changed files with 215 additions and 396 deletions

View file

@ -92,6 +92,8 @@ endif # samd21
ifeq ($(CHIP_FAMILY),samd51)
CIRCUITPY_AUDIOCORE_SINGLE_CHANNEL_OUTPUT = 1
# No native touchio on SAMD51.
CIRCUITPY_TOUCHIO_USE_NATIVE = 0

View file

@ -124,7 +124,7 @@ static void audio_dma_load_next_block(audio_dma_t *dma, size_t buffer_idx) {
uint8_t *sample_buffer;
uint32_t sample_buffer_length;
get_buffer_result = audiosample_get_buffer(dma->sample,
false /* single_channel_output*/, dma->audio_channel, &sample_buffer, &sample_buffer_length);
&sample_buffer, &sample_buffer_length);
if (get_buffer_result == GET_BUFFER_ERROR) {
audio_dma_stop(dma);
@ -144,7 +144,7 @@ static void audio_dma_load_next_block(audio_dma_t *dma, size_t buffer_idx) {
if (get_buffer_result == GET_BUFFER_DONE) {
if (dma->loop) {
audiosample_reset_buffer(dma->sample, false /* single_channel_output */, dma->audio_channel);
audiosample_reset_buffer(dma->sample);
} else {
// Set channel trigger to ourselves so we don't keep going.
dma_channel_hw_t *c = &dma_hw->ch[dma_channel];
@ -203,25 +203,20 @@ audio_dma_result audio_dma_setup_playback(
dma->output_register_address = output_register_address;
dma->swap_channel = swap_channel;
audiosample_reset_buffer(sample, false /* single_channel_output */, audio_channel);
audiosample_reset_buffer(sample);
bool single_buffer; // True if data fits in one single buffer.
bool samples_signed;
uint32_t max_buffer_length;
audiosample_get_buffer_structure(sample, false /* single_channel_output */, &single_buffer, &samples_signed,
&max_buffer_length, &dma->sample_spacing);
audiosample_get_buffer_structure(sample, &single_buffer, &samples_signed,
&max_buffer_length);
// Check to see if we have to scale the resolution up.
if (dma->sample_resolution <= 8 && dma->output_resolution > 8) {
max_buffer_length *= 2;
}
if (output_signed != samples_signed ||
dma->sample_spacing > 1 ||
(dma->sample_resolution != dma->output_resolution)) {
max_buffer_length /= dma->sample_spacing;
}
dma->buffer[0] = (uint8_t *)m_realloc(dma->buffer[0], max_buffer_length);
dma->buffer_length[0] = max_buffer_length;

View file

@ -130,6 +130,9 @@ CFLAGS += -DCIRCUITPY_AUDIOPWMIO=$(CIRCUITPY_AUDIOPWMIO)
CIRCUITPY_AUDIOCORE ?= $(call enable-if-any,$(CIRCUITPY_AUDIOPWMIO) $(CIRCUITPY_AUDIOIO) $(CIRCUITPY_AUDIOBUSIO))
CFLAGS += -DCIRCUITPY_AUDIOCORE=$(CIRCUITPY_AUDIOCORE)
CIRCUITPY_AUDIOCORE_SINGLE_CHANNEL_OUTPUT ?= 0
CFLAGS += -DCIRCUITPY_AUDIOCORE_SINGLE_CHANNEL_OUTPUT=$(CIRCUITPY_AUDIOCORE_SINGLE_CHANNEL_OUTPUT)
CIRCUITPY_AUDIOMIXER ?= $(CIRCUITPY_AUDIOCORE)
CFLAGS += -DCIRCUITPY_AUDIOMIXER=$(CIRCUITPY_AUDIOMIXER)

View file

@ -52,48 +52,30 @@ uint8_t common_hal_audioio_rawsample_get_channel_count(audioio_rawsample_obj_t *
return self->channel_count;
}
void audioio_rawsample_reset_buffer(audioio_rawsample_obj_t *self,
bool single_channel_output,
uint8_t channel) {
void audioio_rawsample_reset_buffer(audioio_rawsample_obj_t *self) {
}
audioio_get_buffer_result_t audioio_rawsample_get_buffer(audioio_rawsample_obj_t *self,
bool single_channel_output,
uint8_t channel,
uint8_t **buffer,
uint32_t *buffer_length) {
if (self->single_buffer) {
*buffer_length = self->len;
if (single_channel_output) {
*buffer = self->buffer + (channel % self->channel_count) * (self->bits_per_sample / 8);
} else {
*buffer = self->buffer;
}
*buffer = self->buffer;
return GET_BUFFER_DONE;
} else {
*buffer_length = self->len / 2;
if (single_channel_output) {
*buffer = self->buffer + (channel % self->channel_count) * (self->bits_per_sample / 8) + \
self->len / 2 * self->buffer_index;
} else {
*buffer = self->buffer + self->len / 2 * self->buffer_index;
}
*buffer = self->buffer + self->len / 2 * self->buffer_index;
self->buffer_index = 1 - self->buffer_index;
return GET_BUFFER_DONE;
}
}
void audioio_rawsample_get_buffer_structure(audioio_rawsample_obj_t *self, bool single_channel_output,
void audioio_rawsample_get_buffer_structure(audioio_rawsample_obj_t *self,
bool *single_buffer, bool *samples_signed,
uint32_t *max_buffer_length, uint8_t *spacing) {
uint32_t *max_buffer_length) {
*single_buffer = self->single_buffer;
*samples_signed = self->samples_signed;
*max_buffer_length = self->len;
if (single_channel_output) {
*spacing = self->channel_count;
} else {
*spacing = 1;
}
}

View file

@ -24,14 +24,10 @@ typedef struct {
// These are not available from Python because it may be called in an interrupt.
void audioio_rawsample_reset_buffer(audioio_rawsample_obj_t *self,
bool single_channel_output,
uint8_t channel);
void audioio_rawsample_reset_buffer(audioio_rawsample_obj_t *self);
audioio_get_buffer_result_t audioio_rawsample_get_buffer(audioio_rawsample_obj_t *self,
bool single_channel_output,
uint8_t channel,
uint8_t **buffer,
uint32_t *buffer_length); // length in bytes
void audioio_rawsample_get_buffer_structure(audioio_rawsample_obj_t *self, bool single_channel_output,
void audioio_rawsample_get_buffer_structure(audioio_rawsample_obj_t *self,
bool *single_buffer, bool *samples_signed,
uint32_t *max_buffer_length, uint8_t *spacing);
uint32_t *max_buffer_length);

View file

@ -137,113 +137,72 @@ uint8_t common_hal_audioio_wavefile_get_channel_count(audioio_wavefile_obj_t *se
return self->channel_count;
}
void audioio_wavefile_reset_buffer(audioio_wavefile_obj_t *self,
bool single_channel_output,
uint8_t channel) {
if (single_channel_output && channel == 1) {
return;
}
void audioio_wavefile_reset_buffer(audioio_wavefile_obj_t *self) {
// We don't reset the buffer index in case we're looping and we have an odd number of buffer
// loads
self->bytes_remaining = self->file_length;
f_lseek(&self->file->fp, self->data_start);
self->read_count = 0;
self->left_read_count = 0;
self->right_read_count = 0;
}
audioio_get_buffer_result_t audioio_wavefile_get_buffer(audioio_wavefile_obj_t *self,
bool single_channel_output,
uint8_t channel,
uint8_t **buffer,
uint32_t *buffer_length) {
if (!single_channel_output) {
channel = 0;
}
uint32_t channel_read_count = self->left_read_count;
if (channel == 1) {
channel_read_count = self->right_read_count;
}
bool need_more_data = self->read_count == channel_read_count;
if (self->bytes_remaining == 0 && need_more_data) {
if (self->bytes_remaining == 0) {
*buffer = NULL;
*buffer_length = 0;
return GET_BUFFER_DONE;
}
if (need_more_data) {
uint32_t num_bytes_to_load = self->len;
if (num_bytes_to_load > self->bytes_remaining) {
num_bytes_to_load = self->bytes_remaining;
}
UINT length_read;
if (self->buffer_index % 2 == 1) {
*buffer = self->second_buffer;
} else {
*buffer = self->buffer;
}
if (f_read(&self->file->fp, *buffer, num_bytes_to_load, &length_read) != FR_OK || length_read != num_bytes_to_load) {
return GET_BUFFER_ERROR;
}
self->bytes_remaining -= length_read;
// Pad the last buffer to word align it.
if (self->bytes_remaining == 0 && length_read % sizeof(uint32_t) != 0) {
uint32_t pad = length_read % sizeof(uint32_t);
length_read += pad;
if (self->bits_per_sample == 8) {
for (uint32_t i = 0; i < pad; i++) {
((uint8_t *)(*buffer))[length_read / sizeof(uint8_t) - i - 1] = 0x80;
}
} else if (self->bits_per_sample == 16) {
// We know the buffer is aligned because we allocated it onto the heap ourselves.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align"
((int16_t *)(*buffer))[length_read / sizeof(int16_t) - 1] = 0;
#pragma GCC diagnostic pop
}
}
*buffer_length = length_read;
if (self->buffer_index % 2 == 1) {
self->second_buffer_length = length_read;
} else {
self->buffer_length = length_read;
}
self->buffer_index += 1;
self->read_count += 1;
uint32_t num_bytes_to_load = self->len;
if (num_bytes_to_load > self->bytes_remaining) {
num_bytes_to_load = self->bytes_remaining;
}
uint32_t buffers_back = self->read_count - 1 - channel_read_count;
if ((self->buffer_index - buffers_back) % 2 == 0) {
UINT length_read;
if (self->buffer_index % 2 == 1) {
*buffer = self->second_buffer;
*buffer_length = self->second_buffer_length;
} else {
*buffer = self->buffer;
*buffer_length = self->buffer_length;
}
if (f_read(&self->file->fp, *buffer, num_bytes_to_load, &length_read) != FR_OK || length_read != num_bytes_to_load) {
return GET_BUFFER_ERROR;
}
self->bytes_remaining -= length_read;
// Pad the last buffer to word align it.
if (self->bytes_remaining == 0 && length_read % sizeof(uint32_t) != 0) {
uint32_t pad = length_read % sizeof(uint32_t);
length_read += pad;
if (self->bits_per_sample == 8) {
for (uint32_t i = 0; i < pad; i++) {
((uint8_t *)(*buffer))[length_read / sizeof(uint8_t) - i - 1] = 0x80;
}
} else if (self->bits_per_sample == 16) {
// We know the buffer is aligned because we allocated it onto the heap ourselves.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align"
((int16_t *)(*buffer))[length_read / sizeof(int16_t) - 1] = 0;
#pragma GCC diagnostic pop
}
}
*buffer_length = length_read;
if (self->buffer_index % 2 == 1) {
self->second_buffer_length = length_read;
} else {
self->buffer_length = length_read;
}
self->buffer_index += 1;
if (channel == 0) {
self->left_read_count += 1;
} else if (channel == 1) {
self->right_read_count += 1;
*buffer = *buffer + self->bits_per_sample / 8;
}
*buffer = self->buffer;
*buffer_length = self->buffer_length;
return self->bytes_remaining == 0 ? GET_BUFFER_DONE : GET_BUFFER_MORE_DATA;
}
void audioio_wavefile_get_buffer_structure(audioio_wavefile_obj_t *self, bool single_channel_output,
void audioio_wavefile_get_buffer_structure(audioio_wavefile_obj_t *self,
bool *single_buffer, bool *samples_signed,
uint32_t *max_buffer_length, uint8_t *spacing) {
uint32_t *max_buffer_length) {
*single_buffer = false;
// In WAV files, 8-bit samples are always unsigned, and larger samples are always signed.
*samples_signed = self->bits_per_sample > 8;
*max_buffer_length = 512;
if (single_channel_output) {
*spacing = self->channel_count;
} else {
*spacing = 1;
}
}

View file

@ -35,14 +35,11 @@ typedef struct {
} audioio_wavefile_obj_t;
// These are not available from Python because it may be called in an interrupt.
void audioio_wavefile_reset_buffer(audioio_wavefile_obj_t *self,
bool single_channel_output,
uint8_t channel);
void audioio_wavefile_reset_buffer(audioio_wavefile_obj_t *self
);
audioio_get_buffer_result_t audioio_wavefile_get_buffer(audioio_wavefile_obj_t *self,
bool single_channel_output,
uint8_t channel,
uint8_t **buffer,
uint32_t *buffer_length); // length in bytes
void audioio_wavefile_get_buffer_structure(audioio_wavefile_obj_t *self, bool single_channel_output,
void audioio_wavefile_get_buffer_structure(audioio_wavefile_obj_t *self,
bool *single_buffer, bool *samples_signed,
uint32_t *max_buffer_length, uint8_t *spacing);
uint32_t *max_buffer_length);

View file

@ -30,27 +30,53 @@ uint8_t audiosample_channel_count(mp_obj_t sample_obj) {
return proto->channel_count(MP_OBJ_TO_PTR(sample_obj));
}
void audiosample_reset_buffer(mp_obj_t sample_obj, bool single_channel_output, uint8_t audio_channel) {
void audiosample_reset_buffer(mp_obj_t sample_obj) {
const audiosample_p_t *proto = mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, sample_obj);
proto->reset_buffer(MP_OBJ_TO_PTR(sample_obj), single_channel_output, audio_channel);
proto->reset_buffer(MP_OBJ_TO_PTR(sample_obj));
}
audioio_get_buffer_result_t audiosample_get_buffer(mp_obj_t sample_obj,
uint8_t **buffer, uint32_t *buffer_length) {
const audiosample_p_t *proto = mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, sample_obj);
return proto->get_buffer(MP_OBJ_TO_PTR(sample_obj), buffer, buffer_length);
}
void audiosample_get_buffer_structure(mp_obj_t sample_obj,
bool *single_buffer, bool *samples_signed,
uint32_t *max_buffer_length) {
const audiosample_p_t *proto = mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, sample_obj);
proto->get_buffer_structure(MP_OBJ_TO_PTR(sample_obj), single_buffer,
samples_signed, max_buffer_length);
}
#if CIRCUITPY_AUDIOCORE_SINGLE_CHANNEL_OUTPUT
audioio_get_buffer_result_t audiosample_get_buffer_sco(mp_obj_t sample_obj,
bool single_channel_output,
uint8_t channel,
uint8_t **buffer, uint32_t *buffer_length) {
const audiosample_p_t *proto = mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, sample_obj);
return proto->get_buffer(MP_OBJ_TO_PTR(sample_obj), single_channel_output, channel, buffer, buffer_length);
if (single_channel_output) {
// TODO: implement it
abort();
}
return audiosample_get_buffer(sample_obj, buffer, buffer_length);
}
void audiosample_get_buffer_structure(mp_obj_t sample_obj, bool single_channel_output,
void audiosample_get_buffer_structure_sco(mp_obj_t sample_obj,
bool single_channel_output,
bool *single_buffer, bool *samples_signed,
uint32_t *max_buffer_length, uint8_t *spacing) {
const audiosample_p_t *proto = mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, sample_obj);
proto->get_buffer_structure(MP_OBJ_TO_PTR(sample_obj), single_channel_output, single_buffer,
proto->get_buffer_structure(MP_OBJ_TO_PTR(sample_obj), single_buffer,
samples_signed, max_buffer_length, spacing);
if (single_channel_output) {
spacing = audiosample_channel_count(sample_obj);
} else {
spacing = 1;
}
}
#endif
void audiosample_convert_u8m_s16s(int16_t *buffer_out, const uint8_t *buffer_in, size_t nframes) {
for (; nframes--;) {
int16_t sample = (*buffer_in++ - 0x80) << 8;

View file

@ -21,15 +21,13 @@ typedef enum {
typedef uint32_t (*audiosample_sample_rate_fun)(mp_obj_t);
typedef uint8_t (*audiosample_bits_per_sample_fun)(mp_obj_t);
typedef uint8_t (*audiosample_channel_count_fun)(mp_obj_t);
typedef void (*audiosample_reset_buffer_fun)(mp_obj_t,
bool single_channel_output, uint8_t audio_channel);
typedef void (*audiosample_reset_buffer_fun)(mp_obj_t);
typedef audioio_get_buffer_result_t (*audiosample_get_buffer_fun)(mp_obj_t,
bool single_channel_output, uint8_t channel, uint8_t **buffer,
uint8_t **buffer,
uint32_t *buffer_length);
typedef void (*audiosample_get_buffer_structure_fun)(mp_obj_t,
bool single_channel_output, bool *single_buffer,
bool *samples_signed, uint32_t *max_buffer_length,
uint8_t *spacing);
bool *single_buffer,
bool *samples_signed, uint32_t *max_buffer_length);
typedef struct _audiosample_p_t {
MP_PROTOCOL_HEAD // MP_QSTR_protocol_audiosample
@ -44,15 +42,23 @@ typedef struct _audiosample_p_t {
uint32_t audiosample_sample_rate(mp_obj_t sample_obj);
uint8_t audiosample_bits_per_sample(mp_obj_t sample_obj);
uint8_t audiosample_channel_count(mp_obj_t sample_obj);
void audiosample_reset_buffer(mp_obj_t sample_obj, bool single_channel_output, uint8_t audio_channel);
audioio_get_buffer_result_t audiosample_get_buffer(mp_obj_t sample_obj,
void audiosample_reset_buffer(mp_obj_t sample_obj);
#if CIRCUITPY_AUDIOCORE_SINGLE_CHANNEL_OUTPUT
audioio_get_buffer_result_t audiosample_get_buffer_sco(mp_obj_t sample_obj,
bool single_channel_output,
uint8_t channel,
uint8_t **buffer, uint32_t *buffer_length);
void audiosample_get_buffer_structure(mp_obj_t sample_obj, bool single_channel_output,
#endif
audioio_get_buffer_result_t audiosample_get_buffer(mp_obj_t sample_obj,
uint8_t **buffer, uint32_t *buffer_length);
#if CIRCUITPY_AUDIOCORE_SINGLE_CHANNEL_OUTPUT
void audiosample_get_buffer_structure_sco(mp_obj_t sample_obj, bool single_channel_output,
bool *single_buffer, bool *samples_signed,
uint32_t *max_buffer_length, uint8_t *spacing);
uint32_t *max_buffer_length);
#endif
void audiosample_get_buffer_structure(mp_obj_t sample_obj,
bool *single_buffer, bool *samples_signed,
uint32_t *max_buffer_length);
void audiosample_convert_u8m_s16s(int16_t *buffer_out, const uint8_t *buffer_in, size_t nframes);
void audiosample_convert_u8s_s16s(int16_t *buffer_out, const uint8_t *buffer_in, size_t nframes);
void audiosample_convert_s8m_s16s(int16_t *buffer_out, const int8_t *buffer_in, size_t nframes);

View file

@ -95,7 +95,7 @@ void common_hal_audiodelays_echo_construct(audiodelays_echo_obj_t *self, uint32_
self->echo_buffer_write_pos = 0;
// where we read the previous echo from delay_ms ago to play back now (for freq shift)
self->echo_buffer_left_pos = self->echo_buffer_right_pos = 0;
self->echo_buffer_pos = 0;
}
bool common_hal_audiodelays_echo_deinited(audiodelays_echo_obj_t *self) {
@ -194,9 +194,8 @@ uint8_t common_hal_audiodelays_echo_get_bits_per_sample(audiodelays_echo_obj_t *
return self->bits_per_sample;
}
void audiodelays_echo_reset_buffer(audiodelays_echo_obj_t *self,
bool single_channel_output,
uint8_t channel) {
void audiodelays_echo_reset_buffer(audiodelays_echo_obj_t *self
) {
memset(self->buffer[0], 0, self->buffer_len);
memset(self->buffer[1], 0, self->buffer_len);
@ -224,8 +223,7 @@ void common_hal_audiodelays_echo_play(audiodelays_echo_obj_t *self, mp_obj_t sam
bool single_buffer;
bool samples_signed;
uint32_t max_buffer_length;
uint8_t spacing;
audiosample_get_buffer_structure(sample, false, &single_buffer, &samples_signed, &max_buffer_length, &spacing);
audiosample_get_buffer_structure(sample, &single_buffer, &samples_signed, &max_buffer_length);
if (samples_signed != self->samples_signed) {
mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_signedness);
}
@ -233,8 +231,8 @@ void common_hal_audiodelays_echo_play(audiodelays_echo_obj_t *self, mp_obj_t sam
self->sample = sample;
self->loop = loop;
audiosample_reset_buffer(self->sample, false, 0);
audioio_get_buffer_result_t result = audiosample_get_buffer(self->sample, false, 0, (uint8_t **)&self->sample_remaining_buffer, &self->sample_buffer_length);
audiosample_reset_buffer(self->sample);
audioio_get_buffer_result_t result = audiosample_get_buffer(self->sample, (uint8_t **)&self->sample_remaining_buffer, &self->sample_buffer_length);
// Track remaining sample length in terms of bytes per sample
self->sample_buffer_length /= (self->bits_per_sample / 8);
@ -277,13 +275,9 @@ int16_t mix_down_sample(int32_t sample) {
return sample;
}
audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *self, bool single_channel_output, uint8_t channel,
audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *self,
uint8_t **buffer, uint32_t *buffer_length) {
if (!single_channel_output) {
channel = 0;
}
// get the effect values we need from the BlockInput. These may change at run time so you need to do bounds checking if required
mp_float_t mix = MIN(1.0, MAX(synthio_block_slot_get(&self->mix), 0.0));
mp_float_t decay = MIN(1.0, MAX(synthio_block_slot_get(&self->decay), 0.0));
@ -307,12 +301,7 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
// Set our echo buffer position accounting for stereo
uint32_t echo_buffer_pos = 0;
if (self->freq_shift) {
echo_buffer_pos = self->echo_buffer_left_pos;
if (channel == 1) {
echo_buffer_pos = self->echo_buffer_right_pos;
}
}
echo_buffer_pos = self->echo_buffer_pos;
// Loop over the entire length of our buffer to fill it, this may require several calls to get data from the sample
while (length != 0) {
@ -320,14 +309,14 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
if (self->sample_buffer_length == 0) {
if (!self->more_data) { // The sample has indicated it has no more data to play
if (self->loop && self->sample) { // If we are supposed to loop reset the sample to the start
audiosample_reset_buffer(self->sample, false, 0);
audiosample_reset_buffer(self->sample);
} else { // If we were not supposed to loop the sample, stop playing it but we still need to play the echo
self->sample = NULL;
}
}
if (self->sample) {
// Load another sample buffer to play
audioio_get_buffer_result_t result = audiosample_get_buffer(self->sample, false, 0, (uint8_t **)&self->sample_remaining_buffer, &self->sample_buffer_length);
audioio_get_buffer_result_t result = audiosample_get_buffer(self->sample, (uint8_t **)&self->sample_remaining_buffer, &self->sample_buffer_length);
// Track length in terms of words.
self->sample_buffer_length /= (self->bits_per_sample / 8);
self->more_data = result == GET_BUFFER_MORE_DATA;
@ -502,13 +491,7 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
}
}
if (self->freq_shift) {
if (channel == 0) {
self->echo_buffer_left_pos = echo_buffer_pos;
} else if (channel == 1) {
self->echo_buffer_right_pos = echo_buffer_pos;
}
}
self->echo_buffer_pos = echo_buffer_pos;
// Finally pass our buffer and length to the calling audio function
*buffer = (uint8_t *)self->buffer[self->last_buf_idx];
@ -518,17 +501,12 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
return GET_BUFFER_MORE_DATA;
}
void audiodelays_echo_get_buffer_structure(audiodelays_echo_obj_t *self, bool single_channel_output,
bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing) {
void audiodelays_echo_get_buffer_structure(audiodelays_echo_obj_t *self,
bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length) {
// Return information about the effect's buffer (not the sample's)
// These are used by calling audio objects to determine how to handle the effect's buffer
*single_buffer = false;
*samples_signed = self->samples_signed;
*max_buffer_length = self->buffer_len;
if (single_channel_output) {
*spacing = self->channel_count;
} else {
*spacing = 1;
}
}

View file

@ -44,24 +44,19 @@ typedef struct {
uint32_t echo_buffer_write_pos; // words
uint32_t echo_buffer_rate; // words << 8
uint32_t echo_buffer_left_pos; // words << 8
uint32_t echo_buffer_right_pos; // words << 8
uint32_t echo_buffer_pos; // words << 8
mp_obj_t sample;
} audiodelays_echo_obj_t;
void recalculate_delay(audiodelays_echo_obj_t *self, mp_float_t f_delay_ms);
void audiodelays_echo_reset_buffer(audiodelays_echo_obj_t *self,
bool single_channel_output,
uint8_t channel);
void audiodelays_echo_reset_buffer(audiodelays_echo_obj_t *self);
audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *self,
bool single_channel_output,
uint8_t channel,
uint8_t **buffer,
uint32_t *buffer_length); // length in bytes
void audiodelays_echo_get_buffer_structure(audiodelays_echo_obj_t *self, bool single_channel_output,
void audiodelays_echo_get_buffer_structure(audiodelays_echo_obj_t *self,
bool *single_buffer, bool *samples_signed,
uint32_t *max_buffer_length, uint8_t *spacing);
uint32_t *max_buffer_length);

View file

@ -154,9 +154,7 @@ uint8_t common_hal_audiofilters_filter_get_bits_per_sample(audiofilters_filter_o
return self->bits_per_sample;
}
void audiofilters_filter_reset_buffer(audiofilters_filter_obj_t *self,
bool single_channel_output,
uint8_t channel) {
void audiofilters_filter_reset_buffer(audiofilters_filter_obj_t *self) {
memset(self->buffer[0], 0, self->buffer_len);
memset(self->buffer[1], 0, self->buffer_len);
@ -190,8 +188,7 @@ void common_hal_audiofilters_filter_play(audiofilters_filter_obj_t *self, mp_obj
bool single_buffer;
bool samples_signed;
uint32_t max_buffer_length;
uint8_t spacing;
audiosample_get_buffer_structure(sample, false, &single_buffer, &samples_signed, &max_buffer_length, &spacing);
audiosample_get_buffer_structure(sample, &single_buffer, &samples_signed, &max_buffer_length);
if (samples_signed != self->samples_signed) {
mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_signedness);
}
@ -199,8 +196,8 @@ void common_hal_audiofilters_filter_play(audiofilters_filter_obj_t *self, mp_obj
self->sample = sample;
self->loop = loop;
audiosample_reset_buffer(self->sample, false, 0);
audioio_get_buffer_result_t result = audiosample_get_buffer(self->sample, false, 0, (uint8_t **)&self->sample_remaining_buffer, &self->sample_buffer_length);
audiosample_reset_buffer(self->sample);
audioio_get_buffer_result_t result = audiosample_get_buffer(self->sample, (uint8_t **)&self->sample_remaining_buffer, &self->sample_buffer_length);
// Track remaining sample length in terms of bytes per sample
self->sample_buffer_length /= (self->bits_per_sample / 8);
@ -242,13 +239,8 @@ int16_t mix_down_sample(int32_t sample) {
return sample;
}
audioio_get_buffer_result_t audiofilters_filter_get_buffer(audiofilters_filter_obj_t *self, bool single_channel_output, uint8_t channel,
audioio_get_buffer_result_t audiofilters_filter_get_buffer(audiofilters_filter_obj_t *self,
uint8_t **buffer, uint32_t *buffer_length) {
(void)channel;
if (!single_channel_output) {
channel = 0;
}
// get the effect values we need from the BlockInput. These may change at run time so you need to do bounds checking if required
mp_float_t mix = MIN(1.0, MAX(synthio_block_slot_get(&self->mix), 0.0));
@ -267,14 +259,14 @@ audioio_get_buffer_result_t audiofilters_filter_get_buffer(audiofilters_filter_o
if (self->sample_buffer_length == 0) {
if (!self->more_data) { // The sample has indicated it has no more data to play
if (self->loop && self->sample) { // If we are supposed to loop reset the sample to the start
audiosample_reset_buffer(self->sample, false, 0);
audiosample_reset_buffer(self->sample);
} else { // If we were not supposed to loop the sample, stop playing it
self->sample = NULL;
}
}
if (self->sample) {
// Load another sample buffer to play
audioio_get_buffer_result_t result = audiosample_get_buffer(self->sample, false, 0, (uint8_t **)&self->sample_remaining_buffer, &self->sample_buffer_length);
audioio_get_buffer_result_t result = audiosample_get_buffer(self->sample, (uint8_t **)&self->sample_remaining_buffer, &self->sample_buffer_length);
// Track length in terms of words.
self->sample_buffer_length /= (self->bits_per_sample / 8);
self->more_data = result == GET_BUFFER_MORE_DATA;
@ -374,17 +366,12 @@ audioio_get_buffer_result_t audiofilters_filter_get_buffer(audiofilters_filter_o
return GET_BUFFER_MORE_DATA;
}
void audiofilters_filter_get_buffer_structure(audiofilters_filter_obj_t *self, bool single_channel_output,
bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing) {
void audiofilters_filter_get_buffer_structure(audiofilters_filter_obj_t *self,
bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length) {
// Return information about the effect's buffer (not the sample's)
// These are used by calling audio objects to determine how to handle the effect's buffer
*single_buffer = false;
*samples_signed = self->samples_signed;
*max_buffer_length = self->buffer_len;
if (single_channel_output) {
*spacing = self->channel_count;
} else {
*spacing = 1;
}
}

View file

@ -44,16 +44,12 @@ typedef struct {
void reset_filter_states(audiofilters_filter_obj_t *self);
void audiofilters_filter_reset_buffer(audiofilters_filter_obj_t *self,
bool single_channel_output,
uint8_t channel);
void audiofilters_filter_reset_buffer(audiofilters_filter_obj_t *self);
audioio_get_buffer_result_t audiofilters_filter_get_buffer(audiofilters_filter_obj_t *self,
bool single_channel_output,
uint8_t channel,
uint8_t **buffer,
uint32_t *buffer_length); // length in bytes
void audiofilters_filter_get_buffer_structure(audiofilters_filter_obj_t *self, bool single_channel_output,
void audiofilters_filter_get_buffer_structure(audiofilters_filter_obj_t *self,
bool *single_buffer, bool *samples_signed,
uint32_t *max_buffer_length, uint8_t *spacing);
uint32_t *max_buffer_length);

View file

@ -74,9 +74,7 @@ bool common_hal_audiomixer_mixer_get_playing(audiomixer_mixer_obj_t *self) {
return false;
}
void audiomixer_mixer_reset_buffer(audiomixer_mixer_obj_t *self,
bool single_channel_output,
uint8_t channel) {
void audiomixer_mixer_reset_buffer(audiomixer_mixer_obj_t *self) {
for (uint8_t i = 0; i < self->voice_count; i++) {
common_hal_audiomixer_mixervoice_stop(self->voice[i]);
}
@ -173,7 +171,7 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self,
if (voice->buffer_length == 0) {
if (!voice->more_data) {
if (voice->loop) {
audiosample_reset_buffer(voice->sample, false, 0);
audiosample_reset_buffer(voice->sample);
} else {
voice->sample = NULL;
break;
@ -181,7 +179,7 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self,
}
if (voice->sample) {
// Load another buffer
audioio_get_buffer_result_t result = audiosample_get_buffer(voice->sample, false, 0, (uint8_t **)&voice->remaining_buffer, &voice->buffer_length);
audioio_get_buffer_result_t result = audiosample_get_buffer(voice->sample, (uint8_t **)&voice->remaining_buffer, &voice->buffer_length);
// Track length in terms of words.
voice->buffer_length /= sizeof(uint32_t);
voice->more_data = result == GET_BUFFER_MORE_DATA;
@ -261,86 +259,55 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self,
}
audioio_get_buffer_result_t audiomixer_mixer_get_buffer(audiomixer_mixer_obj_t *self,
bool single_channel_output,
uint8_t channel,
uint8_t **buffer,
uint32_t *buffer_length) {
if (!single_channel_output) {
channel = 0;
}
uint32_t channel_read_count = self->left_read_count;
if (channel == 1) {
channel_read_count = self->right_read_count;
}
*buffer_length = self->len;
bool need_more_data = self->read_count == channel_read_count;
if (need_more_data) {
uint32_t *word_buffer;
if (self->use_first_buffer) {
*buffer = (uint8_t *)self->first_buffer;
word_buffer = self->first_buffer;
} else {
*buffer = (uint8_t *)self->second_buffer;
word_buffer = self->second_buffer;
}
self->use_first_buffer = !self->use_first_buffer;
bool voices_active = false;
uint32_t length = self->len / sizeof(uint32_t);
for (int32_t v = 0; v < self->voice_count; v++) {
audiomixer_mixervoice_obj_t *voice = MP_OBJ_TO_PTR(self->voice[v]);
if (voice->sample) {
mix_down_one_voice(self, voice, voices_active, word_buffer, length);
voices_active = true;
}
}
if (!voices_active) {
for (uint32_t i = 0; i < length; i++) {
word_buffer[i] = 0;
}
}
if (!self->samples_signed) {
if (self->bits_per_sample == 16) {
for (uint32_t i = 0; i < length; i++) {
word_buffer[i] = tounsigned16(word_buffer[i]);
}
} else {
for (uint32_t i = 0; i < length; i++) {
word_buffer[i] = tounsigned8(word_buffer[i]);
}
}
}
self->read_count += 1;
} else if (!self->use_first_buffer) {
uint32_t *word_buffer;
if (self->use_first_buffer) {
*buffer = (uint8_t *)self->first_buffer;
word_buffer = self->first_buffer;
} else {
*buffer = (uint8_t *)self->second_buffer;
word_buffer = self->second_buffer;
}
self->use_first_buffer = !self->use_first_buffer;
bool voices_active = false;
uint32_t length = self->len / sizeof(uint32_t);
for (int32_t v = 0; v < self->voice_count; v++) {
audiomixer_mixervoice_obj_t *voice = MP_OBJ_TO_PTR(self->voice[v]);
if (voice->sample) {
mix_down_one_voice(self, voice, voices_active, word_buffer, length);
voices_active = true;
}
}
if (!voices_active) {
for (uint32_t i = 0; i < length; i++) {
word_buffer[i] = 0;
}
}
if (channel == 0) {
self->left_read_count += 1;
} else if (channel == 1) {
self->right_read_count += 1;
*buffer = *buffer + self->bits_per_sample / 8;
if (!self->samples_signed) {
if (self->bits_per_sample == 16) {
for (uint32_t i = 0; i < length; i++) {
word_buffer[i] = tounsigned16(word_buffer[i]);
}
} else {
for (uint32_t i = 0; i < length; i++) {
word_buffer[i] = tounsigned8(word_buffer[i]);
}
}
}
return GET_BUFFER_MORE_DATA;
}
void audiomixer_mixer_get_buffer_structure(audiomixer_mixer_obj_t *self, bool single_channel_output,
void audiomixer_mixer_get_buffer_structure(audiomixer_mixer_obj_t *self,
bool *single_buffer, bool *samples_signed,
uint32_t *max_buffer_length, uint8_t *spacing) {
uint32_t *max_buffer_length) {
*single_buffer = false;
*samples_signed = self->samples_signed;
*max_buffer_length = self->len;
if (single_channel_output) {
*spacing = self->channel_count;
} else {
*spacing = 1;
}
}

View file

@ -33,14 +33,10 @@ typedef struct {
// These are not available from Python because it may be called in an interrupt.
void audiomixer_mixer_reset_buffer(audiomixer_mixer_obj_t *self,
bool single_channel_output,
uint8_t channel);
void audiomixer_mixer_reset_buffer(audiomixer_mixer_obj_t *self);
audioio_get_buffer_result_t audiomixer_mixer_get_buffer(audiomixer_mixer_obj_t *self,
bool single_channel_output,
uint8_t channel,
uint8_t **buffer,
uint32_t *buffer_length); // length in bytes
void audiomixer_mixer_get_buffer_structure(audiomixer_mixer_obj_t *self, bool single_channel_output,
void audiomixer_mixer_get_buffer_structure(audiomixer_mixer_obj_t *self,
bool *single_buffer, bool *samples_signed,
uint32_t *max_buffer_length, uint8_t *spacing);
uint32_t *max_buffer_length);

View file

@ -51,17 +51,16 @@ void common_hal_audiomixer_mixervoice_play(audiomixer_mixervoice_obj_t *self, mp
bool single_buffer;
bool samples_signed;
uint32_t max_buffer_length;
uint8_t spacing;
audiosample_get_buffer_structure(sample, false, &single_buffer, &samples_signed,
&max_buffer_length, &spacing);
audiosample_get_buffer_structure(sample, &single_buffer, &samples_signed,
&max_buffer_length);
if (samples_signed != self->parent->samples_signed) {
mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_signedness);
}
self->sample = sample;
self->loop = loop;
audiosample_reset_buffer(sample, false, 0);
audioio_get_buffer_result_t result = audiosample_get_buffer(sample, false, 0, (uint8_t **)&self->remaining_buffer, &self->buffer_length);
audiosample_reset_buffer(sample);
audioio_get_buffer_result_t result = audiosample_get_buffer(sample, (uint8_t **)&self->remaining_buffer, &self->buffer_length);
// Track length in terms of words.
self->buffer_length /= sizeof(uint32_t);
self->more_data = result == GET_BUFFER_MORE_DATA;

View file

@ -351,7 +351,6 @@ void common_hal_audiomp3_mp3file_set_file(audiomp3_mp3file_obj_t *self, mp_obj_t
self->block_ok = false;
stream_set_blocking(self, true);
self->other_channel = -1;
mp3file_update_inbuf_half(self, true);
mp3file_find_sync_word(self, true);
// It **SHOULD** not be necessary to do this; the buffer should be filled
@ -421,12 +420,7 @@ uint8_t common_hal_audiomp3_mp3file_get_channel_count(audiomp3_mp3file_obj_t *se
return self->channel_count;
}
void audiomp3_mp3file_reset_buffer(audiomp3_mp3file_obj_t *self,
bool single_channel_output,
uint8_t channel) {
if (single_channel_output && channel == 1) {
return;
}
void audiomp3_mp3file_reset_buffer(audiomp3_mp3file_obj_t *self) {
// We don't reset the buffer index in case we're looping and we have an odd number of buffer
// loads
background_callback_prevent();
@ -434,7 +428,6 @@ void audiomp3_mp3file_reset_buffer(audiomp3_mp3file_obj_t *self,
INPUT_BUFFER_CLEAR(self->inbuf);
self->eof = 0;
self->samples_decoded = 0;
self->other_channel = -1;
mp3file_skip_id3v2(self, false);
mp3file_find_sync_word(self, false);
}
@ -442,8 +435,6 @@ void audiomp3_mp3file_reset_buffer(audiomp3_mp3file_obj_t *self,
}
audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t *self,
bool single_channel_output,
uint8_t channel,
uint8_t **bufptr,
uint32_t *buffer_length) {
if (!self->inbuf.buf) {
@ -453,27 +444,11 @@ audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t *
}
return GET_BUFFER_ERROR;
}
if (!single_channel_output) {
channel = 0;
}
size_t frame_buffer_size_bytes = self->frame_buffer_size;
*buffer_length = frame_buffer_size_bytes;
if (channel == self->other_channel) {
*bufptr = (uint8_t *)(self->pcm_buffer[self->other_buffer_index] + channel);
self->other_channel = -1;
self->samples_decoded += *buffer_length / sizeof(int16_t);
if (DO_DEBUG) {
mp_printf(&mp_plat_print, "%s:%d\n", __FILE__, __LINE__);
}
return GET_BUFFER_MORE_DATA;
}
self->buffer_index = !self->buffer_index;
self->other_channel = 1 - channel;
self->other_buffer_index = self->buffer_index;
int16_t *buffer = (int16_t *)(void *)self->pcm_buffer[self->buffer_index];
*bufptr = (uint8_t *)buffer;
@ -523,17 +498,12 @@ audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t *
return result;
}
void audiomp3_mp3file_get_buffer_structure(audiomp3_mp3file_obj_t *self, bool single_channel_output,
void audiomp3_mp3file_get_buffer_structure(audiomp3_mp3file_obj_t *self,
bool *single_buffer, bool *samples_signed,
uint32_t *max_buffer_length, uint8_t *spacing) {
uint32_t *max_buffer_length) {
*single_buffer = false;
*samples_signed = true;
*max_buffer_length = self->frame_buffer_size;
if (single_channel_output) {
*spacing = self->channel_count;
} else {
*spacing = 1;
}
}
float common_hal_audiomp3_mp3file_get_rms_level(audiomp3_mp3file_obj_t *self) {

View file

@ -38,24 +38,17 @@ typedef struct {
bool block_ok;
mp_obj_t settimeout_args[3];
int8_t other_channel;
int8_t other_buffer_index;
uint32_t samples_decoded;
} audiomp3_mp3file_obj_t;
// These are not available from Python because it may be called in an interrupt.
void audiomp3_mp3file_reset_buffer(audiomp3_mp3file_obj_t *self,
bool single_channel_output,
uint8_t channel);
void audiomp3_mp3file_reset_buffer(audiomp3_mp3file_obj_t *self);
audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t *self,
bool single_channel_output,
uint8_t channel,
uint8_t **buffer,
uint32_t *buffer_length); // length in bytes
void audiomp3_mp3file_get_buffer_structure(audiomp3_mp3file_obj_t *self, bool single_channel_output,
void audiomp3_mp3file_get_buffer_structure(audiomp3_mp3file_obj_t *self,
bool *single_buffer, bool *samples_signed,
uint32_t *max_buffer_length, uint8_t *spacing);
uint32_t *max_buffer_length);
float audiomp3_mp3file_get_rms_level(audiomp3_mp3file_obj_t *self);

View file

@ -129,20 +129,19 @@ uint8_t common_hal_synthio_miditrack_get_channel_count(synthio_miditrack_obj_t *
return 1;
}
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);
void synthio_miditrack_reset_buffer(synthio_miditrack_obj_t *self) {
synthio_synth_reset_buffer(&self->synth);
start_parse(self);
}
audioio_get_buffer_result_t synthio_miditrack_get_buffer(synthio_miditrack_obj_t *self,
bool single_channel_output, uint8_t channel, uint8_t **buffer, uint32_t *buffer_length) {
uint8_t **buffer, uint32_t *buffer_length) {
if (common_hal_synthio_miditrack_deinited(self)) {
*buffer_length = 0;
return GET_BUFFER_ERROR;
}
synthio_synth_synthesize(&self->synth, buffer, buffer_length, single_channel_output ? 0 : channel);
synthio_synth_synthesize(&self->synth, buffer, buffer_length);
if (self->synth.span.dur == 0) {
if (self->pos == self->track.len) {
return GET_BUFFER_DONE;
@ -153,7 +152,7 @@ audioio_get_buffer_result_t synthio_miditrack_get_buffer(synthio_miditrack_obj_t
return GET_BUFFER_MORE_DATA;
}
void synthio_miditrack_get_buffer_structure(synthio_miditrack_obj_t *self, bool single_channel_output,
bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing) {
return synthio_synth_get_buffer_structure(&self->synth, single_channel_output, single_buffer, samples_signed, max_buffer_length, spacing);
void synthio_miditrack_get_buffer_structure(synthio_miditrack_obj_t *self,
bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length) {
return synthio_synth_get_buffer_structure(&self->synth, single_buffer, samples_signed, max_buffer_length);
}

View file

@ -22,16 +22,12 @@ typedef struct {
// These are not available from Python because it may be called in an interrupt.
void synthio_miditrack_reset_buffer(synthio_miditrack_obj_t *self,
bool single_channel_output,
uint8_t channel);
void synthio_miditrack_reset_buffer(synthio_miditrack_obj_t *self);
audioio_get_buffer_result_t synthio_miditrack_get_buffer(synthio_miditrack_obj_t *self,
bool single_channel_output,
uint8_t channel,
uint8_t **buffer,
uint32_t *buffer_length); // length in bytes
void synthio_miditrack_get_buffer_structure(synthio_miditrack_obj_t *self, bool single_channel_output,
void synthio_miditrack_get_buffer_structure(synthio_miditrack_obj_t *self,
bool *single_buffer, bool *samples_signed,
uint32_t *max_buffer_length, uint8_t *spacing);
uint32_t *max_buffer_length);

View file

@ -37,13 +37,12 @@ uint8_t common_hal_synthio_synthesizer_get_channel_count(synthio_synthesizer_obj
return self->synth.channel_count;
}
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);
void synthio_synthesizer_reset_buffer(synthio_synthesizer_obj_t *self) {
synthio_synth_reset_buffer(&self->synth);
}
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) {
uint8_t **buffer, uint32_t *buffer_length) {
if (common_hal_synthio_synthesizer_deinited(self)) {
*buffer_length = 0;
return GET_BUFFER_ERROR;
@ -51,7 +50,7 @@ audioio_get_buffer_result_t synthio_synthesizer_get_buffer(synthio_synthesizer_o
self->synth.span.dur = SYNTHIO_MAX_DUR;
synthio_synth_synthesize(&self->synth, buffer, buffer_length, single_channel_output ? channel : 0);
synthio_synth_synthesize(&self->synth, buffer, buffer_length);
// free-running LFOs
mp_obj_iter_buf_t iter_buf;
@ -67,9 +66,9 @@ audioio_get_buffer_result_t synthio_synthesizer_get_buffer(synthio_synthesizer_o
return GET_BUFFER_MORE_DATA;
}
void synthio_synthesizer_get_buffer_structure(synthio_synthesizer_obj_t *self, bool single_channel_output,
bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing) {
return synthio_synth_get_buffer_structure(&self->synth, single_channel_output, single_buffer, samples_signed, max_buffer_length, spacing);
void synthio_synthesizer_get_buffer_structure(synthio_synthesizer_obj_t *self,
bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length) {
return synthio_synth_get_buffer_structure(&self->synth, single_buffer, samples_signed, max_buffer_length);
}
void common_hal_synthio_synthesizer_release_all(synthio_synthesizer_obj_t *self) {

View file

@ -19,16 +19,12 @@ typedef struct {
// These are not available from Python because it may be called in an interrupt.
void synthio_synthesizer_reset_buffer(synthio_synthesizer_obj_t *self,
bool single_channel_output,
uint8_t channel);
void synthio_synthesizer_reset_buffer(synthio_synthesizer_obj_t *self);
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); // length in bytes
void synthio_synthesizer_get_buffer_structure(synthio_synthesizer_obj_t *self, bool single_channel_output,
void synthio_synthesizer_get_buffer_structure(synthio_synthesizer_obj_t *self,
bool *single_buffer, bool *samples_signed,
uint32_t *max_buffer_length, uint8_t *spacing);
uint32_t *max_buffer_length);

View file

@ -286,19 +286,11 @@ static void sum_with_loudness(int32_t *out_buffer32, int32_t *tmp_buffer32, int1
}
}
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;
}
void synthio_synth_synthesize(synthio_synth_t *synth, uint8_t **bufptr, uint32_t *buffer_length) {
shared_bindings_synthio_lfo_tick(synth->sample_rate);
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;
@ -361,11 +353,7 @@ void synthio_synth_synthesize(synthio_synth_t *synth, uint8_t **bufptr, uint32_t
*bufptr = (uint8_t *)out_buffer16;
}
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;
void synthio_synth_reset_buffer(synthio_synth_t *synth) {
}
bool synthio_synth_deinited(synthio_synth_t *synth) {
@ -393,7 +381,6 @@ void synthio_synth_init(synthio_synth_t *synth, uint32_t sample_rate, int channe
synth->buffers[0] = m_malloc(synth->buffer_length);
synth->buffers[1] = m_malloc(synth->buffer_length);
synth->channel_count = channel_count;
synth->other_channel = -1;
synth->waveform_obj = waveform_obj;
synth->sample_rate = sample_rate;
synthio_synth_envelope_set(synth, envelope_obj);
@ -403,16 +390,11 @@ void synthio_synth_init(synthio_synth_t *synth, uint32_t sample_rate, int channe
}
}
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_get_buffer_structure(synthio_synth_t *synth,
bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length) {
*single_buffer = false;
*samples_signed = true;
*max_buffer_length = synth->buffer_length;
if (single_channel_output) {
*spacing = synth->channel_count;
} else {
*spacing = 1;
}
}
static void parse_common(mp_buffer_info_t *bufinfo, mp_obj_t o, int16_t what, mp_int_t max_len) {

View file

@ -41,9 +41,9 @@ typedef struct synthio_synth {
uint32_t total_envelope;
int16_t *buffers[2];
uint8_t channel_count;
uint8_t buffer_index;
uint16_t buffer_length;
uint16_t last_buffer_length;
uint8_t other_channel, buffer_index, other_buffer_index;
mp_buffer_info_t waveform_bufinfo;
synthio_envelope_definition_t global_envelope_definition;
mp_obj_t waveform_obj, filter_obj, envelope_obj;
@ -63,13 +63,13 @@ typedef struct {
} synthio_lfo_state_t;
void synthio_synth_synthesize(synthio_synth_t *synth, uint8_t **buffer, uint32_t *buffer_length, uint8_t channel);
void synthio_synth_synthesize(synthio_synth_t *synth, uint8_t **buffer, uint32_t *buffer_length);
void synthio_synth_deinit(synthio_synth_t *synth);
bool synthio_synth_deinited(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 envelope);
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_get_buffer_structure(synthio_synth_t *synth,
bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length);
void synthio_synth_reset_buffer(synthio_synth_t *synth);
void synthio_synth_parse_waveform(mp_buffer_info_t *bufinfo_waveform, mp_obj_t waveform_obj);
void synthio_synth_parse_filter(mp_buffer_info_t *bufinfo_filter, mp_obj_t filter_obj);
void synthio_synth_parse_envelope(uint16_t *envelope_sustain_index, mp_buffer_info_t *bufinfo_envelope, mp_obj_t envelope_obj, mp_obj_t envelope_hold_obj);