blob: 5c83a7d6b0abec40b9b99ce35e265af0a9e08e09 [file] [log] [blame]
Guido van Rossumb66efa01992-06-01 16:01:24 +00001
Guido van Rossumb6775db1994-08-01 11:34:53 +00002/* audioopmodule - Module to detect peak values in arrays */
Jack Jansene1b4d7c1992-08-24 14:36:31 +00003
Mark Dickinson81fece22010-05-11 13:34:35 +00004#define PY_SSIZE_T_CLEAN
5
Roger E. Masseeaa6e111997-01-03 19:26:27 +00006#include "Python.h"
Guido van Rossumb66efa01992-06-01 16:01:24 +00007
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00008typedef short PyInt16;
9
Guido van Rossum7b1e9741994-08-29 10:46:42 +000010#if defined(__CHAR_UNSIGNED__)
11#if defined(signed)
Guido van Rossumb6775db1994-08-01 11:34:53 +000012/* This module currently does not work on systems where only unsigned
13 characters are available. Take it out of Setup. Sorry. */
14#endif
Guido van Rossum7b1e9741994-08-29 10:46:42 +000015#endif
Guido van Rossumb6775db1994-08-01 11:34:53 +000016
Serhiy Storchaka01ad6222013-02-09 11:10:53 +020017static const int maxvals[] = {0, 0x7F, 0x7FFF, 0x7FFFFF, 0x7FFFFFFF};
Tim Goldenfa6ab0f2013-10-31 10:25:47 +000018/* -1 trick is needed on Windows to support -0x80000000 without a warning */
19static const int minvals[] = {0, -0x80, -0x8000, -0x800000, -0x7FFFFFFF-1};
Serhiy Storchaka01ad6222013-02-09 11:10:53 +020020static const unsigned int masks[] = {0, 0xFF, 0xFFFF, 0xFFFFFF, 0xFFFFFFFF};
21
22static int
23fbound(double val, double minval, double maxval)
24{
25 if (val > maxval)
26 val = maxval;
27 else if (val < minval + 1)
28 val = minval;
Victor Stinnerf2b9a342013-05-07 23:49:15 +020029 return (int)val;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +020030}
31
32
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000033/* Code shamelessly stolen from sox, 12.17.7, g711.c
Guido van Rossumb66efa01992-06-01 16:01:24 +000034** (c) Craig Reese, Joe Campbell and Jeff Poskanzer 1989 */
35
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000036/* From g711.c:
37 *
38 * December 30, 1994:
39 * Functions linear2alaw, linear2ulaw have been updated to correctly
40 * convert unquantized 16 bit values.
41 * Tables for direct u- to A-law and A- to u-law conversions have been
42 * corrected.
43 * Borge Lindberg, Center for PersonKommunikation, Aalborg University.
44 * bli@cpk.auc.dk
45 *
46 */
Guido van Rossumb66efa01992-06-01 16:01:24 +000047#define BIAS 0x84 /* define the add-in bias for 16 bit samples */
48#define CLIP 32635
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000049#define SIGN_BIT (0x80) /* Sign bit for a A-law byte. */
50#define QUANT_MASK (0xf) /* Quantization field mask. */
51#define SEG_SHIFT (4) /* Left shift for segment number. */
52#define SEG_MASK (0x70) /* Segment field mask. */
Guido van Rossumb66efa01992-06-01 16:01:24 +000053
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000054static PyInt16 seg_aend[8] = {0x1F, 0x3F, 0x7F, 0xFF,
55 0x1FF, 0x3FF, 0x7FF, 0xFFF};
56static PyInt16 seg_uend[8] = {0x3F, 0x7F, 0xFF, 0x1FF,
57 0x3FF, 0x7FF, 0xFFF, 0x1FFF};
58
59static PyInt16
60search(PyInt16 val, PyInt16 *table, int size)
Roger E. Masseeaa6e111997-01-03 19:26:27 +000061{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000062 int i;
Guido van Rossumb66efa01992-06-01 16:01:24 +000063
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000064 for (i = 0; i < size; i++) {
65 if (val <= *table++)
66 return (i);
67 }
68 return (size);
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000069}
70#define st_ulaw2linear16(uc) (_st_ulaw2linear16[uc])
71#define st_alaw2linear16(uc) (_st_alaw2linear16[uc])
Guido van Rossumb66efa01992-06-01 16:01:24 +000072
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000073static PyInt16 _st_ulaw2linear16[256] = {
74 -32124, -31100, -30076, -29052, -28028, -27004, -25980,
75 -24956, -23932, -22908, -21884, -20860, -19836, -18812,
76 -17788, -16764, -15996, -15484, -14972, -14460, -13948,
77 -13436, -12924, -12412, -11900, -11388, -10876, -10364,
78 -9852, -9340, -8828, -8316, -7932, -7676, -7420,
79 -7164, -6908, -6652, -6396, -6140, -5884, -5628,
80 -5372, -5116, -4860, -4604, -4348, -4092, -3900,
81 -3772, -3644, -3516, -3388, -3260, -3132, -3004,
82 -2876, -2748, -2620, -2492, -2364, -2236, -2108,
83 -1980, -1884, -1820, -1756, -1692, -1628, -1564,
84 -1500, -1436, -1372, -1308, -1244, -1180, -1116,
85 -1052, -988, -924, -876, -844, -812, -780,
86 -748, -716, -684, -652, -620, -588, -556,
87 -524, -492, -460, -428, -396, -372, -356,
88 -340, -324, -308, -292, -276, -260, -244,
89 -228, -212, -196, -180, -164, -148, -132,
90 -120, -112, -104, -96, -88, -80, -72,
91 -64, -56, -48, -40, -32, -24, -16,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000092 -8, 0, 32124, 31100, 30076, 29052, 28028,
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000093 27004, 25980, 24956, 23932, 22908, 21884, 20860,
94 19836, 18812, 17788, 16764, 15996, 15484, 14972,
95 14460, 13948, 13436, 12924, 12412, 11900, 11388,
96 10876, 10364, 9852, 9340, 8828, 8316, 7932,
97 7676, 7420, 7164, 6908, 6652, 6396, 6140,
98 5884, 5628, 5372, 5116, 4860, 4604, 4348,
99 4092, 3900, 3772, 3644, 3516, 3388, 3260,
100 3132, 3004, 2876, 2748, 2620, 2492, 2364,
101 2236, 2108, 1980, 1884, 1820, 1756, 1692,
102 1628, 1564, 1500, 1436, 1372, 1308, 1244,
103 1180, 1116, 1052, 988, 924, 876, 844,
104 812, 780, 748, 716, 684, 652, 620,
105 588, 556, 524, 492, 460, 428, 396,
106 372, 356, 340, 324, 308, 292, 276,
107 260, 244, 228, 212, 196, 180, 164,
108 148, 132, 120, 112, 104, 96, 88,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000109 80, 72, 64, 56, 48, 40, 32,
110 24, 16, 8, 0
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000111};
Guido van Rossumb66efa01992-06-01 16:01:24 +0000112
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000113/*
114 * linear2ulaw() accepts a 14-bit signed integer and encodes it as u-law data
115 * stored in a unsigned char. This function should only be called with
116 * the data shifted such that it only contains information in the lower
117 * 14-bits.
118 *
119 * In order to simplify the encoding process, the original linear magnitude
120 * is biased by adding 33 which shifts the encoding range from (0 - 8158) to
121 * (33 - 8191). The result can be seen in the following encoding table:
122 *
123 * Biased Linear Input Code Compressed Code
124 * ------------------------ ---------------
125 * 00000001wxyza 000wxyz
126 * 0000001wxyzab 001wxyz
127 * 000001wxyzabc 010wxyz
128 * 00001wxyzabcd 011wxyz
129 * 0001wxyzabcde 100wxyz
130 * 001wxyzabcdef 101wxyz
131 * 01wxyzabcdefg 110wxyz
132 * 1wxyzabcdefgh 111wxyz
133 *
134 * Each biased linear code has a leading 1 which identifies the segment
135 * number. The value of the segment number is equal to 7 minus the number
136 * of leading 0's. The quantization interval is directly available as the
137 * four bits wxyz. * The trailing bits (a - h) are ignored.
138 *
139 * Ordinarily the complement of the resulting code word is used for
140 * transmission, and so the code word is complemented before it is returned.
141 *
142 * For further information see John C. Bellamy's Digital Telephony, 1982,
143 * John Wiley & Sons, pps 98-111 and 472-476.
144 */
145static unsigned char
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000146st_14linear2ulaw(PyInt16 pcm_val) /* 2's complement (14-bit range) */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000147{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000148 PyInt16 mask;
149 PyInt16 seg;
150 unsigned char uval;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000151
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000152 /* u-law inverts all bits */
153 /* Get the sign and the magnitude of the value. */
154 if (pcm_val < 0) {
155 pcm_val = -pcm_val;
156 mask = 0x7F;
157 } else {
158 mask = 0xFF;
159 }
160 if ( pcm_val > CLIP ) pcm_val = CLIP; /* clip the magnitude */
161 pcm_val += (BIAS >> 2);
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000162
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000163 /* Convert the scaled magnitude to segment number. */
164 seg = search(pcm_val, seg_uend, 8);
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000165
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000166 /*
167 * Combine the sign, segment, quantization bits;
168 * and complement the code word.
169 */
170 if (seg >= 8) /* out of range, return maximum value. */
171 return (unsigned char) (0x7F ^ mask);
172 else {
173 uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF);
174 return (uval ^ mask);
175 }
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000176
177}
178
179static PyInt16 _st_alaw2linear16[256] = {
180 -5504, -5248, -6016, -5760, -4480, -4224, -4992,
181 -4736, -7552, -7296, -8064, -7808, -6528, -6272,
182 -7040, -6784, -2752, -2624, -3008, -2880, -2240,
183 -2112, -2496, -2368, -3776, -3648, -4032, -3904,
184 -3264, -3136, -3520, -3392, -22016, -20992, -24064,
185 -23040, -17920, -16896, -19968, -18944, -30208, -29184,
186 -32256, -31232, -26112, -25088, -28160, -27136, -11008,
187 -10496, -12032, -11520, -8960, -8448, -9984, -9472,
188 -15104, -14592, -16128, -15616, -13056, -12544, -14080,
189 -13568, -344, -328, -376, -360, -280, -264,
190 -312, -296, -472, -456, -504, -488, -408,
191 -392, -440, -424, -88, -72, -120, -104,
192 -24, -8, -56, -40, -216, -200, -248,
193 -232, -152, -136, -184, -168, -1376, -1312,
194 -1504, -1440, -1120, -1056, -1248, -1184, -1888,
195 -1824, -2016, -1952, -1632, -1568, -1760, -1696,
196 -688, -656, -752, -720, -560, -528, -624,
197 -592, -944, -912, -1008, -976, -816, -784,
198 -880, -848, 5504, 5248, 6016, 5760, 4480,
199 4224, 4992, 4736, 7552, 7296, 8064, 7808,
200 6528, 6272, 7040, 6784, 2752, 2624, 3008,
201 2880, 2240, 2112, 2496, 2368, 3776, 3648,
202 4032, 3904, 3264, 3136, 3520, 3392, 22016,
203 20992, 24064, 23040, 17920, 16896, 19968, 18944,
204 30208, 29184, 32256, 31232, 26112, 25088, 28160,
205 27136, 11008, 10496, 12032, 11520, 8960, 8448,
206 9984, 9472, 15104, 14592, 16128, 15616, 13056,
207 12544, 14080, 13568, 344, 328, 376, 360,
208 280, 264, 312, 296, 472, 456, 504,
209 488, 408, 392, 440, 424, 88, 72,
210 120, 104, 24, 8, 56, 40, 216,
211 200, 248, 232, 152, 136, 184, 168,
212 1376, 1312, 1504, 1440, 1120, 1056, 1248,
213 1184, 1888, 1824, 2016, 1952, 1632, 1568,
214 1760, 1696, 688, 656, 752, 720, 560,
215 528, 624, 592, 944, 912, 1008, 976,
216 816, 784, 880, 848
217};
218
219/*
220 * linear2alaw() accepts an 13-bit signed integer and encodes it as A-law data
221 * stored in a unsigned char. This function should only be called with
222 * the data shifted such that it only contains information in the lower
223 * 13-bits.
224 *
225 * Linear Input Code Compressed Code
226 * ------------------------ ---------------
227 * 0000000wxyza 000wxyz
228 * 0000001wxyza 001wxyz
229 * 000001wxyzab 010wxyz
230 * 00001wxyzabc 011wxyz
231 * 0001wxyzabcd 100wxyz
232 * 001wxyzabcde 101wxyz
233 * 01wxyzabcdef 110wxyz
234 * 1wxyzabcdefg 111wxyz
235 *
236 * For further information see John C. Bellamy's Digital Telephony, 1982,
237 * John Wiley & Sons, pps 98-111 and 472-476.
238 */
239static unsigned char
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000240st_linear2alaw(PyInt16 pcm_val) /* 2's complement (13-bit range) */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000241{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000242 PyInt16 mask;
243 short seg;
244 unsigned char aval;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000245
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000246 /* A-law using even bit inversion */
247 if (pcm_val >= 0) {
248 mask = 0xD5; /* sign (7th) bit = 1 */
249 } else {
250 mask = 0x55; /* sign bit = 0 */
251 pcm_val = -pcm_val - 1;
252 }
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000253
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000254 /* Convert the scaled magnitude to segment number. */
255 seg = search(pcm_val, seg_aend, 8);
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000256
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000257 /* Combine the sign, segment, and quantization bits. */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000258
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000259 if (seg >= 8) /* out of range, return maximum value. */
260 return (unsigned char) (0x7F ^ mask);
261 else {
262 aval = (unsigned char) seg << SEG_SHIFT;
263 if (seg < 2)
264 aval |= (pcm_val >> 1) & QUANT_MASK;
265 else
266 aval |= (pcm_val >> seg) & QUANT_MASK;
267 return (aval ^ mask);
268 }
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000269}
Guido van Rossumb66efa01992-06-01 16:01:24 +0000270/* End of code taken from sox */
271
Guido van Rossumb64e6351992-07-06 14:21:56 +0000272/* Intel ADPCM step variation table */
273static int indexTable[16] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000274 -1, -1, -1, -1, 2, 4, 6, 8,
275 -1, -1, -1, -1, 2, 4, 6, 8,
Guido van Rossumb64e6351992-07-06 14:21:56 +0000276};
277
278static int stepsizeTable[89] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000279 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
280 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
281 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
282 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
283 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
284 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
285 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
286 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
287 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
Guido van Rossumb64e6351992-07-06 14:21:56 +0000288};
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000289
Serhiy Storchaka23a78272013-11-11 07:47:35 +0200290#define GETINTX(T, cp, i) (*(T *)((unsigned char *)(cp) + (i)))
291#define SETINTX(T, cp, i, val) do { \
292 *(T *)((unsigned char *)(cp) + (i)) = (T)(val); \
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300293 } while (0)
Guido van Rossumb66efa01992-06-01 16:01:24 +0000294
295
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300296#define GETINT8(cp, i) GETINTX(signed char, (cp), (i))
297#define GETINT16(cp, i) GETINTX(short, (cp), (i))
298#define GETINT32(cp, i) GETINTX(PY_INT32_T, (cp), (i))
299
300#if WORDS_BIGENDIAN
301#define GETINT24(cp, i) ( \
302 ((unsigned char *)(cp) + (i))[2] + \
303 (((unsigned char *)(cp) + (i))[1] << 8) + \
304 (((signed char *)(cp) + (i))[0] << 16) )
305#else
306#define GETINT24(cp, i) ( \
307 ((unsigned char *)(cp) + (i))[0] + \
308 (((unsigned char *)(cp) + (i))[1] << 8) + \
309 (((signed char *)(cp) + (i))[2] << 16) )
310#endif
311
312
313#define SETINT8(cp, i, val) SETINTX(signed char, (cp), (i), (val))
314#define SETINT16(cp, i, val) SETINTX(short, (cp), (i), (val))
315#define SETINT32(cp, i, val) SETINTX(PY_INT32_T, (cp), (i), (val))
316
317#if WORDS_BIGENDIAN
318#define SETINT24(cp, i, val) do { \
319 ((unsigned char *)(cp) + (i))[2] = (int)(val); \
320 ((unsigned char *)(cp) + (i))[1] = (int)(val) >> 8; \
321 ((signed char *)(cp) + (i))[0] = (int)(val) >> 16; \
322 } while (0)
323#else
324#define SETINT24(cp, i, val) do { \
325 ((unsigned char *)(cp) + (i))[0] = (int)(val); \
326 ((unsigned char *)(cp) + (i))[1] = (int)(val) >> 8; \
327 ((signed char *)(cp) + (i))[2] = (int)(val) >> 16; \
328 } while (0)
329#endif
330
331
332#define GETRAWSAMPLE(size, cp, i) ( \
333 (size == 1) ? (int)GETINT8((cp), (i)) : \
334 (size == 2) ? (int)GETINT16((cp), (i)) : \
335 (size == 3) ? (int)GETINT24((cp), (i)) : \
336 (int)GETINT32((cp), (i)))
337
338#define SETRAWSAMPLE(size, cp, i, val) do { \
339 if (size == 1) \
340 SETINT8((cp), (i), (val)); \
341 else if (size == 2) \
342 SETINT16((cp), (i), (val)); \
343 else if (size == 3) \
344 SETINT24((cp), (i), (val)); \
345 else \
346 SETINT32((cp), (i), (val)); \
347 } while(0)
348
349
350#define GETSAMPLE32(size, cp, i) ( \
351 (size == 1) ? (int)GETINT8((cp), (i)) << 24 : \
352 (size == 2) ? (int)GETINT16((cp), (i)) << 16 : \
353 (size == 3) ? (int)GETINT24((cp), (i)) << 8 : \
354 (int)GETINT32((cp), (i)))
355
356#define SETSAMPLE32(size, cp, i, val) do { \
357 if (size == 1) \
358 SETINT8((cp), (i), (val) >> 24); \
359 else if (size == 2) \
360 SETINT16((cp), (i), (val) >> 16); \
361 else if (size == 3) \
362 SETINT24((cp), (i), (val) >> 8); \
363 else \
364 SETINT32((cp), (i), (val)); \
365 } while(0)
366
Guido van Rossumb66efa01992-06-01 16:01:24 +0000367
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000368static PyObject *AudioopError;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000369
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000370static int
371audioop_check_size(int size)
372{
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300373 if (size < 1 || size > 4) {
374 PyErr_SetString(AudioopError, "Size should be 1, 2, 3 or 4");
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000375 return 0;
376 }
377 else
378 return 1;
379}
380
381static int
Victor Stinner0fcab4a2011-01-04 12:59:15 +0000382audioop_check_parameters(Py_ssize_t len, int size)
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000383{
384 if (!audioop_check_size(size))
385 return 0;
386 if (len % size != 0) {
387 PyErr_SetString(AudioopError, "not a whole number of frames");
388 return 0;
389 }
390 return 1;
391}
392
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000393static PyObject *
Peter Schneider-Kamp8bc8f0d2000-07-10 17:15:07 +0000394audioop_getsample(PyObject *self, PyObject *args)
Guido van Rossumb66efa01992-06-01 16:01:24 +0000395{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200396 Py_buffer view;
397 Py_ssize_t i;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300398 int size;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200399 int val;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000400
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200401 if (!PyArg_ParseTuple(args, "y*in:getsample", &view, &size, &i))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000402 return NULL;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200403 if (!audioop_check_parameters(view.len, size))
404 goto error;
405 if (i < 0 || i >= view.len/size) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000406 PyErr_SetString(AudioopError, "Index out of range");
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200407 goto error;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000408 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200409 val = GETRAWSAMPLE(size, view.buf, i*size);
410 PyBuffer_Release(&view);
411 return PyLong_FromLong(val);
412
413 error:
414 PyBuffer_Release(&view);
415 return NULL;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000416}
417
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000418static PyObject *
Peter Schneider-Kamp8bc8f0d2000-07-10 17:15:07 +0000419audioop_max(PyObject *self, PyObject *args)
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000420{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200421 Py_buffer view;
422 Py_ssize_t i;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300423 int size;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200424 unsigned int absval, max = 0;
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000425
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200426 if (!PyArg_ParseTuple(args, "y*i:max", &view, &size))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000427 return NULL;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200428 if (!audioop_check_parameters(view.len, size)) {
429 PyBuffer_Release(&view);
430 return NULL;
431 }
432 for (i = 0; i < view.len; i += size) {
433 int val = GETRAWSAMPLE(size, view.buf, i);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200434 if (val < 0) absval = (-val);
435 else absval = val;
436 if (absval > max) max = absval;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000437 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200438 PyBuffer_Release(&view);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200439 return PyLong_FromUnsignedLong(max);
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000440}
441
442static PyObject *
Peter Schneider-Kamp8bc8f0d2000-07-10 17:15:07 +0000443audioop_minmax(PyObject *self, PyObject *args)
Sjoerd Mullendera1426131994-09-06 16:19:33 +0000444{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200445 Py_buffer view;
446 Py_ssize_t i;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300447 int size;
Tim Goldenfa6ab0f2013-10-31 10:25:47 +0000448 /* -1 trick below is needed on Windows to support -0x80000000 without
449 a warning */
450 int min = 0x7fffffff, max = -0x7FFFFFFF-1;
Sjoerd Mullendera1426131994-09-06 16:19:33 +0000451
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200452 if (!PyArg_ParseTuple(args, "y*i:minmax", &view, &size))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000453 return NULL;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200454 if (!audioop_check_parameters(view.len, size)) {
455 PyBuffer_Release(&view);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000456 return NULL;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200457 }
458 for (i = 0; i < view.len; i += size) {
459 int val = GETRAWSAMPLE(size, view.buf, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000460 if (val > max) max = val;
461 if (val < min) min = val;
462 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200463 PyBuffer_Release(&view);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000464 return Py_BuildValue("(ii)", min, max);
Sjoerd Mullendera1426131994-09-06 16:19:33 +0000465}
466
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000467static PyObject *
Peter Schneider-Kamp8bc8f0d2000-07-10 17:15:07 +0000468audioop_avg(PyObject *self, PyObject *args)
Guido van Rossumb66efa01992-06-01 16:01:24 +0000469{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200470 Py_buffer view;
471 Py_ssize_t i;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300472 int size, avg;
473 double sum = 0.0;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000474
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200475 if (!PyArg_ParseTuple(args, "y*i:avg", &view, &size))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000476 return NULL;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200477 if (!audioop_check_parameters(view.len, size)) {
478 PyBuffer_Release(&view);
479 return NULL;
480 }
481 for (i = 0; i < view.len; i += size)
482 sum += GETRAWSAMPLE(size, view.buf, i);
483 if (view.len == 0)
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300484 avg = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000485 else
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200486 avg = (int)floor(sum / (double)(view.len/size));
487 PyBuffer_Release(&view);
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300488 return PyLong_FromLong(avg);
Guido van Rossumb66efa01992-06-01 16:01:24 +0000489}
490
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000491static PyObject *
Peter Schneider-Kamp8bc8f0d2000-07-10 17:15:07 +0000492audioop_rms(PyObject *self, PyObject *args)
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000493{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200494 Py_buffer view;
495 Py_ssize_t i;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300496 int size;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200497 unsigned int res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000498 double sum_squares = 0.0;
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000499
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200500 if (!PyArg_ParseTuple(args, "y*i:rms", &view, &size))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000501 return NULL;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200502 if (!audioop_check_parameters(view.len, size)) {
503 PyBuffer_Release(&view);
504 return NULL;
505 }
506 for (i = 0; i < view.len; i += size) {
507 double val = GETRAWSAMPLE(size, view.buf, i);
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300508 sum_squares += val*val;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000509 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200510 if (view.len == 0)
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200511 res = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000512 else
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200513 res = (unsigned int)sqrt(sum_squares / (double)(view.len/size));
514 PyBuffer_Release(&view);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200515 return PyLong_FromUnsignedLong(res);
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000516}
517
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200518static double _sum2(const short *a, const short *b, Py_ssize_t len)
Jack Jansena90805f1993-02-17 14:29:28 +0000519{
Mark Dickinson81fece22010-05-11 13:34:35 +0000520 Py_ssize_t i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000521 double sum = 0.0;
Jack Jansena90805f1993-02-17 14:29:28 +0000522
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000523 for( i=0; i<len; i++) {
524 sum = sum + (double)a[i]*(double)b[i];
525 }
526 return sum;
Jack Jansena90805f1993-02-17 14:29:28 +0000527}
528
529/*
530** Findfit tries to locate a sample within another sample. Its main use
531** is in echo-cancellation (to find the feedback of the output signal in
532** the input signal).
533** The method used is as follows:
534**
535** let R be the reference signal (length n) and A the input signal (length N)
536** with N > n, and let all sums be over i from 0 to n-1.
537**
538** Now, for each j in {0..N-n} we compute a factor fj so that -fj*R matches A
539** as good as possible, i.e. sum( (A[j+i]+fj*R[i])^2 ) is minimal. This
540** equation gives fj = sum( A[j+i]R[i] ) / sum(R[i]^2).
541**
542** Next, we compute the relative distance between the original signal and
543** the modified signal and minimize that over j:
544** vj = sum( (A[j+i]-fj*R[i])^2 ) / sum( A[j+i]^2 ) =>
545** vj = ( sum(A[j+i]^2)*sum(R[i]^2) - sum(A[j+i]R[i])^2 ) / sum( A[j+i]^2 )
546**
547** In the code variables correspond as follows:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000548** cp1 A
549** cp2 R
550** len1 N
551** len2 n
552** aj_m1 A[j-1]
553** aj_lm1 A[j+n-1]
554** sum_ri_2 sum(R[i]^2)
555** sum_aij_2 sum(A[i+j]^2)
556** sum_aij_ri sum(A[i+j]R[i])
Jack Jansena90805f1993-02-17 14:29:28 +0000557**
558** sum_ri is calculated once, sum_aij_2 is updated each step and sum_aij_ri
559** is completely recalculated each step.
560*/
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000561static PyObject *
Peter Schneider-Kamp8bc8f0d2000-07-10 17:15:07 +0000562audioop_findfit(PyObject *self, PyObject *args)
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000563{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200564 Py_buffer view1;
565 Py_buffer view2;
566 const short *cp1, *cp2;
Mark Dickinson81fece22010-05-11 13:34:35 +0000567 Py_ssize_t len1, len2;
568 Py_ssize_t j, best_j;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000569 double aj_m1, aj_lm1;
570 double sum_ri_2, sum_aij_2, sum_aij_ri, result, best_result, factor;
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000571
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200572 if (!PyArg_ParseTuple(args, "y*y*:findfit", &view1, &view2))
573 return NULL;
574 if (view1.len & 1 || view2.len & 1) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000575 PyErr_SetString(AudioopError, "Strings should be even-sized");
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200576 goto error;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000577 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200578 cp1 = (const short *)view1.buf;
579 len1 = view1.len >> 1;
580 cp2 = (const short *)view2.buf;
581 len2 = view2.len >> 1;
Jack Jansena90805f1993-02-17 14:29:28 +0000582
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200583 if (len1 < len2) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000584 PyErr_SetString(AudioopError, "First sample should be longer");
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200585 goto error;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000586 }
587 sum_ri_2 = _sum2(cp2, cp2, len2);
588 sum_aij_2 = _sum2(cp1, cp1, len2);
589 sum_aij_ri = _sum2(cp1, cp2, len2);
Jack Jansena90805f1993-02-17 14:29:28 +0000590
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000591 result = (sum_ri_2*sum_aij_2 - sum_aij_ri*sum_aij_ri) / sum_aij_2;
Jack Jansena90805f1993-02-17 14:29:28 +0000592
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000593 best_result = result;
594 best_j = 0;
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000595
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000596 for ( j=1; j<=len1-len2; j++) {
597 aj_m1 = (double)cp1[j-1];
598 aj_lm1 = (double)cp1[j+len2-1];
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000599
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000600 sum_aij_2 = sum_aij_2 + aj_lm1*aj_lm1 - aj_m1*aj_m1;
601 sum_aij_ri = _sum2(cp1+j, cp2, len2);
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000602
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000603 result = (sum_ri_2*sum_aij_2 - sum_aij_ri*sum_aij_ri)
604 / sum_aij_2;
605
606 if ( result < best_result ) {
607 best_result = result;
608 best_j = j;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000609 }
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000610
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000611 }
612
613 factor = _sum2(cp1+best_j, cp2, len2) / sum_ri_2;
614
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200615 PyBuffer_Release(&view1);
616 PyBuffer_Release(&view2);
Mark Dickinson81fece22010-05-11 13:34:35 +0000617 return Py_BuildValue("(nf)", best_j, factor);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200618
619 error:
620 PyBuffer_Release(&view1);
621 PyBuffer_Release(&view2);
622 return NULL;
Jack Jansena90805f1993-02-17 14:29:28 +0000623}
624
625/*
626** findfactor finds a factor f so that the energy in A-fB is minimal.
627** See the comment for findfit for details.
628*/
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000629static PyObject *
Peter Schneider-Kamp8bc8f0d2000-07-10 17:15:07 +0000630audioop_findfactor(PyObject *self, PyObject *args)
Jack Jansena90805f1993-02-17 14:29:28 +0000631{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200632 Py_buffer view1;
633 Py_buffer view2;
634 const short *cp1, *cp2;
635 Py_ssize_t len;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000636 double sum_ri_2, sum_aij_ri, result;
Jack Jansena90805f1993-02-17 14:29:28 +0000637
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200638 if (!PyArg_ParseTuple(args, "y*y*:findfactor", &view1, &view2))
639 return NULL;
640 if (view1.len & 1 || view2.len & 1) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000641 PyErr_SetString(AudioopError, "Strings should be even-sized");
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200642 goto error;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000643 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200644 if (view1.len != view2.len) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000645 PyErr_SetString(AudioopError, "Samples should be same size");
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200646 goto error;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000647 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200648 cp1 = (const short *)view1.buf;
649 cp2 = (const short *)view2.buf;
650 len = view1.len >> 1;
651 sum_ri_2 = _sum2(cp2, cp2, len);
652 sum_aij_ri = _sum2(cp1, cp2, len);
Jack Jansena90805f1993-02-17 14:29:28 +0000653
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000654 result = sum_aij_ri / sum_ri_2;
Jack Jansena90805f1993-02-17 14:29:28 +0000655
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200656 PyBuffer_Release(&view1);
657 PyBuffer_Release(&view2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000658 return PyFloat_FromDouble(result);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200659
660 error:
661 PyBuffer_Release(&view1);
662 PyBuffer_Release(&view2);
663 return NULL;
Jack Jansena90805f1993-02-17 14:29:28 +0000664}
665
666/*
667** findmax returns the index of the n-sized segment of the input sample
668** that contains the most energy.
669*/
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000670static PyObject *
Peter Schneider-Kamp8bc8f0d2000-07-10 17:15:07 +0000671audioop_findmax(PyObject *self, PyObject *args)
Jack Jansena90805f1993-02-17 14:29:28 +0000672{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200673 Py_buffer view;
674 const short *cp1;
Mark Dickinson81fece22010-05-11 13:34:35 +0000675 Py_ssize_t len1, len2;
676 Py_ssize_t j, best_j;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000677 double aj_m1, aj_lm1;
678 double result, best_result;
Jack Jansena90805f1993-02-17 14:29:28 +0000679
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200680 if (!PyArg_ParseTuple(args, "y*n:findmax", &view, &len2))
681 return NULL;
682 if (view.len & 1) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000683 PyErr_SetString(AudioopError, "Strings should be even-sized");
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200684 goto error;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000685 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200686 cp1 = (const short *)view.buf;
687 len1 = view.len >> 1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000688
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200689 if (len2 < 0 || len1 < len2) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000690 PyErr_SetString(AudioopError, "Input sample should be longer");
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200691 goto error;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000692 }
693
694 result = _sum2(cp1, cp1, len2);
695
696 best_result = result;
697 best_j = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000698
699 for ( j=1; j<=len1-len2; j++) {
700 aj_m1 = (double)cp1[j-1];
701 aj_lm1 = (double)cp1[j+len2-1];
702
703 result = result + aj_lm1*aj_lm1 - aj_m1*aj_m1;
704
705 if ( result > best_result ) {
706 best_result = result;
707 best_j = j;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000708 }
Jack Jansena90805f1993-02-17 14:29:28 +0000709
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000710 }
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000711
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200712 PyBuffer_Release(&view);
Mark Dickinson81fece22010-05-11 13:34:35 +0000713 return PyLong_FromSsize_t(best_j);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200714
715 error:
716 PyBuffer_Release(&view);
717 return NULL;
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000718}
719
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000720static PyObject *
Peter Schneider-Kamp8bc8f0d2000-07-10 17:15:07 +0000721audioop_avgpp(PyObject *self, PyObject *args)
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000722{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200723 Py_buffer view;
724 Py_ssize_t i;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300725 int size, prevval, prevextremevalid = 0,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000726 prevextreme = 0;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200727 double sum = 0.0;
728 unsigned int avg;
729 int diff, prevdiff, nextreme = 0;
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000730
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200731 if (!PyArg_ParseTuple(args, "y*i:avgpp", &view, &size))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000732 return NULL;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200733 if (!audioop_check_parameters(view.len, size)) {
734 PyBuffer_Release(&view);
735 return NULL;
736 }
737 if (view.len <= size) {
738 PyBuffer_Release(&view);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200739 return PyLong_FromLong(0);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200740 }
741 prevval = GETRAWSAMPLE(size, view.buf, 0);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200742 prevdiff = 17; /* Anything != 0, 1 */
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200743 for (i = size; i < view.len; i += size) {
744 int val = GETRAWSAMPLE(size, view.buf, i);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200745 if (val != prevval) {
746 diff = val < prevval;
747 if (prevdiff == !diff) {
748 /* Derivative changed sign. Compute difference to last
749 ** extreme value and remember.
750 */
751 if (prevextremevalid) {
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300752 if (prevval < prevextreme)
753 sum += (double)((unsigned int)prevextreme -
754 (unsigned int)prevval);
755 else
756 sum += (double)((unsigned int)prevval -
757 (unsigned int)prevextreme);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200758 nextreme++;
759 }
760 prevextremevalid = 1;
761 prevextreme = prevval;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000762 }
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200763 prevval = val;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000764 prevdiff = diff;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200765 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000766 }
767 if ( nextreme == 0 )
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200768 avg = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000769 else
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200770 avg = (unsigned int)(sum / (double)nextreme);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200771 PyBuffer_Release(&view);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200772 return PyLong_FromUnsignedLong(avg);
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000773}
774
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000775static PyObject *
Peter Schneider-Kamp8bc8f0d2000-07-10 17:15:07 +0000776audioop_maxpp(PyObject *self, PyObject *args)
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000777{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200778 Py_buffer view;
779 Py_ssize_t i;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300780 int size, prevval, prevextremevalid = 0,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000781 prevextreme = 0;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200782 unsigned int max = 0, extremediff;
783 int diff, prevdiff;
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000784
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200785 if (!PyArg_ParseTuple(args, "y*i:maxpp", &view, &size))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000786 return NULL;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200787 if (!audioop_check_parameters(view.len, size)) {
788 PyBuffer_Release(&view);
789 return NULL;
790 }
791 if (view.len <= size) {
792 PyBuffer_Release(&view);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200793 return PyLong_FromLong(0);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200794 }
795 prevval = GETRAWSAMPLE(size, view.buf, 0);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200796 prevdiff = 17; /* Anything != 0, 1 */
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200797 for (i = size; i < view.len; i += size) {
798 int val = GETRAWSAMPLE(size, view.buf, i);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200799 if (val != prevval) {
800 diff = val < prevval;
801 if (prevdiff == !diff) {
802 /* Derivative changed sign. Compute difference to
803 ** last extreme value and remember.
804 */
805 if (prevextremevalid) {
806 if (prevval < prevextreme)
807 extremediff = (unsigned int)prevextreme -
808 (unsigned int)prevval;
809 else
810 extremediff = (unsigned int)prevval -
811 (unsigned int)prevextreme;
812 if ( extremediff > max )
813 max = extremediff;
814 }
815 prevextremevalid = 1;
816 prevextreme = prevval;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000817 }
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200818 prevval = val;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000819 prevdiff = diff;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200820 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000821 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200822 PyBuffer_Release(&view);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200823 return PyLong_FromUnsignedLong(max);
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000824}
825
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000826static PyObject *
Peter Schneider-Kamp8bc8f0d2000-07-10 17:15:07 +0000827audioop_cross(PyObject *self, PyObject *args)
Guido van Rossumb66efa01992-06-01 16:01:24 +0000828{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200829 Py_buffer view;
830 Py_ssize_t i;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300831 int size;
Mark Dickinson81fece22010-05-11 13:34:35 +0000832 int prevval;
833 Py_ssize_t ncross;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000834
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200835 if (!PyArg_ParseTuple(args, "y*i:cross", &view, &size))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000836 return NULL;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200837 if (!audioop_check_parameters(view.len, size)) {
838 PyBuffer_Release(&view);
839 return NULL;
840 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000841 ncross = -1;
842 prevval = 17; /* Anything <> 0,1 */
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200843 for (i = 0; i < view.len; i += size) {
844 int val = GETRAWSAMPLE(size, view.buf, i) < 0;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300845 if (val != prevval) ncross++;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000846 prevval = val;
847 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200848 PyBuffer_Release(&view);
Mark Dickinson81fece22010-05-11 13:34:35 +0000849 return PyLong_FromSsize_t(ncross);
Guido van Rossumb66efa01992-06-01 16:01:24 +0000850}
851
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000852static PyObject *
Peter Schneider-Kamp8bc8f0d2000-07-10 17:15:07 +0000853audioop_mul(PyObject *self, PyObject *args)
Guido van Rossumb66efa01992-06-01 16:01:24 +0000854{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200855 Py_buffer view;
856 signed char *ncp;
857 Py_ssize_t i;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300858 int size;
859 double factor, maxval, minval;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200860 PyObject *rv = NULL;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000861
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200862 if (!PyArg_ParseTuple(args, "y*id:mul", &view, &size, &factor))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000863 return NULL;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200864 if (!audioop_check_parameters(view.len, size))
865 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000866
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200867 maxval = (double) maxvals[size];
868 minval = (double) minvals[size];
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000869
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200870 rv = PyBytes_FromStringAndSize(NULL, view.len);
871 if (rv == NULL)
872 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000873 ncp = (signed char *)PyBytes_AsString(rv);
874
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200875 for (i = 0; i < view.len; i += size) {
876 double val = GETRAWSAMPLE(size, view.buf, i);
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300877 val *= factor;
878 val = floor(fbound(val, minval, maxval));
879 SETRAWSAMPLE(size, ncp, i, (int)val);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000880 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200881 exit:
882 PyBuffer_Release(&view);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000883 return rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000884}
885
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000886static PyObject *
Peter Schneider-Kamp8bc8f0d2000-07-10 17:15:07 +0000887audioop_tomono(PyObject *self, PyObject *args)
Guido van Rossumb66efa01992-06-01 16:01:24 +0000888{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000889 Py_buffer pcp;
890 signed char *cp, *ncp;
Mark Dickinson81fece22010-05-11 13:34:35 +0000891 Py_ssize_t len, i;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300892 int size;
893 double fac1, fac2, maxval, minval;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200894 PyObject *rv = NULL;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000895
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200896 if (!PyArg_ParseTuple(args, "y*idd:tomono",
897 &pcp, &size, &fac1, &fac2))
898 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000899 cp = pcp.buf;
900 len = pcp.len;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200901 if (!audioop_check_parameters(len, size))
902 goto exit;
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000903 if (((len / size) & 1) != 0) {
904 PyErr_SetString(AudioopError, "not a whole number of frames");
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200905 goto exit;
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000906 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000907
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200908 maxval = (double) maxvals[size];
909 minval = (double) minvals[size];
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000910
911 rv = PyBytes_FromStringAndSize(NULL, len/2);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200912 if (rv == NULL)
913 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000914 ncp = (signed char *)PyBytes_AsString(rv);
915
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300916 for (i = 0; i < len; i += size*2) {
917 double val1 = GETRAWSAMPLE(size, cp, i);
918 double val2 = GETRAWSAMPLE(size, cp, i + size);
919 double val = val1*fac1 + val2*fac2;
920 val = floor(fbound(val, minval, maxval));
921 SETRAWSAMPLE(size, ncp, i/2, val);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000922 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200923 exit:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000924 PyBuffer_Release(&pcp);
925 return rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000926}
927
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000928static PyObject *
Peter Schneider-Kamp8bc8f0d2000-07-10 17:15:07 +0000929audioop_tostereo(PyObject *self, PyObject *args)
Guido van Rossumb66efa01992-06-01 16:01:24 +0000930{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200931 Py_buffer view;
932 signed char *ncp;
933 Py_ssize_t i;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300934 int size;
935 double fac1, fac2, maxval, minval;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200936 PyObject *rv = NULL;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000937
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200938 if (!PyArg_ParseTuple(args, "y*idd:tostereo",
939 &view, &size, &fac1, &fac2))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000940 return NULL;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200941 if (!audioop_check_parameters(view.len, size))
942 goto exit;
Amaury Forgeot d'Arc9c74b142008-06-18 00:47:36 +0000943
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200944 maxval = (double) maxvals[size];
945 minval = (double) minvals[size];
Guido van Rossumb66efa01992-06-01 16:01:24 +0000946
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200947 if (view.len > PY_SSIZE_T_MAX/2) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000948 PyErr_SetString(PyExc_MemoryError,
949 "not enough memory for output buffer");
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200950 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000951 }
Guido van Rossumb66efa01992-06-01 16:01:24 +0000952
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200953 rv = PyBytes_FromStringAndSize(NULL, view.len*2);
954 if (rv == NULL)
955 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000956 ncp = (signed char *)PyBytes_AsString(rv);
Guido van Rossumb66efa01992-06-01 16:01:24 +0000957
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200958 for (i = 0; i < view.len; i += size) {
959 double val = GETRAWSAMPLE(size, view.buf, i);
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300960 int val1 = (int)floor(fbound(val*fac1, minval, maxval));
961 int val2 = (int)floor(fbound(val*fac2, minval, maxval));
962 SETRAWSAMPLE(size, ncp, i*2, val1);
963 SETRAWSAMPLE(size, ncp, i*2 + size, val2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000964 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200965 exit:
966 PyBuffer_Release(&view);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000967 return rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000968}
969
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000970static PyObject *
Peter Schneider-Kamp8bc8f0d2000-07-10 17:15:07 +0000971audioop_add(PyObject *self, PyObject *args)
Guido van Rossumb66efa01992-06-01 16:01:24 +0000972{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200973 Py_buffer view1;
974 Py_buffer view2;
975 signed char *ncp;
976 Py_ssize_t i;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300977 int size, minval, maxval, newval;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200978 PyObject *rv = NULL;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000979
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200980 if (!PyArg_ParseTuple(args, "y*y*i:add",
981 &view1, &view2, &size))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000982 return NULL;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200983 if (!audioop_check_parameters(view1.len, size))
984 goto exit;
985 if (view1.len != view2.len) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000986 PyErr_SetString(AudioopError, "Lengths should be the same");
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200987 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000988 }
Guido van Rossum1851a671997-02-14 16:14:03 +0000989
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200990 maxval = maxvals[size];
991 minval = minvals[size];
Guido van Rossum1851a671997-02-14 16:14:03 +0000992
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200993 rv = PyBytes_FromStringAndSize(NULL, view1.len);
994 if (rv == NULL)
995 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000996 ncp = (signed char *)PyBytes_AsString(rv);
Guido van Rossumb66efa01992-06-01 16:01:24 +0000997
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200998 for (i = 0; i < view1.len; i += size) {
999 int val1 = GETRAWSAMPLE(size, view1.buf, i);
1000 int val2 = GETRAWSAMPLE(size, view2.buf, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001001
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001002 if (size < 4) {
1003 newval = val1 + val2;
1004 /* truncate in case of overflow */
1005 if (newval > maxval)
1006 newval = maxval;
1007 else if (newval < minval)
1008 newval = minval;
1009 }
1010 else {
1011 double fval = (double)val1 + (double)val2;
1012 /* truncate in case of overflow */
1013 newval = (int)floor(fbound(fval, minval, maxval));
1014 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001015
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001016 SETRAWSAMPLE(size, ncp, i, newval);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001017 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001018 exit:
1019 PyBuffer_Release(&view1);
1020 PyBuffer_Release(&view2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001021 return rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001022}
1023
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001024static PyObject *
Peter Schneider-Kamp8bc8f0d2000-07-10 17:15:07 +00001025audioop_bias(PyObject *self, PyObject *args)
Guido van Rossumb66efa01992-06-01 16:01:24 +00001026{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001027 Py_buffer view;
1028 signed char *ncp;
1029 Py_ssize_t i;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001030 int size, bias;
1031 unsigned int val = 0, mask;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001032 PyObject *rv = NULL;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001033
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001034 if (!PyArg_ParseTuple(args, "y*ii:bias",
1035 &view, &size, &bias))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001036 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001037
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001038 if (!audioop_check_parameters(view.len, size))
1039 goto exit;
1040
1041 rv = PyBytes_FromStringAndSize(NULL, view.len);
1042 if (rv == NULL)
1043 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001044 ncp = (signed char *)PyBytes_AsString(rv);
1045
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001046 mask = masks[size];
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001047
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001048 for (i = 0; i < view.len; i += size) {
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001049 if (size == 1)
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001050 val = GETINTX(unsigned char, view.buf, i);
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001051 else if (size == 2)
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001052 val = GETINTX(unsigned short, view.buf, i);
Serhiy Storchakace82eb22013-10-20 09:42:26 +03001053 else if (size == 3)
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001054 val = ((unsigned int)GETINT24(view.buf, i)) & 0xffffffu;
Serhiy Storchakace82eb22013-10-20 09:42:26 +03001055 else {
1056 assert(size == 4);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001057 val = GETINTX(PY_UINT32_T, view.buf, i);
Serhiy Storchakace82eb22013-10-20 09:42:26 +03001058 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001059
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001060 val += (unsigned int)bias;
1061 /* wrap around in case of overflow */
1062 val &= mask;
1063
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001064 if (size == 1)
1065 SETINTX(unsigned char, ncp, i, val);
1066 else if (size == 2)
1067 SETINTX(unsigned short, ncp, i, val);
Serhiy Storchakace82eb22013-10-20 09:42:26 +03001068 else if (size == 3)
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001069 SETINT24(ncp, i, (int)val);
Serhiy Storchakace82eb22013-10-20 09:42:26 +03001070 else {
1071 assert(size == 4);
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001072 SETINTX(PY_UINT32_T, ncp, i, val);
Serhiy Storchakace82eb22013-10-20 09:42:26 +03001073 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001074 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001075 exit:
1076 PyBuffer_Release(&view);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001077 return rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001078}
1079
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001080static PyObject *
Peter Schneider-Kamp8bc8f0d2000-07-10 17:15:07 +00001081audioop_reverse(PyObject *self, PyObject *args)
Jack Jansen337b20e1993-02-23 13:39:57 +00001082{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001083 Py_buffer view;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001084 unsigned char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001085 Py_ssize_t i;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001086 int size;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001087 PyObject *rv = NULL;
Jack Jansen337b20e1993-02-23 13:39:57 +00001088
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001089 if (!PyArg_ParseTuple(args, "y*i:reverse",
1090 &view, &size))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001091 return NULL;
Jack Jansen337b20e1993-02-23 13:39:57 +00001092
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001093 if (!audioop_check_parameters(view.len, size))
1094 goto exit;
1095
1096 rv = PyBytes_FromStringAndSize(NULL, view.len);
1097 if (rv == NULL)
1098 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001099 ncp = (unsigned char *)PyBytes_AsString(rv);
1100
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001101 for (i = 0; i < view.len; i += size) {
1102 int val = GETRAWSAMPLE(size, view.buf, i);
1103 SETRAWSAMPLE(size, ncp, view.len - i - size, val);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001104 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001105 exit:
1106 PyBuffer_Release(&view);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001107 return rv;
Jack Jansen337b20e1993-02-23 13:39:57 +00001108}
1109
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001110static PyObject *
Peter Schneider-Kamp8bc8f0d2000-07-10 17:15:07 +00001111audioop_lin2lin(PyObject *self, PyObject *args)
Jack Jansena90805f1993-02-17 14:29:28 +00001112{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001113 Py_buffer view;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001114 unsigned char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001115 Py_ssize_t i, j;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001116 int size, size2;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001117 PyObject *rv = NULL;
Jack Jansena90805f1993-02-17 14:29:28 +00001118
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001119 if (!PyArg_ParseTuple(args, "y*ii:lin2lin",
1120 &view, &size, &size2))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001121 return NULL;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001122
1123 if (!audioop_check_parameters(view.len, size))
1124 goto exit;
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001125 if (!audioop_check_size(size2))
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001126 goto exit;
Jack Jansena90805f1993-02-17 14:29:28 +00001127
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001128 if (view.len/size > PY_SSIZE_T_MAX/size2) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001129 PyErr_SetString(PyExc_MemoryError,
1130 "not enough memory for output buffer");
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001131 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001132 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001133 rv = PyBytes_FromStringAndSize(NULL, (view.len/size)*size2);
1134 if (rv == NULL)
1135 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001136 ncp = (unsigned char *)PyBytes_AsString(rv);
1137
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001138 for (i = j = 0; i < view.len; i += size, j += size2) {
1139 int val = GETSAMPLE32(size, view.buf, i);
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001140 SETSAMPLE32(size2, ncp, j, val);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001141 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001142 exit:
1143 PyBuffer_Release(&view);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001144 return rv;
Jack Jansena90805f1993-02-17 14:29:28 +00001145}
1146
Guido van Rossumb24c9ea1997-05-20 15:59:35 +00001147static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00001148gcd(int a, int b)
Guido van Rossumb24c9ea1997-05-20 15:59:35 +00001149{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001150 while (b > 0) {
1151 int tmp = a % b;
1152 a = b;
1153 b = tmp;
1154 }
1155 return a;
Guido van Rossumb24c9ea1997-05-20 15:59:35 +00001156}
1157
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001158static PyObject *
Peter Schneider-Kamp8bc8f0d2000-07-10 17:15:07 +00001159audioop_ratecv(PyObject *self, PyObject *args)
Roger E. Massec905fff1997-01-17 18:12:04 +00001160{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001161 Py_buffer view;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001162 char *cp, *ncp;
Mark Dickinson81fece22010-05-11 13:34:35 +00001163 Py_ssize_t len;
1164 int size, nchannels, inrate, outrate, weightA, weightB;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001165 int chan, d, *prev_i, *cur_i, cur_o;
1166 PyObject *state, *samps, *str, *rv = NULL;
1167 int bytes_per_frame;
Guido van Rossum1851a671997-02-14 16:14:03 +00001168
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001169 weightA = 1;
1170 weightB = 0;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001171 if (!PyArg_ParseTuple(args, "y*iiiiO|ii:ratecv", &view, &size,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001172 &nchannels, &inrate, &outrate, &state,
1173 &weightA, &weightB))
1174 return NULL;
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001175 if (!audioop_check_size(size))
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001176 goto exit2;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001177 if (nchannels < 1) {
1178 PyErr_SetString(AudioopError, "# of channels should be >= 1");
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001179 goto exit2;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001180 }
Mark Dickinsonc04ddff2012-10-06 18:04:49 +01001181 if (size > INT_MAX / nchannels) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001182 /* This overflow test is rigorously correct because
1183 both multiplicands are >= 1. Use the argument names
1184 from the docs for the error msg. */
1185 PyErr_SetString(PyExc_OverflowError,
1186 "width * nchannels too big for a C int");
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001187 goto exit2;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001188 }
Mark Dickinsonc04ddff2012-10-06 18:04:49 +01001189 bytes_per_frame = size * nchannels;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001190 if (weightA < 1 || weightB < 0) {
1191 PyErr_SetString(AudioopError,
1192 "weightA should be >= 1, weightB should be >= 0");
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001193 goto exit2;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001194 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001195 if (view.len % bytes_per_frame != 0) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001196 PyErr_SetString(AudioopError, "not a whole number of frames");
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001197 goto exit2;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001198 }
1199 if (inrate <= 0 || outrate <= 0) {
1200 PyErr_SetString(AudioopError, "sampling rate not > 0");
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001201 goto exit2;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001202 }
1203 /* divide inrate and outrate by their greatest common divisor */
1204 d = gcd(inrate, outrate);
1205 inrate /= d;
1206 outrate /= d;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001207 /* divide weightA and weightB by their greatest common divisor */
1208 d = gcd(weightA, weightB);
1209 weightA /= d;
1210 weightA /= d;
Guido van Rossumb24c9ea1997-05-20 15:59:35 +00001211
Mark Dickinson85eacea2010-05-10 16:27:45 +00001212 if ((size_t)nchannels > PY_SIZE_MAX/sizeof(int)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001213 PyErr_SetString(PyExc_MemoryError,
1214 "not enough memory for output buffer");
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001215 goto exit2;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001216 }
Victor Stinnerb6404912013-07-07 16:21:41 +02001217 prev_i = (int *) PyMem_Malloc(nchannels * sizeof(int));
1218 cur_i = (int *) PyMem_Malloc(nchannels * sizeof(int));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001219 if (prev_i == NULL || cur_i == NULL) {
1220 (void) PyErr_NoMemory();
1221 goto exit;
1222 }
1223
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001224 len = view.len / bytes_per_frame; /* # of frames */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001225
1226 if (state == Py_None) {
1227 d = -outrate;
1228 for (chan = 0; chan < nchannels; chan++)
1229 prev_i[chan] = cur_i[chan] = 0;
1230 }
1231 else {
1232 if (!PyArg_ParseTuple(state,
1233 "iO!;audioop.ratecv: illegal state argument",
1234 &d, &PyTuple_Type, &samps))
1235 goto exit;
1236 if (PyTuple_Size(samps) != nchannels) {
1237 PyErr_SetString(AudioopError,
1238 "illegal state argument");
1239 goto exit;
Amaury Forgeot d'Arc9c74b142008-06-18 00:47:36 +00001240 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001241 for (chan = 0; chan < nchannels; chan++) {
1242 if (!PyArg_ParseTuple(PyTuple_GetItem(samps, chan),
1243 "ii:ratecv", &prev_i[chan],
1244 &cur_i[chan]))
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001245 goto exit;
1246 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001247 }
Guido van Rossum1851a671997-02-14 16:14:03 +00001248
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001249 /* str <- Space for the output buffer. */
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001250 if (len == 0)
1251 str = PyBytes_FromStringAndSize(NULL, 0);
1252 else {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001253 /* There are len input frames, so we need (mathematically)
1254 ceiling(len*outrate/inrate) output frames, and each frame
1255 requires bytes_per_frame bytes. Computing this
1256 without spurious overflow is the challenge; we can
Mark Dickinson393b97a2010-05-11 13:09:58 +00001257 settle for a reasonable upper bound, though, in this
1258 case ceiling(len/inrate) * outrate. */
1259
1260 /* compute ceiling(len/inrate) without overflow */
Mark Dickinson81fece22010-05-11 13:34:35 +00001261 Py_ssize_t q = len > 0 ? 1 + (len - 1) / inrate : 0;
1262 if (outrate > PY_SSIZE_T_MAX / q / bytes_per_frame)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001263 str = NULL;
1264 else
Mark Dickinson393b97a2010-05-11 13:09:58 +00001265 str = PyBytes_FromStringAndSize(NULL,
1266 q * outrate * bytes_per_frame);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001267 }
1268 if (str == NULL) {
1269 PyErr_SetString(PyExc_MemoryError,
1270 "not enough memory for output buffer");
1271 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001272 }
1273 ncp = PyBytes_AsString(str);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001274 cp = view.buf;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001275
1276 for (;;) {
1277 while (d < 0) {
1278 if (len == 0) {
1279 samps = PyTuple_New(nchannels);
1280 if (samps == NULL)
1281 goto exit;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001282 for (chan = 0; chan < nchannels; chan++)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001283 PyTuple_SetItem(samps, chan,
1284 Py_BuildValue("(ii)",
1285 prev_i[chan],
1286 cur_i[chan]));
1287 if (PyErr_Occurred())
1288 goto exit;
1289 /* We have checked before that the length
1290 * of the string fits into int. */
Mark Dickinson81fece22010-05-11 13:34:35 +00001291 len = (Py_ssize_t)(ncp - PyBytes_AsString(str));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001292 rv = PyBytes_FromStringAndSize
1293 (PyBytes_AsString(str), len);
1294 Py_DECREF(str);
1295 str = rv;
1296 if (str == NULL)
1297 goto exit;
1298 rv = Py_BuildValue("(O(iO))", str, d, samps);
1299 Py_DECREF(samps);
1300 Py_DECREF(str);
1301 goto exit; /* return rv */
1302 }
1303 for (chan = 0; chan < nchannels; chan++) {
1304 prev_i[chan] = cur_i[chan];
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001305 cur_i[chan] = GETSAMPLE32(size, cp, 0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001306 cp += size;
1307 /* implements a simple digital filter */
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001308 cur_i[chan] = (int)(
1309 ((double)weightA * (double)cur_i[chan] +
1310 (double)weightB * (double)prev_i[chan]) /
1311 ((double)weightA + (double)weightB));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001312 }
1313 len--;
1314 d += outrate;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001315 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001316 while (d >= 0) {
1317 for (chan = 0; chan < nchannels; chan++) {
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001318 cur_o = (int)(((double)prev_i[chan] * (double)d +
1319 (double)cur_i[chan] * (double)(outrate - d)) /
1320 (double)outrate);
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001321 SETSAMPLE32(size, ncp, 0, cur_o);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001322 ncp += size;
1323 }
1324 d -= inrate;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001325 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001326 }
Guido van Rossum65bb3281999-09-07 14:24:05 +00001327 exit:
Victor Stinnerb6404912013-07-07 16:21:41 +02001328 PyMem_Free(prev_i);
1329 PyMem_Free(cur_i);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001330 exit2:
1331 PyBuffer_Release(&view);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001332 return rv;
Roger E. Massec905fff1997-01-17 18:12:04 +00001333}
Guido van Rossum1851a671997-02-14 16:14:03 +00001334
Roger E. Massec905fff1997-01-17 18:12:04 +00001335static PyObject *
Peter Schneider-Kamp8bc8f0d2000-07-10 17:15:07 +00001336audioop_lin2ulaw(PyObject *self, PyObject *args)
Guido van Rossumb66efa01992-06-01 16:01:24 +00001337{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001338 Py_buffer view;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001339 unsigned char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001340 Py_ssize_t i;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001341 int size;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001342 PyObject *rv = NULL;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001343
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001344 if (!PyArg_ParseTuple(args, "y*i:lin2ulaw",
1345 &view, &size))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001346 return NULL;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001347
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001348 if (!audioop_check_parameters(view.len, size))
1349 goto exit;
1350
1351 rv = PyBytes_FromStringAndSize(NULL, view.len/size);
1352 if (rv == NULL)
1353 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001354 ncp = (unsigned char *)PyBytes_AsString(rv);
1355
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001356 for (i = 0; i < view.len; i += size) {
1357 int val = GETSAMPLE32(size, view.buf, i);
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001358 *ncp++ = st_14linear2ulaw(val >> 18);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001359 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001360 exit:
1361 PyBuffer_Release(&view);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001362 return rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001363}
1364
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001365static PyObject *
Peter Schneider-Kamp8bc8f0d2000-07-10 17:15:07 +00001366audioop_ulaw2lin(PyObject *self, PyObject *args)
Guido van Rossumb66efa01992-06-01 16:01:24 +00001367{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001368 Py_buffer view;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001369 unsigned char *cp;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001370 signed char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001371 Py_ssize_t i;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001372 int size;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001373 PyObject *rv = NULL;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001374
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001375 if (!PyArg_ParseTuple(args, "y*i:ulaw2lin",
1376 &view, &size))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001377 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001378
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001379 if (!audioop_check_size(size))
1380 goto exit;
1381
1382 if (view.len > PY_SSIZE_T_MAX/size) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001383 PyErr_SetString(PyExc_MemoryError,
1384 "not enough memory for output buffer");
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001385 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001386 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001387 rv = PyBytes_FromStringAndSize(NULL, view.len*size);
1388 if (rv == NULL)
1389 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001390 ncp = (signed char *)PyBytes_AsString(rv);
1391
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001392 cp = view.buf;
1393 for (i = 0; i < view.len*size; i += size) {
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001394 int val = st_ulaw2linear16(*cp++) << 16;
1395 SETSAMPLE32(size, ncp, i, val);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001396 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001397 exit:
1398 PyBuffer_Release(&view);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001399 return rv;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001400}
1401
1402static PyObject *
1403audioop_lin2alaw(PyObject *self, PyObject *args)
1404{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001405 Py_buffer view;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001406 unsigned char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001407 Py_ssize_t i;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001408 int size;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001409 PyObject *rv = NULL;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001410
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001411 if (!PyArg_ParseTuple(args, "y*i:lin2alaw",
1412 &view, &size))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001413 return NULL;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001414
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001415 if (!audioop_check_parameters(view.len, size))
1416 goto exit;
1417
1418 rv = PyBytes_FromStringAndSize(NULL, view.len/size);
1419 if (rv == NULL)
1420 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001421 ncp = (unsigned char *)PyBytes_AsString(rv);
1422
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001423 for (i = 0; i < view.len; i += size) {
1424 int val = GETSAMPLE32(size, view.buf, i);
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001425 *ncp++ = st_linear2alaw(val >> 19);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001426 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001427 exit:
1428 PyBuffer_Release(&view);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001429 return rv;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001430}
1431
1432static PyObject *
1433audioop_alaw2lin(PyObject *self, PyObject *args)
1434{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001435 Py_buffer view;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001436 unsigned char *cp;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001437 signed char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001438 Py_ssize_t i;
Mark Dickinson81fece22010-05-11 13:34:35 +00001439 int size, val;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001440 PyObject *rv = NULL;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001441
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001442 if (!PyArg_ParseTuple(args, "y*i:alaw2lin",
1443 &view, &size))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001444 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001445
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001446 if (!audioop_check_size(size))
1447 goto exit;
1448
1449 if (view.len > PY_SSIZE_T_MAX/size) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001450 PyErr_SetString(PyExc_MemoryError,
1451 "not enough memory for output buffer");
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001452 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001453 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001454 rv = PyBytes_FromStringAndSize(NULL, view.len*size);
1455 if (rv == NULL)
1456 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001457 ncp = (signed char *)PyBytes_AsString(rv);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001458 cp = view.buf;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001459
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001460 for (i = 0; i < view.len*size; i += size) {
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001461 val = st_alaw2linear16(*cp++) << 16;
1462 SETSAMPLE32(size, ncp, i, val);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001463 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001464 exit:
1465 PyBuffer_Release(&view);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001466 return rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001467}
1468
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001469static PyObject *
Peter Schneider-Kamp8bc8f0d2000-07-10 17:15:07 +00001470audioop_lin2adpcm(PyObject *self, PyObject *args)
Guido van Rossumb64e6351992-07-06 14:21:56 +00001471{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001472 Py_buffer view;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001473 signed char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001474 Py_ssize_t i;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001475 int size, step, valpred, delta,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001476 index, sign, vpdiff, diff;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001477 PyObject *rv = NULL, *state, *str;
Mark Dickinson81fece22010-05-11 13:34:35 +00001478 int outputbuffer = 0, bufferstep;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001479
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001480 if (!PyArg_ParseTuple(args, "y*iO:lin2adpcm",
1481 &view, &size, &state))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001482 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001483
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001484 if (!audioop_check_parameters(view.len, size))
1485 goto exit;
1486
1487 str = PyBytes_FromStringAndSize(NULL, view.len/(size*2));
1488 if (str == NULL)
1489 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001490 ncp = (signed char *)PyBytes_AsString(str);
1491
1492 /* Decode state, should have (value, step) */
1493 if ( state == Py_None ) {
1494 /* First time, it seems. Set defaults */
1495 valpred = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001496 index = 0;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001497 } else if (!PyArg_ParseTuple(state, "ii", &valpred, &index))
1498 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001499
1500 step = stepsizeTable[index];
1501 bufferstep = 1;
1502
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001503 for (i = 0; i < view.len; i += size) {
1504 int val = GETSAMPLE32(size, view.buf, i) >> 16;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001505
1506 /* Step 1 - compute difference with previous value */
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001507 if (val < valpred) {
1508 diff = valpred - val;
1509 sign = 8;
1510 }
1511 else {
1512 diff = val - valpred;
1513 sign = 0;
1514 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001515
1516 /* Step 2 - Divide and clamp */
1517 /* Note:
1518 ** This code *approximately* computes:
1519 ** delta = diff*4/step;
1520 ** vpdiff = (delta+0.5)*step/4;
1521 ** but in shift step bits are dropped. The net result of this
1522 ** is that even if you have fast mul/div hardware you cannot
1523 ** put it to good use since the fixup would be too expensive.
1524 */
1525 delta = 0;
1526 vpdiff = (step >> 3);
1527
1528 if ( diff >= step ) {
1529 delta = 4;
1530 diff -= step;
1531 vpdiff += step;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001532 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001533 step >>= 1;
1534 if ( diff >= step ) {
1535 delta |= 2;
1536 diff -= step;
1537 vpdiff += step;
1538 }
1539 step >>= 1;
1540 if ( diff >= step ) {
1541 delta |= 1;
1542 vpdiff += step;
1543 }
Jack Jansendd8a6ea1993-02-17 14:21:09 +00001544
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001545 /* Step 3 - Update previous value */
1546 if ( sign )
1547 valpred -= vpdiff;
1548 else
1549 valpred += vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001550
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001551 /* Step 4 - Clamp previous value to 16 bits */
1552 if ( valpred > 32767 )
1553 valpred = 32767;
1554 else if ( valpred < -32768 )
1555 valpred = -32768;
1556
1557 /* Step 5 - Assemble value, update index and step values */
1558 delta |= sign;
1559
1560 index += indexTable[delta];
1561 if ( index < 0 ) index = 0;
1562 if ( index > 88 ) index = 88;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001563 step = stepsizeTable[index];
Guido van Rossumb64e6351992-07-06 14:21:56 +00001564
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001565 /* Step 6 - Output value */
1566 if ( bufferstep ) {
1567 outputbuffer = (delta << 4) & 0xf0;
1568 } else {
1569 *ncp++ = (delta & 0x0f) | outputbuffer;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001570 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001571 bufferstep = !bufferstep;
1572 }
1573 rv = Py_BuildValue("(O(ii))", str, valpred, index);
1574 Py_DECREF(str);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001575 exit:
1576 PyBuffer_Release(&view);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001577 return rv;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001578}
1579
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001580static PyObject *
Peter Schneider-Kamp8bc8f0d2000-07-10 17:15:07 +00001581audioop_adpcm2lin(PyObject *self, PyObject *args)
Guido van Rossumb64e6351992-07-06 14:21:56 +00001582{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001583 Py_buffer view;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001584 signed char *cp;
1585 signed char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001586 Py_ssize_t i, outlen;
Mark Dickinson81fece22010-05-11 13:34:35 +00001587 int size, valpred, step, delta, index, sign, vpdiff;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001588 PyObject *rv = NULL, *str, *state;
Mark Dickinson81fece22010-05-11 13:34:35 +00001589 int inputbuffer = 0, bufferstep;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001590
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001591 if (!PyArg_ParseTuple(args, "y*iO:adpcm2lin",
1592 &view, &size, &state))
1593 return NULL;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001594
Antoine Pitrou75ff65e2012-01-28 22:01:59 +01001595 if (!audioop_check_size(size))
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001596 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001597
1598 /* Decode state, should have (value, step) */
1599 if ( state == Py_None ) {
1600 /* First time, it seems. Set defaults */
1601 valpred = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001602 index = 0;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001603 } else if (!PyArg_ParseTuple(state, "ii", &valpred, &index))
1604 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001605
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001606 if (view.len > (PY_SSIZE_T_MAX/2)/size) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001607 PyErr_SetString(PyExc_MemoryError,
1608 "not enough memory for output buffer");
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001609 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001610 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001611 outlen = view.len*size*2;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001612 str = PyBytes_FromStringAndSize(NULL, outlen);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001613 if (str == NULL)
1614 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001615 ncp = (signed char *)PyBytes_AsString(str);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001616 cp = view.buf;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001617
1618 step = stepsizeTable[index];
1619 bufferstep = 0;
1620
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001621 for (i = 0; i < outlen; i += size) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001622 /* Step 1 - get the delta value and compute next index */
1623 if ( bufferstep ) {
1624 delta = inputbuffer & 0xf;
1625 } else {
1626 inputbuffer = *cp++;
1627 delta = (inputbuffer >> 4) & 0xf;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001628 }
Guido van Rossumb64e6351992-07-06 14:21:56 +00001629
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001630 bufferstep = !bufferstep;
1631
1632 /* Step 2 - Find new index value (for later) */
1633 index += indexTable[delta];
1634 if ( index < 0 ) index = 0;
1635 if ( index > 88 ) index = 88;
1636
1637 /* Step 3 - Separate sign and magnitude */
1638 sign = delta & 8;
1639 delta = delta & 7;
1640
1641 /* Step 4 - Compute difference and new predicted value */
1642 /*
1643 ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
1644 ** in adpcm_coder.
1645 */
1646 vpdiff = step >> 3;
1647 if ( delta & 4 ) vpdiff += step;
1648 if ( delta & 2 ) vpdiff += step>>1;
1649 if ( delta & 1 ) vpdiff += step>>2;
1650
1651 if ( sign )
1652 valpred -= vpdiff;
1653 else
1654 valpred += vpdiff;
1655
1656 /* Step 5 - clamp output value */
1657 if ( valpred > 32767 )
1658 valpred = 32767;
1659 else if ( valpred < -32768 )
1660 valpred = -32768;
1661
1662 /* Step 6 - Update step value */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001663 step = stepsizeTable[index];
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001664
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001665 /* Step 6 - Output value */
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001666 SETSAMPLE32(size, ncp, i, valpred << 16);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001667 }
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001668
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001669 rv = Py_BuildValue("(O(ii))", str, valpred, index);
1670 Py_DECREF(str);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001671 exit:
1672 PyBuffer_Release(&view);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001673 return rv;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001674}
1675
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001676static PyMethodDef audioop_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001677 { "max", audioop_max, METH_VARARGS },
1678 { "minmax", audioop_minmax, METH_VARARGS },
1679 { "avg", audioop_avg, METH_VARARGS },
1680 { "maxpp", audioop_maxpp, METH_VARARGS },
1681 { "avgpp", audioop_avgpp, METH_VARARGS },
1682 { "rms", audioop_rms, METH_VARARGS },
1683 { "findfit", audioop_findfit, METH_VARARGS },
1684 { "findmax", audioop_findmax, METH_VARARGS },
1685 { "findfactor", audioop_findfactor, METH_VARARGS },
1686 { "cross", audioop_cross, METH_VARARGS },
1687 { "mul", audioop_mul, METH_VARARGS },
1688 { "add", audioop_add, METH_VARARGS },
1689 { "bias", audioop_bias, METH_VARARGS },
1690 { "ulaw2lin", audioop_ulaw2lin, METH_VARARGS },
1691 { "lin2ulaw", audioop_lin2ulaw, METH_VARARGS },
1692 { "alaw2lin", audioop_alaw2lin, METH_VARARGS },
1693 { "lin2alaw", audioop_lin2alaw, METH_VARARGS },
1694 { "lin2lin", audioop_lin2lin, METH_VARARGS },
1695 { "adpcm2lin", audioop_adpcm2lin, METH_VARARGS },
1696 { "lin2adpcm", audioop_lin2adpcm, METH_VARARGS },
1697 { "tomono", audioop_tomono, METH_VARARGS },
1698 { "tostereo", audioop_tostereo, METH_VARARGS },
1699 { "getsample", audioop_getsample, METH_VARARGS },
1700 { "reverse", audioop_reverse, METH_VARARGS },
1701 { "ratecv", audioop_ratecv, METH_VARARGS },
1702 { 0, 0 }
Guido van Rossumb66efa01992-06-01 16:01:24 +00001703};
1704
Martin v. Löwis1a214512008-06-11 05:26:20 +00001705
1706static struct PyModuleDef audioopmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001707 PyModuleDef_HEAD_INIT,
1708 "audioop",
1709 NULL,
1710 -1,
1711 audioop_methods,
1712 NULL,
1713 NULL,
1714 NULL,
1715 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00001716};
1717
Mark Hammondfe51c6d2002-08-02 02:27:13 +00001718PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00001719PyInit_audioop(void)
Guido van Rossumb66efa01992-06-01 16:01:24 +00001720{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001721 PyObject *m, *d;
1722 m = PyModule_Create(&audioopmodule);
1723 if (m == NULL)
1724 return NULL;
1725 d = PyModule_GetDict(m);
1726 if (d == NULL)
1727 return NULL;
1728 AudioopError = PyErr_NewException("audioop.error", NULL, NULL);
1729 if (AudioopError != NULL)
1730 PyDict_SetItemString(d,"error",AudioopError);
1731 return m;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001732}