17db96d56Sopenharmony_ci/* The audioop module uses the code base in g777.c file of the Sox project.
27db96d56Sopenharmony_ci * Source: https://web.archive.org/web/19970716121258/http://www.spies.com/Sox/Archive/soxgamma.tar.gz
37db96d56Sopenharmony_ci *                 Programming the AdLib/Sound Blaster
47db96d56Sopenharmony_ci *                              FM Music Chips
57db96d56Sopenharmony_ci *                          Version 2.0 (24 Feb 1992)
67db96d56Sopenharmony_ci *
77db96d56Sopenharmony_ci *                 Copyright (c) 1991, 1992 by Jeffrey S. Lee
87db96d56Sopenharmony_ci *
97db96d56Sopenharmony_ci *                               jlee@smylex.uucp
107db96d56Sopenharmony_ci *
117db96d56Sopenharmony_ci *
127db96d56Sopenharmony_ci *
137db96d56Sopenharmony_ci *                       Warranty and Copyright Policy
147db96d56Sopenharmony_ci *
157db96d56Sopenharmony_ci *     This document is provided on an "as-is" basis, and its author makes
167db96d56Sopenharmony_ci *     no warranty or representation, express or implied, with respect to
177db96d56Sopenharmony_ci *    its quality performance or fitness for a particular purpose.  In no
187db96d56Sopenharmony_ci *    event will the author of this document be liable for direct, indirect,
197db96d56Sopenharmony_ci *    special, incidental, or consequential damages arising out of the use
207db96d56Sopenharmony_ci *    or inability to use the information contained within.  Use of this
217db96d56Sopenharmony_ci *    document is at your own risk.
227db96d56Sopenharmony_ci *
237db96d56Sopenharmony_ci *    This file may be used and copied freely so long as the applicable
247db96d56Sopenharmony_ci *    copyright notices are retained, and no modifications are made to the
257db96d56Sopenharmony_ci *    text of the document.  No money shall be charged for its distribution
267db96d56Sopenharmony_ci *    beyond reasonable shipping, handling and duplication costs, nor shall
277db96d56Sopenharmony_ci *    proprietary changes be made to this document so that it cannot be
287db96d56Sopenharmony_ci *    distributed freely.  This document may not be included in published
297db96d56Sopenharmony_ci *    material or commercial packages without the written consent of its
307db96d56Sopenharmony_ci *    author. */
317db96d56Sopenharmony_ci
327db96d56Sopenharmony_ci/* audioopmodule - Module to detect peak values in arrays */
337db96d56Sopenharmony_ci
347db96d56Sopenharmony_ci#define PY_SSIZE_T_CLEAN
357db96d56Sopenharmony_ci
367db96d56Sopenharmony_ci#include "Python.h"
377db96d56Sopenharmony_ci
387db96d56Sopenharmony_cistatic const int maxvals[] = {0, 0x7F, 0x7FFF, 0x7FFFFF, 0x7FFFFFFF};
397db96d56Sopenharmony_ci/* -1 trick is needed on Windows to support -0x80000000 without a warning */
407db96d56Sopenharmony_cistatic const int minvals[] = {0, -0x80, -0x8000, -0x800000, -0x7FFFFFFF-1};
417db96d56Sopenharmony_cistatic const unsigned int masks[] = {0, 0xFF, 0xFFFF, 0xFFFFFF, 0xFFFFFFFF};
427db96d56Sopenharmony_ci
437db96d56Sopenharmony_cistatic int
447db96d56Sopenharmony_cifbound(double val, double minval, double maxval)
457db96d56Sopenharmony_ci{
467db96d56Sopenharmony_ci    if (val > maxval) {
477db96d56Sopenharmony_ci        val = maxval;
487db96d56Sopenharmony_ci    }
497db96d56Sopenharmony_ci    else if (val < minval + 1.0) {
507db96d56Sopenharmony_ci        val = minval;
517db96d56Sopenharmony_ci    }
527db96d56Sopenharmony_ci
537db96d56Sopenharmony_ci    /* Round towards minus infinity (-inf) */
547db96d56Sopenharmony_ci    val = floor(val);
557db96d56Sopenharmony_ci
567db96d56Sopenharmony_ci    /* Cast double to integer: round towards zero */
577db96d56Sopenharmony_ci    return (int)val;
587db96d56Sopenharmony_ci}
597db96d56Sopenharmony_ci
607db96d56Sopenharmony_ci
617db96d56Sopenharmony_ci#define BIAS 0x84   /* define the add-in bias for 16 bit samples */
627db96d56Sopenharmony_ci#define CLIP 32635
637db96d56Sopenharmony_ci#define SIGN_BIT        (0x80)          /* Sign bit for an A-law byte. */
647db96d56Sopenharmony_ci#define QUANT_MASK      (0xf)           /* Quantization field mask. */
657db96d56Sopenharmony_ci#define SEG_SHIFT       (4)             /* Left shift for segment number. */
667db96d56Sopenharmony_ci#define SEG_MASK        (0x70)          /* Segment field mask. */
677db96d56Sopenharmony_ci
687db96d56Sopenharmony_cistatic const int16_t seg_aend[8] = {
697db96d56Sopenharmony_ci    0x1F, 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF
707db96d56Sopenharmony_ci};
717db96d56Sopenharmony_cistatic const int16_t seg_uend[8] = {
727db96d56Sopenharmony_ci    0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF
737db96d56Sopenharmony_ci};
747db96d56Sopenharmony_ci
757db96d56Sopenharmony_cistatic int16_t
767db96d56Sopenharmony_cisearch(int16_t val, const int16_t *table, int size)
777db96d56Sopenharmony_ci{
787db96d56Sopenharmony_ci    int i;
797db96d56Sopenharmony_ci
807db96d56Sopenharmony_ci    for (i = 0; i < size; i++) {
817db96d56Sopenharmony_ci        if (val <= *table++)
827db96d56Sopenharmony_ci            return (i);
837db96d56Sopenharmony_ci    }
847db96d56Sopenharmony_ci    return (size);
857db96d56Sopenharmony_ci}
867db96d56Sopenharmony_ci#define st_ulaw2linear16(uc) (_st_ulaw2linear16[uc])
877db96d56Sopenharmony_ci#define st_alaw2linear16(uc) (_st_alaw2linear16[uc])
887db96d56Sopenharmony_ci
897db96d56Sopenharmony_cistatic const int16_t _st_ulaw2linear16[256] = {
907db96d56Sopenharmony_ci    -32124,  -31100,  -30076,  -29052,  -28028,  -27004,  -25980,
917db96d56Sopenharmony_ci    -24956,  -23932,  -22908,  -21884,  -20860,  -19836,  -18812,
927db96d56Sopenharmony_ci    -17788,  -16764,  -15996,  -15484,  -14972,  -14460,  -13948,
937db96d56Sopenharmony_ci    -13436,  -12924,  -12412,  -11900,  -11388,  -10876,  -10364,
947db96d56Sopenharmony_ci     -9852,   -9340,   -8828,   -8316,   -7932,   -7676,   -7420,
957db96d56Sopenharmony_ci     -7164,   -6908,   -6652,   -6396,   -6140,   -5884,   -5628,
967db96d56Sopenharmony_ci     -5372,   -5116,   -4860,   -4604,   -4348,   -4092,   -3900,
977db96d56Sopenharmony_ci     -3772,   -3644,   -3516,   -3388,   -3260,   -3132,   -3004,
987db96d56Sopenharmony_ci     -2876,   -2748,   -2620,   -2492,   -2364,   -2236,   -2108,
997db96d56Sopenharmony_ci     -1980,   -1884,   -1820,   -1756,   -1692,   -1628,   -1564,
1007db96d56Sopenharmony_ci     -1500,   -1436,   -1372,   -1308,   -1244,   -1180,   -1116,
1017db96d56Sopenharmony_ci     -1052,    -988,    -924,    -876,    -844,    -812,    -780,
1027db96d56Sopenharmony_ci      -748,    -716,    -684,    -652,    -620,    -588,    -556,
1037db96d56Sopenharmony_ci      -524,    -492,    -460,    -428,    -396,    -372,    -356,
1047db96d56Sopenharmony_ci      -340,    -324,    -308,    -292,    -276,    -260,    -244,
1057db96d56Sopenharmony_ci      -228,    -212,    -196,    -180,    -164,    -148,    -132,
1067db96d56Sopenharmony_ci      -120,    -112,    -104,     -96,     -88,     -80,     -72,
1077db96d56Sopenharmony_ci       -64,     -56,     -48,     -40,     -32,     -24,     -16,
1087db96d56Sopenharmony_ci    -8,       0,   32124,   31100,   30076,   29052,   28028,
1097db96d56Sopenharmony_ci     27004,   25980,   24956,   23932,   22908,   21884,   20860,
1107db96d56Sopenharmony_ci     19836,   18812,   17788,   16764,   15996,   15484,   14972,
1117db96d56Sopenharmony_ci     14460,   13948,   13436,   12924,   12412,   11900,   11388,
1127db96d56Sopenharmony_ci     10876,   10364,    9852,    9340,    8828,    8316,    7932,
1137db96d56Sopenharmony_ci      7676,    7420,    7164,    6908,    6652,    6396,    6140,
1147db96d56Sopenharmony_ci      5884,    5628,    5372,    5116,    4860,    4604,    4348,
1157db96d56Sopenharmony_ci      4092,    3900,    3772,    3644,    3516,    3388,    3260,
1167db96d56Sopenharmony_ci      3132,    3004,    2876,    2748,    2620,    2492,    2364,
1177db96d56Sopenharmony_ci      2236,    2108,    1980,    1884,    1820,    1756,    1692,
1187db96d56Sopenharmony_ci      1628,    1564,    1500,    1436,    1372,    1308,    1244,
1197db96d56Sopenharmony_ci      1180,    1116,    1052,     988,     924,     876,     844,
1207db96d56Sopenharmony_ci       812,     780,     748,     716,     684,     652,     620,
1217db96d56Sopenharmony_ci       588,     556,     524,     492,     460,     428,     396,
1227db96d56Sopenharmony_ci       372,     356,     340,     324,     308,     292,     276,
1237db96d56Sopenharmony_ci       260,     244,     228,     212,     196,     180,     164,
1247db96d56Sopenharmony_ci       148,     132,     120,     112,     104,      96,      88,
1257db96d56Sopenharmony_ci    80,      72,      64,      56,      48,      40,      32,
1267db96d56Sopenharmony_ci    24,      16,       8,       0
1277db96d56Sopenharmony_ci};
1287db96d56Sopenharmony_ci
1297db96d56Sopenharmony_ci/*
1307db96d56Sopenharmony_ci * linear2ulaw() accepts a 14-bit signed integer and encodes it as u-law data
1317db96d56Sopenharmony_ci * stored in an unsigned char.  This function should only be called with
1327db96d56Sopenharmony_ci * the data shifted such that it only contains information in the lower
1337db96d56Sopenharmony_ci * 14-bits.
1347db96d56Sopenharmony_ci *
1357db96d56Sopenharmony_ci * In order to simplify the encoding process, the original linear magnitude
1367db96d56Sopenharmony_ci * is biased by adding 33 which shifts the encoding range from (0 - 8158) to
1377db96d56Sopenharmony_ci * (33 - 8191). The result can be seen in the following encoding table:
1387db96d56Sopenharmony_ci *
1397db96d56Sopenharmony_ci *      Biased Linear Input Code        Compressed Code
1407db96d56Sopenharmony_ci *      ------------------------        ---------------
1417db96d56Sopenharmony_ci *      00000001wxyza                   000wxyz
1427db96d56Sopenharmony_ci *      0000001wxyzab                   001wxyz
1437db96d56Sopenharmony_ci *      000001wxyzabc                   010wxyz
1447db96d56Sopenharmony_ci *      00001wxyzabcd                   011wxyz
1457db96d56Sopenharmony_ci *      0001wxyzabcde                   100wxyz
1467db96d56Sopenharmony_ci *      001wxyzabcdef                   101wxyz
1477db96d56Sopenharmony_ci *      01wxyzabcdefg                   110wxyz
1487db96d56Sopenharmony_ci *      1wxyzabcdefgh                   111wxyz
1497db96d56Sopenharmony_ci *
1507db96d56Sopenharmony_ci * Each biased linear code has a leading 1 which identifies the segment
1517db96d56Sopenharmony_ci * number. The value of the segment number is equal to 7 minus the number
1527db96d56Sopenharmony_ci * of leading 0's. The quantization interval is directly available as the
1537db96d56Sopenharmony_ci * four bits wxyz.  * The trailing bits (a - h) are ignored.
1547db96d56Sopenharmony_ci *
1557db96d56Sopenharmony_ci * Ordinarily the complement of the resulting code word is used for
1567db96d56Sopenharmony_ci * transmission, and so the code word is complemented before it is returned.
1577db96d56Sopenharmony_ci *
1587db96d56Sopenharmony_ci * For further information see John C. Bellamy's Digital Telephony, 1982,
1597db96d56Sopenharmony_ci * John Wiley & Sons, pps 98-111 and 472-476.
1607db96d56Sopenharmony_ci */
1617db96d56Sopenharmony_cistatic unsigned char
1627db96d56Sopenharmony_cist_14linear2ulaw(int16_t pcm_val)       /* 2's complement (14-bit range) */
1637db96d56Sopenharmony_ci{
1647db96d56Sopenharmony_ci    int16_t         mask;
1657db96d56Sopenharmony_ci    int16_t         seg;
1667db96d56Sopenharmony_ci    unsigned char   uval;
1677db96d56Sopenharmony_ci
1687db96d56Sopenharmony_ci    /* u-law inverts all bits */
1697db96d56Sopenharmony_ci    /* Get the sign and the magnitude of the value. */
1707db96d56Sopenharmony_ci    if (pcm_val < 0) {
1717db96d56Sopenharmony_ci        pcm_val = -pcm_val;
1727db96d56Sopenharmony_ci        mask = 0x7F;
1737db96d56Sopenharmony_ci    } else {
1747db96d56Sopenharmony_ci        mask = 0xFF;
1757db96d56Sopenharmony_ci    }
1767db96d56Sopenharmony_ci    if ( pcm_val > CLIP ) pcm_val = CLIP;           /* clip the magnitude */
1777db96d56Sopenharmony_ci    pcm_val += (BIAS >> 2);
1787db96d56Sopenharmony_ci
1797db96d56Sopenharmony_ci    /* Convert the scaled magnitude to segment number. */
1807db96d56Sopenharmony_ci    seg = search(pcm_val, seg_uend, 8);
1817db96d56Sopenharmony_ci
1827db96d56Sopenharmony_ci    /*
1837db96d56Sopenharmony_ci     * Combine the sign, segment, quantization bits;
1847db96d56Sopenharmony_ci     * and complement the code word.
1857db96d56Sopenharmony_ci     */
1867db96d56Sopenharmony_ci    if (seg >= 8)           /* out of range, return maximum value. */
1877db96d56Sopenharmony_ci        return (unsigned char) (0x7F ^ mask);
1887db96d56Sopenharmony_ci    else {
1897db96d56Sopenharmony_ci        uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF);
1907db96d56Sopenharmony_ci        return (uval ^ mask);
1917db96d56Sopenharmony_ci    }
1927db96d56Sopenharmony_ci
1937db96d56Sopenharmony_ci}
1947db96d56Sopenharmony_ci
1957db96d56Sopenharmony_cistatic const int16_t _st_alaw2linear16[256] = {
1967db96d56Sopenharmony_ci     -5504,   -5248,   -6016,   -5760,   -4480,   -4224,   -4992,
1977db96d56Sopenharmony_ci     -4736,   -7552,   -7296,   -8064,   -7808,   -6528,   -6272,
1987db96d56Sopenharmony_ci     -7040,   -6784,   -2752,   -2624,   -3008,   -2880,   -2240,
1997db96d56Sopenharmony_ci     -2112,   -2496,   -2368,   -3776,   -3648,   -4032,   -3904,
2007db96d56Sopenharmony_ci     -3264,   -3136,   -3520,   -3392,  -22016,  -20992,  -24064,
2017db96d56Sopenharmony_ci    -23040,  -17920,  -16896,  -19968,  -18944,  -30208,  -29184,
2027db96d56Sopenharmony_ci    -32256,  -31232,  -26112,  -25088,  -28160,  -27136,  -11008,
2037db96d56Sopenharmony_ci    -10496,  -12032,  -11520,   -8960,   -8448,   -9984,   -9472,
2047db96d56Sopenharmony_ci    -15104,  -14592,  -16128,  -15616,  -13056,  -12544,  -14080,
2057db96d56Sopenharmony_ci    -13568,    -344,    -328,    -376,    -360,    -280,    -264,
2067db96d56Sopenharmony_ci      -312,    -296,    -472,    -456,    -504,    -488,    -408,
2077db96d56Sopenharmony_ci      -392,    -440,    -424,     -88,     -72,    -120,    -104,
2087db96d56Sopenharmony_ci       -24,      -8,     -56,     -40,    -216,    -200,    -248,
2097db96d56Sopenharmony_ci      -232,    -152,    -136,    -184,    -168,   -1376,   -1312,
2107db96d56Sopenharmony_ci     -1504,   -1440,   -1120,   -1056,   -1248,   -1184,   -1888,
2117db96d56Sopenharmony_ci     -1824,   -2016,   -1952,   -1632,   -1568,   -1760,   -1696,
2127db96d56Sopenharmony_ci      -688,    -656,    -752,    -720,    -560,    -528,    -624,
2137db96d56Sopenharmony_ci      -592,    -944,    -912,   -1008,    -976,    -816,    -784,
2147db96d56Sopenharmony_ci      -880,    -848,    5504,    5248,    6016,    5760,    4480,
2157db96d56Sopenharmony_ci      4224,    4992,    4736,    7552,    7296,    8064,    7808,
2167db96d56Sopenharmony_ci      6528,    6272,    7040,    6784,    2752,    2624,    3008,
2177db96d56Sopenharmony_ci      2880,    2240,    2112,    2496,    2368,    3776,    3648,
2187db96d56Sopenharmony_ci      4032,    3904,    3264,    3136,    3520,    3392,   22016,
2197db96d56Sopenharmony_ci     20992,   24064,   23040,   17920,   16896,   19968,   18944,
2207db96d56Sopenharmony_ci     30208,   29184,   32256,   31232,   26112,   25088,   28160,
2217db96d56Sopenharmony_ci     27136,   11008,   10496,   12032,   11520,    8960,    8448,
2227db96d56Sopenharmony_ci      9984,    9472,   15104,   14592,   16128,   15616,   13056,
2237db96d56Sopenharmony_ci     12544,   14080,   13568,     344,     328,     376,     360,
2247db96d56Sopenharmony_ci       280,     264,     312,     296,     472,     456,     504,
2257db96d56Sopenharmony_ci       488,     408,     392,     440,     424,      88,      72,
2267db96d56Sopenharmony_ci       120,     104,      24,       8,      56,      40,     216,
2277db96d56Sopenharmony_ci       200,     248,     232,     152,     136,     184,     168,
2287db96d56Sopenharmony_ci      1376,    1312,    1504,    1440,    1120,    1056,    1248,
2297db96d56Sopenharmony_ci      1184,    1888,    1824,    2016,    1952,    1632,    1568,
2307db96d56Sopenharmony_ci      1760,    1696,     688,     656,     752,     720,     560,
2317db96d56Sopenharmony_ci       528,     624,     592,     944,     912,    1008,     976,
2327db96d56Sopenharmony_ci       816,     784,     880,     848
2337db96d56Sopenharmony_ci};
2347db96d56Sopenharmony_ci
2357db96d56Sopenharmony_ci/*
2367db96d56Sopenharmony_ci * linear2alaw() accepts a 13-bit signed integer and encodes it as A-law data
2377db96d56Sopenharmony_ci * stored in an unsigned char.  This function should only be called with
2387db96d56Sopenharmony_ci * the data shifted such that it only contains information in the lower
2397db96d56Sopenharmony_ci * 13-bits.
2407db96d56Sopenharmony_ci *
2417db96d56Sopenharmony_ci *              Linear Input Code       Compressed Code
2427db96d56Sopenharmony_ci *      ------------------------        ---------------
2437db96d56Sopenharmony_ci *      0000000wxyza                    000wxyz
2447db96d56Sopenharmony_ci *      0000001wxyza                    001wxyz
2457db96d56Sopenharmony_ci *      000001wxyzab                    010wxyz
2467db96d56Sopenharmony_ci *      00001wxyzabc                    011wxyz
2477db96d56Sopenharmony_ci *      0001wxyzabcd                    100wxyz
2487db96d56Sopenharmony_ci *      001wxyzabcde                    101wxyz
2497db96d56Sopenharmony_ci *      01wxyzabcdef                    110wxyz
2507db96d56Sopenharmony_ci *      1wxyzabcdefg                    111wxyz
2517db96d56Sopenharmony_ci *
2527db96d56Sopenharmony_ci * For further information see John C. Bellamy's Digital Telephony, 1982,
2537db96d56Sopenharmony_ci * John Wiley & Sons, pps 98-111 and 472-476.
2547db96d56Sopenharmony_ci */
2557db96d56Sopenharmony_cistatic unsigned char
2567db96d56Sopenharmony_cist_linear2alaw(int16_t pcm_val) /* 2's complement (13-bit range) */
2577db96d56Sopenharmony_ci{
2587db96d56Sopenharmony_ci    int16_t         mask;
2597db96d56Sopenharmony_ci    int16_t         seg;
2607db96d56Sopenharmony_ci    unsigned char   aval;
2617db96d56Sopenharmony_ci
2627db96d56Sopenharmony_ci    /* A-law using even bit inversion */
2637db96d56Sopenharmony_ci    if (pcm_val >= 0) {
2647db96d56Sopenharmony_ci        mask = 0xD5;            /* sign (7th) bit = 1 */
2657db96d56Sopenharmony_ci    } else {
2667db96d56Sopenharmony_ci        mask = 0x55;            /* sign bit = 0 */
2677db96d56Sopenharmony_ci        pcm_val = -pcm_val - 1;
2687db96d56Sopenharmony_ci    }
2697db96d56Sopenharmony_ci
2707db96d56Sopenharmony_ci    /* Convert the scaled magnitude to segment number. */
2717db96d56Sopenharmony_ci    seg = search(pcm_val, seg_aend, 8);
2727db96d56Sopenharmony_ci
2737db96d56Sopenharmony_ci    /* Combine the sign, segment, and quantization bits. */
2747db96d56Sopenharmony_ci
2757db96d56Sopenharmony_ci    if (seg >= 8)           /* out of range, return maximum value. */
2767db96d56Sopenharmony_ci        return (unsigned char) (0x7F ^ mask);
2777db96d56Sopenharmony_ci    else {
2787db96d56Sopenharmony_ci        aval = (unsigned char) seg << SEG_SHIFT;
2797db96d56Sopenharmony_ci        if (seg < 2)
2807db96d56Sopenharmony_ci            aval |= (pcm_val >> 1) & QUANT_MASK;
2817db96d56Sopenharmony_ci        else
2827db96d56Sopenharmony_ci            aval |= (pcm_val >> seg) & QUANT_MASK;
2837db96d56Sopenharmony_ci        return (aval ^ mask);
2847db96d56Sopenharmony_ci    }
2857db96d56Sopenharmony_ci}
2867db96d56Sopenharmony_ci/* End of code taken from sox */
2877db96d56Sopenharmony_ci
2887db96d56Sopenharmony_ci/* Intel ADPCM step variation table */
2897db96d56Sopenharmony_cistatic const int indexTable[16] = {
2907db96d56Sopenharmony_ci    -1, -1, -1, -1, 2, 4, 6, 8,
2917db96d56Sopenharmony_ci    -1, -1, -1, -1, 2, 4, 6, 8,
2927db96d56Sopenharmony_ci};
2937db96d56Sopenharmony_ci
2947db96d56Sopenharmony_cistatic const int stepsizeTable[89] = {
2957db96d56Sopenharmony_ci    7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
2967db96d56Sopenharmony_ci    19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
2977db96d56Sopenharmony_ci    50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
2987db96d56Sopenharmony_ci    130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
2997db96d56Sopenharmony_ci    337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
3007db96d56Sopenharmony_ci    876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
3017db96d56Sopenharmony_ci    2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
3027db96d56Sopenharmony_ci    5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
3037db96d56Sopenharmony_ci    15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
3047db96d56Sopenharmony_ci};
3057db96d56Sopenharmony_ci
3067db96d56Sopenharmony_ci#define GETINTX(T, cp, i)  (*(T *)((unsigned char *)(cp) + (i)))
3077db96d56Sopenharmony_ci#define SETINTX(T, cp, i, val)  do {                    \
3087db96d56Sopenharmony_ci        *(T *)((unsigned char *)(cp) + (i)) = (T)(val); \
3097db96d56Sopenharmony_ci    } while (0)
3107db96d56Sopenharmony_ci
3117db96d56Sopenharmony_ci
3127db96d56Sopenharmony_ci#define GETINT8(cp, i)          GETINTX(signed char, (cp), (i))
3137db96d56Sopenharmony_ci#define GETINT16(cp, i)         GETINTX(int16_t, (cp), (i))
3147db96d56Sopenharmony_ci#define GETINT32(cp, i)         GETINTX(int32_t, (cp), (i))
3157db96d56Sopenharmony_ci
3167db96d56Sopenharmony_ci#ifdef WORDS_BIGENDIAN
3177db96d56Sopenharmony_ci#define GETINT24(cp, i)  (                              \
3187db96d56Sopenharmony_ci        ((unsigned char *)(cp) + (i))[2] +              \
3197db96d56Sopenharmony_ci        (((unsigned char *)(cp) + (i))[1] << 8) +       \
3207db96d56Sopenharmony_ci        (((signed char *)(cp) + (i))[0] << 16) )
3217db96d56Sopenharmony_ci#else
3227db96d56Sopenharmony_ci#define GETINT24(cp, i)  (                              \
3237db96d56Sopenharmony_ci        ((unsigned char *)(cp) + (i))[0] +              \
3247db96d56Sopenharmony_ci        (((unsigned char *)(cp) + (i))[1] << 8) +       \
3257db96d56Sopenharmony_ci        (((signed char *)(cp) + (i))[2] << 16) )
3267db96d56Sopenharmony_ci#endif
3277db96d56Sopenharmony_ci
3287db96d56Sopenharmony_ci
3297db96d56Sopenharmony_ci#define SETINT8(cp, i, val)     SETINTX(signed char, (cp), (i), (val))
3307db96d56Sopenharmony_ci#define SETINT16(cp, i, val)    SETINTX(int16_t, (cp), (i), (val))
3317db96d56Sopenharmony_ci#define SETINT32(cp, i, val)    SETINTX(int32_t, (cp), (i), (val))
3327db96d56Sopenharmony_ci
3337db96d56Sopenharmony_ci#ifdef WORDS_BIGENDIAN
3347db96d56Sopenharmony_ci#define SETINT24(cp, i, val)  do {                              \
3357db96d56Sopenharmony_ci        ((unsigned char *)(cp) + (i))[2] = (int)(val);          \
3367db96d56Sopenharmony_ci        ((unsigned char *)(cp) + (i))[1] = (int)(val) >> 8;     \
3377db96d56Sopenharmony_ci        ((signed char *)(cp) + (i))[0] = (int)(val) >> 16;      \
3387db96d56Sopenharmony_ci    } while (0)
3397db96d56Sopenharmony_ci#else
3407db96d56Sopenharmony_ci#define SETINT24(cp, i, val)  do {                              \
3417db96d56Sopenharmony_ci        ((unsigned char *)(cp) + (i))[0] = (int)(val);          \
3427db96d56Sopenharmony_ci        ((unsigned char *)(cp) + (i))[1] = (int)(val) >> 8;     \
3437db96d56Sopenharmony_ci        ((signed char *)(cp) + (i))[2] = (int)(val) >> 16;      \
3447db96d56Sopenharmony_ci    } while (0)
3457db96d56Sopenharmony_ci#endif
3467db96d56Sopenharmony_ci
3477db96d56Sopenharmony_ci
3487db96d56Sopenharmony_ci#define GETRAWSAMPLE(size, cp, i)  (                    \
3497db96d56Sopenharmony_ci        (size == 1) ? (int)GETINT8((cp), (i)) :         \
3507db96d56Sopenharmony_ci        (size == 2) ? (int)GETINT16((cp), (i)) :        \
3517db96d56Sopenharmony_ci        (size == 3) ? (int)GETINT24((cp), (i)) :        \
3527db96d56Sopenharmony_ci                      (int)GETINT32((cp), (i)))
3537db96d56Sopenharmony_ci
3547db96d56Sopenharmony_ci#define SETRAWSAMPLE(size, cp, i, val)  do {    \
3557db96d56Sopenharmony_ci        if (size == 1)                          \
3567db96d56Sopenharmony_ci            SETINT8((cp), (i), (val));          \
3577db96d56Sopenharmony_ci        else if (size == 2)                     \
3587db96d56Sopenharmony_ci            SETINT16((cp), (i), (val));         \
3597db96d56Sopenharmony_ci        else if (size == 3)                     \
3607db96d56Sopenharmony_ci            SETINT24((cp), (i), (val));         \
3617db96d56Sopenharmony_ci        else                                    \
3627db96d56Sopenharmony_ci            SETINT32((cp), (i), (val));         \
3637db96d56Sopenharmony_ci    } while(0)
3647db96d56Sopenharmony_ci
3657db96d56Sopenharmony_ci
3667db96d56Sopenharmony_ci#define GETSAMPLE32(size, cp, i)  (                     \
3677db96d56Sopenharmony_ci        (size == 1) ? (int)GETINT8((cp), (i)) << 24 :   \
3687db96d56Sopenharmony_ci        (size == 2) ? (int)GETINT16((cp), (i)) << 16 :  \
3697db96d56Sopenharmony_ci        (size == 3) ? (int)GETINT24((cp), (i)) << 8 :   \
3707db96d56Sopenharmony_ci                      (int)GETINT32((cp), (i)))
3717db96d56Sopenharmony_ci
3727db96d56Sopenharmony_ci#define SETSAMPLE32(size, cp, i, val)  do {     \
3737db96d56Sopenharmony_ci        if (size == 1)                          \
3747db96d56Sopenharmony_ci            SETINT8((cp), (i), (val) >> 24);    \
3757db96d56Sopenharmony_ci        else if (size == 2)                     \
3767db96d56Sopenharmony_ci            SETINT16((cp), (i), (val) >> 16);   \
3777db96d56Sopenharmony_ci        else if (size == 3)                     \
3787db96d56Sopenharmony_ci            SETINT24((cp), (i), (val) >> 8);    \
3797db96d56Sopenharmony_ci        else                                    \
3807db96d56Sopenharmony_ci            SETINT32((cp), (i), (val));         \
3817db96d56Sopenharmony_ci    } while(0)
3827db96d56Sopenharmony_ci
3837db96d56Sopenharmony_cistatic PyModuleDef audioopmodule;
3847db96d56Sopenharmony_ci
3857db96d56Sopenharmony_citypedef struct {
3867db96d56Sopenharmony_ci    PyObject *AudioopError;
3877db96d56Sopenharmony_ci} audioop_state;
3887db96d56Sopenharmony_ci
3897db96d56Sopenharmony_cistatic inline audioop_state *
3907db96d56Sopenharmony_ciget_audioop_state(PyObject *module)
3917db96d56Sopenharmony_ci{
3927db96d56Sopenharmony_ci    void *state = PyModule_GetState(module);
3937db96d56Sopenharmony_ci    assert(state != NULL);
3947db96d56Sopenharmony_ci    return (audioop_state *)state;
3957db96d56Sopenharmony_ci}
3967db96d56Sopenharmony_ci
3977db96d56Sopenharmony_cistatic int
3987db96d56Sopenharmony_ciaudioop_check_size(PyObject *module, int size)
3997db96d56Sopenharmony_ci{
4007db96d56Sopenharmony_ci    if (size < 1 || size > 4) {
4017db96d56Sopenharmony_ci        PyErr_SetString(get_audioop_state(module)->AudioopError,
4027db96d56Sopenharmony_ci                        "Size should be 1, 2, 3 or 4");
4037db96d56Sopenharmony_ci        return 0;
4047db96d56Sopenharmony_ci    }
4057db96d56Sopenharmony_ci    else
4067db96d56Sopenharmony_ci        return 1;
4077db96d56Sopenharmony_ci}
4087db96d56Sopenharmony_ci
4097db96d56Sopenharmony_cistatic int
4107db96d56Sopenharmony_ciaudioop_check_parameters(PyObject *module, Py_ssize_t len, int size)
4117db96d56Sopenharmony_ci{
4127db96d56Sopenharmony_ci    if (!audioop_check_size(module, size))
4137db96d56Sopenharmony_ci        return 0;
4147db96d56Sopenharmony_ci    if (len % size != 0) {
4157db96d56Sopenharmony_ci        PyErr_SetString(get_audioop_state(module)->AudioopError,
4167db96d56Sopenharmony_ci                        "not a whole number of frames");
4177db96d56Sopenharmony_ci        return 0;
4187db96d56Sopenharmony_ci    }
4197db96d56Sopenharmony_ci    return 1;
4207db96d56Sopenharmony_ci}
4217db96d56Sopenharmony_ci
4227db96d56Sopenharmony_ci/*[clinic input]
4237db96d56Sopenharmony_cimodule audioop
4247db96d56Sopenharmony_ci[clinic start generated code]*/
4257db96d56Sopenharmony_ci/*[clinic end generated code: output=da39a3ee5e6b4b0d input=8fa8f6611be3591a]*/
4267db96d56Sopenharmony_ci
4277db96d56Sopenharmony_ci/*[clinic input]
4287db96d56Sopenharmony_ciaudioop.getsample
4297db96d56Sopenharmony_ci
4307db96d56Sopenharmony_ci    fragment: Py_buffer
4317db96d56Sopenharmony_ci    width: int
4327db96d56Sopenharmony_ci    index: Py_ssize_t
4337db96d56Sopenharmony_ci    /
4347db96d56Sopenharmony_ci
4357db96d56Sopenharmony_ciReturn the value of sample index from the fragment.
4367db96d56Sopenharmony_ci[clinic start generated code]*/
4377db96d56Sopenharmony_ci
4387db96d56Sopenharmony_cistatic PyObject *
4397db96d56Sopenharmony_ciaudioop_getsample_impl(PyObject *module, Py_buffer *fragment, int width,
4407db96d56Sopenharmony_ci                       Py_ssize_t index)
4417db96d56Sopenharmony_ci/*[clinic end generated code: output=8fe1b1775134f39a input=88edbe2871393549]*/
4427db96d56Sopenharmony_ci{
4437db96d56Sopenharmony_ci    int val;
4447db96d56Sopenharmony_ci
4457db96d56Sopenharmony_ci    if (!audioop_check_parameters(module, fragment->len, width))
4467db96d56Sopenharmony_ci        return NULL;
4477db96d56Sopenharmony_ci    if (index < 0 || index >= fragment->len/width) {
4487db96d56Sopenharmony_ci        PyErr_SetString(get_audioop_state(module)->AudioopError,
4497db96d56Sopenharmony_ci                        "Index out of range");
4507db96d56Sopenharmony_ci        return NULL;
4517db96d56Sopenharmony_ci    }
4527db96d56Sopenharmony_ci    val = GETRAWSAMPLE(width, fragment->buf, index*width);
4537db96d56Sopenharmony_ci    return PyLong_FromLong(val);
4547db96d56Sopenharmony_ci}
4557db96d56Sopenharmony_ci
4567db96d56Sopenharmony_ci/*[clinic input]
4577db96d56Sopenharmony_ciaudioop.max
4587db96d56Sopenharmony_ci
4597db96d56Sopenharmony_ci    fragment: Py_buffer
4607db96d56Sopenharmony_ci    width: int
4617db96d56Sopenharmony_ci    /
4627db96d56Sopenharmony_ci
4637db96d56Sopenharmony_ciReturn the maximum of the absolute value of all samples in a fragment.
4647db96d56Sopenharmony_ci[clinic start generated code]*/
4657db96d56Sopenharmony_ci
4667db96d56Sopenharmony_cistatic PyObject *
4677db96d56Sopenharmony_ciaudioop_max_impl(PyObject *module, Py_buffer *fragment, int width)
4687db96d56Sopenharmony_ci/*[clinic end generated code: output=e6c5952714f1c3f0 input=32bea5ea0ac8c223]*/
4697db96d56Sopenharmony_ci{
4707db96d56Sopenharmony_ci    Py_ssize_t i;
4717db96d56Sopenharmony_ci    unsigned int absval, max = 0;
4727db96d56Sopenharmony_ci
4737db96d56Sopenharmony_ci    if (!audioop_check_parameters(module, fragment->len, width))
4747db96d56Sopenharmony_ci        return NULL;
4757db96d56Sopenharmony_ci    for (i = 0; i < fragment->len; i += width) {
4767db96d56Sopenharmony_ci        int val = GETRAWSAMPLE(width, fragment->buf, i);
4777db96d56Sopenharmony_ci        /* Cast to unsigned before negating. Unsigned overflow is well-
4787db96d56Sopenharmony_ci        defined, but signed overflow is not. */
4797db96d56Sopenharmony_ci        if (val < 0) absval = (unsigned int)-(int64_t)val;
4807db96d56Sopenharmony_ci        else absval = val;
4817db96d56Sopenharmony_ci        if (absval > max) max = absval;
4827db96d56Sopenharmony_ci    }
4837db96d56Sopenharmony_ci    return PyLong_FromUnsignedLong(max);
4847db96d56Sopenharmony_ci}
4857db96d56Sopenharmony_ci
4867db96d56Sopenharmony_ci/*[clinic input]
4877db96d56Sopenharmony_ciaudioop.minmax
4887db96d56Sopenharmony_ci
4897db96d56Sopenharmony_ci    fragment: Py_buffer
4907db96d56Sopenharmony_ci    width: int
4917db96d56Sopenharmony_ci    /
4927db96d56Sopenharmony_ci
4937db96d56Sopenharmony_ciReturn the minimum and maximum values of all samples in the sound fragment.
4947db96d56Sopenharmony_ci[clinic start generated code]*/
4957db96d56Sopenharmony_ci
4967db96d56Sopenharmony_cistatic PyObject *
4977db96d56Sopenharmony_ciaudioop_minmax_impl(PyObject *module, Py_buffer *fragment, int width)
4987db96d56Sopenharmony_ci/*[clinic end generated code: output=473fda66b15c836e input=89848e9b927a0696]*/
4997db96d56Sopenharmony_ci{
5007db96d56Sopenharmony_ci    Py_ssize_t i;
5017db96d56Sopenharmony_ci    /* -1 trick below is needed on Windows to support -0x80000000 without
5027db96d56Sopenharmony_ci    a warning */
5037db96d56Sopenharmony_ci    int min = 0x7fffffff, max = -0x7FFFFFFF-1;
5047db96d56Sopenharmony_ci
5057db96d56Sopenharmony_ci    if (!audioop_check_parameters(module, fragment->len, width))
5067db96d56Sopenharmony_ci        return NULL;
5077db96d56Sopenharmony_ci    for (i = 0; i < fragment->len; i += width) {
5087db96d56Sopenharmony_ci        int val = GETRAWSAMPLE(width, fragment->buf, i);
5097db96d56Sopenharmony_ci        if (val > max) max = val;
5107db96d56Sopenharmony_ci        if (val < min) min = val;
5117db96d56Sopenharmony_ci    }
5127db96d56Sopenharmony_ci    return Py_BuildValue("(ii)", min, max);
5137db96d56Sopenharmony_ci}
5147db96d56Sopenharmony_ci
5157db96d56Sopenharmony_ci/*[clinic input]
5167db96d56Sopenharmony_ciaudioop.avg
5177db96d56Sopenharmony_ci
5187db96d56Sopenharmony_ci    fragment: Py_buffer
5197db96d56Sopenharmony_ci    width: int
5207db96d56Sopenharmony_ci    /
5217db96d56Sopenharmony_ci
5227db96d56Sopenharmony_ciReturn the average over all samples in the fragment.
5237db96d56Sopenharmony_ci[clinic start generated code]*/
5247db96d56Sopenharmony_ci
5257db96d56Sopenharmony_cistatic PyObject *
5267db96d56Sopenharmony_ciaudioop_avg_impl(PyObject *module, Py_buffer *fragment, int width)
5277db96d56Sopenharmony_ci/*[clinic end generated code: output=4410a4c12c3586e6 input=1114493c7611334d]*/
5287db96d56Sopenharmony_ci{
5297db96d56Sopenharmony_ci    Py_ssize_t i;
5307db96d56Sopenharmony_ci    int avg;
5317db96d56Sopenharmony_ci    double sum = 0.0;
5327db96d56Sopenharmony_ci
5337db96d56Sopenharmony_ci    if (!audioop_check_parameters(module, fragment->len, width))
5347db96d56Sopenharmony_ci        return NULL;
5357db96d56Sopenharmony_ci    for (i = 0; i < fragment->len; i += width)
5367db96d56Sopenharmony_ci        sum += GETRAWSAMPLE(width, fragment->buf, i);
5377db96d56Sopenharmony_ci    if (fragment->len == 0)
5387db96d56Sopenharmony_ci        avg = 0;
5397db96d56Sopenharmony_ci    else
5407db96d56Sopenharmony_ci        avg = (int)floor(sum / (double)(fragment->len/width));
5417db96d56Sopenharmony_ci    return PyLong_FromLong(avg);
5427db96d56Sopenharmony_ci}
5437db96d56Sopenharmony_ci
5447db96d56Sopenharmony_ci/*[clinic input]
5457db96d56Sopenharmony_ciaudioop.rms
5467db96d56Sopenharmony_ci
5477db96d56Sopenharmony_ci    fragment: Py_buffer
5487db96d56Sopenharmony_ci    width: int
5497db96d56Sopenharmony_ci    /
5507db96d56Sopenharmony_ci
5517db96d56Sopenharmony_ciReturn the root-mean-square of the fragment, i.e. sqrt(sum(S_i^2)/n).
5527db96d56Sopenharmony_ci[clinic start generated code]*/
5537db96d56Sopenharmony_ci
5547db96d56Sopenharmony_cistatic PyObject *
5557db96d56Sopenharmony_ciaudioop_rms_impl(PyObject *module, Py_buffer *fragment, int width)
5567db96d56Sopenharmony_ci/*[clinic end generated code: output=1e7871c826445698 input=4cc57c6c94219d78]*/
5577db96d56Sopenharmony_ci{
5587db96d56Sopenharmony_ci    Py_ssize_t i;
5597db96d56Sopenharmony_ci    unsigned int res;
5607db96d56Sopenharmony_ci    double sum_squares = 0.0;
5617db96d56Sopenharmony_ci
5627db96d56Sopenharmony_ci    if (!audioop_check_parameters(module, fragment->len, width))
5637db96d56Sopenharmony_ci        return NULL;
5647db96d56Sopenharmony_ci    for (i = 0; i < fragment->len; i += width) {
5657db96d56Sopenharmony_ci        double val = GETRAWSAMPLE(width, fragment->buf, i);
5667db96d56Sopenharmony_ci        sum_squares += val*val;
5677db96d56Sopenharmony_ci    }
5687db96d56Sopenharmony_ci    if (fragment->len == 0)
5697db96d56Sopenharmony_ci        res = 0;
5707db96d56Sopenharmony_ci    else
5717db96d56Sopenharmony_ci        res = (unsigned int)sqrt(sum_squares / (double)(fragment->len/width));
5727db96d56Sopenharmony_ci    return PyLong_FromUnsignedLong(res);
5737db96d56Sopenharmony_ci}
5747db96d56Sopenharmony_ci
5757db96d56Sopenharmony_cistatic double _sum2(const int16_t *a, const int16_t *b, Py_ssize_t len)
5767db96d56Sopenharmony_ci{
5777db96d56Sopenharmony_ci    Py_ssize_t i;
5787db96d56Sopenharmony_ci    double sum = 0.0;
5797db96d56Sopenharmony_ci
5807db96d56Sopenharmony_ci    for( i=0; i<len; i++) {
5817db96d56Sopenharmony_ci        sum = sum + (double)a[i]*(double)b[i];
5827db96d56Sopenharmony_ci    }
5837db96d56Sopenharmony_ci    return sum;
5847db96d56Sopenharmony_ci}
5857db96d56Sopenharmony_ci
5867db96d56Sopenharmony_ci/*
5877db96d56Sopenharmony_ci** Findfit tries to locate a sample within another sample. Its main use
5887db96d56Sopenharmony_ci** is in echo-cancellation (to find the feedback of the output signal in
5897db96d56Sopenharmony_ci** the input signal).
5907db96d56Sopenharmony_ci** The method used is as follows:
5917db96d56Sopenharmony_ci**
5927db96d56Sopenharmony_ci** let R be the reference signal (length n) and A the input signal (length N)
5937db96d56Sopenharmony_ci** with N > n, and let all sums be over i from 0 to n-1.
5947db96d56Sopenharmony_ci**
5957db96d56Sopenharmony_ci** Now, for each j in {0..N-n} we compute a factor fj so that -fj*R matches A
5967db96d56Sopenharmony_ci** as good as possible, i.e. sum( (A[j+i]+fj*R[i])^2 ) is minimal. This
5977db96d56Sopenharmony_ci** equation gives fj = sum( A[j+i]R[i] ) / sum(R[i]^2).
5987db96d56Sopenharmony_ci**
5997db96d56Sopenharmony_ci** Next, we compute the relative distance between the original signal and
6007db96d56Sopenharmony_ci** the modified signal and minimize that over j:
6017db96d56Sopenharmony_ci** vj = sum( (A[j+i]-fj*R[i])^2 ) / sum( A[j+i]^2 )  =>
6027db96d56Sopenharmony_ci** vj = ( sum(A[j+i]^2)*sum(R[i]^2) - sum(A[j+i]R[i])^2 ) / sum( A[j+i]^2 )
6037db96d56Sopenharmony_ci**
6047db96d56Sopenharmony_ci** In the code variables correspond as follows:
6057db96d56Sopenharmony_ci** cp1          A
6067db96d56Sopenharmony_ci** cp2          R
6077db96d56Sopenharmony_ci** len1         N
6087db96d56Sopenharmony_ci** len2         n
6097db96d56Sopenharmony_ci** aj_m1        A[j-1]
6107db96d56Sopenharmony_ci** aj_lm1       A[j+n-1]
6117db96d56Sopenharmony_ci** sum_ri_2     sum(R[i]^2)
6127db96d56Sopenharmony_ci** sum_aij_2    sum(A[i+j]^2)
6137db96d56Sopenharmony_ci** sum_aij_ri   sum(A[i+j]R[i])
6147db96d56Sopenharmony_ci**
6157db96d56Sopenharmony_ci** sum_ri is calculated once, sum_aij_2 is updated each step and sum_aij_ri
6167db96d56Sopenharmony_ci** is completely recalculated each step.
6177db96d56Sopenharmony_ci*/
6187db96d56Sopenharmony_ci/*[clinic input]
6197db96d56Sopenharmony_ciaudioop.findfit
6207db96d56Sopenharmony_ci
6217db96d56Sopenharmony_ci    fragment: Py_buffer
6227db96d56Sopenharmony_ci    reference: Py_buffer
6237db96d56Sopenharmony_ci    /
6247db96d56Sopenharmony_ci
6257db96d56Sopenharmony_ciTry to match reference as well as possible to a portion of fragment.
6267db96d56Sopenharmony_ci[clinic start generated code]*/
6277db96d56Sopenharmony_ci
6287db96d56Sopenharmony_cistatic PyObject *
6297db96d56Sopenharmony_ciaudioop_findfit_impl(PyObject *module, Py_buffer *fragment,
6307db96d56Sopenharmony_ci                     Py_buffer *reference)
6317db96d56Sopenharmony_ci/*[clinic end generated code: output=5752306d83cbbada input=62c305605e183c9a]*/
6327db96d56Sopenharmony_ci{
6337db96d56Sopenharmony_ci    const int16_t *cp1, *cp2;
6347db96d56Sopenharmony_ci    Py_ssize_t len1, len2;
6357db96d56Sopenharmony_ci    Py_ssize_t j, best_j;
6367db96d56Sopenharmony_ci    double aj_m1, aj_lm1;
6377db96d56Sopenharmony_ci    double sum_ri_2, sum_aij_2, sum_aij_ri, result, best_result, factor;
6387db96d56Sopenharmony_ci
6397db96d56Sopenharmony_ci    if (fragment->len & 1 || reference->len & 1) {
6407db96d56Sopenharmony_ci        PyErr_SetString(get_audioop_state(module)->AudioopError,
6417db96d56Sopenharmony_ci                        "Strings should be even-sized");
6427db96d56Sopenharmony_ci        return NULL;
6437db96d56Sopenharmony_ci    }
6447db96d56Sopenharmony_ci    cp1 = (const int16_t *)fragment->buf;
6457db96d56Sopenharmony_ci    len1 = fragment->len >> 1;
6467db96d56Sopenharmony_ci    cp2 = (const int16_t *)reference->buf;
6477db96d56Sopenharmony_ci    len2 = reference->len >> 1;
6487db96d56Sopenharmony_ci
6497db96d56Sopenharmony_ci    if (len1 < len2) {
6507db96d56Sopenharmony_ci        PyErr_SetString(get_audioop_state(module)->AudioopError,
6517db96d56Sopenharmony_ci                        "First sample should be longer");
6527db96d56Sopenharmony_ci        return NULL;
6537db96d56Sopenharmony_ci    }
6547db96d56Sopenharmony_ci    sum_ri_2 = _sum2(cp2, cp2, len2);
6557db96d56Sopenharmony_ci    sum_aij_2 = _sum2(cp1, cp1, len2);
6567db96d56Sopenharmony_ci    sum_aij_ri = _sum2(cp1, cp2, len2);
6577db96d56Sopenharmony_ci
6587db96d56Sopenharmony_ci    result = (sum_ri_2*sum_aij_2 - sum_aij_ri*sum_aij_ri) / sum_aij_2;
6597db96d56Sopenharmony_ci
6607db96d56Sopenharmony_ci    best_result = result;
6617db96d56Sopenharmony_ci    best_j = 0;
6627db96d56Sopenharmony_ci
6637db96d56Sopenharmony_ci    for ( j=1; j<=len1-len2; j++) {
6647db96d56Sopenharmony_ci        aj_m1 = (double)cp1[j-1];
6657db96d56Sopenharmony_ci        aj_lm1 = (double)cp1[j+len2-1];
6667db96d56Sopenharmony_ci
6677db96d56Sopenharmony_ci        sum_aij_2 = sum_aij_2 + aj_lm1*aj_lm1 - aj_m1*aj_m1;
6687db96d56Sopenharmony_ci        sum_aij_ri = _sum2(cp1+j, cp2, len2);
6697db96d56Sopenharmony_ci
6707db96d56Sopenharmony_ci        result = (sum_ri_2*sum_aij_2 - sum_aij_ri*sum_aij_ri)
6717db96d56Sopenharmony_ci            / sum_aij_2;
6727db96d56Sopenharmony_ci
6737db96d56Sopenharmony_ci        if ( result < best_result ) {
6747db96d56Sopenharmony_ci            best_result = result;
6757db96d56Sopenharmony_ci            best_j = j;
6767db96d56Sopenharmony_ci        }
6777db96d56Sopenharmony_ci
6787db96d56Sopenharmony_ci    }
6797db96d56Sopenharmony_ci
6807db96d56Sopenharmony_ci    factor = _sum2(cp1+best_j, cp2, len2) / sum_ri_2;
6817db96d56Sopenharmony_ci
6827db96d56Sopenharmony_ci    return Py_BuildValue("(nf)", best_j, factor);
6837db96d56Sopenharmony_ci}
6847db96d56Sopenharmony_ci
6857db96d56Sopenharmony_ci/*
6867db96d56Sopenharmony_ci** findfactor finds a factor f so that the energy in A-fB is minimal.
6877db96d56Sopenharmony_ci** See the comment for findfit for details.
6887db96d56Sopenharmony_ci*/
6897db96d56Sopenharmony_ci/*[clinic input]
6907db96d56Sopenharmony_ciaudioop.findfactor
6917db96d56Sopenharmony_ci
6927db96d56Sopenharmony_ci    fragment: Py_buffer
6937db96d56Sopenharmony_ci    reference: Py_buffer
6947db96d56Sopenharmony_ci    /
6957db96d56Sopenharmony_ci
6967db96d56Sopenharmony_ciReturn a factor F such that rms(add(fragment, mul(reference, -F))) is minimal.
6977db96d56Sopenharmony_ci[clinic start generated code]*/
6987db96d56Sopenharmony_ci
6997db96d56Sopenharmony_cistatic PyObject *
7007db96d56Sopenharmony_ciaudioop_findfactor_impl(PyObject *module, Py_buffer *fragment,
7017db96d56Sopenharmony_ci                        Py_buffer *reference)
7027db96d56Sopenharmony_ci/*[clinic end generated code: output=14ea95652c1afcf8 input=816680301d012b21]*/
7037db96d56Sopenharmony_ci{
7047db96d56Sopenharmony_ci    const int16_t *cp1, *cp2;
7057db96d56Sopenharmony_ci    Py_ssize_t len;
7067db96d56Sopenharmony_ci    double sum_ri_2, sum_aij_ri, result;
7077db96d56Sopenharmony_ci
7087db96d56Sopenharmony_ci    if (fragment->len & 1 || reference->len & 1) {
7097db96d56Sopenharmony_ci        PyErr_SetString(get_audioop_state(module)->AudioopError,
7107db96d56Sopenharmony_ci                        "Strings should be even-sized");
7117db96d56Sopenharmony_ci        return NULL;
7127db96d56Sopenharmony_ci    }
7137db96d56Sopenharmony_ci    if (fragment->len != reference->len) {
7147db96d56Sopenharmony_ci        PyErr_SetString(get_audioop_state(module)->AudioopError,
7157db96d56Sopenharmony_ci                        "Samples should be same size");
7167db96d56Sopenharmony_ci        return NULL;
7177db96d56Sopenharmony_ci    }
7187db96d56Sopenharmony_ci    cp1 = (const int16_t *)fragment->buf;
7197db96d56Sopenharmony_ci    cp2 = (const int16_t *)reference->buf;
7207db96d56Sopenharmony_ci    len = fragment->len >> 1;
7217db96d56Sopenharmony_ci    sum_ri_2 = _sum2(cp2, cp2, len);
7227db96d56Sopenharmony_ci    sum_aij_ri = _sum2(cp1, cp2, len);
7237db96d56Sopenharmony_ci
7247db96d56Sopenharmony_ci    result = sum_aij_ri / sum_ri_2;
7257db96d56Sopenharmony_ci
7267db96d56Sopenharmony_ci    return PyFloat_FromDouble(result);
7277db96d56Sopenharmony_ci}
7287db96d56Sopenharmony_ci
7297db96d56Sopenharmony_ci/*
7307db96d56Sopenharmony_ci** findmax returns the index of the n-sized segment of the input sample
7317db96d56Sopenharmony_ci** that contains the most energy.
7327db96d56Sopenharmony_ci*/
7337db96d56Sopenharmony_ci/*[clinic input]
7347db96d56Sopenharmony_ciaudioop.findmax
7357db96d56Sopenharmony_ci
7367db96d56Sopenharmony_ci    fragment: Py_buffer
7377db96d56Sopenharmony_ci    length: Py_ssize_t
7387db96d56Sopenharmony_ci    /
7397db96d56Sopenharmony_ci
7407db96d56Sopenharmony_ciSearch fragment for a slice of specified number of samples with maximum energy.
7417db96d56Sopenharmony_ci[clinic start generated code]*/
7427db96d56Sopenharmony_ci
7437db96d56Sopenharmony_cistatic PyObject *
7447db96d56Sopenharmony_ciaudioop_findmax_impl(PyObject *module, Py_buffer *fragment,
7457db96d56Sopenharmony_ci                     Py_ssize_t length)
7467db96d56Sopenharmony_ci/*[clinic end generated code: output=f008128233523040 input=2f304801ed42383c]*/
7477db96d56Sopenharmony_ci{
7487db96d56Sopenharmony_ci    const int16_t *cp1;
7497db96d56Sopenharmony_ci    Py_ssize_t len1;
7507db96d56Sopenharmony_ci    Py_ssize_t j, best_j;
7517db96d56Sopenharmony_ci    double aj_m1, aj_lm1;
7527db96d56Sopenharmony_ci    double result, best_result;
7537db96d56Sopenharmony_ci
7547db96d56Sopenharmony_ci    if (fragment->len & 1) {
7557db96d56Sopenharmony_ci        PyErr_SetString(get_audioop_state(module)->AudioopError,
7567db96d56Sopenharmony_ci                        "Strings should be even-sized");
7577db96d56Sopenharmony_ci        return NULL;
7587db96d56Sopenharmony_ci    }
7597db96d56Sopenharmony_ci    cp1 = (const int16_t *)fragment->buf;
7607db96d56Sopenharmony_ci    len1 = fragment->len >> 1;
7617db96d56Sopenharmony_ci
7627db96d56Sopenharmony_ci    if (length < 0 || len1 < length) {
7637db96d56Sopenharmony_ci        PyErr_SetString(get_audioop_state(module)->AudioopError,
7647db96d56Sopenharmony_ci                        "Input sample should be longer");
7657db96d56Sopenharmony_ci        return NULL;
7667db96d56Sopenharmony_ci    }
7677db96d56Sopenharmony_ci
7687db96d56Sopenharmony_ci    result = _sum2(cp1, cp1, length);
7697db96d56Sopenharmony_ci
7707db96d56Sopenharmony_ci    best_result = result;
7717db96d56Sopenharmony_ci    best_j = 0;
7727db96d56Sopenharmony_ci
7737db96d56Sopenharmony_ci    for ( j=1; j<=len1-length; j++) {
7747db96d56Sopenharmony_ci        aj_m1 = (double)cp1[j-1];
7757db96d56Sopenharmony_ci        aj_lm1 = (double)cp1[j+length-1];
7767db96d56Sopenharmony_ci
7777db96d56Sopenharmony_ci        result = result + aj_lm1*aj_lm1 - aj_m1*aj_m1;
7787db96d56Sopenharmony_ci
7797db96d56Sopenharmony_ci        if ( result > best_result ) {
7807db96d56Sopenharmony_ci            best_result = result;
7817db96d56Sopenharmony_ci            best_j = j;
7827db96d56Sopenharmony_ci        }
7837db96d56Sopenharmony_ci
7847db96d56Sopenharmony_ci    }
7857db96d56Sopenharmony_ci
7867db96d56Sopenharmony_ci    return PyLong_FromSsize_t(best_j);
7877db96d56Sopenharmony_ci}
7887db96d56Sopenharmony_ci
7897db96d56Sopenharmony_ci/*[clinic input]
7907db96d56Sopenharmony_ciaudioop.avgpp
7917db96d56Sopenharmony_ci
7927db96d56Sopenharmony_ci    fragment: Py_buffer
7937db96d56Sopenharmony_ci    width: int
7947db96d56Sopenharmony_ci    /
7957db96d56Sopenharmony_ci
7967db96d56Sopenharmony_ciReturn the average peak-peak value over all samples in the fragment.
7977db96d56Sopenharmony_ci[clinic start generated code]*/
7987db96d56Sopenharmony_ci
7997db96d56Sopenharmony_cistatic PyObject *
8007db96d56Sopenharmony_ciaudioop_avgpp_impl(PyObject *module, Py_buffer *fragment, int width)
8017db96d56Sopenharmony_ci/*[clinic end generated code: output=269596b0d5ae0b2b input=0b3cceeae420a7d9]*/
8027db96d56Sopenharmony_ci{
8037db96d56Sopenharmony_ci    Py_ssize_t i;
8047db96d56Sopenharmony_ci    int prevval, prevextremevalid = 0, prevextreme = 0;
8057db96d56Sopenharmony_ci    double sum = 0.0;
8067db96d56Sopenharmony_ci    unsigned int avg;
8077db96d56Sopenharmony_ci    int diff, prevdiff, nextreme = 0;
8087db96d56Sopenharmony_ci
8097db96d56Sopenharmony_ci    if (!audioop_check_parameters(module, fragment->len, width))
8107db96d56Sopenharmony_ci        return NULL;
8117db96d56Sopenharmony_ci    if (fragment->len <= width)
8127db96d56Sopenharmony_ci        return PyLong_FromLong(0);
8137db96d56Sopenharmony_ci    prevval = GETRAWSAMPLE(width, fragment->buf, 0);
8147db96d56Sopenharmony_ci    prevdiff = 17; /* Anything != 0, 1 */
8157db96d56Sopenharmony_ci    for (i = width; i < fragment->len; i += width) {
8167db96d56Sopenharmony_ci        int val = GETRAWSAMPLE(width, fragment->buf, i);
8177db96d56Sopenharmony_ci        if (val != prevval) {
8187db96d56Sopenharmony_ci            diff = val < prevval;
8197db96d56Sopenharmony_ci            if (prevdiff == !diff) {
8207db96d56Sopenharmony_ci                /* Derivative changed sign. Compute difference to last
8217db96d56Sopenharmony_ci                ** extreme value and remember.
8227db96d56Sopenharmony_ci                */
8237db96d56Sopenharmony_ci                if (prevextremevalid) {
8247db96d56Sopenharmony_ci                    if (prevval < prevextreme)
8257db96d56Sopenharmony_ci                        sum += (double)((unsigned int)prevextreme -
8267db96d56Sopenharmony_ci                                        (unsigned int)prevval);
8277db96d56Sopenharmony_ci                    else
8287db96d56Sopenharmony_ci                        sum += (double)((unsigned int)prevval -
8297db96d56Sopenharmony_ci                                        (unsigned int)prevextreme);
8307db96d56Sopenharmony_ci                    nextreme++;
8317db96d56Sopenharmony_ci                }
8327db96d56Sopenharmony_ci                prevextremevalid = 1;
8337db96d56Sopenharmony_ci                prevextreme = prevval;
8347db96d56Sopenharmony_ci            }
8357db96d56Sopenharmony_ci            prevval = val;
8367db96d56Sopenharmony_ci            prevdiff = diff;
8377db96d56Sopenharmony_ci        }
8387db96d56Sopenharmony_ci    }
8397db96d56Sopenharmony_ci    if ( nextreme == 0 )
8407db96d56Sopenharmony_ci        avg = 0;
8417db96d56Sopenharmony_ci    else
8427db96d56Sopenharmony_ci        avg = (unsigned int)(sum / (double)nextreme);
8437db96d56Sopenharmony_ci    return PyLong_FromUnsignedLong(avg);
8447db96d56Sopenharmony_ci}
8457db96d56Sopenharmony_ci
8467db96d56Sopenharmony_ci/*[clinic input]
8477db96d56Sopenharmony_ciaudioop.maxpp
8487db96d56Sopenharmony_ci
8497db96d56Sopenharmony_ci    fragment: Py_buffer
8507db96d56Sopenharmony_ci    width: int
8517db96d56Sopenharmony_ci    /
8527db96d56Sopenharmony_ci
8537db96d56Sopenharmony_ciReturn the maximum peak-peak value in the sound fragment.
8547db96d56Sopenharmony_ci[clinic start generated code]*/
8557db96d56Sopenharmony_ci
8567db96d56Sopenharmony_cistatic PyObject *
8577db96d56Sopenharmony_ciaudioop_maxpp_impl(PyObject *module, Py_buffer *fragment, int width)
8587db96d56Sopenharmony_ci/*[clinic end generated code: output=5b918ed5dbbdb978 input=671a13e1518f80a1]*/
8597db96d56Sopenharmony_ci{
8607db96d56Sopenharmony_ci    Py_ssize_t i;
8617db96d56Sopenharmony_ci    int prevval, prevextremevalid = 0, prevextreme = 0;
8627db96d56Sopenharmony_ci    unsigned int max = 0, extremediff;
8637db96d56Sopenharmony_ci    int diff, prevdiff;
8647db96d56Sopenharmony_ci
8657db96d56Sopenharmony_ci    if (!audioop_check_parameters(module, fragment->len, width))
8667db96d56Sopenharmony_ci        return NULL;
8677db96d56Sopenharmony_ci    if (fragment->len <= width)
8687db96d56Sopenharmony_ci        return PyLong_FromLong(0);
8697db96d56Sopenharmony_ci    prevval = GETRAWSAMPLE(width, fragment->buf, 0);
8707db96d56Sopenharmony_ci    prevdiff = 17; /* Anything != 0, 1 */
8717db96d56Sopenharmony_ci    for (i = width; i < fragment->len; i += width) {
8727db96d56Sopenharmony_ci        int val = GETRAWSAMPLE(width, fragment->buf, i);
8737db96d56Sopenharmony_ci        if (val != prevval) {
8747db96d56Sopenharmony_ci            diff = val < prevval;
8757db96d56Sopenharmony_ci            if (prevdiff == !diff) {
8767db96d56Sopenharmony_ci                /* Derivative changed sign. Compute difference to
8777db96d56Sopenharmony_ci                ** last extreme value and remember.
8787db96d56Sopenharmony_ci                */
8797db96d56Sopenharmony_ci                if (prevextremevalid) {
8807db96d56Sopenharmony_ci                    if (prevval < prevextreme)
8817db96d56Sopenharmony_ci                        extremediff = (unsigned int)prevextreme -
8827db96d56Sopenharmony_ci                                      (unsigned int)prevval;
8837db96d56Sopenharmony_ci                    else
8847db96d56Sopenharmony_ci                        extremediff = (unsigned int)prevval -
8857db96d56Sopenharmony_ci                                      (unsigned int)prevextreme;
8867db96d56Sopenharmony_ci                    if ( extremediff > max )
8877db96d56Sopenharmony_ci                        max = extremediff;
8887db96d56Sopenharmony_ci                }
8897db96d56Sopenharmony_ci                prevextremevalid = 1;
8907db96d56Sopenharmony_ci                prevextreme = prevval;
8917db96d56Sopenharmony_ci            }
8927db96d56Sopenharmony_ci            prevval = val;
8937db96d56Sopenharmony_ci            prevdiff = diff;
8947db96d56Sopenharmony_ci        }
8957db96d56Sopenharmony_ci    }
8967db96d56Sopenharmony_ci    return PyLong_FromUnsignedLong(max);
8977db96d56Sopenharmony_ci}
8987db96d56Sopenharmony_ci
8997db96d56Sopenharmony_ci/*[clinic input]
9007db96d56Sopenharmony_ciaudioop.cross
9017db96d56Sopenharmony_ci
9027db96d56Sopenharmony_ci    fragment: Py_buffer
9037db96d56Sopenharmony_ci    width: int
9047db96d56Sopenharmony_ci    /
9057db96d56Sopenharmony_ci
9067db96d56Sopenharmony_ciReturn the number of zero crossings in the fragment passed as an argument.
9077db96d56Sopenharmony_ci[clinic start generated code]*/
9087db96d56Sopenharmony_ci
9097db96d56Sopenharmony_cistatic PyObject *
9107db96d56Sopenharmony_ciaudioop_cross_impl(PyObject *module, Py_buffer *fragment, int width)
9117db96d56Sopenharmony_ci/*[clinic end generated code: output=5938dcdd74a1f431 input=b1b3f15b83f6b41a]*/
9127db96d56Sopenharmony_ci{
9137db96d56Sopenharmony_ci    Py_ssize_t i;
9147db96d56Sopenharmony_ci    int prevval;
9157db96d56Sopenharmony_ci    Py_ssize_t ncross;
9167db96d56Sopenharmony_ci
9177db96d56Sopenharmony_ci    if (!audioop_check_parameters(module, fragment->len, width))
9187db96d56Sopenharmony_ci        return NULL;
9197db96d56Sopenharmony_ci    ncross = -1;
9207db96d56Sopenharmony_ci    prevval = 17; /* Anything <> 0,1 */
9217db96d56Sopenharmony_ci    for (i = 0; i < fragment->len; i += width) {
9227db96d56Sopenharmony_ci        int val = GETRAWSAMPLE(width, fragment->buf, i) < 0;
9237db96d56Sopenharmony_ci        if (val != prevval) ncross++;
9247db96d56Sopenharmony_ci        prevval = val;
9257db96d56Sopenharmony_ci    }
9267db96d56Sopenharmony_ci    return PyLong_FromSsize_t(ncross);
9277db96d56Sopenharmony_ci}
9287db96d56Sopenharmony_ci
9297db96d56Sopenharmony_ci/*[clinic input]
9307db96d56Sopenharmony_ciaudioop.mul
9317db96d56Sopenharmony_ci
9327db96d56Sopenharmony_ci    fragment: Py_buffer
9337db96d56Sopenharmony_ci    width: int
9347db96d56Sopenharmony_ci    factor: double
9357db96d56Sopenharmony_ci    /
9367db96d56Sopenharmony_ci
9377db96d56Sopenharmony_ciReturn a fragment that has all samples in the original fragment multiplied by the floating-point value factor.
9387db96d56Sopenharmony_ci[clinic start generated code]*/
9397db96d56Sopenharmony_ci
9407db96d56Sopenharmony_cistatic PyObject *
9417db96d56Sopenharmony_ciaudioop_mul_impl(PyObject *module, Py_buffer *fragment, int width,
9427db96d56Sopenharmony_ci                 double factor)
9437db96d56Sopenharmony_ci/*[clinic end generated code: output=6cd48fe796da0ea4 input=c726667baa157d3c]*/
9447db96d56Sopenharmony_ci{
9457db96d56Sopenharmony_ci    signed char *ncp;
9467db96d56Sopenharmony_ci    Py_ssize_t i;
9477db96d56Sopenharmony_ci    double maxval, minval;
9487db96d56Sopenharmony_ci    PyObject *rv;
9497db96d56Sopenharmony_ci
9507db96d56Sopenharmony_ci    if (!audioop_check_parameters(module, fragment->len, width))
9517db96d56Sopenharmony_ci        return NULL;
9527db96d56Sopenharmony_ci
9537db96d56Sopenharmony_ci    maxval = (double) maxvals[width];
9547db96d56Sopenharmony_ci    minval = (double) minvals[width];
9557db96d56Sopenharmony_ci
9567db96d56Sopenharmony_ci    rv = PyBytes_FromStringAndSize(NULL, fragment->len);
9577db96d56Sopenharmony_ci    if (rv == NULL)
9587db96d56Sopenharmony_ci        return NULL;
9597db96d56Sopenharmony_ci    ncp = (signed char *)PyBytes_AsString(rv);
9607db96d56Sopenharmony_ci
9617db96d56Sopenharmony_ci    for (i = 0; i < fragment->len; i += width) {
9627db96d56Sopenharmony_ci        double val = GETRAWSAMPLE(width, fragment->buf, i);
9637db96d56Sopenharmony_ci        int ival = fbound(val * factor, minval, maxval);
9647db96d56Sopenharmony_ci        SETRAWSAMPLE(width, ncp, i, ival);
9657db96d56Sopenharmony_ci    }
9667db96d56Sopenharmony_ci    return rv;
9677db96d56Sopenharmony_ci}
9687db96d56Sopenharmony_ci
9697db96d56Sopenharmony_ci/*[clinic input]
9707db96d56Sopenharmony_ciaudioop.tomono
9717db96d56Sopenharmony_ci
9727db96d56Sopenharmony_ci    fragment: Py_buffer
9737db96d56Sopenharmony_ci    width: int
9747db96d56Sopenharmony_ci    lfactor: double
9757db96d56Sopenharmony_ci    rfactor: double
9767db96d56Sopenharmony_ci    /
9777db96d56Sopenharmony_ci
9787db96d56Sopenharmony_ciConvert a stereo fragment to a mono fragment.
9797db96d56Sopenharmony_ci[clinic start generated code]*/
9807db96d56Sopenharmony_ci
9817db96d56Sopenharmony_cistatic PyObject *
9827db96d56Sopenharmony_ciaudioop_tomono_impl(PyObject *module, Py_buffer *fragment, int width,
9837db96d56Sopenharmony_ci                    double lfactor, double rfactor)
9847db96d56Sopenharmony_ci/*[clinic end generated code: output=235c8277216d4e4e input=c4ec949b3f4dddfa]*/
9857db96d56Sopenharmony_ci{
9867db96d56Sopenharmony_ci    signed char *cp, *ncp;
9877db96d56Sopenharmony_ci    Py_ssize_t len, i;
9887db96d56Sopenharmony_ci    double maxval, minval;
9897db96d56Sopenharmony_ci    PyObject *rv;
9907db96d56Sopenharmony_ci
9917db96d56Sopenharmony_ci    cp = fragment->buf;
9927db96d56Sopenharmony_ci    len = fragment->len;
9937db96d56Sopenharmony_ci    if (!audioop_check_parameters(module, len, width))
9947db96d56Sopenharmony_ci        return NULL;
9957db96d56Sopenharmony_ci    if (((len / width) & 1) != 0) {
9967db96d56Sopenharmony_ci        PyErr_SetString(get_audioop_state(module)->AudioopError,
9977db96d56Sopenharmony_ci                        "not a whole number of frames");
9987db96d56Sopenharmony_ci        return NULL;
9997db96d56Sopenharmony_ci    }
10007db96d56Sopenharmony_ci
10017db96d56Sopenharmony_ci    maxval = (double) maxvals[width];
10027db96d56Sopenharmony_ci    minval = (double) minvals[width];
10037db96d56Sopenharmony_ci
10047db96d56Sopenharmony_ci    rv = PyBytes_FromStringAndSize(NULL, len/2);
10057db96d56Sopenharmony_ci    if (rv == NULL)
10067db96d56Sopenharmony_ci        return NULL;
10077db96d56Sopenharmony_ci    ncp = (signed char *)PyBytes_AsString(rv);
10087db96d56Sopenharmony_ci
10097db96d56Sopenharmony_ci    for (i = 0; i < len; i += width*2) {
10107db96d56Sopenharmony_ci        double val1 = GETRAWSAMPLE(width, cp, i);
10117db96d56Sopenharmony_ci        double val2 = GETRAWSAMPLE(width, cp, i + width);
10127db96d56Sopenharmony_ci        double val = val1 * lfactor + val2 * rfactor;
10137db96d56Sopenharmony_ci        int ival = fbound(val, minval, maxval);
10147db96d56Sopenharmony_ci        SETRAWSAMPLE(width, ncp, i/2, ival);
10157db96d56Sopenharmony_ci    }
10167db96d56Sopenharmony_ci    return rv;
10177db96d56Sopenharmony_ci}
10187db96d56Sopenharmony_ci
10197db96d56Sopenharmony_ci/*[clinic input]
10207db96d56Sopenharmony_ciaudioop.tostereo
10217db96d56Sopenharmony_ci
10227db96d56Sopenharmony_ci    fragment: Py_buffer
10237db96d56Sopenharmony_ci    width: int
10247db96d56Sopenharmony_ci    lfactor: double
10257db96d56Sopenharmony_ci    rfactor: double
10267db96d56Sopenharmony_ci    /
10277db96d56Sopenharmony_ci
10287db96d56Sopenharmony_ciGenerate a stereo fragment from a mono fragment.
10297db96d56Sopenharmony_ci[clinic start generated code]*/
10307db96d56Sopenharmony_ci
10317db96d56Sopenharmony_cistatic PyObject *
10327db96d56Sopenharmony_ciaudioop_tostereo_impl(PyObject *module, Py_buffer *fragment, int width,
10337db96d56Sopenharmony_ci                      double lfactor, double rfactor)
10347db96d56Sopenharmony_ci/*[clinic end generated code: output=046f13defa5f1595 input=27b6395ebfdff37a]*/
10357db96d56Sopenharmony_ci{
10367db96d56Sopenharmony_ci    signed char *ncp;
10377db96d56Sopenharmony_ci    Py_ssize_t i;
10387db96d56Sopenharmony_ci    double maxval, minval;
10397db96d56Sopenharmony_ci    PyObject *rv;
10407db96d56Sopenharmony_ci
10417db96d56Sopenharmony_ci    if (!audioop_check_parameters(module, fragment->len, width))
10427db96d56Sopenharmony_ci        return NULL;
10437db96d56Sopenharmony_ci
10447db96d56Sopenharmony_ci    maxval = (double) maxvals[width];
10457db96d56Sopenharmony_ci    minval = (double) minvals[width];
10467db96d56Sopenharmony_ci
10477db96d56Sopenharmony_ci    if (fragment->len > PY_SSIZE_T_MAX/2) {
10487db96d56Sopenharmony_ci        PyErr_SetString(PyExc_MemoryError,
10497db96d56Sopenharmony_ci                        "not enough memory for output buffer");
10507db96d56Sopenharmony_ci        return NULL;
10517db96d56Sopenharmony_ci    }
10527db96d56Sopenharmony_ci
10537db96d56Sopenharmony_ci    rv = PyBytes_FromStringAndSize(NULL, fragment->len*2);
10547db96d56Sopenharmony_ci    if (rv == NULL)
10557db96d56Sopenharmony_ci        return NULL;
10567db96d56Sopenharmony_ci    ncp = (signed char *)PyBytes_AsString(rv);
10577db96d56Sopenharmony_ci
10587db96d56Sopenharmony_ci    for (i = 0; i < fragment->len; i += width) {
10597db96d56Sopenharmony_ci        double val = GETRAWSAMPLE(width, fragment->buf, i);
10607db96d56Sopenharmony_ci        int val1 = fbound(val * lfactor, minval, maxval);
10617db96d56Sopenharmony_ci        int val2 = fbound(val * rfactor, minval, maxval);
10627db96d56Sopenharmony_ci        SETRAWSAMPLE(width, ncp, i*2, val1);
10637db96d56Sopenharmony_ci        SETRAWSAMPLE(width, ncp, i*2 + width, val2);
10647db96d56Sopenharmony_ci    }
10657db96d56Sopenharmony_ci    return rv;
10667db96d56Sopenharmony_ci}
10677db96d56Sopenharmony_ci
10687db96d56Sopenharmony_ci/*[clinic input]
10697db96d56Sopenharmony_ciaudioop.add
10707db96d56Sopenharmony_ci
10717db96d56Sopenharmony_ci    fragment1: Py_buffer
10727db96d56Sopenharmony_ci    fragment2: Py_buffer
10737db96d56Sopenharmony_ci    width: int
10747db96d56Sopenharmony_ci    /
10757db96d56Sopenharmony_ci
10767db96d56Sopenharmony_ciReturn a fragment which is the addition of the two samples passed as parameters.
10777db96d56Sopenharmony_ci[clinic start generated code]*/
10787db96d56Sopenharmony_ci
10797db96d56Sopenharmony_cistatic PyObject *
10807db96d56Sopenharmony_ciaudioop_add_impl(PyObject *module, Py_buffer *fragment1,
10817db96d56Sopenharmony_ci                 Py_buffer *fragment2, int width)
10827db96d56Sopenharmony_ci/*[clinic end generated code: output=60140af4d1aab6f2 input=4a8d4bae4c1605c7]*/
10837db96d56Sopenharmony_ci{
10847db96d56Sopenharmony_ci    signed char *ncp;
10857db96d56Sopenharmony_ci    Py_ssize_t i;
10867db96d56Sopenharmony_ci    int minval, maxval, newval;
10877db96d56Sopenharmony_ci    PyObject *rv;
10887db96d56Sopenharmony_ci
10897db96d56Sopenharmony_ci    if (!audioop_check_parameters(module, fragment1->len, width))
10907db96d56Sopenharmony_ci        return NULL;
10917db96d56Sopenharmony_ci    if (fragment1->len != fragment2->len) {
10927db96d56Sopenharmony_ci        PyErr_SetString(get_audioop_state(module)->AudioopError,
10937db96d56Sopenharmony_ci                        "Lengths should be the same");
10947db96d56Sopenharmony_ci        return NULL;
10957db96d56Sopenharmony_ci    }
10967db96d56Sopenharmony_ci
10977db96d56Sopenharmony_ci    maxval = maxvals[width];
10987db96d56Sopenharmony_ci    minval = minvals[width];
10997db96d56Sopenharmony_ci
11007db96d56Sopenharmony_ci    rv = PyBytes_FromStringAndSize(NULL, fragment1->len);
11017db96d56Sopenharmony_ci    if (rv == NULL)
11027db96d56Sopenharmony_ci        return NULL;
11037db96d56Sopenharmony_ci    ncp = (signed char *)PyBytes_AsString(rv);
11047db96d56Sopenharmony_ci
11057db96d56Sopenharmony_ci    for (i = 0; i < fragment1->len; i += width) {
11067db96d56Sopenharmony_ci        int val1 = GETRAWSAMPLE(width, fragment1->buf, i);
11077db96d56Sopenharmony_ci        int val2 = GETRAWSAMPLE(width, fragment2->buf, i);
11087db96d56Sopenharmony_ci
11097db96d56Sopenharmony_ci        if (width < 4) {
11107db96d56Sopenharmony_ci            newval = val1 + val2;
11117db96d56Sopenharmony_ci            /* truncate in case of overflow */
11127db96d56Sopenharmony_ci            if (newval > maxval)
11137db96d56Sopenharmony_ci                newval = maxval;
11147db96d56Sopenharmony_ci            else if (newval < minval)
11157db96d56Sopenharmony_ci                newval = minval;
11167db96d56Sopenharmony_ci        }
11177db96d56Sopenharmony_ci        else {
11187db96d56Sopenharmony_ci            double fval = (double)val1 + (double)val2;
11197db96d56Sopenharmony_ci            /* truncate in case of overflow */
11207db96d56Sopenharmony_ci            newval = fbound(fval, minval, maxval);
11217db96d56Sopenharmony_ci        }
11227db96d56Sopenharmony_ci
11237db96d56Sopenharmony_ci        SETRAWSAMPLE(width, ncp, i, newval);
11247db96d56Sopenharmony_ci    }
11257db96d56Sopenharmony_ci    return rv;
11267db96d56Sopenharmony_ci}
11277db96d56Sopenharmony_ci
11287db96d56Sopenharmony_ci/*[clinic input]
11297db96d56Sopenharmony_ciaudioop.bias
11307db96d56Sopenharmony_ci
11317db96d56Sopenharmony_ci    fragment: Py_buffer
11327db96d56Sopenharmony_ci    width: int
11337db96d56Sopenharmony_ci    bias: int
11347db96d56Sopenharmony_ci    /
11357db96d56Sopenharmony_ci
11367db96d56Sopenharmony_ciReturn a fragment that is the original fragment with a bias added to each sample.
11377db96d56Sopenharmony_ci[clinic start generated code]*/
11387db96d56Sopenharmony_ci
11397db96d56Sopenharmony_cistatic PyObject *
11407db96d56Sopenharmony_ciaudioop_bias_impl(PyObject *module, Py_buffer *fragment, int width, int bias)
11417db96d56Sopenharmony_ci/*[clinic end generated code: output=6e0aa8f68f045093 input=2b5cce5c3bb4838c]*/
11427db96d56Sopenharmony_ci{
11437db96d56Sopenharmony_ci    signed char *ncp;
11447db96d56Sopenharmony_ci    Py_ssize_t i;
11457db96d56Sopenharmony_ci    unsigned int val = 0, mask;
11467db96d56Sopenharmony_ci    PyObject *rv;
11477db96d56Sopenharmony_ci
11487db96d56Sopenharmony_ci    if (!audioop_check_parameters(module, fragment->len, width))
11497db96d56Sopenharmony_ci        return NULL;
11507db96d56Sopenharmony_ci
11517db96d56Sopenharmony_ci    rv = PyBytes_FromStringAndSize(NULL, fragment->len);
11527db96d56Sopenharmony_ci    if (rv == NULL)
11537db96d56Sopenharmony_ci        return NULL;
11547db96d56Sopenharmony_ci    ncp = (signed char *)PyBytes_AsString(rv);
11557db96d56Sopenharmony_ci
11567db96d56Sopenharmony_ci    mask = masks[width];
11577db96d56Sopenharmony_ci
11587db96d56Sopenharmony_ci    for (i = 0; i < fragment->len; i += width) {
11597db96d56Sopenharmony_ci        if (width == 1)
11607db96d56Sopenharmony_ci            val = GETINTX(unsigned char, fragment->buf, i);
11617db96d56Sopenharmony_ci        else if (width == 2)
11627db96d56Sopenharmony_ci            val = GETINTX(uint16_t, fragment->buf, i);
11637db96d56Sopenharmony_ci        else if (width == 3)
11647db96d56Sopenharmony_ci            val = ((unsigned int)GETINT24(fragment->buf, i)) & 0xffffffu;
11657db96d56Sopenharmony_ci        else {
11667db96d56Sopenharmony_ci            assert(width == 4);
11677db96d56Sopenharmony_ci            val = GETINTX(uint32_t, fragment->buf, i);
11687db96d56Sopenharmony_ci        }
11697db96d56Sopenharmony_ci
11707db96d56Sopenharmony_ci        val += (unsigned int)bias;
11717db96d56Sopenharmony_ci        /* wrap around in case of overflow */
11727db96d56Sopenharmony_ci        val &= mask;
11737db96d56Sopenharmony_ci
11747db96d56Sopenharmony_ci        if (width == 1)
11757db96d56Sopenharmony_ci            SETINTX(unsigned char, ncp, i, val);
11767db96d56Sopenharmony_ci        else if (width == 2)
11777db96d56Sopenharmony_ci            SETINTX(uint16_t, ncp, i, val);
11787db96d56Sopenharmony_ci        else if (width == 3)
11797db96d56Sopenharmony_ci            SETINT24(ncp, i, (int)val);
11807db96d56Sopenharmony_ci        else {
11817db96d56Sopenharmony_ci            assert(width == 4);
11827db96d56Sopenharmony_ci            SETINTX(uint32_t, ncp, i, val);
11837db96d56Sopenharmony_ci        }
11847db96d56Sopenharmony_ci    }
11857db96d56Sopenharmony_ci    return rv;
11867db96d56Sopenharmony_ci}
11877db96d56Sopenharmony_ci
11887db96d56Sopenharmony_ci/*[clinic input]
11897db96d56Sopenharmony_ciaudioop.reverse
11907db96d56Sopenharmony_ci
11917db96d56Sopenharmony_ci    fragment: Py_buffer
11927db96d56Sopenharmony_ci    width: int
11937db96d56Sopenharmony_ci    /
11947db96d56Sopenharmony_ci
11957db96d56Sopenharmony_ciReverse the samples in a fragment and returns the modified fragment.
11967db96d56Sopenharmony_ci[clinic start generated code]*/
11977db96d56Sopenharmony_ci
11987db96d56Sopenharmony_cistatic PyObject *
11997db96d56Sopenharmony_ciaudioop_reverse_impl(PyObject *module, Py_buffer *fragment, int width)
12007db96d56Sopenharmony_ci/*[clinic end generated code: output=b44135698418da14 input=668f890cf9f9d225]*/
12017db96d56Sopenharmony_ci{
12027db96d56Sopenharmony_ci    unsigned char *ncp;
12037db96d56Sopenharmony_ci    Py_ssize_t i;
12047db96d56Sopenharmony_ci    PyObject *rv;
12057db96d56Sopenharmony_ci
12067db96d56Sopenharmony_ci    if (!audioop_check_parameters(module, fragment->len, width))
12077db96d56Sopenharmony_ci        return NULL;
12087db96d56Sopenharmony_ci
12097db96d56Sopenharmony_ci    rv = PyBytes_FromStringAndSize(NULL, fragment->len);
12107db96d56Sopenharmony_ci    if (rv == NULL)
12117db96d56Sopenharmony_ci        return NULL;
12127db96d56Sopenharmony_ci    ncp = (unsigned char *)PyBytes_AsString(rv);
12137db96d56Sopenharmony_ci
12147db96d56Sopenharmony_ci    for (i = 0; i < fragment->len; i += width) {
12157db96d56Sopenharmony_ci        int val = GETRAWSAMPLE(width, fragment->buf, i);
12167db96d56Sopenharmony_ci        SETRAWSAMPLE(width, ncp, fragment->len - i - width, val);
12177db96d56Sopenharmony_ci    }
12187db96d56Sopenharmony_ci    return rv;
12197db96d56Sopenharmony_ci}
12207db96d56Sopenharmony_ci
12217db96d56Sopenharmony_ci/*[clinic input]
12227db96d56Sopenharmony_ciaudioop.byteswap
12237db96d56Sopenharmony_ci
12247db96d56Sopenharmony_ci    fragment: Py_buffer
12257db96d56Sopenharmony_ci    width: int
12267db96d56Sopenharmony_ci    /
12277db96d56Sopenharmony_ci
12287db96d56Sopenharmony_ciConvert big-endian samples to little-endian and vice versa.
12297db96d56Sopenharmony_ci[clinic start generated code]*/
12307db96d56Sopenharmony_ci
12317db96d56Sopenharmony_cistatic PyObject *
12327db96d56Sopenharmony_ciaudioop_byteswap_impl(PyObject *module, Py_buffer *fragment, int width)
12337db96d56Sopenharmony_ci/*[clinic end generated code: output=50838a9e4b87cd4d input=fae7611ceffa5c82]*/
12347db96d56Sopenharmony_ci{
12357db96d56Sopenharmony_ci    unsigned char *ncp;
12367db96d56Sopenharmony_ci    Py_ssize_t i;
12377db96d56Sopenharmony_ci    PyObject *rv;
12387db96d56Sopenharmony_ci
12397db96d56Sopenharmony_ci    if (!audioop_check_parameters(module, fragment->len, width))
12407db96d56Sopenharmony_ci        return NULL;
12417db96d56Sopenharmony_ci
12427db96d56Sopenharmony_ci    rv = PyBytes_FromStringAndSize(NULL, fragment->len);
12437db96d56Sopenharmony_ci    if (rv == NULL)
12447db96d56Sopenharmony_ci        return NULL;
12457db96d56Sopenharmony_ci    ncp = (unsigned char *)PyBytes_AsString(rv);
12467db96d56Sopenharmony_ci
12477db96d56Sopenharmony_ci    for (i = 0; i < fragment->len; i += width) {
12487db96d56Sopenharmony_ci        int j;
12497db96d56Sopenharmony_ci        for (j = 0; j < width; j++)
12507db96d56Sopenharmony_ci            ncp[i + width - 1 - j] = ((unsigned char *)fragment->buf)[i + j];
12517db96d56Sopenharmony_ci    }
12527db96d56Sopenharmony_ci    return rv;
12537db96d56Sopenharmony_ci}
12547db96d56Sopenharmony_ci
12557db96d56Sopenharmony_ci/*[clinic input]
12567db96d56Sopenharmony_ciaudioop.lin2lin
12577db96d56Sopenharmony_ci
12587db96d56Sopenharmony_ci    fragment: Py_buffer
12597db96d56Sopenharmony_ci    width: int
12607db96d56Sopenharmony_ci    newwidth: int
12617db96d56Sopenharmony_ci    /
12627db96d56Sopenharmony_ci
12637db96d56Sopenharmony_ciConvert samples between 1-, 2-, 3- and 4-byte formats.
12647db96d56Sopenharmony_ci[clinic start generated code]*/
12657db96d56Sopenharmony_ci
12667db96d56Sopenharmony_cistatic PyObject *
12677db96d56Sopenharmony_ciaudioop_lin2lin_impl(PyObject *module, Py_buffer *fragment, int width,
12687db96d56Sopenharmony_ci                     int newwidth)
12697db96d56Sopenharmony_ci/*[clinic end generated code: output=17b14109248f1d99 input=5ce08c8aa2f24d96]*/
12707db96d56Sopenharmony_ci{
12717db96d56Sopenharmony_ci    unsigned char *ncp;
12727db96d56Sopenharmony_ci    Py_ssize_t i, j;
12737db96d56Sopenharmony_ci    PyObject *rv;
12747db96d56Sopenharmony_ci
12757db96d56Sopenharmony_ci    if (!audioop_check_parameters(module, fragment->len, width))
12767db96d56Sopenharmony_ci        return NULL;
12777db96d56Sopenharmony_ci    if (!audioop_check_size(module, newwidth))
12787db96d56Sopenharmony_ci        return NULL;
12797db96d56Sopenharmony_ci
12807db96d56Sopenharmony_ci    if (fragment->len/width > PY_SSIZE_T_MAX/newwidth) {
12817db96d56Sopenharmony_ci        PyErr_SetString(PyExc_MemoryError,
12827db96d56Sopenharmony_ci                        "not enough memory for output buffer");
12837db96d56Sopenharmony_ci        return NULL;
12847db96d56Sopenharmony_ci    }
12857db96d56Sopenharmony_ci    rv = PyBytes_FromStringAndSize(NULL, (fragment->len/width)*newwidth);
12867db96d56Sopenharmony_ci    if (rv == NULL)
12877db96d56Sopenharmony_ci        return NULL;
12887db96d56Sopenharmony_ci    ncp = (unsigned char *)PyBytes_AsString(rv);
12897db96d56Sopenharmony_ci
12907db96d56Sopenharmony_ci    for (i = j = 0; i < fragment->len; i += width, j += newwidth) {
12917db96d56Sopenharmony_ci        int val = GETSAMPLE32(width, fragment->buf, i);
12927db96d56Sopenharmony_ci        SETSAMPLE32(newwidth, ncp, j, val);
12937db96d56Sopenharmony_ci    }
12947db96d56Sopenharmony_ci    return rv;
12957db96d56Sopenharmony_ci}
12967db96d56Sopenharmony_ci
12977db96d56Sopenharmony_cistatic int
12987db96d56Sopenharmony_cigcd(int a, int b)
12997db96d56Sopenharmony_ci{
13007db96d56Sopenharmony_ci    while (b > 0) {
13017db96d56Sopenharmony_ci        int tmp = a % b;
13027db96d56Sopenharmony_ci        a = b;
13037db96d56Sopenharmony_ci        b = tmp;
13047db96d56Sopenharmony_ci    }
13057db96d56Sopenharmony_ci    return a;
13067db96d56Sopenharmony_ci}
13077db96d56Sopenharmony_ci
13087db96d56Sopenharmony_ci/*[clinic input]
13097db96d56Sopenharmony_ciaudioop.ratecv
13107db96d56Sopenharmony_ci
13117db96d56Sopenharmony_ci    fragment: Py_buffer
13127db96d56Sopenharmony_ci    width: int
13137db96d56Sopenharmony_ci    nchannels: int
13147db96d56Sopenharmony_ci    inrate: int
13157db96d56Sopenharmony_ci    outrate: int
13167db96d56Sopenharmony_ci    state: object
13177db96d56Sopenharmony_ci    weightA: int = 1
13187db96d56Sopenharmony_ci    weightB: int = 0
13197db96d56Sopenharmony_ci    /
13207db96d56Sopenharmony_ci
13217db96d56Sopenharmony_ciConvert the frame rate of the input fragment.
13227db96d56Sopenharmony_ci[clinic start generated code]*/
13237db96d56Sopenharmony_ci
13247db96d56Sopenharmony_cistatic PyObject *
13257db96d56Sopenharmony_ciaudioop_ratecv_impl(PyObject *module, Py_buffer *fragment, int width,
13267db96d56Sopenharmony_ci                    int nchannels, int inrate, int outrate, PyObject *state,
13277db96d56Sopenharmony_ci                    int weightA, int weightB)
13287db96d56Sopenharmony_ci/*[clinic end generated code: output=624038e843243139 input=aff3acdc94476191]*/
13297db96d56Sopenharmony_ci{
13307db96d56Sopenharmony_ci    char *cp, *ncp;
13317db96d56Sopenharmony_ci    Py_ssize_t len;
13327db96d56Sopenharmony_ci    int chan, d, *prev_i, *cur_i, cur_o;
13337db96d56Sopenharmony_ci    PyObject *samps, *str, *rv = NULL, *channel;
13347db96d56Sopenharmony_ci    int bytes_per_frame;
13357db96d56Sopenharmony_ci
13367db96d56Sopenharmony_ci    if (!audioop_check_size(module, width))
13377db96d56Sopenharmony_ci        return NULL;
13387db96d56Sopenharmony_ci    if (nchannels < 1) {
13397db96d56Sopenharmony_ci        PyErr_SetString(get_audioop_state(module)->AudioopError,
13407db96d56Sopenharmony_ci                        "# of channels should be >= 1");
13417db96d56Sopenharmony_ci        return NULL;
13427db96d56Sopenharmony_ci    }
13437db96d56Sopenharmony_ci    if (width > INT_MAX / nchannels) {
13447db96d56Sopenharmony_ci        /* This overflow test is rigorously correct because
13457db96d56Sopenharmony_ci           both multiplicands are >= 1.  Use the argument names
13467db96d56Sopenharmony_ci           from the docs for the error msg. */
13477db96d56Sopenharmony_ci        PyErr_SetString(PyExc_OverflowError,
13487db96d56Sopenharmony_ci                        "width * nchannels too big for a C int");
13497db96d56Sopenharmony_ci        return NULL;
13507db96d56Sopenharmony_ci    }
13517db96d56Sopenharmony_ci    bytes_per_frame = width * nchannels;
13527db96d56Sopenharmony_ci    if (weightA < 1 || weightB < 0) {
13537db96d56Sopenharmony_ci        PyErr_SetString(get_audioop_state(module)->AudioopError,
13547db96d56Sopenharmony_ci            "weightA should be >= 1, weightB should be >= 0");
13557db96d56Sopenharmony_ci        return NULL;
13567db96d56Sopenharmony_ci    }
13577db96d56Sopenharmony_ci    assert(fragment->len >= 0);
13587db96d56Sopenharmony_ci    if (fragment->len % bytes_per_frame != 0) {
13597db96d56Sopenharmony_ci        PyErr_SetString(get_audioop_state(module)->AudioopError,
13607db96d56Sopenharmony_ci                        "not a whole number of frames");
13617db96d56Sopenharmony_ci        return NULL;
13627db96d56Sopenharmony_ci    }
13637db96d56Sopenharmony_ci    if (inrate <= 0 || outrate <= 0) {
13647db96d56Sopenharmony_ci        PyErr_SetString(get_audioop_state(module)->AudioopError,
13657db96d56Sopenharmony_ci                        "sampling rate not > 0");
13667db96d56Sopenharmony_ci        return NULL;
13677db96d56Sopenharmony_ci    }
13687db96d56Sopenharmony_ci    /* divide inrate and outrate by their greatest common divisor */
13697db96d56Sopenharmony_ci    d = gcd(inrate, outrate);
13707db96d56Sopenharmony_ci    inrate /= d;
13717db96d56Sopenharmony_ci    outrate /= d;
13727db96d56Sopenharmony_ci    /* divide weightA and weightB by their greatest common divisor */
13737db96d56Sopenharmony_ci    d = gcd(weightA, weightB);
13747db96d56Sopenharmony_ci    weightA /= d;
13757db96d56Sopenharmony_ci    weightB /= d;
13767db96d56Sopenharmony_ci
13777db96d56Sopenharmony_ci    if ((size_t)nchannels > SIZE_MAX/sizeof(int)) {
13787db96d56Sopenharmony_ci        PyErr_SetString(PyExc_MemoryError,
13797db96d56Sopenharmony_ci                        "not enough memory for output buffer");
13807db96d56Sopenharmony_ci        return NULL;
13817db96d56Sopenharmony_ci    }
13827db96d56Sopenharmony_ci    prev_i = (int *) PyMem_Malloc(nchannels * sizeof(int));
13837db96d56Sopenharmony_ci    cur_i = (int *) PyMem_Malloc(nchannels * sizeof(int));
13847db96d56Sopenharmony_ci    if (prev_i == NULL || cur_i == NULL) {
13857db96d56Sopenharmony_ci        (void) PyErr_NoMemory();
13867db96d56Sopenharmony_ci        goto exit;
13877db96d56Sopenharmony_ci    }
13887db96d56Sopenharmony_ci
13897db96d56Sopenharmony_ci    len = fragment->len / bytes_per_frame; /* # of frames */
13907db96d56Sopenharmony_ci
13917db96d56Sopenharmony_ci    if (state == Py_None) {
13927db96d56Sopenharmony_ci        d = -outrate;
13937db96d56Sopenharmony_ci        for (chan = 0; chan < nchannels; chan++)
13947db96d56Sopenharmony_ci            prev_i[chan] = cur_i[chan] = 0;
13957db96d56Sopenharmony_ci    }
13967db96d56Sopenharmony_ci    else {
13977db96d56Sopenharmony_ci        if (!PyTuple_Check(state)) {
13987db96d56Sopenharmony_ci            PyErr_SetString(PyExc_TypeError, "state must be a tuple or None");
13997db96d56Sopenharmony_ci            goto exit;
14007db96d56Sopenharmony_ci        }
14017db96d56Sopenharmony_ci        if (!PyArg_ParseTuple(state,
14027db96d56Sopenharmony_ci                        "iO!;ratecv(): illegal state argument",
14037db96d56Sopenharmony_ci                        &d, &PyTuple_Type, &samps))
14047db96d56Sopenharmony_ci            goto exit;
14057db96d56Sopenharmony_ci        if (PyTuple_Size(samps) != nchannels) {
14067db96d56Sopenharmony_ci            PyErr_SetString(get_audioop_state(module)->AudioopError,
14077db96d56Sopenharmony_ci                            "illegal state argument");
14087db96d56Sopenharmony_ci            goto exit;
14097db96d56Sopenharmony_ci        }
14107db96d56Sopenharmony_ci        for (chan = 0; chan < nchannels; chan++) {
14117db96d56Sopenharmony_ci            channel = PyTuple_GetItem(samps, chan);
14127db96d56Sopenharmony_ci            if (!PyTuple_Check(channel)) {
14137db96d56Sopenharmony_ci                PyErr_SetString(PyExc_TypeError,
14147db96d56Sopenharmony_ci                                "ratecv(): illegal state argument");
14157db96d56Sopenharmony_ci                goto exit;
14167db96d56Sopenharmony_ci            }
14177db96d56Sopenharmony_ci            if (!PyArg_ParseTuple(channel,
14187db96d56Sopenharmony_ci                                  "ii;ratecv(): illegal state argument",
14197db96d56Sopenharmony_ci                                  &prev_i[chan], &cur_i[chan]))
14207db96d56Sopenharmony_ci            {
14217db96d56Sopenharmony_ci                goto exit;
14227db96d56Sopenharmony_ci            }
14237db96d56Sopenharmony_ci        }
14247db96d56Sopenharmony_ci    }
14257db96d56Sopenharmony_ci
14267db96d56Sopenharmony_ci    /* str <- Space for the output buffer. */
14277db96d56Sopenharmony_ci    if (len == 0)
14287db96d56Sopenharmony_ci        str = PyBytes_FromStringAndSize(NULL, 0);
14297db96d56Sopenharmony_ci    else {
14307db96d56Sopenharmony_ci        /* There are len input frames, so we need (mathematically)
14317db96d56Sopenharmony_ci           ceiling(len*outrate/inrate) output frames, and each frame
14327db96d56Sopenharmony_ci           requires bytes_per_frame bytes.  Computing this
14337db96d56Sopenharmony_ci           without spurious overflow is the challenge; we can
14347db96d56Sopenharmony_ci           settle for a reasonable upper bound, though, in this
14357db96d56Sopenharmony_ci           case ceiling(len/inrate) * outrate. */
14367db96d56Sopenharmony_ci
14377db96d56Sopenharmony_ci        /* compute ceiling(len/inrate) without overflow */
14387db96d56Sopenharmony_ci        Py_ssize_t q = 1 + (len - 1) / inrate;
14397db96d56Sopenharmony_ci        if (outrate > PY_SSIZE_T_MAX / q / bytes_per_frame)
14407db96d56Sopenharmony_ci            str = NULL;
14417db96d56Sopenharmony_ci        else
14427db96d56Sopenharmony_ci            str = PyBytes_FromStringAndSize(NULL,
14437db96d56Sopenharmony_ci                                            q * outrate * bytes_per_frame);
14447db96d56Sopenharmony_ci    }
14457db96d56Sopenharmony_ci    if (str == NULL) {
14467db96d56Sopenharmony_ci        PyErr_SetString(PyExc_MemoryError,
14477db96d56Sopenharmony_ci            "not enough memory for output buffer");
14487db96d56Sopenharmony_ci        goto exit;
14497db96d56Sopenharmony_ci    }
14507db96d56Sopenharmony_ci    ncp = PyBytes_AsString(str);
14517db96d56Sopenharmony_ci    cp = fragment->buf;
14527db96d56Sopenharmony_ci
14537db96d56Sopenharmony_ci    for (;;) {
14547db96d56Sopenharmony_ci        while (d < 0) {
14557db96d56Sopenharmony_ci            if (len == 0) {
14567db96d56Sopenharmony_ci                samps = PyTuple_New(nchannels);
14577db96d56Sopenharmony_ci                if (samps == NULL)
14587db96d56Sopenharmony_ci                    goto exit;
14597db96d56Sopenharmony_ci                for (chan = 0; chan < nchannels; chan++)
14607db96d56Sopenharmony_ci                    PyTuple_SetItem(samps, chan,
14617db96d56Sopenharmony_ci                        Py_BuildValue("(ii)",
14627db96d56Sopenharmony_ci                                      prev_i[chan],
14637db96d56Sopenharmony_ci                                      cur_i[chan]));
14647db96d56Sopenharmony_ci                if (PyErr_Occurred())
14657db96d56Sopenharmony_ci                    goto exit;
14667db96d56Sopenharmony_ci                /* We have checked before that the length
14677db96d56Sopenharmony_ci                 * of the string fits into int. */
14687db96d56Sopenharmony_ci                len = (Py_ssize_t)(ncp - PyBytes_AsString(str));
14697db96d56Sopenharmony_ci                rv = PyBytes_FromStringAndSize
14707db96d56Sopenharmony_ci                    (PyBytes_AsString(str), len);
14717db96d56Sopenharmony_ci                Py_DECREF(str);
14727db96d56Sopenharmony_ci                str = rv;
14737db96d56Sopenharmony_ci                if (str == NULL)
14747db96d56Sopenharmony_ci                    goto exit;
14757db96d56Sopenharmony_ci                rv = Py_BuildValue("(O(iO))", str, d, samps);
14767db96d56Sopenharmony_ci                Py_DECREF(samps);
14777db96d56Sopenharmony_ci                Py_DECREF(str);
14787db96d56Sopenharmony_ci                goto exit; /* return rv */
14797db96d56Sopenharmony_ci            }
14807db96d56Sopenharmony_ci            for (chan = 0; chan < nchannels; chan++) {
14817db96d56Sopenharmony_ci                prev_i[chan] = cur_i[chan];
14827db96d56Sopenharmony_ci                cur_i[chan] = GETSAMPLE32(width, cp, 0);
14837db96d56Sopenharmony_ci                cp += width;
14847db96d56Sopenharmony_ci                /* implements a simple digital filter */
14857db96d56Sopenharmony_ci                cur_i[chan] = (int)(
14867db96d56Sopenharmony_ci                    ((double)weightA * (double)cur_i[chan] +
14877db96d56Sopenharmony_ci                     (double)weightB * (double)prev_i[chan]) /
14887db96d56Sopenharmony_ci                    ((double)weightA + (double)weightB));
14897db96d56Sopenharmony_ci            }
14907db96d56Sopenharmony_ci            len--;
14917db96d56Sopenharmony_ci            d += outrate;
14927db96d56Sopenharmony_ci        }
14937db96d56Sopenharmony_ci        while (d >= 0) {
14947db96d56Sopenharmony_ci            for (chan = 0; chan < nchannels; chan++) {
14957db96d56Sopenharmony_ci                cur_o = (int)(((double)prev_i[chan] * (double)d +
14967db96d56Sopenharmony_ci                         (double)cur_i[chan] * (double)(outrate - d)) /
14977db96d56Sopenharmony_ci                    (double)outrate);
14987db96d56Sopenharmony_ci                SETSAMPLE32(width, ncp, 0, cur_o);
14997db96d56Sopenharmony_ci                ncp += width;
15007db96d56Sopenharmony_ci            }
15017db96d56Sopenharmony_ci            d -= inrate;
15027db96d56Sopenharmony_ci        }
15037db96d56Sopenharmony_ci    }
15047db96d56Sopenharmony_ci  exit:
15057db96d56Sopenharmony_ci    PyMem_Free(prev_i);
15067db96d56Sopenharmony_ci    PyMem_Free(cur_i);
15077db96d56Sopenharmony_ci    return rv;
15087db96d56Sopenharmony_ci}
15097db96d56Sopenharmony_ci
15107db96d56Sopenharmony_ci/*[clinic input]
15117db96d56Sopenharmony_ciaudioop.lin2ulaw
15127db96d56Sopenharmony_ci
15137db96d56Sopenharmony_ci    fragment: Py_buffer
15147db96d56Sopenharmony_ci    width: int
15157db96d56Sopenharmony_ci    /
15167db96d56Sopenharmony_ci
15177db96d56Sopenharmony_ciConvert samples in the audio fragment to u-LAW encoding.
15187db96d56Sopenharmony_ci[clinic start generated code]*/
15197db96d56Sopenharmony_ci
15207db96d56Sopenharmony_cistatic PyObject *
15217db96d56Sopenharmony_ciaudioop_lin2ulaw_impl(PyObject *module, Py_buffer *fragment, int width)
15227db96d56Sopenharmony_ci/*[clinic end generated code: output=14fb62b16fe8ea8e input=2450d1b870b6bac2]*/
15237db96d56Sopenharmony_ci{
15247db96d56Sopenharmony_ci    unsigned char *ncp;
15257db96d56Sopenharmony_ci    Py_ssize_t i;
15267db96d56Sopenharmony_ci    PyObject *rv;
15277db96d56Sopenharmony_ci
15287db96d56Sopenharmony_ci    if (!audioop_check_parameters(module, fragment->len, width))
15297db96d56Sopenharmony_ci        return NULL;
15307db96d56Sopenharmony_ci
15317db96d56Sopenharmony_ci    rv = PyBytes_FromStringAndSize(NULL, fragment->len/width);
15327db96d56Sopenharmony_ci    if (rv == NULL)
15337db96d56Sopenharmony_ci        return NULL;
15347db96d56Sopenharmony_ci    ncp = (unsigned char *)PyBytes_AsString(rv);
15357db96d56Sopenharmony_ci
15367db96d56Sopenharmony_ci    for (i = 0; i < fragment->len; i += width) {
15377db96d56Sopenharmony_ci        int val = GETSAMPLE32(width, fragment->buf, i);
15387db96d56Sopenharmony_ci        *ncp++ = st_14linear2ulaw(val >> 18);
15397db96d56Sopenharmony_ci    }
15407db96d56Sopenharmony_ci    return rv;
15417db96d56Sopenharmony_ci}
15427db96d56Sopenharmony_ci
15437db96d56Sopenharmony_ci/*[clinic input]
15447db96d56Sopenharmony_ciaudioop.ulaw2lin
15457db96d56Sopenharmony_ci
15467db96d56Sopenharmony_ci    fragment: Py_buffer
15477db96d56Sopenharmony_ci    width: int
15487db96d56Sopenharmony_ci    /
15497db96d56Sopenharmony_ci
15507db96d56Sopenharmony_ciConvert sound fragments in u-LAW encoding to linearly encoded sound fragments.
15517db96d56Sopenharmony_ci[clinic start generated code]*/
15527db96d56Sopenharmony_ci
15537db96d56Sopenharmony_cistatic PyObject *
15547db96d56Sopenharmony_ciaudioop_ulaw2lin_impl(PyObject *module, Py_buffer *fragment, int width)
15557db96d56Sopenharmony_ci/*[clinic end generated code: output=378356b047521ba2 input=45d53ddce5be7d06]*/
15567db96d56Sopenharmony_ci{
15577db96d56Sopenharmony_ci    unsigned char *cp;
15587db96d56Sopenharmony_ci    signed char *ncp;
15597db96d56Sopenharmony_ci    Py_ssize_t i;
15607db96d56Sopenharmony_ci    PyObject *rv;
15617db96d56Sopenharmony_ci
15627db96d56Sopenharmony_ci    if (!audioop_check_size(module, width))
15637db96d56Sopenharmony_ci        return NULL;
15647db96d56Sopenharmony_ci
15657db96d56Sopenharmony_ci    if (fragment->len > PY_SSIZE_T_MAX/width) {
15667db96d56Sopenharmony_ci        PyErr_SetString(PyExc_MemoryError,
15677db96d56Sopenharmony_ci                        "not enough memory for output buffer");
15687db96d56Sopenharmony_ci        return NULL;
15697db96d56Sopenharmony_ci    }
15707db96d56Sopenharmony_ci    rv = PyBytes_FromStringAndSize(NULL, fragment->len*width);
15717db96d56Sopenharmony_ci    if (rv == NULL)
15727db96d56Sopenharmony_ci        return NULL;
15737db96d56Sopenharmony_ci    ncp = (signed char *)PyBytes_AsString(rv);
15747db96d56Sopenharmony_ci
15757db96d56Sopenharmony_ci    cp = fragment->buf;
15767db96d56Sopenharmony_ci    for (i = 0; i < fragment->len*width; i += width) {
15777db96d56Sopenharmony_ci        int val = st_ulaw2linear16(*cp++) << 16;
15787db96d56Sopenharmony_ci        SETSAMPLE32(width, ncp, i, val);
15797db96d56Sopenharmony_ci    }
15807db96d56Sopenharmony_ci    return rv;
15817db96d56Sopenharmony_ci}
15827db96d56Sopenharmony_ci
15837db96d56Sopenharmony_ci/*[clinic input]
15847db96d56Sopenharmony_ciaudioop.lin2alaw
15857db96d56Sopenharmony_ci
15867db96d56Sopenharmony_ci    fragment: Py_buffer
15877db96d56Sopenharmony_ci    width: int
15887db96d56Sopenharmony_ci    /
15897db96d56Sopenharmony_ci
15907db96d56Sopenharmony_ciConvert samples in the audio fragment to a-LAW encoding.
15917db96d56Sopenharmony_ci[clinic start generated code]*/
15927db96d56Sopenharmony_ci
15937db96d56Sopenharmony_cistatic PyObject *
15947db96d56Sopenharmony_ciaudioop_lin2alaw_impl(PyObject *module, Py_buffer *fragment, int width)
15957db96d56Sopenharmony_ci/*[clinic end generated code: output=d076f130121a82f0 input=ffb1ef8bb39da945]*/
15967db96d56Sopenharmony_ci{
15977db96d56Sopenharmony_ci    unsigned char *ncp;
15987db96d56Sopenharmony_ci    Py_ssize_t i;
15997db96d56Sopenharmony_ci    PyObject *rv;
16007db96d56Sopenharmony_ci
16017db96d56Sopenharmony_ci    if (!audioop_check_parameters(module, fragment->len, width))
16027db96d56Sopenharmony_ci        return NULL;
16037db96d56Sopenharmony_ci
16047db96d56Sopenharmony_ci    rv = PyBytes_FromStringAndSize(NULL, fragment->len/width);
16057db96d56Sopenharmony_ci    if (rv == NULL)
16067db96d56Sopenharmony_ci        return NULL;
16077db96d56Sopenharmony_ci    ncp = (unsigned char *)PyBytes_AsString(rv);
16087db96d56Sopenharmony_ci
16097db96d56Sopenharmony_ci    for (i = 0; i < fragment->len; i += width) {
16107db96d56Sopenharmony_ci        int val = GETSAMPLE32(width, fragment->buf, i);
16117db96d56Sopenharmony_ci        *ncp++ = st_linear2alaw(val >> 19);
16127db96d56Sopenharmony_ci    }
16137db96d56Sopenharmony_ci    return rv;
16147db96d56Sopenharmony_ci}
16157db96d56Sopenharmony_ci
16167db96d56Sopenharmony_ci/*[clinic input]
16177db96d56Sopenharmony_ciaudioop.alaw2lin
16187db96d56Sopenharmony_ci
16197db96d56Sopenharmony_ci    fragment: Py_buffer
16207db96d56Sopenharmony_ci    width: int
16217db96d56Sopenharmony_ci    /
16227db96d56Sopenharmony_ci
16237db96d56Sopenharmony_ciConvert sound fragments in a-LAW encoding to linearly encoded sound fragments.
16247db96d56Sopenharmony_ci[clinic start generated code]*/
16257db96d56Sopenharmony_ci
16267db96d56Sopenharmony_cistatic PyObject *
16277db96d56Sopenharmony_ciaudioop_alaw2lin_impl(PyObject *module, Py_buffer *fragment, int width)
16287db96d56Sopenharmony_ci/*[clinic end generated code: output=85c365ec559df647 input=4140626046cd1772]*/
16297db96d56Sopenharmony_ci{
16307db96d56Sopenharmony_ci    unsigned char *cp;
16317db96d56Sopenharmony_ci    signed char *ncp;
16327db96d56Sopenharmony_ci    Py_ssize_t i;
16337db96d56Sopenharmony_ci    int val;
16347db96d56Sopenharmony_ci    PyObject *rv;
16357db96d56Sopenharmony_ci
16367db96d56Sopenharmony_ci    if (!audioop_check_size(module, width))
16377db96d56Sopenharmony_ci        return NULL;
16387db96d56Sopenharmony_ci
16397db96d56Sopenharmony_ci    if (fragment->len > PY_SSIZE_T_MAX/width) {
16407db96d56Sopenharmony_ci        PyErr_SetString(PyExc_MemoryError,
16417db96d56Sopenharmony_ci                        "not enough memory for output buffer");
16427db96d56Sopenharmony_ci        return NULL;
16437db96d56Sopenharmony_ci    }
16447db96d56Sopenharmony_ci    rv = PyBytes_FromStringAndSize(NULL, fragment->len*width);
16457db96d56Sopenharmony_ci    if (rv == NULL)
16467db96d56Sopenharmony_ci        return NULL;
16477db96d56Sopenharmony_ci    ncp = (signed char *)PyBytes_AsString(rv);
16487db96d56Sopenharmony_ci    cp = fragment->buf;
16497db96d56Sopenharmony_ci
16507db96d56Sopenharmony_ci    for (i = 0; i < fragment->len*width; i += width) {
16517db96d56Sopenharmony_ci        val = st_alaw2linear16(*cp++) << 16;
16527db96d56Sopenharmony_ci        SETSAMPLE32(width, ncp, i, val);
16537db96d56Sopenharmony_ci    }
16547db96d56Sopenharmony_ci    return rv;
16557db96d56Sopenharmony_ci}
16567db96d56Sopenharmony_ci
16577db96d56Sopenharmony_ci/*[clinic input]
16587db96d56Sopenharmony_ciaudioop.lin2adpcm
16597db96d56Sopenharmony_ci
16607db96d56Sopenharmony_ci    fragment: Py_buffer
16617db96d56Sopenharmony_ci    width: int
16627db96d56Sopenharmony_ci    state: object
16637db96d56Sopenharmony_ci    /
16647db96d56Sopenharmony_ci
16657db96d56Sopenharmony_ciConvert samples to 4 bit Intel/DVI ADPCM encoding.
16667db96d56Sopenharmony_ci[clinic start generated code]*/
16677db96d56Sopenharmony_ci
16687db96d56Sopenharmony_cistatic PyObject *
16697db96d56Sopenharmony_ciaudioop_lin2adpcm_impl(PyObject *module, Py_buffer *fragment, int width,
16707db96d56Sopenharmony_ci                       PyObject *state)
16717db96d56Sopenharmony_ci/*[clinic end generated code: output=cc19f159f16c6793 input=12919d549b90c90a]*/
16727db96d56Sopenharmony_ci{
16737db96d56Sopenharmony_ci    signed char *ncp;
16747db96d56Sopenharmony_ci    Py_ssize_t i;
16757db96d56Sopenharmony_ci    int step, valpred, delta,
16767db96d56Sopenharmony_ci        index, sign, vpdiff, diff;
16777db96d56Sopenharmony_ci    PyObject *rv = NULL, *str;
16787db96d56Sopenharmony_ci    int outputbuffer = 0, bufferstep;
16797db96d56Sopenharmony_ci
16807db96d56Sopenharmony_ci    if (!audioop_check_parameters(module, fragment->len, width))
16817db96d56Sopenharmony_ci        return NULL;
16827db96d56Sopenharmony_ci
16837db96d56Sopenharmony_ci    /* Decode state, should have (value, step) */
16847db96d56Sopenharmony_ci    if ( state == Py_None ) {
16857db96d56Sopenharmony_ci        /* First time, it seems. Set defaults */
16867db96d56Sopenharmony_ci        valpred = 0;
16877db96d56Sopenharmony_ci        index = 0;
16887db96d56Sopenharmony_ci    }
16897db96d56Sopenharmony_ci    else if (!PyTuple_Check(state)) {
16907db96d56Sopenharmony_ci        PyErr_SetString(PyExc_TypeError, "state must be a tuple or None");
16917db96d56Sopenharmony_ci        return NULL;
16927db96d56Sopenharmony_ci    }
16937db96d56Sopenharmony_ci    else if (!PyArg_ParseTuple(state, "ii;lin2adpcm(): illegal state argument",
16947db96d56Sopenharmony_ci                               &valpred, &index))
16957db96d56Sopenharmony_ci    {
16967db96d56Sopenharmony_ci        return NULL;
16977db96d56Sopenharmony_ci    }
16987db96d56Sopenharmony_ci    else if (valpred >= 0x8000 || valpred < -0x8000 ||
16997db96d56Sopenharmony_ci             (size_t)index >= Py_ARRAY_LENGTH(stepsizeTable)) {
17007db96d56Sopenharmony_ci        PyErr_SetString(PyExc_ValueError, "bad state");
17017db96d56Sopenharmony_ci        return NULL;
17027db96d56Sopenharmony_ci    }
17037db96d56Sopenharmony_ci
17047db96d56Sopenharmony_ci    str = PyBytes_FromStringAndSize(NULL, fragment->len/(width*2));
17057db96d56Sopenharmony_ci    if (str == NULL)
17067db96d56Sopenharmony_ci        return NULL;
17077db96d56Sopenharmony_ci    ncp = (signed char *)PyBytes_AsString(str);
17087db96d56Sopenharmony_ci
17097db96d56Sopenharmony_ci    step = stepsizeTable[index];
17107db96d56Sopenharmony_ci    bufferstep = 1;
17117db96d56Sopenharmony_ci
17127db96d56Sopenharmony_ci    for (i = 0; i < fragment->len; i += width) {
17137db96d56Sopenharmony_ci        int val = GETSAMPLE32(width, fragment->buf, i) >> 16;
17147db96d56Sopenharmony_ci
17157db96d56Sopenharmony_ci        /* Step 1 - compute difference with previous value */
17167db96d56Sopenharmony_ci        if (val < valpred) {
17177db96d56Sopenharmony_ci            diff = valpred - val;
17187db96d56Sopenharmony_ci            sign = 8;
17197db96d56Sopenharmony_ci        }
17207db96d56Sopenharmony_ci        else {
17217db96d56Sopenharmony_ci            diff = val - valpred;
17227db96d56Sopenharmony_ci            sign = 0;
17237db96d56Sopenharmony_ci        }
17247db96d56Sopenharmony_ci
17257db96d56Sopenharmony_ci        /* Step 2 - Divide and clamp */
17267db96d56Sopenharmony_ci        /* Note:
17277db96d56Sopenharmony_ci        ** This code *approximately* computes:
17287db96d56Sopenharmony_ci        **    delta = diff*4/step;
17297db96d56Sopenharmony_ci        **    vpdiff = (delta+0.5)*step/4;
17307db96d56Sopenharmony_ci        ** but in shift step bits are dropped. The net result of this
17317db96d56Sopenharmony_ci        ** is that even if you have fast mul/div hardware you cannot
17327db96d56Sopenharmony_ci        ** put it to good use since the fixup would be too expensive.
17337db96d56Sopenharmony_ci        */
17347db96d56Sopenharmony_ci        delta = 0;
17357db96d56Sopenharmony_ci        vpdiff = (step >> 3);
17367db96d56Sopenharmony_ci
17377db96d56Sopenharmony_ci        if ( diff >= step ) {
17387db96d56Sopenharmony_ci            delta = 4;
17397db96d56Sopenharmony_ci            diff -= step;
17407db96d56Sopenharmony_ci            vpdiff += step;
17417db96d56Sopenharmony_ci        }
17427db96d56Sopenharmony_ci        step >>= 1;
17437db96d56Sopenharmony_ci        if ( diff >= step  ) {
17447db96d56Sopenharmony_ci            delta |= 2;
17457db96d56Sopenharmony_ci            diff -= step;
17467db96d56Sopenharmony_ci            vpdiff += step;
17477db96d56Sopenharmony_ci        }
17487db96d56Sopenharmony_ci        step >>= 1;
17497db96d56Sopenharmony_ci        if ( diff >= step ) {
17507db96d56Sopenharmony_ci            delta |= 1;
17517db96d56Sopenharmony_ci            vpdiff += step;
17527db96d56Sopenharmony_ci        }
17537db96d56Sopenharmony_ci
17547db96d56Sopenharmony_ci        /* Step 3 - Update previous value */
17557db96d56Sopenharmony_ci        if ( sign )
17567db96d56Sopenharmony_ci            valpred -= vpdiff;
17577db96d56Sopenharmony_ci        else
17587db96d56Sopenharmony_ci            valpred += vpdiff;
17597db96d56Sopenharmony_ci
17607db96d56Sopenharmony_ci        /* Step 4 - Clamp previous value to 16 bits */
17617db96d56Sopenharmony_ci        if ( valpred > 32767 )
17627db96d56Sopenharmony_ci            valpred = 32767;
17637db96d56Sopenharmony_ci        else if ( valpred < -32768 )
17647db96d56Sopenharmony_ci            valpred = -32768;
17657db96d56Sopenharmony_ci
17667db96d56Sopenharmony_ci        /* Step 5 - Assemble value, update index and step values */
17677db96d56Sopenharmony_ci        delta |= sign;
17687db96d56Sopenharmony_ci
17697db96d56Sopenharmony_ci        index += indexTable[delta];
17707db96d56Sopenharmony_ci        if ( index < 0 ) index = 0;
17717db96d56Sopenharmony_ci        if ( index > 88 ) index = 88;
17727db96d56Sopenharmony_ci        step = stepsizeTable[index];
17737db96d56Sopenharmony_ci
17747db96d56Sopenharmony_ci        /* Step 6 - Output value */
17757db96d56Sopenharmony_ci        if ( bufferstep ) {
17767db96d56Sopenharmony_ci            outputbuffer = (delta << 4) & 0xf0;
17777db96d56Sopenharmony_ci        } else {
17787db96d56Sopenharmony_ci            *ncp++ = (delta & 0x0f) | outputbuffer;
17797db96d56Sopenharmony_ci        }
17807db96d56Sopenharmony_ci        bufferstep = !bufferstep;
17817db96d56Sopenharmony_ci    }
17827db96d56Sopenharmony_ci    rv = Py_BuildValue("(O(ii))", str, valpred, index);
17837db96d56Sopenharmony_ci    Py_DECREF(str);
17847db96d56Sopenharmony_ci    return rv;
17857db96d56Sopenharmony_ci}
17867db96d56Sopenharmony_ci
17877db96d56Sopenharmony_ci/*[clinic input]
17887db96d56Sopenharmony_ciaudioop.adpcm2lin
17897db96d56Sopenharmony_ci
17907db96d56Sopenharmony_ci    fragment: Py_buffer
17917db96d56Sopenharmony_ci    width: int
17927db96d56Sopenharmony_ci    state: object
17937db96d56Sopenharmony_ci    /
17947db96d56Sopenharmony_ci
17957db96d56Sopenharmony_ciDecode an Intel/DVI ADPCM coded fragment to a linear fragment.
17967db96d56Sopenharmony_ci[clinic start generated code]*/
17977db96d56Sopenharmony_ci
17987db96d56Sopenharmony_cistatic PyObject *
17997db96d56Sopenharmony_ciaudioop_adpcm2lin_impl(PyObject *module, Py_buffer *fragment, int width,
18007db96d56Sopenharmony_ci                       PyObject *state)
18017db96d56Sopenharmony_ci/*[clinic end generated code: output=3440ea105acb3456 input=f5221144f5ca9ef0]*/
18027db96d56Sopenharmony_ci{
18037db96d56Sopenharmony_ci    signed char *cp;
18047db96d56Sopenharmony_ci    signed char *ncp;
18057db96d56Sopenharmony_ci    Py_ssize_t i, outlen;
18067db96d56Sopenharmony_ci    int valpred, step, delta, index, sign, vpdiff;
18077db96d56Sopenharmony_ci    PyObject *rv, *str;
18087db96d56Sopenharmony_ci    int inputbuffer = 0, bufferstep;
18097db96d56Sopenharmony_ci
18107db96d56Sopenharmony_ci    if (!audioop_check_size(module, width))
18117db96d56Sopenharmony_ci        return NULL;
18127db96d56Sopenharmony_ci
18137db96d56Sopenharmony_ci    /* Decode state, should have (value, step) */
18147db96d56Sopenharmony_ci    if ( state == Py_None ) {
18157db96d56Sopenharmony_ci        /* First time, it seems. Set defaults */
18167db96d56Sopenharmony_ci        valpred = 0;
18177db96d56Sopenharmony_ci        index = 0;
18187db96d56Sopenharmony_ci    }
18197db96d56Sopenharmony_ci    else if (!PyTuple_Check(state)) {
18207db96d56Sopenharmony_ci        PyErr_SetString(PyExc_TypeError, "state must be a tuple or None");
18217db96d56Sopenharmony_ci        return NULL;
18227db96d56Sopenharmony_ci    }
18237db96d56Sopenharmony_ci    else if (!PyArg_ParseTuple(state, "ii;adpcm2lin(): illegal state argument",
18247db96d56Sopenharmony_ci                               &valpred, &index))
18257db96d56Sopenharmony_ci    {
18267db96d56Sopenharmony_ci        return NULL;
18277db96d56Sopenharmony_ci    }
18287db96d56Sopenharmony_ci    else if (valpred >= 0x8000 || valpred < -0x8000 ||
18297db96d56Sopenharmony_ci             (size_t)index >= Py_ARRAY_LENGTH(stepsizeTable)) {
18307db96d56Sopenharmony_ci        PyErr_SetString(PyExc_ValueError, "bad state");
18317db96d56Sopenharmony_ci        return NULL;
18327db96d56Sopenharmony_ci    }
18337db96d56Sopenharmony_ci
18347db96d56Sopenharmony_ci    if (fragment->len > (PY_SSIZE_T_MAX/2)/width) {
18357db96d56Sopenharmony_ci        PyErr_SetString(PyExc_MemoryError,
18367db96d56Sopenharmony_ci                        "not enough memory for output buffer");
18377db96d56Sopenharmony_ci        return NULL;
18387db96d56Sopenharmony_ci    }
18397db96d56Sopenharmony_ci    outlen = fragment->len*width*2;
18407db96d56Sopenharmony_ci    str = PyBytes_FromStringAndSize(NULL, outlen);
18417db96d56Sopenharmony_ci    if (str == NULL)
18427db96d56Sopenharmony_ci        return NULL;
18437db96d56Sopenharmony_ci    ncp = (signed char *)PyBytes_AsString(str);
18447db96d56Sopenharmony_ci    cp = fragment->buf;
18457db96d56Sopenharmony_ci
18467db96d56Sopenharmony_ci    step = stepsizeTable[index];
18477db96d56Sopenharmony_ci    bufferstep = 0;
18487db96d56Sopenharmony_ci
18497db96d56Sopenharmony_ci    for (i = 0; i < outlen; i += width) {
18507db96d56Sopenharmony_ci        /* Step 1 - get the delta value and compute next index */
18517db96d56Sopenharmony_ci        if ( bufferstep ) {
18527db96d56Sopenharmony_ci            delta = inputbuffer & 0xf;
18537db96d56Sopenharmony_ci        } else {
18547db96d56Sopenharmony_ci            inputbuffer = *cp++;
18557db96d56Sopenharmony_ci            delta = (inputbuffer >> 4) & 0xf;
18567db96d56Sopenharmony_ci        }
18577db96d56Sopenharmony_ci
18587db96d56Sopenharmony_ci        bufferstep = !bufferstep;
18597db96d56Sopenharmony_ci
18607db96d56Sopenharmony_ci        /* Step 2 - Find new index value (for later) */
18617db96d56Sopenharmony_ci        index += indexTable[delta];
18627db96d56Sopenharmony_ci        if ( index < 0 ) index = 0;
18637db96d56Sopenharmony_ci        if ( index > 88 ) index = 88;
18647db96d56Sopenharmony_ci
18657db96d56Sopenharmony_ci        /* Step 3 - Separate sign and magnitude */
18667db96d56Sopenharmony_ci        sign = delta & 8;
18677db96d56Sopenharmony_ci        delta = delta & 7;
18687db96d56Sopenharmony_ci
18697db96d56Sopenharmony_ci        /* Step 4 - Compute difference and new predicted value */
18707db96d56Sopenharmony_ci        /*
18717db96d56Sopenharmony_ci        ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
18727db96d56Sopenharmony_ci        ** in adpcm_coder.
18737db96d56Sopenharmony_ci        */
18747db96d56Sopenharmony_ci        vpdiff = step >> 3;
18757db96d56Sopenharmony_ci        if ( delta & 4 ) vpdiff += step;
18767db96d56Sopenharmony_ci        if ( delta & 2 ) vpdiff += step>>1;
18777db96d56Sopenharmony_ci        if ( delta & 1 ) vpdiff += step>>2;
18787db96d56Sopenharmony_ci
18797db96d56Sopenharmony_ci        if ( sign )
18807db96d56Sopenharmony_ci            valpred -= vpdiff;
18817db96d56Sopenharmony_ci        else
18827db96d56Sopenharmony_ci            valpred += vpdiff;
18837db96d56Sopenharmony_ci
18847db96d56Sopenharmony_ci        /* Step 5 - clamp output value */
18857db96d56Sopenharmony_ci        if ( valpred > 32767 )
18867db96d56Sopenharmony_ci            valpred = 32767;
18877db96d56Sopenharmony_ci        else if ( valpred < -32768 )
18887db96d56Sopenharmony_ci            valpred = -32768;
18897db96d56Sopenharmony_ci
18907db96d56Sopenharmony_ci        /* Step 6 - Update step value */
18917db96d56Sopenharmony_ci        step = stepsizeTable[index];
18927db96d56Sopenharmony_ci
18937db96d56Sopenharmony_ci        /* Step 6 - Output value */
18947db96d56Sopenharmony_ci        SETSAMPLE32(width, ncp, i, valpred << 16);
18957db96d56Sopenharmony_ci    }
18967db96d56Sopenharmony_ci
18977db96d56Sopenharmony_ci    rv = Py_BuildValue("(O(ii))", str, valpred, index);
18987db96d56Sopenharmony_ci    Py_DECREF(str);
18997db96d56Sopenharmony_ci    return rv;
19007db96d56Sopenharmony_ci}
19017db96d56Sopenharmony_ci
19027db96d56Sopenharmony_ci#include "clinic/audioop.c.h"
19037db96d56Sopenharmony_ci
19047db96d56Sopenharmony_cistatic PyMethodDef audioop_methods[] = {
19057db96d56Sopenharmony_ci    AUDIOOP_MAX_METHODDEF
19067db96d56Sopenharmony_ci    AUDIOOP_MINMAX_METHODDEF
19077db96d56Sopenharmony_ci    AUDIOOP_AVG_METHODDEF
19087db96d56Sopenharmony_ci    AUDIOOP_MAXPP_METHODDEF
19097db96d56Sopenharmony_ci    AUDIOOP_AVGPP_METHODDEF
19107db96d56Sopenharmony_ci    AUDIOOP_RMS_METHODDEF
19117db96d56Sopenharmony_ci    AUDIOOP_FINDFIT_METHODDEF
19127db96d56Sopenharmony_ci    AUDIOOP_FINDMAX_METHODDEF
19137db96d56Sopenharmony_ci    AUDIOOP_FINDFACTOR_METHODDEF
19147db96d56Sopenharmony_ci    AUDIOOP_CROSS_METHODDEF
19157db96d56Sopenharmony_ci    AUDIOOP_MUL_METHODDEF
19167db96d56Sopenharmony_ci    AUDIOOP_ADD_METHODDEF
19177db96d56Sopenharmony_ci    AUDIOOP_BIAS_METHODDEF
19187db96d56Sopenharmony_ci    AUDIOOP_ULAW2LIN_METHODDEF
19197db96d56Sopenharmony_ci    AUDIOOP_LIN2ULAW_METHODDEF
19207db96d56Sopenharmony_ci    AUDIOOP_ALAW2LIN_METHODDEF
19217db96d56Sopenharmony_ci    AUDIOOP_LIN2ALAW_METHODDEF
19227db96d56Sopenharmony_ci    AUDIOOP_LIN2LIN_METHODDEF
19237db96d56Sopenharmony_ci    AUDIOOP_ADPCM2LIN_METHODDEF
19247db96d56Sopenharmony_ci    AUDIOOP_LIN2ADPCM_METHODDEF
19257db96d56Sopenharmony_ci    AUDIOOP_TOMONO_METHODDEF
19267db96d56Sopenharmony_ci    AUDIOOP_TOSTEREO_METHODDEF
19277db96d56Sopenharmony_ci    AUDIOOP_GETSAMPLE_METHODDEF
19287db96d56Sopenharmony_ci    AUDIOOP_REVERSE_METHODDEF
19297db96d56Sopenharmony_ci    AUDIOOP_BYTESWAP_METHODDEF
19307db96d56Sopenharmony_ci    AUDIOOP_RATECV_METHODDEF
19317db96d56Sopenharmony_ci    { 0,          0 }
19327db96d56Sopenharmony_ci};
19337db96d56Sopenharmony_ci
19347db96d56Sopenharmony_cistatic int
19357db96d56Sopenharmony_ciaudioop_traverse(PyObject *module, visitproc visit, void *arg)
19367db96d56Sopenharmony_ci{
19377db96d56Sopenharmony_ci    audioop_state *state = get_audioop_state(module);
19387db96d56Sopenharmony_ci    Py_VISIT(state->AudioopError);
19397db96d56Sopenharmony_ci    return 0;
19407db96d56Sopenharmony_ci}
19417db96d56Sopenharmony_ci
19427db96d56Sopenharmony_cistatic int
19437db96d56Sopenharmony_ciaudioop_clear(PyObject *module)
19447db96d56Sopenharmony_ci{
19457db96d56Sopenharmony_ci    audioop_state *state = get_audioop_state(module);
19467db96d56Sopenharmony_ci    Py_CLEAR(state->AudioopError);
19477db96d56Sopenharmony_ci    return 0;
19487db96d56Sopenharmony_ci}
19497db96d56Sopenharmony_ci
19507db96d56Sopenharmony_cistatic void
19517db96d56Sopenharmony_ciaudioop_free(void *module) {
19527db96d56Sopenharmony_ci    audioop_clear((PyObject *)module);
19537db96d56Sopenharmony_ci}
19547db96d56Sopenharmony_ci
19557db96d56Sopenharmony_cistatic int
19567db96d56Sopenharmony_ciaudioop_exec(PyObject* module)
19577db96d56Sopenharmony_ci{
19587db96d56Sopenharmony_ci    audioop_state *state = get_audioop_state(module);
19597db96d56Sopenharmony_ci
19607db96d56Sopenharmony_ci    state->AudioopError = PyErr_NewException("audioop.error", NULL, NULL);
19617db96d56Sopenharmony_ci    if (state->AudioopError == NULL) {
19627db96d56Sopenharmony_ci        return -1;
19637db96d56Sopenharmony_ci    }
19647db96d56Sopenharmony_ci
19657db96d56Sopenharmony_ci    Py_INCREF(state->AudioopError);
19667db96d56Sopenharmony_ci    if (PyModule_AddObject(module, "error", state->AudioopError) < 0) {
19677db96d56Sopenharmony_ci        Py_DECREF(state->AudioopError);
19687db96d56Sopenharmony_ci        return -1;
19697db96d56Sopenharmony_ci    }
19707db96d56Sopenharmony_ci
19717db96d56Sopenharmony_ci    return 0;
19727db96d56Sopenharmony_ci}
19737db96d56Sopenharmony_ci
19747db96d56Sopenharmony_cistatic PyModuleDef_Slot audioop_slots[] = {
19757db96d56Sopenharmony_ci    {Py_mod_exec, audioop_exec},
19767db96d56Sopenharmony_ci    {0, NULL}
19777db96d56Sopenharmony_ci};
19787db96d56Sopenharmony_ci
19797db96d56Sopenharmony_cistatic struct PyModuleDef audioopmodule = {
19807db96d56Sopenharmony_ci    PyModuleDef_HEAD_INIT,
19817db96d56Sopenharmony_ci    "audioop",
19827db96d56Sopenharmony_ci    NULL,
19837db96d56Sopenharmony_ci    sizeof(audioop_state),
19847db96d56Sopenharmony_ci    audioop_methods,
19857db96d56Sopenharmony_ci    audioop_slots,
19867db96d56Sopenharmony_ci    audioop_traverse,
19877db96d56Sopenharmony_ci    audioop_clear,
19887db96d56Sopenharmony_ci    audioop_free
19897db96d56Sopenharmony_ci};
19907db96d56Sopenharmony_ci
19917db96d56Sopenharmony_ciPyMODINIT_FUNC
19927db96d56Sopenharmony_ciPyInit_audioop(void)
19937db96d56Sopenharmony_ci{
19947db96d56Sopenharmony_ci    if (PyErr_WarnEx(PyExc_DeprecationWarning,
19957db96d56Sopenharmony_ci                     "'audioop' is deprecated and slated for removal in "
19967db96d56Sopenharmony_ci                     "Python 3.13",
19977db96d56Sopenharmony_ci                     7)) {
19987db96d56Sopenharmony_ci        return NULL;
19997db96d56Sopenharmony_ci    }
20007db96d56Sopenharmony_ci
20017db96d56Sopenharmony_ci    return PyModuleDef_Init(&audioopmodule);
20027db96d56Sopenharmony_ci}
2003