opus1 0.2.1

Pure-Rust implementation of the Opus audio codec (RFC 6716), following libopus 1.x
Documentation
//! The constant tables of `dnn/lpcnet_tables.c` (libopus 1.6.1): the plan of
//! the 320-point FFT (`kfft`), the analysis window and the DCT table.
//!
//! The values are copied from the C file, which `dump_lpcnet_tables.c`
//! generated. They are embedded rather than computed, so they do not depend
//! on the `sin` and `cos` of the platform's math library.
//! `tests/dnn_freq_burg.rs` compares every value with the tables inside a
//! libopus built with the neural network features.

use crate::kiss_fft::KissCpx;

/// `kfft.nfft`: the FFT size.
pub const KFFT_NFFT: usize = 320;
/// `kfft.scale`: 1/320, applied to the forward transform.
pub const KFFT_SCALE: f32 = 0.003125;
/// `kfft.shift`.
pub const KFFT_SHIFT: i32 = -1;
/// `kfft.factors`: pairs (radix, remaining size): 320 = 5·64, 64 = 4·16,
/// 16 = 4·4, 4 = 4·1, then zeros.
pub const KFFT_FACTORS: [i16; 16] = [5, 64, 4, 16, 4, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0];

/// `fft_bitrev`: input sample `i` goes to place `FFT_BITREV[i]`.
pub static FFT_BITREV: [i16; 320] = [
    0, 64, 128, 192, 256, 16, 80, 144, 208, 272, 32, 96, 160, 224, 288,
    48, 112, 176, 240, 304, 4, 68, 132, 196, 260, 20, 84, 148, 212, 276,
    36, 100, 164, 228, 292, 52, 116, 180, 244, 308, 8, 72, 136, 200, 264,
    24, 88, 152, 216, 280, 40, 104, 168, 232, 296, 56, 120, 184, 248, 312,
    12, 76, 140, 204, 268, 28, 92, 156, 220, 284, 44, 108, 172, 236, 300,
    60, 124, 188, 252, 316, 1, 65, 129, 193, 257, 17, 81, 145, 209, 273,
    33, 97, 161, 225, 289, 49, 113, 177, 241, 305, 5, 69, 133, 197, 261,
    21, 85, 149, 213, 277, 37, 101, 165, 229, 293, 53, 117, 181, 245, 309,
    9, 73, 137, 201, 265, 25, 89, 153, 217, 281, 41, 105, 169, 233, 297,
    57, 121, 185, 249, 313, 13, 77, 141, 205, 269, 29, 93, 157, 221, 285,
    45, 109, 173, 237, 301, 61, 125, 189, 253, 317, 2, 66, 130, 194, 258,
    18, 82, 146, 210, 274, 34, 98, 162, 226, 290, 50, 114, 178, 242, 306,
    6, 70, 134, 198, 262, 22, 86, 150, 214, 278, 38, 102, 166, 230, 294,
    54, 118, 182, 246, 310, 10, 74, 138, 202, 266, 26, 90, 154, 218, 282,
    42, 106, 170, 234, 298, 58, 122, 186, 250, 314, 14, 78, 142, 206, 270,
    30, 94, 158, 222, 286, 46, 110, 174, 238, 302, 62, 126, 190, 254, 318,
    3, 67, 131, 195, 259, 19, 83, 147, 211, 275, 35, 99, 163, 227, 291,
    51, 115, 179, 243, 307, 7, 71, 135, 199, 263, 23, 87, 151, 215, 279,
    39, 103, 167, 231, 295, 55, 119, 183, 247, 311, 11, 75, 139, 203, 267,
    27, 91, 155, 219, 283, 43, 107, 171, 235, 299, 59, 123, 187, 251, 315,
    15, 79, 143, 207, 271, 31, 95, 159, 223, 287, 47, 111, 175, 239, 303,
    63, 127, 191, 255, 319,
];

