/*
 * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package com.sun.media.sound;

/**
 * A simple look-ahead volume limiter with very fast attack and fast release.
 * This filter is used for preventing clipping.
 *
 * @author Karl Helgason
 */
public class SoftLimiter implements SoftAudioProcessor {

    float lastmax = 0;
    float gain = 1;
    float[] temp_bufferL;
    float[] temp_bufferR;
    boolean mix = false;
    SoftAudioBuffer bufferL;
    SoftAudioBuffer bufferR;
    SoftAudioBuffer bufferLout;
    SoftAudioBuffer bufferRout;
    float controlrate;

    public void init(float samplerate, float controlrate) {
        this.controlrate = controlrate;
    }

    public void setInput(int pin, SoftAudioBuffer input) {
        if (pin == 0)
            bufferL = input;
        if (pin == 1)
            bufferR = input;
    }

    public void setOutput(int pin, SoftAudioBuffer output) {
        if (pin == 0)
            bufferLout = output;
        if (pin == 1)
            bufferRout = output;
    }

    public void setMixMode(boolean mix) {
        this.mix = mix;
    }

    public void globalParameterControlChange(int[] slothpath, long param,
            long value) {
    }

    double silentcounter = 0;

    public void processAudio() {
        if (this.bufferL.isSilent()
                && (this.bufferR == null || this.bufferR.isSilent())) {
            silentcounter += 1 / controlrate;

            if (silentcounter > 60) {
                if (!mix) {
                    bufferLout.clear();
                    if (bufferRout != null) bufferRout.clear();
                }
                return;
            }
        } else
            silentcounter = 0;

        float[] bufferL = this.bufferL.array();
        float[] bufferR = this.bufferR == null ? null : this.bufferR.array();
        float[] bufferLout = this.bufferLout.array();
        float[] bufferRout = this.bufferRout == null
                                ? null : this.bufferRout.array();

        if (temp_bufferL == null || temp_bufferL.length < bufferL.length)
            temp_bufferL = new float[bufferL.length];
        if (bufferR != null)
            if (temp_bufferR == null || temp_bufferR.length < bufferR.length)
                temp_bufferR = new float[bufferR.length];

        float max = 0;
        int len = bufferL.length;

        if (bufferR == null) {
            for (int i = 0; i < len; i++) {
                if (bufferL[i] > max)
                    max = bufferL[i];
                if (-bufferL[i] > max)
                    max = -bufferL[i];
            }
        } else {
            for (int i = 0; i < len; i++) {
                if (bufferL[i] > max)
                    max = bufferL[i];
                if (bufferR[i] > max)
                    max = bufferR[i];
                if (-bufferL[i] > max)
                    max = -bufferL[i];
                if (-bufferR[i] > max)
                    max = -bufferR[i];
            }
        }

        float lmax = lastmax;
        lastmax = max;
        if (lmax > max)
            max = lmax;

        float newgain = 1;
        if (max > 0.99f)
            newgain = 0.99f / max;
        else
            newgain = 1;

        if (newgain > gain)
            newgain = (newgain + gain * 9) / 10f;

        float gaindelta = (newgain - gain) / len;
        if (mix) {
            if (bufferR == null) {
                for (int i = 0; i < len; i++) {
                    gain += gaindelta;
                    float bL = bufferL[i];
                    float tL = temp_bufferL[i];
                    temp_bufferL[i] = bL;
                    bufferLout[i] += tL * gain;
                }
            } else {
                for (int i = 0; i < len; i++) {
                    gain += gaindelta;
                    float bL = bufferL[i];
                    float bR = bufferR[i];
                    float tL = temp_bufferL[i];
                    float tR = temp_bufferR[i];
                    temp_bufferL[i] = bL;
                    temp_bufferR[i] = bR;
                    bufferLout[i] += tL * gain;
                    bufferRout[i] += tR * gain;
                }
            }

        } else {
            if (bufferR == null) {
                for (int i = 0; i < len; i++) {
                    gain += gaindelta;
                    float bL = bufferL[i];
                    float tL = temp_bufferL[i];
                    temp_bufferL[i] = bL;
                    bufferLout[i] = tL * gain;
                }
            } else {
                for (int i = 0; i < len; i++) {
                    gain += gaindelta;
                    float bL = bufferL[i];
                    float bR = bufferR[i];
                    float tL = temp_bufferL[i];
                    float tR = temp_bufferR[i];
                    temp_bufferL[i] = bL;
                    temp_bufferR[i] = bR;
                    bufferLout[i] = tL * gain;
                    bufferRout[i] = tR * gain;
                }
            }

        }
        gain = newgain;
    }

    public void processControlLogic() {
    }
}
