pub fn synthesis(state: &mut SynthesisState, in_samples: &mut [f32; 576], out: &mut [f32]) {
    let mut s_vec = [0f32; 32];
    let mut d_vec = [0f32; 32];

    // There are 18 synthesized PCM sample blocks.
    for b in 0..18 {
        // First, select the b-th sample from each of the 32 sub-bands, and place them in the s 
        // vector, s_vec.
        for i in 0..32 {
            s_vec[i] = in_samples[18*i + b];
        }

        // Get the front slot of the v_vec FIFO.
        let v_vec = &mut state.v_vec[state.v_front];

        // Matrixing is performed next. As per the standard, matrixing would require 2048 
        // multiplications per sub-band! However, following the method by Konstantinides 
        // published in [1], it is possible to achieve the same result through the use of a 32-point
        // DCT followed by some reconstruction.
        //
        // It should be noted that this is a deceptively simple solution. It is instructive to 
        // derive the algorithm before getting to the implementation to better understand what is 
        // happening, and where the edge-cases are.
        //
        // First, there are a few key observations to this approach:
        //
        //     1) The "matrixing" operation as per the standard is simply a 32-point MDCT. Note that
        //        an N-point MDCT produces a 2N-point output.
        //
        //     2) The output of the MDCT contains repeated blocks of samples. If the result of a
        //        MDCT defined as is X[0..64), then:
        //
        //          1) X(16.. 0] =  X(48..32]
        //          2) X[48..64) = -X[16..32)
        //
        //        Corollary: Only points [16..48) of the MDCT are actually required! All other
        //                   points are redundant.
        //
        //      3) Points [16..48) of the MDCT can be mapped from a 32-point DCT of the input
        //         vector thus allowing the use of an efficient DCT algorithm.
        //
        // The mappings above can be found graphically by plotting each row of the cosine
        // coefficient matricies of both the DCT and MDCT side-by side. The mapping becomes readily 
        // apparent, and so too do the exceptions.
        //
        // Using the observations above, if we apply a 32-point DCT transform to the input vector, 
        // s_vec, and place the output in the DCT output vector, d_vec, we obtain the plot labelled
        // d_vec below.
        //
        // Next, assuming the 32-point MDCT output vector is denoted v_vec. Map the samples from the
        // 32-point DCT, d_vec[0..32], to points v_vec[0..16], v_vec[16..32], v_vec[32..48], and
        // v_vec[48..64] of the 32-point MDCT. The result is depicted graphically in the plot
        // labelled v_vec below.
        //
        // d_vec        0              16             32
        //              .               .              .
        //              .     +---------+   +----------+
        //              +-----+    A    | /     B      |
        //              +---------------+--------------+
        //
        // v_vec        0              16             32             48              64
        //              .               .              .              .               .
        //              .   +-----------+              .              .               .
        //              . /      B      |              .              .               .
        //              +---------------+--------------+--------------+---------------+
        //              .               |     -B     / |   -A   +-----+-----+   -A    |
        //              .               +----------+   +--------+     .     +---------+ 
        //
        // Note however that the mappings in the previous step have exceptions for boundary samples.
        // These exceptions can be seen when plotting the coefficient matricies as mentioned above.
        // The mapping for boundary samples are as follows:
        //
        //     1) v_vec[ 0] =  d_vec[16]
        //     2) v_vec[32] = -d_vec[16]
        //     3) v_vec[48] = -d_vec[ 0]
        //     4) v_vec[16] =  0.0
        //
        // The final algorithm written below performs the copy and flip operations of each 16 sample
        // quadrant in seperate loops to assist auto-vectorization. The boundary samples are
        // excluded from these loops and handled manually afterwards.
        //
        // [1] K. Konstantinides, "Fast subband filtering in MPEG audio coding", Signal Processing 
        // Letters IEEE, vol. 1, no. 2, pp. 26-28, 1994.
        //
        // https://ieeexplore.ieee.org/abstract/document/300309
        dct32(&s_vec, &mut d_vec);

        for (d, s) in v_vec[48-15..48+ 0].iter_mut().rev().zip(&d_vec[1..16]) {
            *d = -s;
        }
        for (d, s) in v_vec[48+ 1..48+16].iter_mut().zip(&d_vec[1..16]) {
            *d = -s;
        }
        for (d, s) in v_vec[16+ 1..16+16].iter_mut().rev().zip(&d_vec[17..32]) {
            *d = -s;
        }
        for (d, s) in v_vec[1..16].iter_mut().zip(&d_vec[17..32]) {
            *d = *s;
        }

        v_vec[ 0] =  d_vec[16];
        v_vec[32] = -d_vec[16];
        v_vec[48] = -d_vec[ 0];
        v_vec[16] =  0.0;

        // Next, as per the specification, build a vector, u_vec, by iterating over the 16 slots in
        // v_vec, and copying the first 32 samples of EVEN numbered v_vec slots, and the last 32
        // samples of ODD numbered v_vec slots sequentially into u_vec.
        //
        // For example, given:
        //
        //        0   32   64   96  128  160  192  224  256           896  928   960  992 1024
        //        +----+----+----+----+----+----+----+----+ . . . . . . +----+-----+----+----+
        // v_vec  | a  : b  | c  : d  | e  : f  | g  | h  | . . . . . . | w  : x   | y  : z  |
        //        +----+----+----+----+----+----+----+----+ . . . . . . +----+-----+----+----+
        //        [ Slot 0 ][ Slot 1 ][ Slot 2 ][ Slot 3 ]  . . . . . . [ Slot 14 ][ Slot 15 ]
        //
        // Assuming v_front, the front of the FIFO, is slot 0, then u_vec is filled as follows:
        //
        //        0   32   64   96  128       448  480  512
        //        +----+----+----+----+ . . . . +----+----+
        // u_vec  | a  | d  | e  | h  | . . . . | w  | z  | 
        //        +----+----+----+----+ . . . . +----+----+
        //
        // Finally, generate the 32 sample PCM blocks. Assuming s[i] is sample i of a PCM sample
        // block, the following equation governs sample generation:
        //
        //         16
        // s[i] = SUM { u_vec[32*j + i] * D[32*j + i] }    for i=0..32
        //        j=0
        // 
        // where:
        //     D[0..512] is the synthesis window provided in table B.3 of ISO/IEC 11172-3.
        //
        // In words, u_vec is logically partitioned into 16 slots of 32 samples each (i.e., 
        // slot 0 spans u_vec[0..32], slot 1 spans u_vec[32..64], and so on). Then, the i-th 
        // sample in the PCM block is the summation of the i-th sample in each of the 16 u_vec 
        // slots after being multiplied by the synthesis window.
        //
        // But wait! This is VERY inefficient!
        //
        // If PCM sample generation is reframed such that instead of iterating j for every i, i is
        // iterated through for every j, then it is possible to iterate straight-through
        // v_vec[j][0..32] and D[32*j..(32*j) + 32] while multiplying and accumulating the
        // intermediary calculations in a zeroed output vector, o_vec. After iterating over every j,
        // o_vec can be copied to the output sample buffer, out, in one block.
        //
        // Using this method, there is no reason to build u_vec and cache locality is greatly
        // improved.
        let mut o_vec = [0f32; 32];

        for j in 0..8 {
            let v_start = state.v_front + (j << 1);

            let v0 = &state.v_vec[(v_start + 0) & 0xf][ 0..32];
            let v1 = &state.v_vec[(v_start + 1) & 0xf][32..64];

            let k = j << 6;

            for i in 0..32 {
                o_vec[i] += v0[i] * SYNTHESIS_D[k + i +  0];
                o_vec[i] += v1[i] * SYNTHESIS_D[k + i + 32];
            }
        }

        // Copy PCM samples in o_vec to the output buffer.
        let i = b << 5;
        out[i..i + 32].copy_from_slice(&o_vec);

        // Shift the v_vec FIFO. The value v_front is the index of the 64 sample slot in v_vec
        // that will be overwritten next iteration. Conversely, that makes it the front of the 
        // FIFO for the purpose of building u_vec. We would like to overwrite the oldest slot,
        // so we subtract 1 via a wrapping addition to move the front backwards by 1 slot,
        // effectively overwriting the oldest slot with the soon-to-be newest.
        state.v_front = (state.v_front + 15) & 0xf;
    }
}
/// Sub-band synthesis transforms 32 sub-band blocks containing 18 time-domain samples each into
/// 18 blocks of 32 PCM audio samples.
Sub-band synthesis transforms 32 sub-band blocks containing 18 time-domain samples each into
18 blocks of 32 PCM audio samples.
Sub - band synthesis transforms 32 sub - band blocks containing 18 time - domain samples each into 18 blocks of 32 PCM audio samples .
pub fn synthesis(state: &mut SynthesisState, in_samples: &mut [f32; 576], out: &mut [f32]) {
    let mut s_vec = [0f32; 32];
    let mut d_vec = [0f32; 32];
    // There are 18 synthesized PCM sample blocks.
    for b in 0..18 {
        // First, select the b-th sample from each of the 32 sub-bands, and place them in the s 
        // vector, s_vec.
        for i in 0..32 {
            s_vec[i] = in_samples[18*i + b];
        }
        // Get the front slot of the v_vec FIFO.
        let v_vec = &mut state.v_vec[state.v_front];
        // Matrixing is performed next. As per the standard, matrixing would require 2048 
        // multiplications per sub-band! However, following the method by Konstantinides 
        // published in [1], it is possible to achieve the same result through the use of a 32-point
        // DCT followed by some reconstruction.
        //
        // It should be noted that this is a deceptively simple solution. It is instructive to 
        // derive the algorithm before getting to the implementation to better understand what is 
        // happening, and where the edge-cases are.
        //
        // First, there are a few key observations to this approach:
        //
        //     1) The "matrixing" operation as per the standard is simply a 32-point MDCT. Note that
        //        an N-point MDCT produces a 2N-point output.
        //
        //     2) The output of the MDCT contains repeated blocks of samples. If the result of a
        //        MDCT defined as is X[0..64), then:
        //
        //          1) X(16.. 0] =  X(48..32]
        //          2) X[48..64) = -X[16..32)
        //
        //        Corollary: Only points [16..48) of the MDCT are actually required! All other
        //                   points are redundant.
        //
        //      3) Points [16..48) of the MDCT can be mapped from a 32-point DCT of the input
        //         vector thus allowing the use of an efficient DCT algorithm.
        //
        // The mappings above can be found graphically by plotting each row of the cosine
        // coefficient matricies of both the DCT and MDCT side-by side. The mapping becomes readily 
        // apparent, and so too do the exceptions.
        //
        // Using the observations above, if we apply a 32-point DCT transform to the input vector, 
        // s_vec, and place the output in the DCT output vector, d_vec, we obtain the plot labelled
        // d_vec below.
        //
        // Next, assuming the 32-point MDCT output vector is denoted v_vec. Map the samples from the
        // 32-point DCT, d_vec[0..32], to points v_vec[0..16], v_vec[16..32], v_vec[32..48], and
        // v_vec[48..64] of the 32-point MDCT. The result is depicted graphically in the plot
        // labelled v_vec below.
        //
        // d_vec        0              16             32
        //              .               .              .
        //              .     +---------+   +----------+
        //              +-----+    A    | /     B      |
        //              +---------------+--------------+
        //
        // v_vec        0              16             32             48              64
        //              .               .              .              .               .
        //              .   +-----------+              .              .               .
        //              . /      B      |              .              .               .
        //              +---------------+--------------+--------------+---------------+
        //              .               |     -B     / |   -A   +-----+-----+   -A    |
        //              .               +----------+   +--------+     .     +---------+ 
        //
        // Note however that the mappings in the previous step have exceptions for boundary samples.
        // These exceptions can be seen when plotting the coefficient matricies as mentioned above.
        // The mapping for boundary samples are as follows:
        //
        //     1) v_vec[ 0] =  d_vec[16]
        //     2) v_vec[32] = -d_vec[16]
        //     3) v_vec[48] = -d_vec[ 0]
        //     4) v_vec[16] =  0.0
        //
        // The final algorithm written below performs the copy and flip operations of each 16 sample
        // quadrant in seperate loops to assist auto-vectorization. The boundary samples are
        // excluded from these loops and handled manually afterwards.
        //
        // [1] K. Konstantinides, "Fast subband filtering in MPEG audio coding", Signal Processing 
        // Letters IEEE, vol. 1, no. 2, pp. 26-28, 1994.
        //
        // https://ieeexplore.ieee.org/abstract/document/300309
        dct32(&s_vec, &mut d_vec);
        for (d, s) in v_vec[48-15..48+ 0].iter_mut().rev().zip(&d_vec[1..16]) {
            *d = -s;
        }
        for (d, s) in v_vec[48+ 1..48+16].iter_mut().zip(&d_vec[1..16]) {
            *d = -s;
        }
        for (d, s) in v_vec[16+ 1..16+16].iter_mut().rev().zip(&d_vec[17..32]) {
            *d = -s;
        }
        for (d, s) in v_vec[1..16].iter_mut().zip(&d_vec[17..32]) {
            *d = *s;
        }
        v_vec[ 0] =  d_vec[16];
        v_vec[32] = -d_vec[16];
        v_vec[48] = -d_vec[ 0];
        v_vec[16] =  0.0;
        // Next, as per the specification, build a vector, u_vec, by iterating over the 16 slots in
        // v_vec, and copying the first 32 samples of EVEN numbered v_vec slots, and the last 32
        // samples of ODD numbered v_vec slots sequentially into u_vec.
        //
        // For example, given:
        //
        //        0   32   64   96  128  160  192  224  256           896  928   960  992 1024
        //        +----+----+----+----+----+----+----+----+ . . . . . . +----+-----+----+----+
        // v_vec  | a  : b  | c  : d  | e  : f  | g  | h  | . . . . . . | w  : x   | y  : z  |
        //        +----+----+----+----+----+----+----+----+ . . . . . . +----+-----+----+----+
        //        [ Slot 0 ][ Slot 1 ][ Slot 2 ][ Slot 3 ]  . . . . . . [ Slot 14 ][ Slot 15 ]
        //
        // Assuming v_front, the front of the FIFO, is slot 0, then u_vec is filled as follows:
        //
        //        0   32   64   96  128       448  480  512
        //        +----+----+----+----+ . . . . +----+----+
        // u_vec  | a  | d  | e  | h  | . . . . | w  | z  | 
        //        +----+----+----+----+ . . . . +----+----+
        //
        // Finally, generate the 32 sample PCM blocks. Assuming s[i] is sample i of a PCM sample
        // block, the following equation governs sample generation:
        //
        //         16
        // s[i] = SUM { u_vec[32*j + i] * D[32*j + i] }    for i=0..32
        //        j=0
        // 
        // where:
        //     D[0..512] is the synthesis window provided in table B.3 of ISO/IEC 11172-3.
        //
        // In words, u_vec is logically partitioned into 16 slots of 32 samples each (i.e., 
        // slot 0 spans u_vec[0..32], slot 1 spans u_vec[32..64], and so on). Then, the i-th 
        // sample in the PCM block is the summation of the i-th sample in each of the 16 u_vec 
        // slots after being multiplied by the synthesis window.
        //
        // But wait! This is VERY inefficient!
        //
        // If PCM sample generation is reframed such that instead of iterating j for every i, i is
        // iterated through for every j, then it is possible to iterate straight-through
        // v_vec[j][0..32] and D[32*j..(32*j) + 32] while multiplying and accumulating the
        // intermediary calculations in a zeroed output vector, o_vec. After iterating over every j,
        // o_vec can be copied to the output sample buffer, out, in one block.
        //
        // Using this method, there is no reason to build u_vec and cache locality is greatly
        // improved.
        let mut o_vec = [0f32; 32];
        for j in 0..8 {
            let v_start = state.v_front + (j << 1);
            let v0 = &state.v_vec[(v_start + 0) & 0xf][ 0..32];
            let v1 = &state.v_vec[(v_start + 1) & 0xf][32..64];
            let k = j << 6;
            for i in 0..32 {
                o_vec[i] += v0[i] * SYNTHESIS_D[k + i +  0];
                o_vec[i] += v1[i] * SYNTHESIS_D[k + i + 32];
            }
        }
        // Copy PCM samples in o_vec to the output buffer.
        let i = b << 5;
        out[i..i + 32].copy_from_slice(&o_vec);
        // Shift the v_vec FIFO. The value v_front is the index of the 64 sample slot in v_vec
        // that will be overwritten next iteration. Conversely, that makes it the front of the 
        // FIFO for the purpose of building u_vec. We would like to overwrite the oldest slot,
        // so we subtract 1 via a wrapping addition to move the front backwards by 1 slot,
        // effectively overwriting the oldest slot with the soon-to-be newest.
        state.v_front = (state.v_front + 15) & 0xf;
    }
}
pub fn synthesis ( state : & mut SynthesisState , in_samples : & mut [ f32 ; 576 ] , out : & mut [ f32 ] ) { let mut s_vec = [ 0f32 ; 32 ] ; let mut d_vec = [ 0f32 ; 32 ] ; // There are 18 synthesized PCM sample blocks. for b in 0 .. 18 { // First, select the b-th sample from each of the 32 sub-bands, and place them in the s  // vector, s_vec. for i in 0 .. 32 { s_vec [ i ] = in_samples [ 18 * i + b ] ; } // Get the front slot of the v_vec FIFO. let v_vec = & mut state . v_vec [ state . v_front ] ; // Matrixing is performed next. As per the standard, matrixing would require 2048  // multiplications per sub-band! However, following the method by Konstantinides  // published in [1], it is possible to achieve the same result through the use of a 32-point // DCT followed by some reconstruction. // // It should be noted that this is a deceptively simple solution. It is instructive to  // derive the algorithm before getting to the implementation to better understand what is  // happening, and where the edge-cases are. // // First, there are a few key observations to this approach: // //     1) The "matrixing" operation as per the standard is simply a 32-point MDCT. Note that //        an N-point MDCT produces a 2N-point output. // //     2) The output of the MDCT contains repeated blocks of samples. If the result of a //        MDCT defined as is X[0..64), then: // //          1) X(16.. 0] =  X(48..32] //          2) X[48..64) = -X[16..32) // //        Corollary: Only points [16..48) of the MDCT are actually required! All other //                   points are redundant. // //      3) Points [16..48) of the MDCT can be mapped from a 32-point DCT of the input //         vector thus allowing the use of an efficient DCT algorithm. // // The mappings above can be found graphically by plotting each row of the cosine // coefficient matricies of both the DCT and MDCT side-by side. The mapping becomes readily  // apparent, and so too do the exceptions. // // Using the observations above, if we apply a 32-point DCT transform to the input vector,  // s_vec, and place the output in the DCT output vector, d_vec, we obtain the plot labelled // d_vec below. // // Next, assuming the 32-point MDCT output vector is denoted v_vec. Map the samples from the // 32-point DCT, d_vec[0..32], to points v_vec[0..16], v_vec[16..32], v_vec[32..48], and // v_vec[48..64] of the 32-point MDCT. The result is depicted graphically in the plot // labelled v_vec below. // // d_vec        0              16             32 //              .               .              . //              .     +---------+   +----------+ //              +-----+    A    | /     B      | //              +---------------+--------------+ // // v_vec        0              16             32             48              64 //              .               .              .              .               . //              .   +-----------+              .              .               . //              . /      B      |              .              .               . //              +---------------+--------------+--------------+---------------+ //              .               |     -B     / |   -A   +-----+-----+   -A    | //              .               +----------+   +--------+     .     +---------+  // // Note however that the mappings in the previous step have exceptions for boundary samples. // These exceptions can be seen when plotting the coefficient matricies as mentioned above. // The mapping for boundary samples are as follows: // //     1) v_vec[ 0] =  d_vec[16] //     2) v_vec[32] = -d_vec[16] //     3) v_vec[48] = -d_vec[ 0] //     4) v_vec[16] =  0.0 // // The final algorithm written below performs the copy and flip operations of each 16 sample // quadrant in seperate loops to assist auto-vectorization. The boundary samples are // excluded from these loops and handled manually afterwards. // // [1] K. Konstantinides, "Fast subband filtering in MPEG audio coding", Signal Processing  // Letters IEEE, vol. 1, no. 2, pp. 26-28, 1994. // // https://ieeexplore.ieee.org/abstract/document/300309 dct32 ( & s_vec , & mut d_vec ) ; for ( d , s ) in v_vec [ 48 - 15 .. 48 + 0 ] . iter_mut ( ) . rev ( ) . zip ( & d_vec [ 1 .. 16 ] ) { * d = - s ; } for ( d , s ) in v_vec [ 48 + 1 .. 48 + 16 ] . iter_mut ( ) . zip ( & d_vec [ 1 .. 16 ] ) { * d = - s ; } for ( d , s ) in v_vec [ 16 + 1 .. 16 + 16 ] . iter_mut ( ) . rev ( ) . zip ( & d_vec [ 17 .. 32 ] ) { * d = - s ; } for ( d , s ) in v_vec [ 1 .. 16 ] . iter_mut ( ) . zip ( & d_vec [ 17 .. 32 ] ) { * d = * s ; } v_vec [ 0 ] = d_vec [ 16 ] ; v_vec [ 32 ] = - d_vec [ 16 ] ; v_vec [ 48 ] = - d_vec [ 0 ] ; v_vec [ 16 ] = 0.0 ; // Next, as per the specification, build a vector, u_vec, by iterating over the 16 slots in // v_vec, and copying the first 32 samples of EVEN numbered v_vec slots, and the last 32 // samples of ODD numbered v_vec slots sequentially into u_vec. // // For example, given: // //        0   32   64   96  128  160  192  224  256           896  928   960  992 1024 //        +----+----+----+----+----+----+----+----+ . . . . . . +----+-----+----+----+ // v_vec  | a  : b  | c  : d  | e  : f  | g  | h  | . . . . . . | w  : x   | y  : z  | //        +----+----+----+----+----+----+----+----+ . . . . . . +----+-----+----+----+ //        [ Slot 0 ][ Slot 1 ][ Slot 2 ][ Slot 3 ]  . . . . . . [ Slot 14 ][ Slot 15 ] // // Assuming v_front, the front of the FIFO, is slot 0, then u_vec is filled as follows: // //        0   32   64   96  128       448  480  512 //        +----+----+----+----+ . . . . +----+----+ // u_vec  | a  | d  | e  | h  | . . . . | w  | z  |  //        +----+----+----+----+ . . . . +----+----+ // // Finally, generate the 32 sample PCM blocks. Assuming s[i] is sample i of a PCM sample // block, the following equation governs sample generation: // //         16 // s[i] = SUM { u_vec[32*j + i] * D[32*j + i] }    for i=0..32 //        j=0 //  // where: //     D[0..512] is the synthesis window provided in table B.3 of ISO/IEC 11172-3. // // In words, u_vec is logically partitioned into 16 slots of 32 samples each (i.e.,  // slot 0 spans u_vec[0..32], slot 1 spans u_vec[32..64], and so on). Then, the i-th  // sample in the PCM block is the summation of the i-th sample in each of the 16 u_vec  // slots after being multiplied by the synthesis window. // // But wait! This is VERY inefficient! // // If PCM sample generation is reframed such that instead of iterating j for every i, i is // iterated through for every j, then it is possible to iterate straight-through // v_vec[j][0..32] and D[32*j..(32*j) + 32] while multiplying and accumulating the // intermediary calculations in a zeroed output vector, o_vec. After iterating over every j, // o_vec can be copied to the output sample buffer, out, in one block. // // Using this method, there is no reason to build u_vec and cache locality is greatly // improved. let mut o_vec = [ 0f32 ; 32 ] ; for j in 0 .. 8 { let v_start = state . v_front + ( j << 1 ) ; let v0 = & state . v_vec [ ( v_start + 0 ) & 0xf ] [ 0 .. 32 ] ; let v1 = & state . v_vec [ ( v_start + 1 ) & 0xf ] [ 32 .. 64 ] ; let k = j << 6 ; for i in 0 .. 32 { o_vec [ i ] += v0 [ i ] * SYNTHESIS_D [ k + i + 0 ] ; o_vec [ i ] += v1 [ i ] * SYNTHESIS_D [ k + i + 32 ] ; } } // Copy PCM samples in o_vec to the output buffer. let i = b << 5 ; out [ i .. i + 32 ] . copy_from_slice ( & o_vec ) ; // Shift the v_vec FIFO. The value v_front is the index of the 64 sample slot in v_vec // that will be overwritten next iteration. Conversely, that makes it the front of the  // FIFO for the purpose of building u_vec. We would like to overwrite the oldest slot, // so we subtract 1 via a wrapping addition to move the front backwards by 1 slot, // effectively overwriting the oldest slot with the soon-to-be newest. state . v_front = ( state . v_front + 15 ) & 0xf ; } }
Sub-band synthesis transforms 32 sub-band blocks containing 18 time-domain samples each into
18 blocks of 32 PCM audio samples.
Sub - band synthesis transforms 32 sub - band blocks containing 18 time - domain samples each into 18 blocks of 32 PCM audio samples .
state
&mut SynthesisState
in_samples
&mut [f32; 576]
out
&mut [f32]
state
&mut SynthesisState
in_samples
&mut [f32; 576]
out
&mut [f32]