/// `fft_twiddles`: `(cos, -sin)` of `2·pi·k/320`, as `kiss_twiddle_cpx`.
#[allow(clippy::excessive_precision, clippy::approx_constant)]
pub static FFT_TWIDDLES: [KissCpx; 320] = [
    KissCpx::new(1.00000000, -0.00000000), KissCpx::new(0.999807239, -0.0196336918),
    KissCpx::new(0.999229014, -0.0392598175), KissCpx::new(0.998265624, -0.0588708036),
    KissCpx::new(0.996917307, -0.0784590989), KissCpx::new(0.995184720, -0.0980171412),
    KissCpx::new(0.993068457, -0.117537394), KissCpx::new(0.990569353, -0.137012348),
    KissCpx::new(0.987688363, -0.156434461), KissCpx::new(0.984426558, -0.175796285),
    KissCpx::new(0.980785251, -0.195090324), KissCpx::new(0.976765871, -0.214309156),
    KissCpx::new(0.972369909, -0.233445361), KissCpx::new(0.967599094, -0.252491564),
    KissCpx::new(0.962455213, -0.271440446), KissCpx::new(0.956940353, -0.290284663),
    KissCpx::new(0.951056540, -0.309017003), KissCpx::new(0.944806039, -0.327630192),
    KissCpx::new(0.938191354, -0.346117049), KissCpx::new(0.931214929, -0.364470512),
    KissCpx::new(0.923879504, -0.382683426), KissCpx::new(0.916187942, -0.400748819),
    KissCpx::new(0.908143163, -0.418659747), KissCpx::new(0.899748266, -0.436409235),
    KissCpx::new(0.891006529, -0.453990489), KissCpx::new(0.881921291, -0.471396744),
    KissCpx::new(0.872496009, -0.488621235), KissCpx::new(0.862734377, -0.505657375),
    KissCpx::new(0.852640152, -0.522498548), KissCpx::new(0.842217207, -0.539138317),
    KissCpx::new(0.831469595, -0.555570245), KissCpx::new(0.820401430, -0.571787953),
    KissCpx::new(0.809017003, -0.587785244), KissCpx::new(0.797320664, -0.603555918),
    KissCpx::new(0.785316944, -0.619093955), KissCpx::new(0.773010433, -0.634393275),
    KissCpx::new(0.760405958, -0.649448037), KissCpx::new(0.747508347, -0.664252460),
    KissCpx::new(0.734322488, -0.678800762), KissCpx::new(0.720853567, -0.693087339),
    KissCpx::new(0.707106769, -0.707106769), KissCpx::new(0.693087339, -0.720853567),
    KissCpx::new(0.678800762, -0.734322488), KissCpx::new(0.664252460, -0.747508347),
    KissCpx::new(0.649448037, -0.760405958), KissCpx::new(0.634393275, -0.773010433),
    KissCpx::new(0.619093955, -0.785316944), KissCpx::new(0.603555918, -0.797320664),
    KissCpx::new(0.587785244, -0.809017003), KissCpx::new(0.571787953, -0.820401430),
    KissCpx::new(0.555570245, -0.831469595), KissCpx::new(0.539138317, -0.842217207),
    KissCpx::new(0.522498548, -0.852640152), KissCpx::new(0.505657375, -0.862734377),
    KissCpx::new(0.488621235, -0.872496009), KissCpx::new(0.471396744, -0.881921291),
    KissCpx::new(0.453990489, -0.891006529), KissCpx::new(0.436409235, -0.899748266),
    KissCpx::new(0.418659747, -0.908143163), KissCpx::new(0.400748819, -0.916187942),
    KissCpx::new(0.382683426, -0.923879504), KissCpx::new(0.364470512, -0.931214929),
    KissCpx::new(0.346117049, -0.938191354), KissCpx::new(0.327630192, -0.944806039),
    KissCpx::new(0.309017003, -0.951056540), KissCpx::new(0.290284663, -0.956940353),
    KissCpx::new(0.271440446, -0.962455213), KissCpx::new(0.252491564, -0.967599094),
    KissCpx::new(0.233445361, -0.972369909), KissCpx::new(0.214309156, -0.976765871),
    KissCpx::new(0.195090324, -0.980785251), KissCpx::new(0.175796285, -0.984426558),
    KissCpx::new(0.156434461, -0.987688363), KissCpx::new(0.137012348, -0.990569353),
    KissCpx::new(0.117537394, -0.993068457), KissCpx::new(0.0980171412, -0.995184720),
    KissCpx::new(0.0784590989, -0.996917307), KissCpx::new(0.0588708036, -0.998265624),
    KissCpx::new(0.0392598175, -0.999229014), KissCpx::new(0.0196336918, -0.999807239),
    KissCpx::new(6.12323426e-17, -1.00000000), KissCpx::new(-0.0196336918, -0.999807239),
    KissCpx::new(-0.0392598175, -0.999229014), KissCpx::new(-0.0588708036, -0.998265624),
    KissCpx::new(-0.0784590989, -0.996917307), KissCpx::new(-0.0980171412, -0.995184720),
    KissCpx::new(-0.117537394, -0.993068457), KissCpx::new(-0.137012348, -0.990569353),
    KissCpx::new(-0.156434461, -0.987688363), KissCpx::new(-0.175796285, -0.984426558),
    KissCpx::new(-0.195090324, -0.980785251), KissCpx::new(-0.214309156, -0.976765871),
    KissCpx::new(-0.233445361, -0.972369909), KissCpx::new(-0.252491564, -0.967599094),
    KissCpx::new(-0.271440446, -0.962455213), KissCpx::new(-0.290284663, -0.956940353),
    KissCpx::new(-0.309017003, -0.951056540), KissCpx::new(-0.327630192, -0.944806039),
    KissCpx::new(-0.346117049, -0.938191354), KissCpx::new(-0.364470512, -0.931214929),
    KissCpx::new(-0.382683426, -0.923879504), KissCpx::new(-0.400748819, -0.916187942),
    KissCpx::new(-0.418659747, -0.908143163), KissCpx::new(-0.436409235, -0.899748266),
    KissCpx::new(-0.453990489, -0.891006529), KissCpx::new(-0.471396744, -0.881921291),
    KissCpx::new(-0.488621235, -0.872496009), KissCpx::new(-0.505657375, -0.862734377),
    KissCpx::new(-0.522498548, -0.852640152), KissCpx::new(-0.539138317, -0.842217207),
    KissCpx::new(-0.555570245, -0.831469595), KissCpx::new(-0.571787953, -0.820401430),
    KissCpx::new(-0.587785244, -0.809017003), KissCpx::new(-0.603555918, -0.797320664),
    KissCpx::new(-0.619093955, -0.785316944), KissCpx::new(-0.634393275, -0.773010433),
    KissCpx::new(-0.649448037, -0.760405958), KissCpx::new(-0.664252460, -0.747508347),
    KissCpx::new(-0.678800762, -0.734322488), KissCpx::new(-0.693087339, -0.720853567),
    KissCpx::new(-0.707106769, -0.707106769), KissCpx::new(-0.720853567, -0.693087339),
    KissCpx::new(-0.734322488, -0.678800762), KissCpx::new(-0.747508347, -0.664252460),
    KissCpx::new(-0.760405958, -0.649448037), KissCpx::new(-0.773010433, -0.634393275),
    KissCpx::new(-0.785316944, -0.619093955), KissCpx::new(-0.797320664, -0.603555918),
    KissCpx::new(-0.809017003, -0.587785244), KissCpx::new(-0.820401430, -0.571787953),
    KissCpx::new(-0.831469595, -0.555570245), KissCpx::new(-0.842217207, -0.539138317),
    KissCpx::new(-0.852640152, -0.522498548), KissCpx::new(-0.862734377, -0.505657375),
    KissCpx::new(-0.872496009, -0.488621235), KissCpx::new(-0.881921291, -0.471396744),
    KissCpx::new(-0.891006529, -0.453990489), KissCpx::new(-0.899748266, -0.436409235),
    KissCpx::new(-0.908143163, -0.418659747), KissCpx::new(-0.916187942, -0.400748819),
    KissCpx::new(-0.923879504, -0.382683426), KissCpx::new(-0.931214929, -0.364470512),
    KissCpx::new(-0.938191354, -0.346117049), KissCpx::new(-0.944806039, -0.327630192),
    KissCpx::new(-0.951056540, -0.309017003), KissCpx::new(-0.956940353, -0.290284663),
    KissCpx::new(-0.962455213, -0.271440446), KissCpx::new(-0.967599094, -0.252491564),
    KissCpx::new(-0.972369909, -0.233445361), KissCpx::new(-0.976765871, -0.214309156),
    KissCpx::new(-0.980785251, -0.195090324), KissCpx::new(-0.984426558, -0.175796285),
    KissCpx::new(-0.987688363, -0.156434461), KissCpx::new(-0.990569353, -0.137012348),
    KissCpx::new(-0.993068457, -0.117537394), KissCpx::new(-0.995184720, -0.0980171412),
    KissCpx::new(-0.996917307, -0.0784590989), KissCpx::new(-0.998265624, -0.0588708036),
    KissCpx::new(-0.999229014, -0.0392598175), KissCpx::new(-0.999807239, -0.0196336918),
    KissCpx::new(-1.00000000, -1.22464685e-16), KissCpx::new(-0.999807239, 0.0196336918),
    KissCpx::new(-0.999229014, 0.0392598175), KissCpx::new(-0.998265624, 0.0588708036),
    KissCpx::new(-0.996917307, 0.0784590989), KissCpx::new(-0.995184720, 0.0980171412),
    KissCpx::new(-0.993068457, 0.117537394), KissCpx::new(-0.990569353, 0.137012348),
    KissCpx::new(-0.987688363, 0.156434461), KissCpx::new(-0.984426558, 0.175796285),
    KissCpx::new(-0.980785251, 0.195090324), KissCpx::new(-0.976765871, 0.214309156),
    KissCpx::new(-0.972369909, 0.233445361), KissCpx::new(-0.967599094, 0.252491564),
    KissCpx::new(-0.962455213, 0.271440446), KissCpx::new(-0.956940353, 0.290284663),
    KissCpx::new(-0.951056540, 0.309017003), KissCpx::new(-0.944806039, 0.327630192),
    KissCpx::new(-0.938191354, 0.346117049), KissCpx::new(-0.931214929, 0.364470512),
    KissCpx::new(-0.923879504, 0.382683426), KissCpx::new(-0.916187942, 0.400748819),
    KissCpx::new(-0.908143163, 0.418659747), KissCpx::new(-0.899748266, 0.436409235),
    KissCpx::new(-0.891006529, 0.453990489), KissCpx::new(-0.881921291, 0.471396744),
    KissCpx::new(-0.872496009, 0.488621235), KissCpx::new(-0.862734377, 0.505657375),
    KissCpx::new(-0.852640152, 0.522498548), KissCpx::new(-0.842217207, 0.539138317),
    KissCpx::new(-0.831469595, 0.555570245), KissCpx::new(-0.820401430, 0.571787953),
    KissCpx::new(-0.809017003, 0.587785244), KissCpx::new(-0.797320664, 0.603555918),
    KissCpx::new(-0.785316944, 0.619093955), KissCpx::new(-0.773010433, 0.634393275),
    KissCpx::new(-0.760405958, 0.649448037), KissCpx::new(-0.747508347, 0.664252460),
    KissCpx::new(-0.734322488, 0.678800762), KissCpx::new(-0.720853567, 0.693087339),
    KissCpx::new(-0.707106769, 0.707106769), KissCpx::new(-0.693087339, 0.720853567),
    KissCpx::new(-0.678800762, 0.734322488), KissCpx::new(-0.664252460, 0.747508347),
    KissCpx::new(-0.649448037, 0.760405958), KissCpx::new(-0.634393275, 0.773010433),
    KissCpx::new(-0.619093955, 0.785316944), KissCpx::new(-0.603555918, 0.797320664),
    KissCpx::new(-0.587785244, 0.809017003), KissCpx::new(-0.571787953, 0.820401430),
    KissCpx::new(-0.555570245, 0.831469595), KissCpx::new(-0.539138317, 0.842217207),
    KissCpx::new(-0.522498548, 0.852640152), KissCpx::new(-0.505657375, 0.862734377),
    KissCpx::new(-0.488621235, 0.872496009), KissCpx::new(-0.471396744, 0.881921291),
    KissCpx::new(-0.453990489, 0.891006529), KissCpx::new(-0.436409235, 0.899748266),
    KissCpx::new(-0.418659747, 0.908143163), KissCpx::new(-0.400748819, 0.916187942),
    KissCpx::new(-0.382683426, 0.923879504), KissCpx::new(-0.364470512, 0.931214929),
    KissCpx::new(-0.346117049, 0.938191354), KissCpx::new(-0.327630192, 0.944806039),
    KissCpx::new(-0.309017003, 0.951056540), KissCpx::new(-0.290284663, 0.956940353),
    KissCpx::new(-0.271440446, 0.962455213), KissCpx::new(-0.252491564, 0.967599094),
    KissCpx::new(-0.233445361, 0.972369909), KissCpx::new(-0.214309156, 0.976765871),
    KissCpx::new(-0.195090324, 0.980785251), KissCpx::new(-0.175796285, 0.984426558),
    KissCpx::new(-0.156434461, 0.987688363), KissCpx::new(-0.137012348, 0.990569353),
    KissCpx::new(-0.117537394, 0.993068457), KissCpx::new(-0.0980171412, 0.995184720),
    KissCpx::new(-0.0784590989, 0.996917307), KissCpx::new(-0.0588708036, 0.998265624),
    KissCpx::new(-0.0392598175, 0.999229014), KissCpx::new(-0.0196336918, 0.999807239),
    KissCpx::new(-1.83697015e-16, 1.00000000), KissCpx::new(0.0196336918, 0.999807239),
    KissCpx::new(0.0392598175, 0.999229014), KissCpx::new(0.0588708036, 0.998265624),
    KissCpx::new(0.0784590989, 0.996917307), KissCpx::new(0.0980171412, 0.995184720),
    KissCpx::new(0.117537394, 0.993068457), KissCpx::new(0.137012348, 0.990569353),
    KissCpx::new(0.156434461, 0.987688363), KissCpx::new(0.175796285, 0.984426558),
    KissCpx::new(0.195090324, 0.980785251), KissCpx::new(0.214309156, 0.976765871),
    KissCpx::new(0.233445361, 0.972369909), KissCpx::new(0.252491564, 0.967599094),
    KissCpx::new(0.271440446, 0.962455213), KissCpx::new(0.290284663, 0.956940353),
    KissCpx::new(0.309017003, 0.951056540), KissCpx::new(0.327630192, 0.944806039),
    KissCpx::new(0.346117049, 0.938191354), KissCpx::new(0.364470512, 0.931214929),
    KissCpx::new(0.382683426, 0.923879504), KissCpx::new(0.400748819, 0.916187942),
    KissCpx::new(0.418659747, 0.908143163), KissCpx::new(0.436409235, 0.899748266),
    KissCpx::new(0.453990489, 0.891006529), KissCpx::new(0.471396744, 0.881921291),
    KissCpx::new(0.488621235, 0.872496009), KissCpx::new(0.505657375, 0.862734377),
    KissCpx::new(0.522498548, 0.852640152), KissCpx::new(0.539138317, 0.842217207),
    KissCpx::new(0.555570245, 0.831469595), KissCpx::new(0.571787953, 0.820401430),
    KissCpx::new(0.587785244, 0.809017003), KissCpx::new(0.603555918, 0.797320664),
    KissCpx::new(0.619093955, 0.785316944), KissCpx::new(0.634393275, 0.773010433),
    KissCpx::new(0.649448037, 0.760405958), KissCpx::new(0.664252460, 0.747508347),
    KissCpx::new(0.678800762, 0.734322488), KissCpx::new(0.693087339, 0.720853567),
    KissCpx::new(0.707106769, 0.707106769), KissCpx::new(0.720853567, 0.693087339),
    KissCpx::new(0.734322488, 0.678800762), KissCpx::new(0.747508347, 0.664252460),
    KissCpx::new(0.760405958, 0.649448037), KissCpx::new(0.773010433, 0.634393275),
    KissCpx::new(0.785316944, 0.619093955), KissCpx::new(0.797320664, 0.603555918),
    KissCpx::new(0.809017003, 0.587785244), KissCpx::new(0.820401430, 0.571787953),
    KissCpx::new(0.831469595, 0.555570245), KissCpx::new(0.842217207, 0.539138317),
    KissCpx::new(0.852640152, 0.522498548), KissCpx::new(0.862734377, 0.505657375),
    KissCpx::new(0.872496009, 0.488621235), KissCpx::new(0.881921291, 0.471396744),
    KissCpx::new(0.891006529, 0.453990489), KissCpx::new(0.899748266, 0.436409235),
    KissCpx::new(0.908143163, 0.418659747), KissCpx::new(0.916187942, 0.400748819),
    KissCpx::new(0.923879504, 0.382683426), KissCpx::new(0.931214929, 0.364470512),
    KissCpx::new(0.938191354, 0.346117049), KissCpx::new(0.944806039, 0.327630192),
    KissCpx::new(0.951056540, 0.309017003), KissCpx::new(0.956940353, 0.290284663),
    KissCpx::new(0.962455213, 0.271440446), KissCpx::new(0.967599094, 0.252491564),
    KissCpx::new(0.972369909, 0.233445361), KissCpx::new(0.976765871, 0.214309156),
    KissCpx::new(0.980785251, 0.195090324), KissCpx::new(0.984426558, 0.175796285),
    KissCpx::new(0.987688363, 0.156434461), KissCpx::new(0.990569353, 0.137012348),
    KissCpx::new(0.993068457, 0.117537394), KissCpx::new(0.995184720, 0.0980171412),
    KissCpx::new(0.996917307, 0.0784590989), KissCpx::new(0.998265624, 0.0588708036),
    KissCpx::new(0.999229014, 0.0392598175), KissCpx::new(0.999807239, 0.0196336918),
];

