/*
 * Copyright (c) 2007, 2013, 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;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import javax.sound.midi.VoiceStatus;

/**
 * Software synthesizer voice class.
 *
 * @author Karl Helgason
 */
public final class SoftVoice extends VoiceStatus {

    public int exclusiveClass = 0;
    public boolean releaseTriggered = false;
    private int noteOn_noteNumber = 0;
    private int noteOn_velocity = 0;
    private int noteOff_velocity = 0;
    private int delay = 0;
    ModelChannelMixer channelmixer = null;
    double tunedKey = 0;
    SoftTuning tuning = null;
    SoftChannel stealer_channel = null;
    ModelConnectionBlock[] stealer_extendedConnectionBlocks = null;
    SoftPerformer stealer_performer = null;
    ModelChannelMixer stealer_channelmixer = null;
    int stealer_voiceID = -1;
    int stealer_noteNumber = 0;
    int stealer_velocity = 0;
    boolean stealer_releaseTriggered = false;
    int voiceID = -1;
    boolean sustain = false;
    boolean sostenuto = false;
    boolean portamento = false;
    private final SoftFilter filter_left;
    private final SoftFilter filter_right;
    private final SoftProcess eg = new SoftEnvelopeGenerator();
    private final SoftProcess lfo = new SoftLowFrequencyOscillator();
    Map<String, SoftControl> objects =
            new HashMap<String, SoftControl>();
    SoftSynthesizer synthesizer;
    SoftInstrument instrument;
    SoftPerformer performer;
    SoftChannel softchannel = null;
    boolean on = false;
    private boolean audiostarted = false;
    private boolean started = false;
    private boolean stopping = false;
    private float osc_attenuation = 0.0f;
    private ModelOscillatorStream osc_stream;
    private int osc_stream_nrofchannels;
    private float[][] osc_buff = new float[2][];
    private boolean osc_stream_off_transmitted = false;
    private boolean out_mixer_end = false;
    private float out_mixer_left = 0;
    private float out_mixer_right = 0;
    private float out_mixer_effect1 = 0;
    private float out_mixer_effect2 = 0;
    private float last_out_mixer_left = 0;
    private float last_out_mixer_right = 0;
    private float last_out_mixer_effect1 = 0;
    private float last_out_mixer_effect2 = 0;
    ModelConnectionBlock[] extendedConnectionBlocks = null;
    private ModelConnectionBlock[] connections;
    // Last value added to destination
    private double[] connections_last = new double[50];
    // Pointer to source value
    private double[][][] connections_src = new double[50][3][];
    // Key-based override (if any)
    private int[][] connections_src_kc = new int[50][3];
    // Pointer to destination value
    private double[][] connections_dst = new double[50][];
    private boolean soundoff = false;
    private float lastMuteValue = 0;
    private float lastSoloMuteValue = 0;
    double[] co_noteon_keynumber = new double[1];
    double[] co_noteon_velocity = new double[1];
    double[] co_noteon_on = new double[1];
    private final SoftControl co_noteon = new SoftControl() {
        double[] keynumber = co_noteon_keynumber;
        double[] velocity = co_noteon_velocity;
        double[] on = co_noteon_on;
        public double[] get(int instance, String name) {
            if (name == null)
                return null;
            if (name.equals("keynumber"))
                return keynumber;
            if (name.equals("velocity"))
                return velocity;
            if (name.equals("on"))
                return on;
            return null;
        }
    };
    private final double[] co_mixer_active = new double[1];
    private final double[] co_mixer_gain = new double[1];
    private final double[] co_mixer_pan = new double[1];
    private final double[] co_mixer_balance = new double[1];
    private final double[] co_mixer_reverb = new double[1];
    private final double[] co_mixer_chorus = new double[1];
    private final SoftControl co_mixer = new SoftControl() {
        double[] active = co_mixer_active;
        double[] gain = co_mixer_gain;
        double[] pan = co_mixer_pan;
        double[] balance = co_mixer_balance;
        double[] reverb = co_mixer_reverb;
        double[] chorus = co_mixer_chorus;
        public double[] get(int instance, String name) {
            if (name == null)
                return null;
            if (name.equals("active"))
                return active;
            if (name.equals("gain"))
                return gain;
            if (name.equals("pan"))
                return pan;
            if (name.equals("balance"))
                return balance;
            if (name.equals("reverb"))
                return reverb;
            if (name.equals("chorus"))
                return chorus;
            return null;
        }
    };
    private final double[] co_osc_pitch = new double[1];
    private final SoftControl co_osc = new SoftControl() {
        double[] pitch = co_osc_pitch;
        public double[] get(int instance, String name) {
            if (name == null)
                return null;
            if (name.equals("pitch"))
                return pitch;
            return null;
        }
    };
    private final double[] co_filter_freq = new double[1];
    private final double[] co_filter_type = new double[1];
    private final double[] co_filter_q = new double[1];
    private final SoftControl co_filter = new SoftControl() {
        double[] freq = co_filter_freq;
        double[] ftype = co_filter_type;
        double[] q = co_filter_q;
        public double[] get(int instance, String name) {
            if (name == null)
                return null;
            if (name.equals("freq"))
                return freq;
            if (name.equals("type"))
                return ftype;
            if (name.equals("q"))
                return q;
            return null;
        }
    };
    SoftResamplerStreamer resampler;
    private final int nrofchannels;

