From 4de7ce252b5b504cde0a89f28283c737c922d69a Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 6 Jun 2018 12:23:28 +0200 Subject: [PATCH 1/2] bpo-33781: audioop: enhance rounding double as int Move the floor() call into fbound() to call floor() on a double rather than an int. The change might enhance the rounding. --- Modules/audioop.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/Modules/audioop.c b/Modules/audioop.c index 80c8a2a8e5210b..4d6ba8071c4e50 100644 --- a/Modules/audioop.c +++ b/Modules/audioop.c @@ -20,11 +20,17 @@ static const unsigned int masks[] = {0, 0xFF, 0xFFFF, 0xFFFFFF, 0xFFFFFFFF}; static int fbound(double val, double minval, double maxval) { - if (val > maxval) + if (val > maxval) { val = maxval; - else if (val < minval + 1) + } + else if (val < minval + 1.0) { val = minval; - return (int)val; + } + + /* Round towards minus infinity (-inf) */ + val = floor(val); + int ival = (int)val; + return ival; } @@ -924,9 +930,8 @@ audioop_mul_impl(PyObject *module, Py_buffer *fragment, int width, for (i = 0; i < fragment->len; i += width) { double val = GETRAWSAMPLE(width, fragment->buf, i); - val *= factor; - val = floor(fbound(val, minval, maxval)); - SETRAWSAMPLE(width, ncp, i, (int)val); + int ival = fbound(val * factor, minval, maxval); + SETRAWSAMPLE(width, ncp, i, ival); } return rv; } @@ -973,9 +978,9 @@ audioop_tomono_impl(PyObject *module, Py_buffer *fragment, int width, for (i = 0; i < len; i += width*2) { double val1 = GETRAWSAMPLE(width, cp, i); double val2 = GETRAWSAMPLE(width, cp, i + width); - double val = val1*lfactor + val2*rfactor; - val = floor(fbound(val, minval, maxval)); - SETRAWSAMPLE(width, ncp, i/2, val); + double val = val1 * lfactor + val2 * rfactor; + int ival = fbound(val, minval, maxval); + SETRAWSAMPLE(width, ncp, i/2, ival); } return rv; } @@ -1021,8 +1026,8 @@ audioop_tostereo_impl(PyObject *module, Py_buffer *fragment, int width, for (i = 0; i < fragment->len; i += width) { double val = GETRAWSAMPLE(width, fragment->buf, i); - int val1 = (int)floor(fbound(val*lfactor, minval, maxval)); - int val2 = (int)floor(fbound(val*rfactor, minval, maxval)); + int val1 = fbound(val * lfactor, minval, maxval); + int val2 = fbound(val * rfactor, minval, maxval); SETRAWSAMPLE(width, ncp, i*2, val1); SETRAWSAMPLE(width, ncp, i*2 + width, val2); } @@ -1080,7 +1085,7 @@ audioop_add_impl(PyObject *module, Py_buffer *fragment1, else { double fval = (double)val1 + (double)val2; /* truncate in case of overflow */ - newval = (int)floor(fbound(fval, minval, maxval)); + newval = fbound(fval, minval, maxval); } SETRAWSAMPLE(width, ncp, i, newval); From 9f5b3ef6f7ab44ac04671f540480b5e94596513e Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 6 Jun 2018 12:57:01 +0200 Subject: [PATCH 2/2] Document (int)double rounding mode --- Modules/audioop.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Modules/audioop.c b/Modules/audioop.c index 4d6ba8071c4e50..f4fdeb23ffa95a 100644 --- a/Modules/audioop.c +++ b/Modules/audioop.c @@ -29,8 +29,9 @@ fbound(double val, double minval, double maxval) /* Round towards minus infinity (-inf) */ val = floor(val); - int ival = (int)val; - return ival; + + /* Cast double to integer: round towards zero */ + return (int)val; }