/*
 * Copyright @ 2015 Atlassian Pty Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.jitsi.impl.neomedia.codec.audio.silk;

/**
 * Apply sine window to signal vector.
 *
 * @author Jing Dai
 * @author Dingxin Xu
 */
public class ApplySineWindowFLP
{
    /**
     * Apply sine window to signal vector.
     * Window types:
     * 0 -> sine window from 0 to pi.
     * 1 -> sine window from 0 to pi/2.
     * 2 -> sine window from pi/2 to pi.
     *
     * @param px_win Pointer to windowed signal.
     * @param px_win_offset  offset of valid data.
     * @param px Pointer to input signal.
     * @param px_offset offset of valid data.
     * @param win_type Selects a window type.
     * @param length Window length, multiple of 4.
     */
//TODO float or double
    static void SKP_Silk_apply_sine_window_FLP(
              float                 px_win[],           /* O    Pointer to windowed signal              */
              int px_win_offset,
              float                 px[],               /* I    Pointer to input signal                 */
              int px_offset,
        final int                   win_type,           /* I    Selects a window type                   */
        final int                   length              /* I    Window length, multiple of 4            */
    )
    {
        int   k;
        float freq, c, S0, S1;

        /* Length must be multiple of 4 */
        assert( ( length & 3 ) == 0 );

        freq = SigProcFLP.PI / ( length + 1 );
        if( win_type == 0 )
        {
            freq = 2.0f * freq;
        }

        /* Approximation of 2 * cos(f) */
        c = 2.0f - freq * freq;

        /* Initialize state */
        if( win_type < 2 )
        {
            /* Start from 0 */
            S0 = 0.0f;
            /* Approximation of sin(f) */
            S1 = freq;
        }
        else
        {
            /* Start from 1 */
            S0 = 1.0f;
            /* Approximation of cos(f) */
            S1 = 0.5f * c;
        }

        /* Uses the recursive equation:   sin(n*f) = 2 * cos(f) * sin((n-1)*f) - sin((n-2)*f)   */
        /* 4 samples at a time */
        for( k = 0; k < length; k += 4 )
        {
            px_win[ px_win_offset + k + 0 ] = px[ px_offset + k + 0 ] * 0.5f * ( S0 + S1 );
            px_win[ px_win_offset + k + 1 ] = px[ px_offset + k + 1 ] * S1;
            S0 = c * S1 - S0;
            px_win[ px_win_offset + k + 2 ] = px[ px_offset + k + 2 ] * 0.5f * ( S1 + S0 );
            px_win[ px_win_offset + k + 3 ] = px[ px_offset + k + 3 ] * S0;
            S1 = c * S0 - S1;
        }
    }
}