    public SoftVoice(SoftSynthesizer synth) {
        synthesizer = synth;
        filter_left = new SoftFilter(synth.getFormat().getSampleRate());
        filter_right = new SoftFilter(synth.getFormat().getSampleRate());
        nrofchannels = synth.getFormat().getChannels();
    }

    private int getValueKC(ModelIdentifier id) {
        if (id.getObject().equals("midi_cc")) {
            int ic = Integer.parseInt(id.getVariable());
            if (ic != 0 && ic != 32) {
                if (ic < 120)
                    return ic;
            }
        } else if (id.getObject().equals("midi_rpn")) {
            if (id.getVariable().equals("1"))
                return 120; // Fine tuning
            if (id.getVariable().equals("2"))
                return 121; // Coarse tuning
        }
        return -1;
    }

    private double[] getValue(ModelIdentifier id) {
        SoftControl o = objects.get(id.getObject());
        if (o == null)
            return null;
        return o.get(id.getInstance(), id.getVariable());
    }

    private double transformValue(double value, ModelSource src) {
        if (src.getTransform() != null)
            return src.getTransform().transform(value);
        else
            return value;
    }

    private double transformValue(double value, ModelDestination dst) {
        if (dst.getTransform() != null)
            return dst.getTransform().transform(value);
        else
            return value;
    }

    private double processKeyBasedController(double value, int keycontrol) {
        if (keycontrol == -1)
            return value;
        if (softchannel.keybasedcontroller_active != null)
            if (softchannel.keybasedcontroller_active[note] != null)
                if (softchannel.keybasedcontroller_active[note][keycontrol]) {
                    double key_controlvalue =
                            softchannel.keybasedcontroller_value[note][keycontrol];
                    if (keycontrol == 10 || keycontrol == 91 || keycontrol == 93)
                        return key_controlvalue;
                    value += key_controlvalue * 2.0 - 1.0;
                    if (value > 1)
                        value = 1;
                    else if (value < 0)
                        value = 0;
                }
        return value;
    }

    private void processConnection(int ix) {
        ModelConnectionBlock conn = connections[ix];
        double[][] src = connections_src[ix];
        double[] dst = connections_dst[ix];
        if (dst == null || Double.isInfinite(dst[0]))
            return;

        double value = conn.getScale();
        if (softchannel.keybasedcontroller_active == null) {
            ModelSource[] srcs = conn.getSources();
            for (int i = 0; i < srcs.length; i++) {
                value *= transformValue(src[i][0], srcs[i]);
                if (value == 0)
                    break;
            }
        } else {
            ModelSource[] srcs = conn.getSources();
            int[] src_kc = connections_src_kc[ix];
            for (int i = 0; i < srcs.length; i++) {
                value *= transformValue(processKeyBasedController(src[i][0],
                        src_kc[i]), srcs[i]);
                if (value == 0)
                    break;
            }
        }

        value = transformValue(value, conn.getDestination());
        dst[0] = dst[0] - connections_last[ix] + value;
        connections_last[ix] = value;
        // co_mixer_gain[0] = 0;
    }

