From e6ece89049260f9be8d60c1ed7e397097e602183 Mon Sep 17 00:00:00 2001 From: George Norton Date: Fri, 31 Mar 2023 13:15:43 +0100 Subject: [PATCH] Fix an overflow in the fix16_t usage which can lead to audio distortion. --- firmware/code/fix16.c | 32 ++++++++++++++++++-------------- firmware/code/run.c | 2 +- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/firmware/code/fix16.c b/firmware/code/fix16.c index d10fc76..b6eea54 100644 --- a/firmware/code/fix16.c +++ b/firmware/code/fix16.c @@ -22,7 +22,7 @@ #include #include #include - +#include #include "fix16.h" fix16_t fix16_from_int(int16_t a) { @@ -30,9 +30,23 @@ fix16_t fix16_from_int(int16_t a) { } int16_t fix16_to_int(fix16_t a) { - if (a >= 0) - return (a + (fix16_one >> 1)) / fix16_one; - return (a - (fix16_one >> 1)) / fix16_one; + // Handle rounding up front, adding one can cause an overflow/underflow + a+=(fix16_one >> 1); + + // Saturate the value if an overflow has occurred + uint32_t upper = (a >> 30); + if (a < 0) { + if (~upper) + { + return SHRT_MIN; + } + } else { + if (upper) + { + return SHRT_MAX; + } + } + return (a >> 15); } fix16_t fix16_from_dbl(double a) { @@ -49,16 +63,6 @@ double fix16_to_dbl(fix16_t a) { fix16_t fix16_mul(fix16_t inArg0, fix16_t inArg1) { int64_t product = (int64_t)inArg0 * inArg1; - uint32_t upper = (product >> 47); - if (product < 0) { - if (~upper) - return fix16_overflow; - product--; - } else { - if (upper) - return fix16_overflow; - } - fix16_t result = product >> 15; result += (product & 0x4000) >> 14; diff --git a/firmware/code/run.c b/firmware/code/run.c index 929a587..9ad3cb3 100644 --- a/firmware/code/run.c +++ b/firmware/code/run.c @@ -91,7 +91,7 @@ static void _as_audio_packet(struct usb_endpoint *ep) { int samples = usb_buffer->data_len / 2; for (int i = 0; i < samples; i++) - out[i] = in[i] / 4; // fixes digital distortion bug + out[i] = in[i]; multicore_fifo_push_blocking(CORE0_READY); multicore_fifo_push_blocking(samples);