/// `half_window`: the rising half of the analysis window (160 values).
#[allow(clippy::excessive_precision, clippy::approx_constant)]
pub static HALF_WINDOW: [f32; 160] = [
    3.78491532e-05, 0.000340620492, 0.000946046319, 0.00185389258, 0.00306380726,
    0.00457531959, 0.00638783723, 0.00850064680, 0.0109129101, 0.0136236614,
    0.0166318044, 0.0199361145, 0.0235352255, 0.0274276342, 0.0316116922,
    0.0360856056, 0.0408474281, 0.0458950549, 0.0512262285, 0.0568385124,
    0.0627293140, 0.0688958541, 0.0753351897, 0.0820441842, 0.0890194997,
    0.0962576419, 0.103754878, 0.111507311, 0.119510807, 0.127761051,
    0.136253506, 0.144983411, 0.153945804, 0.163135484, 0.172547072,
    0.182174906, 0.192013159, 0.202055752, 0.212296382, 0.222728521,
    0.233345464, 0.244140238, 0.255105674, 0.266234398, 0.277518868,
    0.288951218, 0.300523549, 0.312227666, 0.324055225, 0.335997701,
    0.348046392, 0.360192508, 0.372427016, 0.384740859, 0.397124738,
    0.409569323, 0.422065198, 0.434602767, 0.447172493, 0.459764689,
    0.472369671, 0.484977663, 0.497579008, 0.510163903, 0.522722721,
    0.535245717, 0.547723293, 0.560145974, 0.572504222, 0.584788740,
    0.596990347, 0.609099925, 0.621108532, 0.633007407, 0.644788086,
    0.656442165, 0.667961538, 0.679338276, 0.690564752, 0.701633692,
    0.712537885, 0.723270535, 0.733825266, 0.744195819, 0.754376352,
    0.764361382, 0.774145722, 0.783724606, 0.793093503, 0.802248418,
    0.811185598, 0.819901764, 0.828393936, 0.836659551, 0.844696403,
    0.852502763, 0.860077202, 0.867418647, 0.874526560, 0.881400526,
    0.888040781, 0.894447744, 0.900622249, 0.906565487, 0.912279010,
    0.917764664, 0.923024654, 0.928061485, 0.932878017, 0.937477291,
    0.941862822, 0.946038187, 0.950007319, 0.953774393, 0.957343817,
    0.960720181, 0.963908315, 0.966913164, 0.969739914, 0.972393870,
    0.974880517, 0.977205336, 0.979374051, 0.981392324, 0.983266115,
    0.985001266, 0.986603677, 0.988079309, 0.989434063, 0.990674019,
    0.991804957, 0.992832899, 0.993763626, 0.994602919, 0.995356441,
    0.996029854, 0.996628702, 0.997158289, 0.997623861, 0.998030603,
    0.998383403, 0.998687088, 0.998946249, 0.999165416, 0.999348700,
    0.999500215, 0.999623775, 0.999723017, 0.999801278, 0.999861658,
    0.999907196, 0.999940455, 0.999963880, 0.999979615, 0.999989510,
    0.999995291, 0.999998271, 0.999999523, 0.999999940, 1.00000000,
];