    void updateTuning(SoftTuning newtuning) {
        tuning = newtuning;
        tunedKey = tuning.getTuning(note) / 100.0;
        if (!portamento) {
            co_noteon_keynumber[0] = tunedKey * (1.0 / 128.0);
            if(performer == null)
                return;
            int[] c = performer.midi_connections[4];
            if (c == null)
                return;
            for (int i = 0; i < c.length; i++)
                processConnection(c[i]);
        }
    }

    void setNote(int noteNumber) {
        note = noteNumber;
        tunedKey = tuning.getTuning(noteNumber) / 100.0;
    }

    void noteOn(int noteNumber, int velocity, int delay) {

        sustain = false;
        sostenuto = false;
        portamento = false;

        soundoff = false;
        on = true;
        active = true;
        started = true;
        // volume = velocity;

        noteOn_noteNumber = noteNumber;
        noteOn_velocity = velocity;
        this.delay = delay;

        lastMuteValue = 0;
        lastSoloMuteValue = 0;

        setNote(noteNumber);

        if (performer.forcedKeynumber)
            co_noteon_keynumber[0] = 0;
        else
            co_noteon_keynumber[0] = tunedKey * (1f / 128f);
        if (performer.forcedVelocity)
            co_noteon_velocity[0] = 0;
        else
            co_noteon_velocity[0] = velocity * (1f / 128f);
        co_mixer_active[0] = 0;
        co_mixer_gain[0] = 0;
        co_mixer_pan[0] = 0;
        co_mixer_balance[0] = 0;
        co_mixer_reverb[0] = 0;
        co_mixer_chorus[0] = 0;
        co_osc_pitch[0] = 0;
        co_filter_freq[0] = 0;
        co_filter_q[0] = 0;
        co_filter_type[0] = 0;
        co_noteon_on[0] = 1;

        eg.reset();
        lfo.reset();
        filter_left.reset();
        filter_right.reset();

        objects.put("master", synthesizer.getMainMixer().co_master);
        objects.put("eg", eg);
        objects.put("lfo", lfo);
        objects.put("noteon", co_noteon);
        objects.put("osc", co_osc);
        objects.put("mixer", co_mixer);
        objects.put("filter", co_filter);

        connections = performer.connections;

        if (connections_last == null
                || connections_last.length < connections.length) {
            connections_last = new double[connections.length];
        }
        if (connections_src == null
                || connections_src.length < connections.length) {
            connections_src = new double[connections.length][][];
            connections_src_kc = new int[connections.length][];
        }
        if (connections_dst == null
                || connections_dst.length < connections.length) {
            connections_dst = new double[connections.length][];
        }
        for (int i = 0; i < connections.length; i++) {
            ModelConnectionBlock conn = connections[i];
            connections_last[i] = 0;
            if (conn.getSources() != null) {
                ModelSource[] srcs = conn.getSources();
                if (connections_src[i] == null
                        || connections_src[i].length < srcs.length) {
                    connections_src[i] = new double[srcs.length][];
                    connections_src_kc[i] = new int[srcs.length];
                }
                double[][] src = connections_src[i];
                int[] src_kc = connections_src_kc[i];
                connections_src[i] = src;
                for (int j = 0; j < srcs.length; j++) {
                    src_kc[j] = getValueKC(srcs[j].getIdentifier());
                    src[j] = getValue(srcs[j].getIdentifier());
                }
            }

            if (conn.getDestination() != null)
                connections_dst[i] = getValue(conn.getDestination()
                        .getIdentifier());
            else
                connections_dst[i] = null;
        }

        for (int i = 0; i < connections.length; i++)
            processConnection(i);

        if (extendedConnectionBlocks != null) {
            for (ModelConnectionBlock connection: extendedConnectionBlocks) {
                double value = 0;

                if (softchannel.keybasedcontroller_active == null) {
                    for (ModelSource src: connection.getSources()) {
                        double x = getValue(src.getIdentifier())[0];
                        ModelTransform t = src.getTransform();
                        if (t == null)
                            value += x;
                        else
                            value += t.transform(x);
                    }
                } else {
                    for (ModelSource src: connection.getSources()) {
                        double x = getValue(src.getIdentifier())[0];
                        x = processKeyBasedController(x,
                                getValueKC(src.getIdentifier()));
                        ModelTransform t = src.getTransform();
                        if (t == null)
                            value += x;
                        else
                            value += t.transform(x);
                    }
                }

                ModelDestination dest = connection.getDestination();
                ModelTransform t = dest.getTransform();
                if (t != null)
                    value = t.transform(value);
                getValue(dest.getIdentifier())[0] += value;
            }
        }

        eg.init(synthesizer);
        lfo.init(synthesizer);

    }

