summaryrefslogtreecommitdiffstats
path: root/Modules/audioop.c
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/audioop.c')
-rw-r--r--Modules/audioop.c1324
1 files changed, 776 insertions, 548 deletions
diff --git a/Modules/audioop.c b/Modules/audioop.c
index 3f04762..9a5d8c1 100644
--- a/Modules/audioop.c
+++ b/Modules/audioop.c
@@ -5,18 +5,6 @@
#include "Python.h"
-#if SIZEOF_INT == 4
-typedef int Py_Int32;
-typedef unsigned int Py_UInt32;
-#else
-#if SIZEOF_LONG == 4
-typedef long Py_Int32;
-typedef unsigned long Py_UInt32;
-#else
-#error "No 4-byte integral type"
-#endif
-#endif
-
typedef short PyInt16;
#if defined(__CHAR_UNSIGNED__)
@@ -38,7 +26,7 @@ fbound(double val, double minval, double maxval)
val = maxval;
else if (val < minval + 1)
val = minval;
- return val;
+ return (int)val;
}
@@ -124,7 +112,7 @@ static PyInt16 _st_ulaw2linear16[256] = {
/*
* linear2ulaw() accepts a 14-bit signed integer and encodes it as u-law data
- * stored in a unsigned char. This function should only be called with
+ * stored in an unsigned char. This function should only be called with
* the data shifted such that it only contains information in the lower
* 14-bits.
*
@@ -161,9 +149,6 @@ st_14linear2ulaw(PyInt16 pcm_val) /* 2's complement (14-bit range) */
PyInt16 seg;
unsigned char uval;
- /* The original sox code does this in the calling function, not here */
- pcm_val = pcm_val >> 2;
-
/* u-law inverts all bits */
/* Get the sign and the magnitude of the value. */
if (pcm_val < 0) {
@@ -233,7 +218,7 @@ static PyInt16 _st_alaw2linear16[256] = {
/*
* linear2alaw() accepts an 13-bit signed integer and encodes it as A-law data
- * stored in a unsigned char. This function should only be called with
+ * stored in an unsigned char. This function should only be called with
* the data shifted such that it only contains information in the lower
* 13-bits.
*
@@ -258,9 +243,6 @@ st_linear2alaw(PyInt16 pcm_val) /* 2's complement (13-bit range) */
short seg;
unsigned char aval;
- /* The original sox code does this in the calling function, not here */
- pcm_val = pcm_val >> 3;
-
/* A-law using even bit inversion */
if (pcm_val >= 0) {
mask = 0xD5; /* sign (7th) bit = 1 */
@@ -305,10 +287,82 @@ static int stepsizeTable[89] = {
15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
};
-#define CHARP(cp, i) ((signed char *)(cp+i))
-#define SHORTP(cp, i) ((short *)(cp+i))
-#define LONGP(cp, i) ((Py_Int32 *)(cp+i))
+#define GETINTX(T, cp, i) (*(T *)((unsigned char *)(cp) + (i)))
+#define SETINTX(T, cp, i, val) do { \
+ *(T *)((unsigned char *)(cp) + (i)) = (T)(val); \
+ } while (0)
+
+
+#define GETINT8(cp, i) GETINTX(signed char, (cp), (i))
+#define GETINT16(cp, i) GETINTX(short, (cp), (i))
+#define GETINT32(cp, i) GETINTX(PY_INT32_T, (cp), (i))
+
+#if WORDS_BIGENDIAN
+#define GETINT24(cp, i) ( \
+ ((unsigned char *)(cp) + (i))[2] + \
+ (((unsigned char *)(cp) + (i))[1] << 8) + \
+ (((signed char *)(cp) + (i))[0] << 16) )
+#else
+#define GETINT24(cp, i) ( \
+ ((unsigned char *)(cp) + (i))[0] + \
+ (((unsigned char *)(cp) + (i))[1] << 8) + \
+ (((signed char *)(cp) + (i))[2] << 16) )
+#endif
+
+
+#define SETINT8(cp, i, val) SETINTX(signed char, (cp), (i), (val))
+#define SETINT16(cp, i, val) SETINTX(short, (cp), (i), (val))
+#define SETINT32(cp, i, val) SETINTX(PY_INT32_T, (cp), (i), (val))
+
+#if WORDS_BIGENDIAN
+#define SETINT24(cp, i, val) do { \
+ ((unsigned char *)(cp) + (i))[2] = (int)(val); \
+ ((unsigned char *)(cp) + (i))[1] = (int)(val) >> 8; \
+ ((signed char *)(cp) + (i))[0] = (int)(val) >> 16; \
+ } while (0)
+#else
+#define SETINT24(cp, i, val) do { \
+ ((unsigned char *)(cp) + (i))[0] = (int)(val); \
+ ((unsigned char *)(cp) + (i))[1] = (int)(val) >> 8; \
+ ((signed char *)(cp) + (i))[2] = (int)(val) >> 16; \
+ } while (0)
+#endif
+
+#define GETRAWSAMPLE(size, cp, i) ( \
+ (size == 1) ? (int)GETINT8((cp), (i)) : \
+ (size == 2) ? (int)GETINT16((cp), (i)) : \
+ (size == 3) ? (int)GETINT24((cp), (i)) : \
+ (int)GETINT32((cp), (i)))
+
+#define SETRAWSAMPLE(size, cp, i, val) do { \
+ if (size == 1) \
+ SETINT8((cp), (i), (val)); \
+ else if (size == 2) \
+ SETINT16((cp), (i), (val)); \
+ else if (size == 3) \
+ SETINT24((cp), (i), (val)); \
+ else \
+ SETINT32((cp), (i), (val)); \
+ } while(0)
+
+
+#define GETSAMPLE32(size, cp, i) ( \
+ (size == 1) ? (int)GETINT8((cp), (i)) << 24 : \
+ (size == 2) ? (int)GETINT16((cp), (i)) << 16 : \
+ (size == 3) ? (int)GETINT24((cp), (i)) << 8 : \
+ (int)GETINT32((cp), (i)))
+
+#define SETSAMPLE32(size, cp, i, val) do { \
+ if (size == 1) \
+ SETINT8((cp), (i), (val) >> 24); \
+ else if (size == 2) \
+ SETINT16((cp), (i), (val) >> 16); \
+ else if (size == 3) \
+ SETINT24((cp), (i), (val) >> 8); \
+ else \
+ SETINT32((cp), (i), (val)); \
+ } while(0)
static PyObject *AudioopError;
@@ -316,8 +370,8 @@ static PyObject *AudioopError;
static int
audioop_check_size(int size)
{
- if (size != 1 && size != 2 && size != 4) {
- PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
+ if (size < 1 || size > 4) {
+ PyErr_SetString(AudioopError, "Size should be 1, 2, 3 or 4");
return 0;
}
else
@@ -336,43 +390,60 @@ audioop_check_parameters(Py_ssize_t len, int size)
return 1;
}
+/*[clinic input]
+output preset file
+module audioop
+[clinic start generated code]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=5619f935f269199a]*/
+
+/*[clinic input]
+audioop.getsample
+
+ fragment: Py_buffer
+ width: int
+ index: Py_ssize_t
+ /
+
+Return the value of sample index from the fragment.
+[clinic start generated code]*/
+
static PyObject *
-audioop_getsample(PyObject *self, PyObject *args)
+audioop_getsample_impl(PyModuleDef *module, Py_buffer *fragment, int width, Py_ssize_t index)
+/*[clinic end generated code: output=f4482497e6f6e78f input=88edbe2871393549]*/
{
- signed char *cp;
- Py_ssize_t len, i;
- int size, val = 0;
+ int val;
- if ( !PyArg_ParseTuple(args, "s#in:getsample", &cp, &len, &size, &i) )
- return 0;
- if (!audioop_check_parameters(len, size))
+ if (!audioop_check_parameters(fragment->len, width))
return NULL;
- if ( i < 0 || i >= len/size ) {
+ if (index < 0 || index >= fragment->len/width) {
PyErr_SetString(AudioopError, "Index out of range");
- return 0;
+ return NULL;
}
- if ( size == 1 ) val = (int)*CHARP(cp, i);
- else if ( size == 2 ) val = (int)*SHORTP(cp, i*2);
- else if ( size == 4 ) val = (int)*LONGP(cp, i*4);
+ val = GETRAWSAMPLE(width, fragment->buf, index*width);
return PyLong_FromLong(val);
}
+/*[clinic input]
+audioop.max
+
+ fragment: Py_buffer
+ width: int
+ /
+
+Return the maximum of the absolute value of all samples in a fragment.
+[clinic start generated code]*/
+
static PyObject *
-audioop_max(PyObject *self, PyObject *args)
+audioop_max_impl(PyModuleDef *module, Py_buffer *fragment, int width)
+/*[clinic end generated code: output=85047ee1001f2305 input=32bea5ea0ac8c223]*/
{
- signed char *cp;
- Py_ssize_t len, i;
- int size, val = 0;
+ Py_ssize_t i;
unsigned int absval, max = 0;
- if ( !PyArg_ParseTuple(args, "s#i:max", &cp, &len, &size) )
- return 0;
- if (!audioop_check_parameters(len, size))
+ if (!audioop_check_parameters(fragment->len, width))
return NULL;
- 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);
+ for (i = 0; i < fragment->len; i += width) {
+ int val = GETRAWSAMPLE(width, fragment->buf, i);
if (val < 0) absval = (-val);
else absval = val;
if (absval > max) max = absval;
@@ -380,82 +451,96 @@ audioop_max(PyObject *self, PyObject *args)
return PyLong_FromUnsignedLong(max);
}
+/*[clinic input]
+audioop.minmax
+
+ fragment: Py_buffer
+ width: int
+ /
+
+Return the minimum and maximum values of all samples in the sound fragment.
+[clinic start generated code]*/
+
static PyObject *
-audioop_minmax(PyObject *self, PyObject *args)
+audioop_minmax_impl(PyModuleDef *module, Py_buffer *fragment, int width)
+/*[clinic end generated code: output=ae8f5513c64fd569 input=89848e9b927a0696]*/
{
- signed char *cp;
- Py_ssize_t len, i;
- int size, val = 0;
+ Py_ssize_t i;
/* -1 trick below is needed on Windows to support -0x80000000 without
a warning */
int min = 0x7fffffff, max = -0x7FFFFFFF-1;
- if (!PyArg_ParseTuple(args, "s#i:minmax", &cp, &len, &size))
+ if (!audioop_check_parameters(fragment->len, width))
return NULL;
- if (!audioop_check_parameters(len, size))
- return NULL;
- 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);
+ for (i = 0; i < fragment->len; i += width) {
+ int val = GETRAWSAMPLE(width, fragment->buf, i);
if (val > max) max = val;
if (val < min) min = val;
}
return Py_BuildValue("(ii)", min, max);
}
+/*[clinic input]
+audioop.avg
+
+ fragment: Py_buffer
+ width: int
+ /
+
+Return the average over all samples in the fragment.
+[clinic start generated code]*/
+
static PyObject *
-audioop_avg(PyObject *self, PyObject *args)
+audioop_avg_impl(PyModuleDef *module, Py_buffer *fragment, int width)
+/*[clinic end generated code: output=7fccd645c95f4860 input=1114493c7611334d]*/
{
- signed char *cp;
- Py_ssize_t len, i;
- int size, val = 0;
- double avg = 0.0;
+ Py_ssize_t i;
+ int avg;
+ double sum = 0.0;
- if ( !PyArg_ParseTuple(args, "s#i:avg", &cp, &len, &size) )
- return 0;
- if (!audioop_check_parameters(len, size))
+ if (!audioop_check_parameters(fragment->len, width))
return NULL;
- 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);
- avg += val;
- }
- if ( len == 0 )
- val = 0;
+ for (i = 0; i < fragment->len; i += width)
+ sum += GETRAWSAMPLE(width, fragment->buf, i);
+ if (fragment->len == 0)
+ avg = 0;
else
- val = (int)floor(avg / (double)(len/size));
- return PyLong_FromLong(val);
+ avg = (int)floor(sum / (double)(fragment->len/width));
+ return PyLong_FromLong(avg);
}
+/*[clinic input]
+audioop.rms
+
+ fragment: Py_buffer
+ width: int
+ /
+
+Return the root-mean-square of the fragment, i.e. sqrt(sum(S_i^2)/n).
+[clinic start generated code]*/
+
static PyObject *
-audioop_rms(PyObject *self, PyObject *args)
+audioop_rms_impl(PyModuleDef *module, Py_buffer *fragment, int width)
+/*[clinic end generated code: output=7b398702c81b709d input=4cc57c6c94219d78]*/
{
- signed char *cp;
- Py_ssize_t len, i;
- int size, val = 0;
+ Py_ssize_t i;
unsigned int res;
double sum_squares = 0.0;
- if ( !PyArg_ParseTuple(args, "s#i:rms", &cp, &len, &size) )
- return 0;
- if (!audioop_check_parameters(len, size))
+ if (!audioop_check_parameters(fragment->len, width))
return NULL;
- 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);
- sum_squares += (double)val*(double)val;
+ for (i = 0; i < fragment->len; i += width) {
+ double val = GETRAWSAMPLE(width, fragment->buf, i);
+ sum_squares += val*val;
}
- if ( len == 0 )
+ if (fragment->len == 0)
res = 0;
else
- res = (unsigned int)sqrt(sum_squares / (double)(len/size));
+ res = (unsigned int)sqrt(sum_squares / (double)(fragment->len/width));
return PyLong_FromUnsignedLong(res);
}
-static double _sum2(short *a, short *b, Py_ssize_t len)
+static double _sum2(const short *a, const short *b, Py_ssize_t len)
{
Py_ssize_t i;
double sum = 0.0;
@@ -498,32 +583,38 @@ static double _sum2(short *a, short *b, Py_ssize_t len)
** sum_ri is calculated once, sum_aij_2 is updated each step and sum_aij_ri
** is completely recalculated each step.
*/
+/*[clinic input]
+audioop.findfit
+
+ fragment: Py_buffer
+ reference: Py_buffer
+ /
+
+Try to match reference as well as possible to a portion of fragment.
+[clinic start generated code]*/
+
static PyObject *
-audioop_findfit(PyObject *self, PyObject *args)
+audioop_findfit_impl(PyModuleDef *module, Py_buffer *fragment, Py_buffer *reference)
+/*[clinic end generated code: output=505fd04d4244db31 input=62c305605e183c9a]*/
{
- short *cp1, *cp2;
+ const short *cp1, *cp2;
Py_ssize_t len1, len2;
Py_ssize_t j, best_j;
double aj_m1, aj_lm1;
double sum_ri_2, sum_aij_2, sum_aij_ri, result, best_result, factor;
- /* Passing a short** for an 's' argument is correct only
- if the string contents is aligned for interpretation
- as short[]. Due to the definition of PyBytesObject,
- this is currently (Python 2.6) the case. */
- if ( !PyArg_ParseTuple(args, "s#s#:findfit",
- (char**)&cp1, &len1, (char**)&cp2, &len2) )
- return 0;
- if ( len1 & 1 || len2 & 1 ) {
+ if (fragment->len & 1 || reference->len & 1) {
PyErr_SetString(AudioopError, "Strings should be even-sized");
- return 0;
+ return NULL;
}
- len1 >>= 1;
- len2 >>= 1;
+ cp1 = (const short *)fragment->buf;
+ len1 = fragment->len >> 1;
+ cp2 = (const short *)reference->buf;
+ len2 = reference->len >> 1;
- if ( len1 < len2 ) {
+ if (len1 < len2) {
PyErr_SetString(AudioopError, "First sample should be longer");
- return 0;
+ return NULL;
}
sum_ri_2 = _sum2(cp2, cp2, len2);
sum_aij_2 = _sum2(cp1, cp1, len2);
@@ -560,27 +651,37 @@ audioop_findfit(PyObject *self, PyObject *args)
** findfactor finds a factor f so that the energy in A-fB is minimal.
** See the comment for findfit for details.
*/
+/*[clinic input]
+audioop.findfactor
+
+ fragment: Py_buffer
+ reference: Py_buffer
+ /
+
+Return a factor F such that rms(add(fragment, mul(reference, -F))) is minimal.
+[clinic start generated code]*/
+
static PyObject *
-audioop_findfactor(PyObject *self, PyObject *args)
+audioop_findfactor_impl(PyModuleDef *module, Py_buffer *fragment, Py_buffer *reference)
+/*[clinic end generated code: output=ddf35a1e57575ce4 input=816680301d012b21]*/
{
- short *cp1, *cp2;
- Py_ssize_t len1, len2;
+ const short *cp1, *cp2;
+ Py_ssize_t len;
double sum_ri_2, sum_aij_ri, result;
- if ( !PyArg_ParseTuple(args, "s#s#:findfactor",
- (char**)&cp1, &len1, (char**)&cp2, &len2) )
- return 0;
- if ( len1 & 1 || len2 & 1 ) {
+ if (fragment->len & 1 || reference->len & 1) {
PyErr_SetString(AudioopError, "Strings should be even-sized");
- return 0;
+ return NULL;
}
- if ( len1 != len2 ) {
+ if (fragment->len != reference->len) {
PyErr_SetString(AudioopError, "Samples should be same size");
- return 0;
+ return NULL;
}
- len2 >>= 1;
- sum_ri_2 = _sum2(cp2, cp2, len2);
- sum_aij_ri = _sum2(cp1, cp2, len2);
+ cp1 = (const short *)fragment->buf;
+ cp2 = (const short *)reference->buf;
+ len = fragment->len >> 1;
+ sum_ri_2 = _sum2(cp2, cp2, len);
+ sum_aij_ri = _sum2(cp1, cp2, len);
result = sum_aij_ri / sum_ri_2;
@@ -591,37 +692,46 @@ audioop_findfactor(PyObject *self, PyObject *args)
** findmax returns the index of the n-sized segment of the input sample
** that contains the most energy.
*/
+/*[clinic input]
+audioop.findmax
+
+ fragment: Py_buffer
+ length: Py_ssize_t
+ /
+
+Search fragment for a slice of specified number of samples with maximum energy.
+[clinic start generated code]*/
+
static PyObject *
-audioop_findmax(PyObject *self, PyObject *args)
+audioop_findmax_impl(PyModuleDef *module, Py_buffer *fragment, Py_ssize_t length)
+/*[clinic end generated code: output=21d0c2a1e5655134 input=2f304801ed42383c]*/
{
- short *cp1;
- Py_ssize_t len1, len2;
+ const short *cp1;
+ Py_ssize_t len1;
Py_ssize_t j, best_j;
double aj_m1, aj_lm1;
double result, best_result;
- if ( !PyArg_ParseTuple(args, "s#n:findmax",
- (char**)&cp1, &len1, &len2) )
- return 0;
- if ( len1 & 1 ) {
+ if (fragment->len & 1) {
PyErr_SetString(AudioopError, "Strings should be even-sized");
- return 0;
+ return NULL;
}
- len1 >>= 1;
+ cp1 = (const short *)fragment->buf;
+ len1 = fragment->len >> 1;
- if ( len2 < 0 || len1 < len2 ) {
+ if (length < 0 || len1 < length) {
PyErr_SetString(AudioopError, "Input sample should be longer");
- return 0;
+ return NULL;
}
- result = _sum2(cp1, cp1, len2);
+ result = _sum2(cp1, cp1, length);
best_result = result;
best_j = 0;
- for ( j=1; j<=len1-len2; j++) {
+ for ( j=1; j<=len1-length; j++) {
aj_m1 = (double)cp1[j-1];
- aj_lm1 = (double)cp1[j+len2-1];
+ aj_lm1 = (double)cp1[j+length-1];
result = result + aj_lm1*aj_lm1 - aj_m1*aj_m1;
@@ -635,31 +745,34 @@ audioop_findmax(PyObject *self, PyObject *args)
return PyLong_FromSsize_t(best_j);
}
+/*[clinic input]
+audioop.avgpp
+
+ fragment: Py_buffer
+ width: int
+ /
+
+Return the average peak-peak value over all samples in the fragment.
+[clinic start generated code]*/
+
static PyObject *
-audioop_avgpp(PyObject *self, PyObject *args)
+audioop_avgpp_impl(PyModuleDef *module, Py_buffer *fragment, int width)
+/*[clinic end generated code: output=06c8380fd6e34207 input=0b3cceeae420a7d9]*/
{
- signed char *cp;
- Py_ssize_t len, i;
- int size, val = 0, prevval = 0, prevextremevalid = 0,
- prevextreme = 0;
+ Py_ssize_t i;
+ int prevval, prevextremevalid = 0, prevextreme = 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))
+ if (!audioop_check_parameters(fragment->len, width))
return NULL;
- if (len <= size)
+ if (fragment->len <= width)
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);
+ prevval = GETRAWSAMPLE(width, fragment->buf, 0);
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);
+ for (i = width; i < fragment->len; i += width) {
+ int val = GETRAWSAMPLE(width, fragment->buf, i);
if (val != prevval) {
diff = val < prevval;
if (prevdiff == !diff) {
@@ -667,7 +780,12 @@ audioop_avgpp(PyObject *self, PyObject *args)
** extreme value and remember.
*/
if (prevextremevalid) {
- sum += fabs((double)prevval - (double)prevextreme);
+ if (prevval < prevextreme)
+ sum += (double)((unsigned int)prevextreme -
+ (unsigned int)prevval);
+ else
+ sum += (double)((unsigned int)prevval -
+ (unsigned int)prevextreme);
nextreme++;
}
prevextremevalid = 1;
@@ -684,30 +802,33 @@ audioop_avgpp(PyObject *self, PyObject *args)
return PyLong_FromUnsignedLong(avg);
}
+/*[clinic input]
+audioop.maxpp
+
+ fragment: Py_buffer
+ width: int
+ /
+
+Return the maximum peak-peak value in the sound fragment.
+[clinic start generated code]*/
+
static PyObject *
-audioop_maxpp(PyObject *self, PyObject *args)
+audioop_maxpp_impl(PyModuleDef *module, Py_buffer *fragment, int width)
+/*[clinic end generated code: output=c300c0bd7e8535c0 input=671a13e1518f80a1]*/
{
- signed char *cp;
- Py_ssize_t len, i;
- int size, val = 0, prevval = 0, prevextremevalid = 0,
- prevextreme = 0;
+ Py_ssize_t i;
+ int prevval, prevextremevalid = 0, prevextreme = 0;
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))
+ if (!audioop_check_parameters(fragment->len, width))
return NULL;
- if (len <= size)
+ if (fragment->len <= width)
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);
+ prevval = GETRAWSAMPLE(width, fragment->buf, 0);
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);
+ for (i = width; i < fragment->len; i += width) {
+ int val = GETRAWSAMPLE(width, fragment->buf, i);
if (val != prevval) {
diff = val < prevval;
if (prevdiff == !diff) {
@@ -734,209 +855,212 @@ audioop_maxpp(PyObject *self, PyObject *args)
return PyLong_FromUnsignedLong(max);
}
+/*[clinic input]
+audioop.cross
+
+ fragment: Py_buffer
+ width: int
+ /
+
+Return the number of zero crossings in the fragment passed as an argument.
+[clinic start generated code]*/
+
static PyObject *
-audioop_cross(PyObject *self, PyObject *args)
+audioop_cross_impl(PyModuleDef *module, Py_buffer *fragment, int width)
+/*[clinic end generated code: output=99e6572d7d7cdbf1 input=b1b3f15b83f6b41a]*/
{
- signed char *cp;
- Py_ssize_t len, i;
- int size, val = 0;
+ Py_ssize_t i;
int prevval;
Py_ssize_t ncross;
- if ( !PyArg_ParseTuple(args, "s#i:cross", &cp, &len, &size) )
- return 0;
- if (!audioop_check_parameters(len, size))
+ if (!audioop_check_parameters(fragment->len, width))
return NULL;
ncross = -1;
prevval = 17; /* Anything <> 0,1 */
- for ( i=0; i<len; i+= size) {
- if ( size == 1 ) val = ((int)*CHARP(cp, i)) >> 7;
- else if ( size == 2 ) val = ((int)*SHORTP(cp, i)) >> 15;
- else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 31;
- val = val & 1;
- if ( val != prevval ) ncross++;
+ for (i = 0; i < fragment->len; i += width) {
+ int val = GETRAWSAMPLE(width, fragment->buf, i) < 0;
+ if (val != prevval) ncross++;
prevval = val;
}
return PyLong_FromSsize_t(ncross);
}
+/*[clinic input]
+audioop.mul
+
+ fragment: Py_buffer
+ width: int
+ factor: double
+ /
+
+Return a fragment that has all samples in the original fragment multiplied by the floating-point value factor.
+[clinic start generated code]*/
+
static PyObject *
-audioop_mul(PyObject *self, PyObject *args)
+audioop_mul_impl(PyModuleDef *module, Py_buffer *fragment, int width, double factor)
+/*[clinic end generated code: output=a697ebbd5852d38f input=c726667baa157d3c]*/
{
- signed char *cp, *ncp;
- Py_ssize_t len, i;
- int size, val = 0;
- double factor, fval, maxval, minval;
+ signed char *ncp;
+ Py_ssize_t i;
+ double maxval, minval;
PyObject *rv;
- if ( !PyArg_ParseTuple(args, "s#id:mul", &cp, &len, &size, &factor ) )
- return 0;
- if (!audioop_check_parameters(len, size))
+ if (!audioop_check_parameters(fragment->len, width))
return NULL;
- maxval = (double) maxvals[size];
- minval = (double) minvals[size];
+ maxval = (double) maxvals[width];
+ minval = (double) minvals[width];
- rv = PyBytes_FromStringAndSize(NULL, len);
- if ( rv == 0 )
- return 0;
+ rv = PyBytes_FromStringAndSize(NULL, fragment->len);
+ if (rv == NULL)
+ return NULL;
ncp = (signed char *)PyBytes_AsString(rv);
-
- 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);
- fval = (double)val*factor;
- 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;
+ 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);
}
return rv;
}
+/*[clinic input]
+audioop.tomono
+
+ fragment: Py_buffer
+ width: int
+ lfactor: double
+ rfactor: double
+ /
+
+Convert a stereo fragment to a mono fragment.
+[clinic start generated code]*/
+
static PyObject *
-audioop_tomono(PyObject *self, PyObject *args)
+audioop_tomono_impl(PyModuleDef *module, Py_buffer *fragment, int width, double lfactor, double rfactor)
+/*[clinic end generated code: output=436e7710521661dd input=c4ec949b3f4dddfa]*/
{
- Py_buffer pcp;
signed char *cp, *ncp;
Py_ssize_t len, i;
- int size, val1 = 0, val2 = 0;
- double fac1, fac2, fval, maxval, minval;
+ double maxval, minval;
PyObject *rv;
- if ( !PyArg_ParseTuple(args, "s*idd:tomono",
- &pcp, &size, &fac1, &fac2 ) )
- return 0;
- cp = pcp.buf;
- len = pcp.len;
- if (!audioop_check_parameters(len, size)) {
- PyBuffer_Release(&pcp);
+ cp = fragment->buf;
+ len = fragment->len;
+ if (!audioop_check_parameters(len, width))
return NULL;
- }
- if (((len / size) & 1) != 0) {
+ if (((len / width) & 1) != 0) {
PyErr_SetString(AudioopError, "not a whole number of frames");
- PyBuffer_Release(&pcp);
return NULL;
}
- maxval = (double) maxvals[size];
- minval = (double) minvals[size];
+ maxval = (double) maxvals[width];
+ minval = (double) minvals[width];
rv = PyBytes_FromStringAndSize(NULL, len/2);
- if ( rv == 0 ) {
- PyBuffer_Release(&pcp);
- return 0;
- }
+ if (rv == NULL)
+ return NULL;
ncp = (signed char *)PyBytes_AsString(rv);
-
- for ( i=0; i < len; i += size*2 ) {
- if ( size == 1 ) val1 = (int)*CHARP(cp, i);
- else if ( size == 2 ) val1 = (int)*SHORTP(cp, i);
- else if ( size == 4 ) val1 = (int)*LONGP(cp, i);
- if ( size == 1 ) val2 = (int)*CHARP(cp, i+1);
- 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;
- 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;
- }
- PyBuffer_Release(&pcp);
+ 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);
+ }
return rv;
}
+/*[clinic input]
+audioop.tostereo
+
+ fragment: Py_buffer
+ width: int
+ lfactor: double
+ rfactor: double
+ /
+
+Generate a stereo fragment from a mono fragment.
+[clinic start generated code]*/
+
static PyObject *
-audioop_tostereo(PyObject *self, PyObject *args)
+audioop_tostereo_impl(PyModuleDef *module, Py_buffer *fragment, int width, double lfactor, double rfactor)
+/*[clinic end generated code: output=6ff50681c87f4c1c input=27b6395ebfdff37a]*/
{
- signed char *cp, *ncp;
- Py_ssize_t len, i;
- int size, val1, val2, val = 0;
- double fac1, fac2, fval, maxval, minval;
+ signed char *ncp;
+ Py_ssize_t i;
+ double maxval, minval;
PyObject *rv;
- if ( !PyArg_ParseTuple(args, "s#idd:tostereo",
- &cp, &len, &size, &fac1, &fac2 ) )
- return 0;
- if (!audioop_check_parameters(len, size))
+ if (!audioop_check_parameters(fragment->len, width))
return NULL;
- maxval = (double) maxvals[size];
- minval = (double) minvals[size];
+ maxval = (double) maxvals[width];
+ minval = (double) minvals[width];
- if (len > PY_SSIZE_T_MAX/2) {
+ if (fragment->len > PY_SSIZE_T_MAX/2) {
PyErr_SetString(PyExc_MemoryError,
"not enough memory for output buffer");
- return 0;
+ return NULL;
}
- rv = PyBytes_FromStringAndSize(NULL, len*2);
- if ( rv == 0 )
- return 0;
+ rv = PyBytes_FromStringAndSize(NULL, fragment->len*2);
+ if (rv == NULL)
+ return NULL;
ncp = (signed char *)PyBytes_AsString(rv);
-
- 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);
-
- fval = (double)val*fac1;
- val1 = (int)floor(fbound(fval, minval, maxval));
-
- fval = (double)val*fac2;
- 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;
- else if ( size == 4 ) *LONGP(ncp, i*2) = (Py_Int32)val1;
-
- if ( size == 1 ) *CHARP(ncp, i*2+1) = (signed char)val2;
- else if ( size == 2 ) *SHORTP(ncp, i*2+2) = (short)val2;
- else if ( size == 4 ) *LONGP(ncp, i*2+4) = (Py_Int32)val2;
+ 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));
+ SETRAWSAMPLE(width, ncp, i*2, val1);
+ SETRAWSAMPLE(width, ncp, i*2 + width, val2);
}
return rv;
}
+/*[clinic input]
+audioop.add
+
+ fragment1: Py_buffer
+ fragment2: Py_buffer
+ width: int
+ /
+
+Return a fragment which is the addition of the two samples passed as parameters.
+[clinic start generated code]*/
+
static PyObject *
-audioop_add(PyObject *self, PyObject *args)
+audioop_add_impl(PyModuleDef *module, Py_buffer *fragment1, Py_buffer *fragment2, int width)
+/*[clinic end generated code: output=f9218bf9ea75c3f1 input=4a8d4bae4c1605c7]*/
{
- signed char *cp1, *cp2, *ncp;
- Py_ssize_t len1, len2, i;
- int size, val1 = 0, val2 = 0, minval, maxval, newval;
+ signed char *ncp;
+ Py_ssize_t i;
+ int minval, maxval, newval;
PyObject *rv;
- if ( !PyArg_ParseTuple(args, "s#s#i:add",
- &cp1, &len1, &cp2, &len2, &size ) )
- return 0;
- if (!audioop_check_parameters(len1, size))
+ if (!audioop_check_parameters(fragment1->len, width))
return NULL;
- if ( len1 != len2 ) {
+ if (fragment1->len != fragment2->len) {
PyErr_SetString(AudioopError, "Lengths should be the same");
- return 0;
+ return NULL;
}
- maxval = maxvals[size];
- minval = minvals[size];
+ maxval = maxvals[width];
+ minval = minvals[width];
- rv = PyBytes_FromStringAndSize(NULL, len1);
- if ( rv == 0 )
- return 0;
+ rv = PyBytes_FromStringAndSize(NULL, fragment1->len);
+ if (rv == NULL)
+ return NULL;
ncp = (signed char *)PyBytes_AsString(rv);
- for ( i=0; i < len1; i += size ) {
- if ( size == 1 ) val1 = (int)*CHARP(cp1, i);
- else if ( size == 2 ) val1 = (int)*SHORTP(cp1, i);
- else if ( size == 4 ) val1 = (int)*LONGP(cp1, i);
-
- if ( size == 1 ) val2 = (int)*CHARP(cp2, i);
- else if ( size == 2 ) val2 = (int)*SHORTP(cp2, i);
- else if ( size == 4 ) val2 = (int)*LONGP(cp2, i);
+ for (i = 0; i < fragment1->len; i += width) {
+ int val1 = GETRAWSAMPLE(width, fragment1->buf, i);
+ int val2 = GETRAWSAMPLE(width, fragment2->buf, i);
- if (size < 4) {
+ if (width < 4) {
newval = val1 + val2;
/* truncate in case of overflow */
if (newval > maxval)
@@ -950,123 +1074,175 @@ audioop_add(PyObject *self, PyObject *args)
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;
- else if ( size == 4 ) *LONGP(ncp, i) = (Py_Int32)newval;
+ SETRAWSAMPLE(width, ncp, i, newval);
}
return rv;
}
+/*[clinic input]
+audioop.bias
+
+ fragment: Py_buffer
+ width: int
+ bias: int
+ /
+
+Return a fragment that is the original fragment with a bias added to each sample.
+[clinic start generated code]*/
+
static PyObject *
-audioop_bias(PyObject *self, PyObject *args)
+audioop_bias_impl(PyModuleDef *module, Py_buffer *fragment, int width, int bias)
+/*[clinic end generated code: output=8ec80b3f5d510a51 input=2b5cce5c3bb4838c]*/
{
- signed char *cp, *ncp;
- Py_ssize_t len, i;
- int size, bias;
+ signed char *ncp;
+ Py_ssize_t i;
unsigned int val = 0, mask;
PyObject *rv;
- if ( !PyArg_ParseTuple(args, "s#ii:bias",
- &cp, &len, &size , &bias) )
- return 0;
-
- if (!audioop_check_parameters(len, size))
+ if (!audioop_check_parameters(fragment->len, width))
return NULL;
- rv = PyBytes_FromStringAndSize(NULL, len);
- if ( rv == 0 )
- return 0;
+ rv = PyBytes_FromStringAndSize(NULL, fragment->len);
+ if (rv == NULL)
+ return NULL;
ncp = (signed char *)PyBytes_AsString(rv);
- mask = masks[size];
+ mask = masks[width];
- for ( i=0; i < len; i += size ) {
- 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);
+ for (i = 0; i < fragment->len; i += width) {
+ if (width == 1)
+ val = GETINTX(unsigned char, fragment->buf, i);
+ else if (width == 2)
+ val = GETINTX(unsigned short, fragment->buf, i);
+ else if (width == 3)
+ val = ((unsigned int)GETINT24(fragment->buf, i)) & 0xffffffu;
+ else {
+ assert(width == 4);
+ val = GETINTX(PY_UINT32_T, fragment->buf, i);
+ }
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;
+ if (width == 1)
+ SETINTX(unsigned char, ncp, i, val);
+ else if (width == 2)
+ SETINTX(unsigned short, ncp, i, val);
+ else if (width == 3)
+ SETINT24(ncp, i, (int)val);
+ else {
+ assert(width == 4);
+ SETINTX(PY_UINT32_T, ncp, i, val);
+ }
}
return rv;
}
+/*[clinic input]
+audioop.reverse
+
+ fragment: Py_buffer
+ width: int
+ /
+
+Reverse the samples in a fragment and returns the modified fragment.
+[clinic start generated code]*/
+
static PyObject *
-audioop_reverse(PyObject *self, PyObject *args)
+audioop_reverse_impl(PyModuleDef *module, Py_buffer *fragment, int width)
+/*[clinic end generated code: output=6ec3c91337f5925e input=668f890cf9f9d225]*/
{
- signed char *cp;
unsigned char *ncp;
- Py_ssize_t len, i, j;
- int size, val = 0;
+ Py_ssize_t i;
PyObject *rv;
- if ( !PyArg_ParseTuple(args, "s#i:reverse",
- &cp, &len, &size) )
- return 0;
-
- if (!audioop_check_parameters(len, size))
+ if (!audioop_check_parameters(fragment->len, width))
return NULL;
- rv = PyBytes_FromStringAndSize(NULL, len);
- if ( rv == 0 )
- return 0;
+ rv = PyBytes_FromStringAndSize(NULL, fragment->len);
+ if (rv == NULL)
+ return NULL;
ncp = (unsigned char *)PyBytes_AsString(rv);
- for ( i=0; i < len; i += size ) {
- 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);
+ for (i = 0; i < fragment->len; i += width) {
+ int val = GETRAWSAMPLE(width, fragment->buf, i);
+ SETRAWSAMPLE(width, ncp, fragment->len - i - width, val);
+ }
+ return rv;
+}
+
+/*[clinic input]
+audioop.byteswap
+
+ fragment: Py_buffer
+ width: int
+ /
+
+Convert big-endian samples to little-endian and vice versa.
+[clinic start generated code]*/
+
+static PyObject *
+audioop_byteswap_impl(PyModuleDef *module, Py_buffer *fragment, int width)
+/*[clinic end generated code: output=bfe4aa584b7a3f5b input=fae7611ceffa5c82]*/
+{
+ unsigned char *ncp;
+ Py_ssize_t i;
+ PyObject *rv;
+
+ if (!audioop_check_parameters(fragment->len, width))
+ return NULL;
- j = len - i - size;
+ rv = PyBytes_FromStringAndSize(NULL, fragment->len);
+ if (rv == NULL)
+ return NULL;
+ ncp = (unsigned char *)PyBytes_AsString(rv);
- 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;
+ for (i = 0; i < fragment->len; i += width) {
+ int j;
+ for (j = 0; j < width; j++)
+ ncp[i + width - 1 - j] = ((unsigned char *)fragment->buf)[i + j];
}
return rv;
}
+/*[clinic input]
+audioop.lin2lin
+
+ fragment: Py_buffer
+ width: int
+ newwidth: int
+ /
+
+Convert samples between 1-, 2-, 3- and 4-byte formats.
+[clinic start generated code]*/
+
static PyObject *
-audioop_lin2lin(PyObject *self, PyObject *args)
+audioop_lin2lin_impl(PyModuleDef *module, Py_buffer *fragment, int width, int newwidth)
+/*[clinic end generated code: output=3f9468a74472a93e input=5ce08c8aa2f24d96]*/
{
- signed char *cp;
unsigned char *ncp;
- Py_ssize_t len, i, j;
- int size, size2, val = 0;
+ Py_ssize_t i, j;
PyObject *rv;
- if ( !PyArg_ParseTuple(args, "s#ii:lin2lin",
- &cp, &len, &size, &size2) )
- return 0;
-
- if (!audioop_check_parameters(len, size))
+ if (!audioop_check_parameters(fragment->len, width))
return NULL;
- if (!audioop_check_size(size2))
+ if (!audioop_check_size(newwidth))
return NULL;
- if (len/size > PY_SSIZE_T_MAX/size2) {
+ if (fragment->len/width > PY_SSIZE_T_MAX/newwidth) {
PyErr_SetString(PyExc_MemoryError,
"not enough memory for output buffer");
- return 0;
+ return NULL;
}
- rv = PyBytes_FromStringAndSize(NULL, (len/size)*size2);
- if ( rv == 0 )
- return 0;
+ rv = PyBytes_FromStringAndSize(NULL, (fragment->len/width)*newwidth);
+ if (rv == NULL)
+ return NULL;
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)) << 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 >> 24);
- else if ( size2 == 2 ) *SHORTP(ncp, j) = (short)(val >> 16);
- else if ( size2 == 4 ) *LONGP(ncp, j) = (Py_Int32)val;
+ for (i = j = 0; i < fragment->len; i += width, j += newwidth) {
+ int val = GETSAMPLE32(width, fragment->buf, i);
+ SETSAMPLE32(newwidth, ncp, j, val);
}
return rv;
}
@@ -1082,29 +1258,39 @@ gcd(int a, int b)
return a;
}
+/*[clinic input]
+audioop.ratecv
+
+ fragment: Py_buffer
+ width: int
+ nchannels: int
+ inrate: int
+ outrate: int
+ state: object
+ weightA: int = 1
+ weightB: int = 0
+ /
+
+Convert the frame rate of the input fragment.
+[clinic start generated code]*/
+
static PyObject *
-audioop_ratecv(PyObject *self, PyObject *args)
+audioop_ratecv_impl(PyModuleDef *module, Py_buffer *fragment, int width, int nchannels, int inrate, int outrate, PyObject *state, int weightA, int weightB)
+/*[clinic end generated code: output=5585dddc4b5ff236 input=aff3acdc94476191]*/
{
char *cp, *ncp;
Py_ssize_t len;
- int size, nchannels, inrate, outrate, weightA, weightB;
int chan, d, *prev_i, *cur_i, cur_o;
- PyObject *state, *samps, *str, *rv = NULL;
+ PyObject *samps, *str, *rv = NULL;
int bytes_per_frame;
- weightA = 1;
- weightB = 0;
- if (!PyArg_ParseTuple(args, "s#iiiiO|ii:ratecv", &cp, &len, &size,
- &nchannels, &inrate, &outrate, &state,
- &weightA, &weightB))
- return NULL;
- if (!audioop_check_size(size))
+ if (!audioop_check_size(width))
return NULL;
if (nchannels < 1) {
PyErr_SetString(AudioopError, "# of channels should be >= 1");
return NULL;
}
- if (size > INT_MAX / nchannels) {
+ if (width > INT_MAX / nchannels) {
/* This overflow test is rigorously correct because
both multiplicands are >= 1. Use the argument names
from the docs for the error msg. */
@@ -1112,13 +1298,14 @@ audioop_ratecv(PyObject *self, PyObject *args)
"width * nchannels too big for a C int");
return NULL;
}
- bytes_per_frame = size * nchannels;
+ bytes_per_frame = width * nchannels;
if (weightA < 1 || weightB < 0) {
PyErr_SetString(AudioopError,
"weightA should be >= 1, weightB should be >= 0");
return NULL;
}
- if (len % bytes_per_frame != 0) {
+ assert(fragment->len >= 0);
+ if (fragment->len % bytes_per_frame != 0) {
PyErr_SetString(AudioopError, "not a whole number of frames");
return NULL;
}
@@ -1133,21 +1320,21 @@ audioop_ratecv(PyObject *self, PyObject *args)
/* divide weightA and weightB by their greatest common divisor */
d = gcd(weightA, weightB);
weightA /= d;
- weightA /= d;
+ weightB /= d;
if ((size_t)nchannels > PY_SIZE_MAX/sizeof(int)) {
PyErr_SetString(PyExc_MemoryError,
"not enough memory for output buffer");
- return 0;
+ return NULL;
}
- prev_i = (int *) malloc(nchannels * sizeof(int));
- cur_i = (int *) malloc(nchannels * sizeof(int));
+ prev_i = (int *) PyMem_Malloc(nchannels * sizeof(int));
+ cur_i = (int *) PyMem_Malloc(nchannels * sizeof(int));
if (prev_i == NULL || cur_i == NULL) {
(void) PyErr_NoMemory();
goto exit;
}
- len /= bytes_per_frame; /* # of frames */
+ len = fragment->len / bytes_per_frame; /* # of frames */
if (state == Py_None) {
d = -outrate;
@@ -1184,7 +1371,7 @@ audioop_ratecv(PyObject *self, PyObject *args)
case ceiling(len/inrate) * outrate. */
/* compute ceiling(len/inrate) without overflow */
- Py_ssize_t q = len > 0 ? 1 + (len - 1) / inrate : 0;
+ Py_ssize_t q = 1 + (len - 1) / inrate;
if (outrate > PY_SSIZE_T_MAX / q / bytes_per_frame)
str = NULL;
else
@@ -1197,6 +1384,7 @@ audioop_ratecv(PyObject *self, PyObject *args)
goto exit;
}
ncp = PyBytes_AsString(str);
+ cp = fragment->buf;
for (;;) {
while (d < 0) {
@@ -1227,13 +1415,8 @@ 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)) << 24;
- else if (size == 2)
- cur_i[chan] = ((int)*SHORTP(cp, 0)) << 16;
- else if (size == 4)
- cur_i[chan] = (int)*LONGP(cp, 0);
- cp += size;
+ cur_i[chan] = GETSAMPLE32(width, cp, 0);
+ cp += width;
/* implements a simple digital filter */
cur_i[chan] = (int)(
((double)weightA * (double)cur_i[chan] +
@@ -1248,206 +1431,229 @@ audioop_ratecv(PyObject *self, PyObject *args)
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 >> 24);
- else if (size == 2)
- *SHORTP(ncp, 0) = (short)(cur_o >> 16);
- else if (size == 4)
- *LONGP(ncp, 0) = (Py_Int32)(cur_o);
- ncp += size;
+ SETSAMPLE32(width, ncp, 0, cur_o);
+ ncp += width;
}
d -= inrate;
}
}
exit:
- if (prev_i != NULL)
- free(prev_i);
- if (cur_i != NULL)
- free(cur_i);
+ PyMem_Free(prev_i);
+ PyMem_Free(cur_i);
return rv;
}
+/*[clinic input]
+audioop.lin2ulaw
+
+ fragment: Py_buffer
+ width: int
+ /
+
+Convert samples in the audio fragment to u-LAW encoding.
+[clinic start generated code]*/
+
static PyObject *
-audioop_lin2ulaw(PyObject *self, PyObject *args)
+audioop_lin2ulaw_impl(PyModuleDef *module, Py_buffer *fragment, int width)
+/*[clinic end generated code: output=26263cc877c5e1bc input=2450d1b870b6bac2]*/
{
- signed char *cp;
unsigned char *ncp;
- Py_ssize_t len, i;
- int size, val = 0;
+ Py_ssize_t i;
PyObject *rv;
- if ( !PyArg_ParseTuple(args, "s#i:lin2ulaw",
- &cp, &len, &size) )
- return 0 ;
-
- if (!audioop_check_parameters(len, size))
+ if (!audioop_check_parameters(fragment->len, width))
return NULL;
- rv = PyBytes_FromStringAndSize(NULL, len/size);
- if ( rv == 0 )
- return 0;
+ rv = PyBytes_FromStringAndSize(NULL, fragment->len/width);
+ if (rv == NULL)
+ return NULL;
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;
-
- *ncp++ = st_14linear2ulaw(val);
+ for (i = 0; i < fragment->len; i += width) {
+ int val = GETSAMPLE32(width, fragment->buf, i);
+ *ncp++ = st_14linear2ulaw(val >> 18);
}
return rv;
}
+/*[clinic input]
+audioop.ulaw2lin
+
+ fragment: Py_buffer
+ width: int
+ /
+
+Convert sound fragments in u-LAW encoding to linearly encoded sound fragments.
+[clinic start generated code]*/
+
static PyObject *
-audioop_ulaw2lin(PyObject *self, PyObject *args)
+audioop_ulaw2lin_impl(PyModuleDef *module, Py_buffer *fragment, int width)
+/*[clinic end generated code: output=9864cb34e3a1d876 input=45d53ddce5be7d06]*/
{
unsigned char *cp;
- unsigned char cval;
signed char *ncp;
- Py_ssize_t len, i;
- int size, val;
+ Py_ssize_t i;
PyObject *rv;
- if ( !PyArg_ParseTuple(args, "s#i:ulaw2lin",
- &cp, &len, &size) )
- return 0;
-
- if (!audioop_check_size(size))
+ if (!audioop_check_size(width))
return NULL;
- if (len > PY_SSIZE_T_MAX/size) {
+ if (fragment->len > PY_SSIZE_T_MAX/width) {
PyErr_SetString(PyExc_MemoryError,
"not enough memory for output buffer");
- return 0;
+ return NULL;
}
- rv = PyBytes_FromStringAndSize(NULL, len*size);
- if ( rv == 0 )
- return 0;
+ rv = PyBytes_FromStringAndSize(NULL, fragment->len*width);
+ if (rv == NULL)
+ return NULL;
ncp = (signed char *)PyBytes_AsString(rv);
- for ( i=0; i < len*size; i += size ) {
- cval = *cp++;
- val = st_ulaw2linear16(cval);
-
- if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val >> 8);
- else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val);
- else if ( size == 4 ) *LONGP(ncp, i) = (Py_Int32)(val<<16);
+ cp = fragment->buf;
+ for (i = 0; i < fragment->len*width; i += width) {
+ int val = st_ulaw2linear16(*cp++) << 16;
+ SETSAMPLE32(width, ncp, i, val);
}
return rv;
}
+/*[clinic input]
+audioop.lin2alaw
+
+ fragment: Py_buffer
+ width: int
+ /
+
+Convert samples in the audio fragment to a-LAW encoding.
+[clinic start generated code]*/
+
static PyObject *
-audioop_lin2alaw(PyObject *self, PyObject *args)
+audioop_lin2alaw_impl(PyModuleDef *module, Py_buffer *fragment, int width)
+/*[clinic end generated code: output=d5bf14bd0fe6fdcd input=ffb1ef8bb39da945]*/
{
- signed char *cp;
unsigned char *ncp;
- Py_ssize_t len, i;
- int size, val = 0;
+ Py_ssize_t i;
PyObject *rv;
- if ( !PyArg_ParseTuple(args, "s#i:lin2alaw",
- &cp, &len, &size) )
- return 0;
-
- if (!audioop_check_parameters(len, size))
+ if (!audioop_check_parameters(fragment->len, width))
return NULL;
- rv = PyBytes_FromStringAndSize(NULL, len/size);
- if ( rv == 0 )
- return 0;
+ rv = PyBytes_FromStringAndSize(NULL, fragment->len/width);
+ if (rv == NULL)
+ return NULL;
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;
-
- *ncp++ = st_linear2alaw(val);
+ for (i = 0; i < fragment->len; i += width) {
+ int val = GETSAMPLE32(width, fragment->buf, i);
+ *ncp++ = st_linear2alaw(val >> 19);
}
return rv;
}
+/*[clinic input]
+audioop.alaw2lin
+
+ fragment: Py_buffer
+ width: int
+ /
+
+Convert sound fragments in a-LAW encoding to linearly encoded sound fragments.
+[clinic start generated code]*/
+
static PyObject *
-audioop_alaw2lin(PyObject *self, PyObject *args)
+audioop_alaw2lin_impl(PyModuleDef *module, Py_buffer *fragment, int width)
+/*[clinic end generated code: output=d2b604ddd036e1cd input=4140626046cd1772]*/
{
unsigned char *cp;
- unsigned char cval;
signed char *ncp;
- Py_ssize_t len, i;
- int size, val;
+ Py_ssize_t i;
+ int val;
PyObject *rv;
- if ( !PyArg_ParseTuple(args, "s#i:alaw2lin",
- &cp, &len, &size) )
- return 0;
-
- if (!audioop_check_size(size))
+ if (!audioop_check_size(width))
return NULL;
- if (len > PY_SSIZE_T_MAX/size) {
+ if (fragment->len > PY_SSIZE_T_MAX/width) {
PyErr_SetString(PyExc_MemoryError,
"not enough memory for output buffer");
- return 0;
+ return NULL;
}
- rv = PyBytes_FromStringAndSize(NULL, len*size);
- if ( rv == 0 )
- return 0;
+ rv = PyBytes_FromStringAndSize(NULL, fragment->len*width);
+ if (rv == NULL)
+ return NULL;
ncp = (signed char *)PyBytes_AsString(rv);
+ cp = fragment->buf;
- for ( i=0; i < len*size; i += size ) {
- cval = *cp++;
- val = st_alaw2linear16(cval);
-
- if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val >> 8);
- else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val);
- else if ( size == 4 ) *LONGP(ncp, i) = (Py_Int32)(val<<16);
+ for (i = 0; i < fragment->len*width; i += width) {
+ val = st_alaw2linear16(*cp++) << 16;
+ SETSAMPLE32(width, ncp, i, val);
}
return rv;
}
+/*[clinic input]
+audioop.lin2adpcm
+
+ fragment: Py_buffer
+ width: int
+ state: object
+ /
+
+Convert samples to 4 bit Intel/DVI ADPCM encoding.
+[clinic start generated code]*/
+
static PyObject *
-audioop_lin2adpcm(PyObject *self, PyObject *args)
+audioop_lin2adpcm_impl(PyModuleDef *module, Py_buffer *fragment, int width, PyObject *state)
+/*[clinic end generated code: output=4654c29d2731fafe input=12919d549b90c90a]*/
{
- signed char *cp;
signed char *ncp;
- Py_ssize_t len, i;
- int size, val = 0, step, valpred, delta,
+ Py_ssize_t i;
+ int step, valpred, delta,
index, sign, vpdiff, diff;
- PyObject *rv, *state, *str;
+ PyObject *rv = NULL, *str;
int outputbuffer = 0, bufferstep;
- if ( !PyArg_ParseTuple(args, "s#iO:lin2adpcm",
- &cp, &len, &size, &state) )
- return 0;
-
- if (!audioop_check_parameters(len, size))
+ if (!audioop_check_parameters(fragment->len, width))
return NULL;
- str = PyBytes_FromStringAndSize(NULL, len/(size*2));
- if ( str == 0 )
- return 0;
- ncp = (signed char *)PyBytes_AsString(str);
-
/* Decode state, should have (value, step) */
if ( state == Py_None ) {
/* First time, it seems. Set defaults */
valpred = 0;
index = 0;
- } else if ( !PyArg_ParseTuple(state, "ii", &valpred, &index) )
- return 0;
+ }
+ else if (!PyTuple_Check(state)) {
+ PyErr_SetString(PyExc_TypeError, "state must be a tuple or None");
+ return NULL;
+ }
+ else if (!PyArg_ParseTuple(state, "ii", &valpred, &index)) {
+ return NULL;
+ }
+ else if (valpred >= 0x8000 || valpred < -0x8000 ||
+ (size_t)index >= Py_ARRAY_LENGTH(stepsizeTable)) {
+ PyErr_SetString(PyExc_ValueError, "bad state");
+ return NULL;
+ }
+
+ str = PyBytes_FromStringAndSize(NULL, fragment->len/(width*2));
+ if (str == NULL)
+ return NULL;
+ ncp = (signed char *)PyBytes_AsString(str);
step = stepsizeTable[index];
bufferstep = 1;
- 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;
+ for (i = 0; i < fragment->len; i += width) {
+ int val = GETSAMPLE32(width, fragment->buf, i) >> 16;
/* Step 1 - compute difference with previous value */
- diff = val - valpred;
- sign = (diff < 0) ? 8 : 0;
- if ( sign ) diff = (-diff);
+ if (val < valpred) {
+ diff = valpred - val;
+ sign = 8;
+ }
+ else {
+ diff = val - valpred;
+ sign = 0;
+ }
/* Step 2 - Divide and clamp */
/* Note:
@@ -1511,21 +1717,29 @@ audioop_lin2adpcm(PyObject *self, PyObject *args)
return rv;
}
+/*[clinic input]
+audioop.adpcm2lin
+
+ fragment: Py_buffer
+ width: int
+ state: object
+ /
+
+Decode an Intel/DVI ADPCM coded fragment to a linear fragment.
+[clinic start generated code]*/
+
static PyObject *
-audioop_adpcm2lin(PyObject *self, PyObject *args)
+audioop_adpcm2lin_impl(PyModuleDef *module, Py_buffer *fragment, int width, PyObject *state)
+/*[clinic end generated code: output=371965cdcc0aa69b input=f5221144f5ca9ef0]*/
{
signed char *cp;
signed char *ncp;
- Py_ssize_t len, i;
- int size, valpred, step, delta, index, sign, vpdiff;
- PyObject *rv, *str, *state;
+ Py_ssize_t i, outlen;
+ int valpred, step, delta, index, sign, vpdiff;
+ PyObject *rv, *str;
int inputbuffer = 0, bufferstep;
- if ( !PyArg_ParseTuple(args, "s#iO:adpcm2lin",
- &cp, &len, &size, &state) )
- return 0;
-
- if (!audioop_check_size(size))
+ if (!audioop_check_size(width))
return NULL;
/* Decode state, should have (value, step) */
@@ -1533,23 +1747,36 @@ audioop_adpcm2lin(PyObject *self, PyObject *args)
/* First time, it seems. Set defaults */
valpred = 0;
index = 0;
- } else if ( !PyArg_ParseTuple(state, "ii", &valpred, &index) )
- return 0;
+ }
+ else if (!PyTuple_Check(state)) {
+ PyErr_SetString(PyExc_TypeError, "state must be a tuple or None");
+ return NULL;
+ }
+ else if (!PyArg_ParseTuple(state, "ii", &valpred, &index)) {
+ return NULL;
+ }
+ else if (valpred >= 0x8000 || valpred < -0x8000 ||
+ (size_t)index >= Py_ARRAY_LENGTH(stepsizeTable)) {
+ PyErr_SetString(PyExc_ValueError, "bad state");
+ return NULL;
+ }
- if (len > (PY_SSIZE_T_MAX/2)/size) {
+ if (fragment->len > (PY_SSIZE_T_MAX/2)/width) {
PyErr_SetString(PyExc_MemoryError,
"not enough memory for output buffer");
- return 0;
+ return NULL;
}
- str = PyBytes_FromStringAndSize(NULL, len*size*2);
- if ( str == 0 )
- return 0;
+ outlen = fragment->len*width*2;
+ str = PyBytes_FromStringAndSize(NULL, outlen);
+ if (str == NULL)
+ return NULL;
ncp = (signed char *)PyBytes_AsString(str);
+ cp = fragment->buf;
step = stepsizeTable[index];
bufferstep = 0;
- for ( i=0; i < len*size*2; i += size ) {
+ for (i = 0; i < outlen; i += width) {
/* Step 1 - get the delta value and compute next index */
if ( bufferstep ) {
delta = inputbuffer & 0xf;
@@ -1594,9 +1821,7 @@ audioop_adpcm2lin(PyObject *self, PyObject *args)
step = stepsizeTable[index];
/* Step 6 - Output value */
- if ( size == 1 ) *CHARP(ncp, i) = (signed char)(valpred >> 8);
- else if ( size == 2 ) *SHORTP(ncp, i) = (short)(valpred);
- else if ( size == 4 ) *LONGP(ncp, i) = (Py_Int32)(valpred<<16);
+ SETSAMPLE32(width, ncp, i, valpred << 16);
}
rv = Py_BuildValue("(O(ii))", str, valpred, index);
@@ -1604,32 +1829,35 @@ audioop_adpcm2lin(PyObject *self, PyObject *args)
return rv;
}
+#include "clinic/audioop.c.h"
+
static PyMethodDef audioop_methods[] = {
- { "max", audioop_max, METH_VARARGS },
- { "minmax", audioop_minmax, METH_VARARGS },
- { "avg", audioop_avg, METH_VARARGS },
- { "maxpp", audioop_maxpp, METH_VARARGS },
- { "avgpp", audioop_avgpp, METH_VARARGS },
- { "rms", audioop_rms, METH_VARARGS },
- { "findfit", audioop_findfit, METH_VARARGS },
- { "findmax", audioop_findmax, METH_VARARGS },
- { "findfactor", audioop_findfactor, METH_VARARGS },
- { "cross", audioop_cross, METH_VARARGS },
- { "mul", audioop_mul, METH_VARARGS },
- { "add", audioop_add, METH_VARARGS },
- { "bias", audioop_bias, METH_VARARGS },
- { "ulaw2lin", audioop_ulaw2lin, METH_VARARGS },
- { "lin2ulaw", audioop_lin2ulaw, METH_VARARGS },
- { "alaw2lin", audioop_alaw2lin, METH_VARARGS },
- { "lin2alaw", audioop_lin2alaw, METH_VARARGS },
- { "lin2lin", audioop_lin2lin, METH_VARARGS },
- { "adpcm2lin", audioop_adpcm2lin, METH_VARARGS },
- { "lin2adpcm", audioop_lin2adpcm, METH_VARARGS },
- { "tomono", audioop_tomono, METH_VARARGS },
- { "tostereo", audioop_tostereo, METH_VARARGS },
- { "getsample", audioop_getsample, METH_VARARGS },
- { "reverse", audioop_reverse, METH_VARARGS },
- { "ratecv", audioop_ratecv, METH_VARARGS },
+ AUDIOOP_MAX_METHODDEF
+ AUDIOOP_MINMAX_METHODDEF
+ AUDIOOP_AVG_METHODDEF
+ AUDIOOP_MAXPP_METHODDEF
+ AUDIOOP_AVGPP_METHODDEF
+ AUDIOOP_RMS_METHODDEF
+ AUDIOOP_FINDFIT_METHODDEF
+ AUDIOOP_FINDMAX_METHODDEF
+ AUDIOOP_FINDFACTOR_METHODDEF
+ AUDIOOP_CROSS_METHODDEF
+ AUDIOOP_MUL_METHODDEF
+ AUDIOOP_ADD_METHODDEF
+ AUDIOOP_BIAS_METHODDEF
+ AUDIOOP_ULAW2LIN_METHODDEF
+ AUDIOOP_LIN2ULAW_METHODDEF
+ AUDIOOP_ALAW2LIN_METHODDEF
+ AUDIOOP_LIN2ALAW_METHODDEF
+ AUDIOOP_LIN2LIN_METHODDEF
+ AUDIOOP_ADPCM2LIN_METHODDEF
+ AUDIOOP_LIN2ADPCM_METHODDEF
+ AUDIOOP_TOMONO_METHODDEF
+ AUDIOOP_TOSTEREO_METHODDEF
+ AUDIOOP_GETSAMPLE_METHODDEF
+ AUDIOOP_REVERSE_METHODDEF
+ AUDIOOP_BYTESWAP_METHODDEF
+ AUDIOOP_RATECV_METHODDEF
{ 0, 0 }
};