var winHeightFader = 0;
var winHeightFaderLimiter = 0;

var winWidth = 0;
var winHeightVuMeter = 0;
var labelFader = [-80.0, -70.0, -60.0, -50.0, -40.0, -30.0, -20.0, -10.0, 0.0, 10.0, 15.0];
var labelFaderMark = [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0];
var labelVuMeter = [-60.0, -50.0, -45.0, -40.0, -35.0, -30.0, -25.0, -20.0, -19.0, -18.0, -17.0, -16.0, -15.0, -14.0, -13.0, -12.0, -11.0, -10.0, -9.0, -8.0, -7.0, -6.0, -5.0, -4.0, -3.0, -2.0, -1.0, 0.0];
var labelGRVuMeter = [60.0, 50.0, 45.0, 40.0, 35.0, 30.0, 25.0, 20.0, 19.0, 18.0, 17.0, 16.0, 15.0, 14.0, 13.0, 12.0, 11.0, 10.0, 9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0, 0.0];
var labelVuMeterMark = [1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
var labelDelay = [0.0, 1.1, 2.0, 3.0, 4.0, 5.0, 10.0, 15.0, 20.0, 25.0, 30];
var labelDelayMark = [1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1];


var localAmplifier;
var soloChannelSelected = 0;
var loadingChannel = 0;
var channelCount = 16;
var demoMode = 0;
var readbackRefresh = 250;
var refreshDataFirstLoad = true;
var poolMonitorDelay = 2000;

//global scale factor db level;
var globalDbScaleFactor = 0;

var labelOverviewChannel = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P"];

// GAIN MAIN PANEL

var gainScaleMin = -80.0;
var gainScaleMax = 15.0;
var gainScaleStep = 0.1;

var clearGainValue = 0.0;
var clearPolarityEnaValue = false;

// DELAY MAIN PANEL

var delayScaleMin = 0.0;
var delayScaleMax = 30.0;
var delayScaleStep = 0.00001;

var clearDelayValue = 0.0;
var clearDelayEnaValue = false;

// PEQ MAIN PANEL 

var widgetPEQX = 1200;
var widgetPEQY = 800;

var clearPEQEnaValue = false;
var clearPEQTypeValue = 0;
var clearPEQFrequencyValue = [50, 100, 200, 300, 400, 500, 1000, 2000, 3000, 4000, 5000, 10000];
var clearPEQGainValue = 0.0;
var clearPEQQValue = 2.5;

var gainScaleMinPEQ = -40.0;
var gainScaleMaxPEQ = 15.0;

var freqScaleMinPEQ = 10;
var freqScaleMaxPEQ = 22000;

var qScaleMinPEQ = 0.1;
var qScaleMaxPEQ = 48.0;

var typeScaleMinPEQ = 0;
var typeScaleMaxPEQ = 15;

var eqCount = 12; //MAX EQ PER CANAL
var eqEnaDefault = false;
var eqFreqDefault = 1000.0;
var eqFreqDefaultInit = [50, 100, 200, 300, 400, 500, 1000, 2000, 3000, 4000, 5000, 10000];
var eqGainDefault = 0.0;
var eqQDefault = 2.5;
var eqBwDefault = 0.573;

var eqTypeDefault = 0;
var eqXLockDefault = false;
var eqYLockDefault = false;

var gain_scalePEQ = new Array(3);
gain_scalePEQ[0] = [6, 3, 0, -3, -6];
gain_scalePEQ[1] = [18, 12, 6, 0, -6, -12, -18];
gain_scalePEQ[2] = [18, 12, 6, 0, -6, -12, -18, -24, -30, -36];
var gain_scalePEQ_line = new Array(3);
gain_scalePEQ_line[0] = [6, 4.5, 3, 1.5, 0, -1.5, -3, -4.5, -6];
gain_scalePEQ_line[1] = [18, 15, 12, 9, 6, 3, 0, -3, -6, -9, -12, -15, -18];
gain_scalePEQ_line[2] = [18, 12, 6, 0, -6, -12, -18, -24, -30, -36];

var phase_scale = new Array(2);
phase_scale[0] = [180, 90, 0, -90, -180];
phase_scale[1] = [720, 360, 0, -360, -720];
var phase_scale_line = new Array(2);
phase_scale_line[0] = [180, 135, 90, 45, 0, -45, -90, -135, -180];
phase_scale_line[1] = [720, 540, 360, 180, 0, -180, -360, -540, -720];


var freqScaleMinPEQ = 10;
var freqScaleMaxPEQ = 22000;
var freqScaleStepPEQ = 1;
var freqScaleLabelPEQ = "Hz";

var gainScaleMinPEQ = -40.0;
var gainScaleMaxPEQ = 15.0;
var gainScaleStepPEQ = 0.1;
var gainScaleLabelPEQ = "dB";

var qScaleMin = 0.1;
var qScaleMax = 48.0;
var qScaleStep = 0.01;
var qScaleLable = "";

var bwScaleMin = 0.03;
var bwScaleMax = 6.5;

var fS = 48000;

var widgetPEQX = 1200;
var widgetPEQY = 800;

var widgetPEQMarginLeft = 35;
var widgetPEQMarginRight = 10;
var widgetPEQMarginRightDual = 35;
var widgetPEQMarginTop = 15;
var widgetPEQMarginBottom = 25;
var graphPEQHeight = 0;
var graphPEQWidth = 0;

var widgetPEQMainXLock = false;
var widgetPEQMainYLock = false;
var widgetPEQMainQLock = false;

var yZeroPEQ = 0;

var defaultMaxViewFreqPEQ = 24000;

var scale = (Math.log10(defaultMaxViewFreqPEQ) - 1);

var peqLabelCount = 16;
var peqLabel = ["Bell-Sym",
    "Bell-ASym",
    "Notch",
    "Low-Shelving 6dB/oct",
    "Low-Shelving 12dB/oct",
    "High-Shelving 6dB/oct",
    "High-Shelving 12dB/oct",
    "All-Pass 90°",
    "All-Pass 180°",
    "High-Pass 6dB/oct",
    "High-Pass 12dB/oct",
    "High-Pass VariQ 12dB/oct",
    "Low-Pass 6dB/oct",
    "Low-Pass 12dB/oct",
    "Low-Pass VariQ 12dB/oct",
    "Band-Pass"
];

var peqSelectedModalType = 0;

var peqViewMode = 0;
var peqGainScaleType = 2;
var peqPhaseScaleType = 0;

var peqTabMagX = new Array(eqCount);
var peqTabPhaX = new Array(eqCount);

var eqParam = { ena: eqEnaDefault, frequency: eqFreqDefault, gain: eqGainDefault, q: eqQDefault, type: eqTypeDefault, a: {}, b: {}, xLock: eqXLockDefault, yLock: eqYLockDefault };

var arrayEqParam = null;

var eqParamDraggable = new Object();
var arrayEqParamDraggable = new Array();
var peqDrag = [];
var peqDraggie = [];

var peqSoloSelected = 0;

// XOVER MAIN PANEL

var widgetXOVERX = 1200;
var widgetXOVERY = 800;

var clearXOVERHpEnaValue = false;
var clearXOVERHpFrequencyValue = 100.0;
var clearXOVERHpTypeValue = 1;
var clearXOVERLpEnaValue = false;
var clearXOVERLpFrequencyValue = 1000.0;
var clearXOVERLpTypeValue = 1;

var typeScaleMinXOVER = 0;
var typeScaleMaxXOVER = 18;

// FIR MAIN PANEL

var firSize = 768;
var firLengthMin = 32;
var firLengthMax = 768;
var firScaleMin = -1;
var firScaleMax = 1;

var firExtension = ".txt,.csv";

var firTable;
var clearFirTable;
var firTableStatus = 0;

// LIMITER MAIN PANEL 

var clearLimRmsThresValue = 130.0;
var clearLimRmsAttackValue = 20.0;
var clearLimRmsReleaseValue = 320.0;
var clearLimPeakThresValue = 180.0;
var clearLimPeakReleaseValue = 32.0;

var limiterRmsThresDefault = 15.0;
var rmsThresScaleMin = 10;
// var rmsThresScaleMax = 65;
var rmsThresScaleMax = 130;

var limiterRmsAttackDefault = 20.0;
var rmsAttackScaleMin = 0.1;
// var rmsAttackScaleMax = 100;
var rmsAttackScaleMax = 6000;


var limiterRmsReleaseDefault = 320;
var rmsReleaseScaleMin = 5.0;
var rmsReleaseScaleMax = 10000;

var limiterPeakThresDefault = 15.0;
var peakThresScaleMin = 10;
// var peakThresScaleMax = 90;
var peakThresScaleMax = 180;

var limiterPeakReleaseDefault = 320.0;
var peakReleaseScaleMin = 5.0;
var peakReleaseScaleMax = 500;

var loadTable = [2.0, 2.7, 4, 8, 16, 70, 100];

var rmsThresScaleMinPreset = -17;
// var rmsThresScaleMaxPreset = -0.7;
// var rmsThresScaleMaxPreset = 5.3;
var rmsThresScaleMaxPreset = 11.0;
var peakThresScaleMinPreset = -21;
// var peakThresScaleMaxPreset = -1.9;
// var peakThresScaleMaxPreset = 4.1;
var peakThresScaleMaxPreset = 11.0;

// MANAGE SPEAKER PRESETS

var soloFolderSpeakerSelected = 0;
var soloFileSpeakerSelected = 0;

var speakerPresetExtension = ".cpspkr";
var speakerFolderPresetExtension = ".cpspkrfr";

var updateJsonFile = "";
var updateJsonName = "";
var updateJsonStatus = 0;
var downloadSpeakerPresetName = "";
var downloadFolderSpeakerPresetName = "";
//0 ko, 1 ok

// READBACK

var readBackSolo = new Array(4);
var overviewVuMeterHeight = 30;

var readBackLimiter = new Array(channelCount);

var readBackLimiterCount = 5
var subscribeEnable = true;
var subscribeEnableDelay = 1000;


var readbackChannel = "a";
var readbackUserRmsLim = "b";
var readbackUserPeakLim = "c";
var readbackSpeakerRmsLim = "d";
var readbackSpeakerPeakLim = "e";
var readbackAmpLim = "f";

var readbackModuleAmpOn = "g";
var readbackModuleTemp = "h";
var readbackModuleAveragePower = "i";
var readbackModuleOvertemp = "j"
var readbackModuleVoltage = "k"

// WEBSOCKET
var solofolderListSelected = 0;
var soloFileSpeakerSelected = 0;

var globalPresetCreateFolderAction = "Create Folder";
var globalPresetRenameFolderAction = "Rename Folder";
var globalPresetDeleteFolderAction = "Delete Folder";
var globalPresetDeleteFolderProtectedAction = "No Action";
var globalPresetUnlockPresetAction = "Unlock";

var globalPresetCreatePresetAction = "Create Preset";
var globalPresetEditPresetAction = "Save Preset";
var globalPresetRenamePresetAction = "Rename Preset";
var globalPresetSaveAsPresetAction = "Save As Preset";
var globalPresetDeletePresetAction = "Delete Preset";
var globalPresetDeletePresetProtectedAction = "No Action";
var globalPresetLoadPresetAction = "Load Preset";

var cmd_create_speaker_preset_file = "create_speaker_preset_file";
var cmd_upload_speaker_preset_file = "upload_speaker_preset_file";
var cmd_delete_speaker_preset_file = "delete_speaker_preset_file";
var cmd_edit_speaker_preset_file = "edit_speaker_preset_file";
var cmd_get_speaker_preset_file = "get_speaker_preset_file";
var cmd_set_speaker_preset_file = "set_speaker_preset_file";
var cmd_rename_speaker_preset_file = "rename_speaker_preset_file";
var cmd_create_speaker_preset_folder = "create_speaker_preset_folder";
var cmd_delete_speaker_preset_folder = "delete_speaker_preset_folder";
var cmd_rename_speaker_preset_folder = "rename_speaker_preset_folder";

//WARNING ONLY ONE MUTE
var cmd_get_speaker_mute = "get_solo_mute";
var cmd_get_speaker_gain = "get_speaker_gain";
var cmd_get_speaker_polarity = "get_speaker_polarity";
var cmd_get_speaker_delay_enable = "get_speaker_delay_enable";
var cmd_get_speaker_delay_value = "get_speaker_delay_value";
var cmd_get_speaker_peq_enable = "get_speaker_peq_enable";
var cmd_get_speaker_peq_type = "get_speaker_peq_type";
var cmd_get_speaker_peq_freq = "get_speaker_peq_freq";
var cmd_get_speaker_peq_gain = "get_speaker_peq_gain";
var cmd_get_speaker_peq_q = "get_speaker_peq_q";

var cmd_get_speaker_xover_hp_enable = "get_speaker_xover_hp_enable";
var cmd_get_speaker_xover_hp_type = "get_speaker_xover_hp_type";
var cmd_get_speaker_xover_hp_freq = "get_speaker_xover_hp_freq";
var cmd_get_speaker_xover_lp_enable = "get_speaker_xover_lp_enable";
var cmd_get_speaker_xover_lp_type = "get_speaker_xover_lp_type";
var cmd_get_speaker_xover_lp_freq = "get_speaker_xover_lp_freq";
var cmd_get_speaker_fir_table = "get_speaker_fir_table";

var cmd_get_speaker_lim_rms_thres = "get_speaker_lim_rms_thres";
var cmd_get_speaker_lim_rms_attack = "get_speaker_lim_rms_attack";
var cmd_get_speaker_lim_rms_release = "get_speaker_lim_rms_release";
var cmd_get_speaker_lim_peak_thres = "get_speaker_lim_peak_thres";
var cmd_get_speaker_lim_peak_release = "get_speaker_lim_peak_release";

var cmd_get_speaker_preset_folder_names = "get_speaker_preset_folder_names";
var cmd_get_speaker_preset_file_names = "get_speaker_preset_file_names";
var cmd_get_speaker_preset_list_names = "get_speaker_preset_list_names";

var cmd_get_speaker_preset_files_from_folder = "get_speaker_preset_files_from_folder"
var cmd_set_speaker_preset_files_from_folder = "set_speaker_preset_files_from_folder"

var cmd_set_speaker_mute = "set_solo_mute";
var cmd_set_speaker_gain = "set_speaker_gain";
var cmd_set_speaker_polarity = "set_speaker_polarity";
var cmd_set_speaker_delay_enable = "set_speaker_delay_enable";
var cmd_set_speaker_delay_value = "set_speaker_delay_value";
var cmd_set_speaker_peq_enable = "set_speaker_peq_enable";
var cmd_set_speaker_peq_type = "set_speaker_peq_type";
var cmd_set_speaker_peq_freq = "set_speaker_peq_freq";
var cmd_set_speaker_peq_gain = "set_speaker_peq_gain";
var cmd_set_speaker_peq_q = "set_speaker_peq_q";

var cmd_set_speaker_xover_hp_enable = "set_speaker_xover_hp_enable";
var cmd_set_speaker_xover_hp_freq = "set_speaker_xover_hp_freq";
var cmd_set_speaker_xover_hp_type = "set_speaker_xover_hp_type";
var cmd_set_speaker_xover_lp_enable = "set_speaker_xover_lp_enable";
var cmd_set_speaker_xover_lp_freq = "set_speaker_xover_lp_freq";
var cmd_set_speaker_xover_lp_type = "set_speaker_xover_lp_type";
var cmd_set_speaker_xover_hp_overide = "set_speaker_xover_hp_overide";
var cmd_set_speaker_xover_lp_overide = "set_speaker_xover_lp_overide";
var cmd_set_speaker_fir_table = "set_speaker_fir_table";

var cmd_set_speaker_lim_rms_thres = "set_speaker_lim_rms_thres";
var cmd_set_speaker_lim_rms_attack = "set_speaker_lim_rms_attack";
var cmd_set_speaker_lim_rms_release = "set_speaker_lim_rms_release";
var cmd_set_speaker_lim_peak_thres = "set_speaker_lim_peak_thres";
var cmd_set_speaker_lim_peak_release = "set_speaker_lim_peak_release";
var cmd_set_speaker_channel_source_pri = "set_speaker_channel_source_pri";
var cmd_set_speaker_channel_source_sec = "set_speaker_channel_source_sec";

var cmd_oem_get_status = "oem_get_status";
var cmd_oem_remove_code = "oem_remove_code";
var cmd_oem_check_code = "oem_check_code";
var cmd_oem_set_code = "oem_set_code";

var cmd_start_readback = "start_readback";
var cmd_stop_readback = "stop_readback";
var cmd_get_readback = "get_readback";

var cmd_get_json_data = "get_json_data";

var cmd_get_neighbour_list = "get_neighbour_list";
var cmd_set_clear_neighbour_list = "clear_neighbour_list";

var cmd_set_copy_speaker_parameters = "set_copy_speaker_parameters";

var ws = null;
var command = null;
var request_pool;
var lastCommands = null;

var ws_ip = "127.0.0.1";
var ws_port = "5678";

var loginLocal = 0;
var httpSecure = 0;

var subscriptionUpdate = 0;
var delayBetweenSubscriptionAfterUpdate = 5;
var delayBetweenCommands = 20;

var presetKey = "CPPresetKey";
var oemCodeUI = "";

function commandConstructor() {
    this.command = null;
    this.query_arg1 = null;
    this.query_arg2 = null;
    this.query_arg3 = null;
    this.query_arg4 = null;

    this.response_arg1 = null;
    this.response_arg2 = null;

    this.status = 0;
    this.query_time = Date.now();
    this.query_id = 0;
}

$.fn.getCommandFromArgs = function(command, arg1, arg2, arg3, arg4) {
    var temp_request = new commandConstructor();

    //SET COMMAND OBJECT PARAMETERS
    temp_request.command = command;
    temp_request.query_arg1 = arg1;
    temp_request.query_arg2 = arg2;
    temp_request.query_arg3 = arg3;
    temp_request.query_arg4 = arg4;
    if (command != cmd_get_readback)
        temp_request.query_id = $.fn.getRandomValue();
    else
        temp_request.query_id = 1;
    if (command != cmd_get_readback)
        temp_request.query_time = Date.now();
    else
        temp_request.query_time = 1;

    return temp_request;
}

$.fn.getRandomValue = function() {
    let ret = 0;
    let rnd = 0;
    rnd = Math.random();
    ret = Math.floor((Date.now() * (rnd * 463)) + (rnd * 569));
    return ret;
}

function commandsToJSON(cmdArray) {
    var ret = "";
    ret += "[";
    for (i = 0; i < cmdArray.length; i++) {
        ret += "{";
        ret += "\"command\":\"" + cmdArray[i].command + "\",";
        if (cmdArray[i].query_arg1 != "null")
            ret += "\"arg1\": " + cmdArray[i].query_arg1 + ",";
        if (cmdArray[i].query_arg2 != "null") {
            if (typeof(cmdArray[i].query_arg2) === 'string')
                ret += "\"arg2\": \"" + cmdArray[i].query_arg2 + "\",";
            else
                ret += "\"arg2\": " + cmdArray[i].query_arg2 + ",";
        }
        if (cmdArray[i].query_arg3 != "null")
            ret += "\"arg3\": " + cmdArray[i].query_arg3 + ",";
        if (cmdArray[i].query_arg4 != "null") {
            if (cmdArray[i].command === cmd_set_speaker_fir_table)
                ret += "\"arg4\": " + cmdArray[i].query_arg4 + ",";
            else if (typeof(cmdArray[i].query_arg4) === 'string' && cmdArray[i].command != "subscribe" && cmdArray[i].command != cmd_set_speaker_fir_table)
                ret += "\"arg4\": \"" + cmdArray[i].query_arg4 + "\",";
            else
                ret += "\"arg4\": " + cmdArray[i].query_arg4 + ",";
        }
        ret += "\"query_time\":" + cmdArray[i].query_id;
        ret += "}";
        if (i < cmdArray.length - 1)
            ret += ",";

        if (cmdArray[i].command === cmd_set_speaker_fir_table) {
            ret = ret.replace("[0,", "[0.0,");
            ret = ret.replaceAll(",0,", ",0.0,");
            ret = ret.replace(",0]", ",0.0]");
        }
    }
    ret += "]";

    return ret;
}

function loadFile(filePath) {
    var result = null;
    var xmlhttp = new XMLHttpRequest();
    xmlhttp.open("GET", filePath, false);
    xmlhttp.send();
    if (xmlhttp.status == 200) {
        result = xmlhttp.responseText;
        lines = result.split("\n");
        usernameHttp = lines[0];
        passwordHttp = lines[1];
    }
}

$.fn.createWebSocket = function() {
    if (demoMode === 0) {
        request_pool = new Array();
        //TO UNCOMMENT

        $.fn.poolMonitor();
        var href = $(location).attr("href");
        // console.log("href" + href);
        var r = /\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/;
        var t;
        if (href.match(r) != null) {
            //IP ADDRESS
            t = href.match(r);
            loginLocal = 1;
        } else {
            t = new Array(1);
            var x = 0;
            if (href.indexOf(".me/") >= 0) {
                x = href.indexOf(".me/");
                x = x + 3;
            } else
                x = href.length;
            t[0] = href.slice(7, x);
            httpSecure = 1;
        }
        //TEST IF SERVER IS AVAILABLE
        if (t) {
            // displayVal("location server", t[0]);
            if (t[0]) {
                ws_ip = t[0];
            }
            var ws_string = "ws://" + ws_ip + ":" + ws_port + "/";
            if (httpSecure === 1) {
                loadFile("id.txt");
                ws_string = "ws://" + usernameHttp + ":" + passwordHttp + "@" + ws_ip + ":" + ws_port + "/";
            }

            if (ws === null || ws.readyState === WebSocket.CLOSED) {
                // console.log("Creating new WS : " + ws_string);
                ws = new WebSocket(ws_string);

                ws.onmessage = function wsOnMessage(event) {
                    // console.log("msg ws");
                    $.fn.receiveCommandWS(event);
                    return false;
                };

                ws.onopen = function wsOnOpen(event) {
                    $.fn.sendCommandWS(cmd_oem_get_status, "null", "null", "null", "null");
                    $("#iconEthernet").attr("src", "./img/ethernet_hover.png");
                };

                ws.onerror = function(event) {
                    // console.log("error ws");
                    setTimeout(function() {
                        $("#iconEthernet").attr("src", "./img/ethernet_fail.png");
                        $("#mainLoader").addClass("is-active");
                        $.fn.createWebSocket();
                    }, 2000);
                };

                ws.onclose = function(e) {
                    // console.log("onclose ws");
                    setTimeout(function() {
                        $("#iconEthernet").attr("src", "./img/ethernet_fail.png");
                        $("#mainLoader").addClass("is-active");
                        $.fn.createWebSocket();
                    }, 2000);
                };
            }
        }
    } else
        console.log("Demo mode : no server needed");
}

$.fn.sendStringWS = function(command, arg1, arg2, arg3, arg4) {
    var temp_timestamp = 0;
    var temp_request = new commandConstructor();
    //SET COMMAND OBJECT PARAMETERS
    temp_request.command = command;
    temp_request.query_arg1 = arg1;
    temp_request.query_arg2 = arg2;
    temp_request.query_arg3 = arg3;
    temp_request.query_arg4 = arg4;

    //SET THE query_time TO RANDOMLY GENERATE TIMESTAMP
    temp_request.query_time = Date.now();
    temp_request.query_id = $.fn.getRandomValue();
    var send_text = stringsToJSON(temp_request);
    // console.log(send_text);
    $.fn.sendWebSocketData(send_text);
}

function stringsToJSON(cmd) {
    var ret = "";
    ret += "[";
    ret += "{";
    ret += "\"command\":\"" + cmd.command + "\",";
    if (cmd.query_arg1 != "null")
        ret += "\"arg1\":" + cmd.query_arg1 + ",";
    if (cmd.query_arg2 != "null")
        ret += "\"arg2\":\"" + cmd.query_arg2 + "\",";
    if (cmd.query_arg3 != "null")
        ret += "\"arg3\":" + cmd.query_arg3 + ",";
    if (cmd.query_arg4 != "null")
        ret += "\"arg4\":\"" + cmd.query_arg4 + "\",";
    ret += "\"query_time\":" + cmd.query_id;
    ret += "}";
    ret += "]";
    // console.log("RET:" + ret)
    return ret;
}

$.fn.sendWebSocketData = function(data) {
    if (data.toString().indexOf("readback") === -1 && data.toString().indexOf("neighbour") === -1 && data.toString().indexOf("get_solo_channel_name") === -1 && data.toString().indexOf("subscribe") === -1 && data.toString().indexOf("names") === -1 && data.toString().indexOf("\"arg1\": 0") > -1 && data.toString().indexOf(cmd_set_speaker_preset_file) === -1)
        subscriptionUpdate = delayBetweenSubscriptionAfterUpdate;
    if (ws) {
        try {
            // console.log(data);
            ws.send(data);
            return 0;
        } catch (err) {
            console.log("WS Send Error : " + err);
            return -1;
        }
    }
}

$.fn.sendCommandWS = function(command, arg1, arg2, arg3, arg4) {
    var arrayCmd = new Array(1);
    arrayCmd[0] = $.fn.getCommandFromArgs(command, arg1, arg2, arg3, arg4);
    $.fn.sendCommandsWS(arrayCmd);
}

$.fn.sendCommandsWS = function(arrayCmd) {
    if (lastCommands != null) {
        //IF COMMAND SEND MORE THAN "delayBetweenCommands" MS BEFORE
        if (Math.abs(arrayCmd[0].query_time - lastCommands[0].query_time) > delayBetweenCommands) {
            lastCommands = arrayCmd;
            var send_text = commandsToJSON(arrayCmd);
            if ($.fn.sendWebSocketData(send_text) === 0) {
                for (var i = 0; i < arrayCmd.length; i++) {
                    if (i > -1) {
                        arrayCmd[i].status = 1;
                    }
                    if (arrayCmd[i].command != cmd_get_readback)
                        request_pool.push(arrayCmd[i]);
                }
            }
        } else {
            // console.log("command too close : " + arrayCmd[0].command);
            lastCommands = arrayCmd;
            Singletons.getCountdown().time = delayBetweenCommands + 1;
            if (Singletons.getCountdown().enable === false)
                $.fn.sendLastCommands();
        }
    } else {
        lastCommands = arrayCmd;
        //IF FIRST SENT COMMAND, SEND IT 
        var send_text = commandsToJSON(arrayCmd);
        if ($.fn.sendWebSocketData(send_text) === 0) {
            for (var i = 0; i < arrayCmd.length; i++) {
                if (i > -1) {
                    arrayCmd[i].status = 1;
                }
                if (arrayCmd[i].command != cmd_get_readback)
                    request_pool.push(arrayCmd[i]);
            }
        }
    }
}

$.fn.sendLastCommands = function() {
    if (Singletons.getCountdown().time > 0) {
        Singletons.getCountdown().enable = true;
        Singletons.getCountdown().time = Singletons.getCountdown().time - 5;
        setTimeout($.fn.sendLastCommands, 5);
    } else {
        // console.log("send last command : " + lastCommands.toString());
        var send_text = commandsToJSON(lastCommands);
        if ($.fn.sendWebSocketData(send_text) === 0) {
            for (var i = 0; i < lastCommands.length; i++) {
                if (i > -1) {
                    lastCommands[i].status = 1;
                }
                request_pool.push(lastCommands[i]);
            }
        }
        Singletons.getCountdown().enable = false;
    }
}

//CREATE UNIQUE COUNTDOWN FOR LAST COMMAND SEND
var Singletons = (function() {
    var countdown;

    function createCountdown() {
        var cd = new Object();
        cd.time = 0;
        cd.enable = false;
        return cd;
    }

    return {
        getCountdown: function() {
            if (!countdown) {
                countdown = createCountdown();
            }
            return countdown;
        }
    };
})();

function findWithAttr(array, attr, value, cmd) {
    let ret = -1;
    let tmp = 0;
    let retCount = 0;
    let tmp2 = -1;
    for (var i = 0; i < array.length; i++) {
        if (array[i][attr] === parseInt(value)) {
            tmp++;
            tmp2 = i;
        }
        if (array[i][attr] === parseInt(value) && array[i].command === cmd) {
            ret = i;
            retCount++;
        }
    }
    // console.log("Same commands : " + tmp + " // retCount : " + retCount);
    if (ret === -1 && tmp2 != -1) {

        console.log("Same commands : " + tmp + " // retCount : " + retCount + " // cmd : " + cmd + " // COMMAND : " + array[tmp2].toString() + " // CURRENT TIMESTAMP : " + value);
    }
    return ret;
}

function findNameWithinArray(array, value) {
    var ret = -1;
    for (var i = 0; i < array.length; i++) {
        if (array[i].name === value)
            ret = i;
    }
    return ret;
}

$.fn.poolMonitor = function() {
    if (request_pool.length > 0) {
        var deleteArray = new Array();
        for (var i = 0; i < request_pool.length; i++) {
            switch (parseInt(request_pool[i].status)) {
                case 0:
                    break;
                case 1:
                    request_pool[i].status = 2;
                    break;
                case 2:
                    request_pool[i].status = 3;
                    break;
                case 3:
                    deleteArray.push(i);
                    break;
                case 4: //SEND COMMAND
                    request_pool[i].status = 7;
                    break;
                case 5:
                    request_pool[i].status = 7;
                    break;
                case 6: //SEND COMMAND
                    request_pool[i].status = 7;

                    break;
                case 7:
                    deleteArray.push(i);
                    break;
                default:
                    break;
            }
        }
        for (var j = 0; j < deleteArray.length; j++) {
            request_pool.splice(deleteArray[j], 1);
        }
    }
    setTimeout(function() { $.fn.poolMonitor() }, poolMonitorDelay);
}

function download(content, fileName, contentType) {
    const a = document.createElement("a");
    var ciphertext = CryptoJS.AES.encrypt(content, presetKey);
    const file = new Blob([ciphertext], { type: contentType });
    a.href = URL.createObjectURL(file);
    a.download = fileName;
    a.click();
}

function compareWords(a, b) {
    if (a.file_name.toLowerCase() < b.file_name.toLowerCase()) {
        return -1;
    } else {
        return 1;
    }
}

$.fn.receiveCommandWS = function(event) {
    var msg = null;
    var i = -1;
    //TEST IF JSON RESPONSE IS A VALID JSON FILE
    // if (event.data === "") {
    try {
        if (event.data != "JSON is not valid.") {
            // console.log("MESSAGE:" + event.data);
            msg = JSON.parse(event.data);
            if (msg) {
                // console.log("message length:" + msg.length);
                // console.log(msg);
                i = -1
                var msgR = JSON.parse(event.data)
                    //IF MESSAGE IS AN ANSWER FROM THE UI INTERFACE
                if (parseInt(msgR.query_time) > 0) {
                    // console.log(msg.query_time);
                    if (msgR.command != cmd_get_readback && msgR.command != cmd_get_neighbour_list && msgR.command != cmd_get_json_data)
                        i = findWithAttr(request_pool, "query_id", msgR.query_time, msgR.command);
                    // console.log("Amount of same command : " + i);
                    //IF WE FOUND THE RELATED COMMAND, CHANGE STATUS TO "finish"
                    if (i > -1) {
                        index_msg = i;
                        request_pool[i].response_arg1 = msgR.arg1;
                        request_pool[i].response_arg2 = msgR.arg2;
                    }
                }
                switch (msgR.command) {
                    //TO UPDATE TO cmd_get_readback
                    case cmd_get_readback:
                        if (msgR.arg2) {
                            var temp = JSON.parse(msgR.arg2);
                            if (temp) {
                                //READBACK LEVEL
                                // readBackSolo[0] = parseFloat(temp.channel1.toFixed(2)) + globalDbScaleFactor;
                                // readBackSolo[1] = parseFloat(temp.channel2.toFixed(2)) + globalDbScaleFactor;
                                // readBackSolo[2] = parseFloat(temp.channel3.toFixed(2)) + globalDbScaleFactor;
                                // readBackSolo[3] = parseFloat(temp.channel4.toFixed(2)) + globalDbScaleFactor;

                                for (var a = 0; a < channelCount; a++) {
                                    //READBACK LEVEL
                                    readBackSolo[a] = parseFloat(temp[readbackChannel + (a + 1)]) + globalDbScaleFactor;

                                    //CHANNEL LIMITERS
                                    readBackLimiter[a][0] = parseFloat(temp[readbackUserRmsLim + (a + 1)]);
                                    readBackLimiter[a][1] = parseFloat(temp[readbackUserPeakLim + (a + 1)]);
                                    readBackLimiter[a][2] = parseFloat(temp[readbackSpeakerRmsLim + (a + 1)]);
                                    readBackLimiter[a][3] = parseFloat(temp[readbackSpeakerPeakLim + (a + 1)]);
                                    readBackLimiter[a][4] = parseFloat(temp[readbackAmpLim + (a + 1)]);
                                    // readBackLimiter[a][0] = parseFloat(temp["user_rms_lim" + (a + 1)].toFixed(2));
                                    // readBackLimiter[a][1] = parseFloat(temp["user_peak_lim" + (a + 1)].toFixed(2));
                                    // readBackLimiter[a][2] = parseFloat(temp["speaker_rms_lim" + (a + 1)].toFixed(2));
                                    // readBackLimiter[a][3] = parseFloat(temp["speaker_peak_lim" + (a + 1)].toFixed(2));
                                    // readBackLimiter[a][4] = parseFloat(temp["amp_lim" + (a + 1)].toFixed(2));
                                }
                            }
                            $.fn.drawRefreshedData();
                        }
                        break;

                    case cmd_oem_check_code:
                        if (msgR.arg1 === "OK") {
                            oemCodeUI = $("#loginEmail").val();
                            $("#loginPanel").removeClass("is-active");
                            $.fn.loadDataFromAmp();
                            setTimeout(function() {
                                $("#mainLoader").removeClass("is-active");
                            }, 4000);
                        } else {
                            updateJsonFile = "";
                            updateJsonStatus = 0;
                            $("#speakerUploadFileStatus").html("<div class=\"status dead\"></div>Unable to load OEM preset : wrong OEM code ");
                            $("#loginEmail").val("Wrong Code");
                            setTimeout(function() {
                                $("#loginEmail").val("");
                            }, 5000);
                        }
                        break;

                    case cmd_oem_get_status:
                        if (msgR.arg2) {
                            // var temp = JSON.parse(msgR.arg2);
                            var temp = msgR.arg2;
                            if (temp.oem_code_enable === false) {
                                oemCodeUI = "0000000000";
                                // oemCodeUI = $("#loginEmail").val();
                                setTimeout(function() {
                                    $.fn.loadDataFromAmp();
                                    $("#mainLoader").removeClass("is-active");
                                }, 1000);
                            } else {
                                $("#loginPanel").addClass("is-active");
                            }
                        }
                        break;

                    case cmd_get_speaker_mute:
                        if (i > -1) {
                            localAmplifier.channel[request_pool[i].query_arg2].gain.muteEna = Boolean(request_pool[i].response_arg2);
                            $.fn.setDataSoloGain(request_pool[i].query_arg2, 99);
                        }
                        break;

                    case cmd_set_speaker_mute:
                        if (i > -1) {}
                        break;

                    case cmd_get_speaker_gain:
                        if (i > -1) {
                            localAmplifier.channel[request_pool[i].query_arg2].gain.gain = parseFloat(parseFloat(request_pool[i].response_arg2).toFixed(1));
                            $.fn.setDataSoloGain(request_pool[i].query_arg2, 99);
                        }
                        break;

                    case cmd_set_speaker_gain:
                        break;

                    case cmd_get_speaker_polarity:
                        if (i > -1) {
                            if (request_pool[i].response_arg2 === false)
                                localAmplifier.channel[request_pool[i].query_arg2].gain.polarityEna = false;
                            else
                                localAmplifier.channel[request_pool[i].query_arg2].gain.polarityEna = true;
                            $.fn.setDataSoloGain(request_pool[i].query_arg2, 99);
                        }
                        break;

                    case cmd_set_speaker_polarity:
                        break;

                    case cmd_get_speaker_delay_enable:
                        if (i > -1) {
                            if (request_pool[i].response_arg2 === false)
                                localAmplifier.channel[request_pool[i].query_arg2].delay.delayEna = false;
                            else
                                localAmplifier.channel[request_pool[i].query_arg2].delay.delayEna = true;
                            $.fn.setDataSoloDelay(99);
                        }
                        break;

                    case cmd_set_speaker_delay_enable:
                        break;

                    case cmd_get_speaker_delay_value:
                        if (i > -1) {
                            localAmplifier.channel[request_pool[i].query_arg2].delay.delay = parseFloat(request_pool[i].response_arg2.toFixed(2));
                            $.fn.setDataSoloDelay(99);
                        }
                        break;

                    case cmd_set_speaker_delay_value:
                        break;

                    case cmd_get_speaker_peq_enable:
                        if (i > -1) {
                            if (request_pool[i].response_arg2 === false)
                                localAmplifier.channel[request_pool[i].query_arg2].peq.peq[request_pool[i].query_arg3].ena = false;
                            else
                                localAmplifier.channel[request_pool[i].query_arg2].peq.peq[request_pool[i].query_arg3].ena = true;
                            $.fn.setDataSoloPEQ(99, 99);
                        }
                        break;

                    case cmd_set_speaker_peq_enable:
                        break;

                    case cmd_get_speaker_peq_type:
                        if (i > -1) {
                            localAmplifier.channel[request_pool[i].query_arg2].peq.peq[request_pool[i].query_arg3].type = parseInt(request_pool[i].response_arg2);
                            $.fn.setDataSoloPEQ(99, 99);
                        }
                        break;

                    case cmd_set_speaker_peq_type:
                        break;

                    case cmd_get_speaker_peq_freq:
                        if (i > -1) {
                            localAmplifier.channel[request_pool[i].query_arg2].peq.peq[request_pool[i].query_arg3].frequency = parseInt(request_pool[i].response_arg2);
                            $.fn.setDataSoloPEQ(99, 99);
                        }
                        break;

                    case cmd_set_speaker_peq_freq:
                        break;

                    case cmd_get_speaker_peq_gain:
                        if (i > -1) {
                            localAmplifier.channel[request_pool[i].query_arg2].peq.peq[request_pool[i].query_arg3].gain = parseFloat(request_pool[i].response_arg2.toFixed(1));
                            $.fn.setDataSoloPEQ(99, 99);
                        }
                        break;

                    case cmd_set_speaker_peq_gain:
                        break;

                    case cmd_get_speaker_peq_q:
                        if (i > -1) {
                            localAmplifier.channel[request_pool[i].query_arg2].peq.peq[request_pool[i].query_arg3].q = parseFloat(request_pool[i].response_arg2.toFixed(2));
                            $.fn.setDataSoloPEQ(99, 99);
                        }
                        break;

                    case cmd_set_speaker_peq_q:
                        break;

                    case cmd_get_speaker_xover_hp_enable:
                        if (i > -1) {
                            if (request_pool[i].response_arg2 === false)
                                localAmplifier.channel[request_pool[i].query_arg2].xover.hpEna = false;
                            else
                                localAmplifier.channel[request_pool[i].query_arg2].xover.hpEna = true;
                            $.fn.setDataSoloXover(2, 99);
                        }
                        break;

                    case cmd_set_speaker_xover_hp_enable:
                        break;

                    case cmd_get_speaker_xover_hp_type:
                        if (i > -1) {
                            localAmplifier.channel[request_pool[i].query_arg2].xover.hpType = parseInt(request_pool[i].response_arg2);
                            $.fn.setDataSoloXover(2, 99);
                        }
                        break;

                    case cmd_set_speaker_xover_hp_type:
                        break;

                    case cmd_get_speaker_xover_hp_freq:
                        if (i > -1) {
                            localAmplifier.channel[request_pool[i].query_arg2].xover.hpFreq = parseInt(request_pool[i].response_arg2);
                            $.fn.setDataSoloXover(2, 99);
                        }
                        break;

                    case cmd_set_speaker_xover_hp_freq:
                        break;

                    case cmd_get_speaker_xover_lp_enable:
                        if (i > -1) {
                            if (request_pool[i].response_arg2 === false)
                                localAmplifier.channel[request_pool[i].query_arg2].xover.lpEna = false;
                            else
                                localAmplifier.channel[request_pool[i].query_arg2].xover.lpEna = true;
                            $.fn.setDataSoloXover(3, 99);
                        }
                        break;

                    case cmd_set_speaker_xover_lp_enable:
                        break;

                    case cmd_get_speaker_xover_lp_type:
                        if (i > -1) {
                            localAmplifier.channel[request_pool[i].query_arg2].xover.lpType = parseInt(request_pool[i].response_arg2);
                            $.fn.setDataSoloXover(3, 99);
                        }
                        break;

                    case cmd_set_speaker_xover_lp_type:
                        break;

                    case cmd_get_speaker_xover_lp_freq:
                        if (i > -1) {
                            localAmplifier.channel[request_pool[i].query_arg2].xover.lpFreq = parseInt(request_pool[i].response_arg2);
                            $.fn.setDataSoloXover(3, 99);
                        }
                        break;

                    case cmd_set_speaker_xover_lp_freq:
                        break;

                    case cmd_get_speaker_fir_table:
                        if (i > -1) {
                            localAmplifier.channel[request_pool[i].query_arg2].fir.firCoeff = request_pool[i].response_arg2;
                            $.fn.setDataSoloXover(9, request_pool[i].query_arg2);
                        }
                        break;

                    case cmd_set_speaker_fir_table:
                        break;

                    case cmd_get_speaker_lim_rms_thres:
                        if (i > -1) {
                            localAmplifier.channel[request_pool[i].query_arg2].limiter.rmsThres = getThresholdInVolt(parseFloat(request_pool[i].response_arg2.toFixed(1)), 0);
                            if (localAmplifier.channel[request_pool[i].query_arg2].limiter.rmsThres > clearLimRmsThresValue)
                                localAmplifier.channel[request_pool[i].query_arg2].limiter.rmsThres = clearLimRmsThresValue;
                            $.fn.setDataSoloLimiter(1, 99);
                        }
                        break;

                    case cmd_set_speaker_lim_rms_thres:
                        break;

                    case cmd_get_speaker_lim_rms_attack:
                        if (i > -1) {
                            localAmplifier.channel[request_pool[i].query_arg2].limiter.rmsAttack = parseFloat(request_pool[i].response_arg2.toFixed(1));
                            $.fn.setDataSoloLimiter(1, 99);
                        }
                        break;

                    case cmd_set_speaker_lim_rms_attack:
                        break;

                    case cmd_get_speaker_lim_rms_release:
                        if (i > -1) {
                            localAmplifier.channel[request_pool[i].query_arg2].limiter.rmsRelease = parseFloat(request_pool[i].response_arg2.toFixed(1));
                            $.fn.setDataSoloLimiter(1, 99);
                        }
                        break;

                    case cmd_set_speaker_lim_rms_release:
                        break;

                    case cmd_get_speaker_lim_peak_thres:
                        if (i > -1) {
                            localAmplifier.channel[request_pool[i].query_arg2].limiter.peakThres = getThresholdInVolt(parseFloat(request_pool[i].response_arg2.toFixed(1)), 1);
                            if (localAmplifier.channel[request_pool[i].query_arg2].limiter.peakThres > clearLimPeakThresValue)
                                localAmplifier.channel[request_pool[i].query_arg2].limiter.peakThres = clearLimPeakThresValue;
                            $.fn.setDataSoloLimiter(1, 99);
                        }
                        break;

                    case cmd_set_speaker_lim_peak_thres:
                        break;

                    case cmd_get_speaker_lim_peak_release:
                        if (i > -1) {
                            localAmplifier.channel[request_pool[i].query_arg2].limiter.peakRelease = parseFloat(request_pool[i].response_arg2.toFixed(1));
                            $.fn.setDataSoloLimiter(1, 99);
                        }
                        break;

                    case cmd_set_speaker_lim_peak_release:
                        break;

                    case cmd_get_speaker_preset_folder_names:
                        var folders = msgR.arg2;
                        var tempFolders = new foldersConstructor(folders.length);
                        for (var a = 0; a < folders.length; a++) {
                            tempFolders.folderList[a].name = folders[a];
                        }
                        localAmplifier.folderSpeaker = tempFolders;
                        localAmplifier.folderSpeaker.folderCount = folders.length;
                        // $.fn.setDataSoloSpeaker(100);
                        $.fn.setDataSoloSpeaker(101);
                        // }
                        break;

                    case cmd_get_speaker_preset_file_names:
                        if (i > -1) {
                            var files = request_pool[i].response_arg2;
                            var tempFiles = new Array(files.length);
                            for (var b = 0; b < files.length; b++) {
                                tempFiles[b] = new fileConstructor(b);
                                tempFiles[b].file_name = files[b];
                            }
                            var foldIndex = findNameWithinArray(localAmplifier.folderSpeaker.folderList, request_pool[i].query_arg2);
                            if (foldIndex > -1) {
                                localAmplifier.folderSpeaker.folderList[foldIndex].fileList = tempFiles;
                                localAmplifier.folderSpeaker.folderList[foldIndex].fileCount = files.length;
                                $.fn.setDataSoloSpeaker(100);
                            }
                        }
                        break;

                    case cmd_get_speaker_preset_file:
                        var name = "preset";
                        if (downloadSpeakerPresetName != "")
                            name = downloadSpeakerPresetName;
                        downloadSpeakerPresetName = "";
                        download(JSON.stringify(msgR.arg2), name + speakerPresetExtension, "text/plain");
                        break;

                    case cmd_get_speaker_preset_files_from_folder:
                        var name = "preset";
                        if (downloadFolderSpeakerPresetName != "")
                            name = downloadFolderSpeakerPresetName;
                        downloadFolderSpeakerPresetName = "";
                        download(JSON.stringify(msgR.arg2), name + speakerFolderPresetExtension, "text/plain");
                        break;

                    case cmd_get_speaker_preset_list_names:
                        // console.log(JSON.stringify(msgR.arg2));
                        var preset_list = msgR.arg2;
                        var tempFolders = new foldersConstructor(preset_list.length);
                        for (var a = 0; a < preset_list.length; a++) {
                            tempFolders.folderList[a].name = preset_list[a]["folder_name"];
                        }
                        console.log("folder_list_count = " + preset_list.length)
                        localAmplifier.folderSpeaker = tempFolders;
                        localAmplifier.folderSpeaker.folderCount = preset_list.length;

                        for (var a = 0; a < preset_list.length; a++) {
                            var tempFiles = new Array(preset_list[a]["files"].length);
                            for (var b = 0; b < preset_list[a]["files"].length; b++) {
                                tempFiles[b] = new fileConstructor(b);
                                tempFiles[b].file_name = preset_list[a]["files"][b].file_name;
                                tempFiles[b].author = preset_list[a]["files"][b].author;
                                tempFiles[b].version = preset_list[a]["files"][b].version;
                                tempFiles[b].note = preset_list[a]["files"][b].note;
                                tempFiles[b].oem = preset_list[a]["files"][b].oem;
                            }
                            tempFiles = tempFiles.sort(compareWords);
                            localAmplifier.folderSpeaker.folderList[a].fileList = tempFiles;
                            localAmplifier.folderSpeaker.folderList[a].fileCount = preset_list[a]["files"].length;
                        }

                        $.fn.setDataSoloSpeaker(100);
                        break;

                    case cmd_get_neighbour_list:
                        try {
                            var files = JSON.parse(msgR.arg2);
                            if (discoveryList.length < 1) {
                                discoveryList = new Array(files.length);
                                for (var c = 0; c < files.length; c++) {
                                    discoveryList[c] = new discoveredAmpConstructor(files[c]);
                                }
                            } else if (discoveryList.length != files.length) {
                                for (var d = 0; d < (files.length - discoveryList.length); d++) {
                                    discoveryList.push(new discoveredAmpConstructor(files[discoveryList.length + d]));
                                }
                            } else if (discoveryList.length === files.length) {
                                for (var e = 0; e < discoveryList.length; e++) {
                                    if (discoveryList[e].desc != files[e].desc && e > 0) {
                                        discoveryList[e].desc = files[e].desc;
                                        let idDest1 = "#assignGroupTabAmpName" + e;
                                        let idDest2 = "#groupAssignAmpSelectedName";
                                        if ($(idDest1))
                                            $(idDest1).html(discoveryList[e].desc);
                                        if (0 === e) {
                                            $(idDest2).html(discoveryList[e].desc);
                                            // $.fn.setupGroupAssign();
                                        }
                                    }
                                    discoveryList[e].hw_addr = files[e].hw_addr;
                                    if (discoveryList[e].ip_addr != files[e].ip_addr) {
                                        let idDest3 = "#dldcds" + e;
                                        discoveryList[e].ip_addr = files[e].ip_addr;
                                        if ($(idDest3))
                                            $(idDest3).html(discoveryList[e].ip_addr);
                                    }

                                    discoveryList[e].alive = files[e].alive;
                                    discoveryList[e].last_report_time = files[e].last_report_time;
                                    discoveryList[e].model = files[e].model;
                                    discoveryList[e].cloud_device_name = files[e].cloud_device_name;
                                }
                            }
                            $.fn.setDiscoverySource();
                            $.fn.runAfterFirstDiscovery();

                        } catch {
                            console.log("Fail to parse get_neighbour_list");
                        }
                        break;

                    case cmd_set_speaker_preset_file:
                        // console.log(cmd_set_speaker_preset_file + " return value " + msgR.arg1 + " index " + i);
                        if (msgR.arg1 === "OK") {
                            setTimeout(function() {
                                $("#presetLoader").removeClass("is-active");
                                $.fn.clearDataCheck();
                            }, 5000);
                        } else {
                            $("#presetLoader").removeClass("is-active");
                            alert("Preset loading error. Please try again !");
                        }
                        // }
                        break;

                    case cmd_create_speaker_preset_file:
                        if (msgR.arg1 === "OK") {
                            $.fn.sendCommandWS(cmd_get_speaker_preset_list_names, 0, "null", "null", "null");
                        }
                        break;
                    case cmd_upload_speaker_preset_file:
                        if (msgR.arg1 === "OK") {
                            $("#presetUploader").removeClass("is-active");
                            $.fn.sendCommandWS(cmd_get_speaker_preset_list_names, 0, "null", "null", "null");
                        }
                        break;

                    case cmd_set_speaker_preset_files_from_folder:
                        if (msgR.arg1 === "OK") {
                            $("#presetUploader").removeClass("is-active");
                            $.fn.sendCommandWS(cmd_get_speaker_preset_list_names, 0, "null", "null", "null");
                        } else {
                            $("#presetUploader").removeClass("is-active");
                            alert("Preset name already exist in folder !");
                        }
                        break;


                    case cmd_get_json_data:
                        if (subscriptionUpdate === 0) {
                            var jsonObj = JSON.parse(msgR.arg2);
                            //CHANNELS PARAMETERS
                            for (var t = 0; t < channelCount; t++) {




                                // GAIN
                                if (localAmplifier.channel[t].gain.gain != parseFloat(parseFloat(jsonObj[16][t].gain).toFixed(1)) || localAmplifier.channel[t].gain.polarityEna != jsonObj[16][t].polarity || localAmplifier.channel[t].gain.muteEna != jsonObj[t]) {
                                    localAmplifier.channel[t].gain.gain = parseFloat(parseFloat(jsonObj[16][t].gain).toFixed(1));
                                    localAmplifier.channel[t].gain.polarityEna = jsonObj[16][t].polarity;
                                    localAmplifier.channel[t].gain.muteEna = jsonObj[t];
                                    // if (t === soloChannelSelected)
                                    $.fn.setDataSoloGainUpdate(t);
                                    // console.log("UPDATE GAIN FROM SUBSCRITPION");
                                }

                                // DELAY
                                if (localAmplifier.channel[t].delay.delay != parseFloat(parseFloat(jsonObj[16][t].delay_value).toFixed(2)) || localAmplifier.channel[t].delay.delayEna != jsonObj[16][t].delay_enable) {
                                    localAmplifier.channel[t].delay.delay = parseFloat(parseFloat(jsonObj[16][t].delay_value).toFixed(2));
                                    localAmplifier.channel[t].delay.delayEna = jsonObj[16][t].delay_enable;
                                    if (t === soloChannelSelected)
                                        $.fn.setDataSoloDelayUpdate(t);
                                    // console.log("UPDATE DELAY FROM SUBSCRITPION");
                                }

                                // PEQ
                                var updatePEQ = 0;
                                for (var u = 0; u < peqCount; u++) {
                                    updatePEQ = 0;
                                    // PEQ ENABLE
                                    if (localAmplifier.channel[t].peq.peq[u].ena != jsonObj[16][t].peq[u].enable) {
                                        localAmplifier.channel[t].peq.peq[u].ena = jsonObj[16][t].peq[u].enable;
                                        updatePEQ++;
                                    }

                                    // PEQ TYPE
                                    if (localAmplifier.channel[t].peq.peq[u].type != jsonObj[16][t].peq[u].type) {
                                        localAmplifier.channel[t].peq.peq[u].type = jsonObj[16][t].peq[u].type;
                                        updatePEQ++;
                                    }

                                    // PEQ FREQ
                                    if (localAmplifier.channel[t].peq.peq[u].frequency != jsonObj[16][t].peq[u].freq) {
                                        localAmplifier.channel[t].peq.peq[u].frequency = jsonObj[16][t].peq[u].freq;
                                        updatePEQ++;
                                    }

                                    // PEQ GAIN
                                    if (localAmplifier.channel[t].peq.peq[u].gain != jsonObj[16][t].peq[u].gain) {
                                        localAmplifier.channel[t].peq.peq[u].gain = jsonObj[16][t].peq[u].gain;
                                        updatePEQ++;
                                    }

                                    // PEQ Q
                                    if (localAmplifier.channel[t].peq.peq[u].q != jsonObj[16][t].peq[u].q) {
                                        localAmplifier.channel[t].peq.peq[u].q = jsonObj[16][t].peq[u].q;
                                        updatePEQ++;
                                    }

                                    if (updatePEQ > 0 && $("#peqMainPanel").is(":visible"))
                                        if (t === soloChannelSelected)
                                            $.fn.setDataSoloPEQUpdate(u);
                                }

                                // let xoverGraphRefresh = 0;
                                // XOVER HIGHPASS
                                if (localAmplifier.channel[t].xover.hpType != parseInt(jsonObj[16][t].xover_hp_filter.xover_hp_type) || localAmplifier.channel[t].xover.hpEna != jsonObj[16][t].xover_hp_filter.xover_hp_enable || localAmplifier.channel[t].xover.hpFreq != parseInt(jsonObj[16][t].xover_hp_filter.xover_hp_freq) || localAmplifier.channel[t].xover.hpSpeakerPresetOveride != jsonObj[16][t].xover_hp_filter.xover_hp_overide) {
                                    localAmplifier.channel[t].xover.hpType = parseInt(jsonObj[16][t].xover_hp_filter.xover_hp_type);
                                    localAmplifier.channel[t].xover.hpEna = jsonObj[16][t].xover_hp_filter.xover_hp_enable;
                                    localAmplifier.channel[t].xover.hpFreq = parseInt(jsonObj[16][t].xover_hp_filter.xover_hp_freq);
                                    localAmplifier.channel[t].xover.hpSpeakerPresetOveride = jsonObj[16][t].xover_hp_filter.xover_hp_overide;
                                    if (t === soloChannelSelected) {
                                        $.fn.setDataSoloXoverUpdateHP();
                                        $.fn.draggieXOVERSetPosition(0);
                                        // xoverGraphRefresh = 1;
                                    }
                                    // if (t === soloChannelSelected)
                                    //     $.fn.draggieXOVERSetPosition(0);
                                    // console.log("UPDATE XOVER HP FROM SUBSCRITPION");
                                }


                                // XOVER LOWPASS
                                if (localAmplifier.channel[t].xover.lpType != parseInt(jsonObj[16][t].xover_lp_filter.xover_lp_type) || localAmplifier.channel[t].xover.lpEna != jsonObj[16][t].xover_lp_filter.xover_lp_enable || localAmplifier.channel[t].xover.lpFreq != parseInt(jsonObj[16][t].xover_lp_filter.xover_lp_freq) || localAmplifier.channel[t].xover.lpSpeakerPresetOveride != jsonObj[16][t].xover_lp_filter.xover_lp_overide) {
                                    localAmplifier.channel[t].xover.lpType = parseInt(jsonObj[16][t].xover_lp_filter.xover_lp_type);
                                    localAmplifier.channel[t].xover.lpEna = jsonObj[16][t].xover_lp_filter.xover_lp_enable;
                                    localAmplifier.channel[t].xover.lpFreq = parseInt(jsonObj[16][t].xover_lp_filter.xover_lp_freq);
                                    localAmplifier.channel[t].xover.lpSpeakerPresetOveride = jsonObj[16][t].xover_lp_filter.xover_lp_overide;
                                    if (t === soloChannelSelected) {
                                        $.fn.setDataSoloXoverUpdateLP();
                                        $.fn.draggieXOVERSetPosition(1);
                                        // xoverGraphRefresh = 1;
                                    }
                                    // if (t === soloChannelSelected)
                                    //     $.fn.draggieXOVERSetPosition(1);
                                    // console.log("UPDATE XOVER LP FROM SUBSCRITPION");
                                }

                                // if (xoverGraphRefresh === 1 && t === soloChannelSelected) {
                                //     $.fn.setDataSoloPEQ(t, 99);
                                //     $.fn.setDataSoloXover(4, 99);
                                // }

                                // XOVER FIR COEFFICIENTS
                                var tempFir = new Array();
                                for (var r = 0; r < jsonObj[16][t].fir_table.length; r++) {
                                    tempFir.push(jsonObj[16][t].fir_table[r]);
                                }
                                if (!$.fn.firIsEqual(localAmplifier.channel[t].fir.firCoeff, tempFir)) {
                                    localAmplifier.channel[t].fir.firCoeff = tempFir;
                                    if ($.fn.firIsEqual(localAmplifier.channel[t].fir.firCoeff, clearFirTable)) {
                                        localAmplifier.channel[t].fir.firEnable = false;
                                        localAmplifier.channel[t].fir.firName = "";
                                    } else {
                                        localAmplifier.channel[t].fir.firName = "fir values from preset";
                                        localAmplifier.channel[t].fir.firCoeffTemp = tempFir;
                                    }
                                    // if (t === soloChannelSelected)
                                    $.fn.setDataSoloXoverUpdateFIR();
                                    //do nothing
                                }

                                // LIMITER 
                                if (localAmplifier.channel[t].limiter.rmsThres != getThresholdInVolt(parseFloat(jsonObj[16][t].lim_rms.lim_rms_thres), 0) || localAmplifier.channel[t].limiter.rmsAttack != parseFloat(jsonObj[16][t].lim_rms.lim_rms_attack) || localAmplifier.channel[t].limiter.rmsRelease != parseFloat(jsonObj[16][t].lim_rms.lim_rms_release) || localAmplifier.channel[t].limiter.peakThres != getThresholdInVolt(parseFloat(jsonObj[16][t].lim_peak.lim_peak_thres), 1) || localAmplifier.channel[t].limiter.peakRelease != parseFloat(jsonObj[16][t].lim_peak.lim_peak_release)) {
                                    localAmplifier.channel[t].limiter.rmsThres = getThresholdInVolt(parseFloat(jsonObj[16][t].lim_rms.lim_rms_thres), 0);
                                    localAmplifier.channel[t].limiter.rmsAttack = parseFloat(jsonObj[16][t].lim_rms.lim_rms_attack);
                                    localAmplifier.channel[t].limiter.rmsRelease = parseFloat(jsonObj[16][t].lim_rms.lim_rms_release);
                                    localAmplifier.channel[t].limiter.peakThres = getThresholdInVolt(parseFloat(jsonObj[16][t].lim_peak.lim_peak_thres), 1);
                                    localAmplifier.channel[t].limiter.peakRelease = parseFloat(jsonObj[16][t].lim_peak.lim_peak_release);
                                    if (t === soloChannelSelected)
                                        $.fn.setDataSoloLimiterUpdate();
                                    // console.log("UPDATE LIMITER FROM SUBSCRITPION");
                                }
                            }
                            $.fn.runAfterFirstSubscription();
                        } else {
                            subscriptionUpdate--;
                        }
                        break;
                    default:
                        if (i > -1) {
                            // console.log("UNPROCESSED MESSAGE : " + request_pool[i].toString());
                            // console.log("==>" + msgR.command + "<==");
                        }
                        break;
                }
            }
        } else
            console.log("JSON NOT VALID");
    } catch (e) {
        if (i > -1)
            console.log("error in JSON parse : " + e + " // msg : " + msg + " // request : " + request_pool[i].toString());
        else
            console.log("error in JSON parse : " + e + " // msg : " + msg);
    }
}

$.fn.firIsEqual = function(a, b) {
    if (a.length != b.length)
        return false;
    else {
        for (var i = 0; i < a.length; i++)
            if (a[i] != b[i])
                return false;
        return true;
    }
}

$.fn.runAfterFirstSubscription = function() {
    if ($("#mainLoader").hasClass("is-active"))
        $("#mainLoader").removeClass("is-active");
}

$.fn.initData = function() {
    localAmplifier = new localAmplifierConstructor();

    if (arrayEqParam === null) {
        arrayEqParam = new Array(eqCount);
        for (var i = 0; i < eqCount; i++) {
            arrayEqParam[i] = new EqParam(eqEnaDefault, eqFreqDefault, eqGainDefault, eqQDefault, eqTypeDefault, new AParam(), new BParam(), eqXLockDefault, eqYLockDefault);
            arrayEqParam[i].frequency = eqFreqDefaultInit[i];
        }
    }
}

// REFRESH DATA TO SIMULATE CONNECTION WITH REAL AMPLIFIER
$.fn.refreshData = function() {
    if (refreshDataFirstLoad) {
        $.fn.sendCommandWS("start_readback", 0, "null", "null", "null");
        refreshDataFirstLoad = false;
    }
    if ($("#gainMainPanel").is(":visible") || $("#limiterMainPanel").is(":visible"))
        $.fn.sendCommandWS(cmd_get_readback, 0, "null", "null", "null");
    //TO UNCOMMENT
    setTimeout($.fn.refreshData, readbackRefresh);
}

$.fn.drawRefreshedData = function() {
    if (demoMode === 1) {
        // NO REAL TIME DATA
    }

    if ($("#gainMainPanel").is(":visible")) {
        var classGainSolo = "#gainSoloVuMeterCh0";
        var gainHeight = 0;
        if (parseFloat(readBackSolo[soloChannelSelected]) > -60) {
            gainHeight = (parseFloat(readBackSolo[soloChannelSelected]) + 60) / 60;
        }
        $(classGainSolo).css("transform", 'scaleY(' + -gainHeight + ')');
    }

    if ($("#limiterMainPanel").is(":visible")) {
        var classGRLimiterSolo = "#vuMeterGRBGLimiterCh";
        var classPeakLimiterSolo = "#vuMeterPeakBGLimiterCh";
        var classLimiterSolo = "#vuMeterOutputBGLimiterCh";

        var limHeight = 0;
        var peakHeight = 0;
        var outputHeight = 0;

        if (parseFloat(readBackSolo[soloChannelSelected]) > -60) {
            limHeight = Math.abs(parseFloat(readBackLimiter[soloChannelSelected][2])) / 60;

            peakHeight = Math.abs(parseFloat(readBackLimiter[soloChannelSelected][3])) / 60;

            outputHeight = (parseFloat(readBackSolo[soloChannelSelected]) + 60) / 60;

            $(classGRLimiterSolo).css("transform", 'scaleY(' + limHeight + ')');

            $(classPeakLimiterSolo).css("transform", 'scaleY(' + peakHeight + ')');

            $(classLimiterSolo).css("transform", 'scaleY(' + -outputHeight + ')');
        } else {
            $(classGRLimiterSolo).css("transform", 'scaleY(0)');

            $(classPeakLimiterSolo).css("transform", 'scaleY(0)');

            $(classLimiterSolo).css("transform", 'scaleY(0)');
        }
    }
}

$.fn.loadDataFromAmp = function() {
    var str = "[\"channels 0 mute\",\"channels 1 mute\",\"channels 2 mute\",\"channels 3 mute\",\"channels 4 mute\",\"channels 5 mute\",\"channels 6 mute\",\"channels 7 mute\",\"channels 8 mute\",\"channels 9 mute\",\"channels 10 mute\",\"channels 11 mute\",\"channels 12 mute\",\"channels 13 mute\",\"channels 14 mute\",\"channels 15 mute\",\"speaker_presets\"]";
    $.fn.sendCommandWS("subscribe", 0, "null", "null", str);

    //TO UNCOMMENT
    setTimeout(function() { $.fn.refreshData(); }, 1000);
}

$.fn.checkUpdateSpeakerPreset = function(source) {

    for (var k = 0; k < source.length; k++) {

        // TEST CONTAIN KEYS ON JSON

        if (!source[k]["settings"].hasOwnProperty("gain"))
            return "GAIN FIELD IS MISSING";
        if (!source[k]["settings"].hasOwnProperty("polarity"))
            return "POLARITY FIELD IS MISSING";

        if (!source[k]["settings"].hasOwnProperty("delay_enable"))
            return "DELAYENABLE FIELD IS MISSING";
        if (!source[k]["settings"].hasOwnProperty("delay_value"))
            return "DELAY VALUE FIELD IS MISSING";

        if (!source[k]["settings"].hasOwnProperty("peq"))
            return "PEQS FIELD IS MISSING";
        if (source[k]["settings"].peq.length != peqCount)
            return "PEQs COUNT VALUE ERROR";

        for (var i = 0; i < peqCount; i++) {
            if (!source[k]["settings"].peq[i].hasOwnProperty("enable"))
                return "ENABLE PEQ" + i + " FIELD IS MISSING";
            if (!source[k]["settings"].peq[i].hasOwnProperty("type"))
                return "TYPE PEQ" + i + " FIELD IS MISSING";
            if (!source[k]["settings"].peq[i].hasOwnProperty("freq"))
                return "FREQ PEQ" + i + " FIELD  IS MISSING";
            if (!source[k]["settings"].peq[i].hasOwnProperty("gain"))
                return "GAIN PEQ" + i + " FIELD  IS MISSING";
            if (!source[k]["settings"].peq[i].hasOwnProperty("q"))
                return "Q PEQ" + i + " FIELD IS MISSING";
        }

        if (!source[k]["settings"].hasOwnProperty("xover_hp_filter"))
            return "XOVER HP FILTER FIELDs IS MISSING";
        if (!source[k]["settings"].xover_hp_filter.hasOwnProperty("xover_hp_enable"))
            return "XOVER HP ENABLE FIELD IS MISSING";
        if (!source[k]["settings"].xover_hp_filter.hasOwnProperty("xover_hp_type"))
            return "XOVER HP TYPE FIELD IS MISSING";
        if (!source[k]["settings"].xover_hp_filter.hasOwnProperty("xover_hp_freq"))
            return "XOVER HP FREQ FIELD IS MISSING";
        if (!source[k]["settings"].hasOwnProperty("xover_lp_filter"))
            return "XOVER LP FIELDs IS MISSING";
        if (!source[k]["settings"].xover_lp_filter.hasOwnProperty("xover_lp_enable"))
            return "XOVER LP ENABLE FIELD IS MISSING";
        if (!source[k]["settings"].xover_lp_filter.hasOwnProperty("xover_lp_type"))
            return "XOVER LP TYPE FIELD IS MISSING";
        if (!source[k]["settings"].xover_lp_filter.hasOwnProperty("xover_lp_freq"))
            return "XOVER LP FREQ FIELD IS MISSING";

        if (!source[k]["settings"].hasOwnProperty("fir_table"))
            return "FIR TABLE FIELD IS MISSING";

        if (!source[k]["settings"].hasOwnProperty("lim_rms"))
            return "LIMITER RMS FIELDS IS MISSING";
        if (!source[k]["settings"].lim_rms.hasOwnProperty("lim_rms_thres"))
            return "LIMITER RMS THRES FIELD IS MISSING";
        if (!source[k]["settings"].lim_rms.hasOwnProperty("lim_rms_attack"))
            return "LIMITER RMS ATTACK FIELD IS MISSING";
        if (!source[k]["settings"].lim_rms.hasOwnProperty("lim_rms_release"))
            return "LIMITER RMS RELEASE FIELD IS MISSING";

        if (!source[k]["settings"].hasOwnProperty("lim_peak"))
            return "LIMITER FIELDS IS MISSING";
        if (!source[k]["settings"].lim_peak.hasOwnProperty("lim_peak_thres"))
            return "LIMITER PEAK THRES FIELD IS MISSING";
        if (!source[k]["settings"].lim_peak.hasOwnProperty("lim_peak_release"))
            return "LIMITER PEAK RELEASE FIELD IS MISSING";

        // TEST VALUE ON JSON
        if (source[k]["settings"].gain < gainScaleMin || source[k]["settings"].gain > gainScaleMax)
            return "GAIN VALUE OUT OF RANGE";
        if (typeof source[k]["settings"].polarity != "boolean")
            return "POLARITY ENABLE NOT BOOLEAN";

        if (source[k]["settings"].delay_value < delayScaleMin || source[k]["settings"].delay_value > delayScaleMax)
            return "DELAY VALUE OUT OF RANGE";
        if (typeof source[k]["settings"].delay_enable != "boolean")
            return "DELAY ENABLE NOT BOOLEAN";

        for (var i = 0; i < peqCount; i++) {
            if (typeof source[k]["settings"].peq[i].enable != "boolean")
                return "PEQ" + i + " ENABLE NOT BOOLEAN";
            if (source[k]["settings"].peq[i].type < typeScaleMinPEQ || source[k]["settings"].peq[i].type > typeScaleMaxPEQ)
                return "TYPE PEQ" + i + " OUT OF RANGE";
            if (source[k]["settings"].peq[i].freq < freqScaleMinPEQ || source[k]["settings"].peq[i].freq > freqScaleMaxPEQ)
                return "FREQ PEQ" + i + " OUT OF RANGE";
            if (source[k]["settings"].peq[i].gain < gainScaleMinPEQ || source[k]["settings"].peq[i].gain > gainScaleMaxPEQ)
                return "GAIN PEQ" + i + "VALUE OUT OF RANGE";
            if (source[k]["settings"].peq[i].q < qScaleMinPEQ || source[k]["settings"].peq[i].q > qScaleMaxPEQ)
                return "Q PEQ" + i + "VALUE OUT OF RANGE ";
        }

        if (typeof source[k]["settings"].xover_hp_filter.xover_hp_enable != "boolean")
            return "XOVER HP ENABLE NOT BOOLEAN";
        if (source[k]["settings"].xover_hp_filter.xover_hp_type < typeScaleMinXOVER || source[k]["settings"].xover_hp_filter.xover_hp_type > typeScaleMaxXOVER)
            return "XOVER HP TYPE OUT OF RANGE";
        if (source[k]["settings"].xover_hp_filter.xover_hp_freq < freqScaleMinPEQ || source[k]["settings"].xover_hp_filter.xover_hp_freq > freqScaleMaxPEQ)
            return "XOVER HP FREQ OUT OF RANGE";

        if (typeof source[k]["settings"].xover_lp_filter.xover_lp_enable != "boolean")
            return "XOVER LP ENABLE NOT BOOLEAN";
        if (source[k]["settings"].xover_lp_filter.xover_lp_type < typeScaleMinXOVER || source[k]["settings"].xover_lp_filter.xover_lp_type > typeScaleMaxXOVER)
            return "XOVER LP TYPE OUT OF RANGE";
        if (source[k]["settings"].xover_lp_filter.xover_lp_freq < freqScaleMinPEQ || source[k]["settings"].xover_lp_filter.xover_lp_freq > freqScaleMaxPEQ)
            return "XOVER LP FREQ OUT OF RANGE";

        if (source[k]["settings"].fir_table.length < firLengthMin || source[k]["settings"].fir_table.length > firLengthMax)
            return "FIR TABLE WRONG SIZE";
        for (var i = 0; i < source[k]["settings"].fir_table.length; i++) {
            if (source[k]["settings"].fir_table[i] < firScaleMin || source[k]["settings"].fir_table[i] > firScaleMax)
                return "FIR VALUE " + i + " OUT OF RANGE";
        }

        if (source[k]["settings"].lim_rms.lim_rms_thres < rmsThresScaleMinPreset || source[k]["settings"].lim_rms.lim_rms_thres > rmsThresScaleMaxPreset)
            return "LIM RMS THRES OUT OF RANGE";
        if (source[k]["settings"].lim_rms.lim_rms_attack < rmsAttackScaleMin || source[k]["settings"].lim_rms.lim_rms_attack > rmsAttackScaleMax)
            return "LIM RMS ATTACK OUT OF RANGE";
        if (source[k]["settings"].lim_rms.lim_rms_release < rmsReleaseScaleMin || source[k]["settings"].lim_rms.lim_rms_release > rmsReleaseScaleMax)
            return "LIM RMS RELEASE OUT OF RANGE";

        if (source[k]["settings"].lim_peak.lim_peak_thres < peakThresScaleMinPreset || source[k]["settings"].lim_peak.lim_peak_thres > peakThresScaleMaxPreset)
            return "LIM PEAK THRES OUT OF RANGE";
        if (source[k]["settings"].lim_peak.lim_peak_release < peakReleaseScaleMin || source[k]["settings"].lim_peak.lim_peak_release > peakReleaseScaleMax)
            return "LIM PEAK RELEASE OUT OF RANGE";

    }

    return 0;
}

$.fn.checkFirFile = function(source) {
    if (source.length < firLengthMin || source.length > firLengthMax)
        return "FIR TABLE WRONG SIZE";
    for (var i = 0; i < source.length; i++) {
        // console.log("source[" + i + "]:" + source[i]);
        if (!$.isNumeric(source[i]))
            return "FIR VALUE " + i + " NOT NUMERIC";
        if (parseFloat(source[i]) < firScaleMin || parseFloat(source[i]) > firScaleMax) {
            // console.log("source[" + i + "]:" + source[i] + " out of range");
            return "FIR VALUE " + i + " OUT OF RANGE";
        }
    }
    return 0;
}

$.fn.formatFirFile = function(source) {
    var firArray = new Array(firSize);
    var j = source.length - 1;
    for (var i = 0; i < firSize; i++) {
        if (i < (firSize - source.length))
            firArray[i] = 0;
        else {
            firArray[i] = parseFloat(source[j]);
            j--;
        }
    }
    return firArray;
}

$.fn.uploadPreset = function(source) {
    var sourceString = JSON.stringify(source);
    sourceString = sourceString.replaceAll("\"", "\\\"");
    $.fn.sendStringWS(cmd_upload_speaker_preset_file, 0, localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].name + "/" + updateJsonName, "null", sourceString);
}

$.fn.uploadFolderPreset = function(source) {
    var sourceString = JSON.stringify(source);
    sourceString = sourceString.replaceAll("\"", "\\\"");
    $.fn.sendStringWS(cmd_set_speaker_preset_files_from_folder, 0, localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].name, "null", sourceString);
}

jQuery(function() {

    $("#mainLoader").addClass("is-active");

    readBackLimiter[0] = new Array(readBackLimiterCount);
    readBackLimiter[1] = new Array(readBackLimiterCount);
    readBackLimiter[2] = new Array(readBackLimiterCount);
    readBackLimiter[3] = new Array(readBackLimiterCount);
    readBackLimiter[4] = new Array(readBackLimiterCount);
    readBackLimiter[5] = new Array(readBackLimiterCount);
    readBackLimiter[6] = new Array(readBackLimiterCount);
    readBackLimiter[7] = new Array(readBackLimiterCount);
    readBackLimiter[8] = new Array(readBackLimiterCount);
    readBackLimiter[9] = new Array(readBackLimiterCount);
    readBackLimiter[10] = new Array(readBackLimiterCount);
    readBackLimiter[11] = new Array(readBackLimiterCount);
    readBackLimiter[12] = new Array(readBackLimiterCount);
    readBackLimiter[13] = new Array(readBackLimiterCount);
    readBackLimiter[14] = new Array(readBackLimiterCount);
    readBackLimiter[15] = new Array(readBackLimiterCount);

    let firTest = new firConstructor();
    clearFirTable = firTest.firCoeff;

    $("body").on("click", "#loginButton", function(e) {
        $.fn.sendStringWS(cmd_oem_check_code, 0, "null", "null", $("#loginEmail").val());
    });

    $("body").on("dblclick", "span", function(e) {
        // console.log("double click");
        var id = e.target.parentNode.id;
        // console.log(id);
        if (id.indexOf("sliderVertical") > -1) {
            //GAIN SLIDER
            localAmplifier.channel[soloChannelSelected].gain.gain = 0.0;
            $.fn.setDataSoloGain(soloChannelSelected, 1);
        } else if (id.indexOf("sliderDelayVertical") > -1) {
            //DELAY SLIDER
            localAmplifier.channel[soloChannelSelected].delay.delay = 0.0;
            $.fn.setDataSoloDelay(soloChannelSelected, 1);
        } else if (id.indexOf("sliderHorizontalFreq") > -1) {
            localAmplifier.channel[soloChannelSelected].peq.peq[soloChannelSelected].frequency = eqFreqDefaultInit[soloChannelSelected];
            $.fn.setDataSoloPEQ(soloChannelSelected, 2);
        } else if (id.indexOf("sliderHorizontalGain") > -1) {
            localAmplifier.channel[soloChannelSelected].peq.peq[soloChannelSelected].gain = 0.0;
            $.fn.setDataSoloPEQ(soloChannelSelected, 3);
        } else if (id.indexOf("sliderHorizontalQ") > -1) {
            localAmplifier.channel[soloChannelSelected].peq.peq[soloChannelSelected].q = eqQDefault;
            $.fn.setDataSoloPEQ(soloChannelSelected, 4);
        }
    });

    $('#loginEmail').keypress(function(e) {
        if (e.which == 13) {
            $("#loginButton").trigger("click");
            return false;
        }
    });

    //////////////////////////////////////////////////////////
    ////            OVERVIEW BUTTON AREA                  ////
    //////////////////////////////////////////////////////////

    // BUTTON OVERVIEW STYLE
    $("body").on("click", ".overviewMenuDiv > .btnOverview", function() {
        $(".overviewMenuDiv > .btnOverview").removeClass("active");
        $(this).addClass("active");
    });

    //CHANNEL MUTE ENABLE BUTTON
    $("body").on("click", ".overview16ButtonMute", function() {
        let num = parseInt(this.id.toString().match(/(\d+)/g).map(Number));
        // console.log("nummute" + num);
        switch (localAmplifier.channel[num].gain.muteEna) {
            case true:
                localAmplifier.channel[num].gain.muteEna = false;
                $.fn.setDataSoloGain(num, 0);
                break;
            case false:
                localAmplifier.channel[num].gain.muteEna = true;
                $.fn.setDataSoloGain(num, 0);
                break;
        }
    });

    //SHOW COPY MAIN PANEL
    $("body").on("click", "#overviewButtonMenuConfig", function() {
        $.fn.hideMainPanel();
        $("#configMainPanel").show();
        $.fn.setupCopySpeakerParam(7);
        $(".copyChannelSourceRadio").attr("checked", false);
        $("#inlineSourceRadio" + soloChannelSelected).attr("checked", true);
    });

    //SHOW GAIN MAIN PANEL
    $("body").on("click", "#overviewButtonMenuGain", function() {
        $.fn.hideMainPanel();
        $("#gainMainPanel").show();
        $.fn.setDataSoloGain(soloChannelSelected, 99);
    });

    //SHOW DELAY MAIN PANEL
    $("body").on("click", "#overviewButtonMenuDelay", function() {
        $.fn.hideMainPanel();
        $("#delayMainPanel").show();
        $.fn.setDataSoloDelay(soloChannelSelected, 99);
    });

    //SHOW PEQ MAIN PANEL
    $("body").on("click", "#overviewButtonMenuPeq", function() {
        //LOAD DATA FROM SELECTED CHANNEL

        arrayEqParam = localAmplifier.channel[soloChannelSelected].peq.peq;
        // switch (soloChannelSelected) {
        //     case 0:
        //         arrayEqParam = localAmplifier.channel[0].peq.peq;
        //         break;
        //     case 1:
        //         arrayEqParam = localAmplifier.channel[1].peq.peq;
        //         break;
        //     case 2:
        //         arrayEqParam = localAmplifier.channel[2].peq.peq;
        //         break;
        //     case 3:
        //         arrayEqParam = localAmplifier.channel[3].peq.peq;
        //         break;
        //     case 4:
        //         arrayEqParam = localAmplifier.channel[4].peq.peq;
        //         break;
        //     case 5:
        //         arrayEqParam = localAmplifier.channel[5].peq.peq;
        //         break;
        //     case 6:
        //         arrayEqParam = localAmplifier.channel[6].peq.peq;
        //         break;
        //     case 7:
        //         arrayEqParam = localAmplifier.channel[7].peq.peq;
        //         break;

        //     default:
        //         break;
        // }

        $.fn.hideMainPanel();
        $.fn.setupPeqSolo(0);
        $.fn.initPEQ(peqViewMode, peqGainScaleType, peqPhaseScaleType);

        $.fn.setupXOVERSolo();
        $.fn.initXOVER(peqViewMode, peqGainScaleType, peqPhaseScaleType);

        $.fn.drawPEQWidget(99);
        $("#peqMainPanel").show();

        $.fn.drawTickLabels();
        $.fn.drawPEQWidget(peqSoloSelected);

        if (localAmplifier.channel[soloChannelSelected].xover.hpEna)
            $.fn.drawXOVERWidget(0, localAmplifier.channel[soloChannelSelected].xover.hpType);

        if (localAmplifier.channel[soloChannelSelected].xover.lpEna)
            $.fn.drawXOVERWidget(1, localAmplifier.channel[soloChannelSelected].xover.lpType);

        $.fn.initSliderPEQ();
        $.fn.setDataSoloPEQ(99, 99);
    });

    //SHOW XOVER MAIN PANEL
    $("body").on("click", "#overviewButtonMenuXover", function() {
        //LOAD DATA FROM SELECTED CHANNEL
        switch (soloChannelSelected) {
            case 0:
                arrayEqParam = localAmplifier.channel[0].peq.peq;
                break;
            case 1:
                arrayEqParam = localAmplifier.channel[1].peq.peq;
                break;
            case 2:
                arrayEqParam = localAmplifier.channel[2].peq.peq;
                break;
            case 3:
                arrayEqParam = localAmplifier.channel[3].peq.peq;
                break;
            default:
                break;
        }

        $.fn.setupPeqSolo();
        $.fn.initPEQ(peqViewMode, peqGainScaleType, peqPhaseScaleType);
        $.fn.drawPEQWidget(99);
        $.fn.setDataSoloPEQ(99, 99);

        $.fn.setupXOVERSolo();
        $.fn.initXOVER(peqViewMode, peqGainScaleType, peqPhaseScaleType);
        $.fn.hideMainPanel();
        $("#xoverMainPanel").show();
        $.fn.setDataSoloXover(4, 99);
    });

    //SHOW LIMITER MAIN PANEL
    $("body").on("click", "#overviewButtonMenuLimiter", function() {
        $.fn.hideMainPanel();
        $("#limiterMainPanel").show();
        $.fn.resizeLimiter();
        $.fn.initSliderLimiter();
        // $.fn.updateSliderLimiter();
        $.fn.setDataSoloLimiter(1, 99);
    });

    //SHOW SPEAKER MAIN PANEL
    $("body").on("click", "#overviewButtonMenuSpeaker", function() {
        $.fn.hideMainPanel();
        $("#speakerMainPanel").show();
        $.fn.setDataSoloSpeaker(99);
        setTimeout(function() { $.fn.setDataSoloSpeaker(100); }, 1000);
    });

    //MANAGE EVENT ON THE CHANNEL SELECTION "SELECT" BUTTON
    $("body").on("click", ".overview16ButtonSelect", function() {
        var num = parseInt(this.id.toString().match(/(\d+)/g).map(Number));
        $(".overview16ButtonSelect").removeClass("active");
        $(this).addClass("active");
        $(".background16Source").removeClass("active");
        $("#overviewBG" + num).addClass("active");
        soloChannelSelected = num;
        $.fn.clearDataCheck();
        $.fn.loadData();
    });

    // CLEAR GAIN
    $("body").on("click", "#btnOverviewClearGain", function() {
        // console.log("clear gain");
        localAmplifier.channel[soloChannelSelected].gain.gain = clearGainValue;
        localAmplifier.channel[soloChannelSelected].gain.polarityEna = clearPolarityEnaValue;
        $.fn.setDataSoloGain(soloChannelSelected, 3);
    });

    // CLEAR DELAY
    $("body").on("click", "#btnOverviewClearDelay", function() {
        localAmplifier.channel[soloChannelSelected].delay.delay = clearDelayValue;
        localAmplifier.channel[soloChannelSelected].delay.delayEna = clearDelayEnaValue;
        $.fn.setDataSoloDelay(soloChannelSelected, 2);
    });

    // CLEAR PEQ
    $("body").on("click", "#btnOverviewClearPEQ", function() {
        for (var i = 0; i < peqCount; i++) {
            localAmplifier.channel[soloChannelSelected].peq.peq[i].ena = clearPEQEnaValue;
            localAmplifier.channel[soloChannelSelected].peq.peq[i].type = clearPEQTypeValue;
            localAmplifier.channel[soloChannelSelected].peq.peq[i].frequency = clearPEQFrequencyValue[i];
            localAmplifier.channel[soloChannelSelected].peq.peq[i].gain = clearPEQGainValue;
            localAmplifier.channel[soloChannelSelected].peq.peq[i].q = clearPEQQValue;
        }
        $.fn.setDataSoloPEQ(100, 99);
        $.fn.loadData();
    });

    // CLEAR XOVER
    $("body").on("click", "#btnOverviewClearXOVER", function() {
        localAmplifier.channel[soloChannelSelected].xover.hpEna = clearXOVERHpEnaValue;
        localAmplifier.channel[soloChannelSelected].xover.hpFreq = clearXOVERHpFrequencyValue;
        localAmplifier.channel[soloChannelSelected].xover.hpType = clearXOVERHpTypeValue;
        localAmplifier.channel[soloChannelSelected].xover.lpEna = clearXOVERLpEnaValue;
        localAmplifier.channel[soloChannelSelected].xover.lpFreq = clearXOVERLpFrequencyValue;
        localAmplifier.channel[soloChannelSelected].xover.lpType = clearXOVERLpTypeValue;
        localAmplifier.channel[soloChannelSelected].fir.firEnable = false;
        localAmplifier.channel[soloChannelSelected].fir.firName = "";
        localAmplifier.channel[soloChannelSelected].fir.firCoeff = clearFirTable;

        $.fn.setDataSoloXover(8, 99);
        $.fn.loadData();
    });

    // CLEAR LIMITER
    $("body").on("click", "#btnOverviewClearLimiter", function() {
        localAmplifier.channel[soloChannelSelected].limiter.rmsThres = clearLimRmsThresValue;
        localAmplifier.channel[soloChannelSelected].limiter.rmsAttack = clearLimRmsAttackValue;
        localAmplifier.channel[soloChannelSelected].limiter.rmsRelease = clearLimRmsReleaseValue;
        localAmplifier.channel[soloChannelSelected].limiter.peakThres = clearLimPeakThresValue;
        localAmplifier.channel[soloChannelSelected].limiter.peakRelease = clearLimPeakReleaseValue;

        $.fn.setDataSoloLimiter(0, 7);
        $.fn.loadData();
    });



    //////////////////////////////////////////////////////////
    ////            COPY PANEL BUTTON AREA                ////
    //////////////////////////////////////////////////////////

    //MANAGE EVENT ON APPLY COPY CHANNEL PARAMETERS
    $("body").on("click", "#copyChannelContentApply", function() {
        var arrCmd = new Array(0);
        var src = -1;
        var destArray = new Array(0);
        var copyContent = new Object();
        copyContent.mixer = false;
        copyContent.gain = false;
        copyContent.delay = false;
        copyContent.peq = false;
        copyContent.xover = false;
        copyContent.fir = false;
        copyContent.limiter = false;
        copyContent.preset = false;

        //SOURCE
        $(".copyChannelSourceRadio:checked").each(function() {
            src = parseInt(this.id.toString().match(/(\d+)/g).map(Number));
        });

        //COPY
        if ($(copyChannelContentGainCB).is(':checked')) {
            copyContent.gain = true;
            // console.log("Copy : gain")
        }
        if ($(copyChannelContentDelayCB).is(':checked')) {
            copyContent.delay = true;
            // console.log("Copy : delay")
        }
        if ($(copyChannelContentPEQCB).is(':checked')) {
            copyContent.peq = true;
            // console.log("Copy : peq")
        }
        if ($(copyChannelContentXOVERCB).is(':checked')) {
            copyContent.xover = true;
            // console.log("Copy : xover")
        }
        if ($(copyChannelContentFIRCB).is(':checked')) {
            copyContent.fir = true;
            // console.log("Copy : fir")
        }
        if ($(copyChannelContentLimiterCB).is(':checked')) {
            copyContent.limiter = true;
            // console.log("Copy : limiter")
        }

        //DESTINATION
        $(".copyChannelDest:checked").each(function() {
            dest = parseInt(this.id.toString().match(/(\d+)/g).map(Number));
            destArray.push(dest);
        });

        console.log("source = " + src + " // content = " + JSON.stringify(copyContent) + " // destination = " + destArray);

        if (destArray.length > 0) {
            var copyContentTxt = JSON.stringify(copyContent)
            let resultTxt = copyContentTxt.replaceAll("\"", "\\\"");
            arrCmd.push($.fn.getCommandFromArgs(cmd_set_copy_speaker_parameters, 0, parseInt(src), "\"" + destArray + "\"", resultTxt));
        }

        if (arrCmd.length > 0)
            $.fn.sendCommandsWS(arrCmd);
    });

    //////////////////////////////////////////////////////////
    ////            GAIN PANEL BUTTON AREA                ////
    //////////////////////////////////////////////////////////

    // MANAGE CHANNEL EVENT ON BUTTONVOLUP GAIN
    $("body").on("click", ".itemQuarterButtonVolUp", function() {
        if (localAmplifier.channel[soloChannelSelected].gain.gain < gainScaleMax) {
            localAmplifier.channel[soloChannelSelected].gain.gain = parseFloat(parseFloat(localAmplifier.channel[soloChannelSelected].gain.gain + 0.1).toFixed(1));
            $.fn.setDataSoloGain(soloChannelSelected, 1);
        }
    });

    // MANAGE CHANNEL EVENT ON BUTTONVOLDOWN GAIN
    $("body").on("click", ".itemQuarterButtonVolDown", function() {
        if (localAmplifier.channel[soloChannelSelected].gain.gain > gainScaleMin) {
            localAmplifier.channel[soloChannelSelected].gain.gain = parseFloat(parseFloat(localAmplifier.channel[soloChannelSelected].gain.gain - 0.1).toFixed(1));
            $.fn.setDataSoloGain(soloChannelSelected, 1);
        }
    });

    //CHECK VALUE ON THE INPUT GAIN TEXTFIELD
    $("body").on("change", ".itemQuarterTextField", function(e) {
        if (!$.isNumeric(this.value)) {
            alert("GAIN VALUE BETWEEN " + gainScaleMin + "dB and " + gainScaleMax + "dB")
            $(".itemQuarterTextField").val(localAmplifier.channel[soloChannelSelected].gain.gain);
        } else {
            if (this.value < gainScaleMin)
                localAmplifier.channel[soloChannelSelected].gain.gain = gainScaleMin;
            else if (this.value > gainScaleMax)
                localAmplifier.channel[soloChannelSelected].gain.gain = gainScaleMax;
            else
                localAmplifier.channel[soloChannelSelected].gain.gain = parseFloat(parseFloat(this.value).toFixed(1));
            $.fn.setDataSoloGain(soloChannelSelected, 1);
        }
    });

    //CHANNEL PHASE ENABLE BUTTON
    $("body").on("click", ".itemQuarterButtonPhase", function() {
        switch (localAmplifier.channel[soloChannelSelected].gain.polarityEna) {
            case true:
                localAmplifier.channel[soloChannelSelected].gain.polarityEna = false;
                $.fn.setDataSoloGain(soloChannelSelected, 2);
                break;
            case false:
                localAmplifier.channel[soloChannelSelected].gain.polarityEna = true;
                $.fn.setDataSoloGain(soloChannelSelected, 2);
                break;
        }
    });

    //////////////////////////////////////////////////////////
    ////            DELAY PANEL BUTTON AREA               ////
    //////////////////////////////////////////////////////////

    // MANAGE EVENT ON CHANNEL BUTTONDELAYUP DELAY
    $("body").on("click", ".itemQuarterButtonDelayUp", function() {
        if (localAmplifier.channel[soloChannelSelected].delay.delay < delayScaleMax) {
            localAmplifier.channel[soloChannelSelected].delay.delay = parseFloat(parseFloat(localAmplifier.channel[soloChannelSelected].delay.delay + 0.01).toFixed(2));
            $.fn.setDataSoloDelay(soloChannelSelected, 1);
        }
    });

    // MANAGE EVENT ON CHANNEL BUTTONDELAYDOWN DELAY
    $("body").on("click", ".itemQuarterButtonDelayDown", function() {
        if (localAmplifier.channel[soloChannelSelected].delay.delay > delayScaleMin) {
            localAmplifier.channel[soloChannelSelected].delay.delay = parseFloat(parseFloat(localAmplifier.channel[soloChannelSelected].delay.delay - 0.01).toFixed(2));
            $.fn.setDataSoloDelay(soloChannelSelected, 1);
        }
    });

    //CHECK VALUE ON THE INPUT DELAY TEXTFIELD
    $("body").on("change", ".itemQuarterDelayTextField", function() {
        if (!$.isNumeric(this.value)) {
            alert("DELAY VALUE BETWEEN " + delayScaleMin + "ms and " + delayScaleMax + "ms")
            $(".itemQuarterDelayTextField").val(localAmplifier.channel[soloChannelSelected].delay.delay);
        } else {
            if (parseFloat(parseFloat(this.value).toFixed(2)) < delayScaleMin)
                localAmplifier.channel[soloChannelSelected].delay.delay = delayScaleMin;
            else if (parseFloat(parseFloat(this.value).toFixed(2)) > delayScaleMax)
                localAmplifier.channel[soloChannelSelected].delay.delay = delayScaleMax;
            else
                localAmplifier.channel[soloChannelSelected].delay.delay = parseFloat(parseFloat(this.value).toFixed(2));
            $.fn.setDataSoloDelay(soloChannelSelected, 1);
        }
    });

    // MANAGE EVENT ON CHANNEL ENABLE BUTTON DELAY
    $("body").on("click", ".itemQuarterButtonDelayEnable", function() {
        if (localAmplifier.channel[soloChannelSelected].delay.delayEna === true) {
            localAmplifier.channel[soloChannelSelected].delay.delayEna = false;
        } else {
            localAmplifier.channel[soloChannelSelected].delay.delayEna = true;
        }
        $.fn.setDataSoloDelay(soloChannelSelected, 0);
    });

    //////////////////////////////////////////////////////////
    ////             PEQ PANEL BUTTON AREA                ////
    //////////////////////////////////////////////////////////

    //MANAGE EVENT ON SELECT PEQ NAVBAR BUTTON ALL OR SOLO EDIT
    $("body").on("click", "a[href=\"#peq\"]", function() {
        //INITIALIZE VALUE FOR SLIDERS
        for (var i = 0; i < eqCount; i++) {
            var freq = "#sliderHorizontalFreqPEQ" + i;
            var gain = "#sliderHorizontalGainPEQ" + i;
            var q = "#sliderHorizontalQPEQ" + i;
            $(freq).slider("option", "value", Math.log10(localAmplifier.channel[soloChannelSelected].peq.peq[i].frequency));
            $(gain).slider("option", "value", localAmplifier.channel[soloChannelSelected].peq.peq[i].gain);
            $(q).slider("option", "value", Math.log10(localAmplifier.channel[soloChannelSelected].peq.peq[i].q));

        }
        $(".peqButtonNavBar").removeClass("active");
        var num = parseInt(this.id.toString().match(/(\d+)/g).map(Number));
        // displayVal("id nav", num);
        var idS = "#peqAnav" + num;
        $(idS).addClass("active");
        var idEq = "#parametersAreaEQ" + num;
        $.fn.clearPEQParamArea();
        $(idEq).show();
        if (num < eqCount) {
            peqSoloSelected = num;
            $.fn.drawPEQWidget(peqSoloSelected);
        }
        if (num === 100) {
            //TO DO SET SELECTED CHANNEL SOURCE
            $("#inlineRadio" + soloChannelSelected).attr("checked", true);
        }
    });

    //MANAGE EVENT ON ENABLE CHECKBOX PEQ PANEL
    $("body").on("change", ".enaInputPEQ", function() {
        //FIND NUMBER IN ID (FROM 0 TO 11);
        var num = parseInt(this.id.toString().match(/(\d+)/g).map(Number));
        var status = localAmplifier.channel[soloChannelSelected].peq.peq[num].ena;
        switch (status) {
            case true:
                localAmplifier.channel[soloChannelSelected].peq.peq[num].ena = false;
                break;
            case false:
                localAmplifier.channel[soloChannelSelected].peq.peq[num].ena = true;
                break;
        }
        peqSoloSelected = num;
        //SEND DATA TO AMPLIFIER
        $.fn.setDataSoloPEQ(num, 0);

        if (localAmplifier.channel[soloChannelSelected].xover.hpEna)
            $.fn.drawXOVERWidget(0, localAmplifier.channel[soloChannelSelected].xover.hpType);

        if (localAmplifier.channel[soloChannelSelected].xover.lpEna)
            $.fn.drawXOVERWidget(1, localAmplifier.channel[soloChannelSelected].xover.lpType);
    });

    //CHECK VALUE ON THE PEQ TYPE FIELD
    $("body").on("change", ".eqTypeSelect", function() {
        //FIND NUMBER IN ID (FROM 0 TO 11);
        var num = parseInt(this.id.toString().match(/(\d+)/g).map(Number));
        localAmplifier.channel[soloChannelSelected].peq.peq[num].type = parseInt($(this).children("option:selected").val());
        $.fn.setDataSoloPEQ(num, 1);
        $.fn.initiatePEQDraggie();

        if (localAmplifier.channel[soloChannelSelected].xover.hpEna)
            $.fn.drawXOVERWidget(0, localAmplifier.channel[soloChannelSelected].xover.hpType);
        if (localAmplifier.channel[soloChannelSelected].xover.lpEna)
            $.fn.drawXOVERWidget(1, localAmplifier.channel[soloChannelSelected].xover.lpType);
    });

    //CHECK VALUE ON THE PEQ FREQ FIELD
    $("body").on("change", ".freqInputPEQ", function() {
        //FIND NUMBER IN ID (FROM 0 TO 11);
        var num = parseInt(this.id.toString().match(/(\d+)/g).map(Number));
        if (!$.isNumeric(this.value))
            alert("DELAY VALUE BETWEEN 10 and 22000Hz");
        var n = parseInt(this.value);
        if (n < freqScaleMinPEQ)
            n = freqScaleMinPEQ;
        if (n > freqScaleMaxPEQ)
            n = freqScaleMaxPEQ;
        localAmplifier.channel[soloChannelSelected].peq.peq[num].frequency = n;
        //SEND DATA TO AMPLIFIER
        $.fn.setDataSoloPEQ(num, 2);

        if (localAmplifier.channel[soloChannelSelected].xover.hpEna)
            $.fn.drawXOVERWidget(0, localAmplifier.channel[soloChannelSelected].xover.hpType);

        if (localAmplifier.channel[soloChannelSelected].xover.lpEna)
            $.fn.drawXOVERWidget(1, localAmplifier.channel[soloChannelSelected].xover.lpType);
    });

    //CHECK VALUE ON THE PEQ GAIN FIELD
    $("body").on("change", ".gainInputPEQ", function() {
        //FIND NUMBER IN ID (FROM 0 TO 11);
        var num = parseInt(this.id.toString().match(/(\d+)/g).map(Number));
        if (!$.isNumeric(this.value))
            alert("GAIN BETWEEN -36.0dB to 18.0dB");
        var n = parseFloat(parseFloat(this.value).toFixed(1));
        if (n < gainScaleMinPEQ)
            n = gainScaleMinPEQ;
        if (n > gainScaleMaxPEQ)
            n = gainScaleMaxPEQ;
        localAmplifier.channel[soloChannelSelected].peq.peq[num].gain = n;
        //SEND DATA TO AMPLIFIER
        $.fn.setDataSoloPEQ(num, 3);
    });

    //CHECK VALUE ON THE PEQ Q FIELD
    $("body").on("change", ".qInputPEQ", function() {
        //FIND NUMBER IN ID (FROM 0 TO 11);
        var num = parseInt(this.id.toString().match(/(\d+)/g).map(Number));
        if (!$.isNumeric(this.value))
            alert("GAIN BETWEEN -36.0dB to 18.0dB");
        var n = parseFloat(parseFloat(this.value).toFixed(2));
        if (n < qScaleMin)
            n = qScaleMin;
        if (n > qScaleMax)
            n = qScaleMax;
        localAmplifier.channel[soloChannelSelected].peq.peq[num].q = n;
        //SEND DATA TO AMPLIFIER
        $.fn.setDataSoloPEQ(num, 4);

        if (localAmplifier.channel[soloChannelSelected].xover.hpEna)
            $.fn.drawXOVERWidget(0, localAmplifier.channel[soloChannelSelected].xover.hpType);
        if (localAmplifier.channel[soloChannelSelected].xover.lpEna)
            $.fn.drawXOVERWidget(1, localAmplifier.channel[soloChannelSelected].xover.lpType);
    });

    // MANAGE CHANNEL EVENT PEQ SOLO FREQUENCY BUTTON DOWN
    $("body").on("click", ".soloPEQFreqButtonDown", function() {
        var num = parseInt(this.id.toString().match(/(\d+)/g).map(Number));
        if (localAmplifier.channel[soloChannelSelected].peq.peq[num].frequency > freqScaleMinPEQ) {
            localAmplifier.channel[soloChannelSelected].peq.peq[num].frequency = parseInt(localAmplifier.channel[soloChannelSelected].peq.peq[num].frequency - 1);
            //SEND DATA TO AMPLIFIER
            $.fn.setDataSoloPEQ(num, 2);

            if (localAmplifier.channel[soloChannelSelected].xover.hpEna)
                $.fn.drawXOVERWidget(0, localAmplifier.channel[soloChannelSelected].xover.hpType);
            if (localAmplifier.channel[soloChannelSelected].xover.lpEna)
                $.fn.drawXOVERWidget(1, localAmplifier.channel[soloChannelSelected].xover.lpType);
        }
    });

    // MANAGE CHANNEL EVENT PEQ SOLO FREQUENCY BUTTON UP
    $("body").on("click", ".soloPEQFreqButtonUp", function() {
        var num = parseInt(this.id.toString().match(/(\d+)/g).map(Number));
        if (localAmplifier.channel[soloChannelSelected].peq.peq[num].frequency < freqScaleMaxPEQ) {
            localAmplifier.channel[soloChannelSelected].peq.peq[num].frequency = parseInt(localAmplifier.channel[soloChannelSelected].peq.peq[num].frequency + 1);
            //SEND DATA TO AMPLIFIER
            $.fn.setDataSoloPEQ(num, 2);

            if (localAmplifier.channel[soloChannelSelected].xover.hpEna)
                $.fn.drawXOVERWidget(0, localAmplifier.channel[soloChannelSelected].xover.hpType);
            if (localAmplifier.channel[soloChannelSelected].xover.lpEna)
                $.fn.drawXOVERWidget(1, localAmplifier.channel[soloChannelSelected].xover.lpType);
        }
    });

    // MANAGE CHANNEL EVENT PEQ SOLO GAIN BUTTON DOWN
    $("body").on("click", ".soloPEQGainButtonDown", function() {
        var num = parseInt(this.id.toString().match(/(\d+)/g).map(Number));
        if (parseFloat(localAmplifier.channel[soloChannelSelected].peq.peq[num].gain) > gainScaleMinPEQ) {
            localAmplifier.channel[soloChannelSelected].peq.peq[num].gain = parseFloat(parseFloat(localAmplifier.channel[soloChannelSelected].peq.peq[num].gain - 0.1).toFixed(1));
            //SEND DATA TO AMPLIFIER
            $.fn.setDataSoloPEQ(num, 3);
            if (localAmplifier.channel[soloChannelSelected].xover.hpEna)
                $.fn.drawXOVERWidget(0, localAmplifier.channel[soloChannelSelected].xover.hpType);
            if (localAmplifier.channel[soloChannelSelected].xover.lpEna)
                $.fn.drawXOVERWidget(1, localAmplifier.channel[soloChannelSelected].xover.lpType);
        }
    });

    // MANAGE CHANNEL EVENT PEQ SOLO GAIN BUTTON UP
    $("body").on("click", ".soloPEQGainButtonUp", function() {
        var num = parseInt(this.id.toString().match(/(\d+)/g).map(Number));
        if (parseFloat(localAmplifier.channel[soloChannelSelected].peq.peq[num].gain) < gainScaleMaxPEQ) {
            localAmplifier.channel[soloChannelSelected].peq.peq[num].gain = parseFloat(parseFloat(localAmplifier.channel[soloChannelSelected].peq.peq[num].gain + 0.1).toFixed(1));
            //SEND DATA TO AMPLIFIER
            $.fn.setDataSoloPEQ(num, 3);

            if (localAmplifier.channel[soloChannelSelected].xover.hpEna)
                $.fn.drawXOVERWidget(0, localAmplifier.channel[soloChannelSelected].xover.hpType);
            if (localAmplifier.channel[soloChannelSelected].xover.lpEna)
                $.fn.drawXOVERWidget(1, localAmplifier.channel[soloChannelSelected].xover.lpType);
        }
    });

    // MANAGE CHANNEL EVENT PEQ SOLO Q BUTTON DOWN
    $("body").on("click", ".soloPEQQButtonDown", function() {
        var num = parseInt(this.id.toString().match(/(\d+)/g).map(Number));
        if (parseFloat(localAmplifier.channel[soloChannelSelected].peq.peq[num].q) > qScaleMin) {
            localAmplifier.channel[soloChannelSelected].peq.peq[num].q = parseFloat(parseFloat(localAmplifier.channel[soloChannelSelected].peq.peq[num].q - 0.1).toFixed(1));
            //SEND DATA TO AMPLIFIER
            $.fn.setDataSoloPEQ(num, 4);
            if (localAmplifier.channel[soloChannelSelected].xover.pEna)
                $.fn.drawXOVERWidget(0, localAmplifier.channel[soloChannelSelected].xover.hpType);
            if (localAmplifier.channel[soloChannelSelected].xover.lpEna)
                $.fn.drawXOVERWidget(1, localAmplifier.channel[soloChannelSelected].xover.lpType);
        }
    });

    // MANAGE CHANNEL EVENT PEQ SOLO Q BUTTON UP
    $("body").on("click", ".soloPEQQButtonUp", function() {
        var num = parseInt(this.id.toString().match(/(\d+)/g).map(Number));
        if (parseFloat(localAmplifier.channel[soloChannelSelected].peq.peq[num].q) < qScaleMax) {
            localAmplifier.channel[soloChannelSelected].peq.peq[num].q = parseFloat(parseFloat(localAmplifier.channel[soloChannelSelected].peq.peq[num].q + 0.1).toFixed(1));
            //SEND DATA TO AMPLIFIER
            $.fn.setDataSoloPEQ(num, 4);
            $.fn.drawXOVERWidget(0, localAmplifier.channel[soloChannelSelected].xover.hpType);
            $.fn.drawXOVERWidget(1, localAmplifier.channel[soloChannelSelected].xover.lpType);
        }
    });

    //OPEN MODAL VIEW FOR SOLO PEQ TYPE
    $("body").on("click", ".peqButtonTypeSolo", function() {
        peqSelectedModalType = $(this).data('id');
        // displayVal("modal  peq", $(this).data('id'))
        $("#cafeId").val($(this).data('id'));
        $('#modalPeqType').modal('show');
    });

    //ACTION WHEN SELECTED PEQ IS CLICKED ON MODAL
    $("body").on("click", ".peqModalTypeBtn", function() {
        var num = parseInt(this.id.toString().match(/(\d+)/g).map(Number));
        // displayVal("selected type", peqLabel[num]);
        var dest = "#eqType" + peqSelectedModalType;
        $(dest).val(num);
        $(dest).trigger("change");
        $('#modalPeqType').modal('hide')
    });

    // MANAGE EVENT ON PEQ MAIN X LOCK MAGNITUDE
    $("body").on("click", "#eqLockMag", function() {
        this.classList.toggle('changed');
        if (this.classList.contains('changed'))
            widgetPEQMainXLock = true;
        else
            widgetPEQMainXLock = false;
        $.fn.initiatePEQDraggie();
    });

    // MANAGE EVENT ON PEQ MAIN Y LOCK FREQUENCY
    $("body").on("click", "#eqLockFreq", function() {
        this.classList.toggle('changed');
        if (this.classList.contains('changed'))
            widgetPEQMainYLock = true;
        else
            widgetPEQMainYLock = false;
        $.fn.initiatePEQDraggie();
    });

    // MANAGE EVENT ON PEQ MAIN Q LOCK Q
    $("body").on("click", "#eqLockQ", function() {
        this.classList.toggle('changed');
        if (this.classList.contains('changed'))
            widgetPEQMainQLock = true;
        else
            widgetPEQMainQLock = false;
        $.fn.initiatePEQDraggie();
    });

    // MANAGE EVENT ON PEQ MAIN VIEW OPTIONS MODAL
    $("body").on("click", "#peqModalSaveChange", function() {
        displayVal("save changes");
        // $.fn.initiatePEQDraggie();
    });

    //UPDATE GAIN SCALE PEQ
    $("body").on("change", ".peqGainScale", function() {
        var n = $(this).children("option:selected").val();
        // displayVal("val scale", n);
        peqGainScaleType = n;
        $.fn.initPEQ(peqViewMode, peqGainScaleType, peqPhaseScaleType);
        $.fn.drawPEQWidget(peqSoloSelected);

        for (var num = 0; num < eqCount; num++)
            if (localAmplifier.channel[soloChannelSelected].peq.peq[num].ena === true) {
                $.fn.setDataSoloPEQ(num);
            }
    });

    //UPDATE PHASE SCALE PEQ
    $("body").on("change", ".peqPhaseScale", function() {
        var n = $(this).children("option:selected").val();
        // displayVal("val scale", n);
        peqPhaseScaleType = n;
        $.fn.initPEQ(peqViewMode, peqGainScaleType, peqPhaseScaleType);
        $.fn.drawPEQWidget(peqSoloSelected);
        for (var num = 0; num < eqCount; num++)
            if (localAmplifier.channel[soloChannelSelected].peq.peq[num].ena === true) {
                $.fn.setDataSoloPEQ(num);
            }
    });

    //MANAGE EVENT WHEN VIEW MODE IS CHANGED
    $("body").on("change", "#peqViewMode", function() {
        var n = $(this).children("option:selected").val();
        peqViewMode = parseInt(n);
        // console.log("peqViewMode:" + peqViewMode);
        //SETUP PEQ GRAPH TO FOLLOW peqViewMode
        $.fn.initPEQ(peqViewMode, peqGainScaleType, peqPhaseScaleType);
        //REDRAW THE CURVE OF THE LATEST SELECTED PEQ
        $.fn.drawPEQWidget(peqSoloSelected);
        //ADJUST XOVER GRAPH TO FOLLOW peqViewMode
        $.fn.initXOVER(peqViewMode, xoverGainScaleType, xoverPhaseScaleType);
        //SETUP XOVER MODAL VALUE FOR VIEW MODE
        $("#xoverViewMode").val(peqViewMode);
    });

    $("body").on("click", "#peqCopySelectAll", function(e) {
        if ($(".peqCopySelected:checked").length === peqCount) {
            $(".peqCopySelected").attr("checked", false);
        } else {
            $(".peqCopySelected").attr("checked", true);
        }
    });


    $("body").on("click", "#peqCopyApply", function(e) {
        var src = dest = peq = -1;
        var sendArray = new Array(0);
        var peqArray = new Array(0);

        $(".peqCopyChannelDest:checked").each(function() {
            dest = parseInt(this.id.toString().match(/(\d+)/g).map(Number));
            sendArray.push(dest);
            $(".peqCopyChannelSourceRadio:checked").each(function() {
                src = parseInt(this.id.toString().match(/(\d+)/g).map(Number));
                $(".peqCopySelected:checked").each(function() {
                    peq = parseInt(this.id.toString().match(/(\d+)/g).map(Number));
                    peqArray.push(peq);
                    // console.log("copy eq" + peq + " from src" + src + " to dest" + dest);
                    localAmplifier.channel[dest].peq.peq[peq].ena = Boolean(localAmplifier.channel[src].peq.peq[peq].ena);
                    localAmplifier.channel[dest].peq.peq[peq].frequency = parseInt(localAmplifier.channel[src].peq.peq[peq].frequency);
                    localAmplifier.channel[dest].peq.peq[peq].gain = parseFloat(localAmplifier.channel[src].peq.peq[peq].gain);
                    localAmplifier.channel[dest].peq.peq[peq].q = parseFloat(localAmplifier.channel[src].peq.peq[peq].q);
                    localAmplifier.channel[dest].peq.peq[peq].type = parseInt(localAmplifier.channel[src].peq.peq[peq].type);
                });
            });
        });
        // console.log("send array : " + sendArray);
        if (sendArray.length > 0 && peqArray.length > 0)
            $.fn.setDataSoloPEQCopy(sendArray, peqArray);
    });

    $("body").on("click", "#peqFlatApply", function(e) {
        // console.log("flat apply");
        var sendArray = new Array(0)
        var peqArray = new Array(0);
        for (var i = 0; i < peqCount; i++) {
            localAmplifier.channel[soloChannelSelected].peq.peq[i].gain = eqGainDefault;
            peqArray.push(i);
        }
        sendArray.push(soloChannelSelected);
        $.fn.setDataSoloPEQGain(sendArray, peqArray);

        $.fn.setDataSoloPEQUpdate(soloChannelSelected);

        $.fn.drawPEQWidget(peqSoloSelected);

        $.fn.drawXOVERWidget(0, localAmplifier.channel[soloChannelSelected].xover.hpType);
        $.fn.drawXOVERWidget(1, localAmplifier.channel[soloChannelSelected].xover.lpType);

        $.fn.initSliderPEQ();
        $.fn.setDataSoloPEQ(99, 99);
    });

    $("body").on("click", "#peqDefaultApply", function(e) {
        // console.log("peq default apply");
        var sendArray = new Array(0)
        var peqArray = new Array(0);
        for (var i = 0; i < peqCount; i++) {
            localAmplifier.channel[soloChannelSelected].peq.peq[i].ena = eqEnaDefault;
            localAmplifier.channel[soloChannelSelected].peq.peq[i].type = eqTypeDefault;
            localAmplifier.channel[soloChannelSelected].peq.peq[i].frequency = eqFreqDefaultInit[i];
            localAmplifier.channel[soloChannelSelected].peq.peq[i].gain = eqGainDefault;
            localAmplifier.channel[soloChannelSelected].peq.peq[i].q = eqQDefault;
            peqArray.push(i);
        }
        sendArray.push(soloChannelSelected);
        $.fn.setDataSoloPEQCopy(sendArray, peqArray);

        $.fn.setDataSoloPEQUpdate(soloChannelSelected);

        $.fn.drawPEQWidget(peqSoloSelected);

        $.fn.drawXOVERWidget(0, localAmplifier.channel[soloChannelSelected].xover.hpType);
        $.fn.drawXOVERWidget(1, localAmplifier.channel[soloChannelSelected].xover.lpType);

        $.fn.initSliderPEQ();
        $.fn.setDataSoloPEQ(99, 99);
    });

    $("body").on("click", "#peqDefaultAllApply", function(e) {
        // console.log("peq default all apply");
        var sendArray = new Array(0)
        var peqArray = new Array(0);
        for (var j = 0; j < channelCount; j++) {
            for (var i = 0; i < peqCount; i++) {
                localAmplifier.channel[j].peq.peq[i].ena = eqEnaDefault;
                localAmplifier.channel[j].peq.peq[i].type = eqTypeDefault;
                localAmplifier.channel[j].peq.peq[i].frequency = eqFreqDefaultInit[i];
                localAmplifier.channel[j].peq.peq[i].gain = eqGainDefault;
                localAmplifier.channel[j].peq.peq[i].q = eqQDefault;
                if (peqArray.length < peqCount)
                    peqArray.push(i);
            }
            sendArray.push(j);
        }
        $.fn.setDataSoloPEQCopy(sendArray, peqArray);

        $.fn.setDataSoloPEQUpdate(soloChannelSelected);

        $.fn.drawPEQWidget(peqSoloSelected);

        $.fn.drawXOVERWidget(0, localAmplifier.channel[soloChannelSelected].xover.hpType);
        $.fn.drawXOVERWidget(1, localAmplifier.channel[soloChannelSelected].xover.lpType);

        $.fn.initSliderPEQ();
        $.fn.setDataSoloPEQ(99, 99);
    });

    //////////////////////////////////////////////////////////
    ////            XOVER PANEL BUTTON AREA               ////
    //////////////////////////////////////////////////////////

    // MANAGE EVENT ON XOVER MAIN VIEW OPTIONS MODAL
    $("body").on("click", "#xoverModalSaveChange", function() {
        displayVal("save changes");
        // $.fn.initiatePEQDraggie();
    });

    //UPDATE GAIN SCALE XOVER
    $("body").on("change", ".xoverGainScale", function() {
        var n = $(this).children("option:selected").val();
        // displayVal("val scale", n);
        xoverGainScaleType = n;
        $.fn.initXOVER(peqViewMode, xoverGainScaleType, xoverPhaseScaleType);

        if (localAmplifier.channel[soloChannelSelected].xover.hpEna === true)
            $.fn.drawXOVERWidget(0, localAmplifier.channel[soloChannelSelected].xover.hpType);
        if (localAmplifier.channel[soloChannelSelected].xover.lpEna === true)
            $.fn.drawXOVERWidget(1, localAmplifier.channel[soloChannelSelected].xover.lpType);
        $.fn.drawPEQWidget(peqSoloSelected);
    });

    //UPDATE PHASE SCALE XOVER
    $("body").on("change", ".xoverPhaseScale", function() {
        var n = $(this).children("option:selected").val();
        // displayVal("val scale", n);
        xoverPhaseScaleType = n;
        $.fn.initXOVER(peqViewMode, xoverGainScaleType, xoverPhaseScaleType);

        if (localAmplifier.channel[soloChannelSelected].xover.hpEna === true)
            $.fn.drawXOVERWidget(0, localAmplifier.channel[soloChannelSelected].xover.hpType);
        if (localAmplifier.channel[soloChannelSelected].xover.lpEna === true)
            $.fn.drawXOVERWidget(1, localAmplifier.channel[soloChannelSelected].xover.lpType);
        $.fn.drawPEQWidget(peqSoloSelected);
    });

    //MANAGE EVENT WHEN VIEW MODE IS CHANGED XOVER
    $("body").on("change", "#xoverViewMode", function() {
        var n = $(this).children("option:selected").val();
        peqViewMode = n;
        // displayVal("val scale", n);

        $("#peqViewMode").val(peqViewMode);
        $("#peqViewMode").trigger("change");
    });

    //ACTION WHEN SELECTED XOVER IS CLICKED ON MODAL
    $("body").on("click", ".xoverModalTypeBtn", function() {

        var num = parseInt(this.id.toString().match(/(\d+)/g).map(Number));

        if (this.id.indexOf("HighPass") >= 0) {
            localAmplifier.channel[soloChannelSelected].xover.hpType = num;
            $.fn.setDataSoloXover(0, 1);
        } else {
            localAmplifier.channel[soloChannelSelected].xover.lpType = num;
            $.fn.setDataSoloXover(1, 4);
        }
        $.fn.drawPEQWidget(peqSoloSelected);
    });

    $("body").on("change", "#enableToggleFirXOVER", function() {
        switch (localAmplifier.channel[soloChannelSelected].fir.firEnable) {
            case true:
                // $("#enableToggleFirXOVER").removeClass("active");
                localAmplifier.channel[soloChannelSelected].fir.firEnable = false;
                break;
                //SEND DEFAULT FIR TABLE
            case false:
                // $("#enableToggleFirXOVER").addClass("active");
                localAmplifier.channel[soloChannelSelected].fir.firEnable = true;
                break;
            default:
                break;
        }
        $.fn.setDataSoloXover(7, 99);
    });

    //CHECK VALUE ON THE HIGHPASS FREQ FIELD
    $("body").on("change", ".freqInputXOVER", function() {
        if (!$.isNumeric(this.value))
            alert("DELAY VALUE BETWEEN 10 and 22000Hz");
        var n = parseInt(this.value);
        if (n < freqScaleMinPEQ)
            n = freqScaleMinPEQ;
        if (n > freqScaleMaxPEQ)
            n = freqScaleMaxPEQ;
        if (this.id.indexOf("HighPass") >= 0) {
            localAmplifier.channel[soloChannelSelected].xover.hpFreq = n;
            $.fn.setDataSoloXover(0, 2);
        } else {
            localAmplifier.channel[soloChannelSelected].xover.lpFreq = n;
            $.fn.setDataSoloXover(1, 5);
        }
        $.fn.drawPEQWidget(peqSoloSelected);
    });

    //MANAGE EVENT ON ENABLE CHECKBOX XOVER PANEL
    $("body").on("change", ".enaXOVER", function() {
        //IF HIGHPASS CROSSOVER ENABLE BUTTON
        if (this.id.indexOf("HighPass") >= 0) {
            switch (localAmplifier.channel[soloChannelSelected].xover.hpEna) {
                case true:
                    localAmplifier.channel[soloChannelSelected].xover.hpEna = false;
                    localAmplifier.channel[soloChannelSelected].xover.hpSpeakerPresetOveride = false;
                    $.fn.setDataSoloXover(10, 0);
                    break;
                case false:
                    localAmplifier.channel[soloChannelSelected].xover.hpEna = true;
                    break;
                default:
                    break;
            }
            $.fn.setDataSoloXover(0, 0);

            //IF LOWPASS CROSSOVER ENABLE BUTTON
        } else {
            switch (localAmplifier.channel[soloChannelSelected].xover.lpEna) {
                case true:
                    localAmplifier.channel[soloChannelSelected].xover.lpEna = false;
                    localAmplifier.channel[soloChannelSelected].xover.lpSpeakerPresetOveride = false;
                    $.fn.setDataSoloXover(11, 0);
                    break;
                case false:
                    localAmplifier.channel[soloChannelSelected].xover.lpEna = true;
                    break;
                default:
                    break;
            }
            $.fn.setDataSoloXover(1, 3);
        }
        $.fn.drawPEQWidget(peqSoloSelected);
    });

    //MANAGE EVENT ON ENABLE CHECKBOX XOVER OVERIDE PANEL HP
    $("body").on("change", "#enaToggleHighPassXOVEROveride", function() {
        switch (localAmplifier.channel[soloChannelSelected].xover.hpSpeakerPresetOveride) {
            case true:
                localAmplifier.channel[soloChannelSelected].xover.hpSpeakerPresetOveride = false;
                break;
            case false:
                localAmplifier.channel[soloChannelSelected].xover.hpSpeakerPresetOveride = true;
                break;
            default:
                break;
        }
        $.fn.setDataSoloXover(10, 0);
    });

    //MANAGE EVENT ON ENABLE CHECKBOX XOVER OVERIDE PANEL LP
    $("body").on("change", "#enaToggleLowPassXOVEROveride", function() {
        switch (localAmplifier.channel[soloChannelSelected].xover.lpSpeakerPresetOveride) {
            case true:
                localAmplifier.channel[soloChannelSelected].xover.lpSpeakerPresetOveride = false;
                break;
            case false:
                localAmplifier.channel[soloChannelSelected].xover.lpSpeakerPresetOveride = true;
                break;
            default:
                break;
        }
        $.fn.setDataSoloXover(11, 0);
    });

    //MANAGE EVENT ON XOVER FREQ DOWN HIGHPASS BUTTON
    $("body").on("click", "#xoverHPFreqDownButton", function() {
        displayVal("hpfreq", localAmplifier.channel[soloChannelSelected].xover.hpFreq);
        if (localAmplifier.channel[soloChannelSelected].xover.hpFreq > freqScaleMinPEQ) {
            localAmplifier.channel[soloChannelSelected].xover.hpFreq = parseInt(localAmplifier.channel[soloChannelSelected].xover.hpFreq) - 1;
            $.fn.setDataSoloXover(0, 2);
        }
    });

    //MANAGE EVENT ON XOVER FREQ UP HIGHPASS BUTTON
    $("body").on("click", "#xoverHPFreqUpButton", function() {
        if (localAmplifier.channel[soloChannelSelected].xover.hpFreq < freqScaleMaxPEQ) {
            localAmplifier.channel[soloChannelSelected].xover.hpFreq = parseInt(localAmplifier.channel[soloChannelSelected].xover.hpFreq) + 1;
            $.fn.setDataSoloXover(0, 2);
        }
    });

    //MANAGE EVENT ON XOVER FREQ DOWN LOWPASS BUTTON
    $("body").on("click", "#xoverLPFreqDownButton", function() {
        if (localAmplifier.channel[soloChannelSelected].xover.lpFreq > freqScaleMinPEQ) {
            localAmplifier.channel[soloChannelSelected].xover.lpFreq = parseInt(localAmplifier.channel[soloChannelSelected].xover.lpFreq) - 1;
            $.fn.setDataSoloXover(1, 5);
        }
    });

    //MANAGE EVENT ON XOVER FREQ UP LOWPASS BUTTON
    $("body").on("click", "#xoverLPFreqUpButton", function() {
        if (localAmplifier.channel[soloChannelSelected].xover.lpFreq < freqScaleMaxPEQ) {
            localAmplifier.channel[soloChannelSelected].xover.lpFreq = parseInt(localAmplifier.channel[soloChannelSelected].xover.lpFreq) + 1;
            $.fn.setDataSoloXover(1, 5);
        }
    });

    $("body").on("click", "#firXover", function(e) {
        $("#firPresetUpdateFile").attr("accept", firExtension);
        $("#firPresetUpdateFile").val("");
        $("#firUploadFileStatus").html("<div class=\"status progress\"></div>Select a FIR table file");
        $("#firPresetUpdateModal").modal("show");
    })

    $("body").on("change", "#firPresetUpdateFile", function(e) {
        var firName = "";
        firTableStatus = 0;
        // console.log("click upload file");
        var fullPath = $("#firPresetUpdateFile").val();
        if (fullPath) {
            var startIndex = (fullPath.indexOf('\\') >= 0 ? fullPath.lastIndexOf('\\') : fullPath.lastIndexOf('/'));
            var filename = fullPath.substring(startIndex);
            if (filename.indexOf('\\') === 0 || filename.indexOf('/') === 0) {
                filename = filename.substring(1);
            }
            filename = filename.replace(speakerPresetExtension, '');
            firName = filename;
        }

        var files = e.target.files;
        // updateTempFile = files;
        var input = e.target;
        var reader = new FileReader();
        var retJson = "";
        reader.onload = function(event) {
            // console.log("on load");

            try {
                retJson = reader.result;
                var lines = retJson.split("\n");
                // console.log(lines.length);
                if (lines[lines.length - 1] === "")
                    lines.pop();
                // console.log(lines.length);
                var ret = $.fn.checkFirFile(lines);
                if (ret === 0) {
                    // OK OK UPLOAD CAN START
                    firTable = $.fn.formatFirFile(lines);
                    localAmplifier.channel[soloChannelSelected].fir.firCoeffTemp = firTable;
                    localAmplifier.channel[soloChannelSelected].fir.firNameTemp = firName;
                    firTableStatus = 1;
                    $("#firUploadFileStatus").html("<div class=\"status open\"></div>File ok, ready to upload ");
                } else {
                    firTable = "";
                    firTableStatus = 0;
                    $("#firUploadFileStatus").html("<div class=\"status dead\"></div>File error : " + ret);
                }
            } catch (e) {
                // console.log("Error file reading" + files[0].name + " : " + e.message);
                firTable = "";
                firTableStatus = 0;
                $("#firUploadFileStatus").html("<div class=\"status dead\"></div>JSON parse error");
            }
        }
        reader.readAsText(files[0]);
    });

    $("body").on("click", "#firPresetUpdateActionButton", function(e) {
        // CHECK IF FILE IS OK FOR UPLOAD
        if (firTableStatus === 1) {
            localAmplifier.channel[soloChannelSelected].fir.firEnable = true;
            localAmplifier.channel[soloChannelSelected].fir.firName = localAmplifier.channel[soloChannelSelected].fir.firNameTemp;
            $.fn.setDataSoloXover(7, 99);
            $("#firPresetUpdateModal").modal("hide");
        }
    });

    //////////////////////////////////////////////////////////
    ////           LIMITER PANEL BUTTON AREA              ////
    //////////////////////////////////////////////////////////

    //MANAGE EVENT ON SOLO LIMITER RMS THRESHOLD BUTTON DOWN
    $("body").on("click", ".thresRmsSoloLimiterBtnDown", function() {
        if (localAmplifier.channel[soloChannelSelected].limiter.rmsThres > rmsThresScaleMin) {
            localAmplifier.channel[soloChannelSelected].limiter.rmsThres = parseFloat(parseFloat(localAmplifier.channel[soloChannelSelected].limiter.rmsThres - 0.1).toFixed(1));
            $.fn.setDataSoloLimiter(0, 0);
        }
    });

    //MANAGE EVENT ON SOLO LIMITER RMS THRESHOLD BUTTON UP
    $("body").on("click", ".thresRmsSoloLimiterBtnUp", function() {
        if (localAmplifier.channel[soloChannelSelected].limiter.rmsThres < rmsThresScaleMax) {
            localAmplifier.channel[soloChannelSelected].limiter.rmsThres = parseFloat(parseFloat(localAmplifier.channel[soloChannelSelected].limiter.rmsThres + 0.1).toFixed(1));
            $.fn.setDataSoloLimiter(0, 0);
        }
    });

    //MANAGE EVENT ON SOLO LIMITER RMS THRESHOLD INPUT
    $("body").on("change", "#thresRmsSoloLimiterInput", function() {
        if (!$.isNumeric(this.value)) {
            alert("THRESHOLD VALUE BETWEEN " + rmsThresScaleMin + " and " + rmsThresScaleMax);
            $("#thresRmsSoloLimiterInput").val(localAmplifier.channel[soloChannelSelected].limiter.rmsThres);
        } else {
            var n = parseFloat(parseFloat(this.value).toFixed(1));
            if (n < rmsThresScaleMin)
                n = rmsThresScaleMin;
            if (n > rmsThresScaleMax)
                n = rmsThresScaleMax;
            localAmplifier.channel[soloChannelSelected].limiter.rmsThres = parseFloat(n);
            $.fn.setDataSoloLimiter(0, 0);
        }
    });

    //MANAGE EVENT ON SOLO LIMITER RMS ATTACK BUTTON DOWN
    $("body").on("click", ".attackRmsSoloLimiterBtnDown", function() {
        if (localAmplifier.channel[soloChannelSelected].limiter.rmsAttack > rmsAttackScaleMin) {
            localAmplifier.channel[soloChannelSelected].limiter.rmsAttack = parseFloat(parseFloat(localAmplifier.channel[soloChannelSelected].limiter.rmsAttack - 0.1).toFixed(1));
            $.fn.setDataSoloLimiter(0, 1);
        }
    });

    //MANAGE EVENT ON SOLO LIMITER RMS ATTACK BUTTON UP
    $("body").on("click", ".attackRmsSoloLimiterBtnUp", function() {
        if (localAmplifier.channel[soloChannelSelected].limiter.rmsAttack < rmsAttackScaleMax) {
            localAmplifier.channel[soloChannelSelected].limiter.rmsAttack = parseFloat(parseFloat(localAmplifier.channel[soloChannelSelected].limiter.rmsAttack + 0.1).toFixed(1));
            $.fn.setDataSoloLimiter(0, 1);
        }
    });

    //MANAGE EVENT ON SOLO LIMITER RMS ATTACK INPUT
    $("body").on("change", "#attackRmsSoloLimiterInput", function() {
        if (!$.isNumeric(this.value)) {
            alert("ATTACK VALUE BETWEEN " + rmsAttackScaleMin + " and " + rmsAttackScaleMax);
            $("#attackRmsSoloLimiterInput").val(localAmplifier.channel[soloChannelSelected].limiter.rmsAttack);
        } else {
            var n = parseFloat(parseFloat(this.value).toFixed(1));
            if (n < rmsAttackScaleMin)
                n = rmsAttackScaleMin;
            if (n > rmsAttackScaleMax)
                n = rmsAttackScaleMax;
            localAmplifier.channel[soloChannelSelected].limiter.rmsAttack = n;
            $.fn.setDataSoloLimiter(0, 1);
        }
    });

    //MANAGE EVENT ON SOLO LIMITER RMS RELEASE BUTTON DOWN
    $("body").on("click", ".releaseRmsSoloLimiterBtnDown", function() {
        if (localAmplifier.channel[soloChannelSelected].limiter.rmsRelease > rmsReleaseScaleMin) {
            localAmplifier.channel[soloChannelSelected].limiter.rmsRelease = parseFloat(parseFloat(localAmplifier.channel[soloChannelSelected].limiter.rmsRelease - 0.1).toFixed(1));
            $.fn.setDataSoloLimiter(0, 2);
        }
    });

    //MANAGE EVENT ON SOLO LIMITER RMS RELEASE BUTTON UP
    $("body").on("click", ".releaseRmsSoloLimiterBtnUp", function() {
        if (localAmplifier.channel[soloChannelSelected].limiter.rmsRelease < rmsReleaseScaleMax) {
            localAmplifier.channel[soloChannelSelected].limiter.rmsRelease = parseFloat(parseFloat(localAmplifier.channel[soloChannelSelected].limiter.rmsRelease + 0.1).toFixed(1));
            $.fn.setDataSoloLimiter(0, 2);
        }
    });

    //MANAGE EVENT ON SOLO LIMITER RMS RELEASE INPUT
    $("body").on("change", "#releaseRmsSoloLimiterInput", function() {
        if (!$.isNumeric(this.value)) {
            alert("RELEASE VALUE BETWEEN " + rmsReleaseScaleMin + " and " + rmsReleaseScaleMax);
            $("#releaseRmsSoloLimiterInput").val(localAmplifier.channel[soloChannelSelected].limiter.rmsRelease);
        } else {
            var n = parseFloat(parseFloat(this.value).toFixed(1));
            if (n < rmsReleaseScaleMin)
                n = rmsReleaseScaleMin;
            if (n > rmsReleaseScaleMax)
                n = rmsReleaseScaleMax;
            localAmplifier.channel[soloChannelSelected].limiter.rmsRelease = n;
            $.fn.setDataSoloLimiter(0, 2);
        }
    });

    //MANAGE EVENT ON SOLO LIMITER PEAK THRESHOLD BUTTON DOWN
    $("body").on("click", ".thresPeakSoloLimiterBtnDown", function() {
        if (localAmplifier.channel[soloChannelSelected].limiter.peakThres > peakThresScaleMin) {
            localAmplifier.channel[soloChannelSelected].limiter.peakThres = parseFloat(parseFloat(localAmplifier.channel[soloChannelSelected].limiter.peakThres - 0.1).toFixed(1));
            $.fn.setDataSoloLimiter(0, 3);
        }
    });

    //MANAGE EVENT ON SOLO LIMITER PEAK THRESHOLD BUTTON UP
    $("body").on("click", ".thresPeakSoloLimiterBtnUp", function() {
        if (localAmplifier.channel[soloChannelSelected].limiter.peakThres < peakThresScaleMax) {
            localAmplifier.channel[soloChannelSelected].limiter.peakThres = parseFloat(parseFloat(localAmplifier.channel[soloChannelSelected].limiter.peakThres + 0.1).toFixed(1));
            $.fn.setDataSoloLimiter(0, 3);
        }
    });

    //MANAGE EVENT ON SOLO LIMITER PEAK THRESHOLD RELEASE INPUT
    $("body").on("change", "#thresPeakSoloLimiterInput", function() {
        if (!$.isNumeric(this.value)) {
            alert("THRESHOLD VALUE BETWEEN " + peakThresScaleMin + " and " + peakThresScaleMax);
            $("#thresPeakSoloLimiterInput").val(localAmplifier.channel[soloChannelSelected].limiter.peakThres);
        } else {
            var n = parseFloat(parseFloat(this.value).toFixed(1));
            if (n < peakThresScaleMin)
                n = peakThresScaleMin;
            if (n > peakThresScaleMax)
                n = peakThresScaleMax;
            localAmplifier.channel[soloChannelSelected].limiter.peakThres = n;
            $.fn.setDataSoloLimiter(0, 3);
        }
    });

    //MANAGE EVENT ON SOLO LIMITER PEAK RELEASE BUTTON DOWN
    $("body").on("click", ".releasePeakSoloLimiterBtnDown", function() {
        if (localAmplifier.channel[soloChannelSelected].limiter.peakRelease > peakReleaseScaleMin) {
            localAmplifier.channel[soloChannelSelected].limiter.peakRelease = parseFloat(parseFloat(localAmplifier.channel[soloChannelSelected].limiter.peakRelease - 0.1).toFixed(1));
            $.fn.setDataSoloLimiter(0, 4);
        }
    });

    //MANAGE EVENT ON SOLO LIMITER PEAK RELEASE BUTTON UP
    $("body").on("click", ".releasePeakSoloLimiterBtnUp", function() {
        if (localAmplifier.channel[soloChannelSelected].limiter.peakRelease < peakReleaseScaleMax) {
            localAmplifier.channel[soloChannelSelected].limiter.peakRelease = parseFloat(parseFloat(localAmplifier.channel[soloChannelSelected].limiter.peakRelease + 0.1).toFixed(1));
            $.fn.setDataSoloLimiter(0, 4);
        }
    });

    //MANAGE EVENT ON SOLO LIMITER PEAK RELEASE RELEASE INPUT
    $("body").on("change", "#releasePeakSoloLimiterInput", function() {
        if (!$.isNumeric(this.value)) {
            alert("RELEASE VALUE BETWEEN " + peakReleaseScaleMin + " and " + peakReleaseScaleMax);
            $("#releasePeakSoloLimiterInput").val(localAmplifier.channel[soloChannelSelected].limiter.peakRelease);
        } else {
            var n = parseFloat(parseFloat(this.value).toFixed(1));
            if (n < peakReleaseScaleMin)
                n = peakReleaseScaleMin;
            if (n > peakReleaseScaleMax)
                n = peakReleaseScaleMax;
            localAmplifier.channel[soloChannelSelected].limiter.peakRelease = n;
            $.fn.setDataSoloLimiter(0, 4);
        }
    });

    //MANAGE RMS CALCULATOR BUTTON
    $("body").on("click", "#rmsCalculator", function(e) {
        // console.log("rms calculator");
        $("#hpfRmsInput").val(localAmplifier.channel[soloChannelSelected].xover.hpFreq);
        $("#hpfRmsInput").trigger("change");
        var voltRms = 0.0;
        voltRms = Math.pow(parseFloat(localAmplifier.channel[soloChannelSelected].limiter.rmsThres), 2) / loadTable[$("#rmsCalculatorOutputLoadSelect option:selected").val()];
        $("#maxRmsOutputPowerValue").val(parseFloat(voltRms.toFixed(1)));
        $("#maxRmsOutputPowerValue").trigger("change");
        $("#maxVRmsInput").val(localAmplifier.channel[soloChannelSelected].limiter.rmsThres);
        $("#rmsCalculatorOutputLoadSelect").val(3);
        $("#rmsCalculatorOutputLoadSelect").trigger("change");
        $("#rmsCalculatorModal").modal("show");
    });

    $("body").on("change", "#rmsCalculatorOutputLoadSelect", function(e) {
        var power = 0.0;
        if ($("#rmsCalculatorOutputLoadSelect option:selected").val() === "5") {
            $('#maxRmsOutputPowerValue').hide();
            power = 70.0;
        } else if ($("#rmsCalculatorOutputLoadSelect option:selected").val() === "6") {
            $('#maxRmsOutputPowerValue').hide();
            power = 100.0;
        } else {
            $('#maxRmsOutputPowerValue').show();
            power = parseFloat($("#maxRmsOutputPowerValue").val()) * loadTable[$("#rmsCalculatorOutputLoadSelect").val()];
            power = Math.sqrt(power)
        }
        $("#maxVRmsInput").val(power.toFixed(1));
    });

    $("body").on("change", "#maxRmsOutputPowerValue", function(e) {
        if ($.isNumeric($("#maxRmsOutputPowerValue").val())) {
            $("#maxRmsOutputPowerValue").removeClass("is-invalid");
            var power = 0.0;
            if ($("#rmsCalculatorOutputLoadSelect option:selected").val() != 5 && $("#rmsCalculatorOutputLoadSelect option:selected").val() != 6) {
                power = parseFloat($("#maxRmsOutputPowerValue").val()) * loadTable[$("#rmsCalculatorOutputLoadSelect").val()];
                power = Math.sqrt(power);
                if (power > rmsThresScaleMax) {
                    power = rmsThresScaleMax;
                    var voltRms = 0.0;
                    voltRms = Math.pow(rmsThresScaleMax, 2) / loadTable[$("#rmsCalculatorOutputLoadSelect option:selected").val()];
                    $("#maxRmsOutputPowerValue").val(parseFloat(voltRms.toFixed(1)));
                } else if (power < rmsThresScaleMin) {
                    power = rmsThresScaleMin;
                    var voltPeak = 0.0;
                    voltPeak = Math.pow(rmsThresScaleMin, 2) / loadTable[$("#peakCalculatorOutputLoadSelect option:selected").val()];
                    $("#maxRmsOutputPowerValue").val(parseFloat(voltPeak.toFixed(1)));
                }
                $("#maxVRmsInput").val(power.toFixed(1));
            }
        } else {
            $("#maxRmsOutputPowerValue").addClass("is-invalid");
        }
    });

    $("body").on("change", "#hpfRmsInput", function(e) {
        if ($.isNumeric($("#hpfRmsInput").val())) {
            $("#hpfRmsInput").removeClass("is-invalid");
            if (parseInt($("#hpfRmsInput").val()) < freqScaleMinPEQ)
                $("#hpfRmsInput").val(freqScaleMinPEQ);
            if (parseInt($("#hpfRmsInput").val()) > freqScaleMaxPEQ)
                $("#hpfRmsInput").val(freqScaleMaxPEQ);

            var atT = 0.0;
            var reT = 0.0;
            atT = 1000 / (parseInt($("#hpfRmsInput").val()));
            reT = 16 * atT;
            if (parseFloat(atT) > rmsAttackScaleMax)
                atT = rmsAttackScaleMax;
            if (parseFloat(reT) > rmsReleaseScaleMax)
                reT = rmsReleaseScaleMax;
            $("#attackRmsInput").val(atT.toFixed(1));
            $("#releaseRmsInput").val(reT.toFixed(1));
        } else {
            $("#hpfRmsInput").addClass("is-invalid");
        }
    });

    $("body").on("click", "#rmsModalSave", function(e) {
        if (parseFloat($("#maxVRmsInput").val()) < rmsThresScaleMin)
            $("#maxVRmsInput").val(rmsThresScaleMin);
        if (parseFloat($("#maxVRmsInput").val()) > rmsThresScaleMax)
            $("#maxVRmsInput").val(rmsThresScaleMax);

        if (parseFloat($("#attackRmsInput").val()) < rmsAttackScaleMin)
            $("#attackRmsInput").val(rmsAttackScaleMin);
        if (parseFloat($("#attackRmsInput").val()) > rmsAttackScaleMax)
            $("#attackRmsInput").val(rmsAttackScaleMax);

        if (parseFloat($("#releaseRmsInput").val()) < rmsReleaseScaleMin)
            $("#releaseRmsInput").val(rmsReleaseScaleMin);
        if (parseFloat($("#releaseRmsInput").val()) > rmsReleaseScaleMax)
            $("#releaseRmsInput").val(rmsReleaseScaleMax);

        var val = 0.0;
        val = parseFloat($("#maxVRmsInput").val());
        localAmplifier.channel[soloChannelSelected].limiter.rmsThres = parseFloat(val.toFixed(1));
        val = parseFloat($("#attackRmsInput").val());
        localAmplifier.channel[soloChannelSelected].limiter.rmsAttack = parseFloat(val.toFixed(1));
        val = parseFloat($("#releaseRmsInput").val());
        localAmplifier.channel[soloChannelSelected].limiter.rmsRelease = parseFloat(val.toFixed(1));

        $.fn.setDataSoloLimiter(0, 5);

        $("#rmsCalculatorModal").modal("hide");
    });

    //MANAGE PEAK CALCULATOR BUTTON
    $("body").on("click", "#peakCalculator", function(e) {
        // console.log("peak calculator");
        $("#hpfPeakInput").val(localAmplifier.channel[soloChannelSelected].xover.hpFreq);
        $("#hpfPeakInput").trigger("change");
        var voltRms = 0.0;
        voltRms = Math.pow(parseFloat(localAmplifier.channel[soloChannelSelected].limiter.rmsThres), 2) / loadTable[$("#peakCalculatorOutputLoadSelect option:selected").val()];
        $("#maxPeakOutputPowerValue").val(parseFloat(voltRms.toFixed(1)));
        $("#maxPeakOutputPowerValue").trigger("change");
        $("#maxVPeakInput").val(localAmplifier.channel[soloChannelSelected].limiter.rmsThres);
        $("#peakCalculatorOutputLoadSelect").val(3);
        $("#peakCalculatorOutputLoadSelect").trigger("change");
        $("#peakCalculatorModal").modal("show");
    });

    $("body").on("change", "#peakCalculatorOutputLoadSelect", function(e) {
        var power = 0.0;
        if ($("#peakCalculatorOutputLoadSelect option:selected").val() === "5") {
            $('#maxPeakOutputPowerValue').hide();
            power = 98.9;
        } else if ($("#peakCalculatorOutputLoadSelect option:selected").val() === "6") {
            $('#maxPeakOutputPowerValue').hide();
            power = 141.4;
        } else {
            $('#maxPeakOutputPowerValue').show();
            power = parseFloat($("#maxPeakOutputPowerValue").val()) * loadTable[$("#peakCalculatorOutputLoadSelect").val()];
            power = Math.sqrt(power)
        }
        $("#maxVPeakInput").val(power.toFixed(1));
    });

    $("body").on("change", "#maxPeakOutputPowerValue", function(e) {
        if ($.isNumeric($("#maxPeakOutputPowerValue").val())) {
            $("#maxPeakOutputPowerValue").removeClass("is-invalid");
            var power = 0.0;
            if ($("#peakCalculatorOutputLoadSelect option:selected").val() != 5 && $("#peakCalculatorOutputLoadSelect option:selected").val() != 6) {
                power = parseFloat($("#maxPeakOutputPowerValue").val()) * loadTable[$("#peakCalculatorOutputLoadSelect").val()];
                power = Math.sqrt(power);
                if (power > peakThresScaleMax) {
                    power = peakThresScaleMax;
                    var voltPeak = 0.0;
                    voltPeak = Math.pow(peakThresScaleMax, 2) / loadTable[$("#peakCalculatorOutputLoadSelect option:selected").val()];
                    $("#maxPeakOutputPowerValue").val(parseFloat(voltPeak.toFixed(1)));
                } else if (power < peakThresScaleMin) {
                    power = peakThresScaleMin;
                    var voltPeak = 0.0;
                    voltPeak = Math.pow(peakThresScaleMin, 2) / loadTable[$("#peakCalculatorOutputLoadSelect option:selected").val()];
                    $("#maxPeakOutputPowerValue").val(parseFloat(voltPeak.toFixed(1)));
                }
                $("#maxVPeakInput").val(power.toFixed(1));
            }
        } else {
            $("#maxPeakOutputPowerValue").addClass("is-invalid");
        }
    });

    $("body").on("change", "#hpfPeakInput", function(e) {
        if ($.isNumeric($("#hpfPeakInput").val())) {
            $("#hpfPeakInput").removeClass("is-invalid");
            if (parseInt($("#hpfPeakInput").val()) < freqScaleMinPEQ)
                $("#hpfPeakInput").val(freqScaleMinPEQ);
            if (parseInt($("#hpfPeakInput").val()) > freqScaleMaxPEQ)
                $("#hpfPeakInput").val(freqScaleMaxPEQ);

            var atT = 0.0;
            var reT = 0.0;
            atT = 1000 / (parseInt($("#hpfPeakInput").val()));
            reT = 16 * atT;
            if (parseFloat(reT) > peakReleaseScaleMax)
                reT = peakReleaseScaleMax;
            $("#releasePeakInput").val(reT.toFixed(1));
        } else {
            $("#hpfPeakInput").addClass("is-invalid");
        }
    });

    $("body").on("click", "#peakModalSave", function(e) {
        if (parseFloat($("#maxVPeakInput").val()) < peakThresScaleMin)
            $("#maxVPeakInput").val(peakThresScaleMin);
        if (parseFloat($("#maxVPeakInput").val()) > peakThresScaleMax)
            $("#maxVPeakInput").val(peakThresScaleMax);

        if (parseFloat($("#releasePeakInput").val()) < peakReleaseScaleMin)
            $("#releasePeakInput").val(peakReleaseScaleMin);
        if (parseFloat($("#releasePeakInput").val()) > peakReleaseScaleMax)
            $("#releasePeakInput").val(peakReleaseScaleMax);

        var val = 0.0;
        val = parseFloat($("#maxVPeakInput").val());
        localAmplifier.channel[soloChannelSelected].limiter.peakThres = parseFloat(val.toFixed(1));
        val = parseFloat($("#releasePeakInput").val());
        localAmplifier.channel[soloChannelSelected].limiter.peakRelease = parseFloat(val.toFixed(1));

        $.fn.setDataSoloLimiter(0, 6);

        $("#peakCalculatorModal").modal("hide");
    });

    //////////////////////////////////////////////////////////
    ////          MANAGE PANEL BUTTON AREA                ////
    //////////////////////////////////////////////////////////

    //MANAGE EVENT ON CLICK ON FOLDER ON FOLDER LISTS
    $("body").on("click", "#folderListSpeaker>tbody>tr", function(e) {
        var idSource = this.firstChild.id;
        var num = this.firstChild.id.toString().match(/(\d+)/g).map(Number);

        //IF USER SELECT ANOTHER FOLDER
        if (num != soloFolderSpeakerSelected) {
            // console.log("folder:" + num);
            soloFolderSpeakerSelected = parseInt(num);
            soloFileSpeakerSelected = 0;
            $.fn.setDataSoloSpeaker(100);
        }
    });

    //MANAGE EVENT ON CLICK ON FILE ON FILES LISTS
    $("body").on("click", "#fileListSpeaker>tbody>tr", function(e) {
        var idSource = this.firstChild.id;
        var num = this.firstChild.id.toString().match(/(\d+)/g).map(Number);

        //IF USER SELECT ANOTHER FILE
        if (num != soloFileSpeakerSelected) {
            // console.log("file:" + num);
            soloFileSpeakerSelected = parseInt(num);
            $.fn.setDataSoloSpeaker(100);
        }
    });

    //MANAGE EVENT ON MODAL CONFIRM LOAD SPEAKER PRESET
    $("body").on("click", "#loadConfirmSpeakerPresetButton", function(e) {
        // console.log("load preset");
        $("#loadSoloSpeakerPresetModal").modal("hide");
        $.fn.setDataSoloSpeaker(100);
    });

    //MANAGE EVENT ON GLOBAL PRESET LOAD PRESET BUTTON : BUTTON NAME : Load Preset
    $("body").on("click", "#loadPresetSpeakerBtn", function(e) {
        $("#speakerPresetModalTitle").html("Load Speaker Preset File");
        var modalContent = "";
        if (typeof localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].fileList[soloFileSpeakerSelected] === "undefined") {
            modalContent += "Please select a preset file first";
            $("#speakerPresetActionButton").html(globalPresetDeletePresetProtectedAction);
        } else {
            modalContent += "Load " + localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].fileList[soloFileSpeakerSelected].file_name;
            modalContent += " on <b> channel " + (soloChannelSelected + 1) + "</b> ?";
            $("#speakerPresetActionButton").html(globalPresetLoadPresetAction);
        }
        $("#speakerPresetModalContent").html(modalContent);
        $("#speakerPresetModal").modal("show");
    });

    //MANAGE EVENT ON GLOBAL PRESET EDIT PRESET BUTTON : BUTTON NAME : Save Preset
    $("body").on("click", "#editPresetSpeakerBtn", function(e) {
        $("#speakerPresetModalTitle").html("Save Speaker Preset File");
        var modalContent = "";
        if (typeof localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].fileList[soloFileSpeakerSelected] === "undefined") {
            modalContent += "Please select a preset file first";
            $("#speakerPresetActionButton").html(globalPresetDeletePresetProtectedAction);
        } else if (localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].file_name != protectedFolderName) {
            modalContent += "Save " + localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].fileList[soloFileSpeakerSelected].file_name + " ?";
            modalContent += "<br>";
            modalContent += "<label class=\"form-check-label\" for=\"saveAsAuthor\">Author :</label>";
            modalContent += "<input id=\"saveAsAuthor\" class=\" form-control form-control-sm\" placeHolder=\"File name\"></input>";
            modalContent += "<label class=\"form-check-label\" for=\"saveAsVersion\">Version :</label>";
            modalContent += "<input id=\"saveAsVersion\" class=\" form-control form-control-sm\" placeHolder=\"File name\"></input>";
            modalContent += "<label class=\"form-check-label\" for=\"saveAsNote\">Note :</label>";
            modalContent += "<input id=\"saveAsNote\" class=\" form-control form-control-sm\" placeHolder=\"File name\"></input>";
            if (oemCodeUI != "") {
                modalContent += "<div class=\"form-group form-check row\">";
                modalContent += "<div class=\"col-sm-10 offset-sm-4\">";
                modalContent += "<input id=\"oemProtectedCheckbox\"  type=\"checkbox\" class=\"form-check-input\"></input>";
                modalContent += "<label class=\"form-check-label\" for=\"oemProtectedCheckbox\">OEM locked</label>";
                modalContent += "<\div>";
                modalContent += "<\div>";
            }
            $("#speakerPresetActionButton").html(globalPresetEditPresetAction);
        } else {
            modalContent += protectedFolderName + " is protected";
            $("#speakerPresetActionButton").html(globalPresetDeleteFolderProtectedAction);
        }
        $("#speakerPresetModalContent").html(modalContent);
        $("#saveAsAuthor").val(localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].fileList[soloFileSpeakerSelected].author);
        $("#saveAsVersion").val(localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].fileList[soloFileSpeakerSelected].version);
        $("#saveAsNote").val(localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].fileList[soloFileSpeakerSelected].note);
        if (localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].fileList[soloFileSpeakerSelected].oem)
            $("#oemProtectedCheckbox").attr("checked", true);
        $("#speakerPresetModal").modal("show");
    });

    //MANAGE EVENT ON GLOBAL PRESET RENAME PRESET BUTTON : BUTTON NAME : Save As Preset
    $("body").on("click", "#renamePresetSpeakerBtn", function(e) {
        $("#speakerPresetModalTitle").html("Save As Speaker Preset File");
        var modalContent = "";

        if (localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].file_name != protectedFolderName) {
            modalContent += "Save as <input id=\"saveAsFileNameModal\"  type=\"text\" class=\" form-control form-control-sm\" placeHolder=\"File name\"></input>";
            modalContent += "<label class=\"form-check-label\" for=\"saveAsAuthor\">Author :</label>";
            modalContent += "<input id=\"saveAsAuthor\" class=\" form-control form-control-sm\" placeHolder=\"File name\"></input>";
            modalContent += "<label class=\"form-check-label\" for=\"saveAsVersion\">Version :</label>";
            modalContent += "<input id=\"saveAsVersion\" class=\" form-control form-control-sm\" placeHolder=\"File name\"></input>";
            modalContent += "<label class=\"form-check-label\" for=\"saveAsNote\">Note :</label>";
            modalContent += "<input id=\"saveAsNote\" class=\" form-control form-control-sm\" placeHolder=\"File name\"></input>";
            if (oemCodeUI != "") {
                modalContent += "<div class=\"form-group form-check row\">";
                modalContent += "<div class=\"col-sm-10 offset-sm-4\">";
                modalContent += "<input id=\"oemProtectedCheckbox\"  type=\"checkbox\" class=\"form-check-input\"></input>";
                modalContent += "<label class=\"form-check-label\" for=\"oemProtectedCheckbox\">OEM locked</label>";
                modalContent += "<\div>";
                modalContent += "<\div>";
            }
            $("#speakerPresetActionButton").html(globalPresetSaveAsPresetAction);
        } else {
            modalContent += protectedFolderName + " is protected";
            $("#speakerPresetActionButton").html(globalPresetDeleteFolderProtectedAction);
        }
        $("#speakerPresetModalContent").html(modalContent);
        $("#speakerPresetModal").modal("show");
    });

    //MANAGE EVENT ON GLOBAL PRESET DELETE PRESET BUTTON : BUTTON NAME : Delete Preset
    $("body").on("click", "#deletePresetSpeakerBtn", function(e) {
        $("#speakerPresetModalTitle").html("Delete Speaker Preset file");
        var modalContent = "";
        if (typeof localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].fileList[soloFileSpeakerSelected] === "undefined") {
            modalContent += "Please select a preset file first";
            $("#speakerPresetActionButton").html(globalPresetDeletePresetProtectedAction);
        } else if (localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].name == protectedFolderName && localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].fileList[soloFileSpeakerSelected].file_name == protectedPresetName) {
            modalContent += protectedPresetName + " is protected";
            $("#speakerPresetActionButton").html(globalPresetDeletePresetProtectedAction);
        } else {
            modalContent += "Delete " + localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].fileList[soloFileSpeakerSelected].file_name + " ?";
            $("#speakerPresetActionButton").html(globalPresetDeletePresetAction);
        }
        $("#speakerPresetModalContent").html(modalContent);
        $("#speakerPresetModal").modal("show");
    });

    //MANAGE EVENT ON GLOBAL PRESET CREATE FOLDER BUTTON
    $("body").on("click", "#createFolderSpeakerBtn", function(e) {
        $("#speakerPresetModalTitle").html("Create New Speaker Preset Folder");
        var modalContent = "";

        modalContent += "Create <input id=\"createSpeakerFolderNameValue\"  type=\"text\" class=\" form-control form-control-sm\" placeHolder=\"Folder name\"></input><div class=\"invalid-feedback\">Folder name already used</div>";

        $("#speakerPresetModalContent").html(modalContent);
        $("#speakerPresetActionButton").html(globalPresetCreateFolderAction);
        $("#speakerPresetModal").modal("show");
    });

    //MANAGE EVENT ON GLOBAL PRESET RENAME FOLDER BUTTON
    $("body").on("click", "#renameFolderSpeakerBtn", function(e) {
        $("#speakerPresetModalTitle").html("Rename Speaker Preset Folder");
        var modalContent = "";

        modalContent += "Rename " + localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].name + " <input id=\"renameFolderNameModal\"  type=\"text\" class=\" form-control form-control-sm\" placeHolder=\"Folder name\"></input>";
        $("#speakerPresetModalContent").html(modalContent);

        $("#speakerPresetActionButton").html(globalPresetRenameFolderAction);
        $("#speakerPresetModal").modal("show");
    });

    //MANAGE EVENT ON GLOBAL PRESET DELETE FOLDER BUTTON
    $("body").on("click", "#deleteFolderSpeakerBtn", function(e) {

        $("#speakerPresetModalTitle").html("Delete Speaker Preset Folder");
        var modalContent = "";
        if (localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].name != protectedFolderName) {
            modalContent += "Delete " + localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].name + " ?";
            $("#speakerPresetActionButton").html(globalPresetDeleteFolderAction);
        } else {
            modalContent += protectedFolderName + " is protected";
            $("#speakerPresetActionButton").html(globalPresetDeleteFolderProtectedAction);
        }

        $("#speakerPresetModalContent").html(modalContent);
        $("#speakerPresetModal").modal("show");
    });

    //MANAGE EVENT ON GLOBAL PRESET DELETE FOLDER BUTTON
    $("body").on("click", "#refreshFolderSpeakerBtn", function(e) {
        $.fn.sendCommandWS(cmd_get_speaker_preset_folder_names, 0, "null", "null", "null");
    });

    $("body").on("click", "#speakerPresetActionButton", function(e) {
        var noAction = 0;
        var noHide = 0;
        var folderName;
        if (localAmplifier.folderSpeaker.folderList.length > 0) {
            if (localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].name.length > 0)
                folderName = localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].name;
            var fileName;
            if (localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].fileList.length > 0)
                fileName = localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].fileList[soloFileSpeakerSelected].file_name;
        }
        switch (e.target.innerHTML) {
            //CREATE FOLDER
            case globalPresetCreateFolderAction:
                if ($("#createSpeakerFolderNameValue").val().length > 0) {
                    let doubleFolder = 0
                    for (var i = 0; i < localAmplifier.folderSpeaker.folderList.length; i++) {
                        if (localAmplifier.folderSpeaker.folderList[i].name === $("#createSpeakerFolderNameValue").val())
                            doubleFolder++;
                    }
                    if (doubleFolder === 0)
                        $.fn.sendStringWS(cmd_create_speaker_preset_folder, 0, $("#createSpeakerFolderNameValue").val(), "null", "null");
                    else {
                        $(".invalid-feedback").addClass("d-block");
                        setTimeout(function() { $(".invalid-feedback").removeClass("d-block") }, 5000);
                        return;
                    }
                }
                break;
                //RENAME FOLDER
            case globalPresetRenameFolderAction:
                if ($("#renameFolderNameModal").val().length > 0) {
                    $.fn.sendStringWS(cmd_rename_speaker_preset_folder, 0, folderName, "null", $("#renameFolderNameModal").val());
                }
                break;
                //DELETE FOLDER
            case globalPresetDeleteFolderAction:
                // console.log("delete speaker preset folder : " + folderName);
                $.fn.sendStringWS(cmd_delete_speaker_preset_folder, 0, folderName, "null", "null");
                if (localAmplifier.folderSpeaker.folderList.length > 0)
                    soloFolderSpeakerSelected = 0;
                break;

                //LOAD PRESET
            case globalPresetLoadPresetAction:
                $("#presetLoader").addClass("is-active");
                $.fn.setDataSoloSpeaker(0);
                break;

            case globalPresetCreatePresetAction:
                if ($("#createGlobalFileNameModal").val().length > 0) {
                    $.fn.sendStringWS(cmd_create_speaker_preset_file, 0, folderName + "/" + $("#createGlobalFileNameModal").val(), soloChannelSelected, "null");
                }
                break;
                //SAVE PRESET
            case globalPresetEditPresetAction:
                var preset = { "author": "", "version": "", "note": "", "oem": false };
                preset.author = $("#saveAsAuthor").val();
                preset.version = $("#saveAsVersion").val();
                preset.note = $("#saveAsNote").val();
                if ($("#oemProtectedCheckbox").is(':checked'))
                    preset.oem = true;
                var presetString = JSON.stringify(preset);
                presetString = presetString.replaceAll("\"", "\\\"");
                $.fn.sendStringWS(cmd_edit_speaker_preset_file, 0, folderName + "/" + fileName, soloChannelSelected, presetString);
                break;
                //SAVE AS PRESET
            case globalPresetSaveAsPresetAction:
                if ($("#saveAsFileNameModal").val().length > 0) {
                    var preset = { "author": "", "version": "", "note": "", "oem": false };
                    preset.author = $("#saveAsAuthor").val();
                    preset.version = $("#saveAsVersion").val();
                    preset.note = $("#saveAsNote").val();
                    if ($("#oemProtectedCheckbox").is(':checked'))
                        preset.oem = true;
                    var presetString = JSON.stringify(preset);
                    presetString = presetString.replaceAll("\"", "\\\"");
                    $.fn.sendStringWS(cmd_create_speaker_preset_file, 0, folderName + "/" + $("#saveAsFileNameModal").val(), soloChannelSelected, presetString);
                }
                break;
                //DELETE PRESET
            case globalPresetDeletePresetAction:
                $.fn.sendStringWS(cmd_delete_speaker_preset_file, 0, folderName + "/" + fileName, "null", "null");
                if (localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].fileList.length > 0)
                    soloFileSpeakerSelected = 0;
                break;

            default:
                noAction = 1;
                break;
        }
        if (noHide != 1)
            $("#speakerPresetModal").modal("hide");

        if (noAction === 0 && noHide === 0) {
            setTimeout(function() { $.fn.sendCommandWS(cmd_get_speaker_preset_list_names, 0, "null", "null", "null"); }, 2000);
        }
    });

    // DOWNLOAD SPEAKER PRESET FOLDER
    $("body").on("click", "#downloadFolderPresetSpeakerBtn", function(e) {
        var folderName = null;
        if (localAmplifier.folderSpeaker.folderList.length > 0) {
            if (localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].name.length > 0)
                folderName = localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].name;
        }
        if (folderName) {
            downloadFolderSpeakerPresetName = folderName;
            $.fn.sendCommandWS(cmd_get_speaker_preset_files_from_folder, 0, folderName, "null", "null");
        }
    });

    // DOWNLOAD SPEAKER PRESET FILE
    $("body").on("click", "#downloadPresetSpeakerBtn", function(e) {
        var folderName = null;
        var fileName = null;
        if (localAmplifier.folderSpeaker.folderList.length > 0) {
            if (localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].name.length > 0)
                folderName = localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].name;
            var fileName;
            if (localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].fileList.length > 0)
                fileName = localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].fileList[soloFileSpeakerSelected].file_name;
        }

        if (fileName) {
            downloadSpeakerPresetName = fileName;
            $.fn.sendCommandWS(cmd_get_speaker_preset_file, 0, folderName + "/" + fileName, "null", "null");
        }
    });

    $("body").on("click", "#uploadPresetSpeakerBtn", function(e) {
        if (soloFolderSpeakerSelected != 0) {
            $("#speakerPresetUpdateFile").attr("accept", speakerPresetExtension);
            $("#speakerPresetUpdateFile").val("");
            $("#speakerUploadFileStatus").html("<div class=\"status progress\"></div>Select a speaker preset file");
            $("#speakerPresetUpdateActionButton").html("Upload");
            $(".warningUpload").html("");
            $("#speakerPresetUpdateModal").modal("show");
        } else {
            $("#speakerPresetUpdateFile").attr("accept", speakerPresetExtension);
            $("#speakerPresetUpdateFile").val("");
            $("#speakerUploadFileStatus").html("<div class=\"status progress\"></div>Factory Folder is protected");
            $("#speakerPresetUpdateActionButton").html(globalPresetDeleteFolderProtectedAction);
            $(".warningUpload").html("");
            $("#speakerPresetUpdateModal").modal("show");
        }
    })

    $("body").on("click", "#uploadFolderPresetSpeakerBtn", function(e) {
        if (soloFolderSpeakerSelected != 0) {
            $("#speakerPresetUpdateFile").attr("accept", speakerFolderPresetExtension);
            $("#speakerPresetUpdateFile").val("");
            $("#speakerUploadFileStatus").html("<div class=\"status progress\"></div>Select a folder speaker preset file");
            $("#speakerPresetUpdateActionButton").html("Upload in folder");
            $(".warningUpload").html("");
            $("#speakerPresetUpdateModal").modal("show");
        } else {
            $("#speakerPresetUpdateFile").attr("accept", speakerFolderPresetExtension);
            $("#speakerPresetUpdateFile").val("");
            $("#speakerUploadFileStatus").html("<div class=\"status progress\"></div>Factory Folder is protected");
            $("#speakerPresetUpdateActionButton").html(globalPresetDeleteFolderProtectedAction);
            $(".warningUpload").html("");
            $("#speakerPresetUpdateModal").modal("show");
        }
    })

    $("body").on("change", "#speakerPresetUpdateFile", function(e) {
        updateJsonFile = "";
        updateJsonName = "";
        updateJsonStatus = 0;
        // console.log("click upload file");
        var fullPath = $("#speakerPresetUpdateFile").val();
        if (fullPath) {
            var startIndex = (fullPath.indexOf('\\') >= 0 ? fullPath.lastIndexOf('\\') : fullPath.lastIndexOf('/'));
            var filename = fullPath.substring(startIndex);
            if (filename.indexOf('\\') === 0 || filename.indexOf('/') === 0) {
                filename = filename.substring(1);
            }
            filename = filename.replace(speakerPresetExtension, '');
            updateJsonName = filename;
        }

        var files = e.target.files;
        // updateTempFile = files;
        var input = e.target;
        var reader = new FileReader();
        var retJson = "";
        reader.onload = function(event) {
            console.log("on load");
            //TRY TO READ OLD PRESETS
            try {
                retJson = JSON.parse(reader.result);
                var ret = $.fn.checkUpdateSpeakerPreset(retJson);
                if (ret === 0) {
                    updateJsonFile = retJson;
                    updateJsonStatus = 1;
                    oldPreset = { "file_name": updateJsonName, "author": "", "version": "", "note": "", "oem_code": "0000000000", "settings": updateJsonFile };
                    updateJsonFile = oldPreset;
                    $("#speakerUploadFileStatus").html("<div class=\"status open\"></div>File ok, ready to upload \"" + updateJsonName + "\" in " + localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].name);
                } else {
                    // DISPLAY ERROR
                    // console.log("check json ko:" + $.fn.checkUpdateSpeakerPreset(retJson));
                    updateJsonFile = "";
                    updateJsonStatus = 0;
                }

            } catch (e) {
                //IF OLD PRESET FAIL TRY NEW ONE
                try {
                    var bytes = CryptoJS.AES.decrypt(reader.result.toString(), presetKey);
                    var plaintext = bytes.toString(CryptoJS.enc.Utf8);
                    retJson = plaintext;
                    // console.log("json:" + retJson);
                    retJson = JSON.parse(retJson);
                    var ret
                    if (retJson.hasOwnProperty("settings")) {
                        ret = $.fn.checkUpdateSpeakerPreset(retJson.settings);
                        if (retJson.oem_code.length > 0 && retJson.oem_code != "0")
                            $.fn.sendStringWS(cmd_oem_check_code, 0, "null", "null", retJson.oem_code);
                    } else {
                        ret = $.fn.checkUpdateSpeakerPreset(retJson);
                        if (retJson[0].oem_code.length > 0 && retJson[0].oem_code != "0")
                            $.fn.sendStringWS(cmd_oem_check_code, 0, "null", "null", retJson[0].oem_code);
                    }
                    if (ret === 0) {
                        // OK OK UPLOAD CAN START
                        updateJsonFile = retJson;
                        updateJsonStatus = 1;
                        $("#speakerUploadFileStatus").html("<div class=\"status open\"></div>File ok, ready to upload \"" + updateJsonName + "\" in " + localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].name);
                    } else {
                        // DISPLAY ERROR
                        updateJsonFile = "";
                        updateJsonStatus = 0;
                        $("#speakerUploadFileStatus").html("<div class=\"status dead\"></div>File error : " + ret);
                    }
                } catch (e) {
                    // console.log("Error file reading" + files[0].name + " : " + e.message);
                    updateJsonFile = "";
                    updateJsonStatus = 0;
                    $("#speakerUploadFileStatus").html("<div class=\"status dead\"></div>JSON parse error");
                }
            }



        }
        reader.readAsText(files[0]);
    });

    $("body").on("click", "#speakerPresetUpdateActionButton", function(e) {
        if ($("#speakerPresetUpdateActionButton").html() === globalPresetDeleteFolderProtectedAction)
            $("#speakerPresetUpdateModal").modal("hide");
        else {
            let doubleName = 0;
            for (var i = 0; i < localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].fileList.length; i++) {
                if (localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].fileList[i].file_name === updateJsonName)
                    doubleName++;
            }
            // CHECK IF FILE IS OK FOR UPLOAD
            if (updateJsonStatus === 1 && doubleName === 0) {
                // console.log("upload" + updateJsonName);
                if ($("#speakerPresetUpdateActionButton").html() == "Upload")
                    $.fn.uploadPreset(updateJsonFile);
                else
                    $.fn.uploadFolderPreset(updateJsonFile);
                $("#speakerPresetUpdateModal").modal("hide");
                $("#presetUploader").addClass("is-active");
            } else if (doubleName > 0) {
                $("#speakerUploadFileStatus").html("<div class=\"status dead\"></div>This folder already contains a preset with the same name. <br> Please change name file before uploading it.")
                $(".warningUpload").html("");
            }
        }
    });

    //////////////////////////////////////////////////////////
    ////             TBD PANEL BUTTON AREA                ////
    //////////////////////////////////////////////////////////




    //////////////////////////////////////////////////////////
    ////            LOADING PROCEDURE AREA                ////
    //////////////////////////////////////////////////////////

    window.addEventListener("resize", resize);

    $.fn.setupPeqSolo();

    $.fn.setupXOVERSolo();

    $.fn.initSlider();

    $.fn.initSliderPEQ();

    $.fn.initSliderXOVER();

    $.fn.initData();

    $.fn.hideMainPanel();

    $("#overviewButton0").trigger("click");

    resize();

    $.fn.setupLimiterSolo();

    $.fn.initSliderLimiter();

    $.fn.initXOVER(peqViewMode, peqGainScaleType, peqPhaseScaleType);

    $.fn.setDataSoloXover(4, 99);

    $.fn.drawXOVERWidget(0, highPassEqParam.type);
    $.fn.drawXOVERWidget(1, lowPassEqParam.type);

    $.fn.drawTickLabels();

    $.fn.resizeWindows();

    $.fn.createWebSocket();

    //SCALE VU METER TO ZERO AT LOAD WAITING FOR REAL TIME VALUE
    $("#gainSoloVuMeterCh0").css("transform", 'scaleY(0)');
    $("#vuMeterGRBGLimiterCh").css("transform", 'scaleY(0)');
    $("#vuMeterPeakBGLimiterCh").css("transform", 'scaleY(0)');
    $("#vuMeterOutputBGLimiterCh").css("transform", 'scaleY(0)');
})


// $.fn.setupChannelButton = function() {

//     var channelCount = 4;

//     for (var i = 0; i < channelCount; i++) {
//         let id = "overviewBG" + i;
//         let mute = "overviewButtonMute" + i;
//         let select = "overviewButton" + i;
//         $(".overviewChannelArea").append($("<div>").prop({ id: id, className: "backgroundSource bS" }));
//         $("#" + id).append($("<div>").prop({ className: "overviewButtonChannelNumber", innerHTML: labelOverviewChannel[i] }));
//         $("#" + id).append($("<button>").prop({ id: mute, className: "overviewButtonMute", innerHTML: "Mute" }));
//         $("#" + id).append($("<button>").prop({ id: select, className: "overviewButtonSelect oBS", innerHTML: "Select" }));
//     }
// }

//HIDE ALL MAIN PANELS
$.fn.hideMainPanel = function() {
    $("#configMainPanel").hide();
    $("#gainMainPanel").hide();
    $("#delayMainPanel").hide();
    $("#peqMainPanel").hide();
    $("#xoverMainPanel").hide();
    $("#limiterMainPanel").hide();
    $("#speakerMainPanel").hide();
};

$.fn.loadData = function() {
    //CHANNEL VIEW : GET THE SELECTED CHANNEL AND LOAD DATE

    //GAIN SETUP
    if ($("#gainMainPanel").is(":visible"))
        $("#overviewButtonMenuGain").trigger("click");

    //DELAY SETUP
    if ($("#delayMainPanel").is(":visible"))
        $("#overviewButtonMenuDelay").trigger("click");

    //PEQ SETUP
    if ($("#peqMainPanel").is(":visible"))
        $("#overviewButtonMenuPeq").trigger("click");

    //XOVER SETUP
    if ($("#xoverMainPanel").is(":visible"))
        $("#overviewButtonMenuXover").trigger("click");

    //LIMITER SETUP
    if ($("#limiterMainPanel").is(":visible"))
        $("#overviewButtonMenuLimiter").trigger("click");

    //SPEAKER SETUP
    if ($("#speakerMainPanel").is(":visible"))
        $.fn.setDataSoloSpeaker(100);
}

$.fn.clearDataCheck = function() {
    //CLEAR GAIN CHECK
    if (localAmplifier.channel[soloChannelSelected].gain.gain != clearGainValue || localAmplifier.channel[soloChannelSelected].gain.polarityEna != clearPolarityEnaValue)
        $("#overviewStatusGainActive").addClass("enable");
    else
        $("#overviewStatusGainActive").removeClass("enable");

    //CLEAR DELAY CHECK
    if (localAmplifier.channel[soloChannelSelected].delay.delay > clearDelayValue && localAmplifier.channel[soloChannelSelected].delay.delayEna != clearDelayEnaValue)
        $("#overviewStatusDelayActive").addClass("enable");
    else
        $("#overviewStatusDelayActive").removeClass("enable");

    //CLEAR PEQ CHECK
    var a = 0;
    for (var b = 0; b < peqCount; b++) {
        if (localAmplifier.channel[soloChannelSelected].peq.peq[b].ena === true && localAmplifier.channel[soloChannelSelected].peq.peq[b].gain != clearPEQGainValue)
            a++;
    }
    if (a > 0)
        $("#overviewStatusPEQActive").addClass("enable");
    else
        $("#overviewStatusPEQActive").removeClass("enable");

    //CLEAR XOVER CHECK
    if (localAmplifier.channel[soloChannelSelected].fir.firEnable || localAmplifier.channel[soloChannelSelected].xover.hpEna || localAmplifier.channel[soloChannelSelected].xover.lpEna || !$.fn.firIsEqual(localAmplifier.channel[soloChannelSelected].fir.firCoeff, clearFirTable))
        $("#overviewStatusXOVERActive").addClass("enable");
    else
        $("#overviewStatusXOVERActive").removeClass("enable");

    //CLEAR LIMITER CHECK
    if (localAmplifier.channel[soloChannelSelected].limiter.rmsThres < clearLimRmsThresValue || localAmplifier.channel[soloChannelSelected].limiter.rmsAttack != clearLimRmsAttackValue || localAmplifier.channel[soloChannelSelected].limiter.rmsRelease != clearLimRmsReleaseValue || localAmplifier.channel[soloChannelSelected].limiter.peakThres < clearLimPeakThresValue || localAmplifier.channel[soloChannelSelected].limiter.peakRelease != clearLimPeakReleaseValue)
        $("#overviewStatusLimiterActive").addClass("enable");
    else
        $("#overviewStatusLimiterActive").removeClass("enable");
}

//CREATE AND INITIALIZE SLIDERS
$.fn.initSlider = function() {
    // CREATE AND INITIALIZE 4 SLIDERS AND BIND THEM TO THE GAIN TEXTFIELD
    var idSlider = "#sliderVertical0";
    $(idSlider).slider({
        orientation: "vertical",
        range: "min",
        min: gainScaleMin,
        max: gainScaleMax,
        step: gainScaleStep,
        slide: function(event, ui) {
            localAmplifier.channel[soloChannelSelected].gain.gain = parseFloat(parseFloat(ui.value).toFixed(1));
            $.fn.setDataSoloGain(soloChannelSelected, 1);
        }
    });

    // CREATE AND INITIALIZE 4 SLIDERS AND BIND THEM TO THE DELAY TEXTFIELD
    var idSlider = "#sliderDelayVertical0";
    $(idSlider).slider({
        orientation: "vertical",
        range: "min",
        min: delayScaleMin,
        max: Math.log10(delayScaleMax),
        step: delayScaleStep,
        slide: function(event, ui) {
            if (ui.value === Math.log10(delayScaleMax)) {
                localAmplifier.channel[soloChannelSelected].delay.delay = delayScaleMax;
            } else if (ui.value === 0) {
                localAmplifier.channel[soloChannelSelected].delay.delay = delayScaleMin;
            } else {
                localAmplifier.channel[soloChannelSelected].delay.delay = parseFloat(Math.pow(10, ui.value).toFixed(2));
            }
            $.fn.setDataSoloDelay(soloChannelSelected, 1);
        }
    });
}

$.fn.initSliderLimiter = function() {
    //SLIDER THRESHOLD RMS STAGE LIMITER
    $("#thresRmsSoloLimiterSlider").slider({
        orientation: "horizontal",
        range: "min",
        min: rmsThresScaleMin,
        max: rmsThresScaleMax,
        step: 0.1,
        slide: function(event, ui) {
            localAmplifier.channel[soloChannelSelected].limiter.rmsThres = ui.value;
            $.fn.setDataSoloLimiter(0, 0);
        }
    });

    //SLIDER ATTACK RMS STAGE LIMITER
    $("#attackRmsSoloLimiterSlider").slider({
        orientation: "horizontal",
        range: "min",
        min: Math.log10(rmsAttackScaleMin),
        max: Math.log10(rmsAttackScaleMax),
        step: 0.00001,
        slide: function(event, ui) {
            localAmplifier.channel[soloChannelSelected].limiter.rmsAttack = Math.round(Math.pow(10, ui.value) * 10) / 10;
            $.fn.setDataSoloLimiter(0, 1);
        }
    });

    //SLIDER RELEASE RMS STAGE LIMITER
    $("#releaseRmsSoloLimiterSlider").slider({
        orientation: "horizontal",
        range: "min",
        min: Math.log10(rmsReleaseScaleMin),
        max: Math.log10(rmsReleaseScaleMax),
        step: 0.00001,
        // value: Math.log10(16.0),
        slide: function(event, ui) {
            localAmplifier.channel[soloChannelSelected].limiter.rmsRelease = Math.round(Math.pow(10, ui.value) * 10) / 10;
            $.fn.setDataSoloLimiter(0, 2);
        }
    });

    //SLIDER THRESHOLD PEAK STAGE LIMITER
    $("#thresPeakSoloLimiterSlider").slider({
        orientation: "horizontal",
        range: "min",
        min: peakThresScaleMin,
        max: peakThresScaleMax,
        step: 0.1,
        slide: function(event, ui) {
            localAmplifier.channel[soloChannelSelected].limiter.peakThres = ui.value;
            $.fn.setDataSoloLimiter(0, 3);
        }
    });

    //SLIDER RELEASE PEAK STAGE LIMITER
    $("#releasePeakSoloLimiterSlider").slider({
        orientation: "horizontal",
        range: "min",
        min: Math.log10(peakReleaseScaleMin),
        max: Math.log10(peakReleaseScaleMax),
        step: 0.00001,
        slide: function(event, ui) {
            localAmplifier.channel[soloChannelSelected].limiter.peakRelease = Math.round(Math.pow(10, ui.value) * 10) / 10;
            $.fn.setDataSoloLimiter(0, 4);
        }
    });
}

//DRAW TICK LABEL FOR SLIDERS
$.fn.drawTickLabels = function() {
    // DRAW TICK LABEL FOR VERTICAL GAIN SLIDER
    // console.log(winHeightFader);
    var c = document.getElementsByClassName("sliderContainerBackground");
    for (var k = 0; k < c.length; k++) {
        var ctx = c[k].getContext("2d");
        ctx.canvas.height = winHeightFader + 16;
        ctx.font = "8px Arial";
        ctx.fillStyle = "#ebeded";
        ctx.textAlign = "end";
        for (var j = 0; j < labelFader.length; j++) {
            var y = ((-(winHeightFader - 4) / 95.5) * labelFader[j]) + (15 * (winHeightFader - 4) / 95);
            // console.log("valeur label : " + labelFader[j] + " // valeur compute " + y);
            if (labelFaderMark[j] != 0) {
                ctx.fillRect(0, y + 10, 40, 2);
                ctx.fillText(labelFader[j], 52, y + 13);
            } else {
                ctx.fillRect(5, y + 10, 30, 1);
                ctx.fillText(labelFader[j], 52, y + 13);
            }
        }
        ctx.stroke();
    }

    // DRAW TICK LABEL FOR VERTICAL VU METER
    var c = document.getElementsByClassName("itemQuarterVuMeterBackground");

    if (screenHeight < 570)
        winHeightVuMeter += 44;
    else
        winHeightVuMeter += 48;
    for (var k = 0; k < c.length; k++) {
        var ctx = c[k].getContext("2d");
        ctx.canvas.height = winHeightVuMeter - 16;
        ctx.font = "8px Arial";
        ctx.fillStyle = "#ebeded";
        ctx.textAlign = "end";
        for (var j = 0; j < labelVuMeter.length; j++) {
            var y = ((-(winHeightVuMeter - 30) / 60) * labelVuMeter[j] + 2);
            if (labelVuMeterMark[j] != 0) {
                ctx.fillRect(18, y + 8, 16, 2);
                ctx.fillText(labelVuMeter[j], 14, y + 11);
            } else {
                ctx.fillRect(24, y + 8, 12, 1);
            }
        }
        ctx.stroke();
    }
    if (screenHeight < 570)
        winHeightVuMeter -= 44;
    else
        winHeightVuMeter -= 48;

    // DRAW TICK LABEL FOR VERTICAL DELAY SLIDER ((winHeightFader - 30) because the gain slider is 30px higher)
    if (screenHeight < 570) {
        winHeightFader = winHeightFader + 4;
    } else {
        winHeightFader = winHeightFader + 22;
    }
    var c = document.getElementsByClassName("sliderDelayContainerBackground");
    for (var k = 0; k < c.length; k++) {
        var ctx = c[k].getContext("2d");
        ctx.canvas.height = winHeightFader + 37;
        ctx.font = "8px Arial";
        ctx.fillStyle = "#ebeded";
        for (var j = 0; j < labelDelay.length; j++) {
            if (labelDelay[j] != 0.0)
                var y = (winHeightFader - 20) - (Math.log10(labelDelay[j]) * ((winHeightFader - 20) / Math.log10(delayScaleMax)));
            else if (labelDelay[j] === 0.0)
                var y = (winHeightFader) - 20;
            if (labelDelayMark[j] != 0) {
                ctx.fillRect(22, y + 10, 33, 2);
                ctx.textAlign = "end";
                ctx.fillText(labelDelay[j], 14, y + 14);
            } else {
                ctx.fillRect(30, y + 10, 17, 1);
            }
        }
        ctx.stroke();
    }
    if (screenHeight < 570) {
        winHeightFader = winHeightFader - 4;
    } else {
        winHeightFader = winHeightFader - 22;
    }

    var c, ctx;
    c = document.getElementById("canvasVuMeterGRBGLimiter");
    if (c) {
        ctx = c.getContext("2d");
        $.fn.drawTickLimiter(ctx);
    }
    c = document.getElementById("canvasVuMeterPeakBGLimiter");
    if (c) {
        ctx = c.getContext("2d");
        $.fn.drawTickLimiter(ctx);
    }
    c = document.getElementById("canvasVuMeterOutputBGLimiter");
    if (c) {
        ctx = c.getContext("2d");
        $.fn.drawTickLimiter(ctx);
    }
};


$.fn.drawTickLimiter = function(ctx) {
    winHeightFaderLimiter = screenScrollHeight - 375;
    ctx.canvas.height = winHeightFaderLimiter + 16;
    if (screenHeight < 570) {
        if (screenWidth < 990) {
            ctx.canvas.height = 851.2 + 20;
            winHeightFaderLimiter = 847;
        } else {
            ctx.canvas.height = 360 + 20;
            winHeightFaderLimiter = 365;
        }
    }

    ctx.canvas.width = 60;
    ctx.font = "8px Arial";
    ctx.fillStyle = "#ebeded";

    for (var j = 0; j < labelVuMeter.length; j++) {
        // old value was (-winHeightFaderLimiter / 60)
        var y = ((winHeightFaderLimiter / 60) * labelGRVuMeter[j] + 5);
        // console.log("valeur label : " + labelVuMeter[j] + " // valeur compute " + y);
        if (labelVuMeterMark[j] != 0) {
            ctx.fillRect(6, y + 5, 20, 2);
            ctx.textAlign = "start";
            ctx.fillText(labelGRVuMeter[j], 32, y + 7 + 1);
        } else {
            ctx.fillRect(6, y + 5, 14, 1);
            //ctx.fillText(labelVuMeter[j], 42, y + 10 + 1);
        }
    }
    ctx.stroke();
}

//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
/////                                                                               //////
/////                               CREATE MODULES                                  //////
/////                                                                               //////
/////                                                                               //////
/////                                                                               //////
/////                                                                               //////
/////                                                                               //////
/////                                                                               //////
/////                                                                               //////
/////                                                                               //////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////

$.fn.drawModules = function() {
    $.fn.setupPeqSolo();
    $.fn.setupXOVERSolo();
    $.fn.setupLimiterSolo();
}

//SETUP PEQ MAIN PANEL FOR AMP VIEW (TYPE) DEFINE IF IT'S IN THE CHANNEL PATH (0) OR GROUP (1)
$.fn.setupPeqSolo = function() {

    $("#peqMainPanel").html("");
    $("#peqMainPanel").append($("<div>").prop({ id: "peqItemFull", className: "itemFull" }));

    //BUTTON LOCK MAG
    $("#peqItemFull").append($("<button>").prop({ id: "eqLockMag", className: "itemFullButtonLockMag" }));
    $("#eqLockMag").append($("<div>").prop({ id: "eqLockMagDiv", className: "media" }));
    $("#eqLockMagDiv").append($("<img>").prop({ src: "./img/LockMag.png", className: "logoPeqViewButton" }));

    //BUTTON LOCK FREQ
    $("#peqItemFull").append($("<button>").prop({ id: "eqLockFreq", className: "itemFullButtonLockFreq" }));
    $("#eqLockFreq").append($("<div>").prop({ id: "eqLockFreqDiv", className: "media" }));
    $("#eqLockFreqDiv").append($("<img>").prop({ src: "./img/LockFreq.png", className: "logoPeqViewButton" }));

    //BUTTON LOCK Q
    $("#peqItemFull").append($("<button>").prop({ id: "eqLockQ", className: "itemFullButtonLockQ" }));
    $("#eqLockQ").append($("<div>").prop({ id: "eqLockQDiv", className: "media" }));
    $("#eqLockQDiv").append($("<img>").prop({ src: "./img/LockQ.png", className: "logoPeqViewButton" }));

    //BUTTON VIEW
    $("#peqItemFull").append($("<button>").prop({ id: "eqView", className: "itemFullButtonView" }));
    $("#eqView").attr("data-toggle", "modal");
    $("#eqView").attr("data-target", "#peqViewModeModal");
    $("#eqView").append($("<div>").prop({ id: "eqModalViewDiv", className: "media" }));
    $("#eqModalViewDiv").append($("<img>").prop({ src: "./img/View.png", className: "logoPeqViewButton" }));

    //DRAWING AREA FOR PEQ
    $("#peqItemFull").append($("<div>").prop({ id: "widgetParamEQ" }));

    //PARAMETERS AREA FOR PEQ
    $("#peqItemFull").append($("<div>").prop({ id: "parametersArea" }));

    //PEQ NAVBAR
    $("#parametersArea").append($("<div>").prop({ id: "peqNavBar", className: "peqNavBar" }));

    //PEQ SOLO PARAMETERS AREA
    $("#parametersArea").append($("<div>").prop({ id: "paramPEQArea" }));
    // $("#parametersArea").append($("<div>").prop({ class: "peqEndSpacer" }));

    //NAV BAR AREA
    var str = "";
    str += "<nav aria-label= \"Page navigation example\">";
    str += "<ul class=\"pagination \">";
    str += "<li class=\"page-item\">";
    str += "<a class=\"page-link peqButtonNavBar\" href=\"#peq\" id=\"peqAnav99\" aria-label=\"Previous\">ALL &nbsp";
    str += "<span aria-hidden=\"true\"><img src=\"./img/PEQ.png\" height=\"24px\"></span>";
    str += "<span class=\"sr-only\">Bell Sym</span>";
    str += "</a>";
    str += "</li>";
    for (var i = 0; i < eqCount; i++) {
        str += "<li class=\"page-item\">";
        str += "<a class=\"page-link peqButtonNavBar\" href=\"#peq\"  id=\"peqAnav" + i + "\" aria-label=\"Previous\">PEQ " + (i + 1) + "&nbsp";
        str += "<span aria-hidden=\"true\"><img id=\"peqImgNav" + i + "\" src=\"./img/peq/peq0.png\" height=\"24px\"></span>";
        str += "<span class=\"sr-only\">Bell Sym</span>";
        str += "</a>";
        str += "</li>";
    }
    str += "<li class=\"page-item\">";
    str += "<a class=\"page-link peqButtonNavBar\" href=\"#peq\" id=\"peqAnav100\" aria-label=\"Previous\">";
    str += "<span aria-hidden=\"true\"><img src=\"./img/copy.png\" height=\"24px\"></span>";
    str += "</a>";
    str += "</li>";
    str += "</ul>";
    str += "</nav>";

    $("#peqNavBar").append(str);

    $("#paramPEQArea").append($("<div>").prop({ id: "parametersAreaEQ99" }));

    // FIRST COLUMN FOR PEQ PARAMETERS FROM 1 TO 6
    $("#parametersAreaEQ99").append($("<div>").prop({ id: "parametersAreaL" }));
    $("#parametersAreaL").append($("<table>").prop({ id: "peqTableParametersL" }))

    //CREATE HEADER COLUMN TITLE
    var trL = $("<tr></tr>").text("");
    $("#peqTableParametersL").append(trL);
    var t1L = $("<td></td>").text("Band");
    var t2L = $("<td></td>").text("En");
    var t3L = $("<td></td>").text("Filter type");
    var t4L = $("<td></td>").text("Freq. (Hz)");
    var t5L = $("<td></td>").text("Gain (dB)");
    var t6L = $("<td></td>").text("Q");

    trL.append(t1L);
    trL.append(t2L);
    trL.append(t3L);
    trL.append(t4L);
    trL.append(t5L);
    trL.append(t6L);

    for (var i = 0; i < eqCount / 2; i++) {
        let tr = $("<tr></tr>").text("");
        $("#peqTableParametersL").append(tr);

        //INSERT INPUTS AND SELECTORS FOR EVERY EQs
        let cell1 = $("<td></td>").text((i + 1));
        let cell2 = $("<td></td>").html("<input id=\"eqEna" + i + "\" type=\"checkbox\" class=\"enaInputPEQ\" name=\"enaPEQ\" test />");
        let cell3 = $("<td></td>").html("<select id=\"eqType" + i + "\" class=\"eqTypeSelect\"><option value=\"0\">Bell-Sym</option><option value=\"1\">Bell-ASym</option><option value=\"2\">Notch</option><option value=\"3\">Low-Shelving 6dB/oct</option><option value=\"4\">Low-Shelving 12dB/oct</option><option value=\"5\">High-Shelving 6dB/oct</option><option value=\"6\">High-Shelving 12dB/oct</option><option value=\"7\">All-Pass 90°</option><option value=\"8\">All-Pass 180°</option><option value=\"9\">High-Pass 6dB/oct</option><option value=\"10\">High-Pass 12dB/oct</option><option value=\"11\">High-Pass VariQ 12dB/oct</option><option value=\"12\">Low-Pass 6dB/oct</option><option value=\"13\">Low-Pass 12dB/oct</option><option value=\"14\">Low-Pass VariQ 12dB/oct</option><option value=\"15\">Band-Pass</option></select>");
        let cell4 = $("<td></td>").html("<input id=\"freq_text" + i + "\" type=\"number\" step=\"1\" class=\"freqInputPEQ\">");
        let cell5 = $("<td></td>").html("<input id=\"gain_text" + i + "\" type=\"number\" step=\"0.1\" class=\"gainInputPEQ\">");
        let cell6 = $("<td></td>").html("<input id=\"q_text" + i + "\" type=\"number\" step=\"0.01\" class=\"qInputPEQ\">");

        tr.append(cell1);
        tr.append(cell2);
        tr.append(cell3);
        tr.append(cell4);
        tr.append(cell5);
        tr.append(cell6);
    }

    // SECOND COLUMN FOR PEQ PARAMETERS FROM 7 TO 12
    $("#parametersAreaEQ99").append($("<div>").prop({ id: "parametersAreaR" }));
    $("#parametersAreaR").append($("<table>").prop({ id: "peqTableParametersR" }));

    //CREATE HEADER COLUMN TITLE
    var trR = $("<tr></tr>").text("");
    $("#peqTableParametersR").append(trR);
    var t1R = $("<td></td>").text("Band");
    var t2R = $("<td></td>").text("En");
    var t3R = $("<td></td>").text("Filter type");
    var t4R = $("<td></td>").text("Freq. (Hz)");
    var t5R = $("<td></td>").text("Gain (dB)");
    var t6R = $("<td></td>").text("Q");

    trR.append(t1R);
    trR.append(t2R);
    trR.append(t3R);
    trR.append(t4R);
    trR.append(t5R);
    trR.append(t6R);

    for (var i = 0; i < eqCount / 2; i++) {
        j = i + eqCount / 2;
        let tr = $("<tr></tr>").text("");
        $("#peqTableParametersR").append(tr);

        //INSERT INPUTS AND SELECTORS FOR EVERY EQs
        let cell1 = $("<td></td>").text((j + 1));
        let cell2 = $("<td></td>").html("<input id=\"eqEna" + j + "\" type=\"checkbox\" class=\"enaInputPEQ\" name=\"enaPEQ\" test />");
        let cell3 = $("<td></td>").html("<select id=\"eqType" + j + "\" class=\"eqTypeSelect\"><option value=\"0\">Bell-Sym</option><option value=\"1\">Bell-ASym</option><option value=\"2\">Notch</option><option value=\"3\">Low-Shelving 6dB/oct</option><option value=\"4\">Low-Shelving 12dB/oct</option><option value=\"5\">High-Shelving 6dB/oct</option><option value=\"6\">High-Shelving 12dB/oct</option><option value=\"7\">All-Pass 90°</option><option value=\"8\">All-Pass 180°</option><option value=\"9\">High-Pass 6dB/oct</option><option value=\"10\">High-Pass 12dB/oct</option><option value=\"11\">High-Pass VariQ 12dB/oct</option><option value=\"12\">Low-Pass 6dB/oct</option><option value=\"13\">Low-Pass 12dB/oct</option><option value=\"14\">Low-Pass VariQ 12dB/oct</option><option value=\"15\">Band-Pass</option></select>");
        let cell4 = $("<td></td>").html("<input id=\"freq_text" + j + "\" type=\"number\" step=\"1\" class=\"freqInputPEQ\">");
        let cell5 = $("<td></td>").html("<input id=\"gain_text" + j + "\" type=\"number\" step=\"0.1\" class=\"gainInputPEQ\">");
        let cell6 = $("<td></td>").html("<input id=\"q_text" + j + "\" type=\"number\" step=\"0.01\" class=\"qInputPEQ\">");

        tr.append(cell1);
        tr.append(cell2);
        tr.append(cell3);
        tr.append(cell4);
        tr.append(cell5);
        tr.append(cell6);
    }

    //CREATE DIV AREA FOR EDITING PEQs PARAMETERS IN SOLO
    for (var i = 0; i < eqCount; i++) {
        var id = "parametersAreaEQ" + i;
        var idRem = "#" + id
        $(idRem).remove();
        var div = document.createElement("div");
        div.id = id;
        div.style.marginTop = 10 + "px";
        var str = "";

        str += "<div class=\"slidersPEQContainer\">";
        str += "<div class=\"container123\">";
        str += "<div class=\"row\">";

        //ENABLE EQ BUTTON TOGGLE
        //SELECT TYPE EQ BUTTON 
        str += "</div>";
        str += "<div class=\"row justify-content-md-center\">";
        str += "<div class=\"col-lg-1 col-md-2 bgPEQParameterAreaSolo\">";
        str += "<h6>PEQ " + (i + 1) + "</6>";
        str += "<div class=\"enaInputPEQSolo\"> ";
        str += "<input type=\"checkbox\" class=\"ios8-switch enaInputPEQ\" id=\"enaTogglePEQ" + i + "\" > ";
        str += "<label  for=\"enaTogglePEQ" + i + "\"></label>";
        str += "</div>"
        str += "<button class=\"peqButtonTypeSolo\"  id=\"typeButtonPEQ" + i + "\"  data-toggle=\"modal\" data-target=\"#modalPeqType\" data-id=\"" + i + "\"><img id=\"peqImgSolo" + i + "\" src=\"./img/peq/peq0.png\" class=\"peqTypeImageButton\"></button>";
        str += "</div>"

        //RANGE SLIDER FOR FREQ, GAIN AND Q
        str += "<div class=\"col-lg-3 col-md-11 bgPEQParameterAreaSolo\">";
        str += "<h6 class=\"col-12\">Freq. (Hz)</h6>";
        str += "<div class=\"row\">";
        str += "<div class=\"col-sm\"><button id=\"freqButtonDown" + i + "\" class=\"btn btn-outline-dark btn-sm mb-2 soloPEQFreqButtonDown\">&nbsp-&nbsp</button></div>";
        str += "<div class=\"col-sm\"><input id=\"freq_textSolo" + i + "\" type=\"number\" step=\"1\" class=\"freqInputPEQ form-control form-control-sm\"></div>";
        str += "<div class=\"col-sm\"><button id=\"freqButtonUp" + i + "\" class=\"btn btn-outline-dark btn-sm mb-2 soloPEQFreqButtonUp\">&nbsp+&nbsp</button></div>";
        str += "</div>";
        str += "<div class=\"row\">";
        str += "<div class=\"col col-lg-1\"></div>";
        str += "<div id=\"sliderHorizontalFreqPEQ" + i + "\" class=\"sliderHorizontalFreqPEQ col-10 col-sm-10 col-md-10 col-lg-10\"></div>";
        str += "<div class=\"col col-lg-1\"></div>";
        str += "</div>";
        str += "</div>";
        str += "<div class=\"col-lg-3 col-md-11 bgPEQParameterAreaSolo\">";
        str += "<h6>Gain (dB)</h6>";
        str += "<div class=\"row\">";
        str += "<div class=\"col-sm\"><button id=\"gainButtonDown" + i + "\" class=\"btn btn-outline-dark btn-sm mb-2 soloPEQGainButtonDown\">&nbsp-&nbsp</button></div>";
        str += "<div class=\"col-sm\"><input id=\"gain_textSolo" + i + "\" type=\"number\" step=\"0.1\" class=\"gainInputPEQ form-control form-control-sm\"></div>";
        str += "<div class=\"col-sm\"><button id=\"gainButtonUp" + i + "\" class=\"btn btn-outline-dark btn-sm mb-2 soloPEQGainButtonUp\">&nbsp+&nbsp</button></div>";
        str += "</div>";
        str += "<div class=\"row\">";
        str += "<div class=\"col col-lg-1\"></div>";
        str += "<div id=\"sliderHorizontalGainPEQ" + i + "\" class=\"sliderHorizontalGainPEQ col-10 col-sm-10 col-md-10 col-lg-10\"></div>";
        str += "<div class=\"col col-lg-1\"></div>";
        str += "</div>";
        str += "</div>";
        str += "<div class=\"col-lg-3 col-md-11 bgPEQParameterAreaSolo\">";
        str += "<h6>Q</h6>"
        str += "<div class=\"row\">";
        str += "<div class=\"col-sm\"><button id=\"qButtonDown" + i + "\" class=\"btn btn-outline-dark btn-sm mb-2 soloPEQQButtonDown\">&nbsp-&nbsp</button></div>";
        str += "<div class=\"col-sm\"><input id=\"q_textSolo" + i + "\" type=\"number\" step=\"0.01\" class=\"qInputPEQ form-control form-control-sm\"></div>";
        str += "<div class=\"col-sm\"><button id=\"qButtonUp" + i + "\" class=\"btn btn-outline-dark btn-sm mb-2 soloPEQQButtonUp\">&nbsp+&nbsp</button></div>";
        str += "</div>";
        str += "<div class=\"row\">";
        str += "<div class=\"col col-lg-1\"></div>";
        str += "<div id=\"sliderHorizontalQPEQ" + i + "\" class=\"sliderHorizontalQPEQ col-10 col-sm-10 col-md-10 col-lg-10\"></div>";
        str += "<div class=\"col col-lg-1\"></div>";
        str += "</div>";
        str += "</div>";
        str += "</div>";
        str += "</div>";

        str += "</div>";
        div.innerHTML = str;
        $("#paramPEQArea").append(div);
        $(idRem).hide();
    }

    // PEQ COPY MODULE
    $("#paramPEQArea").append($("<div>").prop({ id: "parametersAreaEQ100" }));
    $("#parametersAreaEQ100").append($("<div>").prop({ id: "parametersAreaEQ100Panel", className: "row justify-content-md-center" }))
    $("#parametersAreaEQ100Panel").append($("<div>").prop({ id: "peqCopyPanel", className: "col-xl-3 col-lg-6 col-md-11 bgPEQParameterAreaSolo" }))
    $("#peqCopyPanel").append($("<div>").prop({ innerHTML: "<h6>COPY :</h6>", className: "peqResetArea" }));
    $("#peqCopyPanel").append($("<div>").prop({ id: "peqCopySource" }));
    $("#peqCopySource").append($("<table>").prop({ id: "peqCopySourceTable", className: "peqCopySource" }))
    var str = "";
    str += "<tr>"
    for (var d = 0; d < 4; d++)
        str += "<td>PEQ &nbsp" + (d + 1) + " &nbsp<input id=\"peqCopySelected" + d + "\" type=\"checkbox\" class=\"peqCopySelected\"/>";
    str += "</tr>";
    str += "<tr>"
    for (var d = 4; d < 8; d++)
        str += "<td>PEQ &nbsp" + (d + 1) + " &nbsp<input id=\"peqCopySelected" + d + "\" type=\"checkbox\" class=\"peqCopySelected\"/>";
    str += "</tr>";
    str += "<tr>"
    for (var d = 8; d < 12; d++)
        str += "<td>PEQ &nbsp" + (d + 1) + " &nbsp<input id=\"peqCopySelected" + d + "\" type=\"checkbox\" class=\"peqCopySelected\"/>";
    str += "</tr>";

    $("#peqCopySourceTable").html(str);

    $("#peqCopyPanel").append($("<button>").prop({ id: "peqCopySelectAll", className: "peqCopySelectAllButton", innerHTML: "ALL" }));

    $("#peqCopyPanel").append($("<span>").prop({ innerHTML: "<h6>FROM :</h6>" }));
    var str = "";

    str += "<div class=\"form-check form-check-inline peqCopyRadio\">";
    str += "<label class=\"form-check-label\" for=\"inlineRadio0\">&nbsp Channel 1 &nbsp</label>";
    str += "<input class=\"form-check-input peqCopyChannelSourceRadio\" type=\"radio\" name=\"peqCopyOptions\" id=\"inlineRadio0\">";
    str += "</div>";
    str += "<div class=\"form-check form-check-inline peqCopyRadio\">";
    str += "<label class=\"form-check-label\" for=\"inlineRadio1\">Channel 2 &nbsp</label>";
    str += "<input class=\"form-check-input peqCopyChannelSourceRadio\" type=\"radio\" name=\"peqCopyOptions\" id=\"inlineRadio1\">";
    str += "</div>";
    str += "<div class=\"form-check form-check-inline peqCopyRadio\">";
    str += "<label class=\"form-check-label\" for=\"inlineRadio2\">Channel 3 &nbsp</label>";
    str += "<input class=\"form-check-input peqCopyChannelSourceRadio\" type=\"radio\" name=\"peqCopyOptions\" id=\"inlineRadio2\">";
    str += "</div>";
    str += "<div class=\"form-check form-check-inline peqCopyRadio\">";
    str += "<label class=\"form-check-label\" for=\"inlineRadio3\">Channel 4 &nbsp</label>";
    str += "<input class=\"form-check-input peqCopyChannelSourceRadio\" type=\"radio\" name=\"peqCopyOptions\" id=\"inlineRadio3\">";
    str += "</div>";

    $("#peqCopyPanel").append($("<div>").prop({ id: "peqCopySourceChannel" }));

    $("#peqCopySourceChannel").html(str);

    $("#peqCopyPanel").append($("<span>").prop({ innerHTML: "<h6>TO :</h6>" }));

    $("#peqCopyPanel").append($("<div>").prop({ id: "peqCopySourceChannelDest" }));
    $("#peqCopySourceChannelDest").append($("<table>").prop({ id: "peqCopySourceChannelDestTable", className: "peqCopySource" }))

    var str = "";
    str += "<tr>"
    for (var d = 0; d < 4; d++)
        str += "<td>&nbsp Channel &nbsp" + (d + 1) + " &nbsp<input id=\"peqCopyChannelDest" + d + "\" type=\"checkbox\" class=\"peqCopyChannelDest\"/>";
    str += "</tr>";
    $("#peqCopySourceChannelDestTable").html(str);


    $("#peqCopyPanel").append($("<button>").prop({ id: "peqCopyApply", className: "eqCopyApplyButton", innerHTML: "APPLY" }));

    //SET TO DEFAULT VALUE PEQ MODULE 
    $("#parametersAreaEQ100Panel").append($("<div>").prop({ id: "peqResetPanel", className: "col-xl-3 col-lg-6 col-md-11 bgPEQParameterAreaSolo" }))

    $("#peqResetPanel").append($("<div>").prop({ id: "peqResetFlatAll", className: "peqResetArea" }));
    $("#peqResetFlatAll").append($("<span>").prop({ id: "peqCopyApply", className: "", innerHTML: "<h6>Flat All PEQs : &nbsp</h6>" }));
    $("#peqResetFlatAll").append($("<button>").prop({ id: "peqFlatApply", className: "eqCopyApplyButton", innerHTML: "APPLY" }));

    $("#peqResetPanel").append($("<div>").prop({ id: "peqResetDefaultAll", className: "peqResetArea" }));
    $("#peqResetDefaultAll").append($("<span>").prop({ id: "peqCopyApply", className: "", innerHTML: "<h6>Default values PEQs : &nbsp</h6>" }));
    $("#peqResetDefaultAll").append($("<button>").prop({ id: "peqDefaultApply", className: "eqCopyApplyButton", innerHTML: "APPLY" }));

    $("#peqResetPanel").append($("<div>").prop({ id: "peqResetDefaultChannelAll", className: "peqResetArea" }));
    $("#peqResetDefaultChannelAll").append($("<span>").prop({ id: "peqCopyApply", className: "", innerHTML: "<h6>Default values PEQs for all channels : &nbsp</h6>" }));
    $("#peqResetDefaultChannelAll").append($("<button>").prop({ id: "peqDefaultAllApply", className: "eqCopyApplyButton", innerHTML: "APPLY" }));

    $("#parametersAreaEQ100").hide();

    //FILL CONTENT OF MODAL WINDOWS
    $("#modalPeqTabContent").html("");

    var number_of_rows = 4;
    var number_of_cols = 4;
    var table_body = "<table class=\"peqModalType\">";
    for (var i = 0; i < number_of_rows; i++) {
        table_body += "<tr>";
        for (var j = 0; j < number_of_cols; j++) {
            var t = i * 4 + j;
            table_body += "<td>";
            table_body += "<button class=\"btn btn-default peqModalTypeBtn\" id=\"peqTypeModal" + t + "\">";
            table_body += "<div class=\"media\">";
            table_body += "<img class=\"peqModalTypeLogo logoPeqViewButton\" src=\"./img/peq/peq" + t + ".png\">";
            table_body += "</div>";
            table_body += "<div class=\"peqModalTypeText\">" + peqLabel[t] + "</div>";
            table_body += "</button>";
            table_body += "</td>";
            // displayVal("T", t);
        }
        table_body += "</tr>";
    }
    table_body += "</table>";
    $("#modalPeqTabContent").html(table_body);
    $('#peqModalType td').each(function() {
        var min = 10; // Define a minimum
        var step = 5 * $(this).index(); // Define Step(your step is 5 here)
        $(this).css('width', (min + step) + "px"); // css attribute of your <td> width:15px; i.e.
    });
}

//DRAW PEQ (mode = 0 : only Mag, mode = 1 : only phase, mode = 2 : dual view) (scale = 0 : -36 to 18, scale = 1 : -18 to 18, scale = 2 : -6 to 6) (phase 0 : phase 180, phase = 1 : phase 360)
$.fn.initPEQ = function(mode, scale, phase) {
    peqViewMode = mode;
    peqGainScaleType = scale;
    peqPhaseScaleType = phase;

    $("#canvasWidgetPEQ").remove();
    $("#graphWidgetPEQ").remove();
    $("#dragWidgetPEQ").remove();

    for (var i = 0; i < eqCount; i++) {
        var t = "#dragPEQ" + i;
        $(t).remove();
    }

    if (arrayEqParam === null) {
        arrayEqParam = new Array(eqCount);
        for (var i = 0; i < eqCount; i++) {
            arrayEqParam[i] = new EqParam(eqEnaDefault, eqFreqDefault, eqGainDefault, eqQDefault, eqTypeDefault, new AParam(), new BParam(), eqXLockDefault, eqYLockDefault);
            arrayEqParam[i].frequency = eqFreqDefaultInit[i];
        }
    }
    for (var i = 0; i < eqCount; i++) {
        peqTabMagX[i] = new Array(graphPEQWidth);
        peqTabPhaX[i] = new Array(graphPEQWidth);
        for (var j = 0; j < graphPEQWidth; j++) {
            peqTabMagX[i][j] = 0;
            peqTabPhaX[i][j] = 0;
        }
    }
    graphPEQHeight = widgetPEQY - widgetPEQMarginTop - widgetPEQMarginBottom;

    if (peqViewMode === 2)
        graphPEQWidth = widgetPEQX - widgetPEQMarginLeft - widgetPEQMarginRightDual;
    else
        graphPEQWidth = widgetPEQX - widgetPEQMarginLeft - widgetPEQMarginRight;

    //BACKGROUND INIT
    var canvasPEQ = document.createElement("canvas");
    canvasPEQ.id = "canvasWidgetPEQ";
    canvasPEQ.width = widgetPEQX;
    canvasPEQ.height = widgetPEQY;
    $("#widgetParamEQ").append(canvasPEQ);

    //CURVE DRAWING AREA INIT
    var graphPEQ = document.createElement("canvas");
    graphPEQ.id = "graphWidgetPEQ";
    graphPEQ.width = graphPEQWidth;
    graphPEQ.height = graphPEQHeight;
    graphPEQ.style.marginTop = "" + widgetPEQMarginTop + "px";
    graphPEQ.style.marginLeft = "" + widgetPEQMarginLeft + "px";
    $("#widgetParamEQ").append(graphPEQ);

    //CREATE peqDrag AREA FOR PEQ
    var dragPEQ = document.createElement("div");
    dragPEQ.id = "dragWidgetPEQ";
    dragPEQ.setAttribute("style", "width:" + (graphPEQWidth) + "px; height:" + (graphPEQHeight + 6) + "px; margin-top:" + widgetPEQMarginTop + "px; margin-left: " + (widgetPEQMarginLeft - 9) + "px;");
    $("#widgetParamEQ").append(dragPEQ);

    //INIT EXTERNAL CANVAS
    var c = document.getElementById("canvasWidgetPEQ");
    if (c != null) {
        var ctx = c.getContext("2d");
        c.style.width = widgetPEQX;
        c.style.height = widgetPEQY;
        ctx.beginPath();

        //BG COLOR
        ctx.rect(0, 0, widgetPEQX, widgetPEQY);
        ctx.fillStyle = "#0a1a29";
        ctx.fill();

        //VERTICAL AXE

        //MAG ONLY
        if (peqViewMode === 0) {
            var localGainGap = Math.max(...gain_scalePEQ[peqGainScaleType]) - Math.min(...gain_scalePEQ[peqGainScaleType]);
            // displayVal("gap", localGainGap);
            ctx.strokeStyle = "#3e4954";
            for (var i = 0; i < gain_scalePEQ_line[peqGainScaleType].length; i++) {
                var step = localGainGap / (gain_scalePEQ_line[peqGainScaleType].length - 1);
                step = step * graphPEQHeight / localGainGap;
                ctx.moveTo(widgetPEQMarginLeft, widgetPEQMarginTop + i * step);
                ctx.lineTo(widgetPEQX - widgetPEQMarginRight, widgetPEQMarginTop + i * step);
                ctx.stroke();
                ctx.font = "12px Arial";
                ctx.fillStyle = "white";
                ctx.textAlign = "right";
                if (gain_scalePEQ[peqGainScaleType].includes(gain_scalePEQ_line[peqGainScaleType][i]) != 0)
                    ctx.fillText(gain_scalePEQ_line[peqGainScaleType][i].toString(), widgetPEQMarginLeft - 5, widgetPEQMarginTop + i * step + 5);
            }
            yZeroPEQ = yFromGain(0);
        }

        //PHASE ONLY 
        else if (peqViewMode === 1) {
            var localPhaseGap = Math.max(...phase_scale[peqPhaseScaleType]) - Math.min(...phase_scale[peqPhaseScaleType]);
            // displayVal("gap", localPhaseGap);
            ctx.strokeStyle = "#3e4954";
            for (var i = 0; i < phase_scale_line[peqPhaseScaleType].length; i++) {
                var step = localPhaseGap / (phase_scale_line[peqPhaseScaleType].length - 1);
                step = step * graphPEQHeight / localPhaseGap;
                ctx.moveTo(widgetPEQMarginLeft, widgetPEQMarginTop + i * step);
                ctx.lineTo(widgetPEQX - widgetPEQMarginRight, widgetPEQMarginTop + i * step);
                ctx.stroke();
                ctx.font = "12px Arial";
                ctx.fillStyle = "white";
                ctx.textAlign = "right";
                if (phase_scale[peqPhaseScaleType].includes(phase_scale_line[peqPhaseScaleType][i]) != 0)
                    ctx.fillText(phase_scale_line[peqPhaseScaleType][i].toString() + "°", widgetPEQMarginLeft - 5, widgetPEQMarginTop + i * step + 5);
            }
            yZeroPEQ = yFromGain(0);
        }
        //MAG + PHASE
        else if (peqViewMode === 2) {
            var localGainGap = Math.max(...gain_scalePEQ[peqGainScaleType]) - Math.min(...gain_scalePEQ[peqGainScaleType]);
            // displayVal("gap", localGainGap);
            ctx.strokeStyle = "#3e4954";
            for (var i = 0; i < gain_scalePEQ_line[peqGainScaleType].length; i++) {
                var step = localGainGap / (gain_scalePEQ_line[peqGainScaleType].length - 1);
                step = step * graphPEQHeight / localGainGap;
                ctx.moveTo(widgetPEQMarginLeft, widgetPEQMarginTop + i * step);
                ctx.lineTo(widgetPEQX - widgetPEQMarginRightDual, widgetPEQMarginTop + i * step);
                ctx.stroke();
                ctx.font = "12px Arial";
                ctx.fillStyle = "white";
                ctx.textAlign = "right";
                if (gain_scalePEQ[peqGainScaleType].includes(gain_scalePEQ_line[peqGainScaleType][i]) != 0)
                    ctx.fillText(gain_scalePEQ_line[peqGainScaleType][i].toString(), widgetPEQMarginLeft - 5, widgetPEQMarginTop + i * step + 5);
            }
            yZeroPEQ = yFromGain(0);

            var localPhaseGap = Math.max(...phase_scale[peqPhaseScaleType]) - Math.min(...phase_scale[peqPhaseScaleType]);
            // displayVal("gap", localPhaseGap);
            ctx.strokeStyle = "#3e4954";
            for (var i = 0; i < phase_scale_line[peqPhaseScaleType].length; i++) {
                //ADJUST RIGHT ANGULAR SCALE TO FITS WITH A NON SYMETRICAL (AROUND 0dB)
                if (peqGainScaleType === 2)
                    var step = localPhaseGap / (phase_scale_line[peqPhaseScaleType].length + 4 - 1);
                else
                    var step = localPhaseGap / (phase_scale_line[peqPhaseScaleType].length - 1);
                step = step * graphPEQHeight / localPhaseGap;

                ctx.font = "12px Arial";
                ctx.fillStyle = "white";
                ctx.textAlign = "left";
                if (phase_scale[peqPhaseScaleType].includes(phase_scale_line[peqPhaseScaleType][i]) != 0)
                    ctx.fillText(phase_scale_line[peqPhaseScaleType][i].toString() + "°", widgetPEQX - widgetPEQMarginRightDual + 5, widgetPEQMarginTop + i * step + 5);
            }
        }

        //FREQUENCY AXE
        ctx.strokeStyle = "#3e4954";
        var j = 0;
        ctx.font = "12px Arial";
        ctx.fillStyle = "white";
        ctx.textAlign = "center";
        // displayVal("size widget Y", widgetPEQX);
        var a = widgetPEQY;
        for (var i = 0; i < freq_scale_line.length; i++) {
            // displayVal("X", x - 1);
            ctx.moveTo(xFromFreq(freq_scale_line[i]) + widgetPEQMarginLeft, widgetPEQMarginTop);
            if (peqViewMode === 2) {
                a = graphPEQHeight + widgetPEQMarginTop + widgetPEQMarginBottom;
                ctx.lineTo(xFromFreq(freq_scale_line[i]) + widgetPEQMarginLeft, a - widgetPEQMarginBottom);
            } else
                ctx.lineTo(xFromFreq(freq_scale_line[i]) + widgetPEQMarginLeft, widgetPEQY - widgetPEQMarginBottom);
            ctx.stroke();
            if (freq_scale.includes(freq_scale_line[i]) != 0) {
                if (i === 0)
                    ctx.fillText(freq_scale_text[j].toString(), widgetPEQMarginLeft, a - 10);
                else
                    ctx.fillText(freq_scale_text[j].toString(), xFromFreq(freq_scale_line[i]) + widgetPEQMarginLeft, a - 10);
                j++;
            }
        }

        if (peqViewMode === 2)
            ctx.strokeRect(widgetPEQMarginLeft, widgetPEQMarginTop, widgetPEQX - widgetPEQMarginLeft - widgetPEQMarginRightDual, a - widgetPEQMarginTop - widgetPEQMarginBottom);
        else
            ctx.strokeRect(widgetPEQMarginLeft, widgetPEQMarginTop, widgetPEQX - widgetPEQMarginLeft - widgetPEQMarginRight, a - widgetPEQMarginTop - widgetPEQMarginBottom);

        //INITIALIZE 12 PEQS

        //ADD WHITE BORDER TRANSPARENT BACKGROUND AND NUMBER ON EACH PEQs
        if (peqViewMode != 1) {
            for (var i = 0; i < eqCount; i++) {
                var divLabelGraphPEQ = document.createElement("div");
                divLabelGraphPEQ.id = "dragPEQ" + i;
                divLabelGraphPEQ.className = "circleEq";

                var bgCirclePEQ = document.createElement("div");
                bgCirclePEQ.className = "bgCircleEq";

                var labelGraphPEQ = document.createElement("p");
                labelGraphPEQ.id = "label" + i;
                labelGraphPEQ.className = "labelEq";

                var num = i + 1;
                labelGraphPEQ.innerHTML = "" + num;
                $("#widgetParamEQ").append(divLabelGraphPEQ);

                var t = "#dragPEQ" + i;
                arrayEqParamDraggable[i] = $(t);

                arrayEqParamDraggable[i].append(bgCirclePEQ);
                arrayEqParamDraggable[i].append(labelGraphPEQ);
            }
        }

        $.fn.initiatePEQDraggie();

        //SET INITIAL POSITION FOR EVERY PEQs DEPENDING ON THE DEFAULT VALUE
        for (var i = 0; i < eqCount; i++) {
            if (peqViewMode != 1)
                $.fn.draggieSetPosition(i);
            var ena = "#eqEna" + i;
            $(ena).prop('checked', arrayEqParam[i].ena);
            var type = "#eqType" + i;
            $(type).val(arrayEqParam[i].type);

            var freq = "#freq_text" + i;
            $(freq).val(arrayEqParam[i].frequency);
            freq = "#freq_textSolo" + i;
            $(freq).val(arrayEqParam[i].frequency);

            var gain = "#gain_text" + i;
            $(gain).val(arrayEqParam[i].gain);
            gain = "#gain_textSolo" + i;
            $(gain).val(arrayEqParam[i].gain);

            var q = "#q_text" + i;
            $(q).val(arrayEqParam[i].q);
            q = "#q_textSolo" + i;
            $(q).val(arrayEqParam[i].q);

            var a = "#dragPEQ" + i;
            peqDrag[i] = $(a).draggabilly('disable');
        }
    }
}

//REDRAW CURVES
$.fn.drawPEQWidget = function(updatedPEQ) {
    var c = document.getElementById("graphWidgetPEQ");
    if (c) {
        var ctx = c.getContext("2d");

        ctx.strokeStyle = '#00a3e0';
        ctx.clearRect(0, 0, c.width, c.height);
        ctx.lineWidth = 2;
        ctx.beginPath();
        ctx.setLineDash([]);
        for (var x = 0; x < eqCount; x++) {
            //IF PEQ SELECTED TO UPDATE, WE COMPUTE NEW VALUES -- IF VALUE === 99 WE COMPUTE ALL THE VALUES FOR THE FIRST TIME
            // if (x === updatedPEQ || updatedPEQ === 99) {
            if (arrayEqParam[x].ena === true)
            // displayVal("PEQ Array enable", x);

                if (x === updatedPEQ || updatedPEQ === 99) {
                    // if (x === updatedPEQ) {
                    ctx.beginPath();
                    if (arrayEqParam[x].ena === true) {
                        computePEQCoeff(x);

                        for (var i = 0; i < graphPEQWidth; i++) {
                            var t = $.fn.processPEQ(i, x);
                            peqTabMagX[x][i] = t.magnitude;
                            peqTabPhaX[x][i] = t.phase;
                        }
                        //MAG ONLY
                        if (peqViewMode === 0) {
                            ctx.beginPath();
                            ctx.moveTo(-2, graphPEQHeight);
                            ctx.lineTo(-2, yFromGain(peqTabMagX[x][0]));
                            for (var i = 0; i < graphPEQWidth; i++) {
                                ctx.lineTo(i, yFromGain(peqTabMagX[x][i]));
                            }
                            ctx.lineTo(graphPEQWidth + 100, yFromGain(peqTabMagX[x][graphPEQWidth - 1]));
                            ctx.lineTo(graphPEQWidth + 100, graphPEQHeight);
                            ctx.fillStyle = "rgba(83, 230, 246, 0.2)";
                            ctx.fill("nonzero");
                        }
                        //PHASE ONLY 
                        else if (peqViewMode === 1) {}
                        //MAG + PHASE
                        else if (peqViewMode === 2) {
                            ctx.beginPath();
                            ctx.moveTo(-2, graphPEQHeight);
                            ctx.lineTo(-2, yFromGain(peqTabMagX[x][0]));
                            for (var i = 0; i < graphPEQWidth; i++) {
                                ctx.lineTo(i, yFromGain(peqTabMagX[x][i]))
                            }
                            ctx.lineTo(graphPEQWidth + 100, yZeroPEQ)
                            ctx.lineTo(graphPEQWidth, yFromGain(peqTabMagX[x][graphPEQWidth - 1]));
                            ctx.lineTo(graphPEQWidth + 100, graphPEQHeight);
                            ctx.fillStyle = "rgba(83, 230, 246, 0.2)";
                            ctx.fill("nonzero");
                        }
                        ctx.stroke();
                    }
                }
                //IF PEQ IS NOT UPDATED, WE TAKE VALUE FROM THE STORED ARRAY
                else {
                    ctx.beginPath();
                    if (arrayEqParam[x].ena === true) {
                        //MAG ONLY
                        if (peqViewMode === 0) {}
                        //PHASE ONLY 
                        else if (peqViewMode === 1) {}
                        //MAG + PHASE
                        else if (peqViewMode === 2) {}
                    }
                }
        }

        var valG = new Array(graphPEQWidth);
        var valP = new Array(graphPEQWidth);
        ctx.strokeStyle = '#fe8e00';
        ctx.lineWidth = 2;
        ctx.beginPath();
        for (var i = 0; i < graphPEQWidth; i++) {
            valG[i] = 0;
            valP[i] = 0;
            for (var x = 0; x < eqCount; x++) {
                if (arrayEqParam[x].ena === true) {
                    valG[i] = valG[i] + peqTabMagX[x][i];
                    valP[i] = valP[i] + peqTabPhaX[x][i];
                }
            }
        }
        //MAG ONLY
        if (peqViewMode === 0) {
            ctx.beginPath();
            ctx.strokeStyle = '#fe8e00';
            ctx.moveTo(-2, graphPEQHeight);
            ctx.lineTo(-2, yFromGain(valG[0]));
            for (var i = 0; i < graphPEQWidth; i++) {
                ctx.lineTo(i, yFromGain(valG[i]));
            }
            ctx.lineTo(graphPEQWidth + 100, yFromGain(valG[graphPEQWidth - 1]));
            ctx.lineTo(graphPEQWidth + 100, graphPEQHeight);
            ctx.fillStyle = "rgba(255, 142, 0, 0.1)";
            ctx.fill("nonzero");
            ctx.stroke();
        }
        //PHASE ONLY 
        else if (peqViewMode === 1) {
            ctx.beginPath();
            ctx.strokeStyle = '#fe8e00';
            ctx.moveTo(-2, yFromPhase(0));
            ctx.lineTo(-2, yFromPhase(valP[0]));
            for (var i = 0; i < graphPEQWidth; i++) {
                ctx.lineTo(i, yFromPhase(valP[i]));
            }
            ctx.lineTo(graphPEQWidth + 2, yFromPhase(valP[graphPEQWidth]));
            ctx.lineTo(graphPEQWidth + 2, yFromPhase(0));
            ctx.setLineDash([15, 15]);
            ctx.fillStyle = "rgba(255, 142, 0, 0.1)";
            ctx.fill("nonzero");
            ctx.stroke();
        }
        //MAG + PHASE
        else if (peqViewMode === 2) {
            ctx.beginPath();
            ctx.strokeStyle = '#fe8e00';
            ctx.moveTo(-2, graphPEQHeight);
            ctx.lineTo(-2, yFromGain(valG[0]));
            for (var i = 0; i < graphPEQWidth; i++) {
                ctx.lineTo(i, yFromGain(valG[i]));
            }
            ctx.lineTo(graphPEQWidth + 2, yFromGain(valG[graphPEQWidth - 1]));
            ctx.lineTo(graphPEQWidth + 2, graphPEQHeight);
            // ctx.lineTo(-2, yFromGain(valG[0]));
            // ctx.closePath();
            ctx.setLineDash([]);
            ctx.fillStyle = "rgba(255, 142, 0, 0.1)";
            ctx.fill("nonzero");
            ctx.stroke();
            ctx.beginPath();
            ctx.moveTo(-2, yFromPhase(0));
            ctx.lineTo(0, yFromPhase(valP[0]));
            for (var i = 0; i < graphPEQWidth; i++) {
                ctx.lineTo(i, yFromPhase(valP[i]));
            }
            ctx.lineTo(graphPEQWidth + 2, yFromPhase(valP[graphPEQWidth]));
            ctx.lineTo(graphPEQWidth + 2, yFromPhase(0));
            ctx.setLineDash([10, 5]);
            ctx.stroke();
        }

        //DRAW SUM CURVE ON PEQ CURVE
        //SUM OF PEQ AND CROSSOVER FILTER

        ctx.lineWidth = 1;
        for (var i = 0; i < graphPEQWidth; i++) {
            if (localAmplifier.channel[soloChannelSelected].xover.hpEna === true) {
                valG[i] = valG[i] + xoverTabMagX[0][i];
                valP[i] = valP[i] + xoverTabPhaX[0][i];
            }
            if (localAmplifier.channel[soloChannelSelected].xover.lpEna === true) {
                valG[i] = valG[i] + xoverTabMagX[1][i];
                valP[i] = valP[i] + xoverTabPhaX[1][i];
            }
        }

        //MAG ONLY
        if (peqViewMode === 0) {
            ctx.beginPath();
            ctx.strokeStyle = "rgba(230, 230, 230, 1)";
            ctx.moveTo(-2, graphPEQHeight + 2);
            ctx.lineTo(-2, yFromGain(valG[0]));
            for (var i = 0; i < graphPEQWidth; i++) {
                ctx.lineTo(i, yFromGain(valG[i]));
            }
            ctx.lineTo(graphPEQWidth + 100, yFromGain(valG[graphPEQWidth - 1]));
            ctx.lineTo(graphPEQWidth + 100, graphPEQHeight);
            ctx.fillStyle = "rgba(255, 255, 255, .1)";
            ctx.fill("nonzero");
            ctx.setLineDash([]);
            ctx.stroke();
        }
        //PHASE ONLY 
        else if (peqViewMode === 1) {
            ctx.beginPath();
            ctx.strokeStyle = "rgba(230, 230, 230, 1)";
            ctx.moveTo(-100, yFromPhase(0));
            ctx.lineTo(0, yFromPhase(valP[0]));
            for (var i = 0; i < graphPEQWidth; i++) {
                ctx.lineTo(i, yFromPhase(valP[i]));
            }
            ctx.lineTo(graphPEQWidth + 100, yFromPhase(valP[graphPEQWidth]));
            ctx.lineTo(graphPEQWidth + 100, yFromPhase(0));
            ctx.moveTo(-100, yFromGain(0));
            ctx.lineTo(-2, yFromGain(0));
            ctx.closePath();

            ctx.setLineDash([15, 15]);
            ctx.fillStyle = "rgba(255, 255, 255, .1)";
            ctx.fill("nonzero");
            ctx.stroke();
        }
        //MAG + PHASE
        else if (peqViewMode === 2) {
            ctx.beginPath();
            ctx.strokeStyle = "rgba(230, 230, 230, 1)";
            ctx.moveTo(-2, graphPEQHeight + 2);
            ctx.lineTo(-2, yFromGain(valG[0]));
            for (var i = 0; i < graphPEQWidth; i++) {
                ctx.lineTo(i, yFromGain(valG[i]));
            }
            ctx.lineTo(graphPEQWidth + 100, yFromGain(valG[graphPEQWidth - 1]));
            ctx.lineTo(graphPEQWidth + 100, graphPEQHeight);
            ctx.setLineDash([]);
            ctx.fillStyle = "rgba(255, 255, 255,.1)";
            ctx.fill("nonzero");
            ctx.setLineDash([]);
            ctx.stroke();
            ctx.beginPath();
            ctx.moveTo(-100, yFromPhase(0));
            for (var i = 0; i < graphPEQWidth; i++) {
                ctx.lineTo(i, yFromPhase(valP[i]));
            }
            ctx.lineTo(graphPEQWidth + 100, yFromPhase(valP[graphPEQWidth]));
            ctx.setLineDash([10, 5]);
            ctx.stroke();
        }
    }
}

//INITIALIZE THE DRAGGABILITY OF THE PEQ
$.fn.initiatePEQDraggie = function() {
    // console.log("initiatePEQDRAGGIE");
    //ENABLE EACH PEQS TO BE DRAGGABLE AND SET FUNCTION TO peqDrag EVENTS
    for (var i = 0; i < eqCount; i++) {
        var a = "#dragPEQ" + i;

        // IF XLOCK AND YLOCK IS ENABLE ----> DISABLE THE DRAG AND DROP
        if (widgetPEQMainXLock === true && widgetPEQMainYLock === true) {
            peqDrag[i] = $(a).draggabilly('disable');
        } else if (widgetPEQMainXLock === true && widgetPEQMainYLock === false) {
            peqDrag[i] = $(a).draggabilly({ containment: "#dragWidgetPEQ", axis: "x" });
            peqDrag[i] = $(a).draggabilly('enable');
        } else if (widgetPEQMainXLock === false && widgetPEQMainYLock === true) {
            peqDrag[i] = $(a).draggabilly({ containment: "#dragWidgetPEQ", axis: "y" });
            peqDrag[i] = $(a).draggabilly('enable');
        } else if (widgetPEQMainXLock === false && widgetPEQMainYLock === false) {
            peqDrag[i] = $(a).draggabilly({ containment: "#dragWidgetPEQ", axis: "null" });
            peqDrag[i] = $(a).draggabilly('enable');
        }

        // IF PEQ FILTER IS NO GAIN NEEDED FIX THE GAIN AXE AND SET VALUE TO 0
        if ($.inArray(arrayEqParam[i].type, [2, 7, 8, 9, 10, 11, 12, 13, 14, 15]) >= 0) {
            // console.log("var test eq type = type no gain needed");
            peqDrag[i] = $(a).draggabilly({ containment: "#dragWidgetPEQ", axis: "x" });
            arrayEqParam[i].gain = 0;
            $.fn.draggieSetPosition(i);
            peqDrag[i] = $(a).draggabilly('enable');
        } else
        if ($.inArray(arrayEqParam[i].type, [2, 7, 8, 9, 10, 11, 12, 13, 14, 15]) >= 0 && widgetPEQMainYLock === true) {
            peqDrag[i] = $(a).draggabilly('disable');
        }

        //EXECUTE AFTER RELEASE EQ
        peqDrag[i].on("dragEnd", function() {});
        //GET THE DRAGGABILLY INSTANCE FROM A JQUERY OBJECT 
        peqDraggie[i] = peqDrag[i].data("draggabilly");
        //EXECUTE DURING THE peqDrag AND DROP OPERATION EQ
        peqDrag[i].on("dragMove", function() {
            //FIND NUMBER IN ID (FROM 0 TO 11);
            var num = parseInt(this.id.toString().match(/(\d+)/g).map(Number));
            peqSoloSelected = num;
            var freq = 0;
            var gain = 0;

            gain = Math.round(gainFromY((peqDraggie[num].position.y - widgetPEQMarginTop + 8)) * 100) / 100;
            if (gain > gainScaleMaxPEQ) {
                gain = gainScaleMaxPEQ;
            }
            if (gain < gainScaleMinPEQ) {
                gain = gainScaleMinPEQ;
            }
            localAmplifier.channel[soloChannelSelected].peq.peq[num].gain = gain;

            freq = Math.round(freqFromX((peqDraggie[num].position.x - widgetPEQMarginLeft)));
            if (freq > freqScaleMaxPEQ) {
                freq = freqScaleMaxPEQ;
            }
            if (freq < freqScaleMinPEQ) {
                freq = freqScaleMinPEQ;
            }
            localAmplifier.channel[soloChannelSelected].peq.peq[num].frequency = freq;

            $.fn.setDataSoloPEQ(num, 5);
        });

        if (arrayEqParam[i].ena === true) {
            $("#dragPEQ" + i).draggabilly('enable');
            if (!$("#dragPEQ" + i).hasClass("enable"))
                $("#dragPEQ" + i).toggleClass("enable");
            if (!$("#label" + i).hasClass("enable"))
                $("#label" + i).toggleClass("enable");
            if (!$("#peqAnav" + i).hasClass("enable"))
                $("#peqAnav" + i).toggleClass("enable");
        }
    }
}

$.fn.draggieSetPosition = function(num) {
    if (arrayEqParamDraggable[num])
        arrayEqParamDraggable[num].draggabilly('setPosition', xFromFreq(arrayEqParam[num].frequency) + widgetPEQMarginLeft, yFromGain(arrayEqParam[num].gain) + 6);
}

$.fn.initSliderPEQ = function() {
    // SLIDER FREQ PEQ
    for (var i = 0; i < eqCount; i++) {
        var id = "#sliderHorizontalFreqPEQ" + i;
        $(id).slider({
            orientation: "horizontal",
            range: "min",
            min: 1,
            max: Math.log10(freqScaleMaxPEQ),
            step: 0.00001,
            value: 1,
            slide: function(event, ui) {
                var num = parseInt(this.id.toString().match(/(\d+)/g).map(Number));
                localAmplifier.channel[soloChannelSelected].peq.peq[num].frequency = Math.round(Math.pow(10, ui.value));
                $.fn.drawXOVERWidget(0, localAmplifier.channel[soloChannelSelected].xover.hpType);
                $.fn.drawXOVERWidget(1, localAmplifier.channel[soloChannelSelected].xover.lpType);
                //SEND DATA TO AMPLIFIER
                $.fn.setDataSoloPEQ(num, 2);
            }
        });
    }

    // SLIDER GAIN PEQ
    for (var i = 0; i < eqCount; i++) {
        var id = "#sliderHorizontalGainPEQ" + i;
        $(id).slider({
            orientation: "horizontal",
            range: "min",
            min: -40.0,
            max: 15.0,
            step: 0.1,
            value: 0,
            slide: function(event, ui) {
                var num = parseInt(this.id.toString().match(/(\d+)/g).map(Number));
                localAmplifier.channel[soloChannelSelected].peq.peq[num].gain = ui.value;
                $.fn.drawXOVERWidget(0, localAmplifier.channel[soloChannelSelected].xover.hpType);
                $.fn.drawXOVERWidget(1, localAmplifier.channel[soloChannelSelected].xover.lpType);
                //SEND DATA TO AMPLIFIER
                $.fn.setDataSoloPEQ(num, 3);

            }
        });
    }

    // SLIDER Q PEQ
    for (var i = 0; i < eqCount; i++) {
        var id = "#sliderHorizontalQPEQ" + i;
        $(id).slider({
            orientation: "horizontal",
            range: "min",
            min: Math.log10(0.1),
            max: Math.log10(48),
            step: 0.0001,
            value: 2.5,
            slide: function(event, ui) {
                var num = parseInt(this.id.toString().match(/(\d+)/g).map(Number));
                localAmplifier.channel[soloChannelSelected].peq.peq[num].q = Math.round(Math.pow(10, ui.value) * 100) / 100;
                $.fn.drawXOVERWidget(0, localAmplifier.channel[soloChannelSelected].xover.hpType);
                $.fn.drawXOVERWidget(1, localAmplifier.channel[soloChannelSelected].xover.lpType);
                //SEND DATA TO AMPLIFIER
                $.fn.setDataSoloPEQ(num, 4);
            }
        });
    }
}

//SETUP XOVER MAIN PANEL FOR AMP VIEW
$.fn.setupXOVERSolo = function() {

    //ERASE PREVIOUS VERSION OF XOVER MAIN PANEL
    $("#xoverMainPanel").html("");

    //ITEM FULL FOR BACKGROUND
    $("#xoverMainPanel").append($("<div>").prop({ id: "xoverItemFull", className: "itemFull" }));

    //BUTTON VIEW
    $("#xoverItemFull").append($("<button>").prop({ id: "xoverView", className: "itemFullButtonViewXOVER" }));
    $("#xoverView").attr("data-toggle", "modal");
    $("#xoverView").attr("data-target", "#xoverViewModeModal");
    $("#xoverView").append($("<div>").prop({ id: "xoverModalViewDiv", className: "media" }));
    $("#xoverModalViewDiv").append($("<img>").prop({ src: "./img/View.png", className: "logoPeqViewButton" }));

    //DRAWING AREA FOR XOVER
    $("#xoverItemFull").append($("<div>").prop({ id: "widgetXOVER" }));

    //PARAMETERS AREA FOR XOVER
    $("#xoverItemFull").append($("<div>").prop({ id: "parametersAreaXOVER" }));

    //XOVER SOLO PARAMETERS AREA
    $("#parametersAreaXOVER").append($("<div>").prop({ id: "paramXOVERArea" }));

    $("#parametersAreaXOVER").css("margin-top", widgetPEQY + 20 + "px");

    // $("#parametersAreaXOVER").append($("<div>").prop({ class: "peqEndSpacer" }));

    var str = "";

    str += "<div class=\"slidersXOVERContainer\">";
    str += "<div class=\"container123\">";
    str += "<div class=\"row justify-content-md-center\">";

    //FIR MODULE
    str += "<div class=\"col col-lg-2 col-md-10  bgPEQParameterAreaSolo\">";
    str += "<h6 class=\"col-12\">FIR</h6>";
    str += "<div class=\"enaInputPEQSolo\">";
    str += "<input type=\"checkbox\" class=\"ios8-switch enaFirXOVER\" id=\"enableToggleFirXOVER\">";
    str += "<label  for=\"enableToggleFirXOVER\"></label>";
    str += "<button class=\"firButtonXOVER\" id=\"firXover\" data-toggle=\"modal\"><img id=\"peqImgSolo\" src=\"./img/FIR.png\" height=\"24px\"></button>";
    str += "</div>";
    str += "<span id=\"firLoadedName\" class=\"firLoadedNameSpan\"></span>";
    str += "</div>";

    //LOW PASS HIGH PASS FILTER BOX
    str += "<div class=\"col col-lg-4 col-md-10 bgPEQParameterAreaSolo\">";
    str += "<h6 class=\"col-12\">High-Pass</h6>";
    str += "<div class=\"row\" style=\"height: 32px;\">";
    str += "<div class=\"col-12\">";
    str += "<button class=\"typeFilterXOVER\" id=\"typeHighPassXover\" data-toggle=\"modal\" data-target=\"#modalXOVERTypeHighPass\"><img id=\"peqImgSolo\" src=\"./img/XOver.png\" height=\"24px\"></button>";
    str += "<span id=\"highPassXOVERLabel\" class=\"xoverLabel\"><\span>";
    str += "</div>";
    str += "<div class=\"col-12\">";
    str += "<input type=\"checkbox\" class=\"ios8-switch enaXOVER switchXOVER\" id=\"enaToggleHighPassXOVER\">";
    str += "<label class=\"switchXOVER\" for=\"enaToggleHighPassXOVER\"></label>";
    str += "</div>";
    str += "</div>";
    str += "<div class=\"row\">";
    str += "<div class=\"col-2 col-md-2\"><button id=\"xoverHPFreqDownButton\" type=\"submit\" class=\"btn btn-outline-dark btn-sm mb-2\">&nbsp-&nbsp</button></div>";
    str += "<div class=\"col-8 col-md-8\"><input id=\"freq_HighPassXOVER\" type=\"number\" step=\"1\" class=\"freqInputXOVER form-control form-control-sm\"></div>";
    str += "<div class=\"col-2 col-md-2\"><button id=\"xoverHPFreqUpButton\" type=\"submit\" class=\"btn btn-outline-dark btn-sm mb-2\">&nbsp+&nbsp</button></div>";
    str += "</div>";
    str += "<div class=\"row\" style=\"height: 32px;\">";
    str += "<div class=\"col col-lg-1\"></div>";
    str += "<div id=\"sliderHorizontalHighPassXOVER\" class=\"sliderHorizontalFreqPEQ col-10 col-sm-10 col-md-10 col-lg-10\"></div>";
    str += "<div class=\"col col-lg-1\"></div>";
    str += "</div>";
    str += "<div class=\"row\" style=\"height: 16px;\">";
    str += "</div>";
    str += "<div class=\"col-12\">";
    str += "<input type=\"checkbox\" class=\"enaXOVEROveride switchXOVEROveride\" id=\"enaToggleHighPassXOVEROveride\">";
    str += "<label class=\"switchXOVEROveride\" for=\"enaToggleHighPassXOVEROveride\">Enable HP override</label>";
    str += "</div>";
    str += "</div>";
    str += "<div class=\"col col-lg-4 col-md-10 bgPEQParameterAreaSolo\">";
    str += "<h6>Low-Pass</h6>";
    str += "<div class=\"row\" style=\"height: 32px;\">";
    str += "<div class=\"col-12\">";
    str += "<button class=\"typeFilterXOVER\"  id=\"typeLowPassXover\"  data-toggle=\"modal\" data-target=\"#modalXOVERTypeLowPass\"><img id=\"peqImgSolo\" src=\"./img/XOver.png\" height=\"24px\"></button>";
    str += "<span id=\"lowPassXOVERLabel\" class=\"xoverLabel\"><\span>";
    str += "</div>";
    str += "<div class=\"col-12\">";
    str += "<input type=\"checkbox\" class=\"ios8-switch enaXOVER switchXOVER\" id=\"enaToggleLowPassXOVER\">";
    str += "<label class=\"switchXOVER\" for=\"enaToggleLowPassXOVER\"></label>";
    str += "</div>";
    str += "</div>";
    str += "<div class=\"row\">";
    str += "<div class=\"col-2 col-md-2\"><button id=\"xoverLPFreqDownButton\" type=\"submit\" class=\"btn btn-outline-dark btn-sm mb-2\">&nbsp-&nbsp</button></div>";
    str += "<div class=\"col-8 col-md-8\"><input id=\"freq_LowPassXOVER\" type=\"number\" step=\"0.1\" class=\"freqInputXOVER form-control form-control-sm\"></div>";
    str += "<div class=\"col-2 col-md-2\"><button id=\"xoverLPFreqUpButton\" type=\"submit\" class=\"btn btn-outline-dark btn-sm mb-2\">&nbsp+&nbsp</button></div>";
    str += "</div>";
    str += "<div class=\"row\" style=\"height: 32px;\">";
    str += "<div class=\"col col-lg-1\"></div>";
    str += "<div id=\"sliderHorizontalLowPassXOVER\" class=\"sliderHorizontalGainPEQ col-10 col-sm-10 col-md-10 col-lg-10\"></div>";
    str += "<div class=\"col col-lg-1\"></div>";
    str += "</div>";
    str += "<div class=\"row\" style=\"height: 16px;\">";
    str += "</div>";
    str += "<div class=\"col-12\">";
    str += "<input type=\"checkbox\" class=\"enaXOVEROveride switchXOVEROveride\" id=\"enaToggleLowPassXOVEROveride\">";
    str += "<label class=\"switchXOVEROveride\" for=\"enaToggleLowPassXOVEROveride\">Enable LP override</label>";
    str += "</div>";
    str += "</div>";
    $("#paramXOVERArea").html(str);

    $("#highPassXOVERLabel").html(xoverLabel[highPassDefaultType]);
    $("#lowPassXOVERLabel").html(xoverLabel[lowPassDefaultType]);

    //FILL CONTENT OF MODAL WINDOWS
    $("#modalXOVERTabContentHighPass").html("");
    $("#modalXOVERTabContentLowPass").html("");

    var number_of_rows = 5;
    var number_of_cols = 4;
    var table_body = "<table class=\"xoverModalType\">";
    for (var i = 0; i < number_of_rows; i++) {
        table_body += "<tr>";
        for (var j = 0; j < number_of_cols; j++) {
            var t = i * 4 + j;
            if (xoverLabel[t]) {
                table_body += "<td>";
                table_body += "<button class=\"btn btn-default xoverModalTypeBtn\" id=\"xoverTypeModalHighPass" + t + "\">";
                table_body += "<div class=\"media\">";
                table_body += "<img class=\"peqModalTypeLogo logoPeqViewButton\" src=\"./img/XOver.png\">";
                table_body += "</div>";
                table_body += "<div class=\"peqModalTypeText\">" + xoverLabel[t] + "</div>";
                table_body += "</button>";
                table_body += "</td>";
                // displayVal("T", t);
            }
        }
        table_body += "</tr>";
    }
    table_body += "</table>";

    $("#modalXOVERTabContentHighPass").html(table_body);

    table_body = "";
    table_body = "<table class=\"xoverModalType\">";
    for (var i = 0; i < number_of_rows; i++) {
        table_body += "<tr>";
        for (var j = 0; j < number_of_cols; j++) {
            var t = i * 4 + j;
            if (xoverLabel[t]) {
                table_body += "<td>";
                table_body += "<button class=\"btn btn-default xoverModalTypeBtn\" id=\"xoverTypeModalLowPass" + t + "\">";
                table_body += "<div class=\"media\">";
                table_body += "<img class=\"peqModalTypeLogo logoPeqViewButton\" src=\"./img/XOver.png\">";
                table_body += "</div>";
                table_body += "<div class=\"peqModalTypeText\">" + xoverLabel[t] + "</div>";
                table_body += "</button>";
                table_body += "</td>";
                // displayVal("T", t);
            }
        }
        table_body += "</tr>";
    }
    table_body += "</table>";

    $("#modalXOVERTabContentLowPass").html(table_body);

    $.fn.initSliderXOVER();
};

//DRAW XOVER (mode = 0 : only Mag, mode = 1 : only phase, mode = 2 : dual view) (scale = 0 : -12 to 6, scale = 1 : -24 to 6, scale = 2 : -48 to 6, scale = 3 : -120 to 10) (phase 0 : phase 180, phase = 1 : phase 360)
$.fn.initXOVER = function(mode, scale, phase) {

    peqViewMode = mode;
    xoverGainScaleType = scale;
    xoverPhaseScaleType = phase;

    $("#canvasWidgetXOVER").remove();
    $("#graphWidgetXOVER").remove();
    $("#widgetXOVER").html("");

    highPassEqParam = new XoverParam(eqEnaDefault, highPassDefaultFrequency, eqGainDefault, eqQDefault, highPassDefaultType, eqXLockDefault, eqYLockDefault);
    lowPassEqParam = new XoverParam(eqEnaDefault, lowPassDefaultFrequency, eqGainDefault, eqQDefault, lowPassDefaultType, eqXLockDefault, eqYLockDefault);

    graphXOVERHeight = widgetXOVERY - widgetXOVERMarginTop - widgetXOVERMarginBottom;

    if (peqViewMode === 2)
        graphXOVERWidth = widgetXOVERX - widgetXOVERMarginLeft - widgetXOVERMarginRightDual;
    else
        graphXOVERWidth = widgetXOVERX - widgetXOVERMarginLeft - widgetXOVERMarginRight;

    //BACKGROUND INIT
    var canvasXOVER = document.createElement("canvas");
    canvasXOVER.id = "canvasWidgetXOVER";
    canvasXOVER.width = widgetXOVERX;
    canvasXOVER.height = widgetXOVERY;
    $("#widgetXOVER").append(canvasXOVER);

    //CURVE DRAWING AREA INIT
    var graphXOVER = document.createElement("canvas");
    graphXOVER.id = "graphWidgetXOVER";
    graphXOVER.width = graphXOVERWidth;
    graphXOVER.height = graphXOVERHeight;
    graphXOVER.style.marginTop = "" + widgetXOVERMarginTop + "px";
    graphXOVER.style.marginLeft = "" + widgetXOVERMarginLeft + "px";
    $("#widgetXOVER").append(graphXOVER);

    //CREATE peqDrag AREA FOR PEQ
    var dragXOVER = document.createElement("div");
    dragXOVER.id = "dragWidgetXOVER";
    dragXOVER.setAttribute("style", "width:" + (graphXOVERWidth) + "px; height:" + (graphXOVERHeight + 6) + "px; margin-top:" + widgetXOVERMarginTop + "px; margin-left: " + (widgetXOVERMarginLeft - 9) + "px;");
    $("#widgetXOVER").append(dragXOVER);

    //INIT EXTERNAL CANVAS
    var c = document.getElementById("canvasWidgetXOVER");
    if (c != null) {
        var ctx = c.getContext("2d");
        c.style.width = widgetXOVERX;
        c.style.height = widgetXOVERY;
        ctx.beginPath();

        //BG COLOR
        ctx.rect(0, 0, widgetXOVERX, widgetXOVERY);
        ctx.fillStyle = "#0a1a29";
        ctx.fill();

        //VERTICAL AXE

        //MAG ONLY
        if (peqViewMode === 0) {
            var localGainGap = Math.max(...gain_scaleXOVER[xoverGainScaleType]) - Math.min(...gain_scaleXOVER[xoverGainScaleType]);
            // displayVal("gap", localGainGap);
            ctx.strokeStyle = "#3e4954";
            for (var i = 0; i < gain_scaleXOVER_line[xoverGainScaleType].length; i++) {
                var step = localGainGap / (gain_scaleXOVER_line[xoverGainScaleType].length - 1);
                step = step * graphXOVERHeight / localGainGap;
                ctx.moveTo(widgetXOVERMarginLeft, widgetXOVERMarginTop + i * step);
                ctx.lineTo(widgetXOVERX - widgetXOVERMarginRight, widgetXOVERMarginTop + i * step);
                ctx.stroke();
                ctx.font = "12px Arial";
                ctx.fillStyle = "white";
                ctx.textAlign = "right";
                if (gain_scaleXOVER[xoverGainScaleType].includes(gain_scaleXOVER_line[xoverGainScaleType][i]) != 0)
                    ctx.fillText(gain_scaleXOVER_line[xoverGainScaleType][i].toString(), widgetXOVERMarginLeft - 5, widgetXOVERMarginTop + i * step + 5);
            }
            yZeroXOVER = yFromGainXOVER(0);
        }
        //PHASE ONLY 
        else if (peqViewMode === 1) {
            var localPhaseGap = Math.max(...phase_scale[xoverPhaseScaleType]) - Math.min(...phase_scale[xoverPhaseScaleType]);
            // displayVal("gap", localPhaseGap);
            ctx.strokeStyle = "#3e4954";
            for (var i = 0; i < phase_scale_line[xoverPhaseScaleType].length; i++) {
                var step = localPhaseGap / (phase_scale_line[xoverPhaseScaleType].length - 1);
                step = step * graphXOVERHeight / localPhaseGap;
                ctx.moveTo(widgetXOVERMarginLeft, widgetXOVERMarginTop + i * step);
                ctx.lineTo(widgetXOVERX - widgetXOVERMarginRight, widgetXOVERMarginTop + i * step);
                ctx.stroke();
                ctx.font = "12px Arial";
                ctx.fillStyle = "white";
                ctx.textAlign = "right";
                if (phase_scale[xoverPhaseScaleType].includes(phase_scale_line[xoverPhaseScaleType][i]) != 0)
                    ctx.fillText(phase_scale_line[xoverPhaseScaleType][i].toString() + "°", widgetXOVERMarginLeft - 5, widgetXOVERMarginTop + i * step + 5);
            }
            yZeroXOVER = yFromGainXOVER(0);
        }
        //MAG + PHASE
        else if (peqViewMode === 2) {
            var localGainGap = Math.max(...gain_scaleXOVER[xoverGainScaleType]) - Math.min(...gain_scaleXOVER[xoverGainScaleType]);
            // displayVal("gap", localGainGap);
            ctx.strokeStyle = "#3e4954";
            for (var i = 0; i < gain_scaleXOVER_line[xoverGainScaleType].length; i++) {
                var step = localGainGap / (gain_scaleXOVER_line[xoverGainScaleType].length - 1);
                step = step * graphXOVERHeight / localGainGap;
                ctx.moveTo(widgetXOVERMarginLeft, widgetXOVERMarginTop + i * step);
                ctx.lineTo(widgetXOVERX - widgetXOVERMarginRightDual, widgetXOVERMarginTop + i * step);
                ctx.stroke();
                ctx.font = "12px Arial";
                ctx.fillStyle = "white";
                ctx.textAlign = "right";
                if (gain_scaleXOVER[xoverGainScaleType].includes(gain_scaleXOVER_line[xoverGainScaleType][i]) != 0)
                    ctx.fillText(gain_scaleXOVER_line[xoverGainScaleType][i].toString(), widgetXOVERMarginLeft - 5, widgetXOVERMarginTop + i * step + 5);
            }
            yZeroXOVER = yFromGainXOVER(0);

            var localPhaseGap = Math.max(...phase_scale[xoverPhaseScaleType]) - Math.min(...phase_scale[xoverPhaseScaleType]);
            // displayVal("gap", localPhaseGap);
            ctx.strokeStyle = "#3e4954";
            for (var i = 0; i < phase_scale_line[xoverPhaseScaleType].length; i++) {

                var step = localPhaseGap / (phase_scale_line[xoverPhaseScaleType].length - 1);
                step = step * graphXOVERHeight / localPhaseGap;
                ctx.font = "12px Arial";
                ctx.fillStyle = "white";
                ctx.textAlign = "left";
                if (phase_scale[xoverPhaseScaleType].includes(phase_scale_line[xoverPhaseScaleType][i]) != 0)
                    ctx.fillText(phase_scale_line[xoverPhaseScaleType][i].toString() + "°", widgetXOVERX - widgetXOVERMarginRightDual + 5, widgetXOVERMarginTop + i * step + 5);
            }
        }

        //FREQUENCY AXE
        ctx.strokeStyle = "#3e4954";
        var j = 0;
        ctx.font = "12px Arial";
        ctx.fillStyle = "white";
        ctx.textAlign = "center";
        // displayVal("size widget Y", widgetPEQX);
        var a = widgetXOVERY;
        for (var i = 0; i < freq_scale_line.length; i++) {
            // displayVal("X", x - 1);
            ctx.moveTo(xFromFreqXOVER(freq_scale_line[i]) + widgetXOVERMarginLeft, widgetXOVERMarginTop);
            if (peqViewMode === 2) {
                a = graphXOVERHeight + widgetXOVERMarginTop + widgetXOVERMarginBottom;
                ctx.lineTo(xFromFreqXOVER(freq_scale_line[i]) + widgetXOVERMarginLeft, a - widgetXOVERMarginBottom);
            } else
                ctx.lineTo(xFromFreqXOVER(freq_scale_line[i]) + widgetXOVERMarginLeft, widgetXOVERY - widgetXOVERMarginBottom);
            ctx.stroke();
            if (freq_scale.includes(freq_scale_line[i]) != 0) {
                if (i === 0)
                    ctx.fillText(freq_scale_text[j].toString(), widgetXOVERMarginLeft, a - 10);
                else
                    ctx.fillText(freq_scale_text[j].toString(), xFromFreqXOVER(freq_scale_line[i]) + widgetXOVERMarginLeft, a - 10);
                j++;
            }
        }

        if (peqViewMode === 2)
            ctx.strokeRect(widgetXOVERMarginLeft, widgetXOVERMarginTop, widgetXOVERX - widgetXOVERMarginLeft - widgetXOVERMarginRightDual, a - widgetXOVERMarginTop - widgetXOVERMarginBottom);
        else
            ctx.strokeRect(widgetXOVERMarginLeft, widgetXOVERMarginTop, widgetXOVERX - widgetXOVERMarginLeft - widgetXOVERMarginRight, a - widgetXOVERMarginTop - widgetXOVERMarginBottom);

        //INITIALIZE HIGHPASS LOWPASS
        //ADD WHITE BORDER TRANSPARENT BACKGROUND AND NUMBER ON HIGHPASS AND LOWPASS
        if (peqViewMode != 1) {

            // HIGHPASS
            var divLabelGraphXOVERHighPass = document.createElement("div");
            divLabelGraphXOVERHighPass.id = "dragHighPass";
            divLabelGraphXOVERHighPass.className = "circleEq";

            var bgCircleXOVERHighPass = document.createElement("div");
            bgCircleXOVERHighPass.className = "bgCircleEq";

            var labelGraphXOVERHighPass = document.createElement("p");
            labelGraphXOVERHighPass.id = "labelHighPass";
            labelGraphXOVERHighPass.className = "labelEq";

            labelGraphXOVERHighPass.innerHTML = "H";
            $("#widgetXOVER").append(divLabelGraphXOVERHighPass);

            highPassDrag = $("#dragHighPass");

            $("#dragHighPass").append(bgCircleXOVERHighPass);
            $("#dragHighPass").append(labelGraphXOVERHighPass);

            // LOWPASS
            var divLabelGraphXOVERLowPass = document.createElement("div");
            divLabelGraphXOVERLowPass.id = "dragLowPass"
            divLabelGraphXOVERLowPass.className = "circleEq";

            var bgCircleXOVERLowPass = document.createElement("div");
            bgCircleXOVERLowPass.className = "bgCircleEq";

            var labelGraphXOVERLowPass = document.createElement("p");
            labelGraphXOVERLowPass.id = "labelLowPass";
            labelGraphXOVERLowPass.className = "labelEq";

            labelGraphXOVERLowPass.innerHTML = "L";
            $("#widgetXOVER").append(divLabelGraphXOVERLowPass);

            lowPassDrag = $("#dragLowPass");

            $("#dragLowPass").append(bgCircleXOVERLowPass);
            $("#dragLowPass").append(labelGraphXOVERLowPass);

        }

        //INITIALIZE TAB OF TEMP VALUE FOR DRAWING
        for (var i = 0; i < xoverCount; i++) {
            xoverTabMagX[i] = new Array(graphXOVERWidth);
            xoverTabPhaX[i] = new Array(graphXOVERWidth);
            for (var j = 0; j < graphXOVERWidth; j++) {
                xoverTabMagX[i][j] = 0;
                xoverTabPhaX[i][j] = 0;
            }
        }

        //SET INITIAL POSITION FOR EVERY XOVER DEPENDING ON THE DEFAULT VALUE

        // $.fn.setupXOVERSolo();

        $.fn.initiateXOVERDraggie();

        $.fn.setDataSoloXover(4, 99);
    }
}

//INITIALIZE THE DRAGGABILITY OF THE XOVER
$.fn.initiateXOVERDraggie = function() {

    //ENABLE HIGH PASS LOWW PASS TO BE DRAGGABLE AND SET FUNCTION TO peqDrag EVENTS
    highPassDrag = $("#dragHighPass").draggabilly({ containment: "#dragWidgetXOVER", axis: "x" });
    lowPassDrag = $("#dragLowPass").draggabilly({ containment: "#dragWidgetXOVER", axis: "x" });

    if (localAmplifier.channel[soloChannelSelected].xover.hpEna === true)
        highPassDrag.draggabilly("enable");
    else
        highPassDrag.draggabilly("disable");

    if (localAmplifier.channel[soloChannelSelected].xover.lpEna === true)
        lowPassDrag.draggabilly("enable");
    else
        lowPassDrag.draggabilly("disable");

    //EXECUTE AFTER RELEASE EQ
    highPassDrag.on("dragEnd", function() {
        //SEND EQ VALUES
    });
    lowPassDrag.on("dragEnd", function() {
        //SEND EQ VALUES
    });
    //GET THE DRAGGABILLY INSTANCE FROM A JQUERY OBJECT 
    highPassDraggie = highPassDrag.data("draggabilly");
    lowPassDraggie = lowPassDrag.data("draggabilly");
    //EXECUTE DURING THE peqDrag AND DROP OPERATION EQ
    highPassDrag.on("dragMove", function() {
        localAmplifier.channel[soloChannelSelected].xover.hpFreq = Math.round(freqFromXXOVER((highPassDraggie.position.x - widgetXOVERMarginLeft)));
        $.fn.setDataSoloXover(5, 2);
    });
    //EXECUTE DURING THE peqDrag AND DROP OPERATION EQ
    lowPassDrag.on("dragMove", function() {
        localAmplifier.channel[soloChannelSelected].xover.lpFreq = Math.round(freqFromXXOVER((lowPassDraggie.position.x - widgetXOVERMarginLeft)));
        $.fn.setDataSoloXover(6, 5);
    });
}

//REDRAW CURVES
$.fn.drawXOVERWidget = function(type, indice) {
    var c = document.getElementById("graphWidgetXOVER");
    var ctx = c.getContext("2d");

    ctx.strokeStyle = '#00a3e0';
    ctx.clearRect(0, 0, c.width, c.height);
    ctx.lineWidth = 2;
    ctx.beginPath();
    ctx.setLineDash([]);

    computeXOVERCoeff(type, indice);
    //IF HIGHPASS FILTER, WE ONLY COMPUTE HP VALUE, AND USE LP VALUE FROM MEMORY AND VICE VERSA
    ctx.beginPath();
    if (localAmplifier.channel[soloChannelSelected].xover.hpEna === true || localAmplifier.channel[soloChannelSelected].xover.lpEna === true) {
        //MAG ONLY
        if (peqViewMode === 0) {
            ctx.moveTo(-100, yFromGainXOVER($.fn.processXover(10, type, indice).magnitude));
            for (var i = 0; i < graphXOVERWidth; i++) {
                var y = $.fn.processXover(i, type, indice);
                ctx.lineTo(i, yFromGainXOVER(y.magnitude));
                xoverTabMagX[type][i] = y.magnitude;
                xoverTabPhaX[type][i] = y.phase;
            }
            var t = Math.round($.fn.processXover(graphXOVERWidth + 2, type, indice).magnitude);
            ctx.lineTo(graphXOVERWidth + 100, yFromGainXOVER(t));
            ctx.lineTo(graphXOVERWidth + 100, graphXOVERHeight + 100);
            ctx.lineTo(-100, graphXOVERHeight + 2)
            ctx.lineTo(-100, yFromGainXOVER($.fn.processXover(10, type, indice).magnitude));
            ctx.fillStyle = "rgba(83, 230, 246, 0.2)";
            ctx.fill("nonzero");
        }
        //PHASE ONLY 
        else if (peqViewMode === 1) {
            for (var i = 0; i < graphXOVERWidth; i++) {
                var y = $.fn.processXover(i, type, indice);
                xoverTabMagX[type][i] = y.magnitude;
                xoverTabPhaX[type][i] = y.phase;
            }
        }
        //MAG + PHASE
        else if (peqViewMode === 2) {
            ctx.moveTo(-2, yFromGainXOVER($.fn.processXover(10, type, indice).magnitude));
            for (var i = 0; i < graphXOVERWidth; i++) {
                var y = $.fn.processXover(i, type, indice);
                ctx.lineTo(i, yFromGainXOVER(y.magnitude));
                xoverTabMagX[type][i] = y.magnitude;
                xoverTabPhaX[type][i] = y.phase;
            }
            var t = Math.round($.fn.processXover(graphXOVERWidth + 2, type, indice).magnitude);
            ctx.lineTo(graphXOVERWidth + 2, yFromGainXOVER(t));
            ctx.lineTo(graphXOVERWidth + 2, graphXOVERHeight + 2);
            ctx.lineTo(-10, graphXOVERHeight + 2)
            ctx.lineTo(-2, yFromGainXOVER($.fn.processXover(10, type, indice).magnitude));
            ctx.fillStyle = "rgba(83, 230, 246, 0.2)";
            ctx.fill("nonzero");
        }
        ctx.stroke();
    } else {
        // displayVal("true true enable", "test pass");
        for (var i = 0; i < xoverCount; i++) {
            for (var j = 0; j < graphXOVERWidth; j++) {
                xoverTabMagX[i][j] = 0;
                xoverTabPhaX[i][j] = 0;
            }
        }
    }

    ctx.beginPath();
    var valG = new Array(graphXOVERWidth);
    var valP = new Array(graphXOVERWidth);
    ctx.strokeStyle = 'rgba(254, 142, 0, 1)';
    ctx.lineWidth = 2;
    for (var i = 0; i < graphXOVERWidth; i++) {
        valG[i] = 0;
        valP[i] = 0;
        if (localAmplifier.channel[soloChannelSelected].xover.hpEna === true) {
            valG[i] = valG[i] + xoverTabMagX[0][i];
            valP[i] = valP[i] + xoverTabPhaX[0][i];
        }
        if (localAmplifier.channel[soloChannelSelected].xover.lpEna === true) {
            valG[i] = valG[i] + xoverTabMagX[1][i];
            valP[i] = valP[i] + xoverTabPhaX[1][i];
        }
    }
    //MAG ONLY
    if (peqViewMode === 0) {
        ctx.moveTo(0, yFromGainXOVER(valG[0]));
        for (var i = 0; i < graphXOVERWidth; i++) {
            ctx.lineTo(i, yFromGainXOVER(valG[i]));
        }
    }
    //PHASE ONLY 
    else if (peqViewMode === 1) {
        ctx.moveTo(-100, yFromPhaseXOVER(0));
        ctx.lineTo(0, yFromPhaseXOVER(valP[0]));
        for (var i = 0; i < graphXOVERWidth; i++) {
            ctx.lineTo(i, yFromPhaseXOVER(valP[i]));
        }
        ctx.setLineDash([15, 15]);
    }
    //MAG + PHASE
    else if (peqViewMode === 2) {
        ctx.moveTo(0, yFromGainXOVER(valG[0]));
        for (var i = 0; i < graphXOVERWidth; i++) {
            ctx.lineTo(i, yFromGainXOVER(valG[i]));
        }
        ctx.setLineDash([]);
        ctx.strokeStyle = '#fe8e00';
        ctx.stroke();

        ctx.moveTo(-100, yFromPhaseXOVER(0));
        ctx.lineTo(-100, yFromPhaseXOVER(valP[0]));
        for (var i = 0; i < graphXOVERWidth; i++) {
            ctx.lineTo(i, yFromPhaseXOVER(valP[i]));
        }
        ctx.lineTo(graphXOVERWidth + 100, yFromPhaseXOVER(valP[graphXOVERWidth]));
        ctx.lineTo(graphXOVERWidth + 100, yFromPhaseXOVER(0));
        ctx.setLineDash([10, 5]);
    }
    ctx.stroke();

    //DRAW SUM CURVE ON XOVER CURVE
    //SUM OF PEQ AND CROSSOVER FILTER
    ctx.beginPath();
    var valPEQG = new Array(graphXOVERWidth);
    var valPEQP = new Array(graphXOVERWidth);
    ctx.strokeStyle = "rgba(230, 230, 230, 1)";
    ctx.lineWidth = 2;
    for (var i = 0; i < graphXOVERWidth; i++) {
        valPEQG[i] = 0;
        valPEQP[i] = 0;
        for (var x = 0; x < eqCount; x++) {
            if (arrayEqParam[x].ena === true) {
                valPEQG[i] = valPEQG[i] + peqTabMagX[x][i];
                valPEQP[i] = valPEQP[i] + peqTabPhaX[x][i];
            }
        }
        if (localAmplifier.channel[soloChannelSelected].xover.hpEna === true) {
            valPEQG[i] = valPEQG[i] + xoverTabMagX[0][i];
            valPEQP[i] = valPEQP[i] + xoverTabPhaX[0][i];
        }

        if (localAmplifier.channel[soloChannelSelected].xover.lpEna === true) {
            valPEQG[i] = valPEQG[i] + xoverTabMagX[1][i];
            valPEQP[i] = valPEQP[i] + xoverTabPhaX[1][i];
        }
    }

    //MAG ONLY
    if (peqViewMode === 0) {
        ctx.moveTo(0, yFromGainXOVER(valPEQG[0]));
        for (var i = 0; i < graphXOVERWidth; i++) {
            ctx.lineTo(i, yFromGainXOVER(valPEQG[i]));
        }
        ctx.lineTo(graphXOVERWidth + 100, yFromGainXOVER(0));
        ctx.lineTo(graphXOVERWidth + 100, widgetXOVERY + 2);
        ctx.lineTo(-100, widgetXOVERY + 2);
        ctx.lineTo(-100, yFromGainXOVER(valPEQG[0]));
        ctx.closePath();
        ctx.fillStyle = "rgba(255, 255, 255, .1)";
        ctx.fill("nonzero");
        ctx.setLineDash([]);
        ctx.stroke();
    }
    //PHASE ONLY 
    else if (peqViewMode === 1) {
        ctx.moveTo(-100, yFromPhaseXOVER(0));
        ctx.lineTo(0, yFromPhaseXOVER(valPEQP[0]));
        for (var i = 0; i < graphXOVERWidth; i++) {
            ctx.lineTo(i, yFromPhaseXOVER(valPEQP[i]));
        }
        ctx.lineTo(graphXOVERWidth + 100, yFromPhaseXOVER(valPEQP[graphXOVERWidth]));
        ctx.lineTo(graphXOVERWidth + 100, yFromPhaseXOVER(0));
        ctx.moveTo(-100, yFromGainXOVER(0));
        ctx.lineTo(-2, yFromGainXOVER(0));
        ctx.closePath();

        ctx.setLineDash([15, 15]);
        ctx.fillStyle = "rgba(255, 255, 255, .1)";
        ctx.fill("nonzero");
        ctx.stroke();
    }
    //MAG + PHASE
    else if (peqViewMode === 2) {
        ctx.moveTo(0, yFromGainXOVER(valPEQG[0]));
        for (var i = 0; i < graphXOVERWidth; i++) {
            ctx.lineTo(i, yFromGainXOVER(valPEQG[i]));
        }
        ctx.lineTo(graphXOVERWidth + 100, widgetXOVERY + 2);
        ctx.lineTo(-100, graphXOVERWidth + 100);
        ctx.lineTo(-100, yFromGainXOVER(valPEQG[0]));
        ctx.closePath();
        ctx.setLineDash([]);
        ctx.fillStyle = "rgba(255, 255, 255,.1)";
        ctx.fill("nonzero");
        ctx.setLineDash([]);
        ctx.stroke();

        ctx.moveTo(-100, yFromPhaseXOVER(0));
        for (var i = 0; i < graphXOVERWidth; i++) {
            ctx.lineTo(i, yFromPhaseXOVER(valPEQP[i]));
        }
        ctx.lineTo(graphXOVERWidth + 100, yFromPhaseXOVER(valPEQP[graphXOVERWidth]));

        ctx.setLineDash([10, 5]);
        ctx.stroke();
    }
    ctx.stroke();
}

$.fn.draggieXOVERSetPosition = function(num) {
    switch (num) {
        case 0:
            highPassDrag.draggabilly('setPosition', xFromFreqXOVER(localAmplifier.channel[soloChannelSelected].xover.hpFreq) + widgetXOVERMarginLeft, yFromGainXOVER(0) + 6);
            break;
        case 1:
            lowPassDrag.draggabilly('setPosition', xFromFreqXOVER(localAmplifier.channel[soloChannelSelected].xover.lpFreq) + widgetXOVERMarginLeft, yFromGainXOVER(0) + 6);
            break;
        default:
            break;
    }
}

$.fn.initSliderXOVER = function() {
    //SLIDER HIGH PASS XOVER
    $("#sliderHorizontalHighPassXOVER").slider({
        orientation: "horizontal",
        range: "min",
        min: 1,
        max: Math.log10(freqScaleMaxPEQ),
        step: 0.00001,
        slide: function(event, ui) {
            localAmplifier.channel[soloChannelSelected].xover.hpFreq = Math.round(Math.pow(10, ui.value));
            $.fn.setDataSoloXover(0, 2);
        }
    });

    //SLIDER LOW PASS XOVER
    $("#sliderHorizontalLowPassXOVER").slider({
        orientation: "horizontal",
        range: "min",
        min: 1,
        max: Math.log10(freqScaleMaxPEQ),
        step: 0.00001,
        slide: function(event, ui) {
            localAmplifier.channel[soloChannelSelected].xover.lpFreq = Math.round(Math.pow(10, ui.value));
            $.fn.setDataSoloXover(1, 5);
        }
    });
}

//SETUP THE LIMITER SOLO AREA AT THE FIRST LOADING OF THE PAGE
$.fn.setupLimiterSolo = function() {
    //ITEM FULL FOR BACKGROUND

    $("#limiterMainPanel").addClass("mainPanelLimiter");
    $("#limiterMainPanel").append($("<div>").prop({ id: "containerLimiter", className: "containerSoloLimiter container" }));

    //REAL TIME GRAPHIC AREA LIMITER
    $("#containerLimiter").append($("<div>").prop({ id: "outputPanelBackgroundLimiter", className: "outputPanelBackgroundLimiter" }));
    //FIRST LABEL TITLE "G-R dB"
    $("#outputPanelBackgroundLimiter").append($("<span>").prop({ id: "label1OutputLimiter", className: "label1OutLimiter" }));
    var label1 = "RMS Lim.";
    $("#label1OutputLimiter").html(label1);

    //SECOND LABEL TITLE "Peak dB"
    $("#outputPanelBackgroundLimiter").append($("<span>").prop({ id: "label2OutputLimiter", className: "label2OutLimiter" }));
    var label2 = "Peak Lim.";
    $("#label2OutputLimiter").html(label2);

    //THIRD LABEL TITLE "OUTPUT dBfs"
    $("#outputPanelBackgroundLimiter").append($("<span>").prop({ id: "label3OutputLimiter", className: "label3OutLimiter" }));
    var label3 = "Output dBfs";
    $("#label3OutputLimiter").html(label3);

    //VU METER G-R
    $("#outputPanelBackgroundLimiter").append($("<canvas>").prop({ id: "canvasVuMeterGRBGLimiter", className: "vuMeterRGCanvasLimiter", width: "40px", height: "100px" }));
    $("#outputPanelBackgroundLimiter").append($("<div>").prop({ id: "vuMeterGRBGLimiter", className: "vuMeterRGDivLimiter" }));
    $("#vuMeterGRBGLimiter").append($("<div>").prop({ id: "vuMeterGRBGLimiterCh", className: "limiterGRSoloVuMeter" }));

    //VU METER PEAK
    $("#outputPanelBackgroundLimiter").append($("<canvas>").prop({ id: "canvasVuMeterPeakBGLimiter", className: "vuMeterPeakCanvasLimiter", width: "40px", height: "100px" }));
    $("#outputPanelBackgroundLimiter").append($("<div>").prop({ id: "vuMeterPeakBGLimiter", className: "vuMeterPeakDivLimiter" }));
    $("#vuMeterPeakBGLimiter").append($("<div>").prop({ id: "vuMeterPeakBGLimiterCh", className: "limiterPeakSoloVuMeter" }));

    //VU METER LIMITER
    $("#outputPanelBackgroundLimiter").append($("<canvas>").prop({ id: "canvasVuMeterOutputBGLimiter", className: "vuMeterOutputCanvasLimiter", width: "40px", height: "100px" }));
    $("#outputPanelBackgroundLimiter").append($("<div>").prop({ id: "vuMeterOutputBGLimiter", className: "vuMeterOutputDivLimiter" }));
    $("#vuMeterOutputBGLimiter").append($("<div>").prop({ id: "vuMeterOutputBGLimiterCh", className: "limiterSoloVuMeter" }));


    //PARAMETERS AREA WITH A DIV FOR RMS STAGE
    $("#containerLimiter").append($("<div>").prop({ id: "rmsStageBackgroundLimiter", className: "rmsStageBackgroundLimiter" }));
    $("#rmsStageBackgroundLimiter").append($("<span>").prop({ id: "rmsStageLabelLimiter", className: "stageLabelBackgroundLimiter" }));
    $("#rmsStageBackgroundLimiter").append($("<button>").prop({ id: "rmsCalculator", className: "limiterCalc" }));
    $("#rmsCalculator").append($("<img>").prop({ id: "rmsCalcImg", src: "./img/Calculator.png", className: "limiterCalcIcon" }));

    var rmsStageTitle = "RMS stage";
    $("#rmsStageLabelLimiter").html(rmsStageTitle);

    var str = "";
    str += "<div class=\"row rowStageLimiter\">";
    str += "<div class=\"col-lg-4 col-md-12 bgLimiterParameterAreaSolo\">";
    str += "<h6 class=\"col-12\">Output (Vrms)</h6>";
    str += "<div class=\"row\" style=\"height: 12px;\">";
    str += "</div>";
    str += "<div class=\"row\">";
    str += "<div class=\"col-sm\"><button type=\"button\" class=\"btn btn-outline-dark btn-sm mb-2 thresRmsSoloLimiterBtnDown\">&nbsp-&nbsp</button></div>";
    str += "<div class=\"col-sm\"><input id=\"thresRmsSoloLimiterInput\" type=\"number\" step=\"1\" class=\"inputFieldLimiter form-control form-control-sm\"></div>";
    str += "<div class=\"col-sm\"><button type=\"button\" class=\"btn btn-outline-dark btn-sm mb-2 thresRmsSoloLimiterBtnUp\">&nbsp+&nbsp</button></div>";
    str += "</div>";
    str += "<div class=\"row nowrap\" style=\"height: 32px;\">";
    str += "<div class=\"col col-lg-1\"></div>";
    str += "<div id=\"thresRmsSoloLimiterSlider\" class=\"col-10 col-sm-10 col-md-10 col-lg-10 sliderHorizontalLimiter\"></div>";
    str += "<div class=\"col col-lg-1\"></div>";
    str += "</div>";
    str += "</div>";

    str += "<div class=\"col-lg-4 col-md-12 bgLimiterParameterAreaSolo\">";
    str += "<h6 class=\"col-12\">Attack (ms)</h6>";
    str += "<div class=\"row\" style=\"height: 12px;\">";
    str += "</div>";
    str += "<div class=\"row\">";
    str += "<div class=\"col-sm\"><button type=\"button\" class=\"btn btn-outline-dark btn-sm mb-2 attackRmsSoloLimiterBtnDown\">&nbsp-&nbsp</button></div>";
    str += "<div class=\"col-sm\"><input id=\"attackRmsSoloLimiterInput\" type=\"number\" step=\"1\" class=\"inputFieldLimiter form-control form-control-sm\"></div>";
    str += "<div class=\"col-sm\"><button type=\"button\" class=\"btn btn-outline-dark btn-sm mb-2 attackRmsSoloLimiterBtnUp\">&nbsp+&nbsp</button></div>";
    str += "</div>";
    str += "<div class=\"row\" style=\"height: 32px;\">";
    str += "<div class=\"col col-lg-1\"></div>";
    str += "<div id=\"attackRmsSoloLimiterSlider\" class=\"sliderHorizontalLimiter col-10 col-sm-10 col-md-10 col-lg-10\"></div>";
    str += "<div class=\"col col-lg-1\"></div>";
    str += "</div>";
    str += "</div>";

    str += "<div class=\"col-lg-4 col-md-12 bgLimiterParameterAreaSolo\">";
    str += "<h6 class=\"col-12\">Release (ms)</h6>";
    str += "<div class=\"row\" style=\"height: 12px;\">";
    str += "</div>";
    str += "<div class=\"row\">";
    str += "<div class=\"col-sm\"><button type=\"button\" class=\"btn btn-outline-dark btn-sm mb-2 releaseRmsSoloLimiterBtnDown\">&nbsp-&nbsp</button></div>";
    str += "<div class=\"col-sm\"><input id=\"releaseRmsSoloLimiterInput\" type=\"number\" step=\"1\" class=\"inputFieldLimiter form-control form-control-sm\"></div>";
    str += "<div class=\"col-sm\"><button type=\"button\" class=\"btn btn-outline-dark btn-sm mb-2 releaseRmsSoloLimiterBtnUp\">&nbsp+&nbsp</button></div>";
    str += "</div>";
    str += "<div class=\"row\" style=\"height: 32px;\">";
    str += "<div class=\"col col-lg-1\"></div>";
    str += "<div id=\"releaseRmsSoloLimiterSlider\" class=\"sliderHorizontalLimiter col-10 col-sm-10 col-md-10 col-lg-10\"></div>";
    str += "<div class=\"col col-lg-1\"></div>";
    str += "</div>";
    str += "</div>";
    str += "</div>";
    str += "</div>";

    $("#rmsStageBackgroundLimiter").append(str);

    //PARAMETERS AREA WITH A DIV FOR PEAK STAGE
    $("#containerLimiter").append($("<div>").prop({ id: "peakStageBackgroundLimiter", className: "peakStageBackgroundLimiter" }));
    $("#peakStageBackgroundLimiter").append($("<span>").prop({ id: "peakStageLabelLimiter", className: "stageLabelBackgroundLimiter" }));
    $("#peakStageBackgroundLimiter").append($("<button>").prop({ id: "peakCalculator", className: "limiterCalc" }));
    $("#peakCalculator").append($("<img>").prop({ id: "rmsCalcImg", src: "./img/Calculator.png", className: "limiterCalcIcon" }));

    var peakStageTitle = "Peak stage";
    $("#peakStageLabelLimiter").html(peakStageTitle);

    var str = "";
    str += "<div class=\"row rowStageLimiter\">";
    str += "<div class=\"col-lg-4 col-md-12 bgLimiterParameterAreaSolo container\">";
    str += "<h6 class=\"col-12\">Output (Vpeak)</h6>";
    str += "<div class=\"row\" style=\"height: 12px;\">";
    str += "</div>";
    str += "<div class=\"row\">";
    str += "<div class=\"col-sm\"><button type=\"button\" class=\"btn btn-outline-dark btn-sm mb-2 thresPeakSoloLimiterBtnDown\">&nbsp-&nbsp</button></div>";
    str += "<div class=\"col-sm\"><input id=\"thresPeakSoloLimiterInput\" type=\"number\" step=\"1\" class=\"inputFieldLimiter form-control form-control-sm\"></div>";
    str += "<div class=\"col-sm\"><button type=\"button\" class=\"btn btn-outline-dark btn-sm mb-2 thresPeakSoloLimiterBtnUp\">&nbsp+&nbsp</button></div>";
    str += "</div>";
    str += "<div class=\"row\" style=\"height: 32px;\">";
    str += "<div class=\"col col-lg-1\"></div>";
    str += "<div id=\"thresPeakSoloLimiterSlider\" class=\"sliderHorizontalLimiter col-10 col-sm-10 col-md-10 col-lg-10\"></div>";
    str += "<div class=\"col col-lg-1\"></div>";
    str += "</div>";
    str += "</div>";

    str += "<div class=\"col bgLimiterParameterAreaEmptySolo\">";
    str += "</div>";

    str += "<div class=\"col-lg-4 col-md-12 bgLimiterParameterAreaSolo\">";
    str += "<h6 class=\"col-12\">Release (ms)</h6>";
    str += "<div class=\"row\" style=\"height: 12px;\">";
    str += "</div>";
    str += "<div class=\"row\">";
    str += "<div class=\"col-sm\"><button type=\"button\" class=\"btn btn-outline-dark btn-sm mb-2 releasePeakSoloLimiterBtnDown\">&nbsp-&nbsp</button></div>";
    str += "<div class=\"col-sm\"><input id=\"releasePeakSoloLimiterInput\" type=\"number\" step=\"1\" class=\"inputFieldLimiter form-control form-control-sm\"></div>";
    str += "<div class=\"col-sm\"><button type=\"button\" class=\"btn btn-outline-dark btn-sm mb-2 releasePeakSoloLimiterBtnUp\">&nbsp+&nbsp</button></div>";
    str += "</div>";
    str += "<div class=\"row\" style=\"height: 32px;\">";
    str += "<div class=\"col col-lg-1\"></div>";
    str += "<div id=\"releasePeakSoloLimiterSlider\" class=\"sliderHorizontalLimiter col-10 col-sm-10 col-md-10 col-lg-10\"></div>";
    str += "<div class=\"col col-lg-1\"></div>";
    str += "</div>";
    str += "</div>";
    str += "</div>";
    str += "</div>";

    $("#peakStageBackgroundLimiter").append(str);

    $("#thresRmsSoloLimiterInput").val(limiterRmsThresDefault);
    $("#attackRmsSoloLimiterInput").val(limiterRmsAttackDefault);
    $("#releaseRmsSoloLimiterInput").val(limiterRmsReleaseDefault);

    $("#thresPeakSoloLimiterInput").val(limiterPeakThresDefault);
    $("#releasePeakSoloLimiterInput").val(limiterPeakReleaseDefault);
}


//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
/////                                                                               //////
/////                            SET DATA SOLO UPDATE                               //////
/////                                                                               //////
/////                                                                               //////
/////                                                                               //////
/////                                                                               //////
/////                                                                               //////
/////                                                                               //////
/////                                                                               //////
/////                                                                               //////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////

//SETUP COPY SPEAKER PARAMETERS
$.fn.setupCopySpeakerParam = function(type) {

    //COPY CHANNEL SPEAKER CONTENT
    $("#copyChannelSourceContent").html("");

    $(".copyTabContent").show();
    $("#copyChannelSourceContent").append($("<table>").prop({ id: "CopyChannelSourceTable", className: "peqCopySource" }))

    if (type == 7 || type == 8) {
        for (var i = 0; i < 4; i++) {
            $("#CopyChannelSourceTable").append($("<tr>").prop({ id: "CopyChannelSourceTableRow" + i }));
            for (var j = 0; j < 4; j++) {
                var str = "";
                str += "<label for=\"inlineSourceRadio" + ((i * 4) + j) + "\" class=\"form-check-label peqCopyLabel\">&nbsp; Ch " + labelOverviewChannel[((i * 4) + j)] + " &nbsp</label>";
                str += "<input id=\"inlineSourceRadio" + ((i * 4) + j) + "\" class=\"copyChannelSourceRadio\" type=\"radio\" name=\"copyChannelOptions\">"
                $("#CopyChannelSourceTableRow" + i).append($("<td>").prop({ innerHTML: str }));
            }
        }
    } else if (type < 5) {
        $("#CopyChannelSourceTable").append($("<tr>").prop({ id: "CopyChannelSourceTableRow0" }));
        for (var j = 0; j < 4; j++) {
            var str = "";
            str += "<label for=\"inlineSourceRadio" + j + "\" class=\"form-check-label peqCopyLabel\">&nbsp; Ch " + labelOverviewChannel[j] + " &nbsp</label>";
            str += "<input id=\"inlineSourceRadio" + j + "\" class=\"copyChannelSourceRadio\" type=\"radio\" name=\"copyChannelOptions\">"
            $("#CopyChannelSourceTableRow0").append($("<td>").prop({ innerHTML: str }));
        }
    }

    //COPY CHANNEL CONTENT
    $("#copyChannelCopyContent").html("");

    $("#copyChannelCopyContent").append($("<div>").prop({ id: "copyChannelContentStacked1", className: "form-check" }))
    $("#copyChannelContentStacked1").append($("<input>").prop({ id: "copyChannelContentGainCB", className: "form-check-input", type: "checkbox", value: "" }))
    $("#copyChannelContentStacked1").append($("<label>").prop({ className: "form-check-label", for: "copyChannelContentGainCB", innerHTML: "Gain" }))

    $("#copyChannelCopyContent").append($("<div>").prop({ id: "copyChannelContentStacked2", className: "form-check" }))
    $("#copyChannelContentStacked2").append($("<input>").prop({ id: "copyChannelContentDelayCB", className: "form-check-input", type: "checkbox", value: "" }))
    $("#copyChannelContentStacked2").append($("<label>").prop({ className: "form-check-label", for: "copyChannelContentDelayCB", innerHTML: "Delay" }))

    $("#copyChannelCopyContent").append($("<div>").prop({ id: "copyChannelContentStacked3", className: "form-check" }))
    $("#copyChannelContentStacked3").append($("<input>").prop({ id: "copyChannelContentPEQCB", className: "form-check-input", type: "checkbox", value: "" }))
    $("#copyChannelContentStacked3").append($("<label>").prop({ className: "form-check-label", for: "copyChannelContentPEQCB", innerHTML: "PEQ" }))

    $("#copyChannelCopyContent").append($("<div>").prop({ id: "copyChannelContentStacked4", className: "form-check" }))
    $("#copyChannelContentStacked4").append($("<input>").prop({ id: "copyChannelContentXOVERCB", className: "form-check-input", type: "checkbox", value: "" }))
    $("#copyChannelContentStacked4").append($("<label>").prop({ className: "form-check-label", for: "copyChannelContentXOVERCB", innerHTML: "XOVER" }))

    $("#copyChannelCopyContent").append($("<div>").prop({ id: "copyChannelContentStacked5", className: "form-check" }))
    $("#copyChannelContentStacked5").append($("<input>").prop({ id: "copyChannelContentFIRCB", className: "form-check-input", type: "checkbox", value: "" }))
    $("#copyChannelContentStacked5").append($("<label>").prop({ className: "form-check-label", for: "copyChannelContentFIRCB", innerHTML: "FIR" }))

    $("#copyChannelCopyContent").append($("<div>").prop({ id: "copyChannelContentStacked6", className: "form-check" }))
    $("#copyChannelContentStacked6").append($("<input>").prop({ id: "copyChannelContentLimiterCB", className: "form-check-input", type: "checkbox", value: "" }))
    $("#copyChannelContentStacked6").append($("<label>").prop({ className: "form-check-label", for: "copyChannelContentLimiterCB", innerHTML: "Limiter" }))

    //COPY DESTINATION

    $("#copyChannelDestContent").html("");

    $("#copyChannelDestContent").append($("<table>").prop({ id: "copyChannelDestTable", className: "peqCopySource" }))

    if (type == 7 || type == 8) {
        for (var i = 0; i < 4; i++) {
            $("#copyChannelDestTable").append($("<tr>").prop({ id: "copyChannelDestDestRow" + i }));
            for (var j = 0; j < 4; j++) {
                $("#copyChannelDestDestRow" + i).append($("<td>").prop({ type: "checkbox", innerHTML: "&nbsp Ch " + labelOverviewChannel[((i * 4) + j)] + " &nbsp<input id=\"copyChannelDest" + ((i * 4) + j) + "\" type=\"checkbox\" class=\"copyChannelDest\"/>" }));
            }
        }
    } else if (type < 5) {
        $("#copyChannelDestTable").append($("<tr>").prop({ id: "copyChannelDestRow0" }));
        for (var j = 0; j < 4; j++) {
            $("#copyChannelDestRow0").append($("<td>").prop({ type: "checkbox", innerHTML: "&nbsp Ch " + labelOverviewChannel[j] + " &nbsp<input id=\"copyChannelDest" + j + "\" type=\"checkbox\" class=\"copyChannelDest\"/>" }));
        }
    }
    $("#copyChannelApply").html("");
    $("#copyChannelApply").append($("<button>").prop({ id: "copyChannelContentApply", className: "eqCopyApplyButton", innerHTML: "APPLY" }));
}



//GAIN SETUP
$.fn.setDataSoloGain = function(arg, src) {
    if (arg < 99) {
        $.fn.setDataSoloGainUpdate(arg);
        switch (src) {
            case 0:
                $.fn.sendCommandWS(cmd_set_speaker_mute, 0, Number(arg), "null", localAmplifier.channel[Number(arg)].gain.muteEna);
                break;
            case 1:
                $.fn.sendCommandWS(cmd_set_speaker_gain, 0, Number(arg), "null", localAmplifier.channel[Number(arg)].gain.gain);
                if (localAmplifier.channel[Number(arg)].gain.gain != clearGainValue)
                    $("#overviewStatusGainActive").addClass("enable");
                else
                    $("#overviewStatusGainActive").removeClass("enable");
                break;
            case 2:
                $.fn.sendCommandWS(cmd_set_speaker_polarity, 0, Number(arg), "null", localAmplifier.channel[Number(arg)].gain.polarityEna);
                if (localAmplifier.channel[Number(arg)].gain.polarityEna != clearPolarityEnaValue)
                    $("#overviewStatusGainActive").addClass("enable");
                else
                    $("#overviewStatusGainActive").removeClass("enable");
                break;
            case 3:
                var arrayCmd = new Array();
                arrayCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_gain, 0, Number(arg), "null", localAmplifier.channel[Number(arg)].gain.gain));
                arrayCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_polarity, 0, Number(arg), "null", localAmplifier.channel[Number(arg)].gain.polarityEna));
                $.fn.sendCommandsWS(arrayCmd);
            default:
                break;
        }
    } else if (arg === 99) {
        // $.fn.setDataSoloGainUpdate(arg);
    }
}

$.fn.setDataSoloGainUpdate = function(arg) {
    $.fn.clearDataCheck();
    let g1 = "#gain0";
    let g2 = "#sliderVertical0";
    let g3 = "#overviewButtonMute" + arg;
    let g4 = "#buttonPhase0";
    //GAIN VALUE TEXTFIELD
    $(g1).val(localAmplifier.channel[soloChannelSelected].gain.gain.toFixed(1));
    //SLIDER GAIN VALUE
    $(g2).slider("value", localAmplifier.channel[soloChannelSelected].gain.gain);
    //MUTE BUTTON STATUS
    if (localAmplifier.channel[arg].gain.muteEna === true)
        $(g3).addClass("active");
    else
        $(g3).removeClass("active");
    //POLARITY BUTTON STATUS
    if (localAmplifier.channel[soloChannelSelected].gain.polarityEna === true)
        $(g4).addClass("active");
    else
        $(g4).removeClass("active");

    if (localAmplifier.channel[soloChannelSelected].gain.gain != clearGainValue || localAmplifier.channel[soloChannelSelected].gain.polarityEna != clearPolarityEnaValue)
        $("#overviewStatusGainActive").addClass("enable");
    else
        $("#overviewStatusGainActive").removeClass("enable");
}

//DELAY SETUP
$.fn.setDataSoloDelay = function(arg, src) {
    if (arg < 99) {
        $.fn.setDataSoloDelayUpdate();
        switch (src) {
            //SET DELAY ENABLE VALUE
            case 0:
                $.fn.sendCommandWS(cmd_set_speaker_delay_enable, 0, Number(arg), "null", Boolean(localAmplifier.channel[Number(arg)].delay.delayEna));
                if (localAmplifier.channel[Number(arg)].delay.delayEna != clearDelayEnaValue)
                    $("#overviewStatusDelayActive").addClass("enable");
                else
                    $("#overviewStatusDelayActive").removeClass("enable");
                break;
                //SET DELAY VALUE
            case 1:
                $.fn.sendCommandWS(cmd_set_speaker_delay_value, 0, Number(arg), "null", localAmplifier.channel[Number(arg)].delay.delay);
                if (localAmplifier.channel[Number(arg)].delay.delay != clearDelayValue && localAmplifier.channel[Number(arg)].delay.delayEna != clearDelayEnaValue)
                    $("#overviewStatusDelayActive").addClass("enable");
                else
                    $("#overviewStatusDelayActive").removeClass("enable");
                break;
                //CLEAR DELAY
            case 2:
                var arrayCmd = new Array();
                arrayCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_delay_enable, 0, Number(arg), "null", Boolean(localAmplifier.channel[Number(arg)].delay.delayEna)));
                arrayCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_delay_value, 0, Number(arg), "null", localAmplifier.channel[Number(arg)].delay.delay));
                $.fn.sendCommandsWS(arrayCmd);
                break;
            default:
                break;
        }
    } else if (arg === 99) {
        $.fn.setDataSoloDelayUpdate();
    }
}

$.fn.setDataSoloDelayUpdate = function() {
    $.fn.clearDataCheck();
    let d1 = "#delay0";
    let d2 = "#sliderDelayVertical0";
    let d3 = "#buttonDelay0";
    //DELAY VALUE TEXTFIELD
    $(d1).val(parseFloat(localAmplifier.channel[soloChannelSelected].delay.delay));
    //SLIDER DELAY VALUE 
    $(d2).slider("value", Math.log10(parseFloat(localAmplifier.channel[soloChannelSelected].delay.delay)));
    //DELAY BUTTON STATUS
    if (localAmplifier.channel[soloChannelSelected].delay.delayEna === true)
        $(d3).addClass("active");
    else
        $(d3).removeClass("active");

    if (localAmplifier.channel[soloChannelSelected].delay.delay > clearDelayValue && localAmplifier.channel[soloChannelSelected].delay.delayEna != clearDelayEnaValue)
        $("#overviewStatusDelayActive").addClass("enable");
    else
        $("#overviewStatusDelayActive").removeClass("enable");
}

//PEQ SETUP
$.fn.setDataSoloPEQ = function(arg, src) {
    if (arg < 99) {
        //SEND COMMAND
        switch (src) {
            case 0:
                $.fn.sendCommandWS(cmd_set_speaker_peq_enable, 0, soloChannelSelected, Number(arg), localAmplifier.channel[soloChannelSelected].peq.peq[arg].ena);
                break;
            case 1:
                $.fn.sendCommandWS(cmd_set_speaker_peq_type, 0, soloChannelSelected, Number(arg), localAmplifier.channel[soloChannelSelected].peq.peq[arg].type);
                break;
            case 2:
                $.fn.sendCommandWS(cmd_set_speaker_peq_freq, 0, soloChannelSelected, Number(arg), localAmplifier.channel[soloChannelSelected].peq.peq[arg].frequency);
                break;
            case 3:
                $.fn.sendCommandWS(cmd_set_speaker_peq_gain, 0, soloChannelSelected, Number(arg), localAmplifier.channel[soloChannelSelected].peq.peq[arg].gain);
                break;
            case 4:
                $.fn.sendCommandWS(cmd_set_speaker_peq_q, 0, soloChannelSelected, Number(arg), localAmplifier.channel[soloChannelSelected].peq.peq[arg].q);
                break;
            case 5:
                var arrayCmd = new Array();
                arrayCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_peq_freq, 0, soloChannelSelected, Number(arg), localAmplifier.channel[soloChannelSelected].peq.peq[arg].frequency));
                arrayCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_peq_gain, 0, soloChannelSelected, Number(arg), localAmplifier.channel[soloChannelSelected].peq.peq[arg].gain));
                $.fn.sendCommandsWS(arrayCmd);
                break;
        }

        //UPDATE THE UI
        if (src < 5)
            $.fn.setDataSoloPEQUpdate(arg);
        else
            $.fn.setDataSoloPEQUpdateWithoutDraggie(arg);

    } else if (arg === 100) {
        var arrCmd = new Array();
        for (var j = 0; j < eqCount; j++) {
            arrCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_peq_enable, 0, soloChannelSelected, j, localAmplifier.channel[soloChannelSelected].peq.peq[j].ena));
            arrCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_peq_type, 0, soloChannelSelected, j, localAmplifier.channel[soloChannelSelected].peq.peq[j].type));
            arrCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_peq_freq, 0, soloChannelSelected, j, localAmplifier.channel[soloChannelSelected].peq.peq[j].frequency));
            arrCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_peq_gain, 0, soloChannelSelected, j, localAmplifier.channel[soloChannelSelected].peq.peq[j].gain));
            arrCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_peq_q, 0, soloChannelSelected, j, localAmplifier.channel[soloChannelSelected].peq.peq[j].q));
        }
        $.fn.sendCommandsWS(arrCmd);

        for (var i = 0; i < eqCount; i++) {
            $.fn.setDataSoloPEQUpdate(i);
        }
    } else {
        for (var i = 0; i < eqCount; i++) {
            $.fn.setDataSoloPEQUpdate(i);
        }
    }
}

//SEND COPY CONTENT TO DSP
$.fn.setDataSoloPEQCopy = function(src, peq) {
    var arrCmd = new Array(0);
    for (var k = 0; k < src.length; k++) {
        for (var j = 0; j < peq.length; j++) {
            arrCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_peq_enable, 0, parseInt(src[k]), parseInt(peq[j]), localAmplifier.channel[parseInt(src[k])].peq.peq[parseInt(peq[j])].ena));
            arrCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_peq_type, 0, parseInt(src[k]), parseInt(peq[j]), localAmplifier.channel[parseInt(src[k])].peq.peq[parseInt(peq[j])].type));
            arrCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_peq_freq, 0, parseInt(src[k]), parseInt(peq[j]), localAmplifier.channel[parseInt(src[k])].peq.peq[parseInt(peq[j])].frequency));
            arrCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_peq_gain, 0, parseInt(src[k]), parseInt(peq[j]), localAmplifier.channel[parseInt(src[k])].peq.peq[parseInt(peq[j])].gain));
            arrCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_peq_q, 0, parseInt(src[k]), parseInt(peq[j]), localAmplifier.channel[parseInt(src[k])].peq.peq[parseInt(peq[j])].q));
        }
        // $.fn.setDataSoloPEQUpdate(parseInt(src[k]));
    }
    if (arrCmd.length > 0)
        $.fn.sendCommandsWS(arrCmd);
    // console.log("src peq update" + arrCmd);
}

//SET GAIN PEQ TO DSP
$.fn.setDataSoloPEQGain = function(src, peq) {
    var arrCmd = new Array(0);
    for (var k = 0; k < src.length; k++) {
        for (var j = 0; j < peq.length; j++) {
            arrCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_peq_gain, 0, parseInt(src[k]), parseInt(peq[j]), localAmplifier.channel[parseInt(src[k])].peq.peq[parseInt(peq[j])].gain));
        }
    }
    if (arrCmd.length > 0)
        $.fn.sendCommandsWS(arrCmd);
    // console.log("src peq update" + arrCmd);
}

$.fn.setDataSoloPEQUpdate = function(i) {
    $.fn.clearDataCheck();
    //PEQ ENABLE
    if (localAmplifier.channel[soloChannelSelected].peq.peq[i].ena === true) {
        $("#dragPEQ" + i).addClass("enable");
        $("#label" + i).addClass("enable");
        $("#peqAnav" + i).addClass("enable");
        $("#dragPEQ" + i).draggabilly('enable');
        $("#eqEna" + i).prop("checked", true);
        $("#enaTogglePEQ" + i).addClass("active");
    } else {
        $("#dragPEQ" + i).removeClass("enable");
        $("#label" + i).removeClass("enable");
        $("#peqAnav" + i).removeClass("enable");
        $("#dragPEQ" + i).draggabilly('disable');
        $("#eqEna" + i).prop("checked", false);
        $("#enaTogglePEQ" + i).removeClass("active");
    }
    arrayEqParam[i].ena = localAmplifier.channel[soloChannelSelected].peq.peq[i].ena;

    //PEQ FREQUENCY
    arrayEqParam[i].frequency = localAmplifier.channel[soloChannelSelected].peq.peq[i].frequency;
    var freq = "#freq_text" + i;
    $(freq).val(localAmplifier.channel[soloChannelSelected].peq.peq[i].frequency);
    freq = "#freq_textSolo" + i;
    $(freq).val(localAmplifier.channel[soloChannelSelected].peq.peq[i].frequency);
    var freq = "#sliderHorizontalFreqPEQ" + i;
    if ($(freq).slider("instance"))
        $(freq).slider("option", "value", Math.log10(localAmplifier.channel[soloChannelSelected].peq.peq[i].frequency));

    //PEQ GAIN
    arrayEqParam[i].gain = localAmplifier.channel[soloChannelSelected].peq.peq[i].gain;
    var gain = "#gain_text" + i;
    $(gain).val(localAmplifier.channel[soloChannelSelected].peq.peq[i].gain);
    gain = "#gain_textSolo" + i;
    $(gain).val(localAmplifier.channel[soloChannelSelected].peq.peq[i].gain);
    var gain = "#sliderHorizontalGainPEQ" + i;
    if ($(gain).slider("instance"))
        $(gain).slider("option", "value", localAmplifier.channel[soloChannelSelected].peq.peq[i].gain);

    //PEQ Q
    arrayEqParam[i].q = localAmplifier.channel[soloChannelSelected].peq.peq[i].q;
    var q = "#q_text" + i;
    $(q).val(localAmplifier.channel[soloChannelSelected].peq.peq[i].q);
    q = "#q_textSolo" + i;
    $(q).val(localAmplifier.channel[soloChannelSelected].peq.peq[i].q);
    var q = "#sliderHorizontalQPEQ" + i;
    if ($(q).slider("instance"))
        $(q).slider("option", "value", Math.log10(localAmplifier.channel[soloChannelSelected].peq.peq[i].q));

    //PEQ TYPE
    arrayEqParam[i].type = localAmplifier.channel[soloChannelSelected].peq.peq[i].type;
    var n = localAmplifier.channel[soloChannelSelected].peq.peq[i].type;
    var imgSrc = "./img/peq/peq" + n + ".png";
    var id = "#peqImgNav" + i;
    $(id).attr("src", imgSrc);
    id = "#peqImgSolo" + i;
    $(id).attr("src", imgSrc);
    var dest = "#eqType" + i;
    $(dest).val(n);
    if (peqViewMode != 1)
        $.fn.draggieSetPosition(i);
    $.fn.drawPEQWidget(i);

    var a = 0;
    for (var b = 0; b < peqCount; b++) {
        if (localAmplifier.channel[soloChannelSelected].peq.peq[b].ena === true && localAmplifier.channel[soloChannelSelected].peq.peq[b].gain != clearPEQGainValue)
            a++;
    }
    if (a > 0)
        $("#overviewStatusPEQActive").addClass("enable");
    else
        $("#overviewStatusPEQActive").removeClass("enable");
}

$.fn.setDataSoloPEQUpdateWithoutDraggie = function(i) {
    $.fn.clearDataCheck();
    //PEQ ENABLE
    if (localAmplifier.channel[soloChannelSelected].peq.peq[i].ena === true) {
        $("#dragPEQ" + i).addClass("enable");
        $("#label" + i).addClass("enable");
        $("#peqAnav" + i).addClass("enable");
        $("#dragPEQ" + i).draggabilly('enable');
        $("#eqEna" + i).prop("checked", true);
        $("#enaTogglePEQ" + i).addClass("active");
    } else {
        $("#dragPEQ" + i).removeClass("enable");
        $("#label" + i).removeClass("enable");
        $("#peqAnav" + i).removeClass("enable");
        $("#dragPEQ" + i).draggabilly('disable');
        $("#eqEna" + i).prop("checked", false);
        $("#enaTogglePEQ" + i).removeClass("active");
    }
    arrayEqParam[i].ena = localAmplifier.channel[soloChannelSelected].peq.peq[i].ena;

    //PEQ FREQUENCY
    arrayEqParam[i].frequency = localAmplifier.channel[soloChannelSelected].peq.peq[i].frequency;
    var freq = "#freq_text" + i;
    $(freq).val(localAmplifier.channel[soloChannelSelected].peq.peq[i].frequency);
    freq = "#freq_textSolo" + i;
    $(freq).val(localAmplifier.channel[soloChannelSelected].peq.peq[i].frequency);
    var freq = "#sliderHorizontalFreqPEQ" + i;
    $(freq).slider("option", "value", Math.log10(localAmplifier.channel[soloChannelSelected].peq.peq[i].frequency));

    //PEQ GAIN
    arrayEqParam[i].gain = localAmplifier.channel[soloChannelSelected].peq.peq[i].gain;
    var gain = "#gain_text" + i;
    $(gain).val(localAmplifier.channel[soloChannelSelected].peq.peq[i].gain);
    gain = "#gain_textSolo" + i;
    $(gain).val(localAmplifier.channel[soloChannelSelected].peq.peq[i].gain);
    var gain = "#sliderHorizontalGainPEQ" + i;
    $(gain).slider("option", "value", localAmplifier.channel[soloChannelSelected].peq.peq[i].gain);

    //PEQ Q
    arrayEqParam[i].q = localAmplifier.channel[soloChannelSelected].peq.peq[i].q;
    var q = "#q_text" + i;
    $(q).val(localAmplifier.channel[soloChannelSelected].peq.peq[i].q);
    q = "#q_textSolo" + i;
    $(q).val(localAmplifier.channel[soloChannelSelected].peq.peq[i].q);
    var q = "#sliderHorizontalQPEQ" + i;
    $(q).slider("option", "value", Math.log10(localAmplifier.channel[soloChannelSelected].peq.peq[i].q));

    //PEQ TYPE
    arrayEqParam[i].type = localAmplifier.channel[soloChannelSelected].peq.peq[i].type;
    var n = localAmplifier.channel[soloChannelSelected].peq.peq[i].type;
    var imgSrc = "./img/peq/peq" + n + ".png";
    var id = "#peqImgNav" + i;
    $(id).attr("src", imgSrc);
    id = "#peqImgSolo" + i;
    $(id).attr("src", imgSrc);

    $.fn.drawPEQWidget(i);

    var a = 0;
    for (var b = 0; b < peqCount; b++) {
        if (localAmplifier.channel[soloChannelSelected].peq.peq[b].ena === true && localAmplifier.channel[soloChannelSelected].peq.peq[b].gain != clearPEQGainValue)
            a++;
    }
    if (a > 0)
        $("#overviewStatusPEQActive").addClass("enable");
    else
        $("#overviewStatusPEQActive").removeClass("enable");
}

//XOVER SETUP
$.fn.setDataSoloXover = function(arg, src) {

    highPassEqParam.frequency = localAmplifier.channel[soloChannelSelected].xover.hpFreq;
    highPassEqParam.type = localAmplifier.channel[soloChannelSelected].xover.hpType;

    lowPassEqParam.frequency = localAmplifier.channel[soloChannelSelected].xover.lpFreq;
    lowPassEqParam.type = localAmplifier.channel[soloChannelSelected].xover.lpType;

    switch (arg) {
        //ARG = 0 -> HIGH PASS SET FROM UI
        case 0:
            $.fn.setDataSoloXoverUpdateHP();

            //XOVER SET DRAGGIE POSITION
            $.fn.draggieXOVERSetPosition(0);

            //XOVER SENT COMMAND TO AMPLIFIER
            switch (src) {
                //HP ENA SRC
                case 0:
                    $.fn.sendCommandWS(cmd_set_speaker_xover_hp_enable, 0, soloChannelSelected, "null", localAmplifier.channel[soloChannelSelected].xover.hpEna);
                    break;
                    //HP TYPE SRC
                case 1:
                    $.fn.sendCommandWS(cmd_set_speaker_xover_hp_type, 0, soloChannelSelected, "null", localAmplifier.channel[soloChannelSelected].xover.hpType);
                    break;
                    //HP FREQ SRC
                case 2:
                    $.fn.sendCommandWS(cmd_set_speaker_xover_hp_freq, 0, soloChannelSelected, "null", localAmplifier.channel[soloChannelSelected].xover.hpFreq);
                    break;
                default:
                    break;
            }
            break;
            //ARG = 1 -> LOW PASS SET FROM UI
        case 1:
            $.fn.setDataSoloXoverUpdateLP();

            //XOVER SET DRAGGIE POSITION
            $.fn.draggieXOVERSetPosition(1);

            //XOVER SENT COMMAND TO AMPLIFIER
            switch (src) {
                //LP ENA SRC
                case 3:
                    $.fn.sendCommandWS(cmd_set_speaker_xover_lp_enable, 0, soloChannelSelected, "null", localAmplifier.channel[soloChannelSelected].xover.lpEna);
                    break;
                    //LP TYPE SRC
                case 4:
                    $.fn.sendCommandWS(cmd_set_speaker_xover_lp_type, 0, soloChannelSelected, "null", localAmplifier.channel[soloChannelSelected].xover.lpType);
                    break;
                    //LP FREQ SRC
                case 5:
                    $.fn.sendCommandWS(cmd_set_speaker_xover_lp_freq, 0, soloChannelSelected, "null", localAmplifier.channel[soloChannelSelected].xover.lpFreq);
                    break;
                default:
                    break;
            }
            break;
            //ARG = 2 -> HIGH PASS GET FROM WS
        case 2:
            $.fn.setDataSoloXoverUpdateHP();

            //XOVER SET DRAGGIE POSITION
            $.fn.draggieXOVERSetPosition(0);
            break;
            //ARG = 3 -> LOW PASS GET FROM WS
        case 3:
            $.fn.setDataSoloXoverUpdateLP();

            //XOVER SET DRAGGIE POSITION
            $.fn.draggieXOVERSetPosition(1);
            break;
            //ARG = 4 -> HIGH/LOW PASS SET
        case 4:
            $.fn.setDataSoloXoverUpdateHP();
            $.fn.setDataSoloXoverUpdateLP();
            if (!$.fn.firIsEqual(localAmplifier.channel[soloChannelSelected].fir.firCoeff, clearFirTable))
                localAmplifier.channel[soloChannelSelected].fir.firEnable = true;
            $.fn.setDataSoloXoverUpdateFIR();

            //XOVER SET DRAGGIE POSITION
            $.fn.draggieXOVERSetPosition(0);

            //XOVER SET DRAGGIE POSITION
            $.fn.draggieXOVERSetPosition(1);
            break;
            //ARG = 5 -> HIGH PASS SET FROM DRAGGIE UI
        case 5:
            $.fn.setDataSoloXoverUpdateHP();
            $.fn.sendCommandWS(cmd_set_speaker_xover_hp_freq, 0, soloChannelSelected, "null", localAmplifier.channel[soloChannelSelected].xover.hpFreq);
            break;
            //ARG = 6 -> LOW PASS SET FROM DRAGGIE UI
        case 6:
            $.fn.setDataSoloXoverUpdateLP();
            $.fn.sendCommandWS(cmd_set_speaker_xover_lp_freq, 0, soloChannelSelected, "null", localAmplifier.channel[soloChannelSelected].xover.lpFreq);
            break;
            //ARG = 7 -> FIR ENABLE FROM DRAGGIE
        case 7:
            if (localAmplifier.channel[soloChannelSelected].fir.firEnable === true) {
                if (!$.fn.firIsEqual(localAmplifier.channel[soloChannelSelected].fir.firCoeffTemp, clearFirTable))
                    $.fn.sendCommandWS(cmd_set_speaker_fir_table, 0, soloChannelSelected, "null", "[" + localAmplifier.channel[soloChannelSelected].fir.firCoeffTemp + "]");
            } else {
                if (!$.fn.firIsEqual(localAmplifier.channel[soloChannelSelected].fir.firCoeff, clearFirTable))
                    $.fn.sendCommandWS(cmd_set_speaker_fir_table, 0, soloChannelSelected, "null", "[" + clearFirTable + "]");
            }
            $.fn.setDataSoloXoverUpdateFIR();
            break;
            //ARG = 8 -> CLEAR XOVER + FIR
        case 8:
            var arrayCmd = new Array();
            arrayCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_xover_hp_enable, 0, soloChannelSelected, "null", localAmplifier.channel[soloChannelSelected].xover.hpEna));
            arrayCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_xover_hp_type, 0, soloChannelSelected, "null", localAmplifier.channel[soloChannelSelected].xover.hpType));
            arrayCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_xover_hp_freq, 0, soloChannelSelected, "null", localAmplifier.channel[soloChannelSelected].xover.hpFreq));

            arrayCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_xover_lp_enable, 0, soloChannelSelected, "null", localAmplifier.channel[soloChannelSelected].xover.lpEna));
            arrayCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_xover_lp_type, 0, soloChannelSelected, "null", localAmplifier.channel[soloChannelSelected].xover.lpType));
            arrayCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_xover_lp_freq, 0, soloChannelSelected, "null", localAmplifier.channel[soloChannelSelected].xover.lpFreq));

            arrayCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_fir_table, 0, soloChannelSelected, "null", "[" + localAmplifier.channel[soloChannelSelected].fir.firCoeff + "]"));

            $.fn.sendCommandsWS(arrayCmd);

            $.fn.setDataSoloXoverUpdateHP();
            $.fn.setDataSoloXoverUpdateLP();
            $.fn.setDataSoloXoverUpdateFIR();

            break;
            //ARG = 9 -> FIR FROM WS
        case 9:
            let emptyFir = new firConstructor();
            if (!isEqual(localAmplifier.channel[src].fir.firCoeff, emptyFir.firCoeff))
                localAmplifier.channel[src].fir.firEnable = true;
            $.fn.setDataSoloXoverUpdateFIR();
            break;
            //ARG = 10 -> SET HPPRESETOVERIDE
        case 10:
            $.fn.sendCommandWS(cmd_set_speaker_xover_hp_overide, 0, soloChannelSelected, "null", localAmplifier.channel[soloChannelSelected].xover.hpSpeakerPresetOveride);
            $.fn.setDataSoloXoverUpdateHP();
            break;
            //ARG = 11 -> SET LPPRESETOVERIDE
        case 11:
            $.fn.sendCommandWS(cmd_set_speaker_xover_lp_overide, 0, soloChannelSelected, "null", localAmplifier.channel[soloChannelSelected].xover.lpSpeakerPresetOveride);
            $.fn.setDataSoloXoverUpdateLP();
            break;
        default:
            break;
    }
}

function isEqual(array1, array2) {
    if (array1.length != array2.length)
        return false;
    else {
        for (var i = 0; i < array1.length; i++) {
            if (array1[i] != array2[i])
                return false;
        }
    }
    return true;
}

$.fn.setDataSoloXoverUpdateHP = function() {
    $.fn.clearDataCheck();
    let x1 = "#enaToggleHighPassXOVER";
    let x2 = "#freq_HighPassXOVER";
    let x3 = "#sliderHorizontalHighPassXOVER";

    //XOVER HP OVERIDE ENABLE CHECKBOX
    if (localAmplifier.channel[soloChannelSelected].xover.hpSpeakerPresetOveride === true) {
        $("#enaToggleHighPassXOVEROveride").attr("checked", true);
    } else {
        $("#enaToggleHighPassXOVEROveride").attr("checked", false);
    }

    //XOVER HP ENABLE CHECKBOX
    if (localAmplifier.channel[soloChannelSelected].xover.hpEna === true) {
        $(x1).addClass("active");
        $("#dragHighPass").addClass("enable");
        $("#labelHighPass").addClass("enable");
        highPassDrag.draggabilly('enable');
        $("#enaToggleHighPassXOVEROveride").removeAttr("disabled");
    } else {
        $(x1).removeClass("active");
        $("#dragHighPass").removeClass("enable");
        $("#labelHighPass").removeClass("enable");
        highPassDrag.draggabilly('disable');
        $("#enaToggleHighPassXOVEROveride").attr("checked", false);
        $("#enaTogglehighPassXOVEROveride").attr("disabled", true);
    }

    //XOVER HP FREQUENCY TEXTFIELD
    $(x2).val(parseInt(localAmplifier.channel[soloChannelSelected].xover.hpFreq));

    //XOVER HP FREQUENCY SLIDER
    if ($(x3).slider("instance"))
        $(x3).slider("value", Math.log10(parseFloat(localAmplifier.channel[soloChannelSelected].xover.hpFreq)));

    //XOVER HP TYPE
    $("#highPassXOVERLabel").html(xoverLabel[localAmplifier.channel[soloChannelSelected].xover.hpType]);
    $.fn.drawXOVERWidget(0, localAmplifier.channel[soloChannelSelected].xover.hpType);

    if (localAmplifier.channel[soloChannelSelected].fir.firEnable || localAmplifier.channel[soloChannelSelected].xover.hpEna || localAmplifier.channel[soloChannelSelected].xover.lpEna)
        $("#overviewStatusXOVERActive").addClass("enable");
    else
        $("#overviewStatusXOVERActive").removeClass("enable");
}

$.fn.setDataSoloXoverUpdateLP = function() {
    $.fn.clearDataCheck();
    let x5 = "#enaToggleLowPassXOVER";
    let x6 = "#freq_LowPassXOVER";
    let x7 = "#sliderHorizontalLowPassXOVER";

    //XOVER LP OVERIDE ENABLE CHECKBOX
    if (localAmplifier.channel[soloChannelSelected].xover.lpSpeakerPresetOveride === true) {
        $("#enaToggleLowPassXOVEROveride").attr("checked", true);
    } else {
        $("#enaToggleLowPassXOVEROveride").attr("checked", false);
    }

    //XOVER LP ENABLE CHECKBOX
    if (localAmplifier.channel[soloChannelSelected].xover.lpEna === true) {
        $(x5).addClass("active");
        $("#dragLowPass").addClass("enable");
        $("#labelLowPass").addClass("enable");
        lowPassDrag.draggabilly('enable');
        $("#enaToggleLowPassXOVEROveride").removeAttr("disabled");
    } else {
        $(x5).removeClass("active");
        $("#dragLowPass").removeClass("enable");
        $("#labelLowPass").removeClass("enable");
        lowPassDrag.draggabilly('disable');
        $("#enaToggleLowPassXOVEROveride").attr("checked", false);
        $("#enaToggleLowPassXOVEROveride").attr("disabled", true);
    }

    //XOVER LP FREQUENCY TEXTFIELD
    $(x6).val(parseInt(localAmplifier.channel[soloChannelSelected].xover.lpFreq));

    //XOVER LP FREQUENCY SLIDER

    if ($(x7).slider("instance"))
        $(x7).slider("value", Math.log10(parseFloat(localAmplifier.channel[soloChannelSelected].xover.lpFreq)));

    //XOVER LP TYPE
    $("#lowPassXOVERLabel").html(xoverLabel[localAmplifier.channel[soloChannelSelected].xover.lpType]);
    $.fn.drawXOVERWidget(1, localAmplifier.channel[soloChannelSelected].xover.lpType);
    if (localAmplifier.channel[soloChannelSelected].fir.firEnable || localAmplifier.channel[soloChannelSelected].xover.hpEna || localAmplifier.channel[soloChannelSelected].xover.lpEna)
        $("#overviewStatusXOVERActive").addClass("enable");
    else
        $("#overviewStatusXOVERActive").removeClass("enable");
}

$.fn.setDataSoloXoverUpdateFIR = function() {
    $.fn.clearDataCheck();
    if (localAmplifier.channel[soloChannelSelected].fir.firName != "")
        $("#firLoadedName").html("Loaded file : " + localAmplifier.channel[soloChannelSelected].fir.firName);
    else
        $("#firLoadedName").html("No FIR file loaded");
    if (localAmplifier.channel[soloChannelSelected].fir.firEnable === true) {
        $("#enableToggleFirXOVER").addClass("active");
    } else {
        $("#enableToggleFirXOVER").removeClass("active");
    }
    if (localAmplifier.channel[soloChannelSelected].fir.firEnable || localAmplifier.channel[soloChannelSelected].xover.hpEna || localAmplifier.channel[soloChannelSelected].xover.lpEna)
        $("#overviewStatusXOVERActive").addClass("enable");
    else
        $("#overviewStatusXOVERActive").removeClass("enable");
}

//LIMITER SETUP
$.fn.setDataSoloLimiter = function(arg, src) {
    switch (arg) {
        //UPADTE LIMITER FROM UI
        case 0:
            $.fn.setDataSoloLimiterUpdate();
            switch (src) {
                //RMS THRESHOLD SRC
                case 0:
                    $.fn.sendCommandWS(cmd_set_speaker_lim_rms_thres, 0, soloChannelSelected, "null", getThresholdInDb(localAmplifier.channel[soloChannelSelected].limiter.rmsThres, 0));
                    break;
                    //RMS ATTACK SRC
                case 1:
                    $.fn.sendCommandWS(cmd_set_speaker_lim_rms_attack, 0, soloChannelSelected, "null", localAmplifier.channel[soloChannelSelected].limiter.rmsAttack);
                    break;
                    //RMS RELEASE SRC
                case 2:
                    $.fn.sendCommandWS(cmd_set_speaker_lim_rms_release, 0, soloChannelSelected, "null", localAmplifier.channel[soloChannelSelected].limiter.rmsRelease);
                    break;
                    //PEAK THRESHOLD SRC
                case 3:
                    $.fn.sendCommandWS(cmd_set_speaker_lim_peak_thres, 0, soloChannelSelected, "null", getThresholdInDb(localAmplifier.channel[soloChannelSelected].limiter.peakThres, 1));
                    break;
                    //PEAK RELEASE SRC
                case 4:
                    $.fn.sendCommandWS(cmd_set_speaker_lim_peak_release, 0, soloChannelSelected, "null", localAmplifier.channel[soloChannelSelected].limiter.peakRelease);
                    break;
                    //CALCULATOR RMS SRC
                case 5:
                    var arrayCmd = new Array();
                    arrayCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_lim_rms_thres, 0, soloChannelSelected, "null", getThresholdInDb(localAmplifier.channel[soloChannelSelected].limiter.rmsThres, 0)));
                    arrayCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_lim_rms_attack, 0, soloChannelSelected, "null", localAmplifier.channel[soloChannelSelected].limiter.rmsAttack));
                    arrayCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_lim_rms_release, 0, soloChannelSelected, "null", localAmplifier.channel[soloChannelSelected].limiter.rmsRelease));
                    $.fn.sendCommandsWS(arrayCmd);
                    break;
                    //CALCULATOR PEAK SRC
                case 6:
                    var arrayCmd = new Array();
                    arrayCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_lim_peak_thres, 0, soloChannelSelected, "null", getThresholdInDb(localAmplifier.channel[soloChannelSelected].limiter.peakThres, 1)));
                    arrayCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_lim_peak_release, 0, soloChannelSelected, "null", localAmplifier.channel[soloChannelSelected].limiter.peakRelease));
                    $.fn.sendCommandsWS(arrayCmd);
                    break;
                    //CLEAR LIMITER
                case 7:
                    var arrayCmd = new Array();
                    arrayCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_lim_rms_thres, 0, soloChannelSelected, "null", getThresholdInDb(localAmplifier.channel[soloChannelSelected].limiter.rmsThres, 0)));
                    arrayCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_lim_rms_attack, 0, soloChannelSelected, "null", localAmplifier.channel[soloChannelSelected].limiter.rmsAttack));
                    arrayCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_lim_rms_release, 0, soloChannelSelected, "null", localAmplifier.channel[soloChannelSelected].limiter.rmsRelease));
                    arrayCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_lim_peak_thres, 0, soloChannelSelected, "null", getThresholdInDb(localAmplifier.channel[soloChannelSelected].limiter.peakThres, 1)));
                    arrayCmd.push($.fn.getCommandFromArgs(cmd_set_speaker_lim_peak_release, 0, soloChannelSelected, "null", localAmplifier.channel[soloChannelSelected].limiter.peakRelease));
                    $.fn.sendCommandsWS(arrayCmd);
                    break;
                default:
                    break;
            }
            break;
            //UPADATE FROM WS
        case 1:
            $.fn.setDataSoloLimiterUpdate();
            break;
    }
}

function getThresholdInDb(volt, lim) {
    var ret = 0.0;
    if (lim === 0) {
        if (volt === 130)
            ret = 5.3;
        else
            ret = (20 * Math.log10(volt)) - 37;
    } else {
        if (volt === 180)
            ret = 4.1;
        else
            ret = (20 * Math.log10(volt)) - 41;
    }
    return parseFloat(ret.toFixed(1));
}

function getThresholdInVolt(db, lim) {
    var ret = 0.0;
    if (lim === 0) {
        if (db === 5.3)
            ret = 130;
        else
            ret = Math.pow(10, ((db + 37) / 20));
    } else {
        if (db === 4.1)
            ret = 180;
        else
            ret = Math.pow(10, ((db + 41) / 20));
    }
    return parseFloat(ret.toFixed(1));
}

$.fn.setDataSoloLimiterUpdate = function() {
    $.fn.clearDataCheck();
    //RMS THRESHOLD
    $("#thresRmsSoloLimiterInput").val(parseFloat(parseFloat(localAmplifier.channel[soloChannelSelected].limiter.rmsThres).toFixed(1)));
    $("#thresRmsSoloLimiterSlider").slider('value', localAmplifier.channel[soloChannelSelected].limiter.rmsThres);

    //RMS ATTACK
    $("#attackRmsSoloLimiterInput").val(parseFloat(parseFloat(localAmplifier.channel[soloChannelSelected].limiter.rmsAttack).toFixed(1)));
    $("#attackRmsSoloLimiterSlider").slider('value', Math.log10(localAmplifier.channel[soloChannelSelected].limiter.rmsAttack));

    //RMS RELEASE
    $("#releaseRmsSoloLimiterInput").val(parseFloat(parseFloat(localAmplifier.channel[soloChannelSelected].limiter.rmsRelease).toFixed(1)));
    $("#releaseRmsSoloLimiterSlider").slider('value', Math.log10(localAmplifier.channel[soloChannelSelected].limiter.rmsRelease));

    //PEAK THRESHOLD
    $("#thresPeakSoloLimiterInput").val(parseFloat(parseFloat(localAmplifier.channel[soloChannelSelected].limiter.peakThres).toFixed(1)));
    $("#thresPeakSoloLimiterSlider").slider('value', localAmplifier.channel[soloChannelSelected].limiter.peakThres);

    //PEAK RELEASE
    $("#releasePeakSoloLimiterInput").val(parseFloat(parseFloat(localAmplifier.channel[soloChannelSelected].limiter.peakRelease).toFixed(1)));
    $("#releasePeakSoloLimiterSlider").slider('value', Math.log10(localAmplifier.channel[soloChannelSelected].limiter.peakRelease));
}

//SPEAKER SETUP
$.fn.setDataSoloSpeaker = function(arg) {
    //SET SPEAKER PRESET
    if (arg < 99) {
        //SET SPEAKER PRESET
        var cmd = "\"";
        cmd += soloFolderSpeakerSelected + "\\" + soloFileSpeakerSelected;
        cmd += "\"";
        $.fn.sendCommandWS(cmd_set_speaker_preset_file, 0, localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].name + "/" + localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].fileList[soloFileSpeakerSelected].file_name, soloChannelSelected, "null");
    } else if (arg === 99) {
        //GET THE FOLDERS LIST FROM THE AMPLIFIER
        $.fn.sendCommandWS(cmd_get_speaker_preset_list_names, 0, "null", "null", "null");

    } else if (arg === 100) {
        //JUST UPDATE THE SPEAKER PRESET LIST
        $.fn.setDataSoloSpeakerUpdate();
    } else if (arg === 101) {
        var arrCmd = new Array();
        for (var i = 0; i < localAmplifier.folderSpeaker.folderCount; i++) {
            arrCmd.push($.fn.getCommandFromArgs(cmd_get_speaker_preset_file_names, 0, localAmplifier.folderSpeaker.folderList[i].name, "null", "null"));
        }
        $.fn.sendCommandsWS(arrCmd);
    }
}

$.fn.setDataSoloSpeakerUpdate = function() {
    //GENERATE FOLDER LIST
    var str = "";
    $("#fileListSpeaker").html(str);
    //HEADER OF THE ASSIGN GROUP TAB TABLE
    str += "<thead><tr><th>Speaker Folder</th></tr></thead>";
    str += "<tbody>"

    for (var i = 0; i < localAmplifier.folderSpeaker.folderCount; i++) {
        if (i === soloFolderSpeakerSelected)
            str += "<tr class=\"active\">";
        else
            str += "<tr>";
        str += "<td id=\"folderListIndex" + i + "\" colspan=\"1\">"
        str += "<label id=\"folderListTab" + i + "\">" + localAmplifier.folderSpeaker.folderList[i].name + "</label>";
        str += "</td>";
        str += "</tr>";
    }
    str += "</tbody>"

    $("#folderListSpeaker").html(str);

    //GENERATE FILE LIST
    var str = "";
    //HEADER OF THE ASSIGN GROUP TAB TABLE
    str += "<thead><tr><th>Speaker File</th></tr></thead>";
    str += "<tbody>"

    for (var i = 0; i < localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].fileCount; i++) {
        let name = "";
        if (localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].fileList[i].oem === true) {
            name = localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].fileList[i].file_name + " (OEM)";
        } else {
            name = localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].fileList[i].file_name;
        }

        if (i === soloFileSpeakerSelected)
            str += "<tr class=\"active\">";
        else
            str += "<tr>";
        str += "<td id=\"fileListIndex" + i + "\" colspan=\"1\">"
        str += "<label id=\"fileListTab" + i + "\">" + name + "</label>";
        str += "</td>";
        str += "</tr>";
    }
    str += "</tbody>"

    $("#fileListSpeaker").html(str);

    if (localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].fileList.length > 0) {
        var info = "";
        info += "Preset : " + localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].fileList[soloFileSpeakerSelected].file_name.substr(0, 25);
        info += "<br>";
        info += "Author : " + localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].fileList[soloFileSpeakerSelected].author.substr(0, 25);
        info += "<br>";
        info += "Version : " + localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].fileList[soloFileSpeakerSelected].version.substr(0, 25);
        info += "<br>";
        info += "Note : " + localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].fileList[soloFileSpeakerSelected].note.substr(0, 30);
        info += "<br>";
        if (localAmplifier.folderSpeaker.folderList[soloFolderSpeakerSelected].fileList[soloFileSpeakerSelected].oem)
            info += "OEM Protected : True";
        else
            info += "OEM Protected : False ";
        $("#presetInfoArea").html(info);
    }

}

//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
/////                                                                               //////
/////                               RESIZE FUNCTIONS                                //////
/////                                                                               //////
/////                                                                               //////
/////                                                                               //////
/////                                                                               //////
/////                                                                               //////
/////                                                                               //////
/////                                                                               //////
/////                                                                               //////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////

//FUNCTION RUN WHEN SIZE OF THE WINDOWS IS UPDATED
$(window).resize(function() {
    // console.log("resize function");
    screenHeight = window.innerHeight;
    screenWidth = window.innerWidth;
    screenScrollHeight = document.documentElement.scrollHeight;

    winHeightFader = (screenHeight || document.documentElement.clientHeight || document.body.clientHeight) - 505;
    winHeightGroupFader = (screenHeight || document.documentElement.clientHeight || document.body.clientHeight) - 400;
    winHeightVuMeter = (screenHeight || document.documentElement.clientHeight || document.body.clientHeight) - 445;

    if (screenHeight < 570) {
        winHeightFader = 84;
        winHeightGroupFader = 170;
        winHeightVuMeter = 130;
        $(".sliderContainer").css("min-height", "80px");

        $(".sliderDelayContainer").css("min-height", "90px");
        $(".sliderDelayContainer").css("max-height", "90px");
        $(".sliderDelayContainerBackground").css("min-height", "88px");

        $(".itemQuarterVuMeter").css("min-height", "145px");

        $(".gainSoloVuMeter").css("top", "144px");
        $(".gainSoloVuMeter").css("height", "144px");
        $(".limiterSoloVuMeter").css("top", "366px");
        $(".limiterGRSoloVuMeter").css("height", "365px");
        $(".limiterPeakSoloVuMeter").css("height", "365px");
        $(".limiterSoloVuMeter").css("height", "365px");

        $(".itemQuarterVuMeterBackground").css("min-height", "158px");
        $(".outputPanelBackgroundLimiter").css("min-height", "457px");
    } else {
        $(".sliderContainer").css("min-height", "-webkit-calc(100vh - 492px)");
        $(".sliderContainer").css("min-height", "-moz-calc(100vh - 492px)");
        $(".sliderContainer").css("min-height", "calc(100vh - 492px)");

        $(".sliderGroupContainer").css("min-height", "-webkit-calc(100vh - 422px)");
        $(".sliderGroupContainer").css("min-height", "-moz-calc(100vh - 422px)");
        $(".sliderGroupContainer").css("min-height", "calc(100vh - 422px)");

        $(".sliderDelayContainer").css("min-height", "-webkit-calc(100vh - 500px)");
        $(".sliderDelayContainer").css("min-height", "-moz-calc(100vh - 500px)");
        $(".sliderDelayContainer").css("min-height", "calc(100vh - 500px)");

        $(".itemQuarterVuMeter").css("min-height", "-webkit-calc(100vh - 425px)");
        $(".itemQuarterVuMeter").css("min-height", "-moz-calc(100vh - 425px)");
        $(".itemQuarterVuMeter").css("min-height", "calc(100vh - 425px)");

        $(".gainSoloVuMeter").css("top", "calc(100vh - 426px)");
        $(".gainSoloVuMeter").css("height", (screenHeight - 426) + "px");
        var topPosLimSoloVuMeter = screenScrollHeight - 393;
        topPosLimSoloVuMeter = topPosLimSoloVuMeter.toFixed(0) + "px";
        $(".limiterSoloVuMeter").css("top", topPosLimSoloVuMeter);

        var heightLimSoloVuMeter = screenScrollHeight - 392;
        $(".limiterGRSoloVuMeter").css("height", heightLimSoloVuMeter + "px");
        $(".limiterPeakSoloVuMeter").css("height", heightLimSoloVuMeter + "px");
        $(".limiterSoloVuMeter").css("height", heightLimSoloVuMeter + "px");

        $(".itemQuarterVuMeterBackground").css("min-height", "-webkit-calc(100vh - 412px)");
        $(".itemQuarterVuMeterBackground").css("min-height", "-moz-calc(100vh - 412px)");
        $(".itemQuarterVuMeterBackground").css("min-height", "calc(100vh - 412px)");
    }
    winHeightFaderLimiter = screenHeight - 380;

    var w = screenWidth - 20;

    var h = (screenHeight || document.documentElement.clientHeight || document.body.clientHeight) - 300;

    if ((screenHeight || document.documentElement.clientHeight || document.body.clientHeight) < 680) {
        widgetPEQX = w - 80;
        widgetPEQY = 180;

        widgetXOVERX = w - 80;
        widgetXOVERY = 180;
        $(".itemFullButtonView").css("top", "136px");
        $("#peqNavBar").css("margin-top", 190 + "px");
    } else {
        widgetPEQX = w - 80;
        widgetPEQY = h * 0.5;

        widgetXOVERX = w - 80;
        widgetXOVERY = h * 0.5;

        $(".itemFullButtonView").css("top", "176px");
        $("#peqNavBar").css("margin-top", widgetPEQY + 20 + "px");
    }

    $("#peqGroupNavBar").css("margin-top", widgetPEQY + 20 + "px");
    $("#parametersAreaXOVER").css("margin-top", widgetPEQY + 20 + "px");

    $.fn.resizeLimiter();

    $.fn.drawTickLabels();

    $.fn.initPEQ(peqViewMode, peqGainScaleType, peqPhaseScaleType);
    $.fn.initXOVER(peqViewMode, xoverGainScaleType, xoverPhaseScaleType);


});

function resize() {
    $.fn.resizeWindows();
}

$.fn.resizeWindows = function() {
    screenHeight = window.innerHeight;
    screenWidth = window.innerWidth;
    screenScrollHeight = document.documentElement.scrollHeight;

    winHeightFader = (screenHeight || document.documentElement.clientHeight || document.body.clientHeight) - 505;
    winHeightGroupFader = (screenHeight || document.documentElement.clientHeight || document.body.clientHeight) - 400;
    winHeightVuMeter = (screenHeight || document.documentElement.clientHeight || document.body.clientHeight) - 445;

    if (screenHeight < 570) {
        winHeightFader = 84;
        winHeightGroupFader = 170;
        winHeightVuMeter = 130;
        $(".sliderContainer").css("min-height", "80px");

        $(".sliderDelayContainer").css("min-height", "90px");
        $(".sliderDelayContainer").css("max-height", "90px");
        $(".sliderDelayContainerBackground").css("min-height", "88px");

        $(".itemQuarterVuMeter").css("min-height", "165px");

        $(".gainSoloVuMeter").css("top", "164px");
        $(".gainSoloVuMeter").css("height", "144px");
        $(".limiterSoloVuMeter").css("top", "366px");
        $(".limiterGRSoloVuMeter").css("height", "365px");
        $(".limiterPeakSoloVuMeter").css("height", "365px");
        $(".limiterSoloVuMeter").css("height", "365px");

        $(".itemQuarterVuMeterBackground").css("min-height", "138px");
        $(".outputPanelBackgroundLimiter").css("min-height", "457px");
    } else {
        $(".sliderContainer").css("min-height", "-webkit-calc(100vh - 492px)");
        $(".sliderContainer").css("min-height", "-moz-calc(100vh - 492px)");
        $(".sliderContainer").css("min-height", "calc(100vh - 492px)");

        $(".sliderDelayContainer").css("min-height", "-webkit-calc(100vh - 500px)");
        $(".sliderDelayContainer").css("min-height", "-moz-calc(100vh - 500px)");
        $(".sliderDelayContainer").css("min-height", "calc(100vh - 500px)");

        $(".itemQuarterVuMeter").css("min-height", "-webkit-calc(100vh - 425px)");
        $(".itemQuarterVuMeter").css("min-height", "-moz-calc(100vh - 425px)");
        $(".itemQuarterVuMeter").css("min-height", "calc(100vh - 425px)");

        $(".gainSoloVuMeter").css("top", "calc(100vh - 426px)");
        $(".gainSoloVuMeter").css("height", (screenHeight - 426) + "px");
        var topPosLimSoloVuMeter = screenScrollHeight - 393;
        topPosLimSoloVuMeter = topPosLimSoloVuMeter.toFixed(0) + "px";
        $(".limiterSoloVuMeter").css("top", topPosLimSoloVuMeter);

        var heightLimSoloVuMeter = screenScrollHeight - 392;
        $(".limiterGRSoloVuMeter").css("height", heightLimSoloVuMeter + "px");
        $(".limiterPeakSoloVuMeter").css("height", heightLimSoloVuMeter + "px");
        $(".limiterSoloVuMeter").css("height", heightLimSoloVuMeter + "px");

        $(".itemQuarterVuMeterBackground").css("min-height", "-webkit-calc(100vh - 412px)");
        $(".itemQuarterVuMeterBackground").css("min-height", "-moz-calc(100vh - 412px)");
        $(".itemQuarterVuMeterBackground").css("min-height", "calc(100vh - 412px)");
    }
    winHeightFaderLimiter = screenHeight - 380;

    var w = screenWidth - 20;
    var h = (screenHeight || document.documentElement.clientHeight || document.body.clientHeight) - 300;

    if ((screenHeight || document.documentElement.clientHeight || document.body.clientHeight) < 680) {
        widgetPEQX = w - 80;
        widgetPEQY = 180;

        widgetXOVERX = w - 80;
        widgetXOVERY = 180;
        $(".itemFullButtonView").css("top", "136px");
        $("#peqNavBar").css("margin-top", 190 + "px");
    } else {
        widgetPEQX = w - 80;
        widgetPEQY = h * 0.5;

        widgetXOVERX = w - 80;
        widgetXOVERY = h * 0.5;

        $(".itemFullButtonView").css("top", "176px");
        $("#peqNavBar").css("margin-top", widgetPEQY + 20 + "px");
    }

    $("#peqGroupNavBar").css("margin-top", widgetPEQY + 20 + "px");
    $("#parametersAreaXOVER").css("margin-top", widgetPEQY + 20 + "px");

    $.fn.resizeLimiter();

    $.fn.drawTickLabels();

    $.fn.initPEQ(peqViewMode, peqGainScaleType, peqPhaseScaleType);
    $.fn.initXOVER(peqViewMode, xoverGainScaleType, xoverPhaseScaleType);
}


//RESIZE LIMITER VU METER AREA DEPENDING ON THE WIDTH OF THE PAGE
$.fn.resizeLimiter = function() {
    var moduleWidth = parseFloat($("#outputPanelBackgroundLimiter").width());
    // console.log("SIZE : " + moduleWidth);

    var l = new Array(3);
    var step = 0;

    step = moduleWidth / 3;

    for (var i = 0; i < 3; i++) {
        if (moduleWidth > 170)
            l[i] = i * step + 10;
        else
            l[i] = i * step + 4;
        $("#label" + (i + 1) + "OutputLimiter").css("left", l[i] + "px");
    }

    $("#canvasVuMeterGRBGLimiter").css("left", (l[0] - 4) + "px");
    $("#vuMeterGRBGLimiter").css("left", l[0] + "px");

    $("#canvasVuMeterPeakBGLimiter").css("left", (l[1] - 4) + "px");
    $("#vuMeterPeakBGLimiter").css("left", l[1] + "px");

    $("#canvasVuMeterOutputBGLimiter").css("left", (l[2] - 5) + "px");
    $("#vuMeterOutputBGLimiter").css("left", l[2] + "px");

    var c, ctx;
    c = document.getElementById("canvasVuMeterGRBGLimiter");
    if (c) {
        ctx = c.getContext("2d");
        $.fn.drawTickLimiter(ctx);
    }
    c = document.getElementById("canvasVuMeterPeakBGLimiter");
    if (c) {
        ctx = c.getContext("2d");
        $.fn.drawTickLimiter(ctx);
    }
    c = document.getElementById("canvasVuMeterOutputBGLimiter");
    if (c) {
        ctx = c.getContext("2d");
        $.fn.drawTickLimiter(ctx);
    }
}

//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
/////                                                                               //////
/////                         IMPORT FROM APEX_V0_ADD.JS                            //////
/////                                                                               //////
/////                                                                               //////
/////                                                                               //////
/////                                                                               //////
/////                                                                               //////
/////                                                                               //////
/////                                                                               //////
/////                                                                               //////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////


function localAmplifierConstructor() {
    this.channel = new Array(channelCount);
    for (var i = 0; i < channelCount; i++) {
        this.channel[i] = new channelConstructor();
    }
    this.local = 0;
    this.folderSpeaker = new foldersConstructor(defaultFolderCount);
    this.desc = "";
}

//CONSTRUCTOR OF FOLDERS
function foldersConstructor(count) {
    this.folderList = new Array(count);
    this.folderCount = count;
    for (var i = 0; i < count; i++) {
        this.folderList[i] = new folderConstructor(i, defaultFileCount);
    }
}

function folderConstructor(arg, count) {
    this.name = "" + defaultFolderName + arg;
    this.fileCount = count;
    this.fileList = new Array(count);
    for (var i = 0; i < count; i++) {
        this.fileList[i] = new fileConstructor(i);
    }
}

function fileConstructor(arg) {
    this.file_name = "";
    this.author = "";
    this.version = "";
    this.note = "";
    this.oem = false;
}

// CONSTRUCTOR OF CHANNEL
function channelConstructor() {
    this.gain = new gainConstructor();
    this.delay = new delayConstructor();
    this.peq = new peqConstructor(eqCount);
    this.xover = new xoverConstructor();
    this.limiter = new limiterConstructor();
    this.fir = new firConstructor();
}

//CONSTRUCTOR OF GAIN
function gainConstructor() {
    this.gain = 0.0;
    this.muteEna = false;
    this.polarityEna = false;
}

//CONSTRUCTOR OF DELAY
function delayConstructor() {
    this.delay = 0.0;
    this.delayEna = false;
}

//CONSTRUCTOR OF PEQS 
function peqConstructor(peqCount) {
    this.peq = new Array(peqCount);
    for (var i = 0; i < peqCount; i++) {
        this.peq[i] = new EqParam(eqEnaDefault, eqFreqDefaultInit[i], eqGainDefault, eqQDefault, eqTypeDefault, new AParam(), new BParam(), eqXLockDefault, eqYLockDefault);
    }
}

//CONSTRUCTOR OF XOVER
function xoverConstructor() {
    this.hpEna = false;
    this.lpEna = false;
    this.lpFreq = lowPassDefaultFrequency;
    this.lpType = lowPassDefaultType;
    this.hpFreq = highPassDefaultFrequency;
    this.hpType = highPassDefaultType;
    this.a = new AParam();
    this.b = new BParam()
    this.hpSpeakerPresetOveride = false;
    this.lpSpeakerPresetOveride = false;
}

//CONSTRUCTOR OF LIMITER
function limiterConstructor() {
    this.rmsThres = limiterRmsThresDefault;
    this.rmsAttack = limiterRmsAttackDefault;
    this.rmsRelease = limiterRmsReleaseDefault;

    this.peakThres = limiterPeakThresDefault;
    this.peakRelease = limiterPeakReleaseDefault;
}

//CONSTRUCTOR OF FIR
function firConstructor() {
    this.firCoeff = new Array(firSize);
    //INIT DEFAULT VALUE
    for (var i = 0; i < firSize - 1; i++) {
        this.firCoeff[i] = 0;
    }
    this.firCoeff[firSize - 1] = 1;
    this.firCoeffTemp = this.firCoeff;
    this.firEnable = false;
    this.firName = "";
    this.firNameTemp = "";
}

var counts = [0, 0, 0];
var eqCount = 12; //MAX EQ PER CANAL
var eqEnaDefault = false;
var eqFreqDefault = 1000.0;
var eqFreqDefaultInit = [50, 100, 200, 300, 400, 500, 1000, 2000, 3000, 4000, 5000, 10000];
var eqGainDefault = 0.0;
var eqQDefault = 2.5;
var eqBwDefault = 0.573;

var eqTypeDefault = 0;
var eqXLockDefault = false;
var eqYLockDefault = false;

var freq_scale = [10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000];
var freq_scale_text = ["10", "20", "50", "100", "200", "500", "1k", "2k", "5k", "10k", "20k"];
var freq_scale_line = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000, 20000];

// XOVER
var xoverCount = 2; //draggable stuff

var gain_scaleXOVER = new Array(4);
gain_scaleXOVER[0] = [12, 9, 6, 3, 0, -3, -6, -9, -12];
gain_scaleXOVER[1] = [24, 18, 12, 6, 0, -6, -12, -18, -24];
gain_scaleXOVER[2] = [48, 36, 24, 12, 0, -12, -24, -36, -48];
gain_scaleXOVER[3] = [120, 90, 60, 30, 0, -30, -60, -90, -120];
var gain_scaleXOVER_line = new Array(4);
gain_scaleXOVER_line[0] = [12, 9, 6, 3, 0, -3, -6, -9, -12];
gain_scaleXOVER_line[1] = [24, 18, 12, 6, 0, -6, -12, -18, -24];
gain_scaleXOVER_line[2] = [48, 36, 24, 12, 0, -12, -24, -36, -48];
gain_scaleXOVER_line[3] = [120, 90, 60, 30, 0, -30, -60, -90, -120];

var widgetXOVERX = 1200;
var widgetXOVERY = 800;
var widgetXOVERMarginLeft = 35;
var widgetXOVERMarginRight = 10;
var widgetXOVERMarginRightDual = 35;
var widgetXOVERMarginTop = 15;
var widgetXOVERMarginBottom = 25;
var graphXOVERHeight = 0;
var graphXOVERWidth = 0;
var widgetXOVERMainXLock = false;
var widgetXOVERMainYLock = false;
var widgetXOVERMainQLock = false;
var yZeroXOVER = 0;
var defaultMaxViewFreqPEQXOVER = 24000;
var defaultMaxViewFreqPEQ = 24000;
var scale = (Math.log10(defaultMaxViewFreqPEQ) - 1);

var highPassDefaultFrequency = 50;
var lowPassDefaultFrequency = 1000;
var highPassDefaultType = 3;
var lowPassDefaultType = 5;

var xoverTabMagX = new Array();
var xoverTabPhaX = new Array();

var xoverViewMode = 0;
var xoverGainScaleType = 0;
var xoverPhaseScaleType = 0;

var xoverTabMagX = new Array(eqCount);
var xtabPhaX = new Array(eqCount);


var highPassEqParam;
var lowPassEqParam;


var eqParamDraggable = new Object();

var highPassDraggable = new Array();
var lowPassDraggable = new Array();

var highPassDrag;
var lowPassDrag;

var highPassDraggie;
var lowPassDraggie;

//19 XOVER AVAILABLE
var xoverLabel = ["Butterworth 6dB/oct",
    "Butterworth 12dB/oct",
    "Butterworth 18dB/oct",
    "Butterworth 24dB/oct",
    "Butterworth 30dB/oct",
    "Butterworth 36dB/oct",
    "Butterworth 42dB/oct",
    "Butterworth 48dB/oct",
    "Linkwitz-Riley 12dB/oct",
    "Linkwitz-Riley 24dB/oct",
    "Linkwitz-Riley 36dB/oct",
    "Linkwitz-Riley 48dB/oct",
    "Bessel 12dB/oct",
    "Bessel 18dB/oct",
    "Bessel 24dB/oct",
    "Bessel 30dB/oct",
    "Bessel 36dB/oct",
    "Bessel 42dB/oct",
    "Bessel 48dB/oct",
]

//LIMITER
var limiterRmsThresDefault = 15.0;
var limiterRmsAttackDefault = 20.0;
var limiterRmsReleaseDefault = 320.0;

var limiterPeakThresDefault = 15.0;
var limiterPeakReleaseDefault = 320.0;

//SPEAKER PRESET

var defaultFolderCount = 1;
var defaultFileCount = 0;

var defaultFolderName = "defaultFolder";
var defaultFileName = "defaultFile";
var defaultVersionName = "1.0";
var defaultDesc = "Pass through";

var protectedFolderName = "Factory Folder";
var protectedPresetName = "Blank Preset";

//MAIN

// var channelCount = 4;
var peqCount = 12;
var bessel_coeff = [
    // order: 1
    [
        [-1, 0],
        [0, 0],
        [0, 0],
        [0, 0]
    ],

    // order: 2
    [
        [-1.101601327446325, 0.636009822940780],
        [0, 0],
        [0, 0],
        [0, 0]
    ],

    // order: 3
    [
        [-1.047409162950341, 0.999264438132800],
        [-1.322675802362066, 0],
        [0, 0],
        [0, 0]
    ],

    // order: 4
    [
        [-0.995208762612890, 1.257105737260073],
        [-1.370067828159648, 0.410249716777560],
        [0, 0],
        [0, 0]
    ],

    // order: 5
    [
        [-1.380877331649290, 0.717909590636350],
        [-0.957676552577410, 1.471124326897576],
        [-1.502316277745423, 0],
        [0, 0]
    ],

    // order: 6
    [
        [-1.571490416613821, 0.320896376876750],
        [-1.381858109025903, 0.971471898746610],
        [-0.930656530644320, 1.661863282687855],
        [0, 0]
    ],

    // order: 7
    [
        [-1.612038751019419, 0.589244501373040],
        [-1.378903203788025, 1.191566766560359],
        [-0.909867772040510, 1.836451335712793],
        [-1.684368163384248, 0]
    ],

    // order: 8
    [
        [-1.757408390223183, 0.272867573521960],
        [-1.636939408646247, 0.822795620374250],
        [-1.373841209680391, 1.388356567836560],
        [-0.892869713675890, 1.998325832067540]
    ]
];

$.fn.gainToPxl = function(gain) {
    return ((30 / 95) * parseInt(gain) + (80 / 95) * 30).toFixed(0);
};

//RETURN X VALUE FROM FREQUENCY IN PEQ
function xFromFreq(frequency) {
    var x = 0;
    x = (Math.log10(frequency) - 1) * graphPEQWidth / scale;
    // displayValues("FREQ", frequency, "X", x);
    return x;
}

//RETURN FREQ VALUE FROM X IN PEQgraphPEQWidth
function freqFromX(x) {
    var f = 0;
    f = Math.pow(10, ((x * (scale / graphPEQWidth)) + 1));
    return f;
}

//RETURN Y VALUE FROM GAIN IN PEQ
function yFromGain(gain) {
    var y = 0;
    var gapGain = Math.max(...gain_scalePEQ[peqGainScaleType]) - Math.min(...gain_scalePEQ[peqGainScaleType]);
    y = -(graphPEQHeight / gapGain) * gain + graphPEQHeight * (Math.max(...gain_scalePEQ[peqGainScaleType]) / gapGain);
    return Math.round(y);
}

//RETURN Y VALUE FROM PHASE IN PEQ
function yFromPhase(phase) {
    var y = 0;
    if (peqViewMode == 2 && peqPhaseScaleType == 0)
        var gapPhase = Math.max(...phase_scale[peqPhaseScaleType]) - Math.min(...phase_scale[peqPhaseScaleType]) + 180;
    else if (peqViewMode == 2 && peqPhaseScaleType == 1)
        var gapPhase = Math.max(...phase_scale[peqPhaseScaleType]) - Math.min(...phase_scale[peqPhaseScaleType]) + 720;
    else
        var gapPhase = Math.max(...phase_scale[peqPhaseScaleType]) - Math.min(...phase_scale[peqPhaseScaleType]);

    if (peqGainScaleType != 2) {
        var gapPhase = Math.max(...phase_scale[peqPhaseScaleType]) - Math.min(...phase_scale[peqPhaseScaleType]);
    }
    // var gapPhase = Math.max(...phase_scale[peqPhaseScaleType]) - Math.min(...phase_scale[peqPhaseScaleType]);
    y = -(graphPEQHeight / gapPhase) * phase + graphPEQHeight * (Math.max(...phase_scale[peqPhaseScaleType]) / gapPhase);
    return Math.round(y);
}

//RETURN GAIN VALUE FROM Y IN PEQ
function gainFromY(y) {
    var gain = 0;
    var gapGain = Math.max(...gain_scalePEQ[peqGainScaleType]) - Math.min(...gain_scalePEQ[peqGainScaleType]);
    gain = (y - graphPEQHeight * (Math.max(...gain_scalePEQ[peqGainScaleType]) / gapGain)) * -(gapGain / graphPEQHeight);
    return Math.round(gain * 100) / 100;
}

//RETURN PHASE VALUE FROM Y IN PEQ
function phaseFromY(y) {
    var gain = 0;
    if (peqViewMode == 2 && peqPhaseScaleType == 0)
        var gapPhase = Math.max(...phase_scale[peqPhaseScaleType]) - Math.min(...phase_scale[peqPhaseScaleType]) + 180;
    else if (peqViewMode == 2 && peqPhaseScaleType == 1)
        var gapPhase = Math.max(...phase_scale[peqPhaseScaleType]) - Math.min(...phase_scale[peqPhaseScaleType]) + 720;
    else
        var gapPhase = Math.max(...phase_scale[peqPhaseScaleType]) - Math.min(...phase_scale[peqPhaseScaleType]);
    if (peqGainScaleType != 2) {
        var gapPhase = Math.max(...phase_scale[peqPhaseScaleType]) - Math.min(...phase_scale[peqPhaseScaleType]);
    }
    gain = (y - graphPEQHeight * (Math.max(...phase_scale[peqPhaseScaleType]) / gapPhase)) * -(gapPhase / graphPEQHeight);
    return Math.round(gain * 100) / 100;
}

// XOVER COORDINATE
//RETURN X VALUE FROM FREQUENCY IN XOVER
function xFromFreqXOVER(frequency) {
    var x = 0;
    x = (Math.log10(frequency) - 1) * graphXOVERWidth / scale;
    // displayValues("FREQ", frequency, "X", x);
    return x;
}

//RETURN FREQ VALUE FROM X IN graphXOVERWidth
function freqFromXXOVER(x) {
    var f = 0;
    f = Math.pow(10, ((x * (scale / graphXOVERWidth)) + 1));
    return f;
}

//RETURN Y VALUE FROM GAIN IN XOVER
function yFromGainXOVER(gain) {
    var y = 0;
    var gapGain = Math.max(...gain_scaleXOVER[xoverGainScaleType]) - Math.min(...gain_scaleXOVER[xoverGainScaleType]);
    y = -(graphXOVERHeight / gapGain) * gain + graphXOVERHeight * (Math.max(...gain_scaleXOVER[xoverGainScaleType]) / gapGain);
    return Math.round(y);
}

//RETURN Y VALUE FROM PHASE IN XOVER
function yFromPhaseXOVER(phase) {
    var y = 0;
    var gapPhase = Math.max(...phase_scale[xoverPhaseScaleType]) - Math.min(...phase_scale[xoverPhaseScaleType]);
    y = -(graphXOVERHeight / gapPhase) * phase + graphXOVERHeight * (Math.max(...phase_scale[xoverPhaseScaleType]) / gapPhase);
    return Math.round(y);
}

//RETURN GAIN VALUE FROM Y IN XOVER
function gainFromYXOVER(y) {
    var gain = 0;
    var gapGain = Math.max(...gain_scaleXOVER[xoverGainScaleType]) - Math.min(...gain_scaleXOVER[xoverGainScaleType]);
    gain = (y - graphXOVERHeight * (Math.max(...gain_scaleXOVER[xoverGainScaleType]) / gapGain)) * -(gapGain / graphXOVERHeight);
    return Math.round(gain * 100) / 100;
}

//RETURN PHASE VALUE FROM Y IN XOVER
function phaseFromYXOVER(y) {
    var gain = 0;
    var gapPhase = Math.max(...phase_scale[xoverPhaseScaleType]) - Math.min(...phase_scale[xoverPhaseScaleType]);
    gain = (y - graphXOVERHeight * (Math.max(...phase_scale[xoverPhaseScaleType]) / gapPhase)) * -(gapPhase / graphXOVERHeight);
    return Math.round(gain * 100) / 100;
}

//DISPLAY ONE VALUE IN CONSOLE (PARAM1, PARAM2) PARAM1 TEXT, PARAM2 VALUE
function displayVal(a, b) {
    var text = "VAR " + a + " : ";
    console.log(text + b);
}

//DISPLAY TWO VALUES IN CONSOLE (PARAM1, PARAM2, PARAM3, PARAM4) PARAM1 TEXT, PARAM2 VALUE, PARAM3 TEXT, PARAM4 VALUE
function displayValues(a, b, c, d) {
    var text = "VAR " + a + " : " + b + " \\ VAR " + c + " : " + d;
    console.log(text);
}

//CONVERT Q TO BW OCTAVE FOR PEQ
function BWfromQ(Q) {
    var bw = 0;
    var log2 = Math.log10(2);
    var q2 = Q * Q;
    bw = Math.log10((Math.sqrt(4 * q2 + 1) + 2 * q2 + 1) / (2 * q2)) / log2;
    return Math.round(bw * 1000) / 1000;
}

//CONVERT BW OCTAVE TO Q FOR PEQ
function QfromBW(bw_oct) {
    var q = 0;
    var bw = Math.pow(2, bw_oct);
    q = Math.sqrt(bw) / (bw - 1);
    return Math.round(q * 100) / 100;
}


//COMPUTE COMPLEX VALUE FOR SUM OF ZEROS AND SUM OF POLES IN PEQ COMPUTATION OPERATION
function evalCoefs(coefs, freq) {
    var len = coefs.length;
    var fx = freq / fS;
    // displayVal("length coef",len);
    var res = 0;
    for (var idx = 0; idx < len; idx++)
        res = math.add(res, math.multiply(coefs[idx], math.exp(math.complex(0, -idx * fx * 2 * math.pi))));
    return res
}

//COMPUTE PEQ COEFFICIENTS (A0, A1, A2, B0, B1, B2) AND SAVE IT
function computePEQCoeff(num) {
    switch (arrayEqParam[num].type) {
        case 0:
            BellSymCalcCoefficients(num);
            break;
        case 1:
            BellASymCalcCoefficients(num);
            break;
        case 2:
            NotchCalcCoefficients(num);
            break;
        case 3:
            LowShelf1CalcCoefficients(num);
            break;
        case 4:
            LowShelf2CalcCoefficients(num);
            break;
        case 5:
            HighShelf1CalcCoefficients(num);
            break;
        case 6:
            HighShelf2CalcCoefficients(num);
            break;
        case 7:
            AllPass1CalcCoefficients(num);
            break;
        case 8:
            AllPass2CalcCoefficients(num);
            break;
        case 9:
            Highpass1CalcCoefficients(num);
            break;
        case 10:
            Highpass2CalcCoefficients(num);
            break;
        case 11:
            Highpass2VariQCalcCoefficients(num);
            break;
        case 12:
            Lowpass1CalcCoefficients(num);
            break;
        case 13:
            Lowpass2CalcCoefficients(num);
            break;
        case 14:
            Lowpass2VariQCalcCoefficients(num);
            break;
        case 15:
            Bandpass2CalcCoefficients(num);
            break;
        default:
            displayVal("filter not found", num);
    }
}

// RETURN MAGNITUDE IN DB FOR A FREQUENCY f AND A PEQ NUMBER num
function getMagInDb(f, num) {
    // displayVal("Frequesncy asked", f);
    // displayVal("TYPE EQ",arrayEqParam[num].type);
    var invert = 0;
    switch (arrayEqParam[num].type) {
        case 0: //'Bell-Sym':
            break;
        case 1: //'Bell-ASym':
            invert = 1;
            break;
        case 2: //'Notch':
            invert = 1;
            break;
        case 3: //'Low-Shelving 6dB/oct':
            break;
        case 4: //'Low-Shelving 12dB/oct':
            break;
        case 5: //'High-Shelving 6dB/oct':
            break;
        case 6: //'High-Shelving 12dB/oct':
            break;
        case 7: //'All-Pass 90°':
            invert = 1;
            break;
        case 8: //'All-Pass 180°':
            invert = 1;
            break;
        case 9: //'High-Pass 6dB/oct':
            invert = 1;
            break;
        case 10: //'High-Pass 12dB/oct':
            invert = 1;
            break;
        case 11: //'High-Pass VariQ 12dB/oct':
            invert = 1;
            break;
        case 12: //'Low-Pass 6dB/oct':
            invert = 1;
            break;
        case 13: //'Low-Pass 12dB/oct':
            invert = 1;
            break;
        case 14: //'Low-Pass VariQ 12dB/oct':
            invert = 1;
            break;
        case 15: //'Band-Pass':
            invert = 1;
            break;
        default:
            displayVal("filter not found", arrayEqParam[num].type);
    }
    var aVect = [];
    aVect[0] = arrayEqParam[num].a.a0;
    aVect[1] = arrayEqParam[num].a.a1;
    aVect[2] = arrayEqParam[num].a.a2;
    var bVect = [];
    bVect[0] = arrayEqParam[num].b.b0;
    bVect[1] = arrayEqParam[num].b.b1;
    bVect[2] = arrayEqParam[num].b.b2;
    var resZeros = evalCoefs(aVect, f);
    var resPoles = evalCoefs(bVect, f);
    var res = math.divide(resZeros, resPoles);
    var tempMag = 0;
    tempMag = math.abs(res);
    tempMag = 20 * Math.log10(tempMag);
    if (invert)
        tempMag = -tempMag;
    return tempMag;
}

// RETURN PHASE IN DEGREE FOR A FREQUENCY f AND A PEQ NUMBER num
function getPhaInDg(f, num) {
    // displayVal("TYPE EQ",arrayEqParam[num].type);
    var invert = 0;
    switch (arrayEqParam[num].type) {
        case '0': //'Bell-Sym':
            break;
        case '1': //'Bell-ASym':
            invert = 1;
            break;
        case '2': //'Notch':
            invert = 1;
            break;
        case '3': //'Low-Shelving 6dB/oct':
            break;
        case '4': //'Low-Shelving 12dB/oct':
            break;
        case '5': //'High-Shelving 6dB/oct':
            break;
        case '6': //'High-Shelving 12dB/oct':
            break;
        case '7': //'All-Pass 90°':
            invert = 1;
            break;
        case '8': //'All-Pass 180°':
            invert = 1;
            break;
        case '9': //'High-Pass 6dB/oct':
            invert = 1;
            break;
        case '10': //'High-Pass 12dB/oct':
            invert = 1;
            break;
        case '11': //'High-Pass VariQ 12dB/oct':
            invert = 1;
            break;
        case '12': //'Low-Pass 6dB/oct':
            invert = 1;
            break;
        case '13': //'Low-Pass 12dB/oct':
            invert = 1;
            break;
        case '14': //'Low-Pass VariQ 12dB/oct':
            invert = 1;
            break;
        case '15': //'Band-Pass':
            invert = 1;
            break;
        default:
            console.log("filter not found");
    }
    var aVect = [];
    aVect[0] = arrayEqParam[num].a.a0;
    aVect[1] = arrayEqParam[num].a.a1;
    aVect[2] = arrayEqParam[num].a.a2;
    var bVect = [];
    bVect[0] = arrayEqParam[num].b.b0;
    bVect[1] = arrayEqParam[num].b.b1;
    bVect[2] = arrayEqParam[num].b.b2;
    var resZeros = evalCoefs(aVect, f);
    var resPoles = evalCoefs(bVect, f);
    var res = math.divide(resZeros, resPoles);
    var tempMag = 0;
    tempMag = math.arg(res);
    tempMag = tempMag * (180 / Math.PI);
    if (invert)
        tempMag = -tempMag;
    return tempMag;
}

$.fn.processPEQ = function(x, num) {

    var tempMag = 0;
    var tempPha = 0;
    var f = 0;
    f = freqFromX(x);
    var invert = 0;
    switch (arrayEqParam[num].type) {
        case 0: //'Bell-Sym':
            break;
        case 1: //'Bell-ASym':
            invert = 1;
            break;
        case 2: //'Notch':
            invert = 1;
            break;
        case 3: //'Low-Shelving 6dB/oct':
            break;
        case 4: //'Low-Shelving 12dB/oct':
            break;
        case 5: //'High-Shelving 6dB/oct':
            break;
        case 6: //'High-Shelving 12dB/oct':
            break;
        case 7: //'All-Pass 90°':
            invert = 1;
            break;
        case 8: //'All-Pass 180°':
            invert = 1;
            break;
        case 9: //'High-Pass 6dB/oct':
            invert = 1;
            break;
        case 10: //'High-Pass 12dB/oct':
            invert = 1;
            break;
        case 11: //'High-Pass VariQ 12dB/oct':
            invert = 1;
            break;
        case 12: //'Low-Pass 6dB/oct':
            invert = 1;
            break;
        case 13: //'Low-Pass 12dB/oct':
            invert = 1;
            break;
        case 14: //'Low-Pass VariQ 12dB/oct':
            invert = 1;
            break;
        case 15: //'Band-Pass':
            invert = 1;
            break;
        default:
            displayVal("filter not found", arrayEqParam[num].type);
    }
    var aVect = [];
    aVect[0] = arrayEqParam[num].a.a0;
    aVect[1] = arrayEqParam[num].a.a1;
    aVect[2] = arrayEqParam[num].a.a2;
    var bVect = [];
    bVect[0] = arrayEqParam[num].b.b0;
    bVect[1] = arrayEqParam[num].b.b1;
    bVect[2] = arrayEqParam[num].b.b2;
    var resZeros = evalCoefs(aVect, f);
    var resPoles = evalCoefs(bVect, f);
    var res = math.divide(resZeros, resPoles);
    tempMag = math.abs(res);
    tempMag = 20 * Math.log10(tempMag);
    if (invert)
        tempMag = -tempMag;

    tempPha = math.arg(res);
    tempPha = tempPha * (180 / Math.PI);
    if (invert)
        tempPha = -tempPha;

    return {
        magnitude: tempMag,
        phase: tempPha,
    };
}

// PROCESS PEQ PARAM GROUP
$.fn.processPEQGroup = function(x, num) {

    var tempMag = 0;
    var tempPha = 0;
    var f = 0;
    f = freqFromX(x);
    var invert = 0;
    switch (arrayEqGroupParam[num].type) {
        case 0: //'Bell-Sym':
            break;
        case 1: //'Bell-ASym':
            break;
        case 2: //'Notch':
            invert = 1;
            break;
        case 3: //'Low-Shelving 6dB/oct':
            break;
        case 4: //'Low-Shelving 12dB/oct':
            break;
        case 5: //'High-Shelving 6dB/oct':
            break;
        case 6: //'High-Shelving 12dB/oct':
            break;
        case 7: //'All-Pass 90°':
            invert = 1;
            break;
        case 8: //'All-Pass 180°':
            invert = 1;
            break;
        case 9: //'High-Pass 6dB/oct':
            invert = 1;
            break;
        case 10: //'High-Pass 12dB/oct':
            invert = 1;
            break;
        case 11: //'High-Pass VariQ 12dB/oct':
            invert = 1;
            break;
        case 12: //'Low-Pass 6dB/oct':
            invert = 1;
            break;
        case 13: //'Low-Pass 12dB/oct':
            invert = 1;
            break;
        case 14: //'Low-Pass VariQ 12dB/oct':
            invert = 1;
            break;
        case 15: //'Band-Pass':
            invert = 1;
            break;
        default:
            displayVal("filter not found", arrayEqGroupParam[num].type);
    }
    var aVect = [];
    aVect[0] = arrayEqGroupParam[num].a.a0;
    aVect[1] = arrayEqGroupParam[num].a.a1;
    aVect[2] = arrayEqGroupParam[num].a.a2;
    var bVect = [];
    bVect[0] = arrayEqGroupParam[num].b.b0;
    bVect[1] = arrayEqGroupParam[num].b.b1;
    bVect[2] = arrayEqGroupParam[num].b.b2;
    var resZeros = evalCoefs(aVect, f);
    var resPoles = evalCoefs(bVect, f);
    var res = math.divide(resZeros, resPoles);
    tempMag = math.abs(res);
    tempMag = 20 * Math.log10(tempMag);
    if (invert)
        tempMag = -tempMag;

    tempPha = math.arg(res);
    tempPha = tempPha * (180 / Math.PI);
    if (invert)
        tempPha = -tempPha;

    return {
        magnitude: tempMag,
        phase: tempPha,
    };
}

//HIDE ALL DIV IN PEQ PARAMETERS AREA
$.fn.clearPEQParamArea = function() {
    for (var i = 0; i < eqCount; i++) {
        var id = "#parametersAreaEQ" + i;
        $(id).hide();
    }
    $("#parametersAreaEQ99").hide();
    $("#parametersAreaEQ100").hide();
}

//HIDE ALL DIV IN PEQ GROUP PARAMETERS AREA
$.fn.clearPEQGroupParamArea = function() {
    for (var i = 0; i < eqCount; i++) {
        var id = "#parametersAreaEQGroup" + i;
        $(id).hide();
    }
    $("#parametersAreaEQGroup99").hide();
    $("#parametersAreaEQGroup100").hide();
}

//PEQ COMPUTATION

//CONSTRUCTOR OF PARAMETRIC EQ
function EqParam(e, f, g, q, t, a, b, x, y) {
    this.ena = e;
    this.frequency = f;
    this.gain = g;
    this.q = q;
    this.bw = BWfromQ(q);
    this.type = t;
    this.a = a;
    this.b = b;
    this.xLock = x;
    this.yLock = y;
}

//CONSTRUCTOR OF PARAMETRIC EQ
function XoverParam(e, f, g, q, t, x, y) {
    this.ena = e;
    this.frequency = f;
    this.gain = g;
    this.q = q;
    this.bw = BWfromQ(q);
    this.type = t;
    //CROSSOVER CASCADE FILTER FROM 1th AND 2nd ORDER SO THEY HAVE MULTIPLE COEFFICIENTS A012 ET B012
    this.a = new Array();
    this.b = new Array();
    this.xLock = x;
    this.yLock = y;
}

//CONSTRUCTOR OF A PARAM FOR PEQ
function AParam() {
    this.a0 = 0;
    this.a1 = 0;
    this.a2 = 0;
}

//CONSTRUCTOR OF B PARAM FOR PEQ
function BParam() {
    this.b0 = 0;
    this.b1 = 0;
    this.b2 = 0;
}


// ----------------------------------------------------------------------------
// Filter #0: Bell Symmetric
function BellSymCalcCoefficients(eqNum) {
    // Standard biquad, both numerator and denominator 2nd order
    var freqEq = arrayEqParam[eqNum].frequency;
    var gainEq = -1 * arrayEqParam[eqNum].gain;
    var qEq = arrayEqParam[eqNum].q;
    //AMPLITUDE
    var A = Math.pow(10, gainEq / 20);
    var wx = Math.PI * (freqEq / fS); //arrayEqParam[eqNum].frequency;
    var w0 = 2 * wx;
    var c0 = Math.cos(w0);
    var sx = Math.sin(wx);
    var alpha = sx * sx / (wx * qEq);

    if (A >= 1) {
        var beta = A * alpha;
        var k = -2 * c0;

        arrayEqParam[eqNum].b.b0 = 1 + beta;
        arrayEqParam[eqNum].b.b1 = k;
        arrayEqParam[eqNum].b.b2 = 1 - beta;
        arrayEqParam[eqNum].a.a0 = 1 + alpha;
        arrayEqParam[eqNum].a.a1 = k;
        arrayEqParam[eqNum].a.a2 = 1 - alpha;
    } else {
        var beta = alpha / A;
        var k = -2 * c0;

        arrayEqParam[eqNum].b.b0 = 1 + alpha;
        arrayEqParam[eqNum].b.b1 = k;
        arrayEqParam[eqNum].b.b2 = 1 - alpha;
        arrayEqParam[eqNum].a.a0 = 1 + beta;
        arrayEqParam[eqNum].a.a1 = k;
        arrayEqParam[eqNum].a.a2 = 1 - beta;
    }
}

// ----------------------------------------------------------------------------
// Filter #1: Bell Asymmetric
function BellASymCalcCoefficients(eqNum) {
    // Standard biquad, both numerator and denominator 2nd order
    var freqEq = arrayEqParam[eqNum].frequency;
    var gainEq = arrayEqParam[eqNum].gain;
    var qEq = arrayEqParam[eqNum].q;
    //AMPLITUDE
    var A = Math.pow(10, gainEq / 20);
    var wx = Math.PI * (freqEq / fS);
    var w0 = 2 * wx;
    var c0 = Math.cos(w0);
    var sx = Math.sin(wx);
    var alpha = sx * sx / (wx * qEq);
    var k = -2 * c0;
    var g = A * alpha;

    arrayEqParam[eqNum].b.b0 = 1 + g;
    arrayEqParam[eqNum].b.b1 = k;
    arrayEqParam[eqNum].b.b2 = 1 - g;
    arrayEqParam[eqNum].a.a0 = 1 + alpha;
    arrayEqParam[eqNum].a.a1 = k;
    arrayEqParam[eqNum].a.a2 = 1 - alpha;
}

// ----------------------------------------------------------------------------
// Filter #2: Notch
function NotchCalcCoefficients(eqNum) {
    // Standard biquad, both numerator and denominator 2nd order
    var freqEq = arrayEqParam[eqNum].frequency;
    var qEq = arrayEqParam[eqNum].q;

    var wx = Math.PI * (freqEq / fS);
    var w0 = 2 * wx;
    var c0 = Math.cos(w0);
    var sx = Math.sin(wx);
    var alpha = sx * sx / (wx * qEq);
    var k = -2 * c0;

    arrayEqParam[eqNum].b.b0 = 1;
    arrayEqParam[eqNum].b.b1 = k;
    arrayEqParam[eqNum].b.b2 = 1;
    arrayEqParam[eqNum].a.a0 = 1 + alpha;
    arrayEqParam[eqNum].a.a1 = k;
    arrayEqParam[eqNum].a.a2 = 1 - alpha;
}

// ----------------------------------------------------------------------------
// Filter #3: Low-Shelving 6dB/oct
function LowShelf1CalcCoefficients(eqNum) {
    // Standard first order
    var freqEq = arrayEqParam[eqNum].frequency;
    var gainEq = -1 * arrayEqParam[eqNum].gain;

    var A = Math.pow(10, gainEq / 20);
    var wx = Math.PI * (freqEq / fS);
    var cx = Math.cos(wx);
    var sx = Math.sin(wx);

    if (A >= 1) {
        var g = A * sx;

        arrayEqParam[eqNum].b.b0 = g + cx;
        arrayEqParam[eqNum].b.b1 = g - cx;
        arrayEqParam[eqNum].a.a0 = sx + cx;
        arrayEqParam[eqNum].a.a1 = sx - cx;
    } else {
        A = 1 / A;

        arrayEqParam[eqNum].b.b0 = sx + cx;
        arrayEqParam[eqNum].b.b1 = sx - cx;
        arrayEqParam[eqNum].a.a0 = A * sx + cx;
        arrayEqParam[eqNum].a.a1 = A * sx - cx;
    }

    arrayEqParam[eqNum].a.a2 = 0;
    arrayEqParam[eqNum].b.b2 = 0;
}

// ----------------------------------------------------------------------------
// Filter #4  Low-Shelving 12dB/oct
function LowShelf2CalcCoefficients(eqNum) {
    // Standard biquad, both numerator and denominator 2nd order
    var freqEq = arrayEqParam[eqNum].frequency;
    var gainEq = -1 * arrayEqParam[eqNum].gain;

    var A = Math.pow(10, gainEq / 20);
    var wx = Math.PI * (freqEq / fS);
    var w0 = 2 * wx;
    var c0 = Math.cos(w0);
    // Improved precision for the term 1-c0, necessary when
    // using float calculations instead of double.
    var sx = Math.sin(wx);
    var c1 = 2 * sx * sx;
    var alpha = c1 / (Math.sqrt(2) * wx);

    if (A >= 1) {
        var k = c1 * (A - 1) / 2 + 1;
        var g = Math.sqrt(A) * alpha;

        arrayEqParam[eqNum].b.b0 = k + g;
        arrayEqParam[eqNum].b.b1 = c1 * (A + 1) - 2;
        arrayEqParam[eqNum].b.b2 = k - g;
        arrayEqParam[eqNum].a.a0 = 1 + alpha;
        arrayEqParam[eqNum].a.a1 = -2 * c0;
        arrayEqParam[eqNum].a.a2 = 1 - alpha;
    } else {
        A = 1 / A;
        var k = c1 * (A - 1) / 2 + 1;
        var g = Math.sqrt(A) * alpha;

        arrayEqParam[eqNum].b.b0 = 1 + alpha;
        arrayEqParam[eqNum].b.b1 = -2 * c0;
        arrayEqParam[eqNum].b.b2 = 1 - alpha;
        arrayEqParam[eqNum].a.a0 = k + g;
        arrayEqParam[eqNum].a.a1 = c1 * (A + 1) - 2;
        arrayEqParam[eqNum].a.a2 = k - g;
    }
}

// ----------------------------------------------------------------------------
// Filter #5  High-Shelving 6dB/oct
function HighShelf1CalcCoefficients(eqNum) {
    // Standard first order
    var freqEq = arrayEqParam[eqNum].frequency;
    var gainEq = -1 * arrayEqParam[eqNum].gain;

    var A = Math.pow(10, gainEq / 20);
    var wx = Math.PI * (freqEq / fS);
    var cx = Math.cos(wx);
    var sx = Math.sin(wx);

    if (A >= 1) {
        arrayEqParam[eqNum].b.b0 = sx + A * cx;
        arrayEqParam[eqNum].b.b1 = sx - A * cx;
        arrayEqParam[eqNum].a.a0 = sx + cx;
        arrayEqParam[eqNum].a.a1 = sx - cx;
    } else {
        A = 1 / A;

        arrayEqParam[eqNum].b.b0 = sx + cx;
        arrayEqParam[eqNum].b.b1 = sx - cx;
        arrayEqParam[eqNum].a.a0 = sx + A * cx;
        arrayEqParam[eqNum].a.a1 = sx - A * cx;
    }

    arrayEqParam[eqNum].a.a2 = 0;
    arrayEqParam[eqNum].b.b2 = 0;
}

// ----------------------------------------------------------------------------
// Filter #6  High-Shelving 12dB/oct
function HighShelf2CalcCoefficients(eqNum) {
    // Standard biquad, both numerator and denominator 2nd order
    var freqEq = arrayEqParam[eqNum].frequency;
    var gainEq = -1 * arrayEqParam[eqNum].gain;

    var A = Math.pow(10, gainEq / 20);
    var wx = Math.PI * (freqEq / fS);
    var w0 = 2 * wx;
    var c0 = Math.cos(w0);
    var sx = Math.sin(wx);
    var alpha = 2 * sx * sx / (Math.sqrt(2) * wx);
    var cx = 1 + c0;

    if (A >= 1) {
        var k = cx * (A - 1) / 2 + 1;
        var g = Math.sqrt(A) * alpha;

        arrayEqParam[eqNum].b.b0 = k + g;
        arrayEqParam[eqNum].b.b1 = 2 - cx * (A + 1);
        arrayEqParam[eqNum].b.b2 = k - g;
        arrayEqParam[eqNum].a.a0 = 1 + alpha;
        arrayEqParam[eqNum].a.a1 = -2 * c0;
        arrayEqParam[eqNum].a.a2 = 1 - alpha;
    } else {
        A = 1 / A;
        var k = cx * (A - 1) / 2 + 1;
        var g = Math.sqrt(A) * alpha;

        arrayEqParam[eqNum].b.b0 = 1 + alpha;
        arrayEqParam[eqNum].b.b1 = -2 * c0;
        arrayEqParam[eqNum].b.b2 = 1 - alpha;
        arrayEqParam[eqNum].a.a0 = k + g;
        arrayEqParam[eqNum].a.a1 = 2 - cx * (A + 1);
        arrayEqParam[eqNum].a.a2 = k - g;
    }
}

// ----------------------------------------------------------------------------
// Filter #7  All-Pass 90°
function AllPass1CalcCoefficients(eqNum) {
    // Standard first order
    var freqEq = arrayEqParam[eqNum].frequency;

    var w0 = 2 * Math.PI * (freqEq / fS);
    var c0 = Math.cos(w0);
    var s0 = Math.sin(w0);
    var a = -c0 / (1 + s0);

    arrayEqParam[eqNum].b.b0 = a;
    arrayEqParam[eqNum].b.b1 = 1;
    arrayEqParam[eqNum].a.a0 = 1;
    arrayEqParam[eqNum].a.a1 = a;

    arrayEqParam[eqNum].a.a2 = 0;
    arrayEqParam[eqNum].b.b2 = 0;
}

// ----------------------------------------------------------------------------
// Filter #8  All-Pass 180°
function AllPass2CalcCoefficients(eqNum) {
    // Standard biquad, both numerator and denominator 2nd order
    var freqEq = arrayEqParam[eqNum].frequency;
    var qEq = arrayEqParam[eqNum].q;

    var wx = Math.PI * (freqEq / fS);
    var w0 = 2 * wx;
    var c0 = Math.cos(w0);
    var sx = Math.sin(wx);
    var alpha = sx * sx / (wx * qEq);

    arrayEqParam[eqNum].b.b0 = 1 - alpha;
    arrayEqParam[eqNum].b.b1 = -2 * c0;
    arrayEqParam[eqNum].b.b2 = 1 + alpha;
    arrayEqParam[eqNum].a.a0 = arrayEqParam[eqNum].b.b2;
    arrayEqParam[eqNum].a.a1 = arrayEqParam[eqNum].b.b1;
    arrayEqParam[eqNum].a.a2 = arrayEqParam[eqNum].b.b0;
}

// ----------------------------------------------------------------------------
// Filter #9  High-Pass 6dB/oct
function Highpass1CalcCoefficients(eqNum) {
    // Standard first order
    var freqEq = arrayEqParam[eqNum].frequency;

    var wx = Math.PI * (freqEq / fS);
    var cx = Math.cos(wx);
    var sx = Math.sin(wx);

    arrayEqParam[eqNum].b.b0 = cx;
    arrayEqParam[eqNum].b.b1 = -cx;
    arrayEqParam[eqNum].a.a0 = sx + cx;
    arrayEqParam[eqNum].a.a1 = sx - cx;

    arrayEqParam[eqNum].a.a2 = 0;
    arrayEqParam[eqNum].b.b2 = 0;
}

// ----------------------------------------------------------------------------
// Filter #10: High-Pass 12dB/oct
function Highpass2CalcCoefficients(eqNum) {
    var q = Math.sqrt(2);

    // Standard biquad, both numerator and denominator 2nd order
    var freqEq = arrayEqParam[eqNum].frequency;

    var w0 = 2 * Math.PI * (freqEq / fS);
    var c0 = Math.cos(w0);
    var alpha = Math.sin(w0) / q;
    var c1 = 1 + c0;

    arrayEqParam[eqNum].b.b0 = c1 / 2;
    arrayEqParam[eqNum].b.b1 = -c1;
    arrayEqParam[eqNum].b.b2 = c1 / 2;
    arrayEqParam[eqNum].a.a0 = 1 + alpha;
    arrayEqParam[eqNum].a.a1 = -2 * c0;
    arrayEqParam[eqNum].a.a2 = 1 - alpha;
}

// ----------------------------------------------------------------------------
// Filter #11  High-Pass VariQ 12dB/oct
function Highpass2VariQCalcCoefficients(eqNum) {
    // Standard biquad, both numerator and denominator 2nd order
    var freqEq = arrayEqParam[eqNum].frequency;
    var qEq = arrayEqParam[eqNum].q;

    var w0 = 2 * Math.PI * (freqEq / fS);
    var c0 = Math.cos(w0);
    var alpha = Math.sin(w0) / (2 * qEq);
    var c1 = 1 + c0;

    arrayEqParam[eqNum].b.b0 = c1 / 2;
    arrayEqParam[eqNum].b.b1 = -c1;
    arrayEqParam[eqNum].b.b2 = c1 / 2;
    arrayEqParam[eqNum].a.a0 = 1 + alpha;
    arrayEqParam[eqNum].a.a1 = -2 * c0;
    arrayEqParam[eqNum].a.a2 = 1 - alpha;
}

// ----------------------------------------------------------------------------
// Filter #12  Low-Pass 6dB/oct
function Lowpass1CalcCoefficients(eqNum) {
    // Standard first order
    var freqEq = arrayEqParam[eqNum].frequency;

    var wx = Math.PI * (freqEq / fS);
    var cx = Math.cos(wx);
    var sx = Math.sin(wx);

    arrayEqParam[eqNum].b.b0 = sx;
    arrayEqParam[eqNum].b.b1 = sx;
    arrayEqParam[eqNum].a.a0 = sx + cx;
    arrayEqParam[eqNum].a.a1 = sx - cx;

    arrayEqParam[eqNum].a.a2 = 0;
    arrayEqParam[eqNum].b.b2 = 0;
}

// ----------------------------------------------------------------------------
// Filter #13: Low-Pass 12dB/oct
function Lowpass2CalcCoefficients(eqNum) {
    var q = Math.sqrt(2);

    // Standard biquad, both numerator and denominator 2nd order
    var freqEq = arrayEqParam[eqNum].frequency;

    var wx = Math.PI * (freqEq / fS);
    var w0 = 2 * wx;
    var c0 = Math.cos(w0);
    var alpha = Math.sin(w0) / q;
    // Improved precision for the term 1-c0, necessary when
    // using float calculations instead of double.
    var sx = Math.sin(wx);
    var c1 = 2 * sx * sx;

    arrayEqParam[eqNum].b.b0 = c1 / 2;
    arrayEqParam[eqNum].b.b1 = c1;
    arrayEqParam[eqNum].b.b2 = c1 / 2;
    arrayEqParam[eqNum].a.a0 = 1 + alpha;
    arrayEqParam[eqNum].a.a1 = -2 * c0;
    arrayEqParam[eqNum].a.a2 = 1 - alpha;
}

// ----------------------------------------------------------------------------
// Filter #14  Low-Pass VariQ 12dB/oct
function Lowpass2VariQCalcCoefficients(eqNum) {
    // Standard biquad, both numerator and denominator 2nd order
    var freqEq = arrayEqParam[eqNum].frequency;
    var qEq = arrayEqParam[eqNum].q;

    var wx = Math.PI * (freqEq / fS);
    var w0 = 2 * wx;
    var c0 = Math.cos(w0);
    var alpha = Math.sin(w0) / (2 * qEq);
    // Improved precision for the term 1-c0, necessary when
    // using float calculations instead of double.
    var sx = Math.sin(wx);
    var c1 = 2 * sx * sx;

    arrayEqParam[eqNum].b.b0 = c1 / 2;
    arrayEqParam[eqNum].b.b1 = c1;
    arrayEqParam[eqNum].b.b2 = c1 / 2;
    arrayEqParam[eqNum].a.a0 = 1 + alpha;
    arrayEqParam[eqNum].a.a1 = -2 * c0;
    arrayEqParam[eqNum].a.a2 = 1 - alpha;
}

// ----------------------------------------------------------------------------
// Filter #15: Band-Pass 6dB/oct
function Bandpass2CalcCoefficients(eqNum) {
    // Standard biquad, both numerator and denominator 2nd order
    var freqEq = arrayEqParam[eqNum].frequency;
    var qEq = arrayEqParam[eqNum].q;

    var wx = Math.PI * (freqEq / fS);
    var w0 = 2 * wx;
    var c0 = Math.cos(w0);
    var sx = Math.sin(wx);
    var alpha = sx * sx / (wx * qEq);

    arrayEqParam[eqNum].b.b0 = alpha;
    arrayEqParam[eqNum].b.b1 = 0;
    arrayEqParam[eqNum].b.b2 = -alpha;
    arrayEqParam[eqNum].a.a0 = 1 + alpha;
    arrayEqParam[eqNum].a.a1 = -2 * c0;
    arrayEqParam[eqNum].a.a2 = 1 - alpha;
}

// =============================================================================
// XOVER Filter #0-11: Butterworth 6dB/oct to Linkwitz-Riley 48dB/oct
// Compute a butterworth filter up to 8th order and put the coefficients
// in the supplied array. The coefficient array must be at least length 4.
function ButterworthLinkwitzRileyCalcCoefficients(type, indice) {
    var order = 0;
    var linkwitz = 0;
    if (indice > 7)
        linkwitz = 1

    switch (parseInt(indice)) {
        case 0:
            order = 1;
            break;
        case 1:
            order = 2;
            break;
        case 2:
            order = 3;
            break;
        case 3:
            order = 4;
            break;
        case 4:
            order = 5;
            break;
        case 5:
            order = 6;
            break;
        case 6:
            order = 7;
            break;
        case 7:
            order = 8;
            break;
        case 8:
            order = 2;
            break;
        case 9:
            order = 4;
            break;
        case 10:
            order = 6;
            break;
        case 11:
            order = 8;
            break;
        default:
            break;
    }

    // Remove all filters
    if (type == 0) {
        highPassEqParam.a.length = 0;
        highPassEqParam.b.length = 0;
        var wx = Math.PI * (highPassEqParam.frequency / fS);
        var sx = Math.sin(wx);
        var w0 = 2 * wx;
        var s0 = Math.sin(w0);
        var c0 = Math.cos(w0);
        var sx2 = sx * sx;
    } else {
        lowPassEqParam.a.length = 0;
        lowPassEqParam.b.length = 0;
        var wx = Math.PI * (lowPassEqParam.frequency / fS);
        var sx = Math.sin(wx);
        var w0 = 2 * wx;
        var s0 = Math.sin(w0);
        var c0 = Math.cos(w0);
        var sx2 = sx * sx;
    }

    var n = order;

    if (linkwitz == 1)
        n = n / 2; // Constructed from 2 half-order Butterworths

    var nk = n / 2; // number of biquad sections

    for (var k = 1; k <= nk; k++) {
        var a = new AParam();
        var b = new BParam();
        b.b0 = 1.0;
        a.a0 = 1.0;

        var alpha = s0 * Math.cos(Math.PI * (n - 2 * k + 1) / (2 * n));
        var a0 = 1 + alpha;
        var A;

        if (type == 0) {
            A = (1 + c0) / a0;

            b.b1 = -A;
            A /= 2;
        } else {
            A = sx2 / a0;
            b.b1 = 2 * A;
        }

        b.b0 = A;
        b.b2 = A;
        a.a1 = -2 * c0 / a0;
        a.a2 = (1 - alpha) / a0;

        if (type == 0) {
            highPassEqParam.a.push(a);
            highPassEqParam.b.push(b);
            if (linkwitz) {
                highPassEqParam.a.push(a);
                highPassEqParam.b.push(b);
            }
        } else {

            lowPassEqParam.a.push(a);
            lowPassEqParam.b.push(b);
            if (linkwitz) {
                lowPassEqParam.a.push(a);
                lowPassEqParam.b.push(b);
            }
        }
    }

    // Add the necessary sections to complete odd order filters
    if (n % 2 != 0) {
        // displayVal("n value for n%2 !=0", n);
        if (linkwitz == 1) {
            // displayVal("linkwitz test ok", linkwitz);
            if (type == 0) {
                //HIGHPASS2VARIQ : _filters.push_back(new FilterHighpass2VariQ(_f, 0, 0.5));
                let freqEq = highPassEqParam.frequency;
                let qEq = 0.5;

                let w0 = 2 * Math.PI * (freqEq / fS);
                let c0 = Math.cos(w0);
                let alpha = Math.sin(w0) / (2 * qEq);
                let c1 = 1 + c0;

                let a = new AParam();
                let b = new BParam();

                b.b0 = c1 / 2;
                b.b1 = -c1;
                b.b2 = c1 / 2;
                a.a0 = 1 + alpha;
                a.a1 = -2 * c0;
                a.a2 = 1 - alpha;

                highPassEqParam.a.push(a);
                highPassEqParam.b.push(b);
            } else {
                //LOWPASS2VARIQ : _filters.push_back(new FilterLowpass2VariQ(_f, 0, 0.5));
                let freqEq = lowPassEqParam.frequency;
                let qEq = 0.5;

                let wx = Math.PI * (freqEq / fS);
                let w0 = 2 * wx;
                let c0 = Math.cos(w0);
                let alpha = Math.sin(w0) / (2 * qEq);
                // Improved precision for the term 1-c0, necessary when
                // using float calculations instead of double.
                let sx = Math.sin(wx);
                let c1 = 2 * sx * sx;

                let a = new AParam();
                let b = new BParam();

                b.b0 = c1 / 2;
                b.b1 = c1;
                b.b2 = c1 / 2;
                a.a0 = 1 + alpha;
                a.a1 = -2 * c0;
                a.a2 = 1 - alpha;

                lowPassEqParam.a.push(a);
                lowPassEqParam.b.push(b);
            }
        } else {
            if (type == 0) {
                //FILTERHIGHPASS1 : _filters.push_back(new FilterHighpass1(_f, 0, 0));
                let freqEq = highPassEqParam.frequency;

                let wx = Math.PI * (freqEq / fS);
                let cx = Math.cos(wx);
                let sx = Math.sin(wx);

                let a = new AParam();
                let b = new BParam();

                b.b0 = cx;
                b.b1 = -cx;
                a.a0 = sx + cx;
                a.a1 = sx - cx;
                a.a2 = 0;
                b.b2 = 0;

                highPassEqParam.a.push(a);
                highPassEqParam.b.push(b);
            } else {
                //FILTERLOWPASS1 : _filters.push_back(new FilterLowpass1(_f, 0, 0));
                // Standard first order
                let freqEq = lowPassEqParam.frequency;

                let wx = Math.PI * (freqEq / fS);
                let cx = Math.cos(wx);
                let sx = Math.sin(wx);

                let a = new AParam();
                let b = new BParam();

                b.b0 = sx;
                b.b1 = sx;
                a.a0 = sx + cx;
                a.a1 = sx - cx;
                a.a2 = 0;
                b.b2 = 0;

                lowPassEqParam.a.push(a);
                lowPassEqParam.b.push(b);
            }
        }
    }
}

// ----------------------------------------------------------------------------
// XOVER Filter #12-18: Bessel 12dB/oct to Bessel 48dB/oct
// type = 0 => HIGHPASS type = 1 => LOWPASS
function BesselCalcCoefficients(type, indice) {

    var n = indice - 1;
    var wx = 0;
    var w0 = 0;

    // Remove all filters
    if (type == 0) {
        highPassEqParam.a.length = 0;
        highPassEqParam.b.length = 0;
        wx = Math.PI * (highPassEqParam.frequency / fS);
        w0 = 2 * wx;
    } else {
        lowPassEqParam.a.length = 0;
        lowPassEqParam.b.length = 0;
        wx = Math.PI * (lowPassEqParam.frequency / fS);
        w0 = 2 * wx;
    }

    for (var i = 0; i < 4; ++i) {
        var a = bessel_coeff[n][i][0];
        var b = bessel_coeff[n][i][1];

        var coeff_a = new AParam();
        var coeff_b = new BParam();
        coeff_b.b0 = 1.0;
        coeff_a.a0 = 1.0;

        //HIGHPASS FILTER TEST
        if (type == 0) {
            if (a != 0) {
                if (b == 0) {
                    // First order section
                    let sx = Math.sin(wx);
                    let cx = Math.cos(wx);
                    let ax = -a * cx;
                    let a0 = ax + sx;

                    coeff_b.b0 = ax / a0;
                    coeff_b.b1 = -coeff_b.b0;
                    coeff_a.a1 = (sx - ax) / a0;
                } else {
                    // Second order section
                    let p = a * a + b * b;
                    let c0 = Math.cos(w0);
                    let s0 = Math.sin(w0);
                    let cx = 1 + c0;
                    let a0 = cx * (p - 1) + 2 * (1 - a * s0);

                    coeff_b.b0 = p * cx / a0;
                    coeff_b.b1 = -2 * coeff_b.b0;
                    coeff_b.b2 = coeff_b.b0;
                    coeff_a.a1 = 2 * (2 - cx * (p + 1)) / a0;
                    coeff_a.a2 = (cx * (p - 1) + 2 * (1 + a * s0)) / a0;
                }
                highPassEqParam.a.push(coeff_a);
                highPassEqParam.b.push(coeff_b);
            }
        } else {
            if (a != 0) {
                if (b == 0) {
                    // First order section
                    let sx = Math.sin(wx);
                    let cx = Math.cos(wx);
                    let ax = -a * sx;
                    let a0 = ax + cx;

                    coeff_b.b0 = ax / a0;
                    coeff_b.b1 = coeff_b.b0;
                    coeff_a.a1 = (ax - cx) / a0;
                } else {
                    // Second order section
                    let p = a * a + b * b;
                    let sx = Math.sin(wx);
                    let c0 = 2 * sx * sx; // = 1-cos(w0)
                    let s0 = Math.sin(w0);
                    let a0 = c0 * (p - 1) + 2 * (1 - a * s0);

                    coeff_b.b0 = p * c0 / a0;
                    coeff_b.b1 = 2 * coeff_b.b0;
                    coeff_b.b2 = coeff_b.b0;
                    coeff_a.a1 = 2 * (c0 * (p + 1) - 2) / a0;
                    coeff_a.a2 = (c0 * (p - 1) + 2 * (1 + a * s0)) / a0;
                }
                lowPassEqParam.a.push(coeff_a);
                lowPassEqParam.b.push(coeff_b);
            }
        }
    }
}
//COMPUTE XOVER A AND B ARRAYS OF COEFFICIENT
function computeXOVERCoeff(type, indice) {
    if (indice < 12)
        ButterworthLinkwitzRileyCalcCoefficients(type, indice);
    else
        BesselCalcCoefficients(type, indice - 10);
}

//PROCESS XOVER VALUE FOR MAG AND PHA WITH FREQ freq (0 TO 22000) AND TYPE type ( 0 = HP & 1 = LP )
$.fn.processXover = function(x, type) {
    var tempMag = 0;
    var tempPha = 0;

    var lgt = (type == 0) ? highPassEqParam.a.length : lowPassEqParam.a.length;

    for (var i = 0; i < lgt; i++) {
        if (type == 0) {
            var aVect = [];
            aVect[0] = highPassEqParam.a[i].a0;
            aVect[1] = highPassEqParam.a[i].a1;
            aVect[2] = highPassEqParam.a[i].a2;
            var bVect = [];
            bVect[0] = highPassEqParam.b[i].b0;
            bVect[1] = highPassEqParam.b[i].b1;
            bVect[2] = highPassEqParam.b[i].b2;
        } else {
            var aVect = [];
            aVect[0] = lowPassEqParam.a[i].a0;
            aVect[1] = lowPassEqParam.a[i].a1;
            aVect[2] = lowPassEqParam.a[i].a2;
            var bVect = [];
            bVect[0] = lowPassEqParam.b[i].b0;
            bVect[1] = lowPassEqParam.b[i].b1;
            bVect[2] = lowPassEqParam.b[i].b2;
        }
        var f = freqFromXXOVER(x);
        var resZeros = evalCoefs(aVect, f);
        var resPoles = evalCoefs(bVect, f);
        var res = math.divide(resZeros, resPoles);
        tempMag = tempMag + (20 * Math.log10(math.abs(res)));
        tempPha = tempPha + (math.arg(res) * (180 / Math.PI));
        // displayVal("tempmag[" + i + "]", tempMag);
    }
    tempMag = -tempMag;
    tempPha = -tempPha;
    // displayVal("freq " + freqFromXXOVER(j) + "Hz", Math.round(tempMag) + "dB");
    return {
        magnitude: tempMag,
        phase: tempPha,
    };
}