/// `dct_table`: 18 × 18 DCT-II coefficients; `dct` reads `DCT_TABLE[j * 18 + i]`.
#[allow(clippy::excessive_precision, clippy::approx_constant)]
pub static DCT_TABLE: [f32; 324] = [
    0.707106769, 0.996194720, 0.984807730, 0.965925813, 0.939692616,
    0.906307817, 0.866025388, 0.819152057, 0.766044438, 0.707106769,
    0.642787635, 0.573576450, 0.500000000, 0.422618270, 0.342020154,
    0.258819044, 0.173648179, 0.0871557444, 0.707106769, 0.965925813,
    0.866025388, 0.707106769, 0.500000000, 0.258819044, 6.12323426e-17,
    -0.258819044, -0.500000000, -0.707106769, -0.866025388, -0.965925813,
    -1.00000000, -0.965925813, -0.866025388, -0.707106769, -0.500000000,
    -0.258819044, 0.707106769, 0.906307817, 0.642787635, 0.258819044,
    -0.173648179, -0.573576450, -0.866025388, -0.996194720, -0.939692616,
    -0.707106769, -0.342020154, 0.0871557444, 0.500000000, 0.819152057,
    0.984807730, 0.965925813, 0.766044438, 0.422618270, 0.707106769,
    0.819152057, 0.342020154, -0.258819044, -0.766044438, -0.996194720,
    -0.866025388, -0.422618270, 0.173648179, 0.707106769, 0.984807730,
    0.906307817, 0.500000000, -0.0871557444, -0.642787635, -0.965925813,
    -0.939692616, -0.573576450, 0.707106769, 0.707106769, 6.12323426e-17,
    -0.707106769, -1.00000000, -0.707106769, -1.83697015e-16, 0.707106769,
    1.00000000, 0.707106769, 3.06161700e-16, -0.707106769, -1.00000000,
    -0.707106769, -4.28626385e-16, 0.707106769, 1.00000000, 0.707106769,
    0.707106769, 0.573576450, -0.342020154, -0.965925813, -0.766044438,
    0.0871557444, 0.866025388, 0.906307817, 0.173648179, -0.707106769,
    -0.984807730, -0.422618270, 0.500000000, 0.996194720, 0.642787635,
    -0.258819044, -0.939692616, -0.819152057, 0.707106769, 0.422618270,
    -0.642787635, -0.965925813, -0.173648179, 0.819152057, 0.866025388,
    -0.0871557444, -0.939692616, -0.707106769, 0.342020154, 0.996194720,
    0.500000000, -0.573576450, -0.984807730, -0.258819044, 0.766044438,
    0.906307817, 0.707106769, 0.258819044, -0.866025388, -0.707106769,
    0.500000000, 0.965925813, 3.06161700e-16, -0.965925813, -0.500000000,
    0.707106769, 0.866025388, -0.258819044, -1.00000000, -0.258819044,
    0.866025388, 0.707106769, -0.500000000, -0.965925813, 0.707106769,
    0.0871557444, -0.984807730, -0.258819044, 0.939692616, 0.422618270,
    -0.866025388, -0.573576450, 0.766044438, 0.707106769, -0.642787635,
    -0.819152057, 0.500000000, 0.906307817, -0.342020154, -0.965925813,
    0.173648179, 0.996194720, 0.707106769, -0.0871557444, -0.984807730,
    0.258819044, 0.939692616, -0.422618270, -0.866025388, 0.573576450,
    0.766044438, -0.707106769, -0.642787635, 0.819152057, 0.500000000,
    -0.906307817, -0.342020154, 0.965925813, 0.173648179, -0.996194720,
    0.707106769, -0.258819044, -0.866025388, 0.707106769, 0.500000000,
    -0.965925813, -4.28626385e-16, 0.965925813, -0.500000000, -0.707106769,
    0.866025388, 0.258819044, -1.00000000, 0.258819044, 0.866025388,
    -0.707106769, -0.500000000, 0.965925813, 0.707106769, -0.422618270,
    -0.642787635, 0.965925813, -0.173648179, -0.819152057, 0.866025388,
    0.0871557444, -0.939692616, 0.707106769, 0.342020154, -0.996194720,
    0.500000000, 0.573576450, -0.984807730, 0.258819044, 0.766044438,
    -0.906307817, 0.707106769, -0.573576450, -0.342020154, 0.965925813,
    -0.766044438, -0.0871557444, 0.866025388, -0.906307817, 0.173648179,
    0.707106769, -0.984807730, 0.422618270, 0.500000000, -0.996194720,
    0.642787635, 0.258819044, -0.939692616, 0.819152057, 0.707106769,
    -0.707106769, -1.83697015e-16, 0.707106769, -1.00000000, 0.707106769,
    5.51091070e-16, -0.707106769, 1.00000000, -0.707106769, -2.69484189e-15,
    0.707106769, -1.00000000, 0.707106769, -4.90477710e-16, -0.707106769,
    1.00000000, -0.707106769, 0.707106769, -0.819152057, 0.342020154,
    0.258819044, -0.766044438, 0.996194720, -0.866025388, 0.422618270,
    0.173648179, -0.707106769, 0.984807730, -0.906307817, 0.500000000,
    0.0871557444, -0.642787635, 0.965925813, -0.939692616, 0.573576450,
    0.707106769, -0.906307817, 0.642787635, -0.258819044, -0.173648179,
    0.573576450, -0.866025388, 0.996194720, -0.939692616, 0.707106769,
    -0.342020154, -0.0871557444, 0.500000000, -0.819152057, 0.984807730,
    -0.965925813, 0.766044438, -0.422618270, 0.707106769, -0.965925813,
    0.866025388, -0.707106769, 0.500000000, -0.258819044, 1.10280111e-15,
    0.258819044, -0.500000000, 0.707106769, -0.866025388, 0.965925813,
    -1.00000000, 0.965925813, -0.866025388, 0.707106769, -0.500000000,
    0.258819044, 0.707106769, -0.996194720, 0.984807730, -0.965925813,
    0.939692616, -0.906307817, 0.866025388, -0.819152057, 0.766044438,
    -0.707106769, 0.642787635, -0.573576450, 0.500000000, -0.422618270,
    0.342020154, -0.258819044, 0.173648179, -0.0871557444,
];

