blob: 2a5d805c053c7d5565cbaefb564b441eeab173e7 [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"
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00007
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02008static const int maxvals[] = {0, 0x7F, 0x7FFF, 0x7FFFFF, 0x7FFFFFFF};
Tim Goldenfa6ab0f2013-10-31 10:25:47 +00009/* -1 trick is needed on Windows to support -0x80000000 without a warning */
10static const int minvals[] = {0, -0x80, -0x8000, -0x800000, -0x7FFFFFFF-1};
Serhiy Storchaka01ad6222013-02-09 11:10:53 +020011static const unsigned int masks[] = {0, 0xFF, 0xFFFF, 0xFFFFFF, 0xFFFFFFFF};
12
13static int
14fbound(double val, double minval, double maxval)
15{
Victor Stinner45e4efb2018-06-06 15:50:50 +020016 if (val > maxval) {
Serhiy Storchaka01ad6222013-02-09 11:10:53 +020017 val = maxval;
Victor Stinner45e4efb2018-06-06 15:50:50 +020018 }
19 else if (val < minval + 1.0) {
Serhiy Storchaka01ad6222013-02-09 11:10:53 +020020 val = minval;
Victor Stinner45e4efb2018-06-06 15:50:50 +020021 }
22
23 /* Round towards minus infinity (-inf) */
24 val = floor(val);
25
26 /* Cast double to integer: round towards zero */
Victor Stinnerf2b9a342013-05-07 23:49:15 +020027 return (int)val;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +020028}
29
30
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000031/* Code shamelessly stolen from sox, 12.17.7, g711.c
Guido van Rossumb66efa01992-06-01 16:01:24 +000032** (c) Craig Reese, Joe Campbell and Jeff Poskanzer 1989 */
33
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000034/* From g711.c:
35 *
36 * December 30, 1994:
37 * Functions linear2alaw, linear2ulaw have been updated to correctly
38 * convert unquantized 16 bit values.
39 * Tables for direct u- to A-law and A- to u-law conversions have been
40 * corrected.
41 * Borge Lindberg, Center for PersonKommunikation, Aalborg University.
42 * bli@cpk.auc.dk
43 *
44 */
Guido van Rossumb66efa01992-06-01 16:01:24 +000045#define BIAS 0x84 /* define the add-in bias for 16 bit samples */
46#define CLIP 32635
Martin Panter4c359642016-05-08 13:53:41 +000047#define SIGN_BIT (0x80) /* Sign bit for an A-law byte. */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000048#define QUANT_MASK (0xf) /* Quantization field mask. */
49#define SEG_SHIFT (4) /* Left shift for segment number. */
50#define SEG_MASK (0x70) /* Segment field mask. */
Guido van Rossumb66efa01992-06-01 16:01:24 +000051
Benjamin Petersonbb0b0d92016-09-08 15:08:02 -070052static const int16_t seg_aend[8] = {
Serhiy Storchaka2d06e842015-12-25 19:53:18 +020053 0x1F, 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF
54};
Benjamin Petersonbb0b0d92016-09-08 15:08:02 -070055static const int16_t seg_uend[8] = {
Serhiy Storchaka2d06e842015-12-25 19:53:18 +020056 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF
57};
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000058
Benjamin Petersonbb0b0d92016-09-08 15:08:02 -070059static int16_t
60search(int16_t val, const int16_t *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
Benjamin Petersonbb0b0d92016-09-08 15:08:02 -070073static const int16_t _st_ulaw2linear16[256] = {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000074 -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
Martin Panter7462b6492015-11-02 03:37:02 +0000115 * stored in an unsigned char. This function should only be called with
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000116 * 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
Benjamin Petersonbb0b0d92016-09-08 15:08:02 -0700146st_14linear2ulaw(int16_t pcm_val) /* 2's complement (14-bit range) */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000147{
Benjamin Petersonbb0b0d92016-09-08 15:08:02 -0700148 int16_t mask;
149 int16_t seg;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000150 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
Benjamin Petersonbb0b0d92016-09-08 15:08:02 -0700179static const int16_t _st_alaw2linear16[256] = {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000180 -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/*
Martin Panter4c359642016-05-08 13:53:41 +0000220 * linear2alaw() accepts a 13-bit signed integer and encodes it as A-law data
Martin Panter7462b6492015-11-02 03:37:02 +0000221 * stored in an unsigned char. This function should only be called with
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000222 * 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
Benjamin Petersonbb0b0d92016-09-08 15:08:02 -0700240st_linear2alaw(int16_t pcm_val) /* 2's complement (13-bit range) */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000241{
Benjamin Petersonbb0b0d92016-09-08 15:08:02 -0700242 int16_t mask;
Serhiy Storchaka8be17402016-09-11 14:48:16 +0300243 int16_t seg;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000244 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 */
Serhiy Storchaka2d06e842015-12-25 19:53:18 +0200273static const 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
Serhiy Storchaka2d06e842015-12-25 19:53:18 +0200278static const 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))
Serhiy Storchaka8be17402016-09-11 14:48:16 +0300297#define GETINT16(cp, i) GETINTX(int16_t, (cp), (i))
Benjamin Peterson9b3d7702016-09-06 13:24:00 -0700298#define GETINT32(cp, i) GETINTX(int32_t, (cp), (i))
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300299
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))
Serhiy Storchaka8be17402016-09-11 14:48:16 +0300314#define SETINT16(cp, i, val) SETINTX(int16_t, (cp), (i), (val))
Benjamin Peterson9b3d7702016-09-06 13:24:00 -0700315#define SETINT32(cp, i, val) SETINTX(int32_t, (cp), (i), (val))
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300316
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
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400367static PyModuleDef audioopmodule;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000368
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400369typedef struct {
370 PyObject *AudioopError;
Hai Shi41fbf862020-03-12 00:49:11 +0800371} audioop_state;
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400372
Hai Shi41fbf862020-03-12 00:49:11 +0800373static inline audioop_state *
374get_audioop_state(PyObject *module)
375{
376 void *state = PyModule_GetState(module);
377 assert(state != NULL);
378 return (audioop_state *)state;
379}
Guido van Rossumb66efa01992-06-01 16:01:24 +0000380
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000381static int
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400382audioop_check_size(PyObject *module, int size)
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000383{
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300384 if (size < 1 || size > 4) {
Hai Shi41fbf862020-03-12 00:49:11 +0800385 PyErr_SetString(get_audioop_state(module)->AudioopError,
386 "Size should be 1, 2, 3 or 4");
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000387 return 0;
388 }
389 else
390 return 1;
391}
392
393static int
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400394audioop_check_parameters(PyObject *module, Py_ssize_t len, int size)
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000395{
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400396 if (!audioop_check_size(module, size))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000397 return 0;
398 if (len % size != 0) {
Hai Shi41fbf862020-03-12 00:49:11 +0800399 PyErr_SetString(get_audioop_state(module)->AudioopError,
400 "not a whole number of frames");
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000401 return 0;
402 }
403 return 1;
404}
405
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200406/*[clinic input]
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200407module audioop
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200408[clinic start generated code]*/
Serhiy Storchaka1009bf12015-04-03 23:53:51 +0300409/*[clinic end generated code: output=da39a3ee5e6b4b0d input=8fa8f6611be3591a]*/
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200410
411/*[clinic input]
412audioop.getsample
413
414 fragment: Py_buffer
415 width: int
416 index: Py_ssize_t
417 /
418
419Return the value of sample index from the fragment.
420[clinic start generated code]*/
421
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000422static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300423audioop_getsample_impl(PyObject *module, Py_buffer *fragment, int width,
Larry Hastings89964c42015-04-14 18:07:59 -0400424 Py_ssize_t index)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300425/*[clinic end generated code: output=8fe1b1775134f39a input=88edbe2871393549]*/
Guido van Rossumb66efa01992-06-01 16:01:24 +0000426{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200427 int val;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000428
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400429 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000430 return NULL;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200431 if (index < 0 || index >= fragment->len/width) {
Hai Shi41fbf862020-03-12 00:49:11 +0800432 PyErr_SetString(get_audioop_state(module)->AudioopError,
433 "Index out of range");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200434 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000435 }
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200436 val = GETRAWSAMPLE(width, fragment->buf, index*width);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200437 return PyLong_FromLong(val);
Guido van Rossumb66efa01992-06-01 16:01:24 +0000438}
439
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200440/*[clinic input]
441audioop.max
442
443 fragment: Py_buffer
444 width: int
445 /
446
447Return the maximum of the absolute value of all samples in a fragment.
448[clinic start generated code]*/
449
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000450static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300451audioop_max_impl(PyObject *module, Py_buffer *fragment, int width)
452/*[clinic end generated code: output=e6c5952714f1c3f0 input=32bea5ea0ac8c223]*/
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000453{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200454 Py_ssize_t i;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200455 unsigned int absval, max = 0;
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000456
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400457 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000458 return NULL;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200459 for (i = 0; i < fragment->len; i += width) {
460 int val = GETRAWSAMPLE(width, fragment->buf, i);
Martin Panter6fb90902016-07-19 03:05:42 +0000461 /* Cast to unsigned before negating. Unsigned overflow is well-
462 defined, but signed overflow is not. */
Steve Dowera4391912016-09-06 19:09:15 -0700463 if (val < 0) absval = (unsigned int)-(int64_t)val;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200464 else absval = val;
465 if (absval > max) max = absval;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000466 }
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200467 return PyLong_FromUnsignedLong(max);
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000468}
469
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200470/*[clinic input]
471audioop.minmax
472
473 fragment: Py_buffer
474 width: int
475 /
476
477Return the minimum and maximum values of all samples in the sound fragment.
478[clinic start generated code]*/
479
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000480static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300481audioop_minmax_impl(PyObject *module, Py_buffer *fragment, int width)
482/*[clinic end generated code: output=473fda66b15c836e input=89848e9b927a0696]*/
Sjoerd Mullendera1426131994-09-06 16:19:33 +0000483{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200484 Py_ssize_t i;
Tim Goldenfa6ab0f2013-10-31 10:25:47 +0000485 /* -1 trick below is needed on Windows to support -0x80000000 without
486 a warning */
487 int min = 0x7fffffff, max = -0x7FFFFFFF-1;
Sjoerd Mullendera1426131994-09-06 16:19:33 +0000488
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400489 if (!audioop_check_parameters(module, fragment->len, width))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000490 return NULL;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200491 for (i = 0; i < fragment->len; i += width) {
492 int val = GETRAWSAMPLE(width, fragment->buf, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000493 if (val > max) max = val;
494 if (val < min) min = val;
495 }
496 return Py_BuildValue("(ii)", min, max);
Sjoerd Mullendera1426131994-09-06 16:19:33 +0000497}
498
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200499/*[clinic input]
500audioop.avg
501
502 fragment: Py_buffer
503 width: int
504 /
505
506Return the average over all samples in the fragment.
507[clinic start generated code]*/
508
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000509static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300510audioop_avg_impl(PyObject *module, Py_buffer *fragment, int width)
511/*[clinic end generated code: output=4410a4c12c3586e6 input=1114493c7611334d]*/
Guido van Rossumb66efa01992-06-01 16:01:24 +0000512{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200513 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200514 int avg;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300515 double sum = 0.0;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000516
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400517 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000518 return NULL;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200519 for (i = 0; i < fragment->len; i += width)
520 sum += GETRAWSAMPLE(width, fragment->buf, i);
521 if (fragment->len == 0)
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300522 avg = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000523 else
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200524 avg = (int)floor(sum / (double)(fragment->len/width));
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300525 return PyLong_FromLong(avg);
Guido van Rossumb66efa01992-06-01 16:01:24 +0000526}
527
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200528/*[clinic input]
529audioop.rms
530
531 fragment: Py_buffer
532 width: int
533 /
534
535Return the root-mean-square of the fragment, i.e. sqrt(sum(S_i^2)/n).
536[clinic start generated code]*/
537
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000538static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300539audioop_rms_impl(PyObject *module, Py_buffer *fragment, int width)
540/*[clinic end generated code: output=1e7871c826445698 input=4cc57c6c94219d78]*/
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000541{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200542 Py_ssize_t i;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200543 unsigned int res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000544 double sum_squares = 0.0;
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000545
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400546 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000547 return NULL;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200548 for (i = 0; i < fragment->len; i += width) {
549 double val = GETRAWSAMPLE(width, fragment->buf, i);
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300550 sum_squares += val*val;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000551 }
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200552 if (fragment->len == 0)
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200553 res = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000554 else
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200555 res = (unsigned int)sqrt(sum_squares / (double)(fragment->len/width));
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200556 return PyLong_FromUnsignedLong(res);
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000557}
558
Serhiy Storchaka8be17402016-09-11 14:48:16 +0300559static double _sum2(const int16_t *a, const int16_t *b, Py_ssize_t len)
Jack Jansena90805f1993-02-17 14:29:28 +0000560{
Mark Dickinson81fece22010-05-11 13:34:35 +0000561 Py_ssize_t i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000562 double sum = 0.0;
Jack Jansena90805f1993-02-17 14:29:28 +0000563
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000564 for( i=0; i<len; i++) {
565 sum = sum + (double)a[i]*(double)b[i];
566 }
567 return sum;
Jack Jansena90805f1993-02-17 14:29:28 +0000568}
569
570/*
571** Findfit tries to locate a sample within another sample. Its main use
572** is in echo-cancellation (to find the feedback of the output signal in
573** the input signal).
574** The method used is as follows:
575**
576** let R be the reference signal (length n) and A the input signal (length N)
577** with N > n, and let all sums be over i from 0 to n-1.
578**
579** Now, for each j in {0..N-n} we compute a factor fj so that -fj*R matches A
580** as good as possible, i.e. sum( (A[j+i]+fj*R[i])^2 ) is minimal. This
581** equation gives fj = sum( A[j+i]R[i] ) / sum(R[i]^2).
582**
583** Next, we compute the relative distance between the original signal and
584** the modified signal and minimize that over j:
585** vj = sum( (A[j+i]-fj*R[i])^2 ) / sum( A[j+i]^2 ) =>
586** vj = ( sum(A[j+i]^2)*sum(R[i]^2) - sum(A[j+i]R[i])^2 ) / sum( A[j+i]^2 )
587**
588** In the code variables correspond as follows:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000589** cp1 A
590** cp2 R
591** len1 N
592** len2 n
593** aj_m1 A[j-1]
594** aj_lm1 A[j+n-1]
595** sum_ri_2 sum(R[i]^2)
596** sum_aij_2 sum(A[i+j]^2)
597** sum_aij_ri sum(A[i+j]R[i])
Jack Jansena90805f1993-02-17 14:29:28 +0000598**
599** sum_ri is calculated once, sum_aij_2 is updated each step and sum_aij_ri
600** is completely recalculated each step.
601*/
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200602/*[clinic input]
603audioop.findfit
604
605 fragment: Py_buffer
606 reference: Py_buffer
607 /
608
609Try to match reference as well as possible to a portion of fragment.
610[clinic start generated code]*/
611
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000612static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300613audioop_findfit_impl(PyObject *module, Py_buffer *fragment,
Larry Hastings89964c42015-04-14 18:07:59 -0400614 Py_buffer *reference)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300615/*[clinic end generated code: output=5752306d83cbbada input=62c305605e183c9a]*/
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000616{
Serhiy Storchaka8be17402016-09-11 14:48:16 +0300617 const int16_t *cp1, *cp2;
Mark Dickinson81fece22010-05-11 13:34:35 +0000618 Py_ssize_t len1, len2;
619 Py_ssize_t j, best_j;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000620 double aj_m1, aj_lm1;
621 double sum_ri_2, sum_aij_2, sum_aij_ri, result, best_result, factor;
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000622
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200623 if (fragment->len & 1 || reference->len & 1) {
Hai Shi41fbf862020-03-12 00:49:11 +0800624 PyErr_SetString(get_audioop_state(module)->AudioopError,
625 "Strings should be even-sized");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200626 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000627 }
Serhiy Storchaka8be17402016-09-11 14:48:16 +0300628 cp1 = (const int16_t *)fragment->buf;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200629 len1 = fragment->len >> 1;
Serhiy Storchaka8be17402016-09-11 14:48:16 +0300630 cp2 = (const int16_t *)reference->buf;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200631 len2 = reference->len >> 1;
Jack Jansena90805f1993-02-17 14:29:28 +0000632
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200633 if (len1 < len2) {
Hai Shi41fbf862020-03-12 00:49:11 +0800634 PyErr_SetString(get_audioop_state(module)->AudioopError,
635 "First sample should be longer");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200636 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000637 }
638 sum_ri_2 = _sum2(cp2, cp2, len2);
639 sum_aij_2 = _sum2(cp1, cp1, len2);
640 sum_aij_ri = _sum2(cp1, cp2, len2);
Jack Jansena90805f1993-02-17 14:29:28 +0000641
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000642 result = (sum_ri_2*sum_aij_2 - sum_aij_ri*sum_aij_ri) / sum_aij_2;
Jack Jansena90805f1993-02-17 14:29:28 +0000643
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000644 best_result = result;
645 best_j = 0;
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000646
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000647 for ( j=1; j<=len1-len2; j++) {
648 aj_m1 = (double)cp1[j-1];
649 aj_lm1 = (double)cp1[j+len2-1];
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000650
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000651 sum_aij_2 = sum_aij_2 + aj_lm1*aj_lm1 - aj_m1*aj_m1;
652 sum_aij_ri = _sum2(cp1+j, cp2, len2);
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000653
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000654 result = (sum_ri_2*sum_aij_2 - sum_aij_ri*sum_aij_ri)
655 / sum_aij_2;
656
657 if ( result < best_result ) {
658 best_result = result;
659 best_j = j;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000660 }
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000661
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000662 }
663
664 factor = _sum2(cp1+best_j, cp2, len2) / sum_ri_2;
665
Mark Dickinson81fece22010-05-11 13:34:35 +0000666 return Py_BuildValue("(nf)", best_j, factor);
Jack Jansena90805f1993-02-17 14:29:28 +0000667}
668
669/*
670** findfactor finds a factor f so that the energy in A-fB is minimal.
671** See the comment for findfit for details.
672*/
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200673/*[clinic input]
674audioop.findfactor
675
676 fragment: Py_buffer
677 reference: Py_buffer
678 /
679
680Return a factor F such that rms(add(fragment, mul(reference, -F))) is minimal.
681[clinic start generated code]*/
682
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000683static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300684audioop_findfactor_impl(PyObject *module, Py_buffer *fragment,
Larry Hastings89964c42015-04-14 18:07:59 -0400685 Py_buffer *reference)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300686/*[clinic end generated code: output=14ea95652c1afcf8 input=816680301d012b21]*/
Jack Jansena90805f1993-02-17 14:29:28 +0000687{
Serhiy Storchaka8be17402016-09-11 14:48:16 +0300688 const int16_t *cp1, *cp2;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200689 Py_ssize_t len;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000690 double sum_ri_2, sum_aij_ri, result;
Jack Jansena90805f1993-02-17 14:29:28 +0000691
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200692 if (fragment->len & 1 || reference->len & 1) {
Hai Shi41fbf862020-03-12 00:49:11 +0800693 PyErr_SetString(get_audioop_state(module)->AudioopError,
694 "Strings should be even-sized");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200695 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000696 }
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200697 if (fragment->len != reference->len) {
Hai Shi41fbf862020-03-12 00:49:11 +0800698 PyErr_SetString(get_audioop_state(module)->AudioopError,
699 "Samples should be same size");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200700 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000701 }
Serhiy Storchaka8be17402016-09-11 14:48:16 +0300702 cp1 = (const int16_t *)fragment->buf;
703 cp2 = (const int16_t *)reference->buf;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200704 len = fragment->len >> 1;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200705 sum_ri_2 = _sum2(cp2, cp2, len);
706 sum_aij_ri = _sum2(cp1, cp2, len);
Jack Jansena90805f1993-02-17 14:29:28 +0000707
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000708 result = sum_aij_ri / sum_ri_2;
Jack Jansena90805f1993-02-17 14:29:28 +0000709
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000710 return PyFloat_FromDouble(result);
Jack Jansena90805f1993-02-17 14:29:28 +0000711}
712
713/*
714** findmax returns the index of the n-sized segment of the input sample
715** that contains the most energy.
716*/
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200717/*[clinic input]
718audioop.findmax
719
720 fragment: Py_buffer
721 length: Py_ssize_t
722 /
723
724Search fragment for a slice of specified number of samples with maximum energy.
725[clinic start generated code]*/
726
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000727static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300728audioop_findmax_impl(PyObject *module, Py_buffer *fragment,
Larry Hastings89964c42015-04-14 18:07:59 -0400729 Py_ssize_t length)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300730/*[clinic end generated code: output=f008128233523040 input=2f304801ed42383c]*/
Jack Jansena90805f1993-02-17 14:29:28 +0000731{
Serhiy Storchaka8be17402016-09-11 14:48:16 +0300732 const int16_t *cp1;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200733 Py_ssize_t len1;
Mark Dickinson81fece22010-05-11 13:34:35 +0000734 Py_ssize_t j, best_j;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000735 double aj_m1, aj_lm1;
736 double result, best_result;
Jack Jansena90805f1993-02-17 14:29:28 +0000737
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200738 if (fragment->len & 1) {
Hai Shi41fbf862020-03-12 00:49:11 +0800739 PyErr_SetString(get_audioop_state(module)->AudioopError,
740 "Strings should be even-sized");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200741 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000742 }
Serhiy Storchaka8be17402016-09-11 14:48:16 +0300743 cp1 = (const int16_t *)fragment->buf;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200744 len1 = fragment->len >> 1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000745
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200746 if (length < 0 || len1 < length) {
Hai Shi41fbf862020-03-12 00:49:11 +0800747 PyErr_SetString(get_audioop_state(module)->AudioopError,
748 "Input sample should be longer");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200749 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000750 }
751
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200752 result = _sum2(cp1, cp1, length);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000753
754 best_result = result;
755 best_j = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000756
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200757 for ( j=1; j<=len1-length; j++) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000758 aj_m1 = (double)cp1[j-1];
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200759 aj_lm1 = (double)cp1[j+length-1];
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000760
761 result = result + aj_lm1*aj_lm1 - aj_m1*aj_m1;
762
763 if ( result > best_result ) {
764 best_result = result;
765 best_j = j;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000766 }
Jack Jansena90805f1993-02-17 14:29:28 +0000767
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000768 }
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000769
Mark Dickinson81fece22010-05-11 13:34:35 +0000770 return PyLong_FromSsize_t(best_j);
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000771}
772
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200773/*[clinic input]
774audioop.avgpp
775
776 fragment: Py_buffer
777 width: int
778 /
779
780Return the average peak-peak value over all samples in the fragment.
781[clinic start generated code]*/
782
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000783static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300784audioop_avgpp_impl(PyObject *module, Py_buffer *fragment, int width)
785/*[clinic end generated code: output=269596b0d5ae0b2b input=0b3cceeae420a7d9]*/
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000786{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200787 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200788 int prevval, prevextremevalid = 0, prevextreme = 0;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200789 double sum = 0.0;
790 unsigned int avg;
791 int diff, prevdiff, nextreme = 0;
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000792
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400793 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000794 return NULL;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200795 if (fragment->len <= width)
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200796 return PyLong_FromLong(0);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200797 prevval = GETRAWSAMPLE(width, fragment->buf, 0);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200798 prevdiff = 17; /* Anything != 0, 1 */
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200799 for (i = width; i < fragment->len; i += width) {
800 int val = GETRAWSAMPLE(width, fragment->buf, i);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200801 if (val != prevval) {
802 diff = val < prevval;
803 if (prevdiff == !diff) {
804 /* Derivative changed sign. Compute difference to last
805 ** extreme value and remember.
806 */
807 if (prevextremevalid) {
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300808 if (prevval < prevextreme)
809 sum += (double)((unsigned int)prevextreme -
810 (unsigned int)prevval);
811 else
812 sum += (double)((unsigned int)prevval -
813 (unsigned int)prevextreme);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200814 nextreme++;
815 }
816 prevextremevalid = 1;
817 prevextreme = prevval;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000818 }
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200819 prevval = val;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000820 prevdiff = diff;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200821 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000822 }
823 if ( nextreme == 0 )
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200824 avg = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000825 else
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200826 avg = (unsigned int)(sum / (double)nextreme);
827 return PyLong_FromUnsignedLong(avg);
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000828}
829
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200830/*[clinic input]
831audioop.maxpp
832
833 fragment: Py_buffer
834 width: int
835 /
836
837Return the maximum peak-peak value in the sound fragment.
838[clinic start generated code]*/
839
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000840static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300841audioop_maxpp_impl(PyObject *module, Py_buffer *fragment, int width)
842/*[clinic end generated code: output=5b918ed5dbbdb978 input=671a13e1518f80a1]*/
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000843{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200844 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200845 int prevval, prevextremevalid = 0, prevextreme = 0;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200846 unsigned int max = 0, extremediff;
847 int diff, prevdiff;
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000848
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400849 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000850 return NULL;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200851 if (fragment->len <= width)
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200852 return PyLong_FromLong(0);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200853 prevval = GETRAWSAMPLE(width, fragment->buf, 0);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200854 prevdiff = 17; /* Anything != 0, 1 */
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200855 for (i = width; i < fragment->len; i += width) {
856 int val = GETRAWSAMPLE(width, fragment->buf, i);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200857 if (val != prevval) {
858 diff = val < prevval;
859 if (prevdiff == !diff) {
860 /* Derivative changed sign. Compute difference to
861 ** last extreme value and remember.
862 */
863 if (prevextremevalid) {
864 if (prevval < prevextreme)
865 extremediff = (unsigned int)prevextreme -
866 (unsigned int)prevval;
867 else
868 extremediff = (unsigned int)prevval -
869 (unsigned int)prevextreme;
870 if ( extremediff > max )
871 max = extremediff;
872 }
873 prevextremevalid = 1;
874 prevextreme = prevval;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000875 }
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200876 prevval = val;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000877 prevdiff = diff;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200878 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000879 }
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200880 return PyLong_FromUnsignedLong(max);
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000881}
882
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200883/*[clinic input]
884audioop.cross
885
886 fragment: Py_buffer
887 width: int
888 /
889
890Return the number of zero crossings in the fragment passed as an argument.
891[clinic start generated code]*/
892
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000893static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300894audioop_cross_impl(PyObject *module, Py_buffer *fragment, int width)
895/*[clinic end generated code: output=5938dcdd74a1f431 input=b1b3f15b83f6b41a]*/
Guido van Rossumb66efa01992-06-01 16:01:24 +0000896{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200897 Py_ssize_t i;
Mark Dickinson81fece22010-05-11 13:34:35 +0000898 int prevval;
899 Py_ssize_t ncross;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000900
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400901 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000902 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000903 ncross = -1;
904 prevval = 17; /* Anything <> 0,1 */
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200905 for (i = 0; i < fragment->len; i += width) {
906 int val = GETRAWSAMPLE(width, fragment->buf, i) < 0;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300907 if (val != prevval) ncross++;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000908 prevval = val;
909 }
Mark Dickinson81fece22010-05-11 13:34:35 +0000910 return PyLong_FromSsize_t(ncross);
Guido van Rossumb66efa01992-06-01 16:01:24 +0000911}
912
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200913/*[clinic input]
914audioop.mul
915
916 fragment: Py_buffer
917 width: int
918 factor: double
919 /
920
921Return a fragment that has all samples in the original fragment multiplied by the floating-point value factor.
922[clinic start generated code]*/
923
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000924static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300925audioop_mul_impl(PyObject *module, Py_buffer *fragment, int width,
Larry Hastings89964c42015-04-14 18:07:59 -0400926 double factor)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300927/*[clinic end generated code: output=6cd48fe796da0ea4 input=c726667baa157d3c]*/
Guido van Rossumb66efa01992-06-01 16:01:24 +0000928{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200929 signed char *ncp;
930 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200931 double maxval, minval;
932 PyObject *rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000933
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400934 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000935 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000936
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200937 maxval = (double) maxvals[width];
938 minval = (double) minvals[width];
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000939
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200940 rv = PyBytes_FromStringAndSize(NULL, fragment->len);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200941 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200942 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000943 ncp = (signed char *)PyBytes_AsString(rv);
944
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200945 for (i = 0; i < fragment->len; i += width) {
946 double val = GETRAWSAMPLE(width, fragment->buf, i);
Victor Stinner45e4efb2018-06-06 15:50:50 +0200947 int ival = fbound(val * factor, minval, maxval);
948 SETRAWSAMPLE(width, ncp, i, ival);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000949 }
950 return rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000951}
952
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200953/*[clinic input]
954audioop.tomono
955
956 fragment: Py_buffer
957 width: int
958 lfactor: double
959 rfactor: double
960 /
961
962Convert a stereo fragment to a mono fragment.
963[clinic start generated code]*/
964
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000965static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300966audioop_tomono_impl(PyObject *module, Py_buffer *fragment, int width,
Larry Hastings89964c42015-04-14 18:07:59 -0400967 double lfactor, double rfactor)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300968/*[clinic end generated code: output=235c8277216d4e4e input=c4ec949b3f4dddfa]*/
Guido van Rossumb66efa01992-06-01 16:01:24 +0000969{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000970 signed char *cp, *ncp;
Mark Dickinson81fece22010-05-11 13:34:35 +0000971 Py_ssize_t len, i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200972 double maxval, minval;
973 PyObject *rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000974
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200975 cp = fragment->buf;
976 len = fragment->len;
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400977 if (!audioop_check_parameters(module, len, width))
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200978 return NULL;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200979 if (((len / width) & 1) != 0) {
Hai Shi41fbf862020-03-12 00:49:11 +0800980 PyErr_SetString(get_audioop_state(module)->AudioopError,
981 "not a whole number of frames");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200982 return NULL;
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000983 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000984
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200985 maxval = (double) maxvals[width];
986 minval = (double) minvals[width];
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000987
988 rv = PyBytes_FromStringAndSize(NULL, len/2);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200989 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200990 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000991 ncp = (signed char *)PyBytes_AsString(rv);
992
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200993 for (i = 0; i < len; i += width*2) {
994 double val1 = GETRAWSAMPLE(width, cp, i);
995 double val2 = GETRAWSAMPLE(width, cp, i + width);
Victor Stinner45e4efb2018-06-06 15:50:50 +0200996 double val = val1 * lfactor + val2 * rfactor;
997 int ival = fbound(val, minval, maxval);
998 SETRAWSAMPLE(width, ncp, i/2, ival);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000999 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001000 return rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001001}
1002
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001003/*[clinic input]
1004audioop.tostereo
1005
1006 fragment: Py_buffer
1007 width: int
1008 lfactor: double
1009 rfactor: double
1010 /
1011
1012Generate a stereo fragment from a mono fragment.
1013[clinic start generated code]*/
1014
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001015static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001016audioop_tostereo_impl(PyObject *module, Py_buffer *fragment, int width,
Larry Hastings89964c42015-04-14 18:07:59 -04001017 double lfactor, double rfactor)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001018/*[clinic end generated code: output=046f13defa5f1595 input=27b6395ebfdff37a]*/
Guido van Rossumb66efa01992-06-01 16:01:24 +00001019{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001020 signed char *ncp;
1021 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001022 double maxval, minval;
1023 PyObject *rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001024
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001025 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001026 return NULL;
Amaury Forgeot d'Arc9c74b142008-06-18 00:47:36 +00001027
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001028 maxval = (double) maxvals[width];
1029 minval = (double) minvals[width];
Guido van Rossumb66efa01992-06-01 16:01:24 +00001030
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001031 if (fragment->len > PY_SSIZE_T_MAX/2) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001032 PyErr_SetString(PyExc_MemoryError,
1033 "not enough memory for output buffer");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001034 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001035 }
Guido van Rossumb66efa01992-06-01 16:01:24 +00001036
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001037 rv = PyBytes_FromStringAndSize(NULL, fragment->len*2);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001038 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001039 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001040 ncp = (signed char *)PyBytes_AsString(rv);
Guido van Rossumb66efa01992-06-01 16:01:24 +00001041
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001042 for (i = 0; i < fragment->len; i += width) {
1043 double val = GETRAWSAMPLE(width, fragment->buf, i);
Victor Stinner45e4efb2018-06-06 15:50:50 +02001044 int val1 = fbound(val * lfactor, minval, maxval);
1045 int val2 = fbound(val * rfactor, minval, maxval);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001046 SETRAWSAMPLE(width, ncp, i*2, val1);
1047 SETRAWSAMPLE(width, ncp, i*2 + width, val2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001048 }
1049 return rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001050}
1051
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001052/*[clinic input]
1053audioop.add
1054
1055 fragment1: Py_buffer
1056 fragment2: Py_buffer
1057 width: int
1058 /
1059
1060Return a fragment which is the addition of the two samples passed as parameters.
1061[clinic start generated code]*/
1062
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001063static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001064audioop_add_impl(PyObject *module, Py_buffer *fragment1,
Larry Hastings89964c42015-04-14 18:07:59 -04001065 Py_buffer *fragment2, int width)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001066/*[clinic end generated code: output=60140af4d1aab6f2 input=4a8d4bae4c1605c7]*/
Guido van Rossumb66efa01992-06-01 16:01:24 +00001067{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001068 signed char *ncp;
1069 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001070 int minval, maxval, newval;
1071 PyObject *rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001072
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001073 if (!audioop_check_parameters(module, fragment1->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001074 return NULL;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001075 if (fragment1->len != fragment2->len) {
Hai Shi41fbf862020-03-12 00:49:11 +08001076 PyErr_SetString(get_audioop_state(module)->AudioopError,
1077 "Lengths should be the same");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001078 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001079 }
Guido van Rossum1851a671997-02-14 16:14:03 +00001080
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001081 maxval = maxvals[width];
1082 minval = minvals[width];
Guido van Rossum1851a671997-02-14 16:14:03 +00001083
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001084 rv = PyBytes_FromStringAndSize(NULL, fragment1->len);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001085 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001086 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001087 ncp = (signed char *)PyBytes_AsString(rv);
Guido van Rossumb66efa01992-06-01 16:01:24 +00001088
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001089 for (i = 0; i < fragment1->len; i += width) {
1090 int val1 = GETRAWSAMPLE(width, fragment1->buf, i);
1091 int val2 = GETRAWSAMPLE(width, fragment2->buf, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001092
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001093 if (width < 4) {
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001094 newval = val1 + val2;
1095 /* truncate in case of overflow */
1096 if (newval > maxval)
1097 newval = maxval;
1098 else if (newval < minval)
1099 newval = minval;
1100 }
1101 else {
1102 double fval = (double)val1 + (double)val2;
1103 /* truncate in case of overflow */
Victor Stinner45e4efb2018-06-06 15:50:50 +02001104 newval = fbound(fval, minval, maxval);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001105 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001106
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001107 SETRAWSAMPLE(width, ncp, i, newval);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001108 }
1109 return rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001110}
1111
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001112/*[clinic input]
1113audioop.bias
1114
1115 fragment: Py_buffer
1116 width: int
1117 bias: int
1118 /
1119
1120Return a fragment that is the original fragment with a bias added to each sample.
1121[clinic start generated code]*/
1122
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001123static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001124audioop_bias_impl(PyObject *module, Py_buffer *fragment, int width, int bias)
1125/*[clinic end generated code: output=6e0aa8f68f045093 input=2b5cce5c3bb4838c]*/
Guido van Rossumb66efa01992-06-01 16:01:24 +00001126{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001127 signed char *ncp;
1128 Py_ssize_t i;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001129 unsigned int val = 0, mask;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001130 PyObject *rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001131
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001132 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001133 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001134
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001135 rv = PyBytes_FromStringAndSize(NULL, fragment->len);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001136 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001137 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001138 ncp = (signed char *)PyBytes_AsString(rv);
1139
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001140 mask = masks[width];
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001141
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001142 for (i = 0; i < fragment->len; i += width) {
1143 if (width == 1)
1144 val = GETINTX(unsigned char, fragment->buf, i);
1145 else if (width == 2)
Serhiy Storchaka8be17402016-09-11 14:48:16 +03001146 val = GETINTX(uint16_t, fragment->buf, i);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001147 else if (width == 3)
1148 val = ((unsigned int)GETINT24(fragment->buf, i)) & 0xffffffu;
Serhiy Storchakace82eb22013-10-20 09:42:26 +03001149 else {
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001150 assert(width == 4);
Benjamin Peterson9b3d7702016-09-06 13:24:00 -07001151 val = GETINTX(uint32_t, fragment->buf, i);
Serhiy Storchakace82eb22013-10-20 09:42:26 +03001152 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001153
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001154 val += (unsigned int)bias;
1155 /* wrap around in case of overflow */
1156 val &= mask;
1157
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001158 if (width == 1)
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001159 SETINTX(unsigned char, ncp, i, val);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001160 else if (width == 2)
Serhiy Storchaka8be17402016-09-11 14:48:16 +03001161 SETINTX(uint16_t, ncp, i, val);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001162 else if (width == 3)
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001163 SETINT24(ncp, i, (int)val);
Serhiy Storchakace82eb22013-10-20 09:42:26 +03001164 else {
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001165 assert(width == 4);
Benjamin Peterson9b3d7702016-09-06 13:24:00 -07001166 SETINTX(uint32_t, ncp, i, val);
Serhiy Storchakace82eb22013-10-20 09:42:26 +03001167 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001168 }
1169 return rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001170}
1171
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001172/*[clinic input]
1173audioop.reverse
1174
1175 fragment: Py_buffer
1176 width: int
1177 /
1178
1179Reverse the samples in a fragment and returns the modified fragment.
1180[clinic start generated code]*/
1181
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001182static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001183audioop_reverse_impl(PyObject *module, Py_buffer *fragment, int width)
1184/*[clinic end generated code: output=b44135698418da14 input=668f890cf9f9d225]*/
Jack Jansen337b20e1993-02-23 13:39:57 +00001185{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001186 unsigned char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001187 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001188 PyObject *rv;
Jack Jansen337b20e1993-02-23 13:39:57 +00001189
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001190 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001191 return NULL;
Jack Jansen337b20e1993-02-23 13:39:57 +00001192
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001193 rv = PyBytes_FromStringAndSize(NULL, fragment->len);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001194 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001195 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001196 ncp = (unsigned char *)PyBytes_AsString(rv);
1197
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001198 for (i = 0; i < fragment->len; i += width) {
1199 int val = GETRAWSAMPLE(width, fragment->buf, i);
1200 SETRAWSAMPLE(width, ncp, fragment->len - i - width, val);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001201 }
1202 return rv;
Jack Jansen337b20e1993-02-23 13:39:57 +00001203}
1204
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001205/*[clinic input]
1206audioop.byteswap
1207
1208 fragment: Py_buffer
1209 width: int
1210 /
1211
1212Convert big-endian samples to little-endian and vice versa.
1213[clinic start generated code]*/
1214
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001215static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001216audioop_byteswap_impl(PyObject *module, Py_buffer *fragment, int width)
1217/*[clinic end generated code: output=50838a9e4b87cd4d input=fae7611ceffa5c82]*/
Serhiy Storchaka3062c9a2013-11-23 22:26:01 +02001218{
Serhiy Storchaka3062c9a2013-11-23 22:26:01 +02001219 unsigned char *ncp;
1220 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001221 PyObject *rv;
Serhiy Storchaka3062c9a2013-11-23 22:26:01 +02001222
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001223 if (!audioop_check_parameters(module, fragment->len, width))
Serhiy Storchaka3062c9a2013-11-23 22:26:01 +02001224 return NULL;
1225
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001226 rv = PyBytes_FromStringAndSize(NULL, fragment->len);
Serhiy Storchaka3062c9a2013-11-23 22:26:01 +02001227 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001228 return NULL;
Serhiy Storchaka3062c9a2013-11-23 22:26:01 +02001229 ncp = (unsigned char *)PyBytes_AsString(rv);
1230
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001231 for (i = 0; i < fragment->len; i += width) {
Serhiy Storchaka3062c9a2013-11-23 22:26:01 +02001232 int j;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001233 for (j = 0; j < width; j++)
1234 ncp[i + width - 1 - j] = ((unsigned char *)fragment->buf)[i + j];
Serhiy Storchaka3062c9a2013-11-23 22:26:01 +02001235 }
Serhiy Storchaka3062c9a2013-11-23 22:26:01 +02001236 return rv;
1237}
1238
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001239/*[clinic input]
1240audioop.lin2lin
1241
1242 fragment: Py_buffer
1243 width: int
1244 newwidth: int
1245 /
1246
1247Convert samples between 1-, 2-, 3- and 4-byte formats.
1248[clinic start generated code]*/
1249
Serhiy Storchaka3062c9a2013-11-23 22:26:01 +02001250static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001251audioop_lin2lin_impl(PyObject *module, Py_buffer *fragment, int width,
Larry Hastings89964c42015-04-14 18:07:59 -04001252 int newwidth)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001253/*[clinic end generated code: output=17b14109248f1d99 input=5ce08c8aa2f24d96]*/
Jack Jansena90805f1993-02-17 14:29:28 +00001254{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001255 unsigned char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001256 Py_ssize_t i, j;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001257 PyObject *rv;
Jack Jansena90805f1993-02-17 14:29:28 +00001258
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001259 if (!audioop_check_parameters(module, fragment->len, width))
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001260 return NULL;
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001261 if (!audioop_check_size(module, newwidth))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001262 return NULL;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001263
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001264 if (fragment->len/width > PY_SSIZE_T_MAX/newwidth) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001265 PyErr_SetString(PyExc_MemoryError,
1266 "not enough memory for output buffer");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001267 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001268 }
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001269 rv = PyBytes_FromStringAndSize(NULL, (fragment->len/width)*newwidth);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001270 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001271 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001272 ncp = (unsigned char *)PyBytes_AsString(rv);
1273
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001274 for (i = j = 0; i < fragment->len; i += width, j += newwidth) {
1275 int val = GETSAMPLE32(width, fragment->buf, i);
1276 SETSAMPLE32(newwidth, ncp, j, val);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001277 }
1278 return rv;
Jack Jansena90805f1993-02-17 14:29:28 +00001279}
1280
Guido van Rossumb24c9ea1997-05-20 15:59:35 +00001281static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00001282gcd(int a, int b)
Guido van Rossumb24c9ea1997-05-20 15:59:35 +00001283{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001284 while (b > 0) {
1285 int tmp = a % b;
1286 a = b;
1287 b = tmp;
1288 }
1289 return a;
Guido van Rossumb24c9ea1997-05-20 15:59:35 +00001290}
1291
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001292/*[clinic input]
1293audioop.ratecv
1294
1295 fragment: Py_buffer
1296 width: int
1297 nchannels: int
1298 inrate: int
1299 outrate: int
1300 state: object
1301 weightA: int = 1
1302 weightB: int = 0
1303 /
1304
1305Convert the frame rate of the input fragment.
1306[clinic start generated code]*/
1307
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001308static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001309audioop_ratecv_impl(PyObject *module, Py_buffer *fragment, int width,
Larry Hastings89964c42015-04-14 18:07:59 -04001310 int nchannels, int inrate, int outrate, PyObject *state,
1311 int weightA, int weightB)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001312/*[clinic end generated code: output=624038e843243139 input=aff3acdc94476191]*/
Roger E. Massec905fff1997-01-17 18:12:04 +00001313{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001314 char *cp, *ncp;
Mark Dickinson81fece22010-05-11 13:34:35 +00001315 Py_ssize_t len;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001316 int chan, d, *prev_i, *cur_i, cur_o;
Oren Milman1d1d3e92017-08-20 18:35:36 +03001317 PyObject *samps, *str, *rv = NULL, *channel;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001318 int bytes_per_frame;
Guido van Rossum1851a671997-02-14 16:14:03 +00001319
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001320 if (!audioop_check_size(module, width))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001321 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001322 if (nchannels < 1) {
Hai Shi41fbf862020-03-12 00:49:11 +08001323 PyErr_SetString(get_audioop_state(module)->AudioopError,
1324 "# of channels should be >= 1");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001325 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001326 }
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001327 if (width > INT_MAX / nchannels) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001328 /* This overflow test is rigorously correct because
1329 both multiplicands are >= 1. Use the argument names
1330 from the docs for the error msg. */
1331 PyErr_SetString(PyExc_OverflowError,
1332 "width * nchannels too big for a C int");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001333 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001334 }
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001335 bytes_per_frame = width * nchannels;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001336 if (weightA < 1 || weightB < 0) {
Hai Shi41fbf862020-03-12 00:49:11 +08001337 PyErr_SetString(get_audioop_state(module)->AudioopError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001338 "weightA should be >= 1, weightB should be >= 0");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001339 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001340 }
Christian Heimesc4ab9a42014-01-27 01:12:00 +01001341 assert(fragment->len >= 0);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001342 if (fragment->len % bytes_per_frame != 0) {
Hai Shi41fbf862020-03-12 00:49:11 +08001343 PyErr_SetString(get_audioop_state(module)->AudioopError,
1344 "not a whole number of frames");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001345 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001346 }
1347 if (inrate <= 0 || outrate <= 0) {
Hai Shi41fbf862020-03-12 00:49:11 +08001348 PyErr_SetString(get_audioop_state(module)->AudioopError,
1349 "sampling rate not > 0");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001350 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001351 }
1352 /* divide inrate and outrate by their greatest common divisor */
1353 d = gcd(inrate, outrate);
1354 inrate /= d;
1355 outrate /= d;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001356 /* divide weightA and weightB by their greatest common divisor */
1357 d = gcd(weightA, weightB);
1358 weightA /= d;
Serhiy Storchaka50451eb2015-05-30 00:53:26 +03001359 weightB /= d;
Guido van Rossumb24c9ea1997-05-20 15:59:35 +00001360
Benjamin Peterson2f8bfef2016-09-07 09:26:18 -07001361 if ((size_t)nchannels > SIZE_MAX/sizeof(int)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001362 PyErr_SetString(PyExc_MemoryError,
1363 "not enough memory for output buffer");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001364 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001365 }
Victor Stinnerb6404912013-07-07 16:21:41 +02001366 prev_i = (int *) PyMem_Malloc(nchannels * sizeof(int));
1367 cur_i = (int *) PyMem_Malloc(nchannels * sizeof(int));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001368 if (prev_i == NULL || cur_i == NULL) {
1369 (void) PyErr_NoMemory();
1370 goto exit;
1371 }
1372
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001373 len = fragment->len / bytes_per_frame; /* # of frames */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001374
1375 if (state == Py_None) {
1376 d = -outrate;
1377 for (chan = 0; chan < nchannels; chan++)
1378 prev_i[chan] = cur_i[chan] = 0;
1379 }
1380 else {
Oren Milman1d1d3e92017-08-20 18:35:36 +03001381 if (!PyTuple_Check(state)) {
1382 PyErr_SetString(PyExc_TypeError, "state must be a tuple or None");
1383 goto exit;
1384 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001385 if (!PyArg_ParseTuple(state,
Oren Milman1d1d3e92017-08-20 18:35:36 +03001386 "iO!;ratecv(): illegal state argument",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001387 &d, &PyTuple_Type, &samps))
1388 goto exit;
1389 if (PyTuple_Size(samps) != nchannels) {
Hai Shi41fbf862020-03-12 00:49:11 +08001390 PyErr_SetString(get_audioop_state(module)->AudioopError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001391 "illegal state argument");
1392 goto exit;
Amaury Forgeot d'Arc9c74b142008-06-18 00:47:36 +00001393 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001394 for (chan = 0; chan < nchannels; chan++) {
Oren Milman1d1d3e92017-08-20 18:35:36 +03001395 channel = PyTuple_GetItem(samps, chan);
1396 if (!PyTuple_Check(channel)) {
1397 PyErr_SetString(PyExc_TypeError,
1398 "ratecv(): illegal state argument");
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001399 goto exit;
Oren Milman1d1d3e92017-08-20 18:35:36 +03001400 }
1401 if (!PyArg_ParseTuple(channel,
1402 "ii;ratecv(): illegal state argument",
1403 &prev_i[chan], &cur_i[chan]))
1404 {
1405 goto exit;
1406 }
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001407 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001408 }
Guido van Rossum1851a671997-02-14 16:14:03 +00001409
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001410 /* str <- Space for the output buffer. */
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001411 if (len == 0)
1412 str = PyBytes_FromStringAndSize(NULL, 0);
1413 else {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001414 /* There are len input frames, so we need (mathematically)
1415 ceiling(len*outrate/inrate) output frames, and each frame
1416 requires bytes_per_frame bytes. Computing this
1417 without spurious overflow is the challenge; we can
Mark Dickinson393b97a2010-05-11 13:09:58 +00001418 settle for a reasonable upper bound, though, in this
1419 case ceiling(len/inrate) * outrate. */
1420
1421 /* compute ceiling(len/inrate) without overflow */
Christian Heimesc4ab9a42014-01-27 01:12:00 +01001422 Py_ssize_t q = 1 + (len - 1) / inrate;
Mark Dickinson81fece22010-05-11 13:34:35 +00001423 if (outrate > PY_SSIZE_T_MAX / q / bytes_per_frame)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001424 str = NULL;
1425 else
Mark Dickinson393b97a2010-05-11 13:09:58 +00001426 str = PyBytes_FromStringAndSize(NULL,
1427 q * outrate * bytes_per_frame);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001428 }
1429 if (str == NULL) {
1430 PyErr_SetString(PyExc_MemoryError,
1431 "not enough memory for output buffer");
1432 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001433 }
1434 ncp = PyBytes_AsString(str);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001435 cp = fragment->buf;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001436
1437 for (;;) {
1438 while (d < 0) {
1439 if (len == 0) {
1440 samps = PyTuple_New(nchannels);
1441 if (samps == NULL)
1442 goto exit;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001443 for (chan = 0; chan < nchannels; chan++)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001444 PyTuple_SetItem(samps, chan,
1445 Py_BuildValue("(ii)",
1446 prev_i[chan],
1447 cur_i[chan]));
1448 if (PyErr_Occurred())
1449 goto exit;
1450 /* We have checked before that the length
1451 * of the string fits into int. */
Mark Dickinson81fece22010-05-11 13:34:35 +00001452 len = (Py_ssize_t)(ncp - PyBytes_AsString(str));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001453 rv = PyBytes_FromStringAndSize
1454 (PyBytes_AsString(str), len);
1455 Py_DECREF(str);
1456 str = rv;
1457 if (str == NULL)
1458 goto exit;
1459 rv = Py_BuildValue("(O(iO))", str, d, samps);
1460 Py_DECREF(samps);
1461 Py_DECREF(str);
1462 goto exit; /* return rv */
1463 }
1464 for (chan = 0; chan < nchannels; chan++) {
1465 prev_i[chan] = cur_i[chan];
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001466 cur_i[chan] = GETSAMPLE32(width, cp, 0);
1467 cp += width;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001468 /* implements a simple digital filter */
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001469 cur_i[chan] = (int)(
1470 ((double)weightA * (double)cur_i[chan] +
1471 (double)weightB * (double)prev_i[chan]) /
1472 ((double)weightA + (double)weightB));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001473 }
1474 len--;
1475 d += outrate;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001476 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001477 while (d >= 0) {
1478 for (chan = 0; chan < nchannels; chan++) {
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001479 cur_o = (int)(((double)prev_i[chan] * (double)d +
1480 (double)cur_i[chan] * (double)(outrate - d)) /
1481 (double)outrate);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001482 SETSAMPLE32(width, ncp, 0, cur_o);
1483 ncp += width;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001484 }
1485 d -= inrate;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001486 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001487 }
Guido van Rossum65bb3281999-09-07 14:24:05 +00001488 exit:
Victor Stinnerb6404912013-07-07 16:21:41 +02001489 PyMem_Free(prev_i);
1490 PyMem_Free(cur_i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001491 return rv;
Roger E. Massec905fff1997-01-17 18:12:04 +00001492}
Guido van Rossum1851a671997-02-14 16:14:03 +00001493
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001494/*[clinic input]
1495audioop.lin2ulaw
1496
1497 fragment: Py_buffer
1498 width: int
1499 /
1500
1501Convert samples in the audio fragment to u-LAW encoding.
1502[clinic start generated code]*/
1503
Roger E. Massec905fff1997-01-17 18:12:04 +00001504static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001505audioop_lin2ulaw_impl(PyObject *module, Py_buffer *fragment, int width)
1506/*[clinic end generated code: output=14fb62b16fe8ea8e input=2450d1b870b6bac2]*/
Guido van Rossumb66efa01992-06-01 16:01:24 +00001507{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001508 unsigned char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001509 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001510 PyObject *rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001511
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001512 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001513 return NULL;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001514
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001515 rv = PyBytes_FromStringAndSize(NULL, fragment->len/width);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001516 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001517 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001518 ncp = (unsigned char *)PyBytes_AsString(rv);
1519
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001520 for (i = 0; i < fragment->len; i += width) {
1521 int val = GETSAMPLE32(width, fragment->buf, i);
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001522 *ncp++ = st_14linear2ulaw(val >> 18);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001523 }
1524 return rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001525}
1526
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001527/*[clinic input]
1528audioop.ulaw2lin
1529
1530 fragment: Py_buffer
1531 width: int
1532 /
1533
1534Convert sound fragments in u-LAW encoding to linearly encoded sound fragments.
1535[clinic start generated code]*/
1536
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001537static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001538audioop_ulaw2lin_impl(PyObject *module, Py_buffer *fragment, int width)
1539/*[clinic end generated code: output=378356b047521ba2 input=45d53ddce5be7d06]*/
Guido van Rossumb66efa01992-06-01 16:01:24 +00001540{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001541 unsigned char *cp;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001542 signed char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001543 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001544 PyObject *rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001545
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001546 if (!audioop_check_size(module, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001547 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001548
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001549 if (fragment->len > PY_SSIZE_T_MAX/width) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001550 PyErr_SetString(PyExc_MemoryError,
1551 "not enough memory for output buffer");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001552 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001553 }
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001554 rv = PyBytes_FromStringAndSize(NULL, fragment->len*width);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001555 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001556 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001557 ncp = (signed char *)PyBytes_AsString(rv);
1558
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001559 cp = fragment->buf;
1560 for (i = 0; i < fragment->len*width; i += width) {
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001561 int val = st_ulaw2linear16(*cp++) << 16;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001562 SETSAMPLE32(width, ncp, i, val);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001563 }
1564 return rv;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001565}
1566
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001567/*[clinic input]
1568audioop.lin2alaw
1569
1570 fragment: Py_buffer
1571 width: int
1572 /
1573
1574Convert samples in the audio fragment to a-LAW encoding.
1575[clinic start generated code]*/
1576
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001577static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001578audioop_lin2alaw_impl(PyObject *module, Py_buffer *fragment, int width)
1579/*[clinic end generated code: output=d076f130121a82f0 input=ffb1ef8bb39da945]*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001580{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001581 unsigned char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001582 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001583 PyObject *rv;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001584
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001585 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001586 return NULL;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001587
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001588 rv = PyBytes_FromStringAndSize(NULL, fragment->len/width);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001589 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001590 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001591 ncp = (unsigned char *)PyBytes_AsString(rv);
1592
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001593 for (i = 0; i < fragment->len; i += width) {
1594 int val = GETSAMPLE32(width, fragment->buf, i);
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001595 *ncp++ = st_linear2alaw(val >> 19);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001596 }
1597 return rv;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001598}
1599
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001600/*[clinic input]
1601audioop.alaw2lin
1602
1603 fragment: Py_buffer
1604 width: int
1605 /
1606
1607Convert sound fragments in a-LAW encoding to linearly encoded sound fragments.
1608[clinic start generated code]*/
1609
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001610static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001611audioop_alaw2lin_impl(PyObject *module, Py_buffer *fragment, int width)
1612/*[clinic end generated code: output=85c365ec559df647 input=4140626046cd1772]*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001613{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001614 unsigned char *cp;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001615 signed char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001616 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001617 int val;
1618 PyObject *rv;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001619
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001620 if (!audioop_check_size(module, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001621 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001622
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001623 if (fragment->len > PY_SSIZE_T_MAX/width) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001624 PyErr_SetString(PyExc_MemoryError,
1625 "not enough memory for output buffer");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001626 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001627 }
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001628 rv = PyBytes_FromStringAndSize(NULL, fragment->len*width);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001629 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001630 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001631 ncp = (signed char *)PyBytes_AsString(rv);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001632 cp = fragment->buf;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001633
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001634 for (i = 0; i < fragment->len*width; i += width) {
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001635 val = st_alaw2linear16(*cp++) << 16;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001636 SETSAMPLE32(width, ncp, i, val);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001637 }
1638 return rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001639}
1640
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001641/*[clinic input]
1642audioop.lin2adpcm
1643
1644 fragment: Py_buffer
1645 width: int
1646 state: object
1647 /
1648
1649Convert samples to 4 bit Intel/DVI ADPCM encoding.
1650[clinic start generated code]*/
1651
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001652static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001653audioop_lin2adpcm_impl(PyObject *module, Py_buffer *fragment, int width,
Larry Hastings89964c42015-04-14 18:07:59 -04001654 PyObject *state)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001655/*[clinic end generated code: output=cc19f159f16c6793 input=12919d549b90c90a]*/
Guido van Rossumb64e6351992-07-06 14:21:56 +00001656{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001657 signed char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001658 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001659 int step, valpred, delta,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001660 index, sign, vpdiff, diff;
Benjamin Peterson08673c52014-01-26 10:24:24 -05001661 PyObject *rv = NULL, *str;
Mark Dickinson81fece22010-05-11 13:34:35 +00001662 int outputbuffer = 0, bufferstep;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001663
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001664 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001665 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001666
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001667 /* Decode state, should have (value, step) */
1668 if ( state == Py_None ) {
1669 /* First time, it seems. Set defaults */
1670 valpred = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001671 index = 0;
Benjamin Peterson08673c52014-01-26 10:24:24 -05001672 }
Serhiy Storchaka449e2be2015-06-28 17:52:09 +03001673 else if (!PyTuple_Check(state)) {
1674 PyErr_SetString(PyExc_TypeError, "state must be a tuple or None");
1675 return NULL;
1676 }
Oren Milman1d1d3e92017-08-20 18:35:36 +03001677 else if (!PyArg_ParseTuple(state, "ii;lin2adpcm(): illegal state argument",
1678 &valpred, &index))
1679 {
Serhiy Storchaka449e2be2015-06-28 17:52:09 +03001680 return NULL;
1681 }
1682 else if (valpred >= 0x8000 || valpred < -0x8000 ||
1683 (size_t)index >= Py_ARRAY_LENGTH(stepsizeTable)) {
1684 PyErr_SetString(PyExc_ValueError, "bad state");
1685 return NULL;
1686 }
1687
1688 str = PyBytes_FromStringAndSize(NULL, fragment->len/(width*2));
1689 if (str == NULL)
1690 return NULL;
1691 ncp = (signed char *)PyBytes_AsString(str);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001692
1693 step = stepsizeTable[index];
1694 bufferstep = 1;
1695
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001696 for (i = 0; i < fragment->len; i += width) {
1697 int val = GETSAMPLE32(width, fragment->buf, i) >> 16;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001698
1699 /* Step 1 - compute difference with previous value */
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001700 if (val < valpred) {
1701 diff = valpred - val;
1702 sign = 8;
1703 }
1704 else {
1705 diff = val - valpred;
1706 sign = 0;
1707 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001708
1709 /* Step 2 - Divide and clamp */
1710 /* Note:
1711 ** This code *approximately* computes:
1712 ** delta = diff*4/step;
1713 ** vpdiff = (delta+0.5)*step/4;
1714 ** but in shift step bits are dropped. The net result of this
1715 ** is that even if you have fast mul/div hardware you cannot
1716 ** put it to good use since the fixup would be too expensive.
1717 */
1718 delta = 0;
1719 vpdiff = (step >> 3);
1720
1721 if ( diff >= step ) {
1722 delta = 4;
1723 diff -= step;
1724 vpdiff += step;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001725 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001726 step >>= 1;
1727 if ( diff >= step ) {
1728 delta |= 2;
1729 diff -= step;
1730 vpdiff += step;
1731 }
1732 step >>= 1;
1733 if ( diff >= step ) {
1734 delta |= 1;
1735 vpdiff += step;
1736 }
Jack Jansendd8a6ea1993-02-17 14:21:09 +00001737
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001738 /* Step 3 - Update previous value */
1739 if ( sign )
1740 valpred -= vpdiff;
1741 else
1742 valpred += vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001743
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001744 /* Step 4 - Clamp previous value to 16 bits */
1745 if ( valpred > 32767 )
1746 valpred = 32767;
1747 else if ( valpred < -32768 )
1748 valpred = -32768;
1749
1750 /* Step 5 - Assemble value, update index and step values */
1751 delta |= sign;
1752
1753 index += indexTable[delta];
1754 if ( index < 0 ) index = 0;
1755 if ( index > 88 ) index = 88;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001756 step = stepsizeTable[index];
Guido van Rossumb64e6351992-07-06 14:21:56 +00001757
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001758 /* Step 6 - Output value */
1759 if ( bufferstep ) {
1760 outputbuffer = (delta << 4) & 0xf0;
1761 } else {
1762 *ncp++ = (delta & 0x0f) | outputbuffer;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001763 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001764 bufferstep = !bufferstep;
1765 }
1766 rv = Py_BuildValue("(O(ii))", str, valpred, index);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001767 Py_DECREF(str);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001768 return rv;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001769}
1770
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001771/*[clinic input]
1772audioop.adpcm2lin
1773
1774 fragment: Py_buffer
1775 width: int
1776 state: object
1777 /
1778
1779Decode an Intel/DVI ADPCM coded fragment to a linear fragment.
1780[clinic start generated code]*/
1781
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001782static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001783audioop_adpcm2lin_impl(PyObject *module, Py_buffer *fragment, int width,
Larry Hastings89964c42015-04-14 18:07:59 -04001784 PyObject *state)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001785/*[clinic end generated code: output=3440ea105acb3456 input=f5221144f5ca9ef0]*/
Guido van Rossumb64e6351992-07-06 14:21:56 +00001786{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001787 signed char *cp;
1788 signed char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001789 Py_ssize_t i, outlen;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001790 int valpred, step, delta, index, sign, vpdiff;
1791 PyObject *rv, *str;
Mark Dickinson81fece22010-05-11 13:34:35 +00001792 int inputbuffer = 0, bufferstep;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001793
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001794 if (!audioop_check_size(module, width))
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001795 return NULL;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001796
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001797 /* Decode state, should have (value, step) */
1798 if ( state == Py_None ) {
1799 /* First time, it seems. Set defaults */
1800 valpred = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001801 index = 0;
Serhiy Storchaka449e2be2015-06-28 17:52:09 +03001802 }
1803 else if (!PyTuple_Check(state)) {
Victor Stinnerdaeffd22014-01-03 03:26:47 +01001804 PyErr_SetString(PyExc_TypeError, "state must be a tuple or None");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001805 return NULL;
Serhiy Storchaka449e2be2015-06-28 17:52:09 +03001806 }
Oren Milman1d1d3e92017-08-20 18:35:36 +03001807 else if (!PyArg_ParseTuple(state, "ii;adpcm2lin(): illegal state argument",
1808 &valpred, &index))
1809 {
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001810 return NULL;
Serhiy Storchaka449e2be2015-06-28 17:52:09 +03001811 }
1812 else if (valpred >= 0x8000 || valpred < -0x8000 ||
1813 (size_t)index >= Py_ARRAY_LENGTH(stepsizeTable)) {
1814 PyErr_SetString(PyExc_ValueError, "bad state");
1815 return NULL;
1816 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001817
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001818 if (fragment->len > (PY_SSIZE_T_MAX/2)/width) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001819 PyErr_SetString(PyExc_MemoryError,
1820 "not enough memory for output buffer");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001821 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001822 }
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001823 outlen = fragment->len*width*2;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001824 str = PyBytes_FromStringAndSize(NULL, outlen);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001825 if (str == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001826 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001827 ncp = (signed char *)PyBytes_AsString(str);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001828 cp = fragment->buf;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001829
1830 step = stepsizeTable[index];
1831 bufferstep = 0;
1832
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001833 for (i = 0; i < outlen; i += width) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001834 /* Step 1 - get the delta value and compute next index */
1835 if ( bufferstep ) {
1836 delta = inputbuffer & 0xf;
1837 } else {
1838 inputbuffer = *cp++;
1839 delta = (inputbuffer >> 4) & 0xf;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001840 }
Guido van Rossumb64e6351992-07-06 14:21:56 +00001841
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001842 bufferstep = !bufferstep;
1843
1844 /* Step 2 - Find new index value (for later) */
1845 index += indexTable[delta];
1846 if ( index < 0 ) index = 0;
1847 if ( index > 88 ) index = 88;
1848
1849 /* Step 3 - Separate sign and magnitude */
1850 sign = delta & 8;
1851 delta = delta & 7;
1852
1853 /* Step 4 - Compute difference and new predicted value */
1854 /*
1855 ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
1856 ** in adpcm_coder.
1857 */
1858 vpdiff = step >> 3;
1859 if ( delta & 4 ) vpdiff += step;
1860 if ( delta & 2 ) vpdiff += step>>1;
1861 if ( delta & 1 ) vpdiff += step>>2;
1862
1863 if ( sign )
1864 valpred -= vpdiff;
1865 else
1866 valpred += vpdiff;
1867
1868 /* Step 5 - clamp output value */
1869 if ( valpred > 32767 )
1870 valpred = 32767;
1871 else if ( valpred < -32768 )
1872 valpred = -32768;
1873
1874 /* Step 6 - Update step value */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001875 step = stepsizeTable[index];
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001876
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001877 /* Step 6 - Output value */
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001878 SETSAMPLE32(width, ncp, i, valpred << 16);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001879 }
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001880
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001881 rv = Py_BuildValue("(O(ii))", str, valpred, index);
1882 Py_DECREF(str);
1883 return rv;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001884}
1885
Larry Hastingsf256c222014-01-25 21:30:37 -08001886#include "clinic/audioop.c.h"
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001887
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001888static PyMethodDef audioop_methods[] = {
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001889 AUDIOOP_MAX_METHODDEF
1890 AUDIOOP_MINMAX_METHODDEF
1891 AUDIOOP_AVG_METHODDEF
1892 AUDIOOP_MAXPP_METHODDEF
1893 AUDIOOP_AVGPP_METHODDEF
1894 AUDIOOP_RMS_METHODDEF
1895 AUDIOOP_FINDFIT_METHODDEF
1896 AUDIOOP_FINDMAX_METHODDEF
1897 AUDIOOP_FINDFACTOR_METHODDEF
1898 AUDIOOP_CROSS_METHODDEF
1899 AUDIOOP_MUL_METHODDEF
1900 AUDIOOP_ADD_METHODDEF
1901 AUDIOOP_BIAS_METHODDEF
1902 AUDIOOP_ULAW2LIN_METHODDEF
1903 AUDIOOP_LIN2ULAW_METHODDEF
1904 AUDIOOP_ALAW2LIN_METHODDEF
1905 AUDIOOP_LIN2ALAW_METHODDEF
1906 AUDIOOP_LIN2LIN_METHODDEF
1907 AUDIOOP_ADPCM2LIN_METHODDEF
1908 AUDIOOP_LIN2ADPCM_METHODDEF
1909 AUDIOOP_TOMONO_METHODDEF
1910 AUDIOOP_TOSTEREO_METHODDEF
1911 AUDIOOP_GETSAMPLE_METHODDEF
1912 AUDIOOP_REVERSE_METHODDEF
1913 AUDIOOP_BYTESWAP_METHODDEF
1914 AUDIOOP_RATECV_METHODDEF
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001915 { 0, 0 }
Guido van Rossumb66efa01992-06-01 16:01:24 +00001916};
1917
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001918static int
Hai Shi41fbf862020-03-12 00:49:11 +08001919audioop_traverse(PyObject *module, visitproc visit, void *arg)
1920{
Hai Shi13397ee2020-03-20 01:11:33 +08001921 audioop_state *state = get_audioop_state(module);
Victor Stinner5b1ef202020-03-17 18:09:46 +01001922 Py_VISIT(state->AudioopError);
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001923 return 0;
1924}
Hai Shi41fbf862020-03-12 00:49:11 +08001925
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001926static int
Hai Shi41fbf862020-03-12 00:49:11 +08001927audioop_clear(PyObject *module)
1928{
Hai Shi13397ee2020-03-20 01:11:33 +08001929 audioop_state *state = get_audioop_state(module);
Victor Stinner5b1ef202020-03-17 18:09:46 +01001930 Py_CLEAR(state->AudioopError);
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001931 return 0;
1932}
Hai Shi41fbf862020-03-12 00:49:11 +08001933
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001934static void
Hai Shi41fbf862020-03-12 00:49:11 +08001935audioop_free(void *module) {
1936 audioop_clear((PyObject *)module);
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001937}
Martin v. Löwis1a214512008-06-11 05:26:20 +00001938
Hai Shi41fbf862020-03-12 00:49:11 +08001939static int
1940audioop_exec(PyObject* module)
1941{
1942 audioop_state *state = get_audioop_state(module);
1943
1944 state->AudioopError = PyErr_NewException("audioop.error", NULL, NULL);
1945 if (state->AudioopError == NULL) {
1946 return -1;
1947 }
1948
1949 Py_INCREF(state->AudioopError);
1950 if (PyModule_AddObject(module, "error", state->AudioopError) < 0) {
1951 Py_DECREF(state->AudioopError);
1952 return -1;
1953 }
1954
1955 return 0;
1956}
1957
1958static PyModuleDef_Slot audioop_slots[] = {
1959 {Py_mod_exec, audioop_exec},
1960 {0, NULL}
1961};
1962
Martin v. Löwis1a214512008-06-11 05:26:20 +00001963static struct PyModuleDef audioopmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001964 PyModuleDef_HEAD_INIT,
1965 "audioop",
1966 NULL,
Hai Shi41fbf862020-03-12 00:49:11 +08001967 sizeof(audioop_state),
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001968 audioop_methods,
Hai Shi41fbf862020-03-12 00:49:11 +08001969 audioop_slots,
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001970 audioop_traverse,
1971 audioop_clear,
1972 audioop_free
Martin v. Löwis1a214512008-06-11 05:26:20 +00001973};
1974
Mark Hammondfe51c6d2002-08-02 02:27:13 +00001975PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00001976PyInit_audioop(void)
Guido van Rossumb66efa01992-06-01 16:01:24 +00001977{
Hai Shi41fbf862020-03-12 00:49:11 +08001978 return PyModuleDef_Init(&audioopmodule);
Guido van Rossumb66efa01992-06-01 16:01:24 +00001979}