blob: 3aeb6f04f13cbb6b2e40b058d835676bbc08d9f5 [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;
Hai Shi41fbf862020-03-12 00:49:11 +0800378} audioop_state;
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400379
Hai Shi41fbf862020-03-12 00:49:11 +0800380static inline audioop_state *
381get_audioop_state(PyObject *module)
382{
383 void *state = PyModule_GetState(module);
384 assert(state != NULL);
385 return (audioop_state *)state;
386}
Guido van Rossumb66efa01992-06-01 16:01:24 +0000387
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000388static int
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400389audioop_check_size(PyObject *module, int size)
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000390{
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300391 if (size < 1 || size > 4) {
Hai Shi41fbf862020-03-12 00:49:11 +0800392 PyErr_SetString(get_audioop_state(module)->AudioopError,
393 "Size should be 1, 2, 3 or 4");
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000394 return 0;
395 }
396 else
397 return 1;
398}
399
400static int
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400401audioop_check_parameters(PyObject *module, Py_ssize_t len, int size)
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000402{
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400403 if (!audioop_check_size(module, size))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000404 return 0;
405 if (len % size != 0) {
Hai Shi41fbf862020-03-12 00:49:11 +0800406 PyErr_SetString(get_audioop_state(module)->AudioopError,
407 "not a whole number of frames");
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000408 return 0;
409 }
410 return 1;
411}
412
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200413/*[clinic input]
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200414module audioop
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200415[clinic start generated code]*/
Serhiy Storchaka1009bf12015-04-03 23:53:51 +0300416/*[clinic end generated code: output=da39a3ee5e6b4b0d input=8fa8f6611be3591a]*/
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200417
418/*[clinic input]
419audioop.getsample
420
421 fragment: Py_buffer
422 width: int
423 index: Py_ssize_t
424 /
425
426Return the value of sample index from the fragment.
427[clinic start generated code]*/
428
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000429static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300430audioop_getsample_impl(PyObject *module, Py_buffer *fragment, int width,
Larry Hastings89964c42015-04-14 18:07:59 -0400431 Py_ssize_t index)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300432/*[clinic end generated code: output=8fe1b1775134f39a input=88edbe2871393549]*/
Guido van Rossumb66efa01992-06-01 16:01:24 +0000433{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200434 int val;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000435
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400436 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000437 return NULL;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200438 if (index < 0 || index >= fragment->len/width) {
Hai Shi41fbf862020-03-12 00:49:11 +0800439 PyErr_SetString(get_audioop_state(module)->AudioopError,
440 "Index out of range");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200441 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000442 }
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200443 val = GETRAWSAMPLE(width, fragment->buf, index*width);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200444 return PyLong_FromLong(val);
Guido van Rossumb66efa01992-06-01 16:01:24 +0000445}
446
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200447/*[clinic input]
448audioop.max
449
450 fragment: Py_buffer
451 width: int
452 /
453
454Return the maximum of the absolute value of all samples in a fragment.
455[clinic start generated code]*/
456
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000457static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300458audioop_max_impl(PyObject *module, Py_buffer *fragment, int width)
459/*[clinic end generated code: output=e6c5952714f1c3f0 input=32bea5ea0ac8c223]*/
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000460{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200461 Py_ssize_t i;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200462 unsigned int absval, max = 0;
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000463
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400464 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000465 return NULL;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200466 for (i = 0; i < fragment->len; i += width) {
467 int val = GETRAWSAMPLE(width, fragment->buf, i);
Martin Panter6fb90902016-07-19 03:05:42 +0000468 /* Cast to unsigned before negating. Unsigned overflow is well-
469 defined, but signed overflow is not. */
Steve Dowera4391912016-09-06 19:09:15 -0700470 if (val < 0) absval = (unsigned int)-(int64_t)val;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200471 else absval = val;
472 if (absval > max) max = absval;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000473 }
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200474 return PyLong_FromUnsignedLong(max);
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000475}
476
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200477/*[clinic input]
478audioop.minmax
479
480 fragment: Py_buffer
481 width: int
482 /
483
484Return the minimum and maximum values of all samples in the sound fragment.
485[clinic start generated code]*/
486
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000487static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300488audioop_minmax_impl(PyObject *module, Py_buffer *fragment, int width)
489/*[clinic end generated code: output=473fda66b15c836e input=89848e9b927a0696]*/
Sjoerd Mullendera1426131994-09-06 16:19:33 +0000490{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200491 Py_ssize_t i;
Tim Goldenfa6ab0f2013-10-31 10:25:47 +0000492 /* -1 trick below is needed on Windows to support -0x80000000 without
493 a warning */
494 int min = 0x7fffffff, max = -0x7FFFFFFF-1;
Sjoerd Mullendera1426131994-09-06 16:19:33 +0000495
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400496 if (!audioop_check_parameters(module, fragment->len, width))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000497 return NULL;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200498 for (i = 0; i < fragment->len; i += width) {
499 int val = GETRAWSAMPLE(width, fragment->buf, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000500 if (val > max) max = val;
501 if (val < min) min = val;
502 }
503 return Py_BuildValue("(ii)", min, max);
Sjoerd Mullendera1426131994-09-06 16:19:33 +0000504}
505
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200506/*[clinic input]
507audioop.avg
508
509 fragment: Py_buffer
510 width: int
511 /
512
513Return the average over all samples in the fragment.
514[clinic start generated code]*/
515
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000516static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300517audioop_avg_impl(PyObject *module, Py_buffer *fragment, int width)
518/*[clinic end generated code: output=4410a4c12c3586e6 input=1114493c7611334d]*/
Guido van Rossumb66efa01992-06-01 16:01:24 +0000519{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200520 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200521 int avg;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300522 double sum = 0.0;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000523
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400524 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000525 return NULL;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200526 for (i = 0; i < fragment->len; i += width)
527 sum += GETRAWSAMPLE(width, fragment->buf, i);
528 if (fragment->len == 0)
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300529 avg = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000530 else
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200531 avg = (int)floor(sum / (double)(fragment->len/width));
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300532 return PyLong_FromLong(avg);
Guido van Rossumb66efa01992-06-01 16:01:24 +0000533}
534
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200535/*[clinic input]
536audioop.rms
537
538 fragment: Py_buffer
539 width: int
540 /
541
542Return the root-mean-square of the fragment, i.e. sqrt(sum(S_i^2)/n).
543[clinic start generated code]*/
544
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000545static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300546audioop_rms_impl(PyObject *module, Py_buffer *fragment, int width)
547/*[clinic end generated code: output=1e7871c826445698 input=4cc57c6c94219d78]*/
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000548{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200549 Py_ssize_t i;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200550 unsigned int res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000551 double sum_squares = 0.0;
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000552
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400553 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000554 return NULL;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200555 for (i = 0; i < fragment->len; i += width) {
556 double val = GETRAWSAMPLE(width, fragment->buf, i);
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300557 sum_squares += val*val;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000558 }
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200559 if (fragment->len == 0)
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200560 res = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000561 else
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200562 res = (unsigned int)sqrt(sum_squares / (double)(fragment->len/width));
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200563 return PyLong_FromUnsignedLong(res);
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000564}
565
Serhiy Storchaka8be17402016-09-11 14:48:16 +0300566static double _sum2(const int16_t *a, const int16_t *b, Py_ssize_t len)
Jack Jansena90805f1993-02-17 14:29:28 +0000567{
Mark Dickinson81fece22010-05-11 13:34:35 +0000568 Py_ssize_t i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000569 double sum = 0.0;
Jack Jansena90805f1993-02-17 14:29:28 +0000570
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000571 for( i=0; i<len; i++) {
572 sum = sum + (double)a[i]*(double)b[i];
573 }
574 return sum;
Jack Jansena90805f1993-02-17 14:29:28 +0000575}
576
577/*
578** Findfit tries to locate a sample within another sample. Its main use
579** is in echo-cancellation (to find the feedback of the output signal in
580** the input signal).
581** The method used is as follows:
582**
583** let R be the reference signal (length n) and A the input signal (length N)
584** with N > n, and let all sums be over i from 0 to n-1.
585**
586** Now, for each j in {0..N-n} we compute a factor fj so that -fj*R matches A
587** as good as possible, i.e. sum( (A[j+i]+fj*R[i])^2 ) is minimal. This
588** equation gives fj = sum( A[j+i]R[i] ) / sum(R[i]^2).
589**
590** Next, we compute the relative distance between the original signal and
591** the modified signal and minimize that over j:
592** vj = sum( (A[j+i]-fj*R[i])^2 ) / sum( A[j+i]^2 ) =>
593** vj = ( sum(A[j+i]^2)*sum(R[i]^2) - sum(A[j+i]R[i])^2 ) / sum( A[j+i]^2 )
594**
595** In the code variables correspond as follows:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000596** cp1 A
597** cp2 R
598** len1 N
599** len2 n
600** aj_m1 A[j-1]
601** aj_lm1 A[j+n-1]
602** sum_ri_2 sum(R[i]^2)
603** sum_aij_2 sum(A[i+j]^2)
604** sum_aij_ri sum(A[i+j]R[i])
Jack Jansena90805f1993-02-17 14:29:28 +0000605**
606** sum_ri is calculated once, sum_aij_2 is updated each step and sum_aij_ri
607** is completely recalculated each step.
608*/
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200609/*[clinic input]
610audioop.findfit
611
612 fragment: Py_buffer
613 reference: Py_buffer
614 /
615
616Try to match reference as well as possible to a portion of fragment.
617[clinic start generated code]*/
618
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000619static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300620audioop_findfit_impl(PyObject *module, Py_buffer *fragment,
Larry Hastings89964c42015-04-14 18:07:59 -0400621 Py_buffer *reference)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300622/*[clinic end generated code: output=5752306d83cbbada input=62c305605e183c9a]*/
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000623{
Serhiy Storchaka8be17402016-09-11 14:48:16 +0300624 const int16_t *cp1, *cp2;
Mark Dickinson81fece22010-05-11 13:34:35 +0000625 Py_ssize_t len1, len2;
626 Py_ssize_t j, best_j;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000627 double aj_m1, aj_lm1;
628 double sum_ri_2, sum_aij_2, sum_aij_ri, result, best_result, factor;
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000629
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200630 if (fragment->len & 1 || reference->len & 1) {
Hai Shi41fbf862020-03-12 00:49:11 +0800631 PyErr_SetString(get_audioop_state(module)->AudioopError,
632 "Strings should be even-sized");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200633 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000634 }
Serhiy Storchaka8be17402016-09-11 14:48:16 +0300635 cp1 = (const int16_t *)fragment->buf;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200636 len1 = fragment->len >> 1;
Serhiy Storchaka8be17402016-09-11 14:48:16 +0300637 cp2 = (const int16_t *)reference->buf;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200638 len2 = reference->len >> 1;
Jack Jansena90805f1993-02-17 14:29:28 +0000639
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200640 if (len1 < len2) {
Hai Shi41fbf862020-03-12 00:49:11 +0800641 PyErr_SetString(get_audioop_state(module)->AudioopError,
642 "First sample should be longer");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200643 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000644 }
645 sum_ri_2 = _sum2(cp2, cp2, len2);
646 sum_aij_2 = _sum2(cp1, cp1, len2);
647 sum_aij_ri = _sum2(cp1, cp2, len2);
Jack Jansena90805f1993-02-17 14:29:28 +0000648
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000649 result = (sum_ri_2*sum_aij_2 - sum_aij_ri*sum_aij_ri) / sum_aij_2;
Jack Jansena90805f1993-02-17 14:29:28 +0000650
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000651 best_result = result;
652 best_j = 0;
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000653
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000654 for ( j=1; j<=len1-len2; j++) {
655 aj_m1 = (double)cp1[j-1];
656 aj_lm1 = (double)cp1[j+len2-1];
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000657
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000658 sum_aij_2 = sum_aij_2 + aj_lm1*aj_lm1 - aj_m1*aj_m1;
659 sum_aij_ri = _sum2(cp1+j, cp2, len2);
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000660
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000661 result = (sum_ri_2*sum_aij_2 - sum_aij_ri*sum_aij_ri)
662 / sum_aij_2;
663
664 if ( result < best_result ) {
665 best_result = result;
666 best_j = j;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000667 }
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000668
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000669 }
670
671 factor = _sum2(cp1+best_j, cp2, len2) / sum_ri_2;
672
Mark Dickinson81fece22010-05-11 13:34:35 +0000673 return Py_BuildValue("(nf)", best_j, factor);
Jack Jansena90805f1993-02-17 14:29:28 +0000674}
675
676/*
677** findfactor finds a factor f so that the energy in A-fB is minimal.
678** See the comment for findfit for details.
679*/
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200680/*[clinic input]
681audioop.findfactor
682
683 fragment: Py_buffer
684 reference: Py_buffer
685 /
686
687Return a factor F such that rms(add(fragment, mul(reference, -F))) is minimal.
688[clinic start generated code]*/
689
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000690static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300691audioop_findfactor_impl(PyObject *module, Py_buffer *fragment,
Larry Hastings89964c42015-04-14 18:07:59 -0400692 Py_buffer *reference)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300693/*[clinic end generated code: output=14ea95652c1afcf8 input=816680301d012b21]*/
Jack Jansena90805f1993-02-17 14:29:28 +0000694{
Serhiy Storchaka8be17402016-09-11 14:48:16 +0300695 const int16_t *cp1, *cp2;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200696 Py_ssize_t len;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000697 double sum_ri_2, sum_aij_ri, result;
Jack Jansena90805f1993-02-17 14:29:28 +0000698
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200699 if (fragment->len & 1 || reference->len & 1) {
Hai Shi41fbf862020-03-12 00:49:11 +0800700 PyErr_SetString(get_audioop_state(module)->AudioopError,
701 "Strings should be even-sized");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200702 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000703 }
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200704 if (fragment->len != reference->len) {
Hai Shi41fbf862020-03-12 00:49:11 +0800705 PyErr_SetString(get_audioop_state(module)->AudioopError,
706 "Samples should be same size");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200707 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000708 }
Serhiy Storchaka8be17402016-09-11 14:48:16 +0300709 cp1 = (const int16_t *)fragment->buf;
710 cp2 = (const int16_t *)reference->buf;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200711 len = fragment->len >> 1;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200712 sum_ri_2 = _sum2(cp2, cp2, len);
713 sum_aij_ri = _sum2(cp1, cp2, len);
Jack Jansena90805f1993-02-17 14:29:28 +0000714
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000715 result = sum_aij_ri / sum_ri_2;
Jack Jansena90805f1993-02-17 14:29:28 +0000716
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000717 return PyFloat_FromDouble(result);
Jack Jansena90805f1993-02-17 14:29:28 +0000718}
719
720/*
721** findmax returns the index of the n-sized segment of the input sample
722** that contains the most energy.
723*/
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200724/*[clinic input]
725audioop.findmax
726
727 fragment: Py_buffer
728 length: Py_ssize_t
729 /
730
731Search fragment for a slice of specified number of samples with maximum energy.
732[clinic start generated code]*/
733
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000734static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300735audioop_findmax_impl(PyObject *module, Py_buffer *fragment,
Larry Hastings89964c42015-04-14 18:07:59 -0400736 Py_ssize_t length)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300737/*[clinic end generated code: output=f008128233523040 input=2f304801ed42383c]*/
Jack Jansena90805f1993-02-17 14:29:28 +0000738{
Serhiy Storchaka8be17402016-09-11 14:48:16 +0300739 const int16_t *cp1;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200740 Py_ssize_t len1;
Mark Dickinson81fece22010-05-11 13:34:35 +0000741 Py_ssize_t j, best_j;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000742 double aj_m1, aj_lm1;
743 double result, best_result;
Jack Jansena90805f1993-02-17 14:29:28 +0000744
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200745 if (fragment->len & 1) {
Hai Shi41fbf862020-03-12 00:49:11 +0800746 PyErr_SetString(get_audioop_state(module)->AudioopError,
747 "Strings should be even-sized");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200748 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000749 }
Serhiy Storchaka8be17402016-09-11 14:48:16 +0300750 cp1 = (const int16_t *)fragment->buf;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200751 len1 = fragment->len >> 1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000752
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200753 if (length < 0 || len1 < length) {
Hai Shi41fbf862020-03-12 00:49:11 +0800754 PyErr_SetString(get_audioop_state(module)->AudioopError,
755 "Input sample should be longer");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200756 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000757 }
758
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200759 result = _sum2(cp1, cp1, length);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000760
761 best_result = result;
762 best_j = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000763
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200764 for ( j=1; j<=len1-length; j++) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000765 aj_m1 = (double)cp1[j-1];
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200766 aj_lm1 = (double)cp1[j+length-1];
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000767
768 result = result + aj_lm1*aj_lm1 - aj_m1*aj_m1;
769
770 if ( result > best_result ) {
771 best_result = result;
772 best_j = j;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000773 }
Jack Jansena90805f1993-02-17 14:29:28 +0000774
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000775 }
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000776
Mark Dickinson81fece22010-05-11 13:34:35 +0000777 return PyLong_FromSsize_t(best_j);
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000778}
779
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200780/*[clinic input]
781audioop.avgpp
782
783 fragment: Py_buffer
784 width: int
785 /
786
787Return the average peak-peak value over all samples in the fragment.
788[clinic start generated code]*/
789
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000790static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300791audioop_avgpp_impl(PyObject *module, Py_buffer *fragment, int width)
792/*[clinic end generated code: output=269596b0d5ae0b2b input=0b3cceeae420a7d9]*/
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000793{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200794 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200795 int prevval, prevextremevalid = 0, prevextreme = 0;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200796 double sum = 0.0;
797 unsigned int avg;
798 int diff, prevdiff, nextreme = 0;
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000799
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400800 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000801 return NULL;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200802 if (fragment->len <= width)
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200803 return PyLong_FromLong(0);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200804 prevval = GETRAWSAMPLE(width, fragment->buf, 0);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200805 prevdiff = 17; /* Anything != 0, 1 */
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200806 for (i = width; i < fragment->len; i += width) {
807 int val = GETRAWSAMPLE(width, fragment->buf, i);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200808 if (val != prevval) {
809 diff = val < prevval;
810 if (prevdiff == !diff) {
811 /* Derivative changed sign. Compute difference to last
812 ** extreme value and remember.
813 */
814 if (prevextremevalid) {
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300815 if (prevval < prevextreme)
816 sum += (double)((unsigned int)prevextreme -
817 (unsigned int)prevval);
818 else
819 sum += (double)((unsigned int)prevval -
820 (unsigned int)prevextreme);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200821 nextreme++;
822 }
823 prevextremevalid = 1;
824 prevextreme = prevval;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000825 }
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200826 prevval = val;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000827 prevdiff = diff;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200828 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000829 }
830 if ( nextreme == 0 )
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200831 avg = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000832 else
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200833 avg = (unsigned int)(sum / (double)nextreme);
834 return PyLong_FromUnsignedLong(avg);
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000835}
836
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200837/*[clinic input]
838audioop.maxpp
839
840 fragment: Py_buffer
841 width: int
842 /
843
844Return the maximum peak-peak value in the sound fragment.
845[clinic start generated code]*/
846
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000847static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300848audioop_maxpp_impl(PyObject *module, Py_buffer *fragment, int width)
849/*[clinic end generated code: output=5b918ed5dbbdb978 input=671a13e1518f80a1]*/
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000850{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200851 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200852 int prevval, prevextremevalid = 0, prevextreme = 0;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200853 unsigned int max = 0, extremediff;
854 int diff, prevdiff;
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000855
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400856 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000857 return NULL;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200858 if (fragment->len <= width)
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200859 return PyLong_FromLong(0);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200860 prevval = GETRAWSAMPLE(width, fragment->buf, 0);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200861 prevdiff = 17; /* Anything != 0, 1 */
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200862 for (i = width; i < fragment->len; i += width) {
863 int val = GETRAWSAMPLE(width, fragment->buf, i);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200864 if (val != prevval) {
865 diff = val < prevval;
866 if (prevdiff == !diff) {
867 /* Derivative changed sign. Compute difference to
868 ** last extreme value and remember.
869 */
870 if (prevextremevalid) {
871 if (prevval < prevextreme)
872 extremediff = (unsigned int)prevextreme -
873 (unsigned int)prevval;
874 else
875 extremediff = (unsigned int)prevval -
876 (unsigned int)prevextreme;
877 if ( extremediff > max )
878 max = extremediff;
879 }
880 prevextremevalid = 1;
881 prevextreme = prevval;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000882 }
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200883 prevval = val;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000884 prevdiff = diff;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200885 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000886 }
Serhiy Storchaka01ad6222013-02-09 11:10:53 +0200887 return PyLong_FromUnsignedLong(max);
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000888}
889
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200890/*[clinic input]
891audioop.cross
892
893 fragment: Py_buffer
894 width: int
895 /
896
897Return the number of zero crossings in the fragment passed as an argument.
898[clinic start generated code]*/
899
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000900static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300901audioop_cross_impl(PyObject *module, Py_buffer *fragment, int width)
902/*[clinic end generated code: output=5938dcdd74a1f431 input=b1b3f15b83f6b41a]*/
Guido van Rossumb66efa01992-06-01 16:01:24 +0000903{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200904 Py_ssize_t i;
Mark Dickinson81fece22010-05-11 13:34:35 +0000905 int prevval;
906 Py_ssize_t ncross;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000907
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400908 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000909 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000910 ncross = -1;
911 prevval = 17; /* Anything <> 0,1 */
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200912 for (i = 0; i < fragment->len; i += width) {
913 int val = GETRAWSAMPLE(width, fragment->buf, i) < 0;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +0300914 if (val != prevval) ncross++;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000915 prevval = val;
916 }
Mark Dickinson81fece22010-05-11 13:34:35 +0000917 return PyLong_FromSsize_t(ncross);
Guido van Rossumb66efa01992-06-01 16:01:24 +0000918}
919
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200920/*[clinic input]
921audioop.mul
922
923 fragment: Py_buffer
924 width: int
925 factor: double
926 /
927
928Return a fragment that has all samples in the original fragment multiplied by the floating-point value factor.
929[clinic start generated code]*/
930
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000931static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300932audioop_mul_impl(PyObject *module, Py_buffer *fragment, int width,
Larry Hastings89964c42015-04-14 18:07:59 -0400933 double factor)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300934/*[clinic end generated code: output=6cd48fe796da0ea4 input=c726667baa157d3c]*/
Guido van Rossumb66efa01992-06-01 16:01:24 +0000935{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200936 signed char *ncp;
937 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200938 double maxval, minval;
939 PyObject *rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000940
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400941 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000942 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000943
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200944 maxval = (double) maxvals[width];
945 minval = (double) minvals[width];
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000946
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200947 rv = PyBytes_FromStringAndSize(NULL, fragment->len);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200948 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200949 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000950 ncp = (signed char *)PyBytes_AsString(rv);
951
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200952 for (i = 0; i < fragment->len; i += width) {
953 double val = GETRAWSAMPLE(width, fragment->buf, i);
Victor Stinner45e4efb2018-06-06 15:50:50 +0200954 int ival = fbound(val * factor, minval, maxval);
955 SETRAWSAMPLE(width, ncp, i, ival);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000956 }
957 return rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000958}
959
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200960/*[clinic input]
961audioop.tomono
962
963 fragment: Py_buffer
964 width: int
965 lfactor: double
966 rfactor: double
967 /
968
969Convert a stereo fragment to a mono fragment.
970[clinic start generated code]*/
971
Roger E. Masseeaa6e111997-01-03 19:26:27 +0000972static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300973audioop_tomono_impl(PyObject *module, Py_buffer *fragment, int width,
Larry Hastings89964c42015-04-14 18:07:59 -0400974 double lfactor, double rfactor)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300975/*[clinic end generated code: output=235c8277216d4e4e input=c4ec949b3f4dddfa]*/
Guido van Rossumb66efa01992-06-01 16:01:24 +0000976{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000977 signed char *cp, *ncp;
Mark Dickinson81fece22010-05-11 13:34:35 +0000978 Py_ssize_t len, i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200979 double maxval, minval;
980 PyObject *rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000981
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200982 cp = fragment->buf;
983 len = fragment->len;
Tyler Kieftf548a3e2019-10-22 09:07:03 -0400984 if (!audioop_check_parameters(module, len, width))
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200985 return NULL;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200986 if (((len / width) & 1) != 0) {
Hai Shi41fbf862020-03-12 00:49:11 +0800987 PyErr_SetString(get_audioop_state(module)->AudioopError,
988 "not a whole number of frames");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200989 return NULL;
Victor Stinnerbc5c54b2010-07-03 13:44:22 +0000990 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000991
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200992 maxval = (double) maxvals[width];
993 minval = (double) minvals[width];
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000994
995 rv = PyBytes_FromStringAndSize(NULL, len/2);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +0200996 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +0200997 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000998 ncp = (signed char *)PyBytes_AsString(rv);
999
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001000 for (i = 0; i < len; i += width*2) {
1001 double val1 = GETRAWSAMPLE(width, cp, i);
1002 double val2 = GETRAWSAMPLE(width, cp, i + width);
Victor Stinner45e4efb2018-06-06 15:50:50 +02001003 double val = val1 * lfactor + val2 * rfactor;
1004 int ival = fbound(val, minval, maxval);
1005 SETRAWSAMPLE(width, ncp, i/2, ival);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001006 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001007 return rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001008}
1009
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001010/*[clinic input]
1011audioop.tostereo
1012
1013 fragment: Py_buffer
1014 width: int
1015 lfactor: double
1016 rfactor: double
1017 /
1018
1019Generate a stereo fragment from a mono fragment.
1020[clinic start generated code]*/
1021
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001022static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001023audioop_tostereo_impl(PyObject *module, Py_buffer *fragment, int width,
Larry Hastings89964c42015-04-14 18:07:59 -04001024 double lfactor, double rfactor)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001025/*[clinic end generated code: output=046f13defa5f1595 input=27b6395ebfdff37a]*/
Guido van Rossumb66efa01992-06-01 16:01:24 +00001026{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001027 signed char *ncp;
1028 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001029 double maxval, minval;
1030 PyObject *rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001031
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001032 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001033 return NULL;
Amaury Forgeot d'Arc9c74b142008-06-18 00:47:36 +00001034
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001035 maxval = (double) maxvals[width];
1036 minval = (double) minvals[width];
Guido van Rossumb66efa01992-06-01 16:01:24 +00001037
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001038 if (fragment->len > PY_SSIZE_T_MAX/2) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001039 PyErr_SetString(PyExc_MemoryError,
1040 "not enough memory for output buffer");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001041 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001042 }
Guido van Rossumb66efa01992-06-01 16:01:24 +00001043
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001044 rv = PyBytes_FromStringAndSize(NULL, fragment->len*2);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001045 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001046 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001047 ncp = (signed char *)PyBytes_AsString(rv);
Guido van Rossumb66efa01992-06-01 16:01:24 +00001048
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001049 for (i = 0; i < fragment->len; i += width) {
1050 double val = GETRAWSAMPLE(width, fragment->buf, i);
Victor Stinner45e4efb2018-06-06 15:50:50 +02001051 int val1 = fbound(val * lfactor, minval, maxval);
1052 int val2 = fbound(val * rfactor, minval, maxval);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001053 SETRAWSAMPLE(width, ncp, i*2, val1);
1054 SETRAWSAMPLE(width, ncp, i*2 + width, val2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001055 }
1056 return rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001057}
1058
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001059/*[clinic input]
1060audioop.add
1061
1062 fragment1: Py_buffer
1063 fragment2: Py_buffer
1064 width: int
1065 /
1066
1067Return a fragment which is the addition of the two samples passed as parameters.
1068[clinic start generated code]*/
1069
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001070static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001071audioop_add_impl(PyObject *module, Py_buffer *fragment1,
Larry Hastings89964c42015-04-14 18:07:59 -04001072 Py_buffer *fragment2, int width)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001073/*[clinic end generated code: output=60140af4d1aab6f2 input=4a8d4bae4c1605c7]*/
Guido van Rossumb66efa01992-06-01 16:01:24 +00001074{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001075 signed char *ncp;
1076 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001077 int minval, maxval, newval;
1078 PyObject *rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001079
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001080 if (!audioop_check_parameters(module, fragment1->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001081 return NULL;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001082 if (fragment1->len != fragment2->len) {
Hai Shi41fbf862020-03-12 00:49:11 +08001083 PyErr_SetString(get_audioop_state(module)->AudioopError,
1084 "Lengths should be the same");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001085 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001086 }
Guido van Rossum1851a671997-02-14 16:14:03 +00001087
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001088 maxval = maxvals[width];
1089 minval = minvals[width];
Guido van Rossum1851a671997-02-14 16:14:03 +00001090
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001091 rv = PyBytes_FromStringAndSize(NULL, fragment1->len);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001092 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001093 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001094 ncp = (signed char *)PyBytes_AsString(rv);
Guido van Rossumb66efa01992-06-01 16:01:24 +00001095
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001096 for (i = 0; i < fragment1->len; i += width) {
1097 int val1 = GETRAWSAMPLE(width, fragment1->buf, i);
1098 int val2 = GETRAWSAMPLE(width, fragment2->buf, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001099
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001100 if (width < 4) {
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001101 newval = val1 + val2;
1102 /* truncate in case of overflow */
1103 if (newval > maxval)
1104 newval = maxval;
1105 else if (newval < minval)
1106 newval = minval;
1107 }
1108 else {
1109 double fval = (double)val1 + (double)val2;
1110 /* truncate in case of overflow */
Victor Stinner45e4efb2018-06-06 15:50:50 +02001111 newval = fbound(fval, minval, maxval);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001112 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001113
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001114 SETRAWSAMPLE(width, ncp, i, newval);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001115 }
1116 return rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001117}
1118
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001119/*[clinic input]
1120audioop.bias
1121
1122 fragment: Py_buffer
1123 width: int
1124 bias: int
1125 /
1126
1127Return a fragment that is the original fragment with a bias added to each sample.
1128[clinic start generated code]*/
1129
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001130static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001131audioop_bias_impl(PyObject *module, Py_buffer *fragment, int width, int bias)
1132/*[clinic end generated code: output=6e0aa8f68f045093 input=2b5cce5c3bb4838c]*/
Guido van Rossumb66efa01992-06-01 16:01:24 +00001133{
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001134 signed char *ncp;
1135 Py_ssize_t i;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001136 unsigned int val = 0, mask;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001137 PyObject *rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001138
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001139 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001140 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001141
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001142 rv = PyBytes_FromStringAndSize(NULL, fragment->len);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001143 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001144 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001145 ncp = (signed char *)PyBytes_AsString(rv);
1146
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001147 mask = masks[width];
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001148
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001149 for (i = 0; i < fragment->len; i += width) {
1150 if (width == 1)
1151 val = GETINTX(unsigned char, fragment->buf, i);
1152 else if (width == 2)
Serhiy Storchaka8be17402016-09-11 14:48:16 +03001153 val = GETINTX(uint16_t, fragment->buf, i);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001154 else if (width == 3)
1155 val = ((unsigned int)GETINT24(fragment->buf, i)) & 0xffffffu;
Serhiy Storchakace82eb22013-10-20 09:42:26 +03001156 else {
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001157 assert(width == 4);
Benjamin Peterson9b3d7702016-09-06 13:24:00 -07001158 val = GETINTX(uint32_t, fragment->buf, i);
Serhiy Storchakace82eb22013-10-20 09:42:26 +03001159 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001160
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001161 val += (unsigned int)bias;
1162 /* wrap around in case of overflow */
1163 val &= mask;
1164
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001165 if (width == 1)
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001166 SETINTX(unsigned char, ncp, i, val);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001167 else if (width == 2)
Serhiy Storchaka8be17402016-09-11 14:48:16 +03001168 SETINTX(uint16_t, ncp, i, val);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001169 else if (width == 3)
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001170 SETINT24(ncp, i, (int)val);
Serhiy Storchakace82eb22013-10-20 09:42:26 +03001171 else {
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001172 assert(width == 4);
Benjamin Peterson9b3d7702016-09-06 13:24:00 -07001173 SETINTX(uint32_t, ncp, i, val);
Serhiy Storchakace82eb22013-10-20 09:42:26 +03001174 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001175 }
1176 return rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001177}
1178
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001179/*[clinic input]
1180audioop.reverse
1181
1182 fragment: Py_buffer
1183 width: int
1184 /
1185
1186Reverse the samples in a fragment and returns the modified fragment.
1187[clinic start generated code]*/
1188
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001189static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001190audioop_reverse_impl(PyObject *module, Py_buffer *fragment, int width)
1191/*[clinic end generated code: output=b44135698418da14 input=668f890cf9f9d225]*/
Jack Jansen337b20e1993-02-23 13:39:57 +00001192{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001193 unsigned char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001194 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001195 PyObject *rv;
Jack Jansen337b20e1993-02-23 13:39:57 +00001196
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001197 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001198 return NULL;
Jack Jansen337b20e1993-02-23 13:39:57 +00001199
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001200 rv = PyBytes_FromStringAndSize(NULL, fragment->len);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001201 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001202 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001203 ncp = (unsigned char *)PyBytes_AsString(rv);
1204
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001205 for (i = 0; i < fragment->len; i += width) {
1206 int val = GETRAWSAMPLE(width, fragment->buf, i);
1207 SETRAWSAMPLE(width, ncp, fragment->len - i - width, val);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001208 }
1209 return rv;
Jack Jansen337b20e1993-02-23 13:39:57 +00001210}
1211
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001212/*[clinic input]
1213audioop.byteswap
1214
1215 fragment: Py_buffer
1216 width: int
1217 /
1218
1219Convert big-endian samples to little-endian and vice versa.
1220[clinic start generated code]*/
1221
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001222static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001223audioop_byteswap_impl(PyObject *module, Py_buffer *fragment, int width)
1224/*[clinic end generated code: output=50838a9e4b87cd4d input=fae7611ceffa5c82]*/
Serhiy Storchaka3062c9a2013-11-23 22:26:01 +02001225{
Serhiy Storchaka3062c9a2013-11-23 22:26:01 +02001226 unsigned char *ncp;
1227 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001228 PyObject *rv;
Serhiy Storchaka3062c9a2013-11-23 22:26:01 +02001229
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001230 if (!audioop_check_parameters(module, fragment->len, width))
Serhiy Storchaka3062c9a2013-11-23 22:26:01 +02001231 return NULL;
1232
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001233 rv = PyBytes_FromStringAndSize(NULL, fragment->len);
Serhiy Storchaka3062c9a2013-11-23 22:26:01 +02001234 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001235 return NULL;
Serhiy Storchaka3062c9a2013-11-23 22:26:01 +02001236 ncp = (unsigned char *)PyBytes_AsString(rv);
1237
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001238 for (i = 0; i < fragment->len; i += width) {
Serhiy Storchaka3062c9a2013-11-23 22:26:01 +02001239 int j;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001240 for (j = 0; j < width; j++)
1241 ncp[i + width - 1 - j] = ((unsigned char *)fragment->buf)[i + j];
Serhiy Storchaka3062c9a2013-11-23 22:26:01 +02001242 }
Serhiy Storchaka3062c9a2013-11-23 22:26:01 +02001243 return rv;
1244}
1245
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001246/*[clinic input]
1247audioop.lin2lin
1248
1249 fragment: Py_buffer
1250 width: int
1251 newwidth: int
1252 /
1253
1254Convert samples between 1-, 2-, 3- and 4-byte formats.
1255[clinic start generated code]*/
1256
Serhiy Storchaka3062c9a2013-11-23 22:26:01 +02001257static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001258audioop_lin2lin_impl(PyObject *module, Py_buffer *fragment, int width,
Larry Hastings89964c42015-04-14 18:07:59 -04001259 int newwidth)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001260/*[clinic end generated code: output=17b14109248f1d99 input=5ce08c8aa2f24d96]*/
Jack Jansena90805f1993-02-17 14:29:28 +00001261{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001262 unsigned char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001263 Py_ssize_t i, j;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001264 PyObject *rv;
Jack Jansena90805f1993-02-17 14:29:28 +00001265
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001266 if (!audioop_check_parameters(module, fragment->len, width))
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001267 return NULL;
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001268 if (!audioop_check_size(module, newwidth))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001269 return NULL;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001270
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001271 if (fragment->len/width > PY_SSIZE_T_MAX/newwidth) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001272 PyErr_SetString(PyExc_MemoryError,
1273 "not enough memory for output buffer");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001274 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001275 }
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001276 rv = PyBytes_FromStringAndSize(NULL, (fragment->len/width)*newwidth);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001277 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001278 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001279 ncp = (unsigned char *)PyBytes_AsString(rv);
1280
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001281 for (i = j = 0; i < fragment->len; i += width, j += newwidth) {
1282 int val = GETSAMPLE32(width, fragment->buf, i);
1283 SETSAMPLE32(newwidth, ncp, j, val);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001284 }
1285 return rv;
Jack Jansena90805f1993-02-17 14:29:28 +00001286}
1287
Guido van Rossumb24c9ea1997-05-20 15:59:35 +00001288static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00001289gcd(int a, int b)
Guido van Rossumb24c9ea1997-05-20 15:59:35 +00001290{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001291 while (b > 0) {
1292 int tmp = a % b;
1293 a = b;
1294 b = tmp;
1295 }
1296 return a;
Guido van Rossumb24c9ea1997-05-20 15:59:35 +00001297}
1298
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001299/*[clinic input]
1300audioop.ratecv
1301
1302 fragment: Py_buffer
1303 width: int
1304 nchannels: int
1305 inrate: int
1306 outrate: int
1307 state: object
1308 weightA: int = 1
1309 weightB: int = 0
1310 /
1311
1312Convert the frame rate of the input fragment.
1313[clinic start generated code]*/
1314
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001315static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001316audioop_ratecv_impl(PyObject *module, Py_buffer *fragment, int width,
Larry Hastings89964c42015-04-14 18:07:59 -04001317 int nchannels, int inrate, int outrate, PyObject *state,
1318 int weightA, int weightB)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001319/*[clinic end generated code: output=624038e843243139 input=aff3acdc94476191]*/
Roger E. Massec905fff1997-01-17 18:12:04 +00001320{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001321 char *cp, *ncp;
Mark Dickinson81fece22010-05-11 13:34:35 +00001322 Py_ssize_t len;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001323 int chan, d, *prev_i, *cur_i, cur_o;
Oren Milman1d1d3e92017-08-20 18:35:36 +03001324 PyObject *samps, *str, *rv = NULL, *channel;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001325 int bytes_per_frame;
Guido van Rossum1851a671997-02-14 16:14:03 +00001326
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001327 if (!audioop_check_size(module, width))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001328 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001329 if (nchannels < 1) {
Hai Shi41fbf862020-03-12 00:49:11 +08001330 PyErr_SetString(get_audioop_state(module)->AudioopError,
1331 "# of channels should be >= 1");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001332 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001333 }
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001334 if (width > INT_MAX / nchannels) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001335 /* This overflow test is rigorously correct because
1336 both multiplicands are >= 1. Use the argument names
1337 from the docs for the error msg. */
1338 PyErr_SetString(PyExc_OverflowError,
1339 "width * nchannels too big for a C int");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001340 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001341 }
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001342 bytes_per_frame = width * nchannels;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001343 if (weightA < 1 || weightB < 0) {
Hai Shi41fbf862020-03-12 00:49:11 +08001344 PyErr_SetString(get_audioop_state(module)->AudioopError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001345 "weightA should be >= 1, weightB should be >= 0");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001346 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001347 }
Christian Heimesc4ab9a42014-01-27 01:12:00 +01001348 assert(fragment->len >= 0);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001349 if (fragment->len % bytes_per_frame != 0) {
Hai Shi41fbf862020-03-12 00:49:11 +08001350 PyErr_SetString(get_audioop_state(module)->AudioopError,
1351 "not a whole number of frames");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001352 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001353 }
1354 if (inrate <= 0 || outrate <= 0) {
Hai Shi41fbf862020-03-12 00:49:11 +08001355 PyErr_SetString(get_audioop_state(module)->AudioopError,
1356 "sampling rate not > 0");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001357 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001358 }
1359 /* divide inrate and outrate by their greatest common divisor */
1360 d = gcd(inrate, outrate);
1361 inrate /= d;
1362 outrate /= d;
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001363 /* divide weightA and weightB by their greatest common divisor */
1364 d = gcd(weightA, weightB);
1365 weightA /= d;
Serhiy Storchaka50451eb2015-05-30 00:53:26 +03001366 weightB /= d;
Guido van Rossumb24c9ea1997-05-20 15:59:35 +00001367
Benjamin Peterson2f8bfef2016-09-07 09:26:18 -07001368 if ((size_t)nchannels > SIZE_MAX/sizeof(int)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001369 PyErr_SetString(PyExc_MemoryError,
1370 "not enough memory for output buffer");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001371 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001372 }
Victor Stinnerb6404912013-07-07 16:21:41 +02001373 prev_i = (int *) PyMem_Malloc(nchannels * sizeof(int));
1374 cur_i = (int *) PyMem_Malloc(nchannels * sizeof(int));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001375 if (prev_i == NULL || cur_i == NULL) {
1376 (void) PyErr_NoMemory();
1377 goto exit;
1378 }
1379
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001380 len = fragment->len / bytes_per_frame; /* # of frames */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001381
1382 if (state == Py_None) {
1383 d = -outrate;
1384 for (chan = 0; chan < nchannels; chan++)
1385 prev_i[chan] = cur_i[chan] = 0;
1386 }
1387 else {
Oren Milman1d1d3e92017-08-20 18:35:36 +03001388 if (!PyTuple_Check(state)) {
1389 PyErr_SetString(PyExc_TypeError, "state must be a tuple or None");
1390 goto exit;
1391 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001392 if (!PyArg_ParseTuple(state,
Oren Milman1d1d3e92017-08-20 18:35:36 +03001393 "iO!;ratecv(): illegal state argument",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001394 &d, &PyTuple_Type, &samps))
1395 goto exit;
1396 if (PyTuple_Size(samps) != nchannels) {
Hai Shi41fbf862020-03-12 00:49:11 +08001397 PyErr_SetString(get_audioop_state(module)->AudioopError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001398 "illegal state argument");
1399 goto exit;
Amaury Forgeot d'Arc9c74b142008-06-18 00:47:36 +00001400 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001401 for (chan = 0; chan < nchannels; chan++) {
Oren Milman1d1d3e92017-08-20 18:35:36 +03001402 channel = PyTuple_GetItem(samps, chan);
1403 if (!PyTuple_Check(channel)) {
1404 PyErr_SetString(PyExc_TypeError,
1405 "ratecv(): illegal state argument");
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001406 goto exit;
Oren Milman1d1d3e92017-08-20 18:35:36 +03001407 }
1408 if (!PyArg_ParseTuple(channel,
1409 "ii;ratecv(): illegal state argument",
1410 &prev_i[chan], &cur_i[chan]))
1411 {
1412 goto exit;
1413 }
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001414 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001415 }
Guido van Rossum1851a671997-02-14 16:14:03 +00001416
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001417 /* str <- Space for the output buffer. */
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001418 if (len == 0)
1419 str = PyBytes_FromStringAndSize(NULL, 0);
1420 else {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001421 /* There are len input frames, so we need (mathematically)
1422 ceiling(len*outrate/inrate) output frames, and each frame
1423 requires bytes_per_frame bytes. Computing this
1424 without spurious overflow is the challenge; we can
Mark Dickinson393b97a2010-05-11 13:09:58 +00001425 settle for a reasonable upper bound, though, in this
1426 case ceiling(len/inrate) * outrate. */
1427
1428 /* compute ceiling(len/inrate) without overflow */
Christian Heimesc4ab9a42014-01-27 01:12:00 +01001429 Py_ssize_t q = 1 + (len - 1) / inrate;
Mark Dickinson81fece22010-05-11 13:34:35 +00001430 if (outrate > PY_SSIZE_T_MAX / q / bytes_per_frame)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001431 str = NULL;
1432 else
Mark Dickinson393b97a2010-05-11 13:09:58 +00001433 str = PyBytes_FromStringAndSize(NULL,
1434 q * outrate * bytes_per_frame);
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001435 }
1436 if (str == NULL) {
1437 PyErr_SetString(PyExc_MemoryError,
1438 "not enough memory for output buffer");
1439 goto exit;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001440 }
1441 ncp = PyBytes_AsString(str);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001442 cp = fragment->buf;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001443
1444 for (;;) {
1445 while (d < 0) {
1446 if (len == 0) {
1447 samps = PyTuple_New(nchannels);
1448 if (samps == NULL)
1449 goto exit;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001450 for (chan = 0; chan < nchannels; chan++)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001451 PyTuple_SetItem(samps, chan,
1452 Py_BuildValue("(ii)",
1453 prev_i[chan],
1454 cur_i[chan]));
1455 if (PyErr_Occurred())
1456 goto exit;
1457 /* We have checked before that the length
1458 * of the string fits into int. */
Mark Dickinson81fece22010-05-11 13:34:35 +00001459 len = (Py_ssize_t)(ncp - PyBytes_AsString(str));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001460 rv = PyBytes_FromStringAndSize
1461 (PyBytes_AsString(str), len);
1462 Py_DECREF(str);
1463 str = rv;
1464 if (str == NULL)
1465 goto exit;
1466 rv = Py_BuildValue("(O(iO))", str, d, samps);
1467 Py_DECREF(samps);
1468 Py_DECREF(str);
1469 goto exit; /* return rv */
1470 }
1471 for (chan = 0; chan < nchannels; chan++) {
1472 prev_i[chan] = cur_i[chan];
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001473 cur_i[chan] = GETSAMPLE32(width, cp, 0);
1474 cp += width;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001475 /* implements a simple digital filter */
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001476 cur_i[chan] = (int)(
1477 ((double)weightA * (double)cur_i[chan] +
1478 (double)weightB * (double)prev_i[chan]) /
1479 ((double)weightA + (double)weightB));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001480 }
1481 len--;
1482 d += outrate;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001483 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001484 while (d >= 0) {
1485 for (chan = 0; chan < nchannels; chan++) {
Serhiy Storchaka01ad6222013-02-09 11:10:53 +02001486 cur_o = (int)(((double)prev_i[chan] * (double)d +
1487 (double)cur_i[chan] * (double)(outrate - d)) /
1488 (double)outrate);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001489 SETSAMPLE32(width, ncp, 0, cur_o);
1490 ncp += width;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001491 }
1492 d -= inrate;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001493 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001494 }
Guido van Rossum65bb3281999-09-07 14:24:05 +00001495 exit:
Victor Stinnerb6404912013-07-07 16:21:41 +02001496 PyMem_Free(prev_i);
1497 PyMem_Free(cur_i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001498 return rv;
Roger E. Massec905fff1997-01-17 18:12:04 +00001499}
Guido van Rossum1851a671997-02-14 16:14:03 +00001500
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001501/*[clinic input]
1502audioop.lin2ulaw
1503
1504 fragment: Py_buffer
1505 width: int
1506 /
1507
1508Convert samples in the audio fragment to u-LAW encoding.
1509[clinic start generated code]*/
1510
Roger E. Massec905fff1997-01-17 18:12:04 +00001511static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001512audioop_lin2ulaw_impl(PyObject *module, Py_buffer *fragment, int width)
1513/*[clinic end generated code: output=14fb62b16fe8ea8e input=2450d1b870b6bac2]*/
Guido van Rossumb66efa01992-06-01 16:01:24 +00001514{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001515 unsigned char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001516 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001517 PyObject *rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001518
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001519 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001520 return NULL;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001521
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001522 rv = PyBytes_FromStringAndSize(NULL, fragment->len/width);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001523 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001524 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001525 ncp = (unsigned char *)PyBytes_AsString(rv);
1526
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001527 for (i = 0; i < fragment->len; i += width) {
1528 int val = GETSAMPLE32(width, fragment->buf, i);
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001529 *ncp++ = st_14linear2ulaw(val >> 18);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001530 }
1531 return rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001532}
1533
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001534/*[clinic input]
1535audioop.ulaw2lin
1536
1537 fragment: Py_buffer
1538 width: int
1539 /
1540
1541Convert sound fragments in u-LAW encoding to linearly encoded sound fragments.
1542[clinic start generated code]*/
1543
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001544static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001545audioop_ulaw2lin_impl(PyObject *module, Py_buffer *fragment, int width)
1546/*[clinic end generated code: output=378356b047521ba2 input=45d53ddce5be7d06]*/
Guido van Rossumb66efa01992-06-01 16:01:24 +00001547{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001548 unsigned char *cp;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001549 signed char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001550 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001551 PyObject *rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001552
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001553 if (!audioop_check_size(module, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001554 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001555
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001556 if (fragment->len > PY_SSIZE_T_MAX/width) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001557 PyErr_SetString(PyExc_MemoryError,
1558 "not enough memory for output buffer");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001559 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001560 }
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001561 rv = PyBytes_FromStringAndSize(NULL, fragment->len*width);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001562 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001563 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001564 ncp = (signed char *)PyBytes_AsString(rv);
1565
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001566 cp = fragment->buf;
1567 for (i = 0; i < fragment->len*width; i += width) {
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001568 int val = st_ulaw2linear16(*cp++) << 16;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001569 SETSAMPLE32(width, ncp, i, val);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001570 }
1571 return rv;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001572}
1573
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001574/*[clinic input]
1575audioop.lin2alaw
1576
1577 fragment: Py_buffer
1578 width: int
1579 /
1580
1581Convert samples in the audio fragment to a-LAW encoding.
1582[clinic start generated code]*/
1583
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001584static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001585audioop_lin2alaw_impl(PyObject *module, Py_buffer *fragment, int width)
1586/*[clinic end generated code: output=d076f130121a82f0 input=ffb1ef8bb39da945]*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001587{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001588 unsigned char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001589 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001590 PyObject *rv;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001591
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001592 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001593 return NULL;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001594
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001595 rv = PyBytes_FromStringAndSize(NULL, fragment->len/width);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001596 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001597 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001598 ncp = (unsigned char *)PyBytes_AsString(rv);
1599
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001600 for (i = 0; i < fragment->len; i += width) {
1601 int val = GETSAMPLE32(width, fragment->buf, i);
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001602 *ncp++ = st_linear2alaw(val >> 19);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001603 }
1604 return rv;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001605}
1606
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001607/*[clinic input]
1608audioop.alaw2lin
1609
1610 fragment: Py_buffer
1611 width: int
1612 /
1613
1614Convert sound fragments in a-LAW encoding to linearly encoded sound fragments.
1615[clinic start generated code]*/
1616
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001617static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001618audioop_alaw2lin_impl(PyObject *module, Py_buffer *fragment, int width)
1619/*[clinic end generated code: output=85c365ec559df647 input=4140626046cd1772]*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001620{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001621 unsigned char *cp;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001622 signed char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001623 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001624 int val;
1625 PyObject *rv;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001626
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001627 if (!audioop_check_size(module, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001628 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001629
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001630 if (fragment->len > PY_SSIZE_T_MAX/width) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001631 PyErr_SetString(PyExc_MemoryError,
1632 "not enough memory for output buffer");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001633 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001634 }
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001635 rv = PyBytes_FromStringAndSize(NULL, fragment->len*width);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001636 if (rv == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001637 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001638 ncp = (signed char *)PyBytes_AsString(rv);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001639 cp = fragment->buf;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001640
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001641 for (i = 0; i < fragment->len*width; i += width) {
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001642 val = st_alaw2linear16(*cp++) << 16;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001643 SETSAMPLE32(width, ncp, i, val);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001644 }
1645 return rv;
Guido van Rossumb66efa01992-06-01 16:01:24 +00001646}
1647
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001648/*[clinic input]
1649audioop.lin2adpcm
1650
1651 fragment: Py_buffer
1652 width: int
1653 state: object
1654 /
1655
1656Convert samples to 4 bit Intel/DVI ADPCM encoding.
1657[clinic start generated code]*/
1658
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001659static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001660audioop_lin2adpcm_impl(PyObject *module, Py_buffer *fragment, int width,
Larry Hastings89964c42015-04-14 18:07:59 -04001661 PyObject *state)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001662/*[clinic end generated code: output=cc19f159f16c6793 input=12919d549b90c90a]*/
Guido van Rossumb64e6351992-07-06 14:21:56 +00001663{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001664 signed char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001665 Py_ssize_t i;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001666 int step, valpred, delta,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001667 index, sign, vpdiff, diff;
Benjamin Peterson08673c52014-01-26 10:24:24 -05001668 PyObject *rv = NULL, *str;
Mark Dickinson81fece22010-05-11 13:34:35 +00001669 int outputbuffer = 0, bufferstep;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001670
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001671 if (!audioop_check_parameters(module, fragment->len, width))
Victor Stinnerbc5c54b2010-07-03 13:44:22 +00001672 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001673
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001674 /* Decode state, should have (value, step) */
1675 if ( state == Py_None ) {
1676 /* First time, it seems. Set defaults */
1677 valpred = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001678 index = 0;
Benjamin Peterson08673c52014-01-26 10:24:24 -05001679 }
Serhiy Storchaka449e2be2015-06-28 17:52:09 +03001680 else if (!PyTuple_Check(state)) {
1681 PyErr_SetString(PyExc_TypeError, "state must be a tuple or None");
1682 return NULL;
1683 }
Oren Milman1d1d3e92017-08-20 18:35:36 +03001684 else if (!PyArg_ParseTuple(state, "ii;lin2adpcm(): illegal state argument",
1685 &valpred, &index))
1686 {
Serhiy Storchaka449e2be2015-06-28 17:52:09 +03001687 return NULL;
1688 }
1689 else if (valpred >= 0x8000 || valpred < -0x8000 ||
1690 (size_t)index >= Py_ARRAY_LENGTH(stepsizeTable)) {
1691 PyErr_SetString(PyExc_ValueError, "bad state");
1692 return NULL;
1693 }
1694
1695 str = PyBytes_FromStringAndSize(NULL, fragment->len/(width*2));
1696 if (str == NULL)
1697 return NULL;
1698 ncp = (signed char *)PyBytes_AsString(str);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001699
1700 step = stepsizeTable[index];
1701 bufferstep = 1;
1702
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001703 for (i = 0; i < fragment->len; i += width) {
1704 int val = GETSAMPLE32(width, fragment->buf, i) >> 16;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001705
1706 /* Step 1 - compute difference with previous value */
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001707 if (val < valpred) {
1708 diff = valpred - val;
1709 sign = 8;
1710 }
1711 else {
1712 diff = val - valpred;
1713 sign = 0;
1714 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001715
1716 /* Step 2 - Divide and clamp */
1717 /* Note:
1718 ** This code *approximately* computes:
1719 ** delta = diff*4/step;
1720 ** vpdiff = (delta+0.5)*step/4;
1721 ** but in shift step bits are dropped. The net result of this
1722 ** is that even if you have fast mul/div hardware you cannot
1723 ** put it to good use since the fixup would be too expensive.
1724 */
1725 delta = 0;
1726 vpdiff = (step >> 3);
1727
1728 if ( diff >= step ) {
1729 delta = 4;
1730 diff -= step;
1731 vpdiff += step;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001732 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001733 step >>= 1;
1734 if ( diff >= step ) {
1735 delta |= 2;
1736 diff -= step;
1737 vpdiff += step;
1738 }
1739 step >>= 1;
1740 if ( diff >= step ) {
1741 delta |= 1;
1742 vpdiff += step;
1743 }
Jack Jansendd8a6ea1993-02-17 14:21:09 +00001744
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001745 /* Step 3 - Update previous value */
1746 if ( sign )
1747 valpred -= vpdiff;
1748 else
1749 valpred += vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001750
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001751 /* Step 4 - Clamp previous value to 16 bits */
1752 if ( valpred > 32767 )
1753 valpred = 32767;
1754 else if ( valpred < -32768 )
1755 valpred = -32768;
1756
1757 /* Step 5 - Assemble value, update index and step values */
1758 delta |= sign;
1759
1760 index += indexTable[delta];
1761 if ( index < 0 ) index = 0;
1762 if ( index > 88 ) index = 88;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001763 step = stepsizeTable[index];
Guido van Rossumb64e6351992-07-06 14:21:56 +00001764
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001765 /* Step 6 - Output value */
1766 if ( bufferstep ) {
1767 outputbuffer = (delta << 4) & 0xf0;
1768 } else {
1769 *ncp++ = (delta & 0x0f) | outputbuffer;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001770 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001771 bufferstep = !bufferstep;
1772 }
1773 rv = Py_BuildValue("(O(ii))", str, valpred, index);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001774 Py_DECREF(str);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001775 return rv;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001776}
1777
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001778/*[clinic input]
1779audioop.adpcm2lin
1780
1781 fragment: Py_buffer
1782 width: int
1783 state: object
1784 /
1785
1786Decode an Intel/DVI ADPCM coded fragment to a linear fragment.
1787[clinic start generated code]*/
1788
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001789static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001790audioop_adpcm2lin_impl(PyObject *module, Py_buffer *fragment, int width,
Larry Hastings89964c42015-04-14 18:07:59 -04001791 PyObject *state)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001792/*[clinic end generated code: output=3440ea105acb3456 input=f5221144f5ca9ef0]*/
Guido van Rossumb64e6351992-07-06 14:21:56 +00001793{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001794 signed char *cp;
1795 signed char *ncp;
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001796 Py_ssize_t i, outlen;
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001797 int valpred, step, delta, index, sign, vpdiff;
1798 PyObject *rv, *str;
Mark Dickinson81fece22010-05-11 13:34:35 +00001799 int inputbuffer = 0, bufferstep;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001800
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001801 if (!audioop_check_size(module, width))
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001802 return NULL;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001803
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001804 /* Decode state, should have (value, step) */
1805 if ( state == Py_None ) {
1806 /* First time, it seems. Set defaults */
1807 valpred = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001808 index = 0;
Serhiy Storchaka449e2be2015-06-28 17:52:09 +03001809 }
1810 else if (!PyTuple_Check(state)) {
Victor Stinnerdaeffd22014-01-03 03:26:47 +01001811 PyErr_SetString(PyExc_TypeError, "state must be a tuple or None");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001812 return NULL;
Serhiy Storchaka449e2be2015-06-28 17:52:09 +03001813 }
Oren Milman1d1d3e92017-08-20 18:35:36 +03001814 else if (!PyArg_ParseTuple(state, "ii;adpcm2lin(): illegal state argument",
1815 &valpred, &index))
1816 {
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001817 return NULL;
Serhiy Storchaka449e2be2015-06-28 17:52:09 +03001818 }
1819 else if (valpred >= 0x8000 || valpred < -0x8000 ||
1820 (size_t)index >= Py_ARRAY_LENGTH(stepsizeTable)) {
1821 PyErr_SetString(PyExc_ValueError, "bad state");
1822 return NULL;
1823 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001824
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001825 if (fragment->len > (PY_SSIZE_T_MAX/2)/width) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001826 PyErr_SetString(PyExc_MemoryError,
1827 "not enough memory for output buffer");
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001828 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001829 }
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001830 outlen = fragment->len*width*2;
Serhiy Storchakaeaea5e92013-10-19 21:10:46 +03001831 str = PyBytes_FromStringAndSize(NULL, outlen);
Serhiy Storchaka711e91b2013-11-10 21:44:36 +02001832 if (str == NULL)
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001833 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001834 ncp = (signed char *)PyBytes_AsString(str);
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001835 cp = fragment->buf;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001836
1837 step = stepsizeTable[index];
1838 bufferstep = 0;
1839
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001840 for (i = 0; i < outlen; i += width) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001841 /* Step 1 - get the delta value and compute next index */
1842 if ( bufferstep ) {
1843 delta = inputbuffer & 0xf;
1844 } else {
1845 inputbuffer = *cp++;
1846 delta = (inputbuffer >> 4) & 0xf;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001847 }
Guido van Rossumb64e6351992-07-06 14:21:56 +00001848
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001849 bufferstep = !bufferstep;
1850
1851 /* Step 2 - Find new index value (for later) */
1852 index += indexTable[delta];
1853 if ( index < 0 ) index = 0;
1854 if ( index > 88 ) index = 88;
1855
1856 /* Step 3 - Separate sign and magnitude */
1857 sign = delta & 8;
1858 delta = delta & 7;
1859
1860 /* Step 4 - Compute difference and new predicted value */
1861 /*
1862 ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
1863 ** in adpcm_coder.
1864 */
1865 vpdiff = step >> 3;
1866 if ( delta & 4 ) vpdiff += step;
1867 if ( delta & 2 ) vpdiff += step>>1;
1868 if ( delta & 1 ) vpdiff += step>>2;
1869
1870 if ( sign )
1871 valpred -= vpdiff;
1872 else
1873 valpred += vpdiff;
1874
1875 /* Step 5 - clamp output value */
1876 if ( valpred > 32767 )
1877 valpred = 32767;
1878 else if ( valpred < -32768 )
1879 valpred = -32768;
1880
1881 /* Step 6 - Update step value */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001882 step = stepsizeTable[index];
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001883
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001884 /* Step 6 - Output value */
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001885 SETSAMPLE32(width, ncp, i, valpred << 16);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001886 }
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001887
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001888 rv = Py_BuildValue("(O(ii))", str, valpred, index);
1889 Py_DECREF(str);
1890 return rv;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001891}
1892
Larry Hastingsf256c222014-01-25 21:30:37 -08001893#include "clinic/audioop.c.h"
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001894
Roger E. Masseeaa6e111997-01-03 19:26:27 +00001895static PyMethodDef audioop_methods[] = {
Serhiy Storchaka8d00d732014-01-25 11:57:59 +02001896 AUDIOOP_MAX_METHODDEF
1897 AUDIOOP_MINMAX_METHODDEF
1898 AUDIOOP_AVG_METHODDEF
1899 AUDIOOP_MAXPP_METHODDEF
1900 AUDIOOP_AVGPP_METHODDEF
1901 AUDIOOP_RMS_METHODDEF
1902 AUDIOOP_FINDFIT_METHODDEF
1903 AUDIOOP_FINDMAX_METHODDEF
1904 AUDIOOP_FINDFACTOR_METHODDEF
1905 AUDIOOP_CROSS_METHODDEF
1906 AUDIOOP_MUL_METHODDEF
1907 AUDIOOP_ADD_METHODDEF
1908 AUDIOOP_BIAS_METHODDEF
1909 AUDIOOP_ULAW2LIN_METHODDEF
1910 AUDIOOP_LIN2ULAW_METHODDEF
1911 AUDIOOP_ALAW2LIN_METHODDEF
1912 AUDIOOP_LIN2ALAW_METHODDEF
1913 AUDIOOP_LIN2LIN_METHODDEF
1914 AUDIOOP_ADPCM2LIN_METHODDEF
1915 AUDIOOP_LIN2ADPCM_METHODDEF
1916 AUDIOOP_TOMONO_METHODDEF
1917 AUDIOOP_TOSTEREO_METHODDEF
1918 AUDIOOP_GETSAMPLE_METHODDEF
1919 AUDIOOP_REVERSE_METHODDEF
1920 AUDIOOP_BYTESWAP_METHODDEF
1921 AUDIOOP_RATECV_METHODDEF
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001922 { 0, 0 }
Guido van Rossumb66efa01992-06-01 16:01:24 +00001923};
1924
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001925static int
Hai Shi41fbf862020-03-12 00:49:11 +08001926audioop_traverse(PyObject *module, visitproc visit, void *arg)
1927{
Hai Shi13397ee2020-03-20 01:11:33 +08001928 audioop_state *state = get_audioop_state(module);
Victor Stinner5b1ef202020-03-17 18:09:46 +01001929 Py_VISIT(state->AudioopError);
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001930 return 0;
1931}
Hai Shi41fbf862020-03-12 00:49:11 +08001932
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001933static int
Hai Shi41fbf862020-03-12 00:49:11 +08001934audioop_clear(PyObject *module)
1935{
Hai Shi13397ee2020-03-20 01:11:33 +08001936 audioop_state *state = get_audioop_state(module);
Victor Stinner5b1ef202020-03-17 18:09:46 +01001937 Py_CLEAR(state->AudioopError);
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001938 return 0;
1939}
Hai Shi41fbf862020-03-12 00:49:11 +08001940
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001941static void
Hai Shi41fbf862020-03-12 00:49:11 +08001942audioop_free(void *module) {
1943 audioop_clear((PyObject *)module);
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001944}
Martin v. Löwis1a214512008-06-11 05:26:20 +00001945
Hai Shi41fbf862020-03-12 00:49:11 +08001946static int
1947audioop_exec(PyObject* module)
1948{
1949 audioop_state *state = get_audioop_state(module);
1950
1951 state->AudioopError = PyErr_NewException("audioop.error", NULL, NULL);
1952 if (state->AudioopError == NULL) {
1953 return -1;
1954 }
1955
1956 Py_INCREF(state->AudioopError);
1957 if (PyModule_AddObject(module, "error", state->AudioopError) < 0) {
1958 Py_DECREF(state->AudioopError);
1959 return -1;
1960 }
1961
1962 return 0;
1963}
1964
1965static PyModuleDef_Slot audioop_slots[] = {
1966 {Py_mod_exec, audioop_exec},
1967 {0, NULL}
1968};
1969
Martin v. Löwis1a214512008-06-11 05:26:20 +00001970static struct PyModuleDef audioopmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001971 PyModuleDef_HEAD_INIT,
1972 "audioop",
1973 NULL,
Hai Shi41fbf862020-03-12 00:49:11 +08001974 sizeof(audioop_state),
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001975 audioop_methods,
Hai Shi41fbf862020-03-12 00:49:11 +08001976 audioop_slots,
Tyler Kieftf548a3e2019-10-22 09:07:03 -04001977 audioop_traverse,
1978 audioop_clear,
1979 audioop_free
Martin v. Löwis1a214512008-06-11 05:26:20 +00001980};
1981
Mark Hammondfe51c6d2002-08-02 02:27:13 +00001982PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00001983PyInit_audioop(void)
Guido van Rossumb66efa01992-06-01 16:01:24 +00001984{
Hai Shi41fbf862020-03-12 00:49:11 +08001985 return PyModuleDef_Init(&audioopmodule);
Guido van Rossumb66efa01992-06-01 16:01:24 +00001986}