blob: 7726c88b1a9d49118bfe1ff20b2c1b41cff8d600 [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
Guido van Rossum7b1e9741994-08-29 10:46:42 +00008#if defined(__CHAR_UNSIGNED__)
9#if defined(signed)
Guido van Rossumb6775db1994-08-01 11:34:53 +000010/* This module currently does not work on systems where only unsigned
11 characters are available. Take it out of Setup. Sorry. */
12#endif
Guido van Rossum7b1e9741994-08-29 10:46:42 +000013#endif
Guido van Rossumb6775db1994-08-01 11:34:53 +000014
Serhiy Storchaka01ad6222013-02-09 11:10:53 +020015static const int maxvals[] = {0, 0x7F, 0x7FFF, 0x7FFFFF, 0x7FFFFFFF};
Tim Goldenfa6ab0f2013-10-31 10:25:47 +000016/* -1 trick is needed on Windows to support -0x80000000 without a warning */
17static const int minvals[] = {0, -0x80, -0x8000, -0x800000, -0x7FFFFFFF-1};
Serhiy Storchaka01ad6222013-02-09 11:10:53 +020018static const unsigned int masks[] = {0, 0xFF, 0xFFFF, 0xFFFFFF, 0xFFFFFFFF};
19
20static int
21fbound(double val, double minval, double maxval)
22{
Victor Stinner45e4efb2018-06-06 15:50:50 +020023 if (val > maxval) {
Serhiy Storchaka01ad6222013-02-09 11:10:53 +020024 val = maxval;
Victor Stinner45e4efb2018-06-06 15:50:50 +020025 }
26 else if (val < minval + 1.0) {
Serhiy Storchaka01ad6222013-02-09 11:10:53 +020027 val = minval;
Victor Stinner45e4efb2018-06-06 15:50:50 +020028 }
29
30 /* Round towards minus infinity (-inf) */
31 val = floor(val);
32
33 /* Cast double to integer: round towards zero */
Victor Stinnerf2b9a342013-05-07 23:49:15 +020034 return (int)val;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +020035}
36
37
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000038/* Code shamelessly stolen from sox, 12.17.7, g711.c
Guido van Rossumb66efa01992-06-01 16:01:24 +000039** (c) Craig Reese, Joe Campbell and Jeff Poskanzer 1989 */
40
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000041/* From g711.c:
42 *
43 * December 30, 1994:
44 * Functions linear2alaw, linear2ulaw have been updated to correctly
45 * convert unquantized 16 bit values.
46 * Tables for direct u- to A-law and A- to u-law conversions have been
47 * corrected.
48 * Borge Lindberg, Center for PersonKommunikation, Aalborg University.
49 * bli@cpk.auc.dk
50 *
51 */
Guido van Rossumb66efa01992-06-01 16:01:24 +000052#define BIAS 0x84 /* define the add-in bias for 16 bit samples */
53#define CLIP 32635
Martin Panter4c359642016-05-08 13:53:41 +000054#define SIGN_BIT (0x80) /* Sign bit for an A-law byte. */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000055#define QUANT_MASK (0xf) /* Quantization field mask. */
56#define SEG_SHIFT (4) /* Left shift for segment number. */
57#define SEG_MASK (0x70) /* Segment field mask. */
Guido van Rossumb66efa01992-06-01 16:01:24 +000058
Benjamin Petersonbb0b0d92016-09-08 15:08:02 -070059static const int16_t seg_aend[8] = {
Serhiy Storchaka2d06e842015-12-25 19:53:18 +020060 0x1F, 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF
61};
Benjamin Petersonbb0b0d92016-09-08 15:08:02 -070062static const int16_t seg_uend[8] = {
Serhiy Storchaka2d06e842015-12-25 19:53:18 +020063 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF
64};
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000065
Benjamin Petersonbb0b0d92016-09-08 15:08:02 -070066static int16_t
67search(int16_t val, const int16_t *table, int size)
Roger E. Masseeaa6e111997-01-03 19:26:27 +000068{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000069 int i;
Guido van Rossumb66efa01992-06-01 16:01:24 +000070
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000071 for (i = 0; i < size; i++) {
72 if (val <= *table++)
73 return (i);
74 }
75 return (size);
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000076}
77#define st_ulaw2linear16(uc) (_st_ulaw2linear16[uc])
78#define st_alaw2linear16(uc) (_st_alaw2linear16[uc])
Guido van Rossumb66efa01992-06-01 16:01:24 +000079
Benjamin Petersonbb0b0d92016-09-08 15:08:02 -070080static const int16_t _st_ulaw2linear16[256] = {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000081 -32124, -31100, -30076, -29052, -28028, -27004, -25980,
82 -24956, -23932, -22908, -21884, -20860, -19836, -18812,
83 -17788, -16764, -15996, -15484, -14972, -14460, -13948,
84 -13436, -12924, -12412, -11900, -11388, -10876, -10364,
85 -9852, -9340, -8828, -8316, -7932, -7676, -7420,
86 -7164, -6908, -6652, -6396, -6140, -5884, -5628,
87 -5372, -5116, -4860, -4604, -4348, -4092, -3900,
88 -3772, -3644, -3516, -3388, -3260, -3132, -3004,
89 -2876, -2748, -2620, -2492, -2364, -2236, -2108,
90 -1980, -1884, -1820, -1756, -1692, -1628, -1564,
91 -1500, -1436, -1372, -1308, -1244, -1180, -1116,
92 -1052, -988, -924, -876, -844, -812, -780,
93 -748, -716, -684, -652, -620, -588, -556,
94 -524, -492, -460, -428, -396, -372, -356,
95 -340, -324, -308, -292, -276, -260, -244,
96 -228, -212, -196, -180, -164, -148, -132,
97 -120, -112, -104, -96, -88, -80, -72,
98 -64, -56, -48, -40, -32, -24, -16,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000099 -8, 0, 32124, 31100, 30076, 29052, 28028,
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000100 27004, 25980, 24956, 23932, 22908, 21884, 20860,
101 19836, 18812, 17788, 16764, 15996, 15484, 14972,
102 14460, 13948, 13436, 12924, 12412, 11900, 11388,
103 10876, 10364, 9852, 9340, 8828, 8316, 7932,
104 7676, 7420, 7164, 6908, 6652, 6396, 6140,
105 5884, 5628, 5372, 5116, 4860, 4604, 4348,
106 4092, 3900, 3772, 3644, 3516, 3388, 3260,
107 3132, 3004, 2876, 2748, 2620, 2492, 2364,
108 2236, 2108, 1980, 1884, 1820, 1756, 1692,
109 1628, 1564, 1500, 1436, 1372, 1308, 1244,
110 1180, 1116, 1052, 988, 924, 876, 844,
111 812, 780, 748, 716, 684, 652, 620,
112 588, 556, 524, 492, 460, 428, 396,
113 372, 356, 340, 324, 308, 292, 276,
114 260, 244, 228, 212, 196, 180, 164,
115 148, 132, 120, 112, 104, 96, 88,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000116 80, 72, 64, 56, 48, 40, 32,
117 24, 16, 8, 0
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000118};
Guido van Rossumb66efa01992-06-01 16:01:24 +0000119
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000120/*
121 * linear2ulaw() accepts a 14-bit signed integer and encodes it as u-law data
Martin Panter7462b6492015-11-02 03:37:02 +0000122 * stored in an unsigned char. This function should only be called with
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000123 * the data shifted such that it only contains information in the lower
124 * 14-bits.
125 *
126 * In order to simplify the encoding process, the original linear magnitude
127 * is biased by adding 33 which shifts the encoding range from (0 - 8158) to
128 * (33 - 8191). The result can be seen in the following encoding table:
129 *
130 * Biased Linear Input Code Compressed Code
131 * ------------------------ ---------------
132 * 00000001wxyza 000wxyz
133 * 0000001wxyzab 001wxyz
134 * 000001wxyzabc 010wxyz
135 * 00001wxyzabcd 011wxyz
136 * 0001wxyzabcde 100wxyz
137 * 001wxyzabcdef 101wxyz
138 * 01wxyzabcdefg 110wxyz
139 * 1wxyzabcdefgh 111wxyz
140 *
141 * Each biased linear code has a leading 1 which identifies the segment
142 * number. The value of the segment number is equal to 7 minus the number
143 * of leading 0's. The quantization interval is directly available as the
144 * four bits wxyz. * The trailing bits (a - h) are ignored.
145 *
146 * Ordinarily the complement of the resulting code word is used for
147 * transmission, and so the code word is complemented before it is returned.
148 *
149 * For further information see John C. Bellamy's Digital Telephony, 1982,
150 * John Wiley & Sons, pps 98-111 and 472-476.
151 */
152static unsigned char
Benjamin Petersonbb0b0d92016-09-08 15:08:02 -0700153st_14linear2ulaw(int16_t pcm_val) /* 2's complement (14-bit range) */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000154{
Benjamin Petersonbb0b0d92016-09-08 15:08:02 -0700155 int16_t mask;
156 int16_t seg;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000157 unsigned char uval;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000158
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000159 /* u-law inverts all bits */
160 /* Get the sign and the magnitude of the value. */
161 if (pcm_val < 0) {
162 pcm_val = -pcm_val;
163 mask = 0x7F;
164 } else {
165 mask = 0xFF;
166 }
167 if ( pcm_val > CLIP ) pcm_val = CLIP; /* clip the magnitude */
168 pcm_val += (BIAS >> 2);
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000169
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000170 /* Convert the scaled magnitude to segment number. */
171 seg = search(pcm_val, seg_uend, 8);
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000172
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000173 /*
174 * Combine the sign, segment, quantization bits;
175 * and complement the code word.
176 */
177 if (seg >= 8) /* out of range, return maximum value. */
178 return (unsigned char) (0x7F ^ mask);
179 else {
180 uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF);
181 return (uval ^ mask);
182 }
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000183
184}
185
Benjamin Petersonbb0b0d92016-09-08 15:08:02 -0700186static const int16_t _st_alaw2linear16[256] = {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000187 -5504, -5248, -6016, -5760, -4480, -4224, -4992,
188 -4736, -7552, -7296, -8064, -7808, -6528, -6272,
189 -7040, -6784, -2752, -2624, -3008, -2880, -2240,
190 -2112, -2496, -2368, -3776, -3648, -4032, -3904,
191 -3264, -3136, -3520, -3392, -22016, -20992, -24064,
192 -23040, -17920, -16896, -19968, -18944, -30208, -29184,
193 -32256, -31232, -26112, -25088, -28160, -27136, -11008,
194 -10496, -12032, -11520, -8960, -8448, -9984, -9472,
195 -15104, -14592, -16128, -15616, -13056, -12544, -14080,
196 -13568, -344, -328, -376, -360, -280, -264,
197 -312, -296, -472, -456, -504, -488, -408,
198 -392, -440, -424, -88, -72, -120, -104,
199 -24, -8, -56, -40, -216, -200, -248,
200 -232, -152, -136, -184, -168, -1376, -1312,
201 -1504, -1440, -1120, -1056, -1248, -1184, -1888,
202 -1824, -2016, -1952, -1632, -1568, -1760, -1696,
203 -688, -656, -752, -720, -560, -528, -624,
204 -592, -944, -912, -1008, -976, -816, -784,
205 -880, -848, 5504, 5248, 6016, 5760, 4480,
206 4224, 4992, 4736, 7552, 7296, 8064, 7808,
207 6528, 6272, 7040, 6784, 2752, 2624, 3008,
208 2880, 2240, 2112, 2496, 2368, 3776, 3648,
209 4032, 3904, 3264, 3136, 3520, 3392, 22016,
210 20992, 24064, 23040, 17920, 16896, 19968, 18944,
211 30208, 29184, 32256, 31232, 26112, 25088, 28160,
212 27136, 11008, 10496, 12032, 11520, 8960, 8448,
213 9984, 9472, 15104, 14592, 16128, 15616, 13056,
214 12544, 14080, 13568, 344, 328, 376, 360,
215 280, 264, 312, 296, 472, 456, 504,
216 488, 408, 392, 440, 424, 88, 72,
217 120, 104, 24, 8, 56, 40, 216,
218 200, 248, 232, 152, 136, 184, 168,
219 1376, 1312, 1504, 1440, 1120, 1056, 1248,
220 1184, 1888, 1824, 2016, 1952, 1632, 1568,
221 1760, 1696, 688, 656, 752, 720, 560,
222 528, 624, 592, 944, 912, 1008, 976,
223 816, 784, 880, 848
224};
225
226/*
Martin Panter4c359642016-05-08 13:53:41 +0000227 * linear2alaw() accepts a 13-bit signed integer and encodes it as A-law data
Martin Panter7462b6492015-11-02 03:37:02 +0000228 * stored in an unsigned char. This function should only be called with
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000229 * the data shifted such that it only contains information in the lower
230 * 13-bits.
231 *
232 * Linear Input Code Compressed Code
233 * ------------------------ ---------------
234 * 0000000wxyza 000wxyz
235 * 0000001wxyza 001wxyz
236 * 000001wxyzab 010wxyz
237 * 00001wxyzabc 011wxyz
238 * 0001wxyzabcd 100wxyz
239 * 001wxyzabcde 101wxyz
240 * 01wxyzabcdef 110wxyz
241 * 1wxyzabcdefg 111wxyz
242 *
243 * For further information see John C. Bellamy's Digital Telephony, 1982,
244 * John Wiley & Sons, pps 98-111 and 472-476.
245 */
246static unsigned char
Benjamin Petersonbb0b0d92016-09-08 15:08:02 -0700247st_linear2alaw(int16_t pcm_val) /* 2's complement (13-bit range) */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000248{
Benjamin Petersonbb0b0d92016-09-08 15:08:02 -0700249 int16_t mask;
Serhiy Storchaka8be17402016-09-11 14:48:16 +0300250 int16_t seg;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000251 unsigned char aval;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000252
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000253 /* A-law using even bit inversion */
254 if (pcm_val >= 0) {
255 mask = 0xD5; /* sign (7th) bit = 1 */
256 } else {
257 mask = 0x55; /* sign bit = 0 */
258 pcm_val = -pcm_val - 1;
259 }
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000260
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000261 /* Convert the scaled magnitude to segment number. */
262 seg = search(pcm_val, seg_aend, 8);
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000263
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000264 /* Combine the sign, segment, and quantization bits. */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000265
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000266 if (seg >= 8) /* out of range, return maximum value. */
267 return (unsigned char) (0x7F ^ mask);
268 else {
269 aval = (unsigned char) seg << SEG_SHIFT;
270 if (seg < 2)
271 aval |= (pcm_val >> 1) & QUANT_MASK;
272 else
273 aval |= (pcm_val >> seg) & QUANT_MASK;
274 return (aval ^ mask);
275 }
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000276}
Guido van Rossumb66efa01992-06-01 16:01:24 +0000277/* End of code taken from sox */
278
Guido van Rossumb64e6351992-07-06 14:21:56 +0000279/* Intel ADPCM step variation table */
Serhiy Storchaka2d06e842015-12-25 19:53:18 +0200280static const int indexTable[16] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000281 -1, -1, -1, -1, 2, 4, 6, 8,
282 -1, -1, -1, -1, 2, 4, 6, 8,
Guido van Rossumb64e6351992-07-06 14:21:56 +0000283};
284
Serhiy Storchaka2d06e842015-12-25 19:53:18 +0200285static const int stepsizeTable[89] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000286 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
287 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
288 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
289 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
290 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
291 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
292 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
293 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
294 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
Guido van Rossumb64e6351992-07-06 14:21:56 +0000295};
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000296
Serhiy Storchaka23a78272013-11-11 07:47:35 +0200297#define GETINTX(T, cp, i) (*(T *)((unsigned char *)(cp) + (i)))
298#define SETINTX(T, cp, i, val) do { \
299 *(T *)((unsigned char *)(cp) + (i)) = (T)(val); \
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300300 } while (0)
Guido van Rossumb66efa01992-06-01 16:01:24 +0000301
302
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300303#define GETINT8(cp, i) GETINTX(signed char, (cp), (i))
Serhiy Storchaka8be17402016-09-11 14:48:16 +0300304#define GETINT16(cp, i) GETINTX(int16_t, (cp), (i))
Benjamin Peterson9b3d7702016-09-06 13:24:00 -0700305#define GETINT32(cp, i) GETINTX(int32_t, (cp), (i))
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300306
307#if WORDS_BIGENDIAN
308#define GETINT24(cp, i) ( \
309 ((unsigned char *)(cp) + (i))[2] + \
310 (((unsigned char *)(cp) + (i))[1] << 8) + \
311 (((signed char *)(cp) + (i))[0] << 16) )
312#else
313#define GETINT24(cp, i) ( \
314 ((unsigned char *)(cp) + (i))[0] + \
315 (((unsigned char *)(cp) + (i))[1] << 8) + \
316 (((signed char *)(cp) + (i))[2] << 16) )
317#endif
318
319
320#define SETINT8(cp, i, val) SETINTX(signed char, (cp), (i), (val))
Serhiy Storchaka8be17402016-09-11 14:48:16 +0300321#define SETINT16(cp, i, val) SETINTX(int16_t, (cp), (i), (val))
Benjamin Peterson9b3d7702016-09-06 13:24:00 -0700322#define SETINT32(cp, i, val) SETINTX(int32_t, (cp), (i), (val))
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300323
324#if WORDS_BIGENDIAN
325#define SETINT24(cp, i, val) do { \
326 ((unsigned char *)(cp) + (i))[2] = (int)(val); \
327 ((unsigned char *)(cp) + (i))[1] = (int)(val) >> 8; \
328 ((signed char *)(cp) + (i))[0] = (int)(val) >> 16; \
329 } while (0)
330#else
331#define SETINT24(cp, i, val) do { \
332 ((unsigned char *)(cp) + (i))[0] = (int)(val); \
333 ((unsigned char *)(cp) + (i))[1] = (int)(val) >> 8; \
334 ((signed char *)(cp) + (i))[2] = (int)(val) >> 16; \
335 } while (0)
336#endif
337
338
339#define GETRAWSAMPLE(size, cp, i) ( \
340 (size == 1) ? (int)GETINT8((cp), (i)) : \
341 (size == 2) ? (int)GETINT16((cp), (i)) : \
342 (size == 3) ? (int)GETINT24((cp), (i)) : \
343 (int)GETINT32((cp), (i)))
344
345#define SETRAWSAMPLE(size, cp, i, val) do { \
346 if (size == 1) \
347 SETINT8((cp), (i), (val)); \
348 else if (size == 2) \
349 SETINT16((cp), (i), (val)); \
350 else if (size == 3) \
351 SETINT24((cp), (i), (val)); \
352 else \
353 SETINT32((cp), (i), (val)); \
354 } while(0)
355
356
357#define GETSAMPLE32(size, cp, i) ( \
358 (size == 1) ? (int)GETINT8((cp), (i)) << 24 : \
359 (size == 2) ? (int)GETINT16((cp), (i)) << 16 : \
360 (size == 3) ? (int)GETINT24((cp), (i)) << 8 : \
361 (int)GETINT32((cp), (i)))
362
363#define SETSAMPLE32(size, cp, i, val) do { \
364 if (size == 1) \
365 SETINT8((cp), (i), (val) >> 24); \
366 else if (size == 2) \
367 SETINT16((cp), (i), (val) >> 16); \
368 else if (size == 3) \
369 SETINT24((cp), (i), (val) >> 8); \
370 else \
371 SETINT32((cp), (i), (val)); \
372 } while(0)
373
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400374static PyModuleDef audioopmodule;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000375
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400376typedef struct {
377 PyObject *AudioopError;
378} _audioopstate;
379
380#define _audioopstate(o) ((_audioopstate *)PyModule_GetState(o))
Guido van Rossumb66efa01992-06-01 16:01:24 +0000381
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000382static int
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400383audioop_check_size(PyObject *module, int size)
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000384{
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300385 if (size < 1 || size > 4) {
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400386 PyErr_SetString(_audioopstate(module)->AudioopError, "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) {
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400399 PyErr_SetString(_audioopstate(module)->AudioopError, "not a whole number of frames");
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000400 return 0;
401 }
402 return 1;
403}
404
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200405/*[clinic input]
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200406module audioop
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200407[clinic start generated code]*/
Serhiy Storchaka1009bf12015-04-03 23:53:51 +0300408/*[clinic end generated code: output=da39a3ee5e6b4b0d input=8fa8f6611be3591a]*/
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200409
410/*[clinic input]
411audioop.getsample
412
413 fragment: Py_buffer
414 width: int
415 index: Py_ssize_t
416 /
417
418Return the value of sample index from the fragment.
419[clinic start generated code]*/
420
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000421static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300422audioop_getsample_impl(PyObject *module, Py_buffer *fragment, int width,
Larry Hastings89964c42015-04-14 18:07:59 -0400423 Py_ssize_t index)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300424/*[clinic end generated code: output=8fe1b1775134f39a input=88edbe2871393549]*/
Guido van Rossumb66efa01992-06-01 16:01:24 +0000425{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200426 int val;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000427
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400428 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000429 return NULL;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200430 if (index < 0 || index >= fragment->len/width) {
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400431 PyErr_SetString(_audioopstate(module)->AudioopError, "Index out of range");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200432 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000433 }
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200434 val = GETRAWSAMPLE(width, fragment->buf, index*width);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200435 return PyLong_FromLong(val);
Guido van Rossumb66efa01992-06-01 16:01:24 +0000436}
437
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200438/*[clinic input]
439audioop.max
440
441 fragment: Py_buffer
442 width: int
443 /
444
445Return the maximum of the absolute value of all samples in a fragment.
446[clinic start generated code]*/
447
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000448static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300449audioop_max_impl(PyObject *module, Py_buffer *fragment, int width)
450/*[clinic end generated code: output=e6c5952714f1c3f0 input=32bea5ea0ac8c223]*/
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000451{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200452 Py_ssize_t i;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200453 unsigned int absval, max = 0;
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000454
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400455 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000456 return NULL;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200457 for (i = 0; i < fragment->len; i += width) {
458 int val = GETRAWSAMPLE(width, fragment->buf, i);
Martin Panter6fb90902016-07-19 03:05:42 +0000459 /* Cast to unsigned before negating. Unsigned overflow is well-
460 defined, but signed overflow is not. */
Steve Dowera4391912016-09-06 19:09:15 -0700461 if (val < 0) absval = (unsigned int)-(int64_t)val;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200462 else absval = val;
463 if (absval > max) max = absval;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000464 }
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200465 return PyLong_FromUnsignedLong(max);
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000466}
467
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200468/*[clinic input]
469audioop.minmax
470
471 fragment: Py_buffer
472 width: int
473 /
474
475Return the minimum and maximum values of all samples in the sound fragment.
476[clinic start generated code]*/
477
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000478static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300479audioop_minmax_impl(PyObject *module, Py_buffer *fragment, int width)
480/*[clinic end generated code: output=473fda66b15c836e input=89848e9b927a0696]*/
Sjoerd Mullendera1426131994-09-06 16:19:33 +0000481{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200482 Py_ssize_t i;
Tim Goldenfa6ab0f2013-10-31 10:25:47 +0000483 /* -1 trick below is needed on Windows to support -0x80000000 without
484 a warning */
485 int min = 0x7fffffff, max = -0x7FFFFFFF-1;
Sjoerd Mullendera1426131994-09-06 16:19:33 +0000486
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400487 if (!audioop_check_parameters(module, fragment->len, width))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000488 return NULL;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200489 for (i = 0; i < fragment->len; i += width) {
490 int val = GETRAWSAMPLE(width, fragment->buf, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000491 if (val > max) max = val;
492 if (val < min) min = val;
493 }
494 return Py_BuildValue("(ii)", min, max);
Sjoerd Mullendera1426131994-09-06 16:19:33 +0000495}
496
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200497/*[clinic input]
498audioop.avg
499
500 fragment: Py_buffer
501 width: int
502 /
503
504Return the average over all samples in the fragment.
505[clinic start generated code]*/
506
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000507static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300508audioop_avg_impl(PyObject *module, Py_buffer *fragment, int width)
509/*[clinic end generated code: output=4410a4c12c3586e6 input=1114493c7611334d]*/
Guido van Rossumb66efa01992-06-01 16:01:24 +0000510{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200511 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200512 int avg;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300513 double sum = 0.0;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000514
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400515 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000516 return NULL;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200517 for (i = 0; i < fragment->len; i += width)
518 sum += GETRAWSAMPLE(width, fragment->buf, i);
519 if (fragment->len == 0)
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300520 avg = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000521 else
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200522 avg = (int)floor(sum / (double)(fragment->len/width));
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300523 return PyLong_FromLong(avg);
Guido van Rossumb66efa01992-06-01 16:01:24 +0000524}
525
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200526/*[clinic input]
527audioop.rms
528
529 fragment: Py_buffer
530 width: int
531 /
532
533Return the root-mean-square of the fragment, i.e. sqrt(sum(S_i^2)/n).
534[clinic start generated code]*/
535
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000536static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300537audioop_rms_impl(PyObject *module, Py_buffer *fragment, int width)
538/*[clinic end generated code: output=1e7871c826445698 input=4cc57c6c94219d78]*/
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000539{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200540 Py_ssize_t i;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200541 unsigned int res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000542 double sum_squares = 0.0;
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000543
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400544 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000545 return NULL;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200546 for (i = 0; i < fragment->len; i += width) {
547 double val = GETRAWSAMPLE(width, fragment->buf, i);
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300548 sum_squares += val*val;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000549 }
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200550 if (fragment->len == 0)
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200551 res = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000552 else
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200553 res = (unsigned int)sqrt(sum_squares / (double)(fragment->len/width));
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200554 return PyLong_FromUnsignedLong(res);
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000555}
556
Serhiy Storchaka8be17402016-09-11 14:48:16 +0300557static double _sum2(const int16_t *a, const int16_t *b, Py_ssize_t len)
Jack Jansena90805f1993-02-17 14:29:28 +0000558{
Mark Dickinson81fece22010-05-11 13:34:35 +0000559 Py_ssize_t i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000560 double sum = 0.0;
Jack Jansena90805f1993-02-17 14:29:28 +0000561
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000562 for( i=0; i<len; i++) {
563 sum = sum + (double)a[i]*(double)b[i];
564 }
565 return sum;
Jack Jansena90805f1993-02-17 14:29:28 +0000566}
567
568/*
569** Findfit tries to locate a sample within another sample. Its main use
570** is in echo-cancellation (to find the feedback of the output signal in
571** the input signal).
572** The method used is as follows:
573**
574** let R be the reference signal (length n) and A the input signal (length N)
575** with N > n, and let all sums be over i from 0 to n-1.
576**
577** Now, for each j in {0..N-n} we compute a factor fj so that -fj*R matches A
578** as good as possible, i.e. sum( (A[j+i]+fj*R[i])^2 ) is minimal. This
579** equation gives fj = sum( A[j+i]R[i] ) / sum(R[i]^2).
580**
581** Next, we compute the relative distance between the original signal and
582** the modified signal and minimize that over j:
583** vj = sum( (A[j+i]-fj*R[i])^2 ) / sum( A[j+i]^2 ) =>
584** vj = ( sum(A[j+i]^2)*sum(R[i]^2) - sum(A[j+i]R[i])^2 ) / sum( A[j+i]^2 )
585**
586** In the code variables correspond as follows:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000587** cp1 A
588** cp2 R
589** len1 N
590** len2 n
591** aj_m1 A[j-1]
592** aj_lm1 A[j+n-1]
593** sum_ri_2 sum(R[i]^2)
594** sum_aij_2 sum(A[i+j]^2)
595** sum_aij_ri sum(A[i+j]R[i])
Jack Jansena90805f1993-02-17 14:29:28 +0000596**
597** sum_ri is calculated once, sum_aij_2 is updated each step and sum_aij_ri
598** is completely recalculated each step.
599*/
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200600/*[clinic input]
601audioop.findfit
602
603 fragment: Py_buffer
604 reference: Py_buffer
605 /
606
607Try to match reference as well as possible to a portion of fragment.
608[clinic start generated code]*/
609
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000610static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300611audioop_findfit_impl(PyObject *module, Py_buffer *fragment,
Larry Hastings89964c42015-04-14 18:07:59 -0400612 Py_buffer *reference)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300613/*[clinic end generated code: output=5752306d83cbbada input=62c305605e183c9a]*/
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000614{
Serhiy Storchaka8be17402016-09-11 14:48:16 +0300615 const int16_t *cp1, *cp2;
Mark Dickinson81fece22010-05-11 13:34:35 +0000616 Py_ssize_t len1, len2;
617 Py_ssize_t j, best_j;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000618 double aj_m1, aj_lm1;
619 double sum_ri_2, sum_aij_2, sum_aij_ri, result, best_result, factor;
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000620
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200621 if (fragment->len & 1 || reference->len & 1) {
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400622 PyErr_SetString(_audioopstate(module)->AudioopError, "Strings should be even-sized");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200623 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000624 }
Serhiy Storchaka8be17402016-09-11 14:48:16 +0300625 cp1 = (const int16_t *)fragment->buf;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200626 len1 = fragment->len >> 1;
Serhiy Storchaka8be17402016-09-11 14:48:16 +0300627 cp2 = (const int16_t *)reference->buf;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200628 len2 = reference->len >> 1;
Jack Jansena90805f1993-02-17 14:29:28 +0000629
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200630 if (len1 < len2) {
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400631 PyErr_SetString(_audioopstate(module)->AudioopError, "First sample should be longer");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200632 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000633 }
634 sum_ri_2 = _sum2(cp2, cp2, len2);
635 sum_aij_2 = _sum2(cp1, cp1, len2);
636 sum_aij_ri = _sum2(cp1, cp2, len2);
Jack Jansena90805f1993-02-17 14:29:28 +0000637
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000638 result = (sum_ri_2*sum_aij_2 - sum_aij_ri*sum_aij_ri) / sum_aij_2;
Jack Jansena90805f1993-02-17 14:29:28 +0000639
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000640 best_result = result;
641 best_j = 0;
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000642
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000643 for ( j=1; j<=len1-len2; j++) {
644 aj_m1 = (double)cp1[j-1];
645 aj_lm1 = (double)cp1[j+len2-1];
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000646
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000647 sum_aij_2 = sum_aij_2 + aj_lm1*aj_lm1 - aj_m1*aj_m1;
648 sum_aij_ri = _sum2(cp1+j, cp2, len2);
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000649
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000650 result = (sum_ri_2*sum_aij_2 - sum_aij_ri*sum_aij_ri)
651 / sum_aij_2;
652
653 if ( result < best_result ) {
654 best_result = result;
655 best_j = j;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000656 }
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000657
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000658 }
659
660 factor = _sum2(cp1+best_j, cp2, len2) / sum_ri_2;
661
Mark Dickinson81fece22010-05-11 13:34:35 +0000662 return Py_BuildValue("(nf)", best_j, factor);
Jack Jansena90805f1993-02-17 14:29:28 +0000663}
664
665/*
666** findfactor finds a factor f so that the energy in A-fB is minimal.
667** See the comment for findfit for details.
668*/
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200669/*[clinic input]
670audioop.findfactor
671
672 fragment: Py_buffer
673 reference: Py_buffer
674 /
675
676Return a factor F such that rms(add(fragment, mul(reference, -F))) is minimal.
677[clinic start generated code]*/
678
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000679static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300680audioop_findfactor_impl(PyObject *module, Py_buffer *fragment,
Larry Hastings89964c42015-04-14 18:07:59 -0400681 Py_buffer *reference)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300682/*[clinic end generated code: output=14ea95652c1afcf8 input=816680301d012b21]*/
Jack Jansena90805f1993-02-17 14:29:28 +0000683{
Serhiy Storchaka8be17402016-09-11 14:48:16 +0300684 const int16_t *cp1, *cp2;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200685 Py_ssize_t len;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000686 double sum_ri_2, sum_aij_ri, result;
Jack Jansena90805f1993-02-17 14:29:28 +0000687
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200688 if (fragment->len & 1 || reference->len & 1) {
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400689 PyErr_SetString(_audioopstate(module)->AudioopError, "Strings should be even-sized");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200690 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000691 }
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200692 if (fragment->len != reference->len) {
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400693 PyErr_SetString(_audioopstate(module)->AudioopError, "Samples should be same size");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200694 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000695 }
Serhiy Storchaka8be17402016-09-11 14:48:16 +0300696 cp1 = (const int16_t *)fragment->buf;
697 cp2 = (const int16_t *)reference->buf;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200698 len = fragment->len >> 1;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200699 sum_ri_2 = _sum2(cp2, cp2, len);
700 sum_aij_ri = _sum2(cp1, cp2, len);
Jack Jansena90805f1993-02-17 14:29:28 +0000701
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000702 result = sum_aij_ri / sum_ri_2;
Jack Jansena90805f1993-02-17 14:29:28 +0000703
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000704 return PyFloat_FromDouble(result);
Jack Jansena90805f1993-02-17 14:29:28 +0000705}
706
707/*
708** findmax returns the index of the n-sized segment of the input sample
709** that contains the most energy.
710*/
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200711/*[clinic input]
712audioop.findmax
713
714 fragment: Py_buffer
715 length: Py_ssize_t
716 /
717
718Search fragment for a slice of specified number of samples with maximum energy.
719[clinic start generated code]*/
720
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000721static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300722audioop_findmax_impl(PyObject *module, Py_buffer *fragment,
Larry Hastings89964c42015-04-14 18:07:59 -0400723 Py_ssize_t length)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300724/*[clinic end generated code: output=f008128233523040 input=2f304801ed42383c]*/
Jack Jansena90805f1993-02-17 14:29:28 +0000725{
Serhiy Storchaka8be17402016-09-11 14:48:16 +0300726 const int16_t *cp1;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200727 Py_ssize_t len1;
Mark Dickinson81fece22010-05-11 13:34:35 +0000728 Py_ssize_t j, best_j;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000729 double aj_m1, aj_lm1;
730 double result, best_result;
Jack Jansena90805f1993-02-17 14:29:28 +0000731
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200732 if (fragment->len & 1) {
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400733 PyErr_SetString(_audioopstate(module)->AudioopError, "Strings should be even-sized");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200734 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000735 }
Serhiy Storchaka8be17402016-09-11 14:48:16 +0300736 cp1 = (const int16_t *)fragment->buf;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200737 len1 = fragment->len >> 1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000738
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200739 if (length < 0 || len1 < length) {
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400740 PyErr_SetString(_audioopstate(module)->AudioopError, "Input sample should be longer");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200741 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000742 }
743
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200744 result = _sum2(cp1, cp1, length);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000745
746 best_result = result;
747 best_j = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000748
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200749 for ( j=1; j<=len1-length; j++) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000750 aj_m1 = (double)cp1[j-1];
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200751 aj_lm1 = (double)cp1[j+length-1];
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000752
753 result = result + aj_lm1*aj_lm1 - aj_m1*aj_m1;
754
755 if ( result > best_result ) {
756 best_result = result;
757 best_j = j;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000758 }
Jack Jansena90805f1993-02-17 14:29:28 +0000759
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000760 }
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000761
Mark Dickinson81fece22010-05-11 13:34:35 +0000762 return PyLong_FromSsize_t(best_j);
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000763}
764
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200765/*[clinic input]
766audioop.avgpp
767
768 fragment: Py_buffer
769 width: int
770 /
771
772Return the average peak-peak value over all samples in the fragment.
773[clinic start generated code]*/
774
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000775static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300776audioop_avgpp_impl(PyObject *module, Py_buffer *fragment, int width)
777/*[clinic end generated code: output=269596b0d5ae0b2b input=0b3cceeae420a7d9]*/
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000778{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200779 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200780 int prevval, prevextremevalid = 0, prevextreme = 0;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200781 double sum = 0.0;
782 unsigned int avg;
783 int diff, prevdiff, nextreme = 0;
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000784
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400785 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000786 return NULL;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200787 if (fragment->len <= width)
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200788 return PyLong_FromLong(0);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200789 prevval = GETRAWSAMPLE(width, fragment->buf, 0);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200790 prevdiff = 17; /* Anything != 0, 1 */
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200791 for (i = width; i < fragment->len; i += width) {
792 int val = GETRAWSAMPLE(width, fragment->buf, i);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200793 if (val != prevval) {
794 diff = val < prevval;
795 if (prevdiff == !diff) {
796 /* Derivative changed sign. Compute difference to last
797 ** extreme value and remember.
798 */
799 if (prevextremevalid) {
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300800 if (prevval < prevextreme)
801 sum += (double)((unsigned int)prevextreme -
802 (unsigned int)prevval);
803 else
804 sum += (double)((unsigned int)prevval -
805 (unsigned int)prevextreme);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200806 nextreme++;
807 }
808 prevextremevalid = 1;
809 prevextreme = prevval;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000810 }
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200811 prevval = val;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000812 prevdiff = diff;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200813 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000814 }
815 if ( nextreme == 0 )
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200816 avg = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000817 else
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200818 avg = (unsigned int)(sum / (double)nextreme);
819 return PyLong_FromUnsignedLong(avg);
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000820}
821
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200822/*[clinic input]
823audioop.maxpp
824
825 fragment: Py_buffer
826 width: int
827 /
828
829Return the maximum peak-peak value in the sound fragment.
830[clinic start generated code]*/
831
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000832static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300833audioop_maxpp_impl(PyObject *module, Py_buffer *fragment, int width)
834/*[clinic end generated code: output=5b918ed5dbbdb978 input=671a13e1518f80a1]*/
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000835{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200836 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200837 int prevval, prevextremevalid = 0, prevextreme = 0;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200838 unsigned int max = 0, extremediff;
839 int diff, prevdiff;
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000840
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400841 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000842 return NULL;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200843 if (fragment->len <= width)
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200844 return PyLong_FromLong(0);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200845 prevval = GETRAWSAMPLE(width, fragment->buf, 0);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200846 prevdiff = 17; /* Anything != 0, 1 */
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200847 for (i = width; i < fragment->len; i += width) {
848 int val = GETRAWSAMPLE(width, fragment->buf, i);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200849 if (val != prevval) {
850 diff = val < prevval;
851 if (prevdiff == !diff) {
852 /* Derivative changed sign. Compute difference to
853 ** last extreme value and remember.
854 */
855 if (prevextremevalid) {
856 if (prevval < prevextreme)
857 extremediff = (unsigned int)prevextreme -
858 (unsigned int)prevval;
859 else
860 extremediff = (unsigned int)prevval -
861 (unsigned int)prevextreme;
862 if ( extremediff > max )
863 max = extremediff;
864 }
865 prevextremevalid = 1;
866 prevextreme = prevval;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000867 }
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200868 prevval = val;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000869 prevdiff = diff;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200870 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000871 }
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200872 return PyLong_FromUnsignedLong(max);
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000873}
874
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200875/*[clinic input]
876audioop.cross
877
878 fragment: Py_buffer
879 width: int
880 /
881
882Return the number of zero crossings in the fragment passed as an argument.
883[clinic start generated code]*/
884
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000885static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300886audioop_cross_impl(PyObject *module, Py_buffer *fragment, int width)
887/*[clinic end generated code: output=5938dcdd74a1f431 input=b1b3f15b83f6b41a]*/
Guido van Rossumb66efa01992-06-01 16:01:24 +0000888{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200889 Py_ssize_t i;
Mark Dickinson81fece22010-05-11 13:34:35 +0000890 int prevval;
891 Py_ssize_t ncross;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000892
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400893 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000894 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000895 ncross = -1;
896 prevval = 17; /* Anything <> 0,1 */
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200897 for (i = 0; i < fragment->len; i += width) {
898 int val = GETRAWSAMPLE(width, fragment->buf, i) < 0;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300899 if (val != prevval) ncross++;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000900 prevval = val;
901 }
Mark Dickinson81fece22010-05-11 13:34:35 +0000902 return PyLong_FromSsize_t(ncross);
Guido van Rossumb66efa01992-06-01 16:01:24 +0000903}
904
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200905/*[clinic input]
906audioop.mul
907
908 fragment: Py_buffer
909 width: int
910 factor: double
911 /
912
913Return a fragment that has all samples in the original fragment multiplied by the floating-point value factor.
914[clinic start generated code]*/
915
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000916static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300917audioop_mul_impl(PyObject *module, Py_buffer *fragment, int width,
Larry Hastings89964c42015-04-14 18:07:59 -0400918 double factor)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300919/*[clinic end generated code: output=6cd48fe796da0ea4 input=c726667baa157d3c]*/
Guido van Rossumb66efa01992-06-01 16:01:24 +0000920{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200921 signed char *ncp;
922 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200923 double maxval, minval;
924 PyObject *rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000925
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400926 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000927 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000928
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200929 maxval = (double) maxvals[width];
930 minval = (double) minvals[width];
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000931
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200932 rv = PyBytes_FromStringAndSize(NULL, fragment->len);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200933 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200934 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000935 ncp = (signed char *)PyBytes_AsString(rv);
936
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200937 for (i = 0; i < fragment->len; i += width) {
938 double val = GETRAWSAMPLE(width, fragment->buf, i);
Victor Stinner45e4efb2018-06-06 15:50:50 +0200939 int ival = fbound(val * factor, minval, maxval);
940 SETRAWSAMPLE(width, ncp, i, ival);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000941 }
942 return rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000943}
944
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200945/*[clinic input]
946audioop.tomono
947
948 fragment: Py_buffer
949 width: int
950 lfactor: double
951 rfactor: double
952 /
953
954Convert a stereo fragment to a mono fragment.
955[clinic start generated code]*/
956
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000957static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300958audioop_tomono_impl(PyObject *module, Py_buffer *fragment, int width,
Larry Hastings89964c42015-04-14 18:07:59 -0400959 double lfactor, double rfactor)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300960/*[clinic end generated code: output=235c8277216d4e4e input=c4ec949b3f4dddfa]*/
Guido van Rossumb66efa01992-06-01 16:01:24 +0000961{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000962 signed char *cp, *ncp;
Mark Dickinson81fece22010-05-11 13:34:35 +0000963 Py_ssize_t len, i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200964 double maxval, minval;
965 PyObject *rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000966
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200967 cp = fragment->buf;
968 len = fragment->len;
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400969 if (!audioop_check_parameters(module, len, width))
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200970 return NULL;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200971 if (((len / width) & 1) != 0) {
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400972 PyErr_SetString(_audioopstate(module)->AudioopError, "not a whole number of frames");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200973 return NULL;
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000974 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000975
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200976 maxval = (double) maxvals[width];
977 minval = (double) minvals[width];
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000978
979 rv = PyBytes_FromStringAndSize(NULL, len/2);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200980 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200981 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000982 ncp = (signed char *)PyBytes_AsString(rv);
983
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200984 for (i = 0; i < len; i += width*2) {
985 double val1 = GETRAWSAMPLE(width, cp, i);
986 double val2 = GETRAWSAMPLE(width, cp, i + width);
Victor Stinner45e4efb2018-06-06 15:50:50 +0200987 double val = val1 * lfactor + val2 * rfactor;
988 int ival = fbound(val, minval, maxval);
989 SETRAWSAMPLE(width, ncp, i/2, ival);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000990 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000991 return rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000992}
993
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200994/*[clinic input]
995audioop.tostereo
996
997 fragment: Py_buffer
998 width: int
999 lfactor: double
1000 rfactor: double
1001 /
1002
1003Generate a stereo fragment from a mono fragment.
1004[clinic start generated code]*/
1005
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001006static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001007audioop_tostereo_impl(PyObject *module, Py_buffer *fragment, int width,
Larry Hastings89964c42015-04-14 18:07:59 -04001008 double lfactor, double rfactor)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001009/*[clinic end generated code: output=046f13defa5f1595 input=27b6395ebfdff37a]*/
Guido van Rossumb66efa01992-06-01 16:01:24 +00001010{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001011 signed char *ncp;
1012 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001013 double maxval, minval;
1014 PyObject *rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001015
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001016 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001017 return NULL;
Amaury Forgeot d'Arc9c74b142008-06-18 00:47:36 +00001018
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001019 maxval = (double) maxvals[width];
1020 minval = (double) minvals[width];
Guido van Rossumb66efa01992-06-01 16:01:24 +00001021
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001022 if (fragment->len > PY_SSIZE_T_MAX/2) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001023 PyErr_SetString(PyExc_MemoryError,
1024 "not enough memory for output buffer");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001025 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001026 }
Guido van Rossumb66efa01992-06-01 16:01:24 +00001027
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001028 rv = PyBytes_FromStringAndSize(NULL, fragment->len*2);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001029 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001030 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001031 ncp = (signed char *)PyBytes_AsString(rv);
Guido van Rossumb66efa01992-06-01 16:01:24 +00001032
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001033 for (i = 0; i < fragment->len; i += width) {
1034 double val = GETRAWSAMPLE(width, fragment->buf, i);
Victor Stinner45e4efb2018-06-06 15:50:50 +02001035 int val1 = fbound(val * lfactor, minval, maxval);
1036 int val2 = fbound(val * rfactor, minval, maxval);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001037 SETRAWSAMPLE(width, ncp, i*2, val1);
1038 SETRAWSAMPLE(width, ncp, i*2 + width, val2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001039 }
1040 return rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001041}
1042
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001043/*[clinic input]
1044audioop.add
1045
1046 fragment1: Py_buffer
1047 fragment2: Py_buffer
1048 width: int
1049 /
1050
1051Return a fragment which is the addition of the two samples passed as parameters.
1052[clinic start generated code]*/
1053
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001054static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001055audioop_add_impl(PyObject *module, Py_buffer *fragment1,
Larry Hastings89964c42015-04-14 18:07:59 -04001056 Py_buffer *fragment2, int width)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001057/*[clinic end generated code: output=60140af4d1aab6f2 input=4a8d4bae4c1605c7]*/
Guido van Rossumb66efa01992-06-01 16:01:24 +00001058{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001059 signed char *ncp;
1060 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001061 int minval, maxval, newval;
1062 PyObject *rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001063
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001064 if (!audioop_check_parameters(module, fragment1->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001065 return NULL;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001066 if (fragment1->len != fragment2->len) {
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001067 PyErr_SetString(_audioopstate(module)->AudioopError, "Lengths should be the same");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001068 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001069 }
Guido van Rossum1851a671997-02-14 16:14:03 +00001070
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001071 maxval = maxvals[width];
1072 minval = minvals[width];
Guido van Rossum1851a671997-02-14 16:14:03 +00001073
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001074 rv = PyBytes_FromStringAndSize(NULL, fragment1->len);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001075 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001076 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001077 ncp = (signed char *)PyBytes_AsString(rv);
Guido van Rossumb66efa01992-06-01 16:01:24 +00001078
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001079 for (i = 0; i < fragment1->len; i += width) {
1080 int val1 = GETRAWSAMPLE(width, fragment1->buf, i);
1081 int val2 = GETRAWSAMPLE(width, fragment2->buf, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001082
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001083 if (width < 4) {
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001084 newval = val1 + val2;
1085 /* truncate in case of overflow */
1086 if (newval > maxval)
1087 newval = maxval;
1088 else if (newval < minval)
1089 newval = minval;
1090 }
1091 else {
1092 double fval = (double)val1 + (double)val2;
1093 /* truncate in case of overflow */
Victor Stinner45e4efb2018-06-06 15:50:50 +02001094 newval = fbound(fval, minval, maxval);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001095 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001096
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001097 SETRAWSAMPLE(width, ncp, i, newval);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001098 }
1099 return rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001100}
1101
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001102/*[clinic input]
1103audioop.bias
1104
1105 fragment: Py_buffer
1106 width: int
1107 bias: int
1108 /
1109
1110Return a fragment that is the original fragment with a bias added to each sample.
1111[clinic start generated code]*/
1112
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001113static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001114audioop_bias_impl(PyObject *module, Py_buffer *fragment, int width, int bias)
1115/*[clinic end generated code: output=6e0aa8f68f045093 input=2b5cce5c3bb4838c]*/
Guido van Rossumb66efa01992-06-01 16:01:24 +00001116{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001117 signed char *ncp;
1118 Py_ssize_t i;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001119 unsigned int val = 0, mask;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001120 PyObject *rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001121
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001122 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001123 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001124
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001125 rv = PyBytes_FromStringAndSize(NULL, fragment->len);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001126 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001127 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001128 ncp = (signed char *)PyBytes_AsString(rv);
1129
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001130 mask = masks[width];
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001131
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001132 for (i = 0; i < fragment->len; i += width) {
1133 if (width == 1)
1134 val = GETINTX(unsigned char, fragment->buf, i);
1135 else if (width == 2)
Serhiy Storchaka8be17402016-09-11 14:48:16 +03001136 val = GETINTX(uint16_t, fragment->buf, i);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001137 else if (width == 3)
1138 val = ((unsigned int)GETINT24(fragment->buf, i)) & 0xffffffu;
Serhiy Storchakace82eb22013-10-20 09:42:26 +03001139 else {
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001140 assert(width == 4);
Benjamin Peterson9b3d7702016-09-06 13:24:00 -07001141 val = GETINTX(uint32_t, fragment->buf, i);
Serhiy Storchakace82eb22013-10-20 09:42:26 +03001142 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001143
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001144 val += (unsigned int)bias;
1145 /* wrap around in case of overflow */
1146 val &= mask;
1147
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001148 if (width == 1)
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001149 SETINTX(unsigned char, ncp, i, val);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001150 else if (width == 2)
Serhiy Storchaka8be17402016-09-11 14:48:16 +03001151 SETINTX(uint16_t, ncp, i, val);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001152 else if (width == 3)
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001153 SETINT24(ncp, i, (int)val);
Serhiy Storchakace82eb22013-10-20 09:42:26 +03001154 else {
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001155 assert(width == 4);
Benjamin Peterson9b3d7702016-09-06 13:24:00 -07001156 SETINTX(uint32_t, ncp, i, val);
Serhiy Storchakace82eb22013-10-20 09:42:26 +03001157 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001158 }
1159 return rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001160}
1161
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001162/*[clinic input]
1163audioop.reverse
1164
1165 fragment: Py_buffer
1166 width: int
1167 /
1168
1169Reverse the samples in a fragment and returns the modified fragment.
1170[clinic start generated code]*/
1171
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001172static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001173audioop_reverse_impl(PyObject *module, Py_buffer *fragment, int width)
1174/*[clinic end generated code: output=b44135698418da14 input=668f890cf9f9d225]*/
Jack Jansen337b20e1993-02-23 13:39:57 +00001175{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001176 unsigned char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001177 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001178 PyObject *rv;
Jack Jansen337b20e1993-02-23 13:39:57 +00001179
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001180 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001181 return NULL;
Jack Jansen337b20e1993-02-23 13:39:57 +00001182
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001183 rv = PyBytes_FromStringAndSize(NULL, fragment->len);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001184 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001185 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001186 ncp = (unsigned char *)PyBytes_AsString(rv);
1187
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001188 for (i = 0; i < fragment->len; i += width) {
1189 int val = GETRAWSAMPLE(width, fragment->buf, i);
1190 SETRAWSAMPLE(width, ncp, fragment->len - i - width, val);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001191 }
1192 return rv;
Jack Jansen337b20e1993-02-23 13:39:57 +00001193}
1194
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001195/*[clinic input]
1196audioop.byteswap
1197
1198 fragment: Py_buffer
1199 width: int
1200 /
1201
1202Convert big-endian samples to little-endian and vice versa.
1203[clinic start generated code]*/
1204
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001205static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001206audioop_byteswap_impl(PyObject *module, Py_buffer *fragment, int width)
1207/*[clinic end generated code: output=50838a9e4b87cd4d input=fae7611ceffa5c82]*/
Serhiy Storchaka3062c9a2013-11-23 22:26:01 +02001208{
Serhiy Storchaka3062c9a2013-11-23 22:26:01 +02001209 unsigned char *ncp;
1210 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001211 PyObject *rv;
Serhiy Storchaka3062c9a2013-11-23 22:26:01 +02001212
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001213 if (!audioop_check_parameters(module, fragment->len, width))
Serhiy Storchaka3062c9a2013-11-23 22:26:01 +02001214 return NULL;
1215
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001216 rv = PyBytes_FromStringAndSize(NULL, fragment->len);
Serhiy Storchaka3062c9a2013-11-23 22:26:01 +02001217 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001218 return NULL;
Serhiy Storchaka3062c9a2013-11-23 22:26:01 +02001219 ncp = (unsigned char *)PyBytes_AsString(rv);
1220
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001221 for (i = 0; i < fragment->len; i += width) {
Serhiy Storchaka3062c9a2013-11-23 22:26:01 +02001222 int j;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001223 for (j = 0; j < width; j++)
1224 ncp[i + width - 1 - j] = ((unsigned char *)fragment->buf)[i + j];
Serhiy Storchaka3062c9a2013-11-23 22:26:01 +02001225 }
Serhiy Storchaka3062c9a2013-11-23 22:26:01 +02001226 return rv;
1227}
1228
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001229/*[clinic input]
1230audioop.lin2lin
1231
1232 fragment: Py_buffer
1233 width: int
1234 newwidth: int
1235 /
1236
1237Convert samples between 1-, 2-, 3- and 4-byte formats.
1238[clinic start generated code]*/
1239
Serhiy Storchaka3062c9a2013-11-23 22:26:01 +02001240static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001241audioop_lin2lin_impl(PyObject *module, Py_buffer *fragment, int width,
Larry Hastings89964c42015-04-14 18:07:59 -04001242 int newwidth)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001243/*[clinic end generated code: output=17b14109248f1d99 input=5ce08c8aa2f24d96]*/
Jack Jansena90805f1993-02-17 14:29:28 +00001244{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001245 unsigned char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001246 Py_ssize_t i, j;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001247 PyObject *rv;
Jack Jansena90805f1993-02-17 14:29:28 +00001248
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001249 if (!audioop_check_parameters(module, fragment->len, width))
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001250 return NULL;
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001251 if (!audioop_check_size(module, newwidth))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001252 return NULL;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001253
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001254 if (fragment->len/width > PY_SSIZE_T_MAX/newwidth) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001255 PyErr_SetString(PyExc_MemoryError,
1256 "not enough memory for output buffer");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001257 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001258 }
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001259 rv = PyBytes_FromStringAndSize(NULL, (fragment->len/width)*newwidth);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001260 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001261 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001262 ncp = (unsigned char *)PyBytes_AsString(rv);
1263
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001264 for (i = j = 0; i < fragment->len; i += width, j += newwidth) {
1265 int val = GETSAMPLE32(width, fragment->buf, i);
1266 SETSAMPLE32(newwidth, ncp, j, val);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001267 }
1268 return rv;
Jack Jansena90805f1993-02-17 14:29:28 +00001269}
1270
Guido van Rossumb24c9ea1997-05-20 15:59:35 +00001271static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00001272gcd(int a, int b)
Guido van Rossumb24c9ea1997-05-20 15:59:35 +00001273{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001274 while (b > 0) {
1275 int tmp = a % b;
1276 a = b;
1277 b = tmp;
1278 }
1279 return a;
Guido van Rossumb24c9ea1997-05-20 15:59:35 +00001280}
1281
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001282/*[clinic input]
1283audioop.ratecv
1284
1285 fragment: Py_buffer
1286 width: int
1287 nchannels: int
1288 inrate: int
1289 outrate: int
1290 state: object
1291 weightA: int = 1
1292 weightB: int = 0
1293 /
1294
1295Convert the frame rate of the input fragment.
1296[clinic start generated code]*/
1297
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001298static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001299audioop_ratecv_impl(PyObject *module, Py_buffer *fragment, int width,
Larry Hastings89964c42015-04-14 18:07:59 -04001300 int nchannels, int inrate, int outrate, PyObject *state,
1301 int weightA, int weightB)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001302/*[clinic end generated code: output=624038e843243139 input=aff3acdc94476191]*/
Roger E. Massec905fff1997-01-17 18:12:04 +00001303{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001304 char *cp, *ncp;
Mark Dickinson81fece22010-05-11 13:34:35 +00001305 Py_ssize_t len;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001306 int chan, d, *prev_i, *cur_i, cur_o;
Oren Milman1d1d3e92017-08-20 18:35:36 +03001307 PyObject *samps, *str, *rv = NULL, *channel;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001308 int bytes_per_frame;
Guido van Rossum1851a671997-02-14 16:14:03 +00001309
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001310 if (!audioop_check_size(module, width))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001311 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001312 if (nchannels < 1) {
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001313 PyErr_SetString(_audioopstate(module)->AudioopError, "# of channels should be >= 1");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001314 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001315 }
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001316 if (width > INT_MAX / nchannels) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001317 /* This overflow test is rigorously correct because
1318 both multiplicands are >= 1. Use the argument names
1319 from the docs for the error msg. */
1320 PyErr_SetString(PyExc_OverflowError,
1321 "width * nchannels too big for a C int");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001322 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001323 }
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001324 bytes_per_frame = width * nchannels;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001325 if (weightA < 1 || weightB < 0) {
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001326 PyErr_SetString(_audioopstate(module)->AudioopError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001327 "weightA should be >= 1, weightB should be >= 0");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001328 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001329 }
Christian Heimesc4ab9a42014-01-27 01:12:00 +01001330 assert(fragment->len >= 0);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001331 if (fragment->len % bytes_per_frame != 0) {
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001332 PyErr_SetString(_audioopstate(module)->AudioopError, "not a whole number of frames");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001333 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001334 }
1335 if (inrate <= 0 || outrate <= 0) {
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001336 PyErr_SetString(_audioopstate(module)->AudioopError, "sampling rate not > 0");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001337 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001338 }
1339 /* divide inrate and outrate by their greatest common divisor */
1340 d = gcd(inrate, outrate);
1341 inrate /= d;
1342 outrate /= d;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001343 /* divide weightA and weightB by their greatest common divisor */
1344 d = gcd(weightA, weightB);
1345 weightA /= d;
Serhiy Storchaka50451eb2015-05-30 00:53:26 +03001346 weightB /= d;
Guido van Rossumb24c9ea1997-05-20 15:59:35 +00001347
Benjamin Peterson2f8bfef2016-09-07 09:26:18 -07001348 if ((size_t)nchannels > SIZE_MAX/sizeof(int)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001349 PyErr_SetString(PyExc_MemoryError,
1350 "not enough memory for output buffer");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001351 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001352 }
Victor Stinnerb6404912013-07-07 16:21:41 +02001353 prev_i = (int *) PyMem_Malloc(nchannels * sizeof(int));
1354 cur_i = (int *) PyMem_Malloc(nchannels * sizeof(int));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001355 if (prev_i == NULL || cur_i == NULL) {
1356 (void) PyErr_NoMemory();
1357 goto exit;
1358 }
1359
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001360 len = fragment->len / bytes_per_frame; /* # of frames */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001361
1362 if (state == Py_None) {
1363 d = -outrate;
1364 for (chan = 0; chan < nchannels; chan++)
1365 prev_i[chan] = cur_i[chan] = 0;
1366 }
1367 else {
Oren Milman1d1d3e92017-08-20 18:35:36 +03001368 if (!PyTuple_Check(state)) {
1369 PyErr_SetString(PyExc_TypeError, "state must be a tuple or None");
1370 goto exit;
1371 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001372 if (!PyArg_ParseTuple(state,
Oren Milman1d1d3e92017-08-20 18:35:36 +03001373 "iO!;ratecv(): illegal state argument",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001374 &d, &PyTuple_Type, &samps))
1375 goto exit;
1376 if (PyTuple_Size(samps) != nchannels) {
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001377 PyErr_SetString(_audioopstate(module)->AudioopError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001378 "illegal state argument");
1379 goto exit;
Amaury Forgeot d'Arc9c74b142008-06-18 00:47:36 +00001380 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001381 for (chan = 0; chan < nchannels; chan++) {
Oren Milman1d1d3e92017-08-20 18:35:36 +03001382 channel = PyTuple_GetItem(samps, chan);
1383 if (!PyTuple_Check(channel)) {
1384 PyErr_SetString(PyExc_TypeError,
1385 "ratecv(): illegal state argument");
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001386 goto exit;
Oren Milman1d1d3e92017-08-20 18:35:36 +03001387 }
1388 if (!PyArg_ParseTuple(channel,
1389 "ii;ratecv(): illegal state argument",
1390 &prev_i[chan], &cur_i[chan]))
1391 {
1392 goto exit;
1393 }
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001394 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001395 }
Guido van Rossum1851a671997-02-14 16:14:03 +00001396
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001397 /* str <- Space for the output buffer. */
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001398 if (len == 0)
1399 str = PyBytes_FromStringAndSize(NULL, 0);
1400 else {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001401 /* There are len input frames, so we need (mathematically)
1402 ceiling(len*outrate/inrate) output frames, and each frame
1403 requires bytes_per_frame bytes. Computing this
1404 without spurious overflow is the challenge; we can
Mark Dickinson393b97a2010-05-11 13:09:58 +00001405 settle for a reasonable upper bound, though, in this
1406 case ceiling(len/inrate) * outrate. */
1407
1408 /* compute ceiling(len/inrate) without overflow */
Christian Heimesc4ab9a42014-01-27 01:12:00 +01001409 Py_ssize_t q = 1 + (len - 1) / inrate;
Mark Dickinson81fece22010-05-11 13:34:35 +00001410 if (outrate > PY_SSIZE_T_MAX / q / bytes_per_frame)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001411 str = NULL;
1412 else
Mark Dickinson393b97a2010-05-11 13:09:58 +00001413 str = PyBytes_FromStringAndSize(NULL,
1414 q * outrate * bytes_per_frame);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001415 }
1416 if (str == NULL) {
1417 PyErr_SetString(PyExc_MemoryError,
1418 "not enough memory for output buffer");
1419 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001420 }
1421 ncp = PyBytes_AsString(str);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001422 cp = fragment->buf;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001423
1424 for (;;) {
1425 while (d < 0) {
1426 if (len == 0) {
1427 samps = PyTuple_New(nchannels);
1428 if (samps == NULL)
1429 goto exit;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001430 for (chan = 0; chan < nchannels; chan++)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001431 PyTuple_SetItem(samps, chan,
1432 Py_BuildValue("(ii)",
1433 prev_i[chan],
1434 cur_i[chan]));
1435 if (PyErr_Occurred())
1436 goto exit;
1437 /* We have checked before that the length
1438 * of the string fits into int. */
Mark Dickinson81fece22010-05-11 13:34:35 +00001439 len = (Py_ssize_t)(ncp - PyBytes_AsString(str));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001440 rv = PyBytes_FromStringAndSize
1441 (PyBytes_AsString(str), len);
1442 Py_DECREF(str);
1443 str = rv;
1444 if (str == NULL)
1445 goto exit;
1446 rv = Py_BuildValue("(O(iO))", str, d, samps);
1447 Py_DECREF(samps);
1448 Py_DECREF(str);
1449 goto exit; /* return rv */
1450 }
1451 for (chan = 0; chan < nchannels; chan++) {
1452 prev_i[chan] = cur_i[chan];
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001453 cur_i[chan] = GETSAMPLE32(width, cp, 0);
1454 cp += width;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001455 /* implements a simple digital filter */
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001456 cur_i[chan] = (int)(
1457 ((double)weightA * (double)cur_i[chan] +
1458 (double)weightB * (double)prev_i[chan]) /
1459 ((double)weightA + (double)weightB));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001460 }
1461 len--;
1462 d += outrate;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001463 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001464 while (d >= 0) {
1465 for (chan = 0; chan < nchannels; chan++) {
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001466 cur_o = (int)(((double)prev_i[chan] * (double)d +
1467 (double)cur_i[chan] * (double)(outrate - d)) /
1468 (double)outrate);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001469 SETSAMPLE32(width, ncp, 0, cur_o);
1470 ncp += width;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001471 }
1472 d -= inrate;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001473 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001474 }
Guido van Rossum65bb3281999-09-07 14:24:05 +00001475 exit:
Victor Stinnerb6404912013-07-07 16:21:41 +02001476 PyMem_Free(prev_i);
1477 PyMem_Free(cur_i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001478 return rv;
Roger E. Massec905fff1997-01-17 18:12:04 +00001479}
Guido van Rossum1851a671997-02-14 16:14:03 +00001480
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001481/*[clinic input]
1482audioop.lin2ulaw
1483
1484 fragment: Py_buffer
1485 width: int
1486 /
1487
1488Convert samples in the audio fragment to u-LAW encoding.
1489[clinic start generated code]*/
1490
Roger E. Massec905fff1997-01-17 18:12:04 +00001491static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001492audioop_lin2ulaw_impl(PyObject *module, Py_buffer *fragment, int width)
1493/*[clinic end generated code: output=14fb62b16fe8ea8e input=2450d1b870b6bac2]*/
Guido van Rossumb66efa01992-06-01 16:01:24 +00001494{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001495 unsigned char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001496 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001497 PyObject *rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001498
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001499 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001500 return NULL;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001501
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001502 rv = PyBytes_FromStringAndSize(NULL, fragment->len/width);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001503 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001504 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001505 ncp = (unsigned char *)PyBytes_AsString(rv);
1506
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001507 for (i = 0; i < fragment->len; i += width) {
1508 int val = GETSAMPLE32(width, fragment->buf, i);
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001509 *ncp++ = st_14linear2ulaw(val >> 18);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001510 }
1511 return rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001512}
1513
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001514/*[clinic input]
1515audioop.ulaw2lin
1516
1517 fragment: Py_buffer
1518 width: int
1519 /
1520
1521Convert sound fragments in u-LAW encoding to linearly encoded sound fragments.
1522[clinic start generated code]*/
1523
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001524static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001525audioop_ulaw2lin_impl(PyObject *module, Py_buffer *fragment, int width)
1526/*[clinic end generated code: output=378356b047521ba2 input=45d53ddce5be7d06]*/
Guido van Rossumb66efa01992-06-01 16:01:24 +00001527{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001528 unsigned char *cp;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001529 signed char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001530 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001531 PyObject *rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001532
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001533 if (!audioop_check_size(module, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001534 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001535
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001536 if (fragment->len > PY_SSIZE_T_MAX/width) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001537 PyErr_SetString(PyExc_MemoryError,
1538 "not enough memory for output buffer");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001539 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001540 }
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001541 rv = PyBytes_FromStringAndSize(NULL, fragment->len*width);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001542 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001543 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001544 ncp = (signed char *)PyBytes_AsString(rv);
1545
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001546 cp = fragment->buf;
1547 for (i = 0; i < fragment->len*width; i += width) {
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001548 int val = st_ulaw2linear16(*cp++) << 16;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001549 SETSAMPLE32(width, ncp, i, val);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001550 }
1551 return rv;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001552}
1553
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001554/*[clinic input]
1555audioop.lin2alaw
1556
1557 fragment: Py_buffer
1558 width: int
1559 /
1560
1561Convert samples in the audio fragment to a-LAW encoding.
1562[clinic start generated code]*/
1563
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001564static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001565audioop_lin2alaw_impl(PyObject *module, Py_buffer *fragment, int width)
1566/*[clinic end generated code: output=d076f130121a82f0 input=ffb1ef8bb39da945]*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001567{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001568 unsigned char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001569 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001570 PyObject *rv;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001571
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001572 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001573 return NULL;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001574
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001575 rv = PyBytes_FromStringAndSize(NULL, fragment->len/width);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001576 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001577 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001578 ncp = (unsigned char *)PyBytes_AsString(rv);
1579
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001580 for (i = 0; i < fragment->len; i += width) {
1581 int val = GETSAMPLE32(width, fragment->buf, i);
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001582 *ncp++ = st_linear2alaw(val >> 19);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001583 }
1584 return rv;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001585}
1586
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001587/*[clinic input]
1588audioop.alaw2lin
1589
1590 fragment: Py_buffer
1591 width: int
1592 /
1593
1594Convert sound fragments in a-LAW encoding to linearly encoded sound fragments.
1595[clinic start generated code]*/
1596
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001597static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001598audioop_alaw2lin_impl(PyObject *module, Py_buffer *fragment, int width)
1599/*[clinic end generated code: output=85c365ec559df647 input=4140626046cd1772]*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001600{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001601 unsigned char *cp;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001602 signed char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001603 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001604 int val;
1605 PyObject *rv;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001606
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001607 if (!audioop_check_size(module, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001608 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001609
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001610 if (fragment->len > PY_SSIZE_T_MAX/width) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001611 PyErr_SetString(PyExc_MemoryError,
1612 "not enough memory for output buffer");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001613 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001614 }
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001615 rv = PyBytes_FromStringAndSize(NULL, fragment->len*width);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001616 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001617 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001618 ncp = (signed char *)PyBytes_AsString(rv);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001619 cp = fragment->buf;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001620
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001621 for (i = 0; i < fragment->len*width; i += width) {
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001622 val = st_alaw2linear16(*cp++) << 16;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001623 SETSAMPLE32(width, ncp, i, val);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001624 }
1625 return rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001626}
1627
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001628/*[clinic input]
1629audioop.lin2adpcm
1630
1631 fragment: Py_buffer
1632 width: int
1633 state: object
1634 /
1635
1636Convert samples to 4 bit Intel/DVI ADPCM encoding.
1637[clinic start generated code]*/
1638
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001639static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001640audioop_lin2adpcm_impl(PyObject *module, Py_buffer *fragment, int width,
Larry Hastings89964c42015-04-14 18:07:59 -04001641 PyObject *state)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001642/*[clinic end generated code: output=cc19f159f16c6793 input=12919d549b90c90a]*/
Guido van Rossumb64e6351992-07-06 14:21:56 +00001643{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001644 signed char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001645 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001646 int step, valpred, delta,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001647 index, sign, vpdiff, diff;
Benjamin Peterson08673c52014-01-26 10:24:24 -05001648 PyObject *rv = NULL, *str;
Mark Dickinson81fece22010-05-11 13:34:35 +00001649 int outputbuffer = 0, bufferstep;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001650
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001651 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001652 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001653
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001654 /* Decode state, should have (value, step) */
1655 if ( state == Py_None ) {
1656 /* First time, it seems. Set defaults */
1657 valpred = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001658 index = 0;
Benjamin Peterson08673c52014-01-26 10:24:24 -05001659 }
Serhiy Storchaka449e2be2015-06-28 17:52:09 +03001660 else if (!PyTuple_Check(state)) {
1661 PyErr_SetString(PyExc_TypeError, "state must be a tuple or None");
1662 return NULL;
1663 }
Oren Milman1d1d3e92017-08-20 18:35:36 +03001664 else if (!PyArg_ParseTuple(state, "ii;lin2adpcm(): illegal state argument",
1665 &valpred, &index))
1666 {
Serhiy Storchaka449e2be2015-06-28 17:52:09 +03001667 return NULL;
1668 }
1669 else if (valpred >= 0x8000 || valpred < -0x8000 ||
1670 (size_t)index >= Py_ARRAY_LENGTH(stepsizeTable)) {
1671 PyErr_SetString(PyExc_ValueError, "bad state");
1672 return NULL;
1673 }
1674
1675 str = PyBytes_FromStringAndSize(NULL, fragment->len/(width*2));
1676 if (str == NULL)
1677 return NULL;
1678 ncp = (signed char *)PyBytes_AsString(str);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001679
1680 step = stepsizeTable[index];
1681 bufferstep = 1;
1682
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001683 for (i = 0; i < fragment->len; i += width) {
1684 int val = GETSAMPLE32(width, fragment->buf, i) >> 16;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001685
1686 /* Step 1 - compute difference with previous value */
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001687 if (val < valpred) {
1688 diff = valpred - val;
1689 sign = 8;
1690 }
1691 else {
1692 diff = val - valpred;
1693 sign = 0;
1694 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001695
1696 /* Step 2 - Divide and clamp */
1697 /* Note:
1698 ** This code *approximately* computes:
1699 ** delta = diff*4/step;
1700 ** vpdiff = (delta+0.5)*step/4;
1701 ** but in shift step bits are dropped. The net result of this
1702 ** is that even if you have fast mul/div hardware you cannot
1703 ** put it to good use since the fixup would be too expensive.
1704 */
1705 delta = 0;
1706 vpdiff = (step >> 3);
1707
1708 if ( diff >= step ) {
1709 delta = 4;
1710 diff -= step;
1711 vpdiff += step;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001712 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001713 step >>= 1;
1714 if ( diff >= step ) {
1715 delta |= 2;
1716 diff -= step;
1717 vpdiff += step;
1718 }
1719 step >>= 1;
1720 if ( diff >= step ) {
1721 delta |= 1;
1722 vpdiff += step;
1723 }
Jack Jansendd8a6ea1993-02-17 14:21:09 +00001724
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001725 /* Step 3 - Update previous value */
1726 if ( sign )
1727 valpred -= vpdiff;
1728 else
1729 valpred += vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001730
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001731 /* Step 4 - Clamp previous value to 16 bits */
1732 if ( valpred > 32767 )
1733 valpred = 32767;
1734 else if ( valpred < -32768 )
1735 valpred = -32768;
1736
1737 /* Step 5 - Assemble value, update index and step values */
1738 delta |= sign;
1739
1740 index += indexTable[delta];
1741 if ( index < 0 ) index = 0;
1742 if ( index > 88 ) index = 88;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001743 step = stepsizeTable[index];
Guido van Rossumb64e6351992-07-06 14:21:56 +00001744
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001745 /* Step 6 - Output value */
1746 if ( bufferstep ) {
1747 outputbuffer = (delta << 4) & 0xf0;
1748 } else {
1749 *ncp++ = (delta & 0x0f) | outputbuffer;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001750 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001751 bufferstep = !bufferstep;
1752 }
1753 rv = Py_BuildValue("(O(ii))", str, valpred, index);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001754 Py_DECREF(str);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001755 return rv;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001756}
1757
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001758/*[clinic input]
1759audioop.adpcm2lin
1760
1761 fragment: Py_buffer
1762 width: int
1763 state: object
1764 /
1765
1766Decode an Intel/DVI ADPCM coded fragment to a linear fragment.
1767[clinic start generated code]*/
1768
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001769static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001770audioop_adpcm2lin_impl(PyObject *module, Py_buffer *fragment, int width,
Larry Hastings89964c42015-04-14 18:07:59 -04001771 PyObject *state)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001772/*[clinic end generated code: output=3440ea105acb3456 input=f5221144f5ca9ef0]*/
Guido van Rossumb64e6351992-07-06 14:21:56 +00001773{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001774 signed char *cp;
1775 signed char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001776 Py_ssize_t i, outlen;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001777 int valpred, step, delta, index, sign, vpdiff;
1778 PyObject *rv, *str;
Mark Dickinson81fece22010-05-11 13:34:35 +00001779 int inputbuffer = 0, bufferstep;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001780
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001781 if (!audioop_check_size(module, width))
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001782 return NULL;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001783
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001784 /* Decode state, should have (value, step) */
1785 if ( state == Py_None ) {
1786 /* First time, it seems. Set defaults */
1787 valpred = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001788 index = 0;
Serhiy Storchaka449e2be2015-06-28 17:52:09 +03001789 }
1790 else if (!PyTuple_Check(state)) {
Victor Stinnerdaeffd22014-01-03 03:26:47 +01001791 PyErr_SetString(PyExc_TypeError, "state must be a tuple or None");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001792 return NULL;
Serhiy Storchaka449e2be2015-06-28 17:52:09 +03001793 }
Oren Milman1d1d3e92017-08-20 18:35:36 +03001794 else if (!PyArg_ParseTuple(state, "ii;adpcm2lin(): illegal state argument",
1795 &valpred, &index))
1796 {
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001797 return NULL;
Serhiy Storchaka449e2be2015-06-28 17:52:09 +03001798 }
1799 else if (valpred >= 0x8000 || valpred < -0x8000 ||
1800 (size_t)index >= Py_ARRAY_LENGTH(stepsizeTable)) {
1801 PyErr_SetString(PyExc_ValueError, "bad state");
1802 return NULL;
1803 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001804
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001805 if (fragment->len > (PY_SSIZE_T_MAX/2)/width) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001806 PyErr_SetString(PyExc_MemoryError,
1807 "not enough memory for output buffer");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001808 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001809 }
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001810 outlen = fragment->len*width*2;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001811 str = PyBytes_FromStringAndSize(NULL, outlen);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001812 if (str == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001813 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001814 ncp = (signed char *)PyBytes_AsString(str);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001815 cp = fragment->buf;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001816
1817 step = stepsizeTable[index];
1818 bufferstep = 0;
1819
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001820 for (i = 0; i < outlen; i += width) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001821 /* Step 1 - get the delta value and compute next index */
1822 if ( bufferstep ) {
1823 delta = inputbuffer & 0xf;
1824 } else {
1825 inputbuffer = *cp++;
1826 delta = (inputbuffer >> 4) & 0xf;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001827 }
Guido van Rossumb64e6351992-07-06 14:21:56 +00001828
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001829 bufferstep = !bufferstep;
1830
1831 /* Step 2 - Find new index value (for later) */
1832 index += indexTable[delta];
1833 if ( index < 0 ) index = 0;
1834 if ( index > 88 ) index = 88;
1835
1836 /* Step 3 - Separate sign and magnitude */
1837 sign = delta & 8;
1838 delta = delta & 7;
1839
1840 /* Step 4 - Compute difference and new predicted value */
1841 /*
1842 ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
1843 ** in adpcm_coder.
1844 */
1845 vpdiff = step >> 3;
1846 if ( delta & 4 ) vpdiff += step;
1847 if ( delta & 2 ) vpdiff += step>>1;
1848 if ( delta & 1 ) vpdiff += step>>2;
1849
1850 if ( sign )
1851 valpred -= vpdiff;
1852 else
1853 valpred += vpdiff;
1854
1855 /* Step 5 - clamp output value */
1856 if ( valpred > 32767 )
1857 valpred = 32767;
1858 else if ( valpred < -32768 )
1859 valpred = -32768;
1860
1861 /* Step 6 - Update step value */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001862 step = stepsizeTable[index];
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001863
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001864 /* Step 6 - Output value */
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001865 SETSAMPLE32(width, ncp, i, valpred << 16);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001866 }
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001867
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001868 rv = Py_BuildValue("(O(ii))", str, valpred, index);
1869 Py_DECREF(str);
1870 return rv;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001871}
1872
Larry Hastingsf256c222014-01-25 21:30:37 -08001873#include "clinic/audioop.c.h"
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001874
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001875static PyMethodDef audioop_methods[] = {
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001876 AUDIOOP_MAX_METHODDEF
1877 AUDIOOP_MINMAX_METHODDEF
1878 AUDIOOP_AVG_METHODDEF
1879 AUDIOOP_MAXPP_METHODDEF
1880 AUDIOOP_AVGPP_METHODDEF
1881 AUDIOOP_RMS_METHODDEF
1882 AUDIOOP_FINDFIT_METHODDEF
1883 AUDIOOP_FINDMAX_METHODDEF
1884 AUDIOOP_FINDFACTOR_METHODDEF
1885 AUDIOOP_CROSS_METHODDEF
1886 AUDIOOP_MUL_METHODDEF
1887 AUDIOOP_ADD_METHODDEF
1888 AUDIOOP_BIAS_METHODDEF
1889 AUDIOOP_ULAW2LIN_METHODDEF
1890 AUDIOOP_LIN2ULAW_METHODDEF
1891 AUDIOOP_ALAW2LIN_METHODDEF
1892 AUDIOOP_LIN2ALAW_METHODDEF
1893 AUDIOOP_LIN2LIN_METHODDEF
1894 AUDIOOP_ADPCM2LIN_METHODDEF
1895 AUDIOOP_LIN2ADPCM_METHODDEF
1896 AUDIOOP_TOMONO_METHODDEF
1897 AUDIOOP_TOSTEREO_METHODDEF
1898 AUDIOOP_GETSAMPLE_METHODDEF
1899 AUDIOOP_REVERSE_METHODDEF
1900 AUDIOOP_BYTESWAP_METHODDEF
1901 AUDIOOP_RATECV_METHODDEF
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001902 { 0, 0 }
Guido van Rossumb66efa01992-06-01 16:01:24 +00001903};
1904
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001905static int
1906audioop_traverse(PyObject *m, visitproc visit, void *arg) {
1907 _audioopstate *state = _audioopstate(m);
1908 if (state != NULL)
1909 Py_VISIT(state->AudioopError);
1910 return 0;
1911}
1912static int
1913audioop_clear(PyObject *m) {
1914 _audioopstate *state = _audioopstate(m);
1915 if (state != NULL)
1916 Py_CLEAR(state->AudioopError);
1917 return 0;
1918}
1919static void
1920audioop_free(void *m) {
1921 audioop_clear((PyObject *)m);
1922}
Martin v. Löwis1a214512008-06-11 05:26:20 +00001923
1924static struct PyModuleDef audioopmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001925 PyModuleDef_HEAD_INIT,
1926 "audioop",
1927 NULL,
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001928 sizeof(_audioopstate),
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001929 audioop_methods,
1930 NULL,
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001931 audioop_traverse,
1932 audioop_clear,
1933 audioop_free
Martin v. Löwis1a214512008-06-11 05:26:20 +00001934};
1935
Mark Hammondfe51c6d2002-08-02 02:27:13 +00001936PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00001937PyInit_audioop(void)
Guido van Rossumb66efa01992-06-01 16:01:24 +00001938{
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001939 PyObject *m = PyModule_Create(&audioopmodule);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001940 if (m == NULL)
1941 return NULL;
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001942 PyObject *AudioopError = PyErr_NewException("audioop.error", NULL, NULL);
1943 if (AudioopError == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001944 return NULL;
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001945 Py_INCREF(AudioopError);
1946 PyModule_AddObject(m, "error", AudioopError);
1947 _audioopstate(m)->AudioopError = AudioopError;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001948 return m;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001949}