// The values come from the C file, not from these formulas. The test only
// checks that they were copied completely and in the right order.
#[cfg(test)]
mod tests {
    use super::*;

    fn close(a: f32, b: f64) -> bool {
        (a as f64 - b).abs() <= 2e-7
    }

    #[test]
    fn fft_bitrev_is_a_permutation() {
        let mut seen = [false; KFFT_NFFT];
        for &p in FFT_BITREV.iter() {
            assert!(!seen[p as usize], "{p} twice");
            seen[p as usize] = true;
        }
    }

    #[test]
    fn tables_follow_their_formulas() {
        use core::f64::consts::PI;
        for (k, t) in FFT_TWIDDLES.iter().enumerate() {
            let phase = 2.0 * PI * k as f64 / 320.0;
            assert!(close(t.r, phase.cos()) && close(t.i, -phase.sin()), "twiddle {k}");
        }
        for (i, &w) in HALF_WINDOW.iter().enumerate() {
            let s = (0.5 * PI * (i as f64 + 0.5) / 160.0).sin();
            assert!(close(w, (0.5 * PI * s * s).sin()), "window {i}");
        }
        for (n, &c) in DCT_TABLE.iter().enumerate() {
            let (i, j) = (n / 18, n % 18);
            let mut v = ((i as f64 + 0.5) * j as f64 * PI / 18.0).cos();
            if j == 0 {
                v *= 0.5f64.sqrt();
            }
            assert!(close(c, v), "dct {i} {j}");
        }
    }
}