blob: ae3ff060b4742ca3cd298ed7c1bcd935c1ac477c [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 *
Serhiy Storchaka3062c9a2013-11-23 22:26:01 +02001111audioop_byteswap(PyObject *self, PyObject *args)
1112{
1113 Py_buffer view;
1114 unsigned char *ncp;
1115 Py_ssize_t i;
1116 int size;
1117 PyObject *rv = NULL;
1118
1119 if (!PyArg_ParseTuple(args, "y*i:swapbytes",
1120 &view, &size))
1121 return NULL;
1122
1123 if (!audioop_check_parameters(view.len, size))
1124 goto exit;
1125
1126 rv = PyBytes_FromStringAndSize(NULL, view.len);
1127 if (rv == NULL)
1128 goto exit;
1129 ncp = (unsigned char *)PyBytes_AsString(rv);
1130
1131 for (i = 0; i < view.len; i += size) {
1132 int j;
1133 for (j = 0; j < size; j++)
1134 ncp[i + size - 1 - j] = ((unsigned char *)view.buf)[i + j];
1135 }
1136 exit:
1137 PyBuffer_Release(&view);
1138 return rv;
1139}
1140
1141static PyObject *
Peter Schneider-Kamp8bc8f0d2000-07-10 17:15:07 +00001142audioop_lin2lin(PyObject *self, PyObject *args)
Jack Jansena90805f1993-02-17 14:29:28 +00001143{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001144 Py_buffer view;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001145 unsigned char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001146 Py_ssize_t i, j;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001147 int size, size2;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001148 PyObject *rv = NULL;
Jack Jansena90805f1993-02-17 14:29:28 +00001149
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001150 if (!PyArg_ParseTuple(args, "y*ii:lin2lin",
1151 &view, &size, &size2))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001152 return NULL;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001153
1154 if (!audioop_check_parameters(view.len, size))
1155 goto exit;
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001156 if (!audioop_check_size(size2))
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001157 goto exit;
Jack Jansena90805f1993-02-17 14:29:28 +00001158
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001159 if (view.len/size > PY_SSIZE_T_MAX/size2) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001160 PyErr_SetString(PyExc_MemoryError,
1161 "not enough memory for output buffer");
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001162 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001163 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001164 rv = PyBytes_FromStringAndSize(NULL, (view.len/size)*size2);
1165 if (rv == NULL)
1166 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001167 ncp = (unsigned char *)PyBytes_AsString(rv);
1168
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001169 for (i = j = 0; i < view.len; i += size, j += size2) {
1170 int val = GETSAMPLE32(size, view.buf, i);
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001171 SETSAMPLE32(size2, ncp, j, val);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001172 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001173 exit:
1174 PyBuffer_Release(&view);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001175 return rv;
Jack Jansena90805f1993-02-17 14:29:28 +00001176}
1177
Guido van Rossumb24c9ea1997-05-20 15:59:35 +00001178static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00001179gcd(int a, int b)
Guido van Rossumb24c9ea1997-05-20 15:59:35 +00001180{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001181 while (b > 0) {
1182 int tmp = a % b;
1183 a = b;
1184 b = tmp;
1185 }
1186 return a;
Guido van Rossumb24c9ea1997-05-20 15:59:35 +00001187}
1188
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001189static PyObject *
Peter Schneider-Kamp8bc8f0d2000-07-10 17:15:07 +00001190audioop_ratecv(PyObject *self, PyObject *args)
Roger E. Massec905fff1997-01-17 18:12:04 +00001191{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001192 Py_buffer view;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001193 char *cp, *ncp;
Mark Dickinson81fece22010-05-11 13:34:35 +00001194 Py_ssize_t len;
1195 int size, nchannels, inrate, outrate, weightA, weightB;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001196 int chan, d, *prev_i, *cur_i, cur_o;
1197 PyObject *state, *samps, *str, *rv = NULL;
1198 int bytes_per_frame;
Guido van Rossum1851a671997-02-14 16:14:03 +00001199
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001200 weightA = 1;
1201 weightB = 0;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001202 if (!PyArg_ParseTuple(args, "y*iiiiO|ii:ratecv", &view, &size,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001203 &nchannels, &inrate, &outrate, &state,
1204 &weightA, &weightB))
1205 return NULL;
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001206 if (!audioop_check_size(size))
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001207 goto exit2;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001208 if (nchannels < 1) {
1209 PyErr_SetString(AudioopError, "# of channels should be >= 1");
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001210 goto exit2;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001211 }
Mark Dickinsonc04ddff2012-10-06 18:04:49 +01001212 if (size > INT_MAX / nchannels) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001213 /* This overflow test is rigorously correct because
1214 both multiplicands are >= 1. Use the argument names
1215 from the docs for the error msg. */
1216 PyErr_SetString(PyExc_OverflowError,
1217 "width * nchannels too big for a C int");
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001218 goto exit2;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001219 }
Mark Dickinsonc04ddff2012-10-06 18:04:49 +01001220 bytes_per_frame = size * nchannels;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001221 if (weightA < 1 || weightB < 0) {
1222 PyErr_SetString(AudioopError,
1223 "weightA should be >= 1, weightB should be >= 0");
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001224 goto exit2;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001225 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001226 if (view.len % bytes_per_frame != 0) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001227 PyErr_SetString(AudioopError, "not a whole number of frames");
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001228 goto exit2;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001229 }
1230 if (inrate <= 0 || outrate <= 0) {
1231 PyErr_SetString(AudioopError, "sampling rate not > 0");
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001232 goto exit2;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001233 }
1234 /* divide inrate and outrate by their greatest common divisor */
1235 d = gcd(inrate, outrate);
1236 inrate /= d;
1237 outrate /= d;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001238 /* divide weightA and weightB by their greatest common divisor */
1239 d = gcd(weightA, weightB);
1240 weightA /= d;
1241 weightA /= d;
Guido van Rossumb24c9ea1997-05-20 15:59:35 +00001242
Mark Dickinson85eacea2010-05-10 16:27:45 +00001243 if ((size_t)nchannels > PY_SIZE_MAX/sizeof(int)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001244 PyErr_SetString(PyExc_MemoryError,
1245 "not enough memory for output buffer");
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001246 goto exit2;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001247 }
Victor Stinnerb6404912013-07-07 16:21:41 +02001248 prev_i = (int *) PyMem_Malloc(nchannels * sizeof(int));
1249 cur_i = (int *) PyMem_Malloc(nchannels * sizeof(int));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001250 if (prev_i == NULL || cur_i == NULL) {
1251 (void) PyErr_NoMemory();
1252 goto exit;
1253 }
1254
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001255 len = view.len / bytes_per_frame; /* # of frames */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001256
1257 if (state == Py_None) {
1258 d = -outrate;
1259 for (chan = 0; chan < nchannels; chan++)
1260 prev_i[chan] = cur_i[chan] = 0;
1261 }
1262 else {
1263 if (!PyArg_ParseTuple(state,
1264 "iO!;audioop.ratecv: illegal state argument",
1265 &d, &PyTuple_Type, &samps))
1266 goto exit;
1267 if (PyTuple_Size(samps) != nchannels) {
1268 PyErr_SetString(AudioopError,
1269 "illegal state argument");
1270 goto exit;
Amaury Forgeot d'Arc9c74b142008-06-18 00:47:36 +00001271 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001272 for (chan = 0; chan < nchannels; chan++) {
1273 if (!PyArg_ParseTuple(PyTuple_GetItem(samps, chan),
1274 "ii:ratecv", &prev_i[chan],
1275 &cur_i[chan]))
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001276 goto exit;
1277 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001278 }
Guido van Rossum1851a671997-02-14 16:14:03 +00001279
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001280 /* str <- Space for the output buffer. */
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001281 if (len == 0)
1282 str = PyBytes_FromStringAndSize(NULL, 0);
1283 else {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001284 /* There are len input frames, so we need (mathematically)
1285 ceiling(len*outrate/inrate) output frames, and each frame
1286 requires bytes_per_frame bytes. Computing this
1287 without spurious overflow is the challenge; we can
Mark Dickinson393b97a2010-05-11 13:09:58 +00001288 settle for a reasonable upper bound, though, in this
1289 case ceiling(len/inrate) * outrate. */
1290
1291 /* compute ceiling(len/inrate) without overflow */
Mark Dickinson81fece22010-05-11 13:34:35 +00001292 Py_ssize_t q = len > 0 ? 1 + (len - 1) / inrate : 0;
1293 if (outrate > PY_SSIZE_T_MAX / q / bytes_per_frame)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001294 str = NULL;
1295 else
Mark Dickinson393b97a2010-05-11 13:09:58 +00001296 str = PyBytes_FromStringAndSize(NULL,
1297 q * outrate * bytes_per_frame);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001298 }
1299 if (str == NULL) {
1300 PyErr_SetString(PyExc_MemoryError,
1301 "not enough memory for output buffer");
1302 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001303 }
1304 ncp = PyBytes_AsString(str);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001305 cp = view.buf;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001306
1307 for (;;) {
1308 while (d < 0) {
1309 if (len == 0) {
1310 samps = PyTuple_New(nchannels);
1311 if (samps == NULL)
1312 goto exit;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001313 for (chan = 0; chan < nchannels; chan++)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001314 PyTuple_SetItem(samps, chan,
1315 Py_BuildValue("(ii)",
1316 prev_i[chan],
1317 cur_i[chan]));
1318 if (PyErr_Occurred())
1319 goto exit;
1320 /* We have checked before that the length
1321 * of the string fits into int. */
Mark Dickinson81fece22010-05-11 13:34:35 +00001322 len = (Py_ssize_t)(ncp - PyBytes_AsString(str));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001323 rv = PyBytes_FromStringAndSize
1324 (PyBytes_AsString(str), len);
1325 Py_DECREF(str);
1326 str = rv;
1327 if (str == NULL)
1328 goto exit;
1329 rv = Py_BuildValue("(O(iO))", str, d, samps);
1330 Py_DECREF(samps);
1331 Py_DECREF(str);
1332 goto exit; /* return rv */
1333 }
1334 for (chan = 0; chan < nchannels; chan++) {
1335 prev_i[chan] = cur_i[chan];
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001336 cur_i[chan] = GETSAMPLE32(size, cp, 0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001337 cp += size;
1338 /* implements a simple digital filter */
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001339 cur_i[chan] = (int)(
1340 ((double)weightA * (double)cur_i[chan] +
1341 (double)weightB * (double)prev_i[chan]) /
1342 ((double)weightA + (double)weightB));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001343 }
1344 len--;
1345 d += outrate;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001346 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001347 while (d >= 0) {
1348 for (chan = 0; chan < nchannels; chan++) {
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001349 cur_o = (int)(((double)prev_i[chan] * (double)d +
1350 (double)cur_i[chan] * (double)(outrate - d)) /
1351 (double)outrate);
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001352 SETSAMPLE32(size, ncp, 0, cur_o);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001353 ncp += size;
1354 }
1355 d -= inrate;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001356 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001357 }
Guido van Rossum65bb3281999-09-07 14:24:05 +00001358 exit:
Victor Stinnerb6404912013-07-07 16:21:41 +02001359 PyMem_Free(prev_i);
1360 PyMem_Free(cur_i);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001361 exit2:
1362 PyBuffer_Release(&view);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001363 return rv;
Roger E. Massec905fff1997-01-17 18:12:04 +00001364}
Guido van Rossum1851a671997-02-14 16:14:03 +00001365
Roger E. Massec905fff1997-01-17 18:12:04 +00001366static PyObject *
Peter Schneider-Kamp8bc8f0d2000-07-10 17:15:07 +00001367audioop_lin2ulaw(PyObject *self, PyObject *args)
Guido van Rossumb66efa01992-06-01 16:01:24 +00001368{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001369 Py_buffer view;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001370 unsigned 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:lin2ulaw",
1376 &view, &size))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001377 return NULL;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001378
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001379 if (!audioop_check_parameters(view.len, size))
1380 goto exit;
1381
1382 rv = PyBytes_FromStringAndSize(NULL, view.len/size);
1383 if (rv == NULL)
1384 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001385 ncp = (unsigned char *)PyBytes_AsString(rv);
1386
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001387 for (i = 0; i < view.len; i += size) {
1388 int val = GETSAMPLE32(size, view.buf, i);
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001389 *ncp++ = st_14linear2ulaw(val >> 18);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001390 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001391 exit:
1392 PyBuffer_Release(&view);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001393 return rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001394}
1395
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001396static PyObject *
Peter Schneider-Kamp8bc8f0d2000-07-10 17:15:07 +00001397audioop_ulaw2lin(PyObject *self, PyObject *args)
Guido van Rossumb66efa01992-06-01 16:01:24 +00001398{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001399 Py_buffer view;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001400 unsigned char *cp;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001401 signed char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001402 Py_ssize_t i;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001403 int size;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001404 PyObject *rv = NULL;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001405
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001406 if (!PyArg_ParseTuple(args, "y*i:ulaw2lin",
1407 &view, &size))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001408 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001409
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001410 if (!audioop_check_size(size))
1411 goto exit;
1412
1413 if (view.len > PY_SSIZE_T_MAX/size) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001414 PyErr_SetString(PyExc_MemoryError,
1415 "not enough memory for output buffer");
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001416 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001417 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001418 rv = PyBytes_FromStringAndSize(NULL, view.len*size);
1419 if (rv == NULL)
1420 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001421 ncp = (signed char *)PyBytes_AsString(rv);
1422
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001423 cp = view.buf;
1424 for (i = 0; i < view.len*size; i += size) {
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001425 int val = st_ulaw2linear16(*cp++) << 16;
1426 SETSAMPLE32(size, ncp, i, val);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001427 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001428 exit:
1429 PyBuffer_Release(&view);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001430 return rv;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001431}
1432
1433static PyObject *
1434audioop_lin2alaw(PyObject *self, PyObject *args)
1435{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001436 Py_buffer view;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001437 unsigned char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001438 Py_ssize_t i;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001439 int size;
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:lin2alaw",
1443 &view, &size))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001444 return NULL;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001445
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001446 if (!audioop_check_parameters(view.len, size))
1447 goto exit;
1448
1449 rv = PyBytes_FromStringAndSize(NULL, view.len/size);
1450 if (rv == NULL)
1451 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001452 ncp = (unsigned char *)PyBytes_AsString(rv);
1453
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001454 for (i = 0; i < view.len; i += size) {
1455 int val = GETSAMPLE32(size, view.buf, i);
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001456 *ncp++ = st_linear2alaw(val >> 19);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001457 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001458 exit:
1459 PyBuffer_Release(&view);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001460 return rv;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001461}
1462
1463static PyObject *
1464audioop_alaw2lin(PyObject *self, PyObject *args)
1465{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001466 Py_buffer view;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001467 unsigned char *cp;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001468 signed char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001469 Py_ssize_t i;
Mark Dickinson81fece22010-05-11 13:34:35 +00001470 int size, val;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001471 PyObject *rv = NULL;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001472
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001473 if (!PyArg_ParseTuple(args, "y*i:alaw2lin",
1474 &view, &size))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001475 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001476
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001477 if (!audioop_check_size(size))
1478 goto exit;
1479
1480 if (view.len > PY_SSIZE_T_MAX/size) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001481 PyErr_SetString(PyExc_MemoryError,
1482 "not enough memory for output buffer");
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001483 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001484 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001485 rv = PyBytes_FromStringAndSize(NULL, view.len*size);
1486 if (rv == NULL)
1487 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001488 ncp = (signed char *)PyBytes_AsString(rv);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001489 cp = view.buf;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001490
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001491 for (i = 0; i < view.len*size; i += size) {
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001492 val = st_alaw2linear16(*cp++) << 16;
1493 SETSAMPLE32(size, ncp, i, val);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001494 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001495 exit:
1496 PyBuffer_Release(&view);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001497 return rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001498}
1499
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001500static PyObject *
Peter Schneider-Kamp8bc8f0d2000-07-10 17:15:07 +00001501audioop_lin2adpcm(PyObject *self, PyObject *args)
Guido van Rossumb64e6351992-07-06 14:21:56 +00001502{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001503 Py_buffer view;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001504 signed char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001505 Py_ssize_t i;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001506 int size, step, valpred, delta,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001507 index, sign, vpdiff, diff;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001508 PyObject *rv = NULL, *state, *str;
Mark Dickinson81fece22010-05-11 13:34:35 +00001509 int outputbuffer = 0, bufferstep;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001510
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001511 if (!PyArg_ParseTuple(args, "y*iO:lin2adpcm",
1512 &view, &size, &state))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001513 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001514
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001515 if (!audioop_check_parameters(view.len, size))
1516 goto exit;
1517
1518 str = PyBytes_FromStringAndSize(NULL, view.len/(size*2));
1519 if (str == NULL)
1520 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001521 ncp = (signed char *)PyBytes_AsString(str);
1522
1523 /* Decode state, should have (value, step) */
1524 if ( state == Py_None ) {
1525 /* First time, it seems. Set defaults */
1526 valpred = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001527 index = 0;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001528 } else if (!PyArg_ParseTuple(state, "ii", &valpred, &index))
1529 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001530
1531 step = stepsizeTable[index];
1532 bufferstep = 1;
1533
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001534 for (i = 0; i < view.len; i += size) {
1535 int val = GETSAMPLE32(size, view.buf, i) >> 16;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001536
1537 /* Step 1 - compute difference with previous value */
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001538 if (val < valpred) {
1539 diff = valpred - val;
1540 sign = 8;
1541 }
1542 else {
1543 diff = val - valpred;
1544 sign = 0;
1545 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001546
1547 /* Step 2 - Divide and clamp */
1548 /* Note:
1549 ** This code *approximately* computes:
1550 ** delta = diff*4/step;
1551 ** vpdiff = (delta+0.5)*step/4;
1552 ** but in shift step bits are dropped. The net result of this
1553 ** is that even if you have fast mul/div hardware you cannot
1554 ** put it to good use since the fixup would be too expensive.
1555 */
1556 delta = 0;
1557 vpdiff = (step >> 3);
1558
1559 if ( diff >= step ) {
1560 delta = 4;
1561 diff -= step;
1562 vpdiff += step;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001563 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001564 step >>= 1;
1565 if ( diff >= step ) {
1566 delta |= 2;
1567 diff -= step;
1568 vpdiff += step;
1569 }
1570 step >>= 1;
1571 if ( diff >= step ) {
1572 delta |= 1;
1573 vpdiff += step;
1574 }
Jack Jansendd8a6ea1993-02-17 14:21:09 +00001575
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001576 /* Step 3 - Update previous value */
1577 if ( sign )
1578 valpred -= vpdiff;
1579 else
1580 valpred += vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001581
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001582 /* Step 4 - Clamp previous value to 16 bits */
1583 if ( valpred > 32767 )
1584 valpred = 32767;
1585 else if ( valpred < -32768 )
1586 valpred = -32768;
1587
1588 /* Step 5 - Assemble value, update index and step values */
1589 delta |= sign;
1590
1591 index += indexTable[delta];
1592 if ( index < 0 ) index = 0;
1593 if ( index > 88 ) index = 88;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001594 step = stepsizeTable[index];
Guido van Rossumb64e6351992-07-06 14:21:56 +00001595
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001596 /* Step 6 - Output value */
1597 if ( bufferstep ) {
1598 outputbuffer = (delta << 4) & 0xf0;
1599 } else {
1600 *ncp++ = (delta & 0x0f) | outputbuffer;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001601 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001602 bufferstep = !bufferstep;
1603 }
1604 rv = Py_BuildValue("(O(ii))", str, valpred, index);
1605 Py_DECREF(str);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001606 exit:
1607 PyBuffer_Release(&view);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001608 return rv;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001609}
1610
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001611static PyObject *
Peter Schneider-Kamp8bc8f0d2000-07-10 17:15:07 +00001612audioop_adpcm2lin(PyObject *self, PyObject *args)
Guido van Rossumb64e6351992-07-06 14:21:56 +00001613{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001614 Py_buffer view;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001615 signed char *cp;
1616 signed char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001617 Py_ssize_t i, outlen;
Mark Dickinson81fece22010-05-11 13:34:35 +00001618 int size, valpred, step, delta, index, sign, vpdiff;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001619 PyObject *rv = NULL, *str, *state;
Mark Dickinson81fece22010-05-11 13:34:35 +00001620 int inputbuffer = 0, bufferstep;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001621
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001622 if (!PyArg_ParseTuple(args, "y*iO:adpcm2lin",
1623 &view, &size, &state))
1624 return NULL;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001625
Antoine Pitrou75ff65e2012-01-28 22:01:59 +01001626 if (!audioop_check_size(size))
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001627 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001628
1629 /* Decode state, should have (value, step) */
1630 if ( state == Py_None ) {
1631 /* First time, it seems. Set defaults */
1632 valpred = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001633 index = 0;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001634 } else if (!PyArg_ParseTuple(state, "ii", &valpred, &index))
1635 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001636
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001637 if (view.len > (PY_SSIZE_T_MAX/2)/size) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001638 PyErr_SetString(PyExc_MemoryError,
1639 "not enough memory for output buffer");
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001640 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001641 }
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001642 outlen = view.len*size*2;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001643 str = PyBytes_FromStringAndSize(NULL, outlen);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001644 if (str == NULL)
1645 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001646 ncp = (signed char *)PyBytes_AsString(str);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001647 cp = view.buf;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001648
1649 step = stepsizeTable[index];
1650 bufferstep = 0;
1651
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001652 for (i = 0; i < outlen; i += size) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001653 /* Step 1 - get the delta value and compute next index */
1654 if ( bufferstep ) {
1655 delta = inputbuffer & 0xf;
1656 } else {
1657 inputbuffer = *cp++;
1658 delta = (inputbuffer >> 4) & 0xf;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001659 }
Guido van Rossumb64e6351992-07-06 14:21:56 +00001660
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001661 bufferstep = !bufferstep;
1662
1663 /* Step 2 - Find new index value (for later) */
1664 index += indexTable[delta];
1665 if ( index < 0 ) index = 0;
1666 if ( index > 88 ) index = 88;
1667
1668 /* Step 3 - Separate sign and magnitude */
1669 sign = delta & 8;
1670 delta = delta & 7;
1671
1672 /* Step 4 - Compute difference and new predicted value */
1673 /*
1674 ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
1675 ** in adpcm_coder.
1676 */
1677 vpdiff = step >> 3;
1678 if ( delta & 4 ) vpdiff += step;
1679 if ( delta & 2 ) vpdiff += step>>1;
1680 if ( delta & 1 ) vpdiff += step>>2;
1681
1682 if ( sign )
1683 valpred -= vpdiff;
1684 else
1685 valpred += vpdiff;
1686
1687 /* Step 5 - clamp output value */
1688 if ( valpred > 32767 )
1689 valpred = 32767;
1690 else if ( valpred < -32768 )
1691 valpred = -32768;
1692
1693 /* Step 6 - Update step value */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001694 step = stepsizeTable[index];
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001695
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001696 /* Step 6 - Output value */
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001697 SETSAMPLE32(size, ncp, i, valpred << 16);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001698 }
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001699
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001700 rv = Py_BuildValue("(O(ii))", str, valpred, index);
1701 Py_DECREF(str);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001702 exit:
1703 PyBuffer_Release(&view);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001704 return rv;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001705}
1706
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001707static PyMethodDef audioop_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001708 { "max", audioop_max, METH_VARARGS },
1709 { "minmax", audioop_minmax, METH_VARARGS },
1710 { "avg", audioop_avg, METH_VARARGS },
1711 { "maxpp", audioop_maxpp, METH_VARARGS },
1712 { "avgpp", audioop_avgpp, METH_VARARGS },
1713 { "rms", audioop_rms, METH_VARARGS },
1714 { "findfit", audioop_findfit, METH_VARARGS },
1715 { "findmax", audioop_findmax, METH_VARARGS },
1716 { "findfactor", audioop_findfactor, METH_VARARGS },
1717 { "cross", audioop_cross, METH_VARARGS },
1718 { "mul", audioop_mul, METH_VARARGS },
1719 { "add", audioop_add, METH_VARARGS },
1720 { "bias", audioop_bias, METH_VARARGS },
1721 { "ulaw2lin", audioop_ulaw2lin, METH_VARARGS },
1722 { "lin2ulaw", audioop_lin2ulaw, METH_VARARGS },
1723 { "alaw2lin", audioop_alaw2lin, METH_VARARGS },
1724 { "lin2alaw", audioop_lin2alaw, METH_VARARGS },
1725 { "lin2lin", audioop_lin2lin, METH_VARARGS },
1726 { "adpcm2lin", audioop_adpcm2lin, METH_VARARGS },
1727 { "lin2adpcm", audioop_lin2adpcm, METH_VARARGS },
1728 { "tomono", audioop_tomono, METH_VARARGS },
1729 { "tostereo", audioop_tostereo, METH_VARARGS },
1730 { "getsample", audioop_getsample, METH_VARARGS },
1731 { "reverse", audioop_reverse, METH_VARARGS },
Serhiy Storchaka3062c9a2013-11-23 22:26:01 +02001732 { "byteswap", audioop_byteswap, METH_VARARGS },
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001733 { "ratecv", audioop_ratecv, METH_VARARGS },
1734 { 0, 0 }
Guido van Rossumb66efa01992-06-01 16:01:24 +00001735};
1736
Martin v. Löwis1a214512008-06-11 05:26:20 +00001737
1738static struct PyModuleDef audioopmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001739 PyModuleDef_HEAD_INIT,
1740 "audioop",
1741 NULL,
1742 -1,
1743 audioop_methods,
1744 NULL,
1745 NULL,
1746 NULL,
1747 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00001748};
1749
Mark Hammondfe51c6d2002-08-02 02:27:13 +00001750PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00001751PyInit_audioop(void)
Guido van Rossumb66efa01992-06-01 16:01:24 +00001752{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001753 PyObject *m, *d;
1754 m = PyModule_Create(&audioopmodule);
1755 if (m == NULL)
1756 return NULL;
1757 d = PyModule_GetDict(m);
1758 if (d == NULL)
1759 return NULL;
1760 AudioopError = PyErr_NewException("audioop.error", NULL, NULL);
1761 if (AudioopError != NULL)
1762 PyDict_SetItemString(d,"error",AudioopError);
1763 return m;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001764}