audiomixer: Fix garbled playback when voice 0 is stopped, audio pops
There were two main problems - word_buffer was being filled as though with unsigned samples, but during mixing all samples are kept in signed mode - If the first buffer was stopped, the voices_active flag got set anyway, even though the output buffer wasn't initialized yet, so the samples were mixed with indeterminate data We also cover the case where no buffer was playing, and ensure the output buffer is filled. This now works much better. Tested on neotrellis m4 playing back 4 mp3 streams at a time in signed-16, 22050Hz
This commit is contained in:
parent
47efd595fc
commit
0722dafc24
|
@ -143,19 +143,17 @@ static inline uint32_t pack8(uint32_t val) {
|
||||||
static void mix_down_one_voice(audiomixer_mixer_obj_t* self,
|
static void mix_down_one_voice(audiomixer_mixer_obj_t* self,
|
||||||
audiomixer_mixervoice_obj_t* voice, bool voices_active,
|
audiomixer_mixervoice_obj_t* voice, bool voices_active,
|
||||||
uint32_t* word_buffer, uint32_t length) {
|
uint32_t* word_buffer, uint32_t length) {
|
||||||
bool voice_done = voice->sample == NULL;
|
while (length != 0) {
|
||||||
while (!voice_done && length != 0) {
|
|
||||||
if (voice->buffer_length == 0) {
|
if (voice->buffer_length == 0) {
|
||||||
if (!voice->more_data) {
|
if (!voice->more_data) {
|
||||||
if (voice->loop) {
|
if (voice->loop) {
|
||||||
audiosample_reset_buffer(voice->sample, false, 0);
|
audiosample_reset_buffer(voice->sample, false, 0);
|
||||||
} else {
|
} else {
|
||||||
voice->sample = NULL;
|
voice->sample = NULL;
|
||||||
voice_done = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!voice_done) {
|
if (voice->sample) {
|
||||||
// Load another buffer
|
// 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, false, 0, (uint8_t**) &voice->remaining_buffer, &voice->buffer_length);
|
||||||
// Track length in terms of words.
|
// Track length in terms of words.
|
||||||
|
@ -230,10 +228,8 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t* self,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (length && !voices_active) {
|
if (length && !voices_active) {
|
||||||
uint32_t sample_value = self->bits_per_sample == 8
|
|
||||||
? 0x80808080 : 0x80008000;
|
|
||||||
for (uint32_t i = 0; i<length; i++) {
|
for (uint32_t i = 0; i<length; i++) {
|
||||||
word_buffer[i] = sample_value;
|
word_buffer[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -269,9 +265,16 @@ audioio_get_buffer_result_t audiomixer_mixer_get_buffer(audiomixer_mixer_obj_t*
|
||||||
|
|
||||||
for (int32_t v = 0; v < self->voice_count; v++) {
|
for (int32_t v = 0; v < self->voice_count; v++) {
|
||||||
audiomixer_mixervoice_obj_t* voice = MP_OBJ_TO_PTR(self->voice[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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mix_down_one_voice(self, voice, voices_active, word_buffer, length);
|
if (!voices_active) {
|
||||||
voices_active = true;
|
for (uint32_t i = 0; i<length; i++) {
|
||||||
|
word_buffer[i] = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!self->samples_signed) {
|
if (!self->samples_signed) {
|
||||||
|
|
Loading…
Reference in New Issue