    void setPolyPressure(int pressure) {
        if(performer == null)
            return;
        int[] c = performer.midi_connections[2];
        if (c == null)
            return;
        for (int i = 0; i < c.length; i++)
            processConnection(c[i]);
    }

    void setChannelPressure(int pressure) {
        if(performer == null)
            return;
        int[] c = performer.midi_connections[1];
        if (c == null)
            return;
        for (int i = 0; i < c.length; i++)
            processConnection(c[i]);
    }

    void controlChange(int controller, int value) {
        if(performer == null)
            return;
        int[] c = performer.midi_ctrl_connections[controller];
        if (c == null)
            return;
        for (int i = 0; i < c.length; i++)
            processConnection(c[i]);
    }

    void nrpnChange(int controller, int value) {
        if(performer == null)
            return;
        int[] c = performer.midi_nrpn_connections.get(controller);
        if (c == null)
            return;
        for (int i = 0; i < c.length; i++)
            processConnection(c[i]);
    }

    void rpnChange(int controller, int value) {
        if(performer == null)
            return;
        int[] c = performer.midi_rpn_connections.get(controller);
        if (c == null)
            return;
        for (int i = 0; i < c.length; i++)
            processConnection(c[i]);
    }

    void setPitchBend(int bend) {
        if(performer == null)
            return;
        int[] c = performer.midi_connections[0];
        if (c == null)
            return;
        for (int i = 0; i < c.length; i++)
            processConnection(c[i]);
    }

    void setMute(boolean mute) {
        co_mixer_gain[0] -= lastMuteValue;
        lastMuteValue = mute ? -960 : 0;
        co_mixer_gain[0] += lastMuteValue;
    }

    void setSoloMute(boolean mute) {
        co_mixer_gain[0] -= lastSoloMuteValue;
        lastSoloMuteValue = mute ? -960 : 0;
        co_mixer_gain[0] += lastSoloMuteValue;
    }

    void shutdown() {
        if (co_noteon_on[0] < -0.5)
            return;
        on = false;

        co_noteon_on[0] = -1;

        if(performer == null)
            return;
        int[] c = performer.midi_connections[3];
        if (c == null)
            return;
        for (int i = 0; i < c.length; i++)
            processConnection(c[i]);
    }

    void soundOff() {
        on = false;
        soundoff = true;
    }

    void noteOff(int velocity) {
        if (!on)
            return;
        on = false;

        noteOff_velocity = velocity;

        if (softchannel.sustain) {
            sustain = true;
            return;
        }
        if (sostenuto)
            return;

        co_noteon_on[0] = 0;

        if(performer == null)
            return;
        int[] c = performer.midi_connections[3];
        if (c == null)
            return;
        for (int i = 0; i < c.length; i++)
            processConnection(c[i]);
    }

    void redamp() {
        if (co_noteon_on[0] > 0.5)
            return;
        if (co_noteon_on[0] < -0.5)
            return; // don't redamp notes in shutdown stage

        sustain = true;
        co_noteon_on[0] = 1;

        if(performer == null)
            return;
        int[] c = performer.midi_connections[3];
        if (c == null)
            return;
        for (int i = 0; i < c.length; i++)
            processConnection(c[i]);
    }

    void processControlLogic() {
        if (stopping) {
            active = false;
            stopping = false;
            audiostarted = false;
            instrument = null;
            performer = null;
            connections = null;
            extendedConnectionBlocks = null;
            channelmixer = null;
            if (osc_stream != null)
                try {
                    osc_stream.close();
                } catch (IOException e) {
                    //e.printStackTrace();
                }

            if (stealer_channel != null) {
                stealer_channel.initVoice(this, stealer_performer,
                        stealer_voiceID, stealer_noteNumber, stealer_velocity, 0,
                        stealer_extendedConnectionBlocks, stealer_channelmixer,
                        stealer_releaseTriggered);
                stealer_releaseTriggered = false;
                stealer_channel = null;
                stealer_performer = null;
                stealer_voiceID = -1;
                stealer_noteNumber = 0;
                stealer_velocity = 0;
                stealer_extendedConnectionBlocks = null;
                stealer_channelmixer = null;
            }
        }
        if (started) {
            audiostarted = true;

            ModelOscillator osc = performer.oscillators[0];

            osc_stream_off_transmitted = false;
            if (osc instanceof ModelWavetable) {
                try {
                    resampler.open((ModelWavetable)osc,
                            synthesizer.getFormat().getSampleRate());
                    osc_stream = resampler;
                } catch (IOException e) {
                    //e.printStackTrace();
                }
            } else {
                osc_stream = osc.open(synthesizer.getFormat().getSampleRate());
            }
            osc_attenuation = osc.getAttenuation();
            osc_stream_nrofchannels = osc.getChannels();
            if (osc_buff == null || osc_buff.length < osc_stream_nrofchannels)
                osc_buff = new float[osc_stream_nrofchannels][];

            if (osc_stream != null)
                osc_stream.noteOn(softchannel, this, noteOn_noteNumber,
                        noteOn_velocity);


        }
        if (audiostarted) {
            if (portamento) {
                double note_delta = tunedKey - (co_noteon_keynumber[0] * 128);
                double note_delta_a = Math.abs(note_delta);
                if (note_delta_a < 0.0000000001) {
                    co_noteon_keynumber[0] = tunedKey * (1.0 / 128.0);
                    portamento = false;
                } else {
                    if (note_delta_a > softchannel.portamento_time)
                        note_delta = Math.signum(note_delta)
                                * softchannel.portamento_time;
                    co_noteon_keynumber[0] += note_delta * (1.0 / 128.0);
                }

                int[] c = performer.midi_connections[4];
                if (c == null)
                    return;
                for (int i = 0; i < c.length; i++)
                    processConnection(c[i]);
            }

            eg.processControlLogic();
            lfo.processControlLogic();

            for (int i = 0; i < performer.ctrl_connections.length; i++)
                processConnection(performer.ctrl_connections[i]);

            osc_stream.setPitch((float)co_osc_pitch[0]);

            int filter_type = (int)co_filter_type[0];
            double filter_freq;

            if (co_filter_freq[0] == 13500.0)
                filter_freq = 19912.126958213175;
            else
                filter_freq = 440.0 * Math.exp(
                        ((co_filter_freq[0]) - 6900.0) *
                        (Math.log(2.0) / 1200.0));
            /*
            filter_freq = 440.0 * Math.pow(2.0,
            ((co_filter_freq[0]) - 6900.0) / 1200.0);*/
            /*
             * double velocity = co_noteon_velocity[0]; if(velocity < 0.5)
             * filter_freq *= ((velocity * 2)*0.75 + 0.25);
             */

            double q = co_filter_q[0] / 10.0;
            filter_left.setFilterType(filter_type);
            filter_left.setFrequency(filter_freq);
            filter_left.setResonance(q);
            filter_right.setFilterType(filter_type);
            filter_right.setFrequency(filter_freq);
            filter_right.setResonance(q);
            /*
            float gain = (float) Math.pow(10,
            (-osc_attenuation + co_mixer_gain[0]) / 200.0);
             */
            float gain = (float)Math.exp(
                    (-osc_attenuation + co_mixer_gain[0])*(Math.log(10) / 200.0));

            if (co_mixer_gain[0] <= -960)
                gain = 0;

            if (soundoff) {
                stopping = true;
                gain = 0;
                /*
                 * if(co_mixer_gain[0] > -960)
                 *   co_mixer_gain[0] -= 960;
                 */
            }

            volume = (int)(Math.sqrt(gain) * 128);

            // gain *= 0.2;

            double pan = co_mixer_pan[0] * (1.0 / 1000.0);
            // System.out.println("pan = " + pan);
            if (pan < 0)
                pan = 0;
            else if (pan > 1)
                pan = 1;

            if (pan == 0.5) {
                out_mixer_left = gain * 0.7071067811865476f;
                out_mixer_right = out_mixer_left;
            } else {
                out_mixer_left = gain * (float)Math.cos(pan * Math.PI * 0.5);
                out_mixer_right = gain * (float)Math.sin(pan * Math.PI * 0.5);
            }

            double balance = co_mixer_balance[0] * (1.0 / 1000.0);
            if (balance != 0.5) {
                if (balance > 0.5)
                    out_mixer_left *= (1 - balance) * 2;
                else
                    out_mixer_right *= balance * 2;
            }

            if (synthesizer.reverb_on) {
                out_mixer_effect1 = (float)(co_mixer_reverb[0] * (1.0 / 1000.0));
                out_mixer_effect1 *= gain;
            } else
                out_mixer_effect1 = 0;
            if (synthesizer.chorus_on) {
                out_mixer_effect2 = (float)(co_mixer_chorus[0] * (1.0 / 1000.0));
                out_mixer_effect2 *= gain;
            } else
                out_mixer_effect2 = 0;
            out_mixer_end = co_mixer_active[0] < 0.5;

            if (!on)
                if (!osc_stream_off_transmitted) {
                    osc_stream_off_transmitted = true;
                    if (osc_stream != null)
                        osc_stream.noteOff(noteOff_velocity);
                }

        }
        if (started) {
            last_out_mixer_left = out_mixer_left;
            last_out_mixer_right = out_mixer_right;
            last_out_mixer_effect1 = out_mixer_effect1;
            last_out_mixer_effect2 = out_mixer_effect2;
            started = false;
        }

    }

    void mixAudioStream(SoftAudioBuffer in, SoftAudioBuffer out,
                                SoftAudioBuffer dout, float amp_from,
                                float amp_to) {
        int bufferlen = in.getSize();
        if (amp_from < 0.000000001 && amp_to < 0.000000001)
            return;
        if(dout != null && delay != 0)
        {
            if (amp_from == amp_to) {
                float[] fout = out.array();
                float[] fin = in.array();
                int j = 0;
                for (int i = delay; i < bufferlen; i++)
                    fout[i] += fin[j++] * amp_to;
                fout = dout.array();
                for (int i = 0; i < delay; i++)
                    fout[i] += fin[j++] * amp_to;
            } else {
                float amp = amp_from;
                float amp_delta = (amp_to - amp_from) / bufferlen;
                float[] fout = out.array();
                float[] fin = in.array();
                int j = 0;
                for (int i = delay; i < bufferlen; i++) {
                    amp += amp_delta;
                    fout[i] += fin[j++] * amp;
                }
                fout = dout.array();
                for (int i = 0; i < delay; i++) {
                    amp += amp_delta;
                    fout[i] += fin[j++] * amp;
                }
            }
        }
        else
        {
            if (amp_from == amp_to) {
                float[] fout = out.array();
                float[] fin = in.array();
                for (int i = 0; i < bufferlen; i++)
                    fout[i] += fin[i] * amp_to;
            } else {
                float amp = amp_from;
                float amp_delta = (amp_to - amp_from) / bufferlen;
                float[] fout = out.array();
                float[] fin = in.array();
                for (int i = 0; i < bufferlen; i++) {
                    amp += amp_delta;
                    fout[i] += fin[i] * amp;
                }
            }
        }

    }

    void processAudioLogic(SoftAudioBuffer[] buffer) {
        if (!audiostarted)
            return;

        int bufferlen = buffer[0].getSize();

        try {
            osc_buff[0] = buffer[SoftMainMixer.CHANNEL_LEFT_DRY].array();
            if (nrofchannels != 1)
                osc_buff[1] = buffer[SoftMainMixer.CHANNEL_RIGHT_DRY].array();
            int ret = osc_stream.read(osc_buff, 0, bufferlen);
            if (ret == -1) {
                stopping = true;
                return;
            }
            if (ret != bufferlen) {
                Arrays.fill(osc_buff[0], ret, bufferlen, 0f);
                if (nrofchannels != 1)
                    Arrays.fill(osc_buff[1], ret, bufferlen, 0f);
            }

        } catch (IOException e) {
            //e.printStackTrace();
        }

        SoftAudioBuffer left = buffer[SoftMainMixer.CHANNEL_LEFT];
        SoftAudioBuffer right = buffer[SoftMainMixer.CHANNEL_RIGHT];
        SoftAudioBuffer mono = buffer[SoftMainMixer.CHANNEL_MONO];
        SoftAudioBuffer eff1 = buffer[SoftMainMixer.CHANNEL_EFFECT1];
        SoftAudioBuffer eff2 = buffer[SoftMainMixer.CHANNEL_EFFECT2];

        SoftAudioBuffer dleft = buffer[SoftMainMixer.CHANNEL_DELAY_LEFT];
        SoftAudioBuffer dright = buffer[SoftMainMixer.CHANNEL_DELAY_RIGHT];
        SoftAudioBuffer dmono = buffer[SoftMainMixer.CHANNEL_DELAY_MONO];
        SoftAudioBuffer deff1 = buffer[SoftMainMixer.CHANNEL_DELAY_EFFECT1];
        SoftAudioBuffer deff2 = buffer[SoftMainMixer.CHANNEL_DELAY_EFFECT2];

        SoftAudioBuffer leftdry = buffer[SoftMainMixer.CHANNEL_LEFT_DRY];
        SoftAudioBuffer rightdry = buffer[SoftMainMixer.CHANNEL_RIGHT_DRY];

        if (osc_stream_nrofchannels == 1)
            rightdry = null;

        if (!Double.isInfinite(co_filter_freq[0])) {
            filter_left.processAudio(leftdry);
            if (rightdry != null)
                filter_right.processAudio(rightdry);
        }

        if (nrofchannels == 1) {
            out_mixer_left = (out_mixer_left + out_mixer_right) / 2;
            mixAudioStream(leftdry, left, dleft, last_out_mixer_left, out_mixer_left);
            if (rightdry != null)
                mixAudioStream(rightdry, left, dleft, last_out_mixer_left,
                        out_mixer_left);
        } else {
            if(rightdry == null &&
                    last_out_mixer_left == last_out_mixer_right &&
                    out_mixer_left == out_mixer_right)
            {
                mixAudioStream(leftdry, mono, dmono, last_out_mixer_left, out_mixer_left);
            }
            else
            {
                mixAudioStream(leftdry, left, dleft, last_out_mixer_left, out_mixer_left);
                if (rightdry != null)
                    mixAudioStream(rightdry, right, dright, last_out_mixer_right,
                        out_mixer_right);
                else
                    mixAudioStream(leftdry, right, dright, last_out_mixer_right,
                        out_mixer_right);
            }
        }

        if (rightdry == null) {
            mixAudioStream(leftdry, eff1, deff1, last_out_mixer_effect1,
                    out_mixer_effect1);
            mixAudioStream(leftdry, eff2, deff2, last_out_mixer_effect2,
                    out_mixer_effect2);
        } else {
            mixAudioStream(leftdry, eff1, deff1, last_out_mixer_effect1 * 0.5f,
                    out_mixer_effect1 * 0.5f);
            mixAudioStream(leftdry, eff2, deff2, last_out_mixer_effect2 * 0.5f,
                    out_mixer_effect2 * 0.5f);
            mixAudioStream(rightdry, eff1, deff1, last_out_mixer_effect1 * 0.5f,
                    out_mixer_effect1 * 0.5f);
            mixAudioStream(rightdry, eff2, deff2, last_out_mixer_effect2 * 0.5f,
                    out_mixer_effect2 * 0.5f);
        }

        last_out_mixer_left = out_mixer_left;
        last_out_mixer_right = out_mixer_right;
        last_out_mixer_effect1 = out_mixer_effect1;
        last_out_mixer_effect2 = out_mixer_effect2;

        if (out_mixer_end) {
            stopping = true;
        }

    }
}
