Skip to content

RP2040: fix 8-bit WAV playback #8436

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 30, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions ports/raspberrypi/audio_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,20 +64,26 @@ STATIC size_t audio_dma_convert_samples(audio_dma_t *dma, uint8_t *input, uint32
if (dma->sample_resolution <= 8 && dma->output_resolution > 8) {
// reading bytes, writing 16-bit words, so output buffer will be bigger.

output_length_used = output_length * 2;
output_length_used *= 2;
if (output_length_used > output_length) {
mp_raise_RuntimeError(translate("Internal audio buffer too small"));
}

size_t shift = dma->output_resolution - dma->sample_resolution;
// Correct "rail-to-rail" scaling of arbitrary-depth input to output
// requires more operations than this, but at least the vital 8- to
// 16-bit cases are correctly scaled now. Prior code was only
// considering 8-to-16 anyway, but had a slight DC offset in the
// result, so this is no worse off WRT supported resolutions.
uint16_t mul = ((1 << dma->output_resolution) - 1) / ((1 << dma->sample_resolution) - 1);
uint16_t offset = (1 << dma->output_resolution) / 2;

for (uint32_t i = 0; i < input_length; i += dma->sample_spacing) {
if (dma->signed_to_unsigned) {
((uint16_t *)output)[out_i] = ((uint16_t)((int8_t *)input)[i] + 0x80) << shift;
((uint16_t *)output)[out_i] = (uint16_t)((((int8_t *)input)[i] + 0x80) * mul);
} else if (dma->unsigned_to_signed) {
((int16_t *)output)[out_i] = ((int16_t)((uint8_t *)input)[i] - 0x80) << shift;
((int16_t *)output)[out_i] = (int16_t)(((uint8_t *)input)[i] * mul - offset);
} else {
((uint16_t *)output)[out_i] = ((uint16_t)((uint8_t *)input)[i]) << shift;
((uint16_t *)output)[out_i] = (uint16_t)(((uint8_t *)input)[i] * mul);
}
out_i += 1;
}
Expand Down