mirror of
https://github.com/python/cpython.git
synced 2025-08-03 08:34:29 +00:00
Issue #16686: Fixed a lot of bugs in audioop module.
* avgpp() and maxpp() no more crash on empty and 1-samples input fragment. They now work when peak-peak values are greater INT_MAX. * ratecv() no more crashes on empty input fragment. * Fixed an integer overflow in ratecv(). * Fixed an integer overflow in add() and bias() for 32-bit samples. * reverse(), lin2lin() and ratecv() no more lose precision for 32-bit samples. * max() and rms() no more returns negative result for 32-bit sample -0x80000000. * minmax() now returns correct max value for 32-bit sample -0x80000000. * avg(), mul(), tomono() and tostereo() now round negative result down and can return 32-bit sample -0x80000000. * add() now can return 32-bit sample -0x80000000.
This commit is contained in:
parent
a48b61f8f2
commit
01ad622a2c
4 changed files with 435 additions and 286 deletions
|
@ -26,6 +26,21 @@ typedef short PyInt16;
|
|||
#endif
|
||||
#endif
|
||||
|
||||
static const int maxvals[] = {0, 0x7F, 0x7FFF, 0x7FFFFF, 0x7FFFFFFF};
|
||||
static const int minvals[] = {0, -0x80, -0x8000, -0x800000, -0x80000000};
|
||||
static const unsigned int masks[] = {0, 0xFF, 0xFFFF, 0xFFFFFF, 0xFFFFFFFF};
|
||||
|
||||
static int
|
||||
fbound(double val, double minval, double maxval)
|
||||
{
|
||||
if (val > maxval)
|
||||
val = maxval;
|
||||
else if (val < minval + 1)
|
||||
val = minval;
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
/* Code shamelessly stolen from sox, 12.17.7, g711.c
|
||||
** (c) Craig Reese, Joe Campbell and Jeff Poskanzer 1989 */
|
||||
|
||||
|
@ -347,7 +362,7 @@ audioop_max(PyObject *self, PyObject *args)
|
|||
signed char *cp;
|
||||
Py_ssize_t len, i;
|
||||
int size, val = 0;
|
||||
int max = 0;
|
||||
unsigned int absval, max = 0;
|
||||
|
||||
if ( !PyArg_ParseTuple(args, "s#i:max", &cp, &len, &size) )
|
||||
return 0;
|
||||
|
@ -357,10 +372,11 @@ audioop_max(PyObject *self, PyObject *args)
|
|||
if ( size == 1 ) val = (int)*CHARP(cp, i);
|
||||
else if ( size == 2 ) val = (int)*SHORTP(cp, i);
|
||||
else if ( size == 4 ) val = (int)*LONGP(cp, i);
|
||||
if ( val < 0 ) val = (-val);
|
||||
if ( val > max ) max = val;
|
||||
if (val < 0) absval = (-val);
|
||||
else absval = val;
|
||||
if (absval > max) max = absval;
|
||||
}
|
||||
return PyLong_FromLong(max);
|
||||
return PyLong_FromUnsignedLong(max);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
|
@ -369,7 +385,7 @@ audioop_minmax(PyObject *self, PyObject *args)
|
|||
signed char *cp;
|
||||
Py_ssize_t len, i;
|
||||
int size, val = 0;
|
||||
int min = 0x7fffffff, max = -0x7fffffff;
|
||||
int min = 0x7fffffff, max = -0x80000000;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s#i:minmax", &cp, &len, &size))
|
||||
return NULL;
|
||||
|
@ -406,7 +422,7 @@ audioop_avg(PyObject *self, PyObject *args)
|
|||
if ( len == 0 )
|
||||
val = 0;
|
||||
else
|
||||
val = (int)(avg / (double)(len/size));
|
||||
val = (int)floor(avg / (double)(len/size));
|
||||
return PyLong_FromLong(val);
|
||||
}
|
||||
|
||||
|
@ -416,6 +432,7 @@ audioop_rms(PyObject *self, PyObject *args)
|
|||
signed char *cp;
|
||||
Py_ssize_t len, i;
|
||||
int size, val = 0;
|
||||
unsigned int res;
|
||||
double sum_squares = 0.0;
|
||||
|
||||
if ( !PyArg_ParseTuple(args, "s#i:rms", &cp, &len, &size) )
|
||||
|
@ -429,10 +446,10 @@ audioop_rms(PyObject *self, PyObject *args)
|
|||
sum_squares += (double)val*(double)val;
|
||||
}
|
||||
if ( len == 0 )
|
||||
val = 0;
|
||||
res = 0;
|
||||
else
|
||||
val = (int)sqrt(sum_squares / (double)(len/size));
|
||||
return PyLong_FromLong(val);
|
||||
res = (unsigned int)sqrt(sum_squares / (double)(len/size));
|
||||
return PyLong_FromUnsignedLong(res);
|
||||
}
|
||||
|
||||
static double _sum2(short *a, short *b, Py_ssize_t len)
|
||||
|
@ -624,52 +641,46 @@ audioop_avgpp(PyObject *self, PyObject *args)
|
|||
Py_ssize_t len, i;
|
||||
int size, val = 0, prevval = 0, prevextremevalid = 0,
|
||||
prevextreme = 0;
|
||||
double avg = 0.0;
|
||||
int diff, prevdiff, extremediff, nextreme = 0;
|
||||
double sum = 0.0;
|
||||
unsigned int avg;
|
||||
int diff, prevdiff, nextreme = 0;
|
||||
|
||||
if ( !PyArg_ParseTuple(args, "s#i:avgpp", &cp, &len, &size) )
|
||||
return 0;
|
||||
if (!audioop_check_parameters(len, size))
|
||||
return NULL;
|
||||
/* Compute first delta value ahead. Also automatically makes us
|
||||
** skip the first extreme value
|
||||
*/
|
||||
if (len <= size)
|
||||
return PyLong_FromLong(0);
|
||||
if ( size == 1 ) prevval = (int)*CHARP(cp, 0);
|
||||
else if ( size == 2 ) prevval = (int)*SHORTP(cp, 0);
|
||||
else if ( size == 4 ) prevval = (int)*LONGP(cp, 0);
|
||||
if ( size == 1 ) val = (int)*CHARP(cp, size);
|
||||
else if ( size == 2 ) val = (int)*SHORTP(cp, size);
|
||||
else if ( size == 4 ) val = (int)*LONGP(cp, size);
|
||||
prevdiff = val - prevval;
|
||||
|
||||
prevdiff = 17; /* Anything != 0, 1 */
|
||||
for ( i=size; i<len; i+= size) {
|
||||
if ( size == 1 ) val = (int)*CHARP(cp, i);
|
||||
else if ( size == 2 ) val = (int)*SHORTP(cp, i);
|
||||
else if ( size == 4 ) val = (int)*LONGP(cp, i);
|
||||
diff = val - prevval;
|
||||
if ( diff*prevdiff < 0 ) {
|
||||
/* Derivative changed sign. Compute difference to last
|
||||
** extreme value and remember.
|
||||
*/
|
||||
if ( prevextremevalid ) {
|
||||
extremediff = prevval - prevextreme;
|
||||
if ( extremediff < 0 )
|
||||
extremediff = -extremediff;
|
||||
avg += extremediff;
|
||||
nextreme++;
|
||||
if (val != prevval) {
|
||||
diff = val < prevval;
|
||||
if (prevdiff == !diff) {
|
||||
/* Derivative changed sign. Compute difference to last
|
||||
** extreme value and remember.
|
||||
*/
|
||||
if (prevextremevalid) {
|
||||
sum += fabs((double)prevval - (double)prevextreme);
|
||||
nextreme++;
|
||||
}
|
||||
prevextremevalid = 1;
|
||||
prevextreme = prevval;
|
||||
}
|
||||
prevextremevalid = 1;
|
||||
prevextreme = prevval;
|
||||
}
|
||||
prevval = val;
|
||||
if ( diff != 0 )
|
||||
prevval = val;
|
||||
prevdiff = diff;
|
||||
}
|
||||
}
|
||||
if ( nextreme == 0 )
|
||||
val = 0;
|
||||
avg = 0;
|
||||
else
|
||||
val = (int)(avg / (double)nextreme);
|
||||
return PyLong_FromLong(val);
|
||||
avg = (unsigned int)(sum / (double)nextreme);
|
||||
return PyLong_FromUnsignedLong(avg);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
|
@ -679,48 +690,47 @@ audioop_maxpp(PyObject *self, PyObject *args)
|
|||
Py_ssize_t len, i;
|
||||
int size, val = 0, prevval = 0, prevextremevalid = 0,
|
||||
prevextreme = 0;
|
||||
int max = 0;
|
||||
int diff, prevdiff, extremediff;
|
||||
unsigned int max = 0, extremediff;
|
||||
int diff, prevdiff;
|
||||
|
||||
if ( !PyArg_ParseTuple(args, "s#i:maxpp", &cp, &len, &size) )
|
||||
return 0;
|
||||
if (!audioop_check_parameters(len, size))
|
||||
return NULL;
|
||||
/* Compute first delta value ahead. Also automatically makes us
|
||||
** skip the first extreme value
|
||||
*/
|
||||
if (len <= size)
|
||||
return PyLong_FromLong(0);
|
||||
if ( size == 1 ) prevval = (int)*CHARP(cp, 0);
|
||||
else if ( size == 2 ) prevval = (int)*SHORTP(cp, 0);
|
||||
else if ( size == 4 ) prevval = (int)*LONGP(cp, 0);
|
||||
if ( size == 1 ) val = (int)*CHARP(cp, size);
|
||||
else if ( size == 2 ) val = (int)*SHORTP(cp, size);
|
||||
else if ( size == 4 ) val = (int)*LONGP(cp, size);
|
||||
prevdiff = val - prevval;
|
||||
|
||||
prevdiff = 17; /* Anything != 0, 1 */
|
||||
for ( i=size; i<len; i+= size) {
|
||||
if ( size == 1 ) val = (int)*CHARP(cp, i);
|
||||
else if ( size == 2 ) val = (int)*SHORTP(cp, i);
|
||||
else if ( size == 4 ) val = (int)*LONGP(cp, i);
|
||||
diff = val - prevval;
|
||||
if ( diff*prevdiff < 0 ) {
|
||||
/* Derivative changed sign. Compute difference to
|
||||
** last extreme value and remember.
|
||||
*/
|
||||
if ( prevextremevalid ) {
|
||||
extremediff = prevval - prevextreme;
|
||||
if ( extremediff < 0 )
|
||||
extremediff = -extremediff;
|
||||
if ( extremediff > max )
|
||||
max = extremediff;
|
||||
if (val != prevval) {
|
||||
diff = val < prevval;
|
||||
if (prevdiff == !diff) {
|
||||
/* Derivative changed sign. Compute difference to
|
||||
** last extreme value and remember.
|
||||
*/
|
||||
if (prevextremevalid) {
|
||||
if (prevval < prevextreme)
|
||||
extremediff = (unsigned int)prevextreme -
|
||||
(unsigned int)prevval;
|
||||
else
|
||||
extremediff = (unsigned int)prevval -
|
||||
(unsigned int)prevextreme;
|
||||
if ( extremediff > max )
|
||||
max = extremediff;
|
||||
}
|
||||
prevextremevalid = 1;
|
||||
prevextreme = prevval;
|
||||
}
|
||||
prevextremevalid = 1;
|
||||
prevextreme = prevval;
|
||||
}
|
||||
prevval = val;
|
||||
if ( diff != 0 )
|
||||
prevval = val;
|
||||
prevdiff = diff;
|
||||
}
|
||||
}
|
||||
return PyLong_FromLong(max);
|
||||
return PyLong_FromUnsignedLong(max);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
|
@ -755,7 +765,7 @@ audioop_mul(PyObject *self, PyObject *args)
|
|||
signed char *cp, *ncp;
|
||||
Py_ssize_t len, i;
|
||||
int size, val = 0;
|
||||
double factor, fval, maxval;
|
||||
double factor, fval, maxval, minval;
|
||||
PyObject *rv;
|
||||
|
||||
if ( !PyArg_ParseTuple(args, "s#id:mul", &cp, &len, &size, &factor ) )
|
||||
|
@ -763,13 +773,8 @@ audioop_mul(PyObject *self, PyObject *args)
|
|||
if (!audioop_check_parameters(len, size))
|
||||
return NULL;
|
||||
|
||||
if ( size == 1 ) maxval = (double) 0x7f;
|
||||
else if ( size == 2 ) maxval = (double) 0x7fff;
|
||||
else if ( size == 4 ) maxval = (double) 0x7fffffff;
|
||||
else {
|
||||
PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
|
||||
return 0;
|
||||
}
|
||||
maxval = (double) maxvals[size];
|
||||
minval = (double) minvals[size];
|
||||
|
||||
rv = PyBytes_FromStringAndSize(NULL, len);
|
||||
if ( rv == 0 )
|
||||
|
@ -782,9 +787,7 @@ audioop_mul(PyObject *self, PyObject *args)
|
|||
else if ( size == 2 ) val = (int)*SHORTP(cp, i);
|
||||
else if ( size == 4 ) val = (int)*LONGP(cp, i);
|
||||
fval = (double)val*factor;
|
||||
if ( fval > maxval ) fval = maxval;
|
||||
else if ( fval < -maxval ) fval = -maxval;
|
||||
val = (int)fval;
|
||||
val = (int)floor(fbound(fval, minval, maxval));
|
||||
if ( size == 1 ) *CHARP(ncp, i) = (signed char)val;
|
||||
else if ( size == 2 ) *SHORTP(ncp, i) = (short)val;
|
||||
else if ( size == 4 ) *LONGP(ncp, i) = (Py_Int32)val;
|
||||
|
@ -799,7 +802,7 @@ audioop_tomono(PyObject *self, PyObject *args)
|
|||
signed char *cp, *ncp;
|
||||
Py_ssize_t len, i;
|
||||
int size, val1 = 0, val2 = 0;
|
||||
double fac1, fac2, fval, maxval;
|
||||
double fac1, fac2, fval, maxval, minval;
|
||||
PyObject *rv;
|
||||
|
||||
if ( !PyArg_ParseTuple(args, "s*idd:tomono",
|
||||
|
@ -817,14 +820,8 @@ audioop_tomono(PyObject *self, PyObject *args)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if ( size == 1 ) maxval = (double) 0x7f;
|
||||
else if ( size == 2 ) maxval = (double) 0x7fff;
|
||||
else if ( size == 4 ) maxval = (double) 0x7fffffff;
|
||||
else {
|
||||
PyBuffer_Release(&pcp);
|
||||
PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
|
||||
return 0;
|
||||
}
|
||||
maxval = (double) maxvals[size];
|
||||
minval = (double) minvals[size];
|
||||
|
||||
rv = PyBytes_FromStringAndSize(NULL, len/2);
|
||||
if ( rv == 0 ) {
|
||||
|
@ -842,9 +839,7 @@ audioop_tomono(PyObject *self, PyObject *args)
|
|||
else if ( size == 2 ) val2 = (int)*SHORTP(cp, i+2);
|
||||
else if ( size == 4 ) val2 = (int)*LONGP(cp, i+4);
|
||||
fval = (double)val1*fac1 + (double)val2*fac2;
|
||||
if ( fval > maxval ) fval = maxval;
|
||||
else if ( fval < -maxval ) fval = -maxval;
|
||||
val1 = (int)fval;
|
||||
val1 = (int)floor(fbound(fval, minval, maxval));
|
||||
if ( size == 1 ) *CHARP(ncp, i/2) = (signed char)val1;
|
||||
else if ( size == 2 ) *SHORTP(ncp, i/2) = (short)val1;
|
||||
else if ( size == 4 ) *LONGP(ncp, i/2)= (Py_Int32)val1;
|
||||
|
@ -859,7 +854,7 @@ audioop_tostereo(PyObject *self, PyObject *args)
|
|||
signed char *cp, *ncp;
|
||||
Py_ssize_t len, i;
|
||||
int size, val1, val2, val = 0;
|
||||
double fac1, fac2, fval, maxval;
|
||||
double fac1, fac2, fval, maxval, minval;
|
||||
PyObject *rv;
|
||||
|
||||
if ( !PyArg_ParseTuple(args, "s#idd:tostereo",
|
||||
|
@ -868,13 +863,8 @@ audioop_tostereo(PyObject *self, PyObject *args)
|
|||
if (!audioop_check_parameters(len, size))
|
||||
return NULL;
|
||||
|
||||
if ( size == 1 ) maxval = (double) 0x7f;
|
||||
else if ( size == 2 ) maxval = (double) 0x7fff;
|
||||
else if ( size == 4 ) maxval = (double) 0x7fffffff;
|
||||
else {
|
||||
PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
|
||||
return 0;
|
||||
}
|
||||
maxval = (double) maxvals[size];
|
||||
minval = (double) minvals[size];
|
||||
|
||||
if (len > PY_SSIZE_T_MAX/2) {
|
||||
PyErr_SetString(PyExc_MemoryError,
|
||||
|
@ -894,14 +884,10 @@ audioop_tostereo(PyObject *self, PyObject *args)
|
|||
else if ( size == 4 ) val = (int)*LONGP(cp, i);
|
||||
|
||||
fval = (double)val*fac1;
|
||||
if ( fval > maxval ) fval = maxval;
|
||||
else if ( fval < -maxval ) fval = -maxval;
|
||||
val1 = (int)fval;
|
||||
val1 = (int)floor(fbound(fval, minval, maxval));
|
||||
|
||||
fval = (double)val*fac2;
|
||||
if ( fval > maxval ) fval = maxval;
|
||||
else if ( fval < -maxval ) fval = -maxval;
|
||||
val2 = (int)fval;
|
||||
val2 = (int)floor(fbound(fval, minval, maxval));
|
||||
|
||||
if ( size == 1 ) *CHARP(ncp, i*2) = (signed char)val1;
|
||||
else if ( size == 2 ) *SHORTP(ncp, i*2) = (short)val1;
|
||||
|
@ -919,7 +905,7 @@ audioop_add(PyObject *self, PyObject *args)
|
|||
{
|
||||
signed char *cp1, *cp2, *ncp;
|
||||
Py_ssize_t len1, len2, i;
|
||||
int size, val1 = 0, val2 = 0, maxval, newval;
|
||||
int size, val1 = 0, val2 = 0, minval, maxval, newval;
|
||||
PyObject *rv;
|
||||
|
||||
if ( !PyArg_ParseTuple(args, "s#s#i:add",
|
||||
|
@ -932,13 +918,8 @@ audioop_add(PyObject *self, PyObject *args)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if ( size == 1 ) maxval = 0x7f;
|
||||
else if ( size == 2 ) maxval = 0x7fff;
|
||||
else if ( size == 4 ) maxval = 0x7fffffff;
|
||||
else {
|
||||
PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
|
||||
return 0;
|
||||
}
|
||||
maxval = maxvals[size];
|
||||
minval = minvals[size];
|
||||
|
||||
rv = PyBytes_FromStringAndSize(NULL, len1);
|
||||
if ( rv == 0 )
|
||||
|
@ -954,12 +935,19 @@ audioop_add(PyObject *self, PyObject *args)
|
|||
else if ( size == 2 ) val2 = (int)*SHORTP(cp2, i);
|
||||
else if ( size == 4 ) val2 = (int)*LONGP(cp2, i);
|
||||
|
||||
newval = val1 + val2;
|
||||
/* truncate in case of overflow */
|
||||
if (newval > maxval) newval = maxval;
|
||||
else if (newval < -maxval) newval = -maxval;
|
||||
else if (size == 4 && (newval^val1) < 0 && (newval^val2) < 0)
|
||||
newval = val1 > 0 ? maxval : - maxval;
|
||||
if (size < 4) {
|
||||
newval = val1 + val2;
|
||||
/* truncate in case of overflow */
|
||||
if (newval > maxval)
|
||||
newval = maxval;
|
||||
else if (newval < minval)
|
||||
newval = minval;
|
||||
}
|
||||
else {
|
||||
double fval = (double)val1 + (double)val2;
|
||||
/* truncate in case of overflow */
|
||||
newval = (int)floor(fbound(fval, minval, maxval));
|
||||
}
|
||||
|
||||
if ( size == 1 ) *CHARP(ncp, i) = (signed char)newval;
|
||||
else if ( size == 2 ) *SHORTP(ncp, i) = (short)newval;
|
||||
|
@ -973,9 +961,9 @@ audioop_bias(PyObject *self, PyObject *args)
|
|||
{
|
||||
signed char *cp, *ncp;
|
||||
Py_ssize_t len, i;
|
||||
int size, val = 0;
|
||||
int size, bias;
|
||||
unsigned int val = 0, mask;
|
||||
PyObject *rv;
|
||||
int bias;
|
||||
|
||||
if ( !PyArg_ParseTuple(args, "s#ii:bias",
|
||||
&cp, &len, &size , &bias) )
|
||||
|
@ -989,15 +977,20 @@ audioop_bias(PyObject *self, PyObject *args)
|
|||
return 0;
|
||||
ncp = (signed char *)PyBytes_AsString(rv);
|
||||
|
||||
mask = masks[size];
|
||||
|
||||
for ( i=0; i < len; i += size ) {
|
||||
if ( size == 1 ) val = (int)*CHARP(cp, i);
|
||||
else if ( size == 2 ) val = (int)*SHORTP(cp, i);
|
||||
else if ( size == 4 ) val = (int)*LONGP(cp, i);
|
||||
if ( size == 1 ) val = (unsigned int)(unsigned char)*CHARP(cp, i);
|
||||
else if ( size == 2 ) val = (unsigned int)(unsigned short)*SHORTP(cp, i);
|
||||
else if ( size == 4 ) val = (unsigned int)(Py_UInt32)*LONGP(cp, i);
|
||||
|
||||
if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val+bias);
|
||||
else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val+bias);
|
||||
else if ( size == 4 ) *LONGP(ncp, i) = (Py_Int32)(val+bias);
|
||||
val += (unsigned int)bias;
|
||||
/* wrap around in case of overflow */
|
||||
val &= mask;
|
||||
|
||||
if ( size == 1 ) *CHARP(ncp, i) = (signed char)(unsigned char)val;
|
||||
else if ( size == 2 ) *SHORTP(ncp, i) = (short)(unsigned short)val;
|
||||
else if ( size == 4 ) *LONGP(ncp, i) = (Py_Int32)(Py_UInt32)val;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
@ -1024,15 +1017,15 @@ audioop_reverse(PyObject *self, PyObject *args)
|
|||
ncp = (unsigned char *)PyBytes_AsString(rv);
|
||||
|
||||
for ( i=0; i < len; i += size ) {
|
||||
if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
|
||||
else if ( size == 2 ) val = (int)*SHORTP(cp, i);
|
||||
else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
|
||||
if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 24;
|
||||
else if ( size == 2 ) val = ((int)*SHORTP(cp, i)) << 16;
|
||||
else if ( size == 4 ) val = (int)*LONGP(cp, i);
|
||||
|
||||
j = len - i - size;
|
||||
|
||||
if ( size == 1 ) *CHARP(ncp, j) = (signed char)(val >> 8);
|
||||
else if ( size == 2 ) *SHORTP(ncp, j) = (short)(val);
|
||||
else if ( size == 4 ) *LONGP(ncp, j) = (Py_Int32)(val<<16);
|
||||
if ( size == 1 ) *CHARP(ncp, j) = (signed char)(val >> 24);
|
||||
else if ( size == 2 ) *SHORTP(ncp, j) = (short)(val >> 16);
|
||||
else if ( size == 4 ) *LONGP(ncp, j) = (Py_Int32)val;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
@ -1066,13 +1059,13 @@ audioop_lin2lin(PyObject *self, PyObject *args)
|
|||
ncp = (unsigned char *)PyBytes_AsString(rv);
|
||||
|
||||
for ( i=0, j=0; i < len; i += size, j += size2 ) {
|
||||
if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
|
||||
else if ( size == 2 ) val = (int)*SHORTP(cp, i);
|
||||
else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
|
||||
if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 24;
|
||||
else if ( size == 2 ) val = ((int)*SHORTP(cp, i)) << 16;
|
||||
else if ( size == 4 ) val = (int)*LONGP(cp, i);
|
||||
|
||||
if ( size2 == 1 ) *CHARP(ncp, j) = (signed char)(val >> 8);
|
||||
else if ( size2 == 2 ) *SHORTP(ncp, j) = (short)(val);
|
||||
else if ( size2 == 4 ) *LONGP(ncp, j) = (Py_Int32)(val<<16);
|
||||
if ( size2 == 1 ) *CHARP(ncp, j) = (signed char)(val >> 24);
|
||||
else if ( size2 == 2 ) *SHORTP(ncp, j) = (short)(val >> 16);
|
||||
else if ( size2 == 4 ) *LONGP(ncp, j) = (Py_Int32)val;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
@ -1136,6 +1129,10 @@ audioop_ratecv(PyObject *self, PyObject *args)
|
|||
d = gcd(inrate, outrate);
|
||||
inrate /= d;
|
||||
outrate /= d;
|
||||
/* divide weightA and weightB by their greatest common divisor */
|
||||
d = gcd(weightA, weightB);
|
||||
weightA /= d;
|
||||
weightA /= d;
|
||||
|
||||
if ((size_t)nchannels > PY_SIZE_MAX/sizeof(int)) {
|
||||
PyErr_SetString(PyExc_MemoryError,
|
||||
|
@ -1175,7 +1172,9 @@ audioop_ratecv(PyObject *self, PyObject *args)
|
|||
}
|
||||
|
||||
/* str <- Space for the output buffer. */
|
||||
{
|
||||
if (len == 0)
|
||||
str = PyBytes_FromStringAndSize(NULL, 0);
|
||||
else {
|
||||
/* There are len input frames, so we need (mathematically)
|
||||
ceiling(len*outrate/inrate) output frames, and each frame
|
||||
requires bytes_per_frame bytes. Computing this
|
||||
|
@ -1190,12 +1189,11 @@ audioop_ratecv(PyObject *self, PyObject *args)
|
|||
else
|
||||
str = PyBytes_FromStringAndSize(NULL,
|
||||
q * outrate * bytes_per_frame);
|
||||
|
||||
if (str == NULL) {
|
||||
PyErr_SetString(PyExc_MemoryError,
|
||||
"not enough memory for output buffer");
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
if (str == NULL) {
|
||||
PyErr_SetString(PyExc_MemoryError,
|
||||
"not enough memory for output buffer");
|
||||
goto exit;
|
||||
}
|
||||
ncp = PyBytes_AsString(str);
|
||||
|
||||
|
@ -1229,32 +1227,32 @@ audioop_ratecv(PyObject *self, PyObject *args)
|
|||
for (chan = 0; chan < nchannels; chan++) {
|
||||
prev_i[chan] = cur_i[chan];
|
||||
if (size == 1)
|
||||
cur_i[chan] = ((int)*CHARP(cp, 0)) << 8;
|
||||
cur_i[chan] = ((int)*CHARP(cp, 0)) << 24;
|
||||
else if (size == 2)
|
||||
cur_i[chan] = (int)*SHORTP(cp, 0);
|
||||
cur_i[chan] = ((int)*SHORTP(cp, 0)) << 16;
|
||||
else if (size == 4)
|
||||
cur_i[chan] = ((int)*LONGP(cp, 0)) >> 16;
|
||||
cur_i[chan] = (int)*LONGP(cp, 0);
|
||||
cp += size;
|
||||
/* implements a simple digital filter */
|
||||
cur_i[chan] =
|
||||
(weightA * cur_i[chan] +
|
||||
weightB * prev_i[chan]) /
|
||||
(weightA + weightB);
|
||||
cur_i[chan] = (int)(
|
||||
((double)weightA * (double)cur_i[chan] +
|
||||
(double)weightB * (double)prev_i[chan]) /
|
||||
((double)weightA + (double)weightB));
|
||||
}
|
||||
len--;
|
||||
d += outrate;
|
||||
}
|
||||
while (d >= 0) {
|
||||
for (chan = 0; chan < nchannels; chan++) {
|
||||
cur_o = (prev_i[chan] * d +
|
||||
cur_i[chan] * (outrate - d)) /
|
||||
outrate;
|
||||
cur_o = (int)(((double)prev_i[chan] * (double)d +
|
||||
(double)cur_i[chan] * (double)(outrate - d)) /
|
||||
(double)outrate);
|
||||
if (size == 1)
|
||||
*CHARP(ncp, 0) = (signed char)(cur_o >> 8);
|
||||
*CHARP(ncp, 0) = (signed char)(cur_o >> 24);
|
||||
else if (size == 2)
|
||||
*SHORTP(ncp, 0) = (short)(cur_o);
|
||||
*SHORTP(ncp, 0) = (short)(cur_o >> 16);
|
||||
else if (size == 4)
|
||||
*LONGP(ncp, 0) = (Py_Int32)(cur_o<<16);
|
||||
*LONGP(ncp, 0) = (Py_Int32)(cur_o);
|
||||
ncp += size;
|
||||
}
|
||||
d -= inrate;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue