'use strict';

/* ────────────────────────────────────────────────────────────────
   EPIC E7 — nice2dev-audio (Advanced Audio)
   
   Procedural synthesis, real-time effects, adaptive music,
   audio reactive visuals, voice chat
──────────────────────────────────────────────────────────────── */
const DEFAULT_ADSR = {
    attack: 0.01,
    decay: 0.1,
    sustain: 0.7,
    release: 0.3,
};
/** Generate a single sample from an oscillator (for procedural audio). */
function oscillatorSample(config, time) {
    var _a;
    const freq = config.frequency * Math.pow(2, config.detune / 1200);
    const phase = config.phase + time * freq * Math.PI * 2;
    const normalizedPhase = phase % (Math.PI * 2);
    switch (config.waveform) {
        case 'sine':
            return Math.sin(phase) * config.amplitude;
        case 'square':
            return (Math.sin(phase) >= 0 ? 1 : -1) * config.amplitude;
        case 'sawtooth':
            return ((normalizedPhase / Math.PI - 1) % 2) * config.amplitude;
        case 'triangle': {
            const t = normalizedPhase / (Math.PI * 2);
            return (4 * Math.abs(t - 0.5) - 1) * config.amplitude;
        }
        case 'noise':
            return (Math.random() * 2 - 1) * config.amplitude;
        case 'pulse': {
            const pw = (_a = config.pulseWidth) !== null && _a !== void 0 ? _a : 0.5;
            const t = normalizedPhase / (Math.PI * 2);
            return (t < pw ? 1 : -1) * config.amplitude;
        }
        default:
            return 0;
    }
}
/** Compute ADSR envelope value at a given time. */
function adsrValue(env, time, noteOffTime) {
    // Attack
    if (time < env.attack)
        return time / env.attack;
    // Decay
    const afterAttack = time - env.attack;
    if (afterAttack < env.decay) {
        return 1 - (1 - env.sustain) * (afterAttack / env.decay);
    }
    // Sustain (held)
    if (noteOffTime === null)
        return env.sustain;
    // Release
    const releaseTime = time - noteOffTime;
    if (releaseTime < env.release) {
        return env.sustain * (1 - releaseTime / env.release);
    }
    return 0;
}
/** Preset synth patches. */
const SYNTH_PRESETS = {
    piano: {
        name: 'Piano',
        oscillators: [
            { waveform: 'triangle', frequency: 440, amplitude: 0.6, phase: 0, detune: 0 },
            { waveform: 'sine', frequency: 880, amplitude: 0.2, phase: 0, detune: 0 },
        ],
        envelope: { attack: 0.005, decay: 0.3, sustain: 0.4, release: 0.5 },
        filterType: 'lowpass', filterFrequency: 4000, filterResonance: 1, filterEnvAmount: 2000,
        gain: 0.5, pan: 0,
    },
    bass: {
        name: 'Bass',
        oscillators: [
            { waveform: 'sawtooth', frequency: 110, amplitude: 0.8, phase: 0, detune: 0 },
        ],
        envelope: { attack: 0.01, decay: 0.2, sustain: 0.6, release: 0.2 },
        filterType: 'lowpass', filterFrequency: 800, filterResonance: 4, filterEnvAmount: 500,
        gain: 0.7, pan: 0,
    },
    pad: {
        name: 'Pad',
        oscillators: [
            { waveform: 'sine', frequency: 440, amplitude: 0.4, phase: 0, detune: 5 },
            { waveform: 'sine', frequency: 440, amplitude: 0.4, phase: 0, detune: -5 },
            { waveform: 'triangle', frequency: 220, amplitude: 0.2, phase: 0, detune: 0 },
        ],
        envelope: { attack: 0.8, decay: 0.5, sustain: 0.7, release: 1.5 },
        filterType: 'lowpass', filterFrequency: 2000, filterResonance: 2, filterEnvAmount: 0,
        lfo: { waveform: 'sine', frequency: 0.5, amplitude: 0.1, target: 'filter' },
        gain: 0.4, pan: 0,
    },
    sfxLaser: {
        name: 'SFX Laser',
        oscillators: [
            { waveform: 'square', frequency: 1200, amplitude: 0.5, phase: 0, detune: 0 },
        ],
        envelope: { attack: 0.001, decay: 0.15, sustain: 0, release: 0.1 },
        filterType: 'highpass', filterFrequency: 500, filterResonance: 8, filterEnvAmount: -1e3,
        gain: 0.3, pan: 0,
    },
    sfxExplosion: {
        name: 'SFX Explosion',
        oscillators: [
            { waveform: 'noise', frequency: 0, amplitude: 1, phase: 0, detune: 0 },
            { waveform: 'sine', frequency: 60, amplitude: 0.8, phase: 0, detune: 0 },
        ],
        envelope: { attack: 0.001, decay: 0.4, sustain: 0, release: 0.5 },
        filterType: 'lowpass', filterFrequency: 2000, filterResonance: 1, filterEnvAmount: -1500,
        gain: 0.6, pan: 0,
    },
};
function createReverb(roomSize = 0.7, damping = 0.5, wet = 0.3) {
    return { type: 'reverb', enabled: true, wet, params: { roomSize, damping, preDelay: 0.02 } };
}
function createDelay(time = 0.375, feedback = 0.4, wet = 0.3) {
    return { type: 'delay', enabled: true, wet, params: { time, feedback, pingPong: 0 } };
}
function createDistortion(amount = 0.5, tone = 0.5, wet = 1) {
    return { type: 'distortion', enabled: true, wet, params: { amount, tone } };
}
function createCompressor(threshold = -24, ratio = 4, attack = 0.003, release = 0.25) {
    return { type: 'compressor', enabled: true, wet: 1, params: { threshold, ratio, attack, release, knee: 30 } };
}
function createEffectsChain(effects = []) {
    return { effects, masterGain: 1, masterPan: 0 };
}
function evaluateMusicConditions(conditions, params) {
    var _a;
    for (const cond of conditions) {
        const val = (_a = params.get(cond.parameter)) !== null && _a !== void 0 ? _a : 0;
        const target = typeof cond.value === 'number' ? cond.value : parseFloat(cond.value);
        switch (cond.operator) {
            case '=':
                if (val !== target)
                    return false;
                break;
            case '!=':
                if (val === target)
                    return false;
                break;
            case '<':
                if (val >= target)
                    return false;
                break;
            case '>':
                if (val <= target)
                    return false;
                break;
            case '<=':
                if (val > target)
                    return false;
                break;
            case '>=':
                if (val < target)
                    return false;
                break;
        }
    }
    return true;
}
function findNextMusicState(config) {
    for (const transition of config.transitions) {
        if (transition.fromState !== config.currentState)
            continue;
        const targetState = config.states.find(s => s.name === transition.toState);
        if (!targetState)
            continue;
        // Check if any layer's conditions are met
        const allConditionsMet = targetState.layers.every(layer => layer.conditions.length === 0 || evaluateMusicConditions(layer.conditions, config.parameters));
        if (allConditionsMet)
            return transition.toState;
    }
    return null;
}
/** Beat/bar timing helpers. */
function beatDuration(bpm) {
    return 60 / bpm;
}
function barDuration(bpm, beatsPerBar) {
    return (60 / bpm) * beatsPerBar;
}
function currentBeat(time, bpm) {
    return time / (60 / bpm);
}
function nextBarTime(time, bpm, beatsPerBar) {
    const barLen = barDuration(bpm, beatsPerBar);
    return Math.ceil(time / barLen) * barLen;
}
const DEFAULT_ANALYSIS_CONFIG = {
    fftSize: 1024,
    smoothingTimeConstant: 0.8,
    minDecibels: -90,
    maxDecibels: -10,
};
function extractBands(frequencyData, sampleRate) {
    const binCount = frequencyData.length;
    const binWidth = sampleRate / (binCount * 2);
    function avgRange(lowHz, highHz) {
        const startBin = Math.max(0, Math.floor(lowHz / binWidth));
        const endBin = Math.min(binCount - 1, Math.floor(highHz / binWidth));
        if (startBin > endBin)
            return 0;
        let sum = 0;
        for (let i = startBin; i <= endBin; i++)
            sum += frequencyData[i];
        return sum / (endBin - startBin + 1) / 255;
    }
    let rms = 0;
    for (let i = 0; i < binCount; i++)
        rms += (frequencyData[i] / 255) * (frequencyData[i] / 255);
    rms = Math.sqrt(rms / binCount);
    return {
        sub: avgRange(20, 60),
        bass: avgRange(60, 250),
        lowMid: avgRange(250, 500),
        mid: avgRange(500, 2000),
        highMid: avgRange(2000, 4000),
        presence: avgRange(4000, 6000),
        brilliance: avgRange(6000, 20000),
        overall: rms,
    };
}
const DEFAULT_VOICE_CONFIG = {
    codec: 'opus',
    sampleRate: 48000,
    bitrate: 64000,
    channelCount: 1,
    echoCancellation: true,
    noiseSuppression: true,
    autoGainControl: true,
    vadEnabled: true,
    vadThreshold: 0.3,
    spatialAudio: false,
    maxDistance: 50,
    pushToTalk: false,
    pushToTalkKey: 'KeyV',
    muteOnDeafen: true,
};

exports.DEFAULT_ADSR = DEFAULT_ADSR;
exports.DEFAULT_ANALYSIS_CONFIG = DEFAULT_ANALYSIS_CONFIG;
exports.DEFAULT_VOICE_CONFIG = DEFAULT_VOICE_CONFIG;
exports.SYNTH_PRESETS = SYNTH_PRESETS;
exports.adsrValue = adsrValue;
exports.barDuration = barDuration;
exports.beatDuration = beatDuration;
exports.createCompressor = createCompressor;
exports.createDelay = createDelay;
exports.createDistortion = createDistortion;
exports.createEffectsChain = createEffectsChain;
exports.createReverb = createReverb;
exports.currentBeat = currentBeat;
exports.evaluateMusicConditions = evaluateMusicConditions;
exports.extractBands = extractBands;
exports.findNextMusicState = findNextMusicState;
exports.nextBarTime = nextBarTime;
exports.oscillatorSample = oscillatorSample;
//# sourceMappingURL=AudioAdvanced.js.map
