{"common/mixcommon.ts":"export function createInstrumentArray<T>(length: i32, factoryFunc: () => T): T[] {\n    const arr = new Array<T>(length);\n    for(let n  = 0; n < length;n++) {\n        arr[n] = factoryFunc();\n    }\n    return arr;\n}\n","environment.ts":"// earlier this used to externally declared\nexport const SAMPLERATE: f32 = 44100;","fx/allpass.ts":"import { DelayLine } from \"./delayline\";\n\nexport class AllPass {\n    readonly delay_line: DelayLine;\n\n    constructor(delay_length: usize) {\n        this.delay_line = new DelayLine(delay_length);\n    }\n\n    tick(input: f32): f32 {\n        let delayed: f32 = this.delay_line.read();\n        let output: f32 = -input + delayed;\n\n        // in the original version of freeverb this is a member which is never modified\n        const feedback: f32 = 0.5;\n\n        this.delay_line\n            .write_and_advance(input + delayed * feedback);\n\n        return output;\n    }\n}\n\nexport class AllPassFloat {\n    coeff: f32;\n    previousinput: f32;\n    previousoutput: f32;\n\n    setDelta(delta: f32): void {\n        this.coeff = (1 - delta) / (1 + delta);\n    }\n\n    clearBuffers(): void {\n        this.previousinput = 0;\n        this.previousoutput = 0;\n    }\n\n    process(input: f32): f32 {\n        const output = this.coeff * (input\n            - this.previousoutput)\n            + this.previousinput;\n        this.previousoutput = output;\n        this.previousinput = input;\n        return output;\n    }\n}\n","fx/bandpass.ts":"import { BiQuadFilter, FilterType, Q_BUTTERWORTH } from \"../synth/biquad\";\nimport { SAMPLERATE } from \"../environment\";\n\nexport class BandPass {\n    lpfilter: BiQuadFilter = new BiQuadFilter();\n    hpfilter: BiQuadFilter = new BiQuadFilter();\n    \n    constructor(lowfreq: f32, hifreq: f32) {\n        this.update_frequencies(lowfreq, hifreq);\n    }\n\n    clearBuffers(): void {\n        this.hpfilter.clearBuffers();\n        this.lpfilter.clearBuffers();\n    }\n\n    update_frequencies(lowfreq: f32, hifreq: f32): void {\n        this.lpfilter.update_coeffecients(FilterType.LowPass, SAMPLERATE, hifreq, Q_BUTTERWORTH);\n        this.hpfilter.update_coeffecients(FilterType.HighPass, SAMPLERATE, lowfreq, Q_BUTTERWORTH);\n    }\n\n    process(sample: f32): f32 {\n        return this.lpfilter.process(this.hpfilter.process(sample));                \n    }\n}","fx/comb.ts":"import { DelayLine } from \"./delayline\";\n\nexport class Comb {\n    readonly delay_line: DelayLine;\n    feedback: f32;\n    filter_state: f32;\n    dampening: f32;\n    dampening_inverse: f32;\n\n    constructor(delay_length: usize) {        \n        this.delay_line = new DelayLine(delay_length);\n        this.feedback= 0.5;\n        this.filter_state = 0.0;\n        this.dampening = 0.5;\n        this.dampening_inverse = 0.5;\n        \n    }\n\n    set_dampening(value: f32): void{\n        this.dampening = value;\n        this.dampening_inverse = 1.0 - value;\n    }\n\n    set_feedback(value: f32): void {\n        this.feedback = value;\n    }\n\n    tick(input: f32): f32 {\n        let output = this.delay_line.read();\n\n        this.filter_state =\n            output * this.dampening_inverse + this.filter_state * this.dampening;\n\n        this.delay_line\n            .write_and_advance(input + this.filter_state * this.feedback);\n\n        return output;\n    }\n}\n","fx/delayline.ts":"import { AllPassFloat } from \"./allpass\";\n\nexport class DelayLine {\n    readonly bufferPointer: usize;\n    index: usize = 0;\n    length: usize = 0;\n    currentPeak: f32 = 0;\n    currentPeakSamplesToLive: usize = 0;\n\n    private numsamplesf64: f64 = 0\n    private meanSquared: f64 = 0;\n\n    constructor(private numsamples: usize) {\n        this.numsamplesf64 = numsamples as f64;\n        this.length = numsamples * 4 as usize;\n        this.bufferPointer = __new(this.length, 0);\n    }\n\n    read(): f32 {\n        return load<f32>(this.bufferPointer + this.index);\n    }\n\n    calculateRMS(): f32 {\n        let ndx = this.index;\n        let bufferPointer = this.bufferPointer;\n\n        let leastrecentsample: f64 = load<f32>(bufferPointer + ndx) as f64;\n        if (ndx === 0) {\n            ndx = this.length;\n        }\n        ndx -= 4;\n        let mostrecentsample: f64 = load<f32>(bufferPointer + ndx) as f64;\n\n        let meanSquared: f64 = this.meanSquared;\n        let numSamples: f64 = this.numsamplesf64;\n        meanSquared += ((mostrecentsample * mostrecentsample) / numSamples);\n        meanSquared -= ((leastrecentsample * leastrecentsample) / numSamples);\n        this.meanSquared = meanSquared;\n\n        return Math.sqrt(meanSquared) as f32;\n    }\n\n    getPeakValue(): f32 {\n        let ndx = this.index;\n        if (ndx === 0) {\n            ndx = this.length;\n        }\n        ndx -= 4;\n        let mostrecentsample: f32 = load<f32>(this.bufferPointer + ndx) as f32;\n        if (mostrecentsample < 0) {\n            mostrecentsample = -mostrecentsample;\n        }\n        if (mostrecentsample > this.currentPeak) {\n            this.currentPeak = mostrecentsample;\n            this.currentPeakSamplesToLive = this.numsamples;\n        } else if (this.currentPeakSamplesToLive > 0) {\n            this.currentPeakSamplesToLive--;\n        }\n        if (this.currentPeakSamplesToLive == 0) {\n            this.currentPeak = this.calculatePeakValue();\n        }\n        return this.currentPeak;\n    }\n\n    private calculatePeakValue(): f32 {\n        let peak: f32 = 0.0;\n        for (let i: usize = 0; i < this.length; i += 4) {\n            let value = load<f32>(this.bufferPointer + i);\n            if (value < 0) {\n                value = -value;\n            }\n            if (value > peak) {\n                peak = value;\n                this.currentPeakSamplesToLive = ((i >= this.index) ? (i - this.index) : ((this.length) - this.index) + i) >> 2;\n            }\n        }\n        return peak;\n    }\n\n    write_and_advance(value: f32): void {\n        store<f32>(this.bufferPointer + this.index, value);\n\n        if (this.index === this.length - 4) {\n            this.index = 0;\n        } else {\n            this.index += 4;\n        }\n    }\n}\n\nexport class DelayLineFloat {\n    buffer: StaticArray<f32>;\n    frame: f64 = 0;\n    numframes: f64 = 1;\n    previous: f32;\n    allpass: AllPassFloat = new AllPassFloat();\n\n    constructor(private buffersizeframes: i32) {\n        this.buffer = new StaticArray<f32>(buffersizeframes);\n    }\n\n    read(): f32 {\n        const index = this.frame as i32 % this.buffer.length;\n        return this.allpass.process(this.buffer[index]);\n    }\n\n    reset(): void {\n        this.allpass.previousoutput = 0;\n        this.allpass.previousinput = 0;\n        for (let n = 0; n < this.numframes; n++) {\n            this.buffer[n] = 0;\n        }\n        this.frame = 0;\n    }\n\n    setNumFramesAndClear(numframes: f64): void {\n        this.numframes = Math.floor(numframes);\n        this.allpass.setDelta((numframes - this.numframes) as f32);\n        this.reset();\n    }\n\n    write_and_advance(value: f32): void {\n        const index = ((this.frame++) + this.numframes) as i32 % this.buffer.length;\n        this.buffer[index] = value;\n    }\n}\n","fx/eqband.ts":"import { BiQuadFilter, FilterType, Q_BUTTERWORTH } from \"../synth/biquad\";\nimport { SAMPLERATE } from \"../environment\";\n\nexport class EQBand {\n    lpfilter: BiQuadFilter = new BiQuadFilter();\n    hpfilter: BiQuadFilter = new BiQuadFilter();\n    lpfilter2: BiQuadFilter = new BiQuadFilter();\n    hpfilter2: BiQuadFilter = new BiQuadFilter();\n    \n    \n    constructor(lowfreq: f32, hifreq: f32) {\n        this.lpfilter.update_coeffecients(FilterType.LowPass, SAMPLERATE, hifreq, Q_BUTTERWORTH);\n        this.lpfilter2.update_coeffecients(FilterType.LowPass, SAMPLERATE, hifreq, Q_BUTTERWORTH);\n        this.hpfilter.update_coeffecients(FilterType.HighPass, SAMPLERATE, lowfreq, Q_BUTTERWORTH);\n        this.hpfilter2.update_coeffecients(FilterType.HighPass, SAMPLERATE, lowfreq, Q_BUTTERWORTH);        \n    }\n\n    process(left: f32): f32 {\n        return this.lpfilter2.process(this.lpfilter.process(this.hpfilter2.process(this.hpfilter.process(left))));                \n    }\n}","fx/freeverb.ts":"\n/**\n * Freeverb implementation taken from Rust implementation here:\n * https://github.com/irh/freeverb-rs/blob/master/freeverb/src/freeverb.rs\n */\nimport { Comb } from './comb';\nimport { AllPass } from './allpass';\nimport { SAMPLERATE as SAMPLERATE_f32 } from '../environment';\nimport { StereoSignal } from '../synth/stereosignal.class';\n\nlet SAMPLERATE = SAMPLERATE_f32 as usize;\nconst FIXED_GAIN: f32 = 0.015;\n\nconst SCALE_WET: f32 = 3.0;\nconst SCALE_DAMPENING: f32 = 0.4;\n\nconst SCALE_ROOM: f32 = 0.28;\nconst OFFSET_ROOM: f32 = 0.7;\n\nconst STEREO_SPREAD: usize = 23;\n\nconst COMB_TUNING_L1: usize = 1116;\nconst COMB_TUNING_R1: usize = 1116 + STEREO_SPREAD;\nconst COMB_TUNING_L2: usize = 1188;\nconst COMB_TUNING_R2: usize = 1188 + STEREO_SPREAD;\nconst COMB_TUNING_L3: usize = 1277;\nconst COMB_TUNING_R3: usize = 1277 + STEREO_SPREAD;\nconst COMB_TUNING_L4: usize = 1356;\nconst COMB_TUNING_R4: usize = 1356 + STEREO_SPREAD;\nconst COMB_TUNING_L5: usize = 1422;\nconst COMB_TUNING_R5: usize = 1422 + STEREO_SPREAD;\nconst COMB_TUNING_L6: usize = 1491;\nconst COMB_TUNING_R6: usize = 1491 + STEREO_SPREAD;\nconst COMB_TUNING_L7: usize = 1557;\nconst COMB_TUNING_R7: usize = 1557 + STEREO_SPREAD;\nconst COMB_TUNING_L8: usize = 1617;\nconst COMB_TUNING_R8: usize = 1617 + STEREO_SPREAD;\n\nconst ALLPASS_TUNING_L1: usize = 556;\nconst ALLPASS_TUNING_R1: usize = 556 + STEREO_SPREAD;\nconst ALLPASS_TUNING_L2: usize = 441;\nconst ALLPASS_TUNING_R2: usize = 441 + STEREO_SPREAD;\nconst ALLPASS_TUNING_L3: usize = 341;\nconst ALLPASS_TUNING_R3: usize = 341 + STEREO_SPREAD;\nconst ALLPASS_TUNING_L4: usize = 225;\nconst ALLPASS_TUNING_R4: usize = 225 + STEREO_SPREAD;\n\nfunction adjust_length(length: usize, sr: usize): usize {\n    return ((length as f32) * (sr as f32) / SAMPLERATE_f32) as usize;\n}\n\nexport class Freeverb {    \n    readonly COMB1_L: Comb = new Comb(adjust_length(COMB_TUNING_L1, SAMPLERATE));\n    readonly COMB1_R: Comb = new Comb(adjust_length(COMB_TUNING_L1, SAMPLERATE));\n    readonly COMB2_L: Comb = new Comb(adjust_length(COMB_TUNING_R2, SAMPLERATE));\n    readonly COMB2_R: Comb = new Comb(adjust_length(COMB_TUNING_L2, SAMPLERATE));\n    readonly COMB3_L: Comb = new Comb(adjust_length(COMB_TUNING_R3, SAMPLERATE));\n    readonly COMB3_R: Comb = new Comb(adjust_length(COMB_TUNING_L3, SAMPLERATE));\n    readonly COMB4_L: Comb = new Comb(adjust_length(COMB_TUNING_R4, SAMPLERATE));\n    readonly COMB4_R: Comb = new Comb(adjust_length(COMB_TUNING_L4, SAMPLERATE));\n    readonly COMB5_L: Comb = new Comb(adjust_length(COMB_TUNING_R5, SAMPLERATE));\n    readonly COMB5_R: Comb = new Comb(adjust_length(COMB_TUNING_L5, SAMPLERATE));\n    readonly COMB6_L: Comb = new Comb(adjust_length(COMB_TUNING_R6, SAMPLERATE));\n    readonly COMB6_R: Comb = new Comb(adjust_length(COMB_TUNING_L6, SAMPLERATE));\n    readonly COMB7_L: Comb = new Comb(adjust_length(COMB_TUNING_R7, SAMPLERATE));\n    readonly COMB7_R: Comb = new Comb(adjust_length(COMB_TUNING_L7, SAMPLERATE));\n    readonly COMB8_L: Comb = new Comb(adjust_length(COMB_TUNING_R8, SAMPLERATE));\n    readonly COMB8_R: Comb = new Comb(adjust_length(COMB_TUNING_L8, SAMPLERATE));\n\n    readonly ALL1_L: AllPass = new AllPass(adjust_length(ALLPASS_TUNING_L1, SAMPLERATE));\n    readonly ALL1_R: AllPass = new AllPass(adjust_length(ALLPASS_TUNING_R1, SAMPLERATE));\n    readonly ALL2_L: AllPass = new AllPass(adjust_length(ALLPASS_TUNING_L2, SAMPLERATE));\n    readonly ALL2_R: AllPass = new AllPass(adjust_length(ALLPASS_TUNING_R2, SAMPLERATE));\n    readonly ALL3_L: AllPass = new AllPass(adjust_length(ALLPASS_TUNING_L3, SAMPLERATE));\n    readonly ALL3_R: AllPass = new AllPass(adjust_length(ALLPASS_TUNING_R3, SAMPLERATE));\n    readonly ALL4_L: AllPass = new AllPass(adjust_length(ALLPASS_TUNING_L4, SAMPLERATE));\n    readonly ALL4_R: AllPass = new AllPass(adjust_length(ALLPASS_TUNING_R4, SAMPLERATE));\n\n    wet_gain_left: f32 = 0;\n    wet_gain_right: f32 = 0;\n    \n    wet: f32 = 0;\n    width: f32 = 0;\n    dry: f32 = 0;\n    input_gain: f32 = 0;\n    dampening: f32 = 0;\n    room_size: f32 = 0;\n    frozen: bool = 0;\n\n    constructor() {\n        this.set_wet(1.0);\n        this.set_width(0.5);\n        this.set_dampening(0.5);\n        this.set_room_size(0.7);\n        this.set_frozen(false);        \n    }\n\n    tick(signal: StereoSignal): void {\n        let input_mixed = (signal.left + signal.right) * FIXED_GAIN * this.input_gain;\n\n        let leftoutput:f32 = 0;\n        let rightoutput:f32 = 0;\n\n        leftoutput += this.COMB1_L.tick(input_mixed);\n        rightoutput+= this.COMB1_R.tick(input_mixed);\n        leftoutput += this.COMB2_L.tick(input_mixed);\n        rightoutput+= this.COMB2_R.tick(input_mixed);\n        leftoutput += this.COMB3_L.tick(input_mixed);\n        rightoutput+= this.COMB3_R.tick(input_mixed);\n        leftoutput += this.COMB4_L.tick(input_mixed);\n        rightoutput+= this.COMB4_R.tick(input_mixed);\n        leftoutput += this.COMB5_L.tick(input_mixed);\n        rightoutput+= this.COMB5_R.tick(input_mixed);\n        leftoutput += this.COMB6_L.tick(input_mixed);\n        rightoutput+= this.COMB6_R.tick(input_mixed);\n        leftoutput += this.COMB7_L.tick(input_mixed);\n        rightoutput+= this.COMB7_R.tick(input_mixed);\n        leftoutput += this.COMB8_L.tick(input_mixed);\n        rightoutput+= this.COMB8_R.tick(input_mixed);\n        \n        leftoutput= this.ALL1_L.tick(leftoutput);\n        rightoutput = this.ALL1_R.tick(rightoutput);\n        leftoutput= this.ALL2_L.tick(leftoutput);\n        rightoutput = this.ALL2_R.tick(rightoutput);\n        leftoutput= this.ALL3_L.tick(leftoutput);\n        rightoutput = this.ALL3_R.tick(rightoutput);\n        leftoutput= this.ALL4_L.tick(leftoutput);\n        rightoutput = this.ALL4_R.tick(rightoutput);\n\n        signal.left = leftoutput * this.wet_gain_left +\n                                rightoutput * this.wet_gain_right +\n                                signal.left * this.dry;\n        signal.right = rightoutput * this.wet_gain_left +\n                                leftoutput * this.wet_gain_right +\n                                signal.right * this.dry;        \n    }\n\n    update_combs(): void {\n        let feedback: f32;\n        let dampening: f32;\n\n        if(this.frozen) {\n            feedback =1.0;\n            dampening = 0.0;\n        } else {\n            feedback = this.room_size;\n            dampening = this.dampening;\n        }\n        \n        this.COMB1_L.set_feedback(feedback);\n        this.COMB1_R.set_feedback(feedback);\n        this.COMB1_L.set_dampening(dampening);\n        this.COMB1_R.set_dampening(dampening);\n        this.COMB2_L.set_feedback(feedback);\n        this.COMB2_R.set_feedback(feedback);\n        this.COMB2_L.set_dampening(dampening);\n        this.COMB2_R.set_dampening(dampening);\n        this.COMB3_L.set_feedback(feedback);\n        this.COMB3_R.set_feedback(feedback);\n        this.COMB3_L.set_dampening(dampening);\n        this.COMB3_R.set_dampening(dampening);\n        this.COMB4_L.set_feedback(feedback);\n        this.COMB4_R.set_feedback(feedback);\n        this.COMB4_L.set_dampening(dampening);\n        this.COMB4_R.set_dampening(dampening);\n        this.COMB5_L.set_feedback(feedback);\n        this.COMB5_R.set_feedback(feedback);\n        this.COMB5_L.set_dampening(dampening);\n        this.COMB5_R.set_dampening(dampening);\n        this.COMB6_L.set_feedback(feedback);\n        this.COMB6_R.set_feedback(feedback);\n        this.COMB6_L.set_dampening(dampening);\n        this.COMB6_R.set_dampening(dampening);\n        this.COMB7_L.set_feedback(feedback);\n        this.COMB7_R.set_feedback(feedback);\n        this.COMB7_L.set_dampening(dampening);\n        this.COMB7_R.set_dampening(dampening);\n        this.COMB8_L.set_feedback(feedback);\n        this.COMB8_R.set_feedback(feedback);\n        this.COMB8_L.set_dampening(dampening);\n        this.COMB8_R.set_dampening(dampening);\n    }\n\n    set_dampening(value: f32): void {\n        this.dampening = value * SCALE_DAMPENING;\n        this.update_combs();\n    }\n\n    set_freeze(frozen: bool): void {\n        this.frozen = frozen;\n        this.update_combs();\n    }\n\n    set_wet(value: f32): void {\n        this.wet = value * SCALE_WET;\n        this.update_wet_gains();\n    }\n\n    set_width(value: f32): void {\n        this.width = value;\n        this.update_wet_gains();\n    }\n\n    update_wet_gains(): void {\n        this.wet_gain_left = this.wet * (this.width / 2.0 + 0.5);\n        this.wet_gain_right = this.wet * ((1.0 - this.width) / 2.0);    \n    }\n\n    set_frozen(frozen: bool): void {\n        this.frozen = frozen;\n        this.input_gain = frozen ? 0.0 : 1.0;\n        this.update_combs();\n    }\n\n    set_room_size(value: f32): void {\n        this.room_size = value * SCALE_ROOM + OFFSET_ROOM;\n        this.update_combs();\n    }\n\n    set_dry(value: f32): void {\n        this.dry = value;\n    }\n}\n","fx/limiter.ts":"import { SAMPLERATE } from '../environment';\n\nexport class Limiter {\n    attack: f32 = 0;\n    release: f32 = 0;\n    envelope: f32 = 0;\n\n    constructor(attackMs: f32, releaseMs: f32) {\n        this.attack = Mathf.pow(0.01, 1.0 / (attackMs * SAMPLERATE * 0.001));\n        this.release = Mathf.pow(0.01, 1.0 / (releaseMs * SAMPLERATE * 0.001));\n    }\n\n    process(signal: f32): f32 {\n        const v = Mathf.abs(signal);\n        if (v > this.envelope) {\n            this.envelope = this.attack * (this.envelope - v) + v;\n        } else {\n            this.envelope = this.release * (this.envelope - v) + v;\n        }\n\n        if (this.envelope > 1) {\n            signal /= this.envelope;\n        }\n        return signal;\n    }\n}\n","fx/midsideprocessor.ts":"import { StereoSignal } from \"../synth/stereosignal.class\";\n\nexport class MidSideProcessor {\n  signal: StereoSignal = new StereoSignal();\n\n  constructor(private side_level: f32) {\n\n  }\n\n  process(left: f32, right: f32): void {\n    // Mid-side processing\n    let mid: f32 = (left + right) / 2.0;\n    let side: f32 = (left - right) / 2.0;\n\n    side *= this.side_level;\n    this.signal.left = mid + side;\n    this.signal.right = mid - side;\n  }\n}","fx/monocompressor.ts":"import { DelayLine } from \"./delayline\";\nexport class MonoCompressor {\n    delay: DelayLine;\n\n    gain: f64 = 1.0;\n    targetgain: f64 = 1.0;\n    gainChangePerSample: f64 = 0;\n    delaybuffersamplecount: f64;\n    releasesamplecount: f64;\n\n    constructor(numsamples: usize) {\n        this.delay = new DelayLine(numsamples);\n        this.delaybuffersamplecount = numsamples as f64;\n        this.releasesamplecount = this.delaybuffersamplecount;\n    }\n\n    setRelaseSampleCount(releasesamplecount: f64): void {\n        this.releasesamplecount = releasesamplecount;\n    }\n\n    process(signal: f32, threshold: f32, makeupgain: f32): f32 {\n        this.delay.write_and_advance(signal);\n\n        let currentTargetGain: f64 = this.targetgain;\n        let currentGain: f64 = this.gain;\n\n        let peak: f64 = this.delay.getPeakValue();\n\n        if(peak > threshold) {\n            let targetGain = threshold / peak;\n\n            if(targetGain < currentTargetGain) {\n              currentTargetGain = targetGain;\n              this.targetgain = targetGain;\n\n              let newGainChangePerSample = (currentTargetGain - currentGain) / this.delaybuffersamplecount;\n        \n              if(newGainChangePerSample < this.gainChangePerSample) {\n                  this.gainChangePerSample = newGainChangePerSample;\n              }\n            }   \n        } else if(currentTargetGain < 1.0) {\n            currentTargetGain = 1.0;\n            this.targetgain = currentTargetGain;            \n            this.gainChangePerSample = (currentTargetGain - currentGain) / this.releasesamplecount;\n        }\n\n        let gainChangePerSample: f64 = this.gainChangePerSample;\n        if((gainChangePerSample < 0 && currentTargetGain < currentGain) ||\n            (gainChangePerSample > 0 && currentTargetGain > currentGain)) {\n            currentGain += gainChangePerSample;\n            this.gain = currentGain;\n        }\n\n        return this.delay.read() * currentGain as f32 * makeupgain;\n    }\n}\n\nexport class StereoCompressor {\n    leftCompressor: MonoCompressor;\n    rightCompressor: MonoCompressor;\n\n    resultSignal: StereoSignal = new StereoSignal();\n    \n    constructor(numsamples: usize) {\n        this.leftCompressor = new MonoCompressor(numsamples);\n        this.rightCompressor = new MonoCompressor(numsamples);\n    }\n\n    process(left: f32, right: f32, threshold: f32, makeupgain: f32): void {\n        this.resultSignal.left = this.leftCompressor.process(left, threshold, makeupgain);\n      \tthis.resultSignal.right = this.rightCompressor.process(right, threshold, makeupgain);        \n    }\n}\n","fx/multibandeq.ts":"import { EQBand } from './eqband';\nexport class MultiBandEQ {\n    bands: StaticArray<EQBand>;\n\n    constructor(freqs: f32[]) {\n        this.bands = new StaticArray<EQBand>(freqs.length - 1);\n        for (let n = 1; n < freqs.length; n++) {\n            this.bands[n - 1] = new EQBand(freqs[n - 1], freqs[n]);\n        }\n    }\n\n\n    process(signal: f32, levels: f32[]): f32 {\n        let ret: f32 = 0;\n        const numbands = this.bands.length;\n        for (let n = 0; n < numbands; n++) {\n            ret += this.bands[n].process(signal) * levels[n];\n        }\n        return ret;\n    }\n}\n","fx/stereocompressor.ts":"import { StereoSignal } from \"../synth/stereosignal.class\";\nimport { MonoCompressor } from \"./monocompressor\";\n\nexport class StereoCompressor {\n    leftCompressor: MonoCompressor;\n    rightCompressor: MonoCompressor;\n\n    resultSignal: StereoSignal = new StereoSignal();\n    \n    constructor(numsamples: usize) {\n        this.leftCompressor = new MonoCompressor(numsamples);\n        this.rightCompressor = new MonoCompressor(numsamples);\n    }\n\n    process(left: f32, right: f32, threshold: f32, makeupgain: f32): void {\n        this.resultSignal.left = this.leftCompressor.process(left, threshold, makeupgain);\n      \tthis.resultSignal.right = this.rightCompressor.process(right, threshold, makeupgain);        \n    }\n}\n","fx/tribandeq.ts":"import { EQBand } from \"./eqband\";\n\nexport class TriBandEQ {\n    \n    lowerband: EQBand;\n    midband: EQBand;\n    hiband: EQBand;\n\n    constructor(low: f32, midlo: f32, midhi: f32, high: f32) {\n        this.lowerband = new EQBand(low, midlo);\n        this.midband = new EQBand(midlo, midhi);\n        this.hiband = new EQBand(midhi, high);\n    }\n\n    process(signal: f32, lolevel: f32, midlevel: f32, hilevel: f32): f32 {\n        return this.lowerband.process(signal) * lolevel +\n                this.midband.process(signal) * midlevel +\n                this.hiband.process(signal) * hilevel;\n    }\n}","fx/tribandstereocompressor.ts":"import { EQBand } from \"./eqband\";\nimport { StereoSignal } from \"../synth/stereosignal.class\";\nimport { StereoCompressor } from \"./stereocompressor\";\nimport { SAMPLERATE } from \"../environment\";\n\nexport class TriBandStereoCompressor {\n    lowerbandl: EQBand;    \n    midbandl: EQBand;    \n    hibandl: EQBand;\n    \n    lowerbandr: EQBand;    \n    midbandr: EQBand;    \n    hibandr: EQBand;\n    \n    compressorLow: StereoCompressor;\n    compressorMid: StereoCompressor;\n    compressorHigh: StereoCompressor;\n\n    stereosignal: StereoSignal = new StereoSignal();\n\n    constructor(low: f32, midlo: f32, midhi: f32, high: f32, compressor_delay: f32 = 0.2) {\n        this.compressorLow = new StereoCompressor((SAMPLERATE * compressor_delay) as usize);\n        this.compressorMid = new StereoCompressor((SAMPLERATE * compressor_delay) as usize);\n        this.compressorHigh = new StereoCompressor((SAMPLERATE * compressor_delay) as usize);\n\n        this.lowerbandl = new EQBand(low, midlo);\n        this.lowerbandr = new EQBand(low, midlo);\n        \n        this.midbandl = new EQBand(midlo, midhi);\n        this.midbandr = new EQBand(midlo, midhi);\n        \n        this.hibandl = new EQBand(midhi, high);\n        this.hibandr = new EQBand(midhi, high);\n    }\n\n    process(left: f32, right: f32, \n        lolevel: f32, \n        midlevel: f32, \n        hilevel: f32,\n        lomakeupgain: f32,\n        midmakeupgain: f32,\n        himakeupgain: f32): void {\n        let lowleft = this.lowerbandl.process(left);\n        let midleft = this.midbandl.process(left);\n        let hileft = this.hibandl.process(left);\n\n        let lowright = this.lowerbandr.process(right);\n        let midright = this.midbandr.process(right);\n        let hiright = this.hibandr.process(right);\n\n        this.compressorLow.process(lowleft,lowright,lolevel,lomakeupgain);\n        this.compressorMid.process(midleft,midright,midlevel,midmakeupgain);\n        this.compressorHigh.process(hileft,hiright,hilevel,himakeupgain);\n        \n        this.stereosignal.left = this.compressorLow.resultSignal.left + this.compressorMid.resultSignal.left + this.compressorHigh.resultSignal.left;\n        this.stereosignal.right = this.compressorLow.resultSignal.right + this.compressorMid.resultSignal.right + this.compressorHigh.resultSignal.right;\n    }\n}","index.ts":"// The entry file of the synth WebAssembly module.\n\n// --- Replace with your own mix implementation here\nimport { mixernext, setChannelValue, PATTERN_SIZE_SHIFT, BEATS_PER_PATTERN_SHIFT } from './mixes/newyear.mix';\nexport { setChannelValue } from './mixes/newyear.mix';\n// -------------------------------------------------\n\nimport { SAMPLERATE } from './environment';\n\nconst PATTERN_LENGTH: f32 = (1 << PATTERN_SIZE_SHIFT) as f32;\n\nlet NUM_INSTRUMENTS: i32;\n\nlet holdChannelValuesBufferPtr: usize;\nlet currentChannelValuesBufferPtr: usize;\nlet patternsPtr: usize;\nlet instrumentPatternListsPtr: usize;\nlet sampleBufferPtr: usize;\nlet sampleBufferFrames: usize;\nlet songlength: usize = 0;\n\nlet patternIndexf64: f64 = 0;\nlet patternIndex: usize = 0;  \nlet patternNoteIndex: usize = -1;\n\nlet tick: f64 = 0;\nlet ticksPerBeat: f32 = (1 << PATTERN_SIZE_SHIFT >> BEATS_PER_PATTERN_SHIFT) as f32;\nlet bpm: f32 = 120;\n\nlet ticksPerSec = ticksPerBeat * bpm / 60;\nlet ticksPerSample = ticksPerSec / SAMPLERATE;\n\nlet playOrPause: boolean = true;\n\nexport function setBPM(BPM: f32): void {\n  bpm = BPM;\n  ticksPerSec = ticksPerBeat * BPM / 60;\n  ticksPerSample = ticksPerSec / SAMPLERATE;\n}\n\nexport function setTick(newtick: f64): void {\n  tick = newtick;\n}\n\nexport function getTick(): f64 {\n  return tick;\n}\n\nexport function setMilliSecondPosition(millis: f64): void {\n  let newtick: f64 = millis * ticksPerSec / 1000;\n  let ticklength = songlength as f64 * PATTERN_LENGTH;\n\n  newtick -= (floor(newtick / ticklength) * ticklength);\n  if(abs(newtick - tick) > 1) {\n    tick = newtick;\n  }\n}\n\nexport function getPatternIndex(): usize {\n  return patternIndex;\n}\n\nexport function getPatternNoteIndex(): usize {\n  return patternNoteIndex;\n}\n\nexport function toggleSongPlay(status: boolean): void {\n  if(!status && playOrPause) {\n    for(let n=0;n<NUM_INSTRUMENTS;n++) {    \n      setChannelValue(n, 0 as f32);\n    }\n  }\n  playOrPause = status;\n}\n\nexport function isPlaying(): boolean {\n  return playOrPause;\n}\n\nfunction updateInstrumentNotes(): void {\n  if(!playOrPause) {\n    return;\n  }\n  let songlengthf64: f64 = songlength as f64;\n\n  if((tick / PATTERN_LENGTH) > songlengthf64) {\n    tick -= (songlengthf64 * PATTERN_LENGTH);    \n  }\n\n  patternIndexf64 = (tick / PATTERN_LENGTH) as f64;\n  patternIndex = patternIndexf64 as usize;  \n  let newPatternNoteIndex: usize = ((patternIndexf64 - (patternIndex as f64)) * PATTERN_LENGTH) as usize;\n\n  if(newPatternNoteIndex===patternNoteIndex) {\n    return;\n  }\n\n  patternNoteIndex = newPatternNoteIndex;\n  \n  for(let n=0;n<NUM_INSTRUMENTS;n++) {    \n    let instrumentPatternIndex = load<u8>(instrumentPatternListsPtr +\n        n * songlength +\n        patternIndex) as usize;\n    \n    let channelValue: f32 = load<u8>(patternsPtr + (instrumentPatternIndex << PATTERN_SIZE_SHIFT)\n        + patternNoteIndex) as f32;\n    \n    let holdChannelValue: f32 = load<f32>(holdChannelValuesBufferPtr + n * 4);\n    if(holdChannelValue > 0 && channelValue !== 1 && channelValue !== holdChannelValue) {\n      // Hold value\n      channelValue = 1;\n      store<u8>(patternsPtr + (instrumentPatternIndex << PATTERN_SIZE_SHIFT)\n        + patternNoteIndex, 1 as u8);\n    }\n\n    // 1 means HOLD value - no change to the visualizer     \n    if(channelValue !== 1) {   \n      // For external visualizer to monitor channel values currently been played by the sequencer            \n      store<f32>(currentChannelValuesBufferPtr + n*4, channelValue);\n      setChannelValue(n, channelValue);\n    }    \n  }\n}\n\nexport function getHoldChannelValuesBufferPtr(): usize {\n  return holdChannelValuesBufferPtr;\n}\n\nexport function recordChannelValue(channel: usize, value: f32): void {\n  store<f32>(holdChannelValuesBufferPtr + channel * 4, value);\n  setChannelValue(channel, value);\n}\n\nexport function setPatternsPtr(ptr: usize): void {\n  patternsPtr = ptr;\n}\n\nexport function allocatePatterns(numpatterns: i32): usize {\n  patternsPtr = __new(numpatterns << PATTERN_SIZE_SHIFT, idof<Array<u32>>());\n  return patternsPtr;\n}\n\nexport function setInstrumentPatternListPtr(ptr: usize, songpatternslength: i32, numinstruments: i32): void {\n  instrumentPatternListsPtr = ptr;\n  NUM_INSTRUMENTS = numinstruments;\n  songlength = songpatternslength;\n  \n  currentChannelValuesBufferPtr = __new(NUM_INSTRUMENTS * 4, idof<Array<f32>>());\n  holdChannelValuesBufferPtr = __new(NUM_INSTRUMENTS * 4, idof<Array<f32>>());\n}\n\nexport function allocateInstrumentPatternList(songpatternslength: i32, numinstruments: i32): usize {\n  NUM_INSTRUMENTS = numinstruments;\n  songlength = songpatternslength;\n  \n  currentChannelValuesBufferPtr = __new(NUM_INSTRUMENTS * 4, idof<Array<f32>>());\n  holdChannelValuesBufferPtr = __new(NUM_INSTRUMENTS * 4, idof<Array<f32>>());\n  instrumentPatternListsPtr = __new(songpatternslength * NUM_INSTRUMENTS, idof<Array<u32>>());\n\n  return instrumentPatternListsPtr;\n}\n\nexport function allocateSampleBuffer(frames: usize): usize {\n  sampleBufferFrames = frames;\n  sampleBufferPtr = __new(frames * 2 * 4, idof<Array<f32>>());\n  return sampleBufferPtr;\n}\n\nexport function getCurrentChannelValuesBufferPtr(): usize {\n  return currentChannelValuesBufferPtr;\n}\n\nexport function fillSampleBuffer(): void {      \n  updateInstrumentNotes();\n  for(let n: usize = 0;n<sampleBufferFrames;n++) {   \n    let sampleNdx: usize = n << 2; \n    mixernext(sampleBufferPtr + sampleNdx, sampleBufferPtr + sampleNdx + (sampleBufferFrames << 2));    \n    tick += ticksPerSample;\n  }\n}\n\nexport function fillSampleBufferInterleaved(): void {      \n  updateInstrumentNotes();\n  for(let n: usize = 0;n<sampleBufferFrames;n++) {   \n    let sampleNdx: usize = n << 3; \n    mixernext(sampleBufferPtr + sampleNdx, sampleBufferPtr + sampleNdx + 4);    \n    tick += ticksPerSample;\n  }\n}","instruments/bass/deepbass.ts":"\nimport { SAMPLERATE } from '../../environment';\n\nimport { StereoSignal } from '../../synth/stereosignal.class';\nimport { Envelope } from '../../synth/envelope.class';\nimport { SawOscillator } from '../../synth/sawoscillator.class';\n\nimport { BiQuadFilter, FilterType, Q_BUTTERWORTH } from '../../synth/biquad';\nimport { notefreq } from '../../synth/note';\n\nimport { Instrument } from '../instrument.class';\n\nexport class DeepBass extends Instrument {\n    readonly envelope: Envelope = new Envelope(0.01, 0.2, 0.70, 0.2);\n    readonly filterenv: Envelope = new Envelope(0.01, 0.4, 0.0, 0.2);\n    readonly sawoscillator: SawOscillator = new SawOscillator();\n    readonly sawoscillator2: SawOscillator = new SawOscillator();\n    readonly filter: BiQuadFilter = new BiQuadFilter();\n    readonly hpfilterl: BiQuadFilter = new BiQuadFilter();\n    readonly hpfilterr: BiQuadFilter = new BiQuadFilter();\n    \n    readonly lpfilterl: BiQuadFilter = new BiQuadFilter();\n    readonly lpfilterr: BiQuadFilter = new BiQuadFilter();\n\n    constructor() {\n        super();\n        this.hpfilterl.update_coeffecients(FilterType.HighPass, SAMPLERATE, 35, Q_BUTTERWORTH);\n        this.hpfilterr.update_coeffecients(FilterType.HighPass, SAMPLERATE, 35, Q_BUTTERWORTH);   \n    }\n\n    set note(note: f32) {        \n        if(note > 1) {            \n            this.sawoscillator.frequency = notefreq(note + 0.1) / 2;\n            this.sawoscillator2.frequency = notefreq(note - 0.1) / 2;\n            this.envelope.attack();   \n            this.filterenv.attack();                     \n        } else {\n            this.envelope.release();\n            this.filterenv.release();\n        }\n    }\n\n    next(): void {        \n        let env: f32 = this.envelope.next();\n        if(env === 0) {\n            this.signal.clear();\n            return;\n        }\n        // this.signal.clear();\n        let filterenv = this.filterenv.next();\n        this.signal.left *= 0.9 * env; // feedback\n        this.signal.right *= 0.9 * env; // feedback\n        this.lpfilterl.update_coeffecients(FilterType.LowPass, SAMPLERATE, 300 + (100 * filterenv), Q_BUTTERWORTH);\n        this.lpfilterr.update_coeffecients(FilterType.LowPass, SAMPLERATE, 300 + (100 * filterenv), Q_BUTTERWORTH);\n        \n        this.signal.addMonoSignal(\n            this.lpfilterl.process(this.hpfilterl.process(this.sawoscillator.next() * env)), 0.3, 0.3\n        );\n        this.signal.addMonoSignal(\n            this.lpfilterr.process(this.hpfilterr.process(this.sawoscillator2.next() * env)), 0.3, 0.7\n        );\n    } \n}\n  ","instruments/bass/sawbass2.class.ts":"\nimport { SAMPLERATE } from '../../environment';\n\nimport { StereoSignal } from '../../synth/stereosignal.class';\nimport { Envelope } from '../../synth/envelope.class';\nimport { SawOscillator } from '../../synth/sawoscillator.class';\n\nimport { BiQuadFilter, FilterType, Q_BUTTERWORTH } from '../../synth/biquad';\nimport { notefreq } from '../../synth/note';\n\n\nexport class SawBass2 {\n    private _note: f32;\n    readonly envelope: Envelope = new Envelope(0.01, 0.2, 0.8, 0.2);\n    readonly filterenv: Envelope = new Envelope(0.01, 0.4, 0.0, 0.2);\n    readonly sawoscillator: SawOscillator = new SawOscillator();\n    readonly sawoscillator2: SawOscillator = new SawOscillator();\n    readonly filter: BiQuadFilter = new BiQuadFilter();\n    readonly hpfilterl: BiQuadFilter = new BiQuadFilter();\n    readonly hpfilterr: BiQuadFilter = new BiQuadFilter();\n    \n    readonly lpfilterl: BiQuadFilter = new BiQuadFilter();\n    readonly lpfilterr: BiQuadFilter = new BiQuadFilter();\n    \n    readonly signal: StereoSignal = new StereoSignal();\n\n    constructor() {\n        this.hpfilterl.update_coeffecients(FilterType.HighPass, SAMPLERATE, 35, Q_BUTTERWORTH);\n        this.hpfilterr.update_coeffecients(FilterType.HighPass, SAMPLERATE, 35, Q_BUTTERWORTH);\n        \n    }\n\n    set note(note: f32) {        \n        if(note > 1) {            \n            this.sawoscillator.frequency = notefreq(note + 0.1);\n            this.sawoscillator2.frequency = notefreq(note - 0.1);\n            this.envelope.attack();   \n            this.filterenv.attack();                     \n        } else {\n            this.envelope.release();\n            this.filterenv.release();\n        }\n        this._note = note;\n    }\n\n    get note(): f32 {\n        return this._note;\n    }\n\n    next(): void {        \n        let env: f32 = this.envelope.next();\n        if(env === 0) {\n            this.signal.clear();\n            return;\n        }\n        // this.signal.clear();\n        let filterenv = this.filterenv.next();\n        this.signal.left /= 1.03; // feedback\n        this.signal.right /= 1.03; // feedback\n        this.lpfilterl.update_coeffecients(FilterType.LowPass, SAMPLERATE, 300 + (8000 * filterenv), Q_BUTTERWORTH);\n        this.lpfilterr.update_coeffecients(FilterType.LowPass, SAMPLERATE, 300 + (8000 * filterenv), Q_BUTTERWORTH);\n        \n        this.signal.addMonoSignal(\n            this.lpfilterl.process(this.hpfilterl.process(this.sawoscillator.next() * env)), 0.3, 0.3\n        );\n        this.signal.addMonoSignal(\n            this.lpfilterr.process(this.hpfilterr.process(this.sawoscillator2.next() * env)), 0.3, 0.7\n        );\n    } \n}\n  ","instruments/bass/sawbass3.ts":"\nimport { SAMPLERATE } from '../../environment';\n\nimport { StereoSignal } from '../../synth/stereosignal.class';\nimport { Envelope } from '../../synth/envelope.class';\nimport { SawOscillator } from '../../synth/sawoscillator.class';\n\nimport { BiQuadFilter, FilterType, Q_BUTTERWORTH } from '../../synth/biquad';\nimport { notefreq } from '../../synth/note';\nimport { BandPass } from '../../fx/bandpass';\n\n\nexport class SawBass3 {\n    private _note: f32;\n    readonly envelope: Envelope = new Envelope(0.01, 0.3, 0.8, 0.2);\n    readonly filterenv: Envelope = new Envelope(0.01, 0.2, 0.1, 0.2);\n    readonly sawoscillator: SawOscillator = new SawOscillator();\n    \n    readonly filter: BiQuadFilter = new BiQuadFilter();\n   \n    readonly lpfilter: BiQuadFilter = new BiQuadFilter();\n    readonly band1: BandPass = new BandPass(1000, 2000);\n    readonly signal: StereoSignal = new StereoSignal();\n\n    constructor() {\n        \n        \n    }\n\n    set note(note: f32) {        \n        if(note > 1) {            \n            this.sawoscillator.frequency = notefreq(note);\n            \n            this.envelope.attack();   \n            this.filterenv.attack();                     \n        } else {\n            this.envelope.release();\n            this.filterenv.release();\n        }\n        this._note = note;\n    }\n\n    get note(): f32 {\n        return this._note;\n    }\n\n    next(): void {        \n        let env: f32 = this.envelope.next();\n        if(env === 0) {\n            this.signal.clear();\n            return;\n        }\n        \n        let filterenv = this.filterenv.next();\n        \n        let signal = this.sawoscillator.next();\n        signal *= env;\n        \n        this.lpfilter.update_coeffecients(FilterType.LowPass, SAMPLERATE,\n                this.sawoscillator.frequency + (16 * this.sawoscillator.frequency * filterenv), Q_BUTTERWORTH);\n    \n        const band1freq = this.sawoscillator.frequency * 4;\n        this.band1.update_frequencies(band1freq, band1freq + env * this.sawoscillator.frequency);\n\n        let band1 = this.band1.process(signal);\n        signal = this.lpfilter.process(signal);\n        \n        this.signal.left = signal * 2 + band1;        \n        this.signal.right = signal * 2 - band1;\n        \n    } \n}\n  ","instruments/drivelead.class.ts":"\nimport { SAMPLERATE } from '../environment';\nimport { SineOscillator } from '../synth/sineoscillator.class';\nimport { StereoSignal } from '../synth/stereosignal.class';\nimport { Envelope } from '../synth/envelope.class';\nimport { SawOscillator } from '../synth/sawoscillator.class';\nimport { Noise } from '../synth/noise.class';\nimport { WaveShaper } from '../synth/shaper';\nimport { notefreq } from '../synth/note';\n\n\nexport class DriveLead {\n    private _note: f32;\n    readonly envelope: Envelope = new Envelope(0.1, 1.0, 0.6, 0.2);\n    readonly sawoscillatorl: SawOscillator = new SawOscillator();\n    readonly sawoscillatorr: SawOscillator = new SawOscillator();\n    readonly shaper: WaveShaper = new WaveShaper();\n    readonly signal: StereoSignal = new StereoSignal();\n    readonly lfoenvelope: Envelope = new Envelope(1.0, 0, 1.0, 0.1);\n    readonly lfo: SineOscillator = new SineOscillator();\n    baseFrequency : f32;\n    pitchbend: f32 = 0;\n\n    set note(note: f32) {        \n        if(note > 1) {   \n            this.shaper.drive = 0.5;         \n            this.baseFrequency = notefreq(note);\n            this.lfo.frequency = 8;\n            this.envelope.attack();    \n            this.lfoenvelope.attack();                    \n            this._note = note;\n        } else {\n            this.envelope.release();\n            this.lfoenvelope.release();\n        }\n        \n    }\n\n    get note(): f32 {\n        return this._note;\n    }\n\n    setPitchbend(bend: f32): void {\n        this.pitchbend = bend;        \n    }\n\n    next(): void {        \n        let env: f32 = this.envelope.next();\n        if(env===0) {\n            this.signal.clear();\n            return;\n        }\n        \n        const pitchbend: f32 = this.pitchbend;\n        if (Math.abs(pitchbend) > 0.01) {\n            // Simple pitchbend that always will return to base note\n            this.baseFrequency = notefreq(this._note + pitchbend);\n            this.pitchbend = pitchbend * 0.9999;\n        } else if(pitchbend !==0 ) {\n            this.pitchbend = 0;\n            this.baseFrequency = notefreq(this._note);\n        }\n        \n        let lfo: f32 = this.lfo.next() * 3 * this.lfoenvelope.next();\n        this.sawoscillatorl.frequency = this.baseFrequency + lfo + 0.5;\n        this.sawoscillatorr.frequency = this.baseFrequency + lfo - 0.5;\n        \n        let left = env* this.sawoscillatorl.next() + this.signal.right * 0.5;\n        left = this.shaper.process(left);\n        \n        let right = env* this.sawoscillatorr.next() + this.signal.left * 0.5;\n        right = this.shaper.process(right);\n        \n        this.signal.left = left * 0.5 + right;\n        this.signal.right = right * 0.5 + left;  \n    } \n}\n  ","instruments/drums/kick2.class.ts":"\nimport { StereoSignal } from '../../synth/stereosignal.class';\nimport { Envelope } from '../../synth/envelope.class';\nimport { Noise } from '../../synth/noise.class';\nimport { BandPass } from '../../fx/bandpass';\nimport { Instrument } from '../instrument.class';\n\nexport class Kick2 extends Instrument {\n    private velocity: f32;\n    \n    readonly noise: Noise = new Noise();\n    \n    readonly env2: Envelope = new Envelope(0.001, 0.01, 0.0, 1);\n    readonly bp2: BandPass = new BandPass(4000, 5000);    \n    \n    readonly env3: Envelope = new Envelope(0.001, 0.1, 0.05, 0.1);\n    readonly bp3: BandPass = new BandPass(10, 100);\n\n    set note(note: f32) {        \n        if(note > 1) {            \n            this.velocity = note / 16;    \n            this.env2.attack();        \n            this.env3.attack();  \n        } else {\n            \n            this.env2.release();            \n            this.env3.release();            \n        }\n    }\n\n    next(): void {\n        let env2: f32 = this.env2.next();\n        let env3: f32 = this.env3.next();\n                \n        let osc: f32 = this.noise.next();\n        \n        \n        let sig2 = this.bp2.process(osc) * env2 ;\n        let sig3 = this.bp3.process(osc) * env3 * 8;\n\n        this.signal.left = this.velocity * (-sig2  + sig3);\n        this.signal.right = this.velocity * ( + sig2 - sig3);        \n    } \n}\n  ","instruments/drums/rimshot.class.ts":"\nimport { SAMPLERATE } from '../../environment';\nimport { StereoSignal } from '../../synth/stereosignal.class';\nimport { Envelope } from '../../synth/envelope.class';\nimport { SawOscillator } from '../../synth/sawoscillator.class';\nimport { BiQuadFilter, FilterType, Q_BUTTERWORTH } from '../../synth/biquad';\nimport { Noise } from '../../synth/noise.class';\nimport { BandPass } from '../../fx/bandpass';\n\nexport class Rimshot {\n    private _note: f32;\n    private velocity: f32;\n    \n    readonly noise: Noise = new Noise();\n    readonly env1: Envelope = new Envelope(0.001, 1.0, 0.8, 0.3);\n    readonly bp1: BandPass = new BandPass(200, 350);\n    readonly env2: Envelope = new Envelope(0.001, 0.08, 0.06, 1);\n    readonly bp2: BandPass = new BandPass(3000, 7000);    \n    \n    readonly env3: Envelope = new Envelope(0.001, 0.05, 0.01, 0.1);\n    readonly bp3: BandPass = new BandPass(10, 150);    \n    \n    readonly signal: StereoSignal = new StereoSignal();\n\n    constructor() {\n       \n    }\n\n    set note(note: f32) {        \n        if(note > 1) {            \n            this.velocity = note / 16;    \n            this.env1.attack();           \n            this.env2.attack();        \n            this.env3.attack();  \n        } else {\n            this.env1.release();\n            this.env2.release();            \n            this.env3.release();            \n        }\n        this._note = note;\n    }\n\n    get note(): f32 {\n        return this._note;\n    }\n\n    next(): void {        \n        let env1: f32 = this.env1.next();\n        let env2: f32 = this.env2.next();\n        let env3: f32 = this.env3.next();\n                \n        let osc: f32 = this.noise.next();\n        \n        let sig1 = this.bp1.process(osc) * env1;\n        let sig2 = this.bp2.process(osc) * env2 * 2;\n        let sig3 = this.bp3.process(osc) * env3 * 16;\n\n        this.signal.left = this.velocity * (sig1 + sig2 * 0.8 + sig3);\n        this.signal.right = this.velocity * (sig1 * 0.8 + sig2 + sig3);\n        \n        \n    } \n}\n  ","instruments/drums/snare2.class.ts":"\nimport { SAMPLERATE } from '../../environment';\nimport { StereoSignal } from '../../synth/stereosignal.class';\nimport { Envelope } from '../../synth/envelope.class';\nimport { SawOscillator } from '../../synth/sawoscillator.class';\nimport { BiQuadFilter, FilterType, Q_BUTTERWORTH } from '../../synth/biquad';\nimport { Noise } from '../../synth/noise.class';\nimport { BandPass } from '../../fx/bandpass';\n\nexport class Snare2 {\n    private _note: f32;\n    private velocity: f32;\n    \n    readonly noise: Noise = new Noise();\n    readonly env1: Envelope = new Envelope(0.001, 1.0, 0.8, 0.3);\n    readonly bp1: BandPass = new BandPass(200, 350);\n    readonly env2: Envelope = new Envelope(0.001, 0.08, 0.06, 0.5);\n    readonly bp2: BandPass = new BandPass(3000, 7000);    \n    \n    readonly env3: Envelope = new Envelope(0.001, 0.05, 0.01, 0.1);\n    readonly bp3: BandPass = new BandPass(10, 150);    \n    \n    readonly signal: StereoSignal = new StereoSignal();\n\n    constructor() {\n       \n    }\n\n    set note(note: f32) {        \n        if(note > 1) {            \n            this.velocity = note / 16;    \n            this.env1.attack();           \n            this.env2.attack();        \n            this.env3.attack();  \n        } else {\n            this.env1.release();\n            this.env2.release();            \n            this.env3.release();            \n        }\n        this._note = note;\n    }\n\n    get note(): f32 {\n        return this._note;\n    }\n\n    next(): void {        \n        let env1: f32 = this.env1.next();\n        let env2: f32 = this.env2.next();\n        let env3: f32 = this.env3.next();\n                \n        let osc: f32 = this.noise.next();\n        \n        let sig1 = this.bp1.process(osc) * env1 * 6;\n        let sig2 = this.bp2.process(osc) * env2 * 2;\n        let sig3 = this.bp3.process(osc) * env3 * 4;\n\n        this.signal.left = this.velocity * (sig1 + sig2 * 0.8 + sig3);\n        this.signal.right = this.velocity * (sig1 * 0.8 + sig2 + sig3);\n        \n        \n    } \n}\n  ","instruments/hihat.class.ts":"\nimport { SAMPLERATE } from '../environment';\nimport { StereoSignal } from '../synth/stereosignal.class';\nimport { Envelope } from '../synth/envelope.class';\nimport { BiQuadFilter, FilterType, Q_BUTTERWORTH } from '../synth/biquad';\nimport { Noise } from '../synth/noise.class';\n\nexport class Hihat {\n    private _note: f32;\n    private velocity: f32;\n\n    readonly envelope: Envelope = new Envelope(0.0, 0.08, 0, 0.1);    \n    readonly noise: Noise = new Noise();\n    \n    readonly filter: BiQuadFilter = new BiQuadFilter();\n    readonly signal: StereoSignal = new StereoSignal();\n\n    set note(note: f32) {        \n        if(note > 1) {        \n            this.velocity = note / 32;    \n            this.envelope.attack();           \n        } else {\n            this.envelope.release();\n        }\n        this._note = note;\n    }\n\n    get note(): f32 {\n        return this._note;\n    }\n\n    next(): void {        \n        let env: f32 = this.envelope.next();   \n        if(env === 0) {\n            this.signal.clear();\n            return;\n        }     \n        let osc: f32 = this.noise.next();        \n        let signal = this.velocity * 2 * env * osc;\n        \n        this.filter.update_coeffecients(FilterType.HighPass, SAMPLERATE, \n            10000 + 2000 * env, Q_BUTTERWORTH);\n\n        signal = this.filter.process(signal);\n\n        this.signal.left = signal;\n        this.signal.right = signal;\n    } \n}\n  ","instruments/instrument.class.ts":"import { StereoSignal } from \"../synth/stereosignal.class\";\n\nexport abstract class Instrument {\n    abstract set note(note: f32);\n    readonly signal: StereoSignal = new StereoSignal();\n    abstract next(): void;\n}","instruments/kick.class.ts":"\nimport { SAMPLERATE } from '../environment';\nimport { StereoSignal } from '../synth/stereosignal.class';\nimport { Envelope } from '../synth/envelope.class';\nimport { SawOscillator } from '../synth/sawoscillator.class';\nimport { BiQuadFilter, FilterType, Q_BUTTERWORTH } from '../synth/biquad';\nimport { Noise } from '../synth/noise.class';\n\n\n\nexport class Kick {\n    private _note: f32;\n    private velocity: f32;\n    readonly envelope: Envelope = new Envelope(0.0, 0.2, 0, 0.2);\n    readonly filterenvelope: Envelope = new Envelope(0.0, 0.05, 0.05, 0.1);\n    readonly sawoscillator: SawOscillator = new SawOscillator();\n    readonly noise: Noise = new Noise();\n    \n    readonly filter: BiQuadFilter = new BiQuadFilter();\n    readonly signal: StereoSignal = new StereoSignal();\n\n    set note(note: f32) {        \n        if(note > 1) {            \n            this.sawoscillator.frequency = 150;\n            this.velocity = note / 16;   \n            this.envelope.attack();           \n            this.filterenvelope.attack();             \n        } else {\n            this.envelope.release();\n            this.filterenvelope.release();\n        }\n        this._note = note;\n    }\n\n    get note(): f32 {\n        return this._note;\n    }\n\n    next(): void {        \n        let env: f32 = this.envelope.next();\n        if(env === 0) {\n            this.signal.clear();\n            return;\n        }\n        this.sawoscillator.frequency = 20.0 + (env * 150.0);\n        \n        this.filter.update_coeffecients(FilterType.LowPass, SAMPLERATE, \n            40 + (this.filterenvelope.next() * 2000), 0.2);\n\n        let osc1: f32 = this.envelope.next() * this.velocity * this.sawoscillator.next() * 0.8 + this.noise.next();\n\n        osc1 = this.filter.process(osc1);\n        \n        this.signal.left = env * osc1;\n        this.signal.right = env * osc1;\n    } \n}\n  ","instruments/lead/brassy.ts":"\nimport { SAMPLERATE } from '../../environment';\nimport { StereoSignal } from '../../synth/stereosignal.class';\nimport { Envelope } from '../../synth/envelope.class';\n\nimport { BiQuadFilter, FilterType, Q_BUTTERWORTH } from '../../synth/biquad';\n\nimport { SineOscillator } from '../../synth/sineoscillator.class';\nimport { notefreq } from '../../synth/note';\nimport { SawOscillator } from '../../synth/sawoscillator.class';\n\nexport class BrassyLead {\n    private _note: f32;\n    \n    readonly osc: SineOscillator = new SineOscillator();\n    readonly osc2: SawOscillator = new SawOscillator();\n    \n    readonly env1: Envelope = new Envelope(0.01, 0.1, 0.4, 0.3);\n    \n    readonly filterenv: Envelope = new Envelope(0.01, 0.1, 0.1, 0.3);\n    \n    readonly lopass: BiQuadFilter = new BiQuadFilter();\n    readonly signal: StereoSignal = new StereoSignal();\n\n    constructor() {\n       \n    }\n\n    set note(note: f32) {        \n        if(note > 1) { \n            this.osc.frequency = notefreq(note);\n            this.osc2.frequency = notefreq(note);\n            this._note = note;\n            this.env1.attack();\n            \n            this.filterenv.attack();           \n        } else {\n            this.env1.release();  \n            \n            this.filterenv.release();          \n        }\n        \n    }\n\n    get note(): f32 {\n        return this._note;\n    }\n\n    next(): void {        \n        const env1: f32 = this.env1.next();\n        if(env1 === 0) {\n            this.signal.clear();\n            return;\n        }\n        \n        let osc: f32 = this.osc.next() * 0.05;\n        let osc2: f32 = this.osc2.next() * env1 * 0.2;\n\n        const pan = this._note / 127;\n\n        let sig = osc + osc2;\n\n        const filterenv = this.filterenv.next();\n        this.lopass.update_coeffecients(FilterType.LowPass, SAMPLERATE, \n            (14000 * filterenv) , Q_BUTTERWORTH);\n        sig = this.lopass.process(sig);\n        \n        this.signal.left = sig;\n        this.signal.right = sig;\n        \n        \n    } \n}\n  ","instruments/lead/eftang.ts":"\nimport { SAMPLERATE } from '../../environment';\nimport { StereoSignal } from '../../synth/stereosignal.class';\nimport { Envelope } from '../../synth/envelope.class';\nimport { SawOscillator } from '../../synth/sawoscillator.class';\nimport { BiQuadFilter, FilterType, Q_BUTTERWORTH } from '../../synth/biquad';\nimport { Noise } from '../../synth/noise.class';\nimport { BandPass } from '../../fx/bandpass';\nimport { SawOscillator } from '../../synth/sawoscillator.class';\nimport { notefreq } from '../../synth/note';\nimport { SineOscillator } from '../../synth/sineoscillator.class';\n\nexport class Eftang {\n    private _note: f32;\n    \n\n    readonly lfo: SineOscillator = new SineOscillator();\n    readonly osc: SawOscillator = new SawOscillator();\n    readonly osc2: SawOscillator = new SawOscillator();\n    readonly osc3: SawOscillator = new SawOscillator();\n    \n    readonly noise: Noise = new Noise();\n    readonly env1: Envelope = new Envelope(0.001, 1.0, 0.8, 0.3);\n    readonly bp1: BandPass = new BandPass(200, 350);\n    readonly env2: Envelope = new Envelope(0.1, 0.2, 0.5, 1);\n    readonly bp2: BandPass = new BandPass(3000, 7000);    \n    \n    readonly env3: Envelope = new Envelope(0.001, 0.3, 0.1, 0.1);\n    readonly bp3: BandPass = new BandPass(10, 150);    \n    \n    readonly signal: StereoSignal = new StereoSignal();\n\n    constructor() {\n       \n    }\n\n    set note(note: f32) {        \n        if(note > 1) {            \n            this.osc.frequency = notefreq(note);\n            this.osc2.frequency = notefreq(note - 0.1);\n            this.osc3.frequency = notefreq(note + 0.1);\n            this.lfo.position = 0;\n            this.lfo.frequency = 4;\n            \n            this.env1.attack();           \n            this.env2.attack();        \n            this.env3.attack();  \n        } else {\n            this.env1.release();\n            this.env2.release();            \n            this.env3.release();            \n        }\n        this._note = note;\n    }\n\n    get note(): f32 {\n        return this._note;\n    }\n\n    next(): void {        \n        const env1: f32 = this.env1.next();\n        if(env1 === 0) {\n            this.signal.clear();\n            return;\n        }\n        \n        const env2: f32 = this.env2.next();\n        const env3: f32 = this.env3.next();\n                \n        const osc: f32 = this.osc.next() + this.osc2.next() + this.osc3.next();\n        \n        const lfo = this.lfo.next() + 1;\n        const basefreq = this.osc.frequency;\n        this.bp1.update_frequencies(20, basefreq + 1);\n        this.bp2.update_frequencies(basefreq * 1.5,basefreq * 1.6);\n        this.bp3.update_frequencies(basefreq * 12, 8000 + (lfo * 5000));\n        const noise = this.noise.next();\n\n        const sig1 = this.bp1.process(osc) * env1;\n        const sig2 = this.bp2.process(osc) * env2;\n        const sig3 = this.bp3.process(osc +  noise * 0.2) * env3;\n\n        this.signal.left = (sig1 + sig3);\n        this.signal.right = ( sig1 + sig2 );\n        \n        \n    } \n}\n  ","instruments/lead/sinelead.ts":"\nimport { SAMPLERATE } from '../../environment';\nimport { StereoSignal } from '../../synth/stereosignal.class';\nimport { Envelope } from '../../synth/envelope.class';\n\nimport { BiQuadFilter, FilterType, Q_BUTTERWORTH } from '../../synth/biquad';\nimport { Noise } from '../../synth/noise.class';\nimport { BandPass } from '../../fx/bandpass';\nimport { SawOscillator } from '../../synth/sawoscillator.class';\nimport { notefreq } from '../../synth/note';\nimport { SineOscillator } from '../../synth/sineoscillator.class';\n\nexport class SineLead {\n    private _note: f32;\n    \n\n    readonly osc: SineOscillator = new SineOscillator();\n    readonly osc2: SineOscillator = new SineOscillator();\n    \n    readonly env1: Envelope = new Envelope(0.02, 0.15, 0.05, 0.3);\n    \n    readonly signal: StereoSignal = new StereoSignal();\n\n    constructor() {\n       \n    }\n\n    set note(note: f32) {        \n        if(note > 1) { \n            this.osc.frequency = notefreq(note) * 2;\n            this.osc2.frequency = notefreq(note);\n            this._note = note;\n            this.env1.attack();           \n        } else {\n            this.env1.release();            \n        }\n        \n    }\n\n    get note(): f32 {\n        return this._note;\n    }\n\n    next(): void {        \n        const env1: f32 = this.env1.next();\n                \n        let osc: f32 = this.osc.next();\n        let osc2: f32 = this.osc2.next() * 0.2 * env1;\n        osc *= env1;\n\n        const pan = this._note / 127;\n\n        this.signal.left = osc * pan + osc2 * (1-pan);\n        this.signal.right = osc * (1 - pan) + osc2 * pan;\n        \n        \n    } \n}\n  ","instruments/pad/flatpad.class.ts":"\nimport { SAMPLERATE } from '../../environment';\nimport { StereoSignal } from '../../synth/stereosignal.class';\nimport { Envelope } from '../../synth/envelope.class';\nimport { SawOscillator } from '../../synth/sawoscillator.class';\nimport { BiQuadFilter, FilterType, Q_BUTTERWORTH } from '../../synth/biquad';\nimport { notefreq } from '../../synth/note';\nimport { SineOscillator } from '../../synth/sineoscillator.class';\n\nexport class FlatPad {\n    private _note: f32;\n    readonly envelope: Envelope = new Envelope(0.01, 0.1, 1.0, 0.1);\n    readonly filterenvelope: Envelope = new Envelope(0.001, 1.0, 1.0, 0.1);\n    readonly hipassfilterenvelope: Envelope = new Envelope(0.02, 3, 0.2, 2.0);\n    readonly sawoscillator: SawOscillator = new SawOscillator();\n    readonly sawoscillator2: SawOscillator = new SawOscillator();\n    readonly sawoscillator3: SawOscillator = new SawOscillator();\n    readonly sawoscillator4: SawOscillator = new SawOscillator();\n    readonly sawoscillator5: SawOscillator = new SawOscillator();\n    readonly lfo: SineOscillator = new SineOscillator();\n    \n    readonly filterl: BiQuadFilter = new BiQuadFilter();\n    readonly filterr: BiQuadFilter = new BiQuadFilter();\n    readonly signal: StereoSignal = new StereoSignal();\n\n    set note(note: f32) {        \n        if(note > 1) {            \n            this.lfo.frequency = 1;\n            this.lfo.position = 0;\n            this.sawoscillator.frequency = notefreq(note);\n            this.sawoscillator2.frequency = notefreq(note + 0.03);\n            this.sawoscillator3.frequency = notefreq(note - 0.03);\n            this.sawoscillator4.frequency = notefreq(note + 0.06);\n            this.sawoscillator5.frequency = notefreq(note - 0.06);\n            \n            this.envelope.attack();           \n            this.filterenvelope.attack();             \n            this.hipassfilterenvelope.attack();  \n            this._note = note;       \n        } else {\n            this.envelope.release();\n            this.filterenvelope.release();\n            this.hipassfilterenvelope.release();   \n        }\n        \n    }\n\n    get note(): f32 {\n        return this._note;\n    }\n\n    next(): void {        \n        let env: f32 = this.envelope.next();\n        if(env === 0) {\n            this.signal.clear();\n            return;\n        \n        }\n\n        const lfo: f32 = this.lfo.next();\n\n        const note = this.note;\n        if(note<2) {\n            return;\n        }\n        this.sawoscillator2.frequency = notefreq(note + 0.05 + (0.02 * lfo));\n        this.sawoscillator3.frequency = notefreq(note - 0.05 - (0.02 * lfo));\n        this.sawoscillator4.frequency = notefreq(note + 0.1 + (0.03 * lfo));\n        this.sawoscillator5.frequency = notefreq(note - 0.1 - (0.03 * lfo));\n        \n        \n        let osc: f32 = this.sawoscillator.next();\n        let osc2: f32 = this.sawoscillator2.next();\n        let osc3: f32 = this.sawoscillator3.next();\n        let osc4: f32 = this.sawoscillator4.next();\n        let osc5: f32 = this.sawoscillator5.next();\n        \n        let left = env * (osc + osc2 + osc5);\n        let right = env * (osc + osc3 + osc4 );\n\n        const filterlfo: f32 = (lfo * 0.9) + 1;\n        this.filterl.update_coeffecients(FilterType.LowPass, SAMPLERATE, \n            200 + this.filterenvelope.next() * filterlfo * 10000 + 20 * (127 - this.note), Q_BUTTERWORTH);\n        \n        this.filterr.update_coeffecients(FilterType.LowPass, SAMPLERATE, \n                200 + this.filterenvelope.next() * filterlfo * 10000 + 20 * (this.note), Q_BUTTERWORTH);\n            \n        this.signal.left = this.filterl.process(left );\n        this.signal.right = this.filterr.process(right );\n    } \n}\n  ","instruments/pad/softpad.class.ts":"\nimport { SAMPLERATE } from '../../environment';\nimport { StereoSignal } from '../../synth/stereosignal.class';\nimport { Envelope } from '../../synth/envelope.class';\nimport { SawOscillator } from '../../synth/sawoscillator.class';\nimport { BiQuadFilter, FilterType, Q_BUTTERWORTH } from '../../synth/biquad';\nimport { notefreq } from '../../synth/note';\nimport { SineOscillator } from '../../synth/sineoscillator.class';\n\nexport class SoftPad {\n    private _note: f32;\n    readonly envelope: Envelope = new Envelope(0.2, 0.6, 0.75, 0.5);\n    readonly filterenvelope: Envelope = new Envelope(0.8, 1.0, 0.6, 0.5);\n    readonly hipassfilterenvelope: Envelope = new Envelope(0.02, 3, 0.2, 2.0);\n    readonly sawoscillator: SawOscillator = new SawOscillator();\n    readonly sawoscillator2: SawOscillator = new SawOscillator();\n    readonly sawoscillator3: SawOscillator = new SawOscillator();\n    readonly sawoscillator4: SawOscillator = new SawOscillator();\n    readonly sawoscillator5: SawOscillator = new SawOscillator();\n    readonly lfo: SineOscillator = new SineOscillator();\n    \n    readonly filterl: BiQuadFilter = new BiQuadFilter();\n    readonly filterr: BiQuadFilter = new BiQuadFilter();\n    readonly signal: StereoSignal = new StereoSignal();\n\n    set note(note: f32) {        \n        if(note > 1) {            \n            this.lfo.frequency = 1;\n            this.lfo.position = 0;\n            this.sawoscillator.frequency = notefreq(note);\n            this.sawoscillator2.frequency = notefreq(note + 0.03);\n            this.sawoscillator3.frequency = notefreq(note - 0.03);\n            this.sawoscillator4.frequency = notefreq(note + 0.06);\n            this.sawoscillator5.frequency = notefreq(note - 0.06);\n            \n            this.envelope.attack();           \n            this.filterenvelope.attack();             \n            this.hipassfilterenvelope.attack();  \n            this._note = note;       \n        } else {\n            this.envelope.release();\n            this.filterenvelope.release();\n            this.hipassfilterenvelope.release();   \n        }\n        \n    }\n\n    get note(): f32 {\n        return this._note;\n    }\n\n    next(): void {        \n        let env: f32 = this.envelope.next();\n        if(env === 0) {\n            this.signal.clear();\n            return;\n        \n        }\n\n        const lfo: f32 = this.lfo.next();\n\n        const note = this.note;\n        if(note<2) {\n            return;\n        }\n        this.sawoscillator2.frequency = notefreq(note + 0.05 + (0.02 * lfo));\n        this.sawoscillator3.frequency = notefreq(note - 0.05 - (0.02 * lfo));\n        this.sawoscillator4.frequency = notefreq(note + 0.1 + (0.03 * lfo));\n        this.sawoscillator5.frequency = notefreq(note - 0.1 - (0.03 * lfo));\n        \n        \n        let osc: f32 = this.sawoscillator.next();\n        let osc2: f32 = this.sawoscillator2.next();\n        let osc3: f32 = this.sawoscillator3.next();\n        let osc4: f32 = this.sawoscillator4.next();\n        let osc5: f32 = this.sawoscillator5.next();\n        \n        let left = env * (osc + osc2 + osc5);\n        let right = env * (osc + osc3 + osc4 );\n\n        const filterlfo = lfo + 1;\n        this.filterl.update_coeffecients(FilterType.LowPass, SAMPLERATE, \n            200 + this.filterenvelope.next() * filterlfo * 2000 + 20 * (127 - this.note), Q_BUTTERWORTH);\n        \n        this.filterr.update_coeffecients(FilterType.LowPass, SAMPLERATE, \n                200 + this.filterenvelope.next() * filterlfo * 2000 + 20 * (this.note), Q_BUTTERWORTH);\n            \n        this.signal.left = this.filterl.process(left );\n        this.signal.right = this.filterr.process(right );\n    } \n}\n  ","instruments/pad.class.ts":"\nimport { SAMPLERATE } from '../environment';\nimport { StereoSignal } from '../synth/stereosignal.class';\nimport { Envelope } from '../synth/envelope.class';\nimport { SawOscillator } from '../synth/sawoscillator.class';\nimport { BiQuadFilter, FilterType, Q_BUTTERWORTH } from '../synth/biquad';\nimport { notefreq } from '../synth/note';\nimport { WaveShaper } from '../synth/shaper';\n\n\n\nexport class Pad {\n    private _note: f32;\n    readonly envelope: Envelope = new Envelope(0.05, 0.6, 0.75, 0.3);\n    readonly filterenvelope: Envelope = new Envelope(0.06, 0.6, 0.3, 0.3);\n    readonly hipassfilterenvelope: Envelope = new Envelope(0.02, 3, 0.2, 2.0);\n    readonly sawoscillator: SawOscillator = new SawOscillator();\n    readonly sawoscillator2: SawOscillator = new SawOscillator();\n    readonly sawoscillator3: SawOscillator = new SawOscillator();\n    readonly sawoscillator4: SawOscillator = new SawOscillator();\n    readonly sawoscillator5: SawOscillator = new SawOscillator();\n    \n    readonly filter: BiQuadFilter = new BiQuadFilter();\n    readonly hipassfilterl: BiQuadFilter = new BiQuadFilter();\n    readonly hipassfilterr: BiQuadFilter = new BiQuadFilter();\n    readonly signal: StereoSignal = new StereoSignal();\n\n    set note(note: f32) {        \n        if(note > 1) {            \n            this.sawoscillator.frequency = notefreq(note);\n            this.sawoscillator2.frequency = notefreq(note + 0.05);\n            this.sawoscillator3.frequency = notefreq(note - 0.05);\n            this.sawoscillator4.frequency = notefreq(note + 0.1);\n            this.sawoscillator5.frequency = notefreq(note - 0.1);\n            \n            this.envelope.attack();           \n            this.filterenvelope.attack();             \n            this.hipassfilterenvelope.attack();         \n        } else {\n            this.envelope.release();\n            this.filterenvelope.release();\n            this.hipassfilterenvelope.release();   \n        }\n        this._note = note;\n    }\n\n    get note(): f32 {\n        return this._note;\n    }\n\n    next(): void {        \n        let env: f32 = this.envelope.next();\n        if(env === 0) {\n            this.signal.clear();\n            return;\n        \n        }\n        let osc: f32 = this.sawoscillator.next();\n        let osc2: f32 = this.sawoscillator2.next();\n        let osc3: f32 = this.sawoscillator3.next();\n        let osc4: f32 = this.sawoscillator4.next();\n        let osc5: f32 = this.sawoscillator5.next();\n        \n        let left = env * (osc + osc2 + osc5);\n        let right = env * (osc + osc3 + osc4 );\n\n        this.filter.update_coeffecients(FilterType.LowPass, SAMPLERATE, \n            200 + this.filterenvelope.next() * 18000, 0.2);\n        let hpfilterfreq: f32 = 0 + (1-this.hipassfilterenvelope.next()) * 500;\n        this.hipassfilterl.update_coeffecients(FilterType.HighPass, SAMPLERATE, \n            hpfilterfreq, 0.3);\n        this.hipassfilterr.update_coeffecients(FilterType.HighPass, SAMPLERATE, \n            hpfilterfreq, 0.3);\n        \n        this.signal.left = this.hipassfilterl.process(this.filter.process(left ));\n        this.signal.right = this.hipassfilterr.process(this.filter.process(right ));\n    } \n}\n  ","instruments/piano/subpiano.ts":"import { StereoSignal } from '../../synth/stereosignal.class';\nimport { Envelope } from '../../synth/envelope.class';\nimport { Noise } from '../../synth/noise.class';\nimport { BandPass } from '../../fx/bandpass';\nimport { notefreq } from '../../synth/note';\nimport { SquareOscillator } from '../../synth/squareoscillator.class';\nimport { SineOscillator } from '../../synth/sineoscillator.class';\n\nexport class SubPiano {\n    private _note: f32;\n    private pan: f32;\n\n    readonly lfo: SineOscillator = new SineOscillator();\n    readonly osc: SquareOscillator = new SquareOscillator();\n    readonly env1: Envelope = new Envelope(0.02, 1.5, 0.1, 0.4);\n    readonly bp1: BandPass = new BandPass(200, 350);\n    readonly env2: Envelope = new Envelope(0.01, 0.6, 0.02, 0.2);\n    readonly bp2: BandPass = new BandPass(3000, 7000);    \n    \n    readonly env3: Envelope = new Envelope(0.01, 0.1, 0.00, 0.1);\n    readonly bp3: BandPass = new BandPass(10, 150);    \n    \n    readonly signal: StereoSignal = new StereoSignal();\n\n    constructor() {\n       \n    }\n\n    set note(note: f32) {        \n        if(note > 1) {            \n            let freq : f32 = notefreq(note);\n            this.osc.frequency = freq;\n            this.lfo.frequency = 5.0;\n            this.pan = note / 128.0;\n\n            this.env1.attack();           \n            this.env2.attack();        \n            this.env3.attack();  \n        } else {\n            this.env1.release();\n            this.env2.release();            \n            this.env3.release();            \n        }\n        this._note = note;\n    }\n\n    get note(): f32 {\n        return this._note;\n    }\n\n    next(): void {        \n        let env1: f32 = this.env1.next();\n        let env2: f32 = this.env2.next();\n        let env3: f32 = this.env3.next();\n                \n        let osc: f32 = this.osc.next();\n        \n        const lfo: f32 = this.lfo.next();\n        const filterlfo = lfo + 1;\n        const panlfo = lfo * 0.2 + 1;\n        const freq: f32 = this.osc.frequency;\n        this.bp1.update_frequencies(freq, freq + filterlfo * 30);\n        this.bp2.update_frequencies(freq * 1.5, freq * 1.5 + filterlfo * 300);\n        this.bp3.update_frequencies(freq * 2.25, freq * 2.25  + filterlfo * 800);\n        \n        let sig1 = this.bp1.process(osc) * env1 * 12;\n        let sig2 = this.bp2.process(osc) * env2 * 6;\n        let sig3 = this.bp3.process(osc) * env3 * 10;\n\n        this.signal.left = this.pan * (sig1 * panlfo + sig2 * 0.8 * -panlfo + sig3 * panlfo);\n        this.signal.right = 1 - this.pan * (sig1 * 0.8 * -panlfo + sig2 * panlfo + sig3 - panlfo * 0.2);\n    } \n}\n  ","instruments/sawbass.class.ts":"\nimport { SAMPLERATE } from '../environment';\nimport { StereoSignal } from '../synth/stereosignal.class';\nimport { Envelope } from '../synth/envelope.class';\nimport { SawOscillator } from '../synth/sawoscillator.class';\nimport { BiQuadFilter, FilterType, Q_BUTTERWORTH } from '../synth/biquad';\nimport { notefreq } from '../synth/note';\nimport { Instrument } from './instrument.class';\n\nexport class SawBass extends Instrument {\n    readonly envelope: Envelope = new Envelope(0.01, 0.2, 0.8, 0.2);\n    readonly sawoscillator: SawOscillator = new SawOscillator();\n    readonly sawoscillator2: SawOscillator = new SawOscillator();\n    readonly filter: BiQuadFilter = new BiQuadFilter();\n    readonly hpfilterl: BiQuadFilter = new BiQuadFilter();\n    readonly hpfilterr: BiQuadFilter = new BiQuadFilter();\n    \n    constructor() {\n        super();\n        this.hpfilterl.update_coeffecients(FilterType.HighPass, SAMPLERATE, 35, Q_BUTTERWORTH);\n        this.hpfilterr.update_coeffecients(FilterType.HighPass, SAMPLERATE, 35, Q_BUTTERWORTH);\n    }\n\n    set note(note: f32) {        \n        if(note > 1) {            \n            this.sawoscillator.frequency = notefreq(note + 0.1);\n            this.sawoscillator2.frequency = notefreq(note - 0.1);\n            this.envelope.attack();                        \n        } else {\n            this.envelope.release();\n        }\n    }\n\n    next(): void {        \n        let env: f32 = this.envelope.next();\n        if(env === 0) {\n            this.signal.clear();\n            return;\n        }\n        // this.signal.clear();\n        this.signal.left /= 1.03; // feedback\n        this.signal.right /= 1.03; // feedback\n        this.signal.addMonoSignal(\n            this.hpfilterl.process(this.sawoscillator.next() * env), 0.3, 0.3\n        );\n        this.signal.addMonoSignal(\n            this.hpfilterr.process(this.sawoscillator2.next() * env), 0.3, 0.7\n        );\n    } \n}\n  ","instruments/snare.class.ts":"\nimport { SAMPLERATE } from '../environment';\nimport { StereoSignal } from '../synth/stereosignal.class';\nimport { Envelope } from '../synth/envelope.class';\nimport { SawOscillator } from '../synth/sawoscillator.class';\nimport { BiQuadFilter, FilterType, Q_BUTTERWORTH } from '../synth/biquad';\nimport { Noise } from '../synth/noise.class';\nimport { Instrument } from './instrument.class';\n\nexport class Snare extends Instrument {\n    private velocity: f32;\n    readonly envelope: Envelope = new Envelope(0.01, 0.2, 0, 0.2);\n    readonly hpfilterenvelope: Envelope = new Envelope(0.01, 0.5, 0.5, 0.3);\n    \n    readonly sawoscillator: SawOscillator = new SawOscillator();\n    readonly noise: Noise = new Noise();\n    \n    readonly hpfilter: BiQuadFilter = new BiQuadFilter();\n    readonly lpfilter: BiQuadFilter = new BiQuadFilter();\n\n    constructor() {\n        super();\n        this.lpfilter.update_coeffecients(FilterType.LowPass, SAMPLERATE, \n           13000 , Q_BUTTERWORTH);\n    }\n\n    set note(note: f32) {        \n        if(note > 1) {            \n            this.sawoscillator.frequency = 200;\n            this.velocity = note / 16;    \n            this.envelope.attack();           \n            this.hpfilterenvelope.attack();        \n        } else {\n            this.envelope.release();\n            this.hpfilterenvelope.release();\n        }\n    }\n\n    next(): void {        \n        let env: f32 = this.envelope.next();\n        if(env === 0) {\n            this.signal.clear();\n            return;\n        }\n        this.sawoscillator.frequency = 20.0 + (env * 200.0);\n        \n                \n        this.hpfilter.update_coeffecients(FilterType.HighPass, SAMPLERATE, \n            20000 - (19900 * this.hpfilterenvelope.next()) , Q_BUTTERWORTH);\n\n        let osc1: f32 = this.sawoscillator.next() * 0.6 + this.noise.next();\n        osc1= this.hpfilter.process(osc1);\n        osc1 = this.lpfilter.process(osc1);\n\n        this.signal.left = this.velocity * env * osc1;\n        this.signal.right = this.velocity * env * osc1;\n        \n        \n    } \n}\n  ","instruments/squarelead.class.ts":"\nimport { SineOscillator } from '../synth/sineoscillator.class';\nimport { StereoSignal } from '../synth/stereosignal.class';\nimport { Envelope } from '../synth/envelope.class';\nimport { WaveShaper } from '../synth/shaper';\nimport { notefreq } from '../synth/note';\nimport { SquareOscillator } from '../synth/squareoscillator.class';\nimport { BiQuadFilter, Q_BUTTERWORTH, FilterType } from '../synth/biquad';\nimport { SAMPLERATE } from '../environment';\n\n\nexport class SquareLead {\n    private _note: f32;\n    readonly envelope: Envelope = new Envelope(0.02, 0.2, 0.2, 0.2);\n    readonly filterenvelope: Envelope = new Envelope(0.02, 0.1, 0.4, 0.2);\n    readonly squareoscillatorl: SquareOscillator = new SquareOscillator();\n    readonly squareoscillatorr: SquareOscillator = new SquareOscillator();\n    readonly lpfilterleft: BiQuadFilter = new BiQuadFilter();\n    readonly lpfilterright: BiQuadFilter = new BiQuadFilter();\n    readonly shaper: WaveShaper = new WaveShaper();\n    readonly signal: StereoSignal = new StereoSignal();\n    \n    baseFrequency : f32;\n\n    set note(note: f32) {        \n        if(note > 1) {   \n            this.shaper.drive = 0.5;         \n            this.baseFrequency = notefreq(note);\n            this.envelope.attack();    \n            this.filterenvelope.attack();\n        } else {\n            this.envelope.release();\n            this.filterenvelope.release();\n        }\n        this._note = note;\n    }\n\n    get note(): f32 {\n        return this._note;\n    }\n\n    next(): void {        \n        let env: f32 = this.envelope.next();\n        let filterenv: f32 = this.filterenvelope.next();\n        if(env===0 && filterenv===0) {\n            this.signal.clear();\n            return;\n        }\n        \n        this.squareoscillatorl.frequency = this.baseFrequency + 0.3;\n        this.squareoscillatorr.frequency = this.baseFrequency - 0.3;\n        \n        this.lpfilterleft.update_coeffecients(FilterType.LowPass, SAMPLERATE,\n            filterenv * 3000, Q_BUTTERWORTH);\n        this.lpfilterright.update_coeffecients(FilterType.LowPass, SAMPLERATE,\n            filterenv * 3000, Q_BUTTERWORTH);\n                    \n        let left = env* this.squareoscillatorl.next();\n        left = this.shaper.process(left);\n        left = this.lpfilterleft.process(left);\n\n        let right = env* this.squareoscillatorr.next();\n        right = this.shaper.process(right);\n        right = this.lpfilterright.process(right);\n\n        this.signal.left = left;\n        this.signal.right = right;  \n    } \n}\n  ","instruments/string1.class.ts":"\nimport { SineOscillator } from '../synth/sineoscillator.class';\nimport { StereoSignal } from '../synth/stereosignal.class';\nimport { Envelope } from '../synth/envelope.class';\nimport { SawOscillator } from '../synth/sawoscillator.class';\nimport { notefreq } from '../synth/note';\n\nexport class Test4KlangString {\n    private _note: f32;\n    readonly env0: Envelope = new Envelope(0.01, 0.2, 0.8, 0.2);\n    readonly vco1: SineOscillator = new SineOscillator();\n    readonly vco5: SawOscillator = new SawOscillator();\n    readonly vco6: SawOscillator = new SawOscillator();\n\n    readonly signal: StereoSignal = new StereoSignal();\n\n    notefreq: f32;\n\n    set note(note: f32) {        \n        if(note > 1) {           \n            this.notefreq = notefreq(note);\n            this.vco1.frequency = this.notefreq / 1000;\n\n            this.env0.attack();                        \n        } else {\n            this.env0.release();\n        }\n        this._note = note;\n    }\n\n    get note(): f32 {\n        return this._note;\n    }\n\n    next(): void {        \n        let f_0:f32 = this.env0.next(); // GO4K_ENV     ATTAC(88),DECAY(88),SUSTAIN(88),RELEASE(88),GAIN(88)\n        let f_1:f32 = this.vco1.next(); // GO4K_VCO     TRANSPOSE(76),DETUNE(64),PHASE(64),GATES(85),COLOR(64),SHAPE(64),GAIN(64),FLAGS(SINE|LFO)\n        this.vco5.frequency = this.notefreq + f_1; // GO4K_FST   AMOUNT(70),DEST(5*MAX_UNIT_SLOTS+2+FST_SET)\n        this.vco6.frequency = this.notefreq - f_1;  // GO4K_FST   AMOUNT(70),DEST(6*MAX_UNIT_SLOTS+5+FST_SET)\n\n        f_1 = this.vco5.next(); // GO4K_VCO     TRANSPOSE(64),DETUNE(65),PHASE(64),GATES(85),COLOR(52),SHAPE(64),GAIN(64),FLAGS(TRISAW)\n        let f_2:f32 = this.vco6.next(); // GO4K_VCO     TRANSPOSE(64),DETUNE(63),PHASE(64),GATES(85),COLOR(52),SHAPE(64),GAIN(64),FLAGS(TRISAW)\n        f_1 += f_2; // GO4K_FOP OP(FOP_ADDP)\n        f_0 *= f_1; // GO4K_FOP OP(FOP_MULP)\n        f_1 = f_0; // GO4K_PAN   PANNING(64)\n        this.signal.left = f_1;\n        this.signal.right = f_0; // GO4K_OUT    GAIN(0), AUXSEND(128)\n    } \n}\n  ","instruments/testinstrument.class.ts":"\nimport { SAMPLERATE } from '../environment';\nimport { SineOscillator } from '../synth/sineoscillator.class';\nimport { StereoSignal } from '../synth/stereosignal.class';\nimport { Envelope } from '../synth/envelope.class';\nimport { DelayLine } from '../fx/delayline';\nimport { notefreq } from '../synth/note';\n\nexport class TestInstrument {\n    private _note: f32;\n    readonly envelope: Envelope = new Envelope(0.02, 0.2, 0.2, 0.2);\n    readonly sineoscillator: SineOscillator = new SineOscillator();\n    readonly sineoscillator2: SineOscillator = new SineOscillator();\n    readonly delayline: DelayLine = new DelayLine(SAMPLERATE * 0.5 as usize);\n    readonly delayline2: DelayLine = new DelayLine(SAMPLERATE * 0.5 as usize);\n    readonly signal: StereoSignal = new StereoSignal();\n\n    set note(note: f32) {        \n        if(note!==this.note && note > 1) {            \n            this.envelope.attack();            \n            this.sineoscillator.frequency = notefreq(note);\n            this.sineoscillator2.frequency = notefreq(note + 12);\n        } else if(note===0) {\n            this.envelope.release();\n        }\n        this._note = note;\n    }\n\n    get note(): f32 {\n        return this._note;\n    }\n\n    next(): void {                \n        let env: f32 = this.envelope.next();\n        if(env === 0) {\n            this.signal.clear();            \n        } else {\n            let osc1 = env * this.sineoscillator.next();\n            let osc2 = env * this.sineoscillator2.next();\n            this.signal.left = osc1 * 0.8 + osc2 * 0.2;\n            this.signal.right = osc1 * 0.2 + osc2 * 0.8;\n        }\n    } \n}\n  ","math/fft.ts":"/**\n * Originally ported from http://rosettacode.org/wiki/Fast_Fourier_transform#C_sharp\n * \n * Optimized by reusing Complex objects instead of creating new, avoiding garbage collection\n * Precalculating of twiddles, making reuse of the FFT instance faster \n */ \n\n\nexport class Complex {\n    re: f32 = 0;\n    im: f32 = 0;\n \n    public clone(b: Complex): void {\n        this.re = b.re;\n        this.im = b.im;\n    }\n\n    public add(b: Complex): void {\n        this.re += b.re;\n        this.im += b.im;\n    }\n \n    public sub(b: Complex): void {\n        this.re -= b.re;\n        this.im -= b.im;\n    }\n \n    public mult(b: Complex): void {\n        const re: f32 = this.re;\n\n        this.re = re * b.re - this.im * b.im;\n        this.im = re * b.im + this.im * b.re;\n    }\n\n    public scale(n: f32): void {\n        this.re *= n;\n        this.im *= n;\n    }\n\n    public conjugate(): void {\n        this.im = -this.im;\n    }\n}\n\nfunction bitReverse(n: i32, bits: i32): i32 {\n    let reversedN: i32 = n;\n    let count: i32 = bits - 1;\n\n    n >>= 1;\n    while (n > 0) {\n        reversedN = (reversedN << 1) | (n & 1);\n        count--;\n        n >>= 1;\n    }\n\n    return ((reversedN << count) & ((1 << bits) - 1));\n}\n \n/* Uses Cooley-Tukey iterative in-place algorithm with radix-2 DIT case\n * assumes no of points provided are a power of 2 */\nexport class FFT {\n    buffer: StaticArray<Complex>;\n    bits: i32;\n    exps: StaticArray<Complex>;\n    tmp: Complex = new Complex();\n\n    /**\n     * \n     * @param buffersize_shift buffersize will be 2^buffersize_shift\n     */\n    constructor(buffersize_shift: i32) {\n        const buffersize = 1 << buffersize_shift;\n        const buffer = new StaticArray<Complex>(buffersize);\n        for (let n=0;n<buffersize;n++) {\n            buffer[n] = new Complex();\n        }\n        this.buffer = buffer;\n        this.bits = buffersize_shift;\n        \n        this.exps = new StaticArray<Complex>((\n                    buffersize as f32 *\n                    NativeMathf.log2(buffersize as f32)\n                ) as i32);\n\n        let expsIndex = 0;\n        for (let N: i32 = 2; N <= buffer.length; N <<= 1) {\n            for (let i: i32 = 0; i < buffer.length; i += N) {\n                for (let k: i32 = 0; k < (N >> 1); k++) {\n                    const term: f32 = -2 * NativeMathf.PI * (k as f32) / (N as f32);\n                    const exp: Complex = new Complex();\n                    exp.re = NativeMathf.cos(term);\n                    exp.im = NativeMathf.sin(term);\n                    this.exps[expsIndex++] = exp;\n                }\n            }\n        }\n    }\n\n    calculateInverse(): void {\n        const N = this.buffer.length;\n        const iN: f32 = 1 / (N as f32);\n\n        for (let n=0;n<N;n++) {\n            this.buffer[n].conjugate();\n        }\n        this.calculate();\n        for (let n=0;n<N;n++) {\n            this.buffer[n].conjugate();\n            this.buffer[n].scale(iN);\n        }\n    }\n\n    calculate(): void {\n        const buffer = this.buffer;\n        const bits = this.bits;\n\n        for (let j = 1; j < buffer.length; j++) {\n            const swapPos: i32 = bitReverse(j, bits);\n            if (swapPos <= j) {\n                continue;\n            }\n            const temp = buffer[j];\n            buffer[j] = buffer[swapPos];\n            buffer[swapPos] = temp;\n        }\n\n        let expsIndex = 0;\n        for (let N: i32 = 2; N <= buffer.length; N <<= 1) {\n            for (let i: i32 = 0; i < buffer.length; i += N) {\n                for (let k: i32 = 0; k < (N >> 1); k++) {\n                    const evenIndex = i + k;\n                    const oddIndex = i + k + (N >> 1);\n                    const even = buffer[evenIndex];\n                    const odd = buffer[oddIndex];\n                    const exp = this.tmp;\n                    exp.clone(this.exps[expsIndex++]);\n\n                    exp.mult(odd);\n\n                    odd.clone(even);\n                    even.add(exp);\n                    odd.sub(exp);\n                }\n            }\n        }\n    }\n}\n\nexport function createFFT(buffersize_shift: i32): usize {\n    return changetype<usize>(new FFT(buffersize_shift));\n}\n\nexport function setComplex(instance: usize, arrayIndex: i32, re: f32, im: f32): void {\n    const buffer = changetype<FFT>(instance).buffer;\n    buffer[arrayIndex].re = re;\n    buffer[arrayIndex].im = im;\n}\n\nexport function getComplexRe(instance: usize, arrayIndex: i32): f32 {\n    return changetype<FFT>(instance).buffer[arrayIndex].re;\n}\n\nexport function getComplexIm(instance: usize, arrayIndex: i32): f32 {\n    return changetype<FFT>(instance).buffer[arrayIndex].im;\n}\n\nexport function calculateFFT(instance: usize): void {\n    changetype<FFT>(instance).calculate();\n}\n\nexport function calculateIFFT(instance: usize): void {\n    changetype<FFT>(instance).calculateInverse();\n}","math/sin.ts":"// By Max Graey ( https://github.com/petersalomonsen/javascriptmusic/issues/2#issuecomment-469419609 )\n\nexport const PI: f32 = 3.141592653589793;\nexport function sin(x: f32): f32 {\n  var y: f32, z: f32;\n  x *= 1 / PI;\n  y  = floor(x);\n  z  = x - y;\n  z *= 1.0 - z;\n  z *= 3.6 * z + 3.1;\n  return select(-z, z, <i32>y & 1);\n}\n\nexport function cos(x: f32): f32 {\n  return sin(x + PI * .5);\n}","midi/instruments/audioplayer.ts":"import { LoPassBiQuadFilter, MidiChannel, Q_BUTTERWORTH } from \"../../mixes/globalimports\";\nimport { Envelope } from \"../../synth/envelope.class\";\nimport { MidiVoice } from \"../midisynth\";\n\nconst CONTROL_FREQUENCY_CUTOFF = 74;\nconst MAX_CUTOFF_FREQUENCY: f32 = 20000;\nconst audioBuffers: Array<StaticArray<f32>> = new Array<StaticArray<f32>>();\n\nexport class AudioPlayerChannel extends MidiChannel {\n    gain: f32 = 1.0;\n    cutoff: f32 = MAX_CUTOFF_FREQUENCY;\n    lopassleft: LoPassBiQuadFilter = new LoPassBiQuadFilter();\n    lopassright: LoPassBiQuadFilter = new LoPassBiQuadFilter();\n\n    controlchange(controller: u8, value: u8): void {\n        super.controlchange(controller, value);\n        switch (controller) {\n            case CONTROL_FREQUENCY_CUTOFF:\n                this.cutoff = value * MAX_CUTOFF_FREQUENCY / 127 as f32;\n                this.lopassleft.update(this.cutoff, Q_BUTTERWORTH);\n                this.lopassright.update(this.cutoff, Q_BUTTERWORTH);\n                break;\n        }\n    }\n\n    preprocess(): void {\n        let left = this.signal.left;\n        let right = this.signal.right;\n        if (this.cutoff < MAX_CUTOFF_FREQUENCY) {\n            left = this.lopassleft.process(left);\n            right = this.lopassright.process(right);\n        }\n        left *= this.gain;\n        right *= this.gain;\n\n        this.signal.left = left;\n        this.signal.right = right;\n    }\n}\n\nexport class AudioPlayer extends MidiVoice {\n    position: i32 = 0;\n    velocityLevel: f32;\n\n    constructor(channel: MidiChannel,\n        private audioBufferPairNdx: i32,\n        private startPosition: i32,\n        noteNumber: u8,\n        private env: Envelope = new Envelope(0.01, 0.0, 1.0, 0.01)\n    ) {\n        super(channel);\n        this.minnote = noteNumber;\n        this.maxnote = noteNumber;\n    }\n\n    noteon(note: u8, velocity: u8): void {\n        super.noteon(note, velocity);\n        this.velocityLevel = velocity as f32 / 127 as f32;\n        this.position = this.startPosition;\n        this.env.attack();\n    }\n\n    noteoff(): void {\n        this.env.release();\n    }\n\n    isDone(): boolean {\n        return audioBuffers.length == 0 || this.env.isDone();\n    }\n\n    nextframe(): void {\n        const env = this.env.next();\n        const vel = env * this.velocityLevel;\n\n        let pos = this.position;\n        const audioBufferNdx = this.audioBufferPairNdx << 1;\n        const leftarr = audioBuffers[audioBufferNdx];\n        const left = vel * leftarr[pos];\n        const right = vel * audioBuffers[audioBufferNdx + 1][pos];\n        pos++;\n        if (pos == leftarr.length) {\n            pos = 0;\n        }\n        this.position = pos;\n\n        this.channel.signal.left += left;\n        this.channel.signal.right += right;\n    }\n}\n\nexport class MonoAudioPlayer {\n    position: i32 = 0;\n\n    constructor(private audioBufferNdx: i32) {\n\n    }\n\n    restart(): void {\n        this.position = 0;\n    }\n\n    get audioBuffer(): StaticArray<f32> {\n        return audioBuffers[this.audioBufferNdx];\n    }\n\n    nextframe(): f32 {\n        return this.audioBuffer[(this.position++) % this.audioBuffer.length];\n    }\n}\n\nexport function allocateAudioBuffer(frames: i32): usize {\n    const buf = new StaticArray<f32>(frames);\n    audioBuffers.push(buf);\n    return changetype<usize>(buf);\n}","midi/instruments/defaultinstrument.ts":"import { Envelope } from \"../../synth/envelope.class\";\nimport { notefreq } from \"../../synth/note\";\nimport { SineOscillator } from \"../../synth/sineoscillator.class\";\nimport { MidiVoice } from \"../midisynth\";\n\nexport class DefaultInstrument extends MidiVoice {\n    osc: SineOscillator = new SineOscillator();\n    env: Envelope = new Envelope(0.01, 0.0, 1.0, 0.01);\n\n    noteon(note: u8, velocity: u8): void {\n        super.noteon(note, velocity);\n        this.osc.frequency = notefreq(note);\n        this.env.attack();\n    }\n\n    noteoff(): void {\n        this.env.release();\n    }\n\n    isDone(): boolean {\n        return this.env.isDone();\n    }\n\n    nextframe(): void {\n        const signal = this.osc.next() * this.env.next() * this.velocity / 256;\n        this.channel.signal.addMonoSignal(signal, 0.2, 0.5);\n    }\n}","midi/midisynth.ts":"import { initializeMidiSynth, postprocess } from '../mixes/midi.mix';\nimport { StereoSignal, Freeverb } from '../mixes/globalimports';\nimport { midiLevelToGain } from '../synth/decibel';\n\nimport { Pan } from '../synth/pan.class';\nimport { DefaultInstrument } from './instruments/defaultinstrument';\n// export { allocateAudioBuffer } from './instruments/audioplayer';\n\nexport const MAX_ACTIVE_VOICES_SHIFT = 5; // up to 32 voices playing simultaneously\nexport const MAX_ACTIVE_VOICES = 1 << MAX_ACTIVE_VOICES_SHIFT;\n\nexport const midichannels = new StaticArray<MidiChannel>(16);\nexport const activeVoices = new StaticArray<MidiVoice | null>(MAX_ACTIVE_VOICES);\nconst activeVoicesStatusSnapshot = new StaticArray<u8>(MAX_ACTIVE_VOICES * 3);\n\nexport let numActiveVoices = 0;\nexport let voiceActivationCount = 0;\n\nexport const sampleBufferFrames = 128;\nexport const sampleBufferBytesPerChannel = sampleBufferFrames * 4;\nexport const sampleBufferChannels = 2;\nexport const samplebuffer = new StaticArray<f32>(sampleBufferFrames * sampleBufferChannels);\nconst bufferposstart = changetype<usize>(samplebuffer);\n\nconst CONTROL_SUSTAIN: u8 = 64;\nconst CONTROL_VOLUME: u8 = 7;\nconst CONTROL_PAN: u8 = 10;\nconst CONTROL_REVERB: u8 = 91;\n\nconst mainline = new StereoSignal();\nconst reverbline = new StereoSignal();\nexport const freeverb = new Freeverb();\nexport const outputline = new StereoSignal();\nexport class MidiChannel {\n    controllerValues: StaticArray<u8> = new StaticArray<u8>(128);\n    voices: StaticArray<MidiVoice>;\n    sustainedVoices: StaticArray<MidiVoice | null> = new StaticArray<MidiVoice | null>(128);\n\n    signal: StereoSignal = new StereoSignal();\n    volume: f32 = midiLevelToGain(100);\n    reverb: f32 = midiLevelToGain(7);\n    pan: Pan = new Pan();\n    voiceTransitionBuffer: StaticArray<f32> = new StaticArray<f32>(sampleBufferFrames * 2);\n\n    constructor(numvoices: i32, factoryFunc: (channel: MidiChannel, voiceindex: i32) => MidiVoice) {\n        this.voices = new StaticArray<MidiVoice>(numvoices);\n        for (let n = 0; n < numvoices; n++) {\n            this.voices[n] = factoryFunc(this, n);\n        }\n\n    }\n\n    controlchange(controller: u8, value: u8): void {\n        this.controllerValues[controller] = value;\n\n        switch (controller) {\n            case CONTROL_SUSTAIN:\n                // sustain\n                if (value < 64) {\n                    for (let n = 0; n < 128; n++) {\n                        if (this.sustainedVoices[n] != null) {\n                            (this.sustainedVoices[n] as MidiVoice).noteoff();\n                            this.sustainedVoices[n] = null;\n                        }\n                    }\n                }\n                break;\n            case CONTROL_VOLUME:\n                this.volume = midiLevelToGain(value);\n                break;\n            case CONTROL_REVERB:\n                this.reverb = midiLevelToGain(value);\n                break;\n            case CONTROL_PAN:\n                this.pan.setPan((value as f32) / 127.0);\n                break;\n        }\n    }\n\n    noteoff(note: u8): void {\n        for (let n = 0; n < this.voices.length; n++) {\n            const voice = this.voices[n];\n            if (voice.note === note) {\n                if (this.controllerValues[CONTROL_SUSTAIN] >= 64) {\n                    this.sustainedVoices[note] = voice;\n                } else {\n                    voice.noteoff();\n                }\n                break;\n            }\n        }\n    }\n\n    removeFromSustainedVoices(voice: MidiVoice): void {\n        this.sustainedVoices[voice.note] = null;\n    }\n\n    activateVoice(note: u8, channelNo: u8): MidiVoice | null {\n        for (let n = 0; n < this.voices.length; n++) {\n            const voice = this.voices[n];\n            voice.channelNo = channelNo;\n            if (voice.activeVoicesIndex > -1 && voice.note === note) {\n                // Found already active voice for the given note\n                voice.activationCount = voiceActivationCount++;\n                // must remove from sustained voices\n                this.removeFromSustainedVoices(voice);\n                return voice;\n            }\n        }\n\n        if (numActiveVoices === activeVoices.length) {\n            return null;\n        }\n\n        let activeVoiceIndex: i32 = numActiveVoices;\n\n        for (let n = 0; n < this.voices.length; n++) {\n            const voice = this.voices[n];\n            if (voice.activeVoicesIndex === -1 &&\n                note >= voice.minnote &&\n                note <= voice.maxnote) {\n                const availableVoice = voice as MidiVoice;\n                activeVoices[activeVoiceIndex] = availableVoice;\n                availableVoice.activeVoicesIndex = activeVoiceIndex;\n                numActiveVoices++;\n                availableVoice.activationCount = voiceActivationCount++;\n                return availableVoice;\n            }\n        }\n\n        // no available voices for the current channel, we'll pick the oldest\n        let oldestVoice: MidiVoice | null = null;\n        for (let n = 0; n < this.voices.length; n++) {\n            const voice = this.voices[n];\n            if (\n                (oldestVoice === null ||\n                    voice.activationCount <= (oldestVoice as MidiVoice).activationCount) &&\n                note >= voice.minnote &&\n                note <= voice.maxnote) {\n                oldestVoice = voice;\n            }\n        }\n        if (oldestVoice !== null) {\n            const voice = (oldestVoice as MidiVoice);\n            for (let n = 0; n < sampleBufferFrames; n++) {\n                voice.nextframe();\n                const fact: f32 = ((sampleBufferFrames as f32) - (n as f32)) / (sampleBufferFrames as f32);\n                this.voiceTransitionBuffer[n << 1] += this.signal.left * fact;\n                this.voiceTransitionBuffer[(n << 1) + 1] += this.signal.right * fact;\n                this.signal.clear();\n            }\n            voice.activationCount = voiceActivationCount++;\n            this.removeFromSustainedVoices(voice);\n        }\n        return oldestVoice;\n    }\n\n    /**\n     * Process channel signal before sending to outputs\n     */\n    preprocess(): void {\n\n    }\n}\n\nexport abstract class MidiVoice {\n    channel: MidiChannel;\n    channelNo: u8;\n    note: u8;\n    velocity: u8;\n    activeVoicesIndex: i32 = -1;\n    activationCount: i32;\n    minnote: u8 = 0;\n    maxnote: u8 = 127;\n\n    constructor(channel: MidiChannel) {\n        this.channel = channel;\n    }\n\n    /**\n     * If you override this (e.g. to trigger attacks on envelopes), make sure you call super.noteon\n     * @param note \n     * @param velocity \n     */\n    noteon(note: u8, velocity: u8): void {\n        this.note = note;\n        this.velocity = velocity;\n    }\n\n    /**\n     * Override this to e.g. trigger releases on envelopes\n     */\n    noteoff(): void {\n        this.velocity = 0;\n    }\n\n    /**\n     * This will be called repeatedly as long as the voice is active\n     * \n     * Override it to add checks for e.g. envelope to be fully released\n     */\n    isDone(): boolean {\n        return this.velocity === 0;\n    }\n\n    deactivate(): void {\n        activeVoices[this.activeVoicesIndex] = null;\n        this.activeVoicesIndex = -1;\n    }\n\n    /**\n     * Will be called for rendering an audio frame\n     */\n    abstract nextframe(): void;\n}\n\nexport function shortmessage(val1: u8, val2: u8, val3: u8): void {\n    const channel = val1 & 0xf;\n    const command = val1 & 0xf0;\n\n    if (command === 0x90 && val3 > 0) {\n        const activatedVoice = midichannels[channel].activateVoice(val2, channel);\n        if (activatedVoice !== null) {\n            const voice = activatedVoice as MidiVoice;\n            voice.noteon(val2, val3);\n        }\n    } else if (\n        (command === 0x80 ||\n            (command === 0x90 && val3 === 0)) // \n    ) {\n        // note off\n        midichannels[channel].noteoff(val2);\n    } else if (command === 0xb0) {\n        // control change\n        midichannels[channel].controlchange(val2, val3);\n    }\n}\n\nexport function getActiveVoicesStatusSnapshot(): usize {\n    for (let n = 0; n < activeVoices.length; n++) {\n        const activeVoicesStatusSnapshotIndex = n * 3;\n        if (activeVoices[n] != null) {\n            const voice = (activeVoices[n] as MidiVoice);\n            activeVoicesStatusSnapshot[activeVoicesStatusSnapshotIndex] = voice.channelNo;\n            activeVoicesStatusSnapshot[activeVoicesStatusSnapshotIndex + 1] = voice.note;\n            activeVoicesStatusSnapshot[activeVoicesStatusSnapshotIndex + 2] = voice.velocity;\n        } else {\n            activeVoicesStatusSnapshot[activeVoicesStatusSnapshotIndex] = 0;\n            activeVoicesStatusSnapshot[activeVoicesStatusSnapshotIndex + 1] = 0;\n            activeVoicesStatusSnapshot[activeVoicesStatusSnapshotIndex + 2] = 0;\n        }\n    }\n    return changetype<usize>(activeVoicesStatusSnapshot);\n}\n\nexport function allNotesOff(): void {\n    for (let n = 0; n < numActiveVoices; n++) {\n        const voice = activeVoices[n] as MidiVoice;\n        voice.noteoff();\n    }\n}\n\nexport function cleanupInactiveVoices(): void {\n    for (let n = 0; n < numActiveVoices; n++) {\n        const voice = activeVoices[n] as MidiVoice;\n        if (voice.isDone()) {\n            voice.deactivate();\n            for (let r = n + 1; r < numActiveVoices; r++) {\n                const nextVoice = activeVoices[r] as MidiVoice;\n                nextVoice.activeVoicesIndex--;\n                activeVoices[r - 1] = nextVoice;\n                activeVoices[r] = null;\n            }\n            numActiveVoices--;\n            n--;\n        }\n    }\n}\n\nexport function playActiveVoices(): void {\n    for (let n = 0; n < numActiveVoices; n++) {\n        (activeVoices[n] as MidiVoice).nextframe();\n    }\n}\n\nexport function fillSampleBuffer(): void {\n    fillSampleBufferWithNumSamples(sampleBufferFrames);\n}\n\nexport function fillSampleBufferWithNumSamples(numSamples: i32): void {\n    const bufferposend = changetype<usize>(samplebuffer) + 4 * numSamples;\n\n    cleanupInactiveVoices();\n\n    let voiceTransitionBufferNdx = 0;\n\n    for (let bufferpos = bufferposstart; bufferpos < bufferposend; bufferpos += 4) {\n        playActiveVoices();\n\n        for (let ch = 0; ch < 16; ch++) {\n            const midichannel = midichannels[ch];\n            const channelsignal = midichannel.signal;\n\n            channelsignal.left += midichannel.voiceTransitionBuffer[voiceTransitionBufferNdx];\n            midichannel.voiceTransitionBuffer[voiceTransitionBufferNdx] = 0;\n            channelsignal.right += midichannel.voiceTransitionBuffer[voiceTransitionBufferNdx + 1];\n            midichannel.voiceTransitionBuffer[voiceTransitionBufferNdx + 1] = 0;\n\n            midichannel.preprocess();\n\n            channelsignal.left *= midichannel.pan.leftLevel * midichannel.volume;\n            channelsignal.right *= midichannel.pan.rightLevel * midichannel.volume;\n\n            const reverb = midichannel.reverb;\n\n            mainline.add(channelsignal.left, channelsignal.right);\n            reverbline.add(channelsignal.left * reverb, channelsignal.right * reverb);\n            midichannel.signal.clear();\n        }\n\n        freeverb.tick(reverbline);\n\n        outputline.add(\n            mainline.left + reverbline.left,\n            mainline.right + reverbline.right\n        );\n\n        postprocess();\n\n        store<f32>(bufferpos, outputline.left);\n        store<f32>(bufferpos + sampleBufferBytesPerChannel, outputline.right);\n\n        mainline.clear();\n        reverbline.clear();\n        outputline.clear();\n        voiceTransitionBufferNdx += 2;\n    }\n}\n\nconst defaultMidiChannel = new MidiChannel(1, (channel: MidiChannel) => new DefaultInstrument(channel));\n\nfor (let ch = 0; ch < 16; ch++) {\n    midichannels[ch] = defaultMidiChannel;\n}\n\ninitializeMidiSynth();\n\n","midi/sequencer/midiparts.ts":"import { MidiSequencerPart, MidiSequencerPartSchedule } from \"./midisequencerpart\";\n\nexport const midiparts: MidiSequencerPart[] = new Array<MidiSequencerPart>();\nexport const midipartschedule: MidiSequencerPartSchedule[] = new Array<MidiSequencerPartSchedule>();\n","midi/sequencer/midisequencer.ts":"import { SAMPLERATE } from \"../../environment\";\nimport { midiparts, midipartschedule } from \"./midiparts\";\nimport { fillSampleBuffer, sampleBufferFrames } from \"../midisynth\";\n\nconst PLAY_EVENT_INTERVAL = ((sampleBufferFrames * 1000) as f64 / SAMPLERATE);\n\nexport let currentTimeMillis: f64 = 0;\n\nexport function seek(time: i32): void {\n    currentTimeMillis = time as f64;\n\n    for (let ndx = 0;\n        ndx < midipartschedule.length;\n        ndx++) {\n        const scheduleEntry = midipartschedule[ndx];\n        const midiSequencerPart = midiparts[scheduleEntry.midipartindex];\n        if (scheduleEntry.endTime >= currentTimeMillis && scheduleEntry.startTime <= currentTimeMillis) {\n            midiSequencerPart.seek(Math.round(currentTimeMillis) as i32 - scheduleEntry.startTime);\n        } else {\n            midiSequencerPart.seek(0);\n        }\n    }\n}\n\nexport function playMidiPartEvents(): void {\n    for (let ndx = 0;\n        ndx < midipartschedule.length;\n        ndx++) {\n        const scheduleEntry = midipartschedule[ndx];        \n        if (scheduleEntry.startTime > currentTimeMillis) {\n            break;\n        }\n        const midiSequencerPart = midiparts[scheduleEntry.midipartindex];\n        if (currentTimeMillis <= (scheduleEntry.endTime + PLAY_EVENT_INTERVAL)) {\n            midiSequencerPart.playEvents(Math.round(currentTimeMillis) as i32 - scheduleEntry.startTime);\n        }\n    }\n}\n\nexport function playEventsAndFillSampleBuffer(): void {\n    playMidiPartEvents();\n    fillSampleBuffer();\n    currentTimeMillis += PLAY_EVENT_INTERVAL;\n}\n\nexport function setMidiPartSchedule(ndx: i32, midipartindex: i32, startTime: i32): void {\n    midipartschedule[ndx].updateEndTime(midipartindex, startTime);\n}\n","midi/sequencer/midisequencerpart.ts":"import { midiparts, midipartschedule } from \"./midiparts\";\nimport { shortmessage } from \"../midisynth\";\n\nexport class MidiSequencerPart {\n    currentEventTime: i32 = 0;\n    currentEventIndex: i32 = 0;\n    previousTargetTime: i32 = 0;\n    lastEventTime: i32 = 0;\n\n    constructor(public eventlist: u8[]) {\n        let lastEventTime = 0;\n        for (let ndx = 0; ndx < this.eventlist.length;ndx += 3) {\n            let deltaTime: i32 = 0;\n            let deltaTimePart: u8;\n\n            let shiftamount: u8 = 0;\n            do {\n                deltaTimePart = this.eventlist[ndx++];\n                deltaTime += (((deltaTimePart & 0x7f) as i32) << shiftamount);\n                shiftamount += 7;\n            } while (deltaTimePart & 0x80);\n\n            lastEventTime = lastEventTime + deltaTime;\n        }\n        this.lastEventTime = lastEventTime;\n    }\n\n    playEvents(targetTime: i32): void {\n        if (targetTime < this.previousTargetTime) {\n            this.currentEventTime = 0;\n            this.currentEventIndex = 0;\n        }\n        this.previousTargetTime = targetTime;\n        let ndx = this.currentEventIndex;\n\n        while (ndx < this.eventlist.length) {\n            let deltaTime: i32 = 0;\n            let deltaTimePart: u8;\n\n            let shiftamount: u8 = 0;\n            do {\n                deltaTimePart = this.eventlist[ndx++];\n                deltaTime += (((deltaTimePart & 0x7f) as i32) << shiftamount);\n                shiftamount += 7;\n            } while (deltaTimePart & 0x80);\n\n            const newTime = this.currentEventTime + deltaTime;\n\n            if (newTime <= targetTime) {\n                shortmessage(this.eventlist[ndx++], this.eventlist[ndx++], this.eventlist[ndx++]);\n\n                this.currentEventTime = newTime;\n                this.currentEventIndex = ndx;\n            } else {\n                break;\n            }\n        }\n    }\n\n    seek(targetTime: i32): void {\n        this.currentEventIndex = 0;\n        this.currentEventTime = 0;\n        let ndx = this.currentEventIndex;\n\n        while (ndx < this.eventlist.length) {\n            let deltaTime: i32 = 0;\n            let deltaTimePart: u8;\n\n            let shiftamount: u8 = 0;\n            do {\n                deltaTimePart = this.eventlist[ndx++];\n                deltaTime += ((deltaTimePart & 0x7f) << shiftamount);\n                shiftamount += 7;\n            } while (deltaTimePart & 0x80);\n\n            const newTime = this.currentEventTime + deltaTime;\n\n            if (newTime < targetTime) {\n                ndx += 3;\n                this.currentEventTime = newTime;\n                this.currentEventIndex = ndx;\n            } else if (newTime === targetTime) {\n                this.currentEventTime = newTime;\n            } else {\n                break;\n            }\n        }\n    }\n}\n\nexport class MidiSequencerPartSchedule {\n    public endTime: i32\n\n    constructor(\n        public midipartindex: i32,\n        public startTime: i32) {\n            this.endTime = midiparts[midipartindex].lastEventTime + startTime;\n    }\n\n    updateEndTime(midipartindex: i32, startTime: i32): void {\n        this.startTime = startTime;\n        this.midipartindex = midipartindex;\n        this.endTime = midiparts[midipartindex].lastEventTime + startTime;\n    }\n}\n","mixes/empty.mix.ts":"import { Kick2, SawBass, Instrument,\n  StereoSignal,\n  Freeverb } from \"./globalimports\";\n\nexport const PATTERN_SIZE_SHIFT: usize = 4;\nexport const BEATS_PER_PATTERN_SHIFT: usize = 2;\n\nconst kick = new Kick2();\nconst sawbass = new SawBass();\n\nexport function setChannelValue(channel: usize, value: f32): void {\n  ([kick, sawbass] as Instrument[])[channel].note = value;\n}\n\nconst mainline = new StereoSignal();\nconst reverbline = new StereoSignal();\nconst freeverb = new Freeverb();\n\n@inline\nexport function mixernext(leftSampleBufferPtr: usize, rightSampleBufferPtr: usize): void {  \n  mainline.clear();\n  reverbline.clear();\n\n  kick.next();\n  mainline.addStereoSignal(kick.signal, 0.5, 0.5);\n\n  sawbass.next();\n  mainline.addStereoSignal(sawbass.signal, 0.5, 0.5);\n  reverbline.addStereoSignal(sawbass.signal, 0.1, 0.5);\n\n  freeverb.tick(reverbline);\n\n  store<f32>(leftSampleBufferPtr, mainline.left + reverbline.left);\n  store<f32>(rightSampleBufferPtr, mainline.right + reverbline.right);    \n}","mixes/globalimports.ts":"export { createInstrumentArray } from '../common/mixcommon';\nexport { AllPass } from '../fx/allpass';\nexport { AllPassFloat } from '../fx/allpass';\nexport { BandPass } from '../fx/bandpass';\nexport { Comb } from '../fx/comb';\nexport { DelayLine } from '../fx/delayline';\nexport { DelayLineFloat } from '../fx/delayline';\nexport { EQBand } from '../fx/eqband';\nexport { Freeverb } from '../fx/freeverb';\nexport { Limiter } from '../fx/limiter';\nexport { MidSideProcessor } from '../fx/midsideprocessor';\nexport { MonoCompressor } from '../fx/monocompressor';\nexport { StereoCompressor } from '../fx/monocompressor';\nexport { MultiBandEQ } from '../fx/multibandeq';\nexport { StereoCompressor } from '../fx/stereocompressor';\nexport { TriBandEQ } from '../fx/tribandeq';\nexport { TriBandStereoCompressor } from '../fx/tribandstereocompressor';\nexport { DeepBass } from '../instruments/bass/deepbass';\nexport { SawBass2 } from '../instruments/bass/sawbass2.class';\nexport { SawBass3 } from '../instruments/bass/sawbass3';\nexport { DriveLead } from '../instruments/drivelead.class';\nexport { Kick2 } from '../instruments/drums/kick2.class';\nexport { Rimshot } from '../instruments/drums/rimshot.class';\nexport { Snare2 } from '../instruments/drums/snare2.class';\nexport { Hihat } from '../instruments/hihat.class';\nexport { Instrument } from '../instruments/instrument.class';\nexport { Kick } from '../instruments/kick.class';\nexport { BrassyLead } from '../instruments/lead/brassy';\nexport { Eftang } from '../instruments/lead/eftang';\nexport { SineLead } from '../instruments/lead/sinelead';\nexport { FlatPad } from '../instruments/pad/flatpad.class';\nexport { SoftPad } from '../instruments/pad/softpad.class';\nexport { Pad } from '../instruments/pad.class';\nexport { SubPiano } from '../instruments/piano/subpiano';\nexport { SawBass } from '../instruments/sawbass.class';\nexport { Snare } from '../instruments/snare.class';\nexport { SquareLead } from '../instruments/squarelead.class';\nexport { Test4KlangString } from '../instruments/string1.class';\nexport { TestInstrument } from '../instruments/testinstrument.class';\nexport { Complex } from '../math/fft';\nexport { FFT } from '../math/fft';\nexport { createFFT } from '../math/fft';\nexport { setComplex } from '../math/fft';\nexport { getComplexRe } from '../math/fft';\nexport { getComplexIm } from '../math/fft';\nexport { calculateFFT } from '../math/fft';\nexport { calculateIFFT } from '../math/fft';\nexport { PI } from '../math/sin';\nexport { sin } from '../math/sin';\nexport { cos } from '../math/sin';\nexport { AudioPlayerChannel } from '../midi/instruments/audioplayer';\nexport { AudioPlayer } from '../midi/instruments/audioplayer';\nexport { MonoAudioPlayer } from '../midi/instruments/audioplayer';\nexport { allocateAudioBuffer } from '../midi/instruments/audioplayer';\nexport { DefaultInstrument } from '../midi/instruments/defaultinstrument';\nexport { MAX_ACTIVE_VOICES_SHIFT } from '../midi/midisynth';\nexport { MAX_ACTIVE_VOICES } from '../midi/midisynth';\nexport { midichannels } from '../midi/midisynth';\nexport { activeVoices } from '../midi/midisynth';\nexport { numActiveVoices } from '../midi/midisynth';\nexport { voiceActivationCount } from '../midi/midisynth';\nexport { sampleBufferFrames } from '../midi/midisynth';\nexport { sampleBufferBytesPerChannel } from '../midi/midisynth';\nexport { sampleBufferChannels } from '../midi/midisynth';\nexport { samplebuffer } from '../midi/midisynth';\nexport { freeverb } from '../midi/midisynth';\nexport { outputline } from '../midi/midisynth';\nexport { MidiChannel } from '../midi/midisynth';\nexport { MidiVoice } from '../midi/midisynth';\nexport { shortmessage } from '../midi/midisynth';\nexport { getActiveVoicesStatusSnapshot } from '../midi/midisynth';\nexport { allNotesOff } from '../midi/midisynth';\nexport { cleanupInactiveVoices } from '../midi/midisynth';\nexport { playActiveVoices } from '../midi/midisynth';\nexport { fillSampleBuffer } from '../midi/midisynth';\nexport { fillSampleBufferWithNumSamples } from '../midi/midisynth';\nexport { Q_BUTTERWORTH } from '../synth/biquad';\nexport { FilterType } from '../synth/biquad';\nexport { Coefficients } from '../synth/biquad';\nexport { BiQuadFilter } from '../synth/biquad';\nexport { LoPassBiQuadFilter } from '../synth/biquad';\nexport { HiPassBiQuadFilter } from '../synth/biquad';\nexport { beatToFrame } from '../synth/bpm';\nexport { softclip } from '../synth/clip';\nexport { hardclip } from '../synth/clip';\nexport { decibelToGain } from '../synth/decibel';\nexport { midiLevelToDecibel } from '../synth/decibel';\nexport { midiLevelToGain } from '../synth/decibel';\nexport { EnvelopeState } from '../synth/envelope.class';\nexport { Envelope } from '../synth/envelope.class';\nexport { IFFTOscillator } from '../synth/ifftoscillator.class';\nexport { Noise } from '../synth/noise.class';\nexport { notefreq } from '../synth/note';\nexport { Pan } from '../synth/pan.class';\nexport { SawOscillator } from '../synth/sawoscillator.class';\nexport { WaveShaper } from '../synth/shaper';\nexport { SineOscillator } from '../synth/sineoscillator.class';\nexport { SquareOscillator } from '../synth/squareoscillator.class';\nexport { StereoSignal } from '../synth/stereosignal.class';\nexport { TriangleOscillator } from '../synth/triangleoscillator.class';\nexport { noise } from '../synth/waveguide';\nexport { WaveGuide } from '../synth/waveguide';\nexport { AuxExciterWaveGuide } from '../synth/waveguide';\nexport { AudioExciterWaveGuide } from '../synth/waveguide';\nexport { CustomExciterWaveGuide } from '../synth/waveguide';","mixes/goodtimes.mix.ts":"import { StereoSignal } from \"../synth/stereosignal.class\";\n\nimport { Freeverb } from \"../fx/freeverb\";\nimport { TestInstrument } from \"../instruments/testinstrument.class\";\n\nimport { Pad } from \"../instruments/pad.class\";\nimport { Kick2 } from \"../instruments/drums/kick2.class\";\nimport { Rimshot } from \"../instruments/drums/rimshot.class\";\nimport { DriveLead } from \"../instruments/drivelead.class\";\n\nimport { Hihat } from \"../instruments/hihat.class\";\nimport { DelayLine } from \"../fx/delayline\";\nimport { SAMPLERATE } from \"../environment\";\nimport { SquareLead } from \"../instruments/squarelead.class\";\n\nimport { TriBandStereoCompressor } from \"../fx/tribandstereocompressor\";\nimport { EQBand } from \"../fx/eqband\";\nimport { SawBass2 } from \"../instruments/bass/sawbass2.class\";\n\nexport const PATTERN_SIZE_SHIFT: usize = 4;\nexport const BEATS_PER_PATTERN_SHIFT: usize = 2;\n\nconst gain: f32 = 0.2;\nconst ENABLE_MULTIBAND_COMPRESSOR = false;\n\nlet flute = new TestInstrument();\nlet drivelead = new DriveLead();\nlet bass = new SawBass2();\nlet pad1 = new Pad();\nlet pad2 = new Pad();\nlet pad3 = new Pad();\nlet kick = new Kick2();\nlet rimshot = new Rimshot();\nlet hihat = new Hihat();\nlet squarelead = new SquareLead();\n\nlet freeverb = new Freeverb();\n\nlet delayLeft: DelayLine = new DelayLine(SAMPLERATE * 0.5 as usize);\nlet delayRight: DelayLine = new DelayLine(SAMPLERATE * 0.5 as usize);\n    \nlet echoline = new StereoSignal();\nlet reverbline = new StereoSignal();\nlet mainline = new StereoSignal();\n\nlet tribandstereocompressor = new TriBandStereoCompressor(20,500,7000,19500);\nlet eqbandl = new EQBand(20, 19500);\nlet eqbandr = new EQBand(20, 19500);\n\nexport function setChannelValue(channel: usize, value: f32): void {\n    switch(channel) {\n        case 0:\n            flute.note = value;\n            break;\n        case 1:\n            bass.note = value;\n            break;\n        case 2:\n            pad1.note = value;\n            break;\n        case 3:\n            pad2.note = value;\n            break;\n        case 4:\n            pad3.note = value;\n            break;\n        case 5:\n            kick.note = value;\n            break;\n        case 6:\n            rimshot.note = value;\n            break;\n        case 7:\n            drivelead.note = value;\n            break;\n        case 8:\n            hihat.note = value;\n            break;\n        case 9:\n            squarelead.note = value;\n            break;\n    }\n    \n}\n\nexport function mixernext(leftSampleBufferPtr: usize, rightSampleBufferPtr: usize): void {  \n    mainline.clear()\n    reverbline.clear();\n    echoline.clear();\n    \n    flute.next();\n    pad1.next(); \n    pad2.next();\n    pad3.next(); \n    kick.next();\n    rimshot.next();\n    hihat.next();\n    bass.next(); \n    drivelead.next();\n    squarelead.next();\n\n    mainline.addStereoSignal(flute.signal, 0.6, 0.0);\n    echoline.addStereoSignal(flute.signal, 0.5, 1.0);\n    \n    mainline.addStereoSignal(pad1.signal, 0.5, 0.25);\n    echoline.addStereoSignal(pad1.signal, 0.3, 0.25); \n    mainline.addStereoSignal(pad2.signal, 0.5, 0.5);\n    echoline.addStereoSignal(pad2.signal, 0.25, 0.5);\n    mainline.addStereoSignal(pad3.signal, 0.5, 0.75);\n    echoline.addStereoSignal(pad3.signal, 0.25, 0.75);\n\n    mainline.addStereoSignal(kick.signal, 1.7, 0.5);\n    reverbline.addStereoSignal(kick.signal, 0.08, 0.0);\n    \n    mainline.addStereoSignal(rimshot.signal, 0.75, 0.6);\n    reverbline.addStereoSignal(rimshot.signal, 0.20, 0.4);\n   \n    mainline.addStereoSignal(hihat.signal, 1.0, 0.4);\n    reverbline.addStereoSignal(hihat.signal, 0.2, 0.6);\n\n    mainline.addStereoSignal(bass.signal, 0.6, 0.5);\n    reverbline.addStereoSignal(bass.signal, 0.07, 0.0);\n\n    mainline.addStereoSignal(drivelead.signal, 0.17, 0.4);\n    echoline.addStereoSignal(drivelead.signal, 0.4, 0.6);\n\n    mainline.addStereoSignal(squarelead.signal,0.6, 0.6);\n    echoline.addStereoSignal(squarelead.signal, 0.6, 0.0);\n\n    echoline.left += delayRight.read() * 0.5;\n    echoline.right += delayLeft.read() * 0.5;\n        \n    delayLeft.write_and_advance(echoline.left);\n    delayRight.write_and_advance(echoline.right);\n\n    reverbline.addStereoSignal(echoline, 0.5, 0.5);\n    \n    freeverb.tick(reverbline);\n        \n    let left = gain * (mainline.left + echoline.left + reverbline.left);\n    let right = gain * (mainline.right + echoline.right + reverbline.right);\n\n    if (ENABLE_MULTIBAND_COMPRESSOR) {\n        tribandstereocompressor.process(left,right,0.45, 1.0, 0.9 , 1.3, 1.05, 1.0);\n        left = tribandstereocompressor.stereosignal.left;\n        right  = tribandstereocompressor.stereosignal.right;\n    } else {\n        left = eqbandl.process(left);\n        right = eqbandr.process(right);\n    }\n\n    store<f32>(leftSampleBufferPtr, left);\n    store<f32>(rightSampleBufferPtr, right);    \n}","mixes/midi.mix.ts":"import { midichannels, MidiChannel, MidiVoice, SineOscillator, Envelope, notefreq } from './globalimports';\nimport { outputline } from '../midi/midisynth';\nimport { hardclip } from '../synth/clip';\n\nclass SimpleSine extends MidiVoice {\n    osc: SineOscillator = new SineOscillator();\n    env: Envelope = new Envelope(0.1, 0.0, 1.0, 0.1);\n\n    noteon(note: u8, velocity: u8): void {\n        super.noteon(note, velocity);\n        this.osc.frequency = notefreq(note);\n        this.env.attack();\n    }\n\n    noteoff(): void {\n        this.env.release();\n    }\n\n    isDone(): boolean {\n        return this.env.isDone();\n    }\n\n    nextframe(): void {\n        const signal = this.osc.next() * this.env.next() * this.velocity / 256;\n        this.channel.signal.addMonoSignal(signal, 0.2, 0.7);\n    }\n}\n\nexport function initializeMidiSynth(): void {\n    midichannels[0] = new MidiChannel(6, (channel: MidiChannel) => new SimpleSine(channel));\n}\n\nexport function postprocess(): void {\n    outputline.left = hardclip(outputline.left);\n    outputline.right = hardclip(outputline.right);\n}","mixes/newyear.mix.ts":"/**\n * Mix for \"WASM song\"\n */\nimport { EQBand } from \"../fx/eqband\";\nimport { Envelope } from '../synth/envelope.class';\nimport { Snare } from \"../instruments/snare.class\";\nimport { SawBass3 } from \"../instruments/bass/sawbass3\";\nimport { Eftang } from \"../instruments/lead/eftang\";\nimport { StereoSignal } from \"../synth/stereosignal.class\";\nimport { Kick } from \"../instruments/kick.class\";\nimport { BrassyLead } from \"../instruments/lead/brassy\";\nimport { Hihat } from \"../instruments/hihat.class\";\nimport { WaveShaper } from '../synth/shaper';\nimport { createInstrumentArray } from '../common/mixcommon';\nimport { Freeverb } from \"../fx/freeverb\";\nimport { DelayLine } from \"../fx/delayline\";\nimport { SAMPLERATE } from \"../environment\";\nimport { BiQuadFilter, FilterType, Q_BUTTERWORTH } from '../synth/biquad';\nimport { notefreq } from '../synth/note';\nimport { SineOscillator } from '../synth/sineoscillator.class';\nimport { SawOscillator } from '../synth/sawoscillator.class';\nimport { TriBandStereoCompressor } from \"../fx/tribandstereocompressor\";\n\nexport const PATTERN_SIZE_SHIFT: usize = 4;\nexport const BEATS_PER_PATTERN_SHIFT: usize = 2;\n\nconst tribandstereocompressor = new TriBandStereoCompressor(0.05, 25,150,1500,20000);\nconst ENABLE_MULTIBAND_COMPRESSOR = true;\n\nconst gain: f32 = 0.5;\n\nconst bass = new SawBass3();\nconst lead = new Eftang();\nconst kick = new Kick();\nconst snare = new Snare();\nconst hihat = new Hihat();\n\n\nexport class FlatPad {\n    private _note: f32;\n    readonly envelope: Envelope = new Envelope(0.01, 0.1, 1.0, 0.1);\n    readonly filterenvelope: Envelope = new Envelope(0.001, 1.0, 1.0, 0.1);\n    readonly hipassfilterenvelope: Envelope = new Envelope(0.02, 3, 0.2, 2.0);\n    readonly sawoscillator: SawOscillator = new SawOscillator();\n    readonly sawoscillator2: SawOscillator = new SawOscillator();\n    readonly sawoscillator3: SawOscillator = new SawOscillator();\n    readonly sawoscillator4: SawOscillator = new SawOscillator();\n    readonly sawoscillator5: SawOscillator = new SawOscillator();\n    readonly lfo: SineOscillator = new SineOscillator();\n    \n    readonly filterl: BiQuadFilter = new BiQuadFilter();\n    readonly filterr: BiQuadFilter = new BiQuadFilter();\n    readonly signal: StereoSignal = new StereoSignal();\n  \n    set note(note: f32) {        \n        if(note > 1) {            \n            this.lfo.frequency = 1;\n            this.lfo.position = 0;\n            this.sawoscillator.frequency = notefreq(note);\n            this.sawoscillator2.frequency = notefreq(note + 0.03);\n            this.sawoscillator3.frequency = notefreq(note - 0.03);\n            this.sawoscillator4.frequency = notefreq(note + 0.06);\n            this.sawoscillator5.frequency = notefreq(note - 0.06);\n            \n            this.envelope.attack();           \n            this.filterenvelope.attack();             \n            this.hipassfilterenvelope.attack();  \n            this._note = note;       \n        } else {\n            this.envelope.release();\n            this.filterenvelope.release();\n            this.hipassfilterenvelope.release();   \n        }\n        \n    }\n\n    get note(): f32 {\n        return this._note;\n    }\n\n    next(): void {        \n        let env: f32 = this.envelope.next();\n        if(env === 0) {\n            this.signal.clear();\n            return;\n        \n        }\n\n        const lfo: f32 = this.lfo.next();\n\n        const note = this.note;\n        if(note<2) {\n            return;\n        }\n        this.sawoscillator2.frequency = notefreq(note + 0.05 + (0.02 * lfo));\n        this.sawoscillator3.frequency = notefreq(note - 0.05 - (0.02 * lfo));\n        this.sawoscillator4.frequency = notefreq(note + 0.1 + (0.03 * lfo));\n        this.sawoscillator5.frequency = notefreq(note - 0.1 - (0.03 * lfo));\n        \n        \n        let osc: f32 = this.sawoscillator.next();\n        let osc2: f32 = this.sawoscillator2.next();\n        let osc3: f32 = this.sawoscillator3.next();\n        let osc4: f32 = this.sawoscillator4.next();\n        let osc5: f32 = this.sawoscillator5.next();\n        \n        let left = env * (osc + osc2 + osc5);\n        let right = env * (osc + osc3 + osc4 );\n\n        const filterlfo: f32 = (lfo * 0.9) + 1;\n        this.filterl.update_coeffecients(FilterType.LowPass, SAMPLERATE, \n            200 + this.filterenvelope.next() * filterlfo * 10000 + 20 * (127 - this.note), Q_BUTTERWORTH);\n        \n        this.filterr.update_coeffecients(FilterType.LowPass, SAMPLERATE, \n                200 + this.filterenvelope.next() * filterlfo * 10000 + 20 * (this.note), Q_BUTTERWORTH);\n            \n        this.signal.left = this.filterl.process(left );\n        this.signal.right = this.filterr.process(right );\n    } \n}\n  \nconst pads: FlatPad[] = createInstrumentArray<FlatPad>(10, () => new FlatPad());\nlet padsVolume: f32 = 1.0;\n\nclass SineLead {\n    private _note: f32;\n    \n    readonly osc: SineOscillator = new SineOscillator();\n    readonly env1: Envelope = new Envelope(0.02, 0.15, 0.5, 0.3);    \n    readonly signal: StereoSignal = new StereoSignal();\n\n\n    set note(note: f32) {        \n        if(note > 1) { \n            this.osc.frequency = notefreq(note);\n            this._note = note;\n            this.env1.attack();           \n        } else {\n            this.env1.release();            \n        }        \n    }\n\n    get note(): f32 {\n        return this._note;\n    }\n\n    next(): void {        \n        const env1: f32 = this.env1.next();\n                \n        let osc: f32 = this.osc.next();        \n        osc *= env1;\n\n        const pan = this._note / 127;\n\n        this.signal.left = osc * pan;\n        this.signal.right = osc * (1 - pan);                \n    } \n}\n\nexport class DriveLead {\n    private _note: f32;\n    readonly envelope: Envelope = new Envelope(0.03, 1.0, 0.6, 0.2);\n    readonly sawoscillatorl: SawOscillator = new SawOscillator();\n    readonly sawoscillatorr: SawOscillator = new SawOscillator();\n    readonly shaper: WaveShaper = new WaveShaper();\n    readonly signal: StereoSignal = new StereoSignal();\n    readonly lfoenvelope: Envelope = new Envelope(1.0, 0, 1.0, 0.1);\n    readonly lfo: SineOscillator = new SineOscillator();\n    private baseFrequency : f32;\n    private pitchbend: f32 = 0;\n\n    set note(note: f32) {        \n        if(note > 1) {   \n            this.shaper.drive = 0.5;         \n            this.baseFrequency = notefreq(note + this.pitchbend);\n            this.lfo.frequency = 8;\n            this.envelope.attack();    \n            this.lfoenvelope.attack();                    \n            this._note = note;\n        } else {\n            this.envelope.release();\n            this.lfoenvelope.release();\n        }\n        \n    }\n\n    get note(): f32 {\n        return this._note;\n    }\n\n    setPitchbend(bend: f32): void {\n      \tthis.pitchbend = bend;\n      \tthis.baseFrequency = notefreq(this._note + bend);              \t\n    }\n\n    next(): void {        \n        let env: f32 = this.envelope.next();\n        if(env===0) {\n            this.signal.clear();\n            return;\n        }       \n        \n        let lfo: f32 = this.lfo.next() * 3 * this.lfoenvelope.next();\n        this.sawoscillatorl.frequency = this.baseFrequency + lfo + 0.5;\n        this.sawoscillatorr.frequency = this.baseFrequency + lfo - 0.5;\n        \n        let left = env* this.sawoscillatorl.next() + this.signal.right * 0.5;\n        left = this.shaper.process(left);\n        \n        let right = env* this.sawoscillatorr.next() + this.signal.left * 0.5;\n        right = this.shaper.process(right);\n        \n        this.signal.left = left * 0.5 + right;\n        this.signal.right = right * 0.5 + left;  \n    } \n}\n\nconst sinelead = new SineLead();\nconst drivelead = new DriveLead();\n\nexport function setChannelValue(channel: usize, value: f32): void {\n  const setChannelValueFunctions: usize[] = [\n    changetype<usize>((value:f32): void => {bass.note = value;}),\n    changetype<usize>((value:f32): void => {lead.note = value;}),\n    changetype<usize>((value:f32): void => {sinelead.note = value;}),\n    changetype<usize>((value:f32): void => {kick.note = value;}),\n    changetype<usize>((value:f32): void => {snare.note = value;}),\n    changetype<usize>((value:f32): void => {hihat.note = value;}),\n    changetype<usize>((value:f32): void => {pads[0].note = value;}),\n    changetype<usize>((value:f32): void => {pads[1].note = value;}),\n    changetype<usize>((value:f32): void => {pads[2].note = value;}),\n    changetype<usize>((value:f32): void => {pads[3].note = value;}),    \n    changetype<usize>((value:f32): void => {pads[4].note = value;}),    \n    changetype<usize>((value:f32): void => {pads[5].note = value;}),\n    changetype<usize>((value:f32): void => {pads[6].note = value;}),\n    changetype<usize>((value:f32): void => {pads[7].note = value;}),\n    changetype<usize>((value:f32): void => {pads[8].note = value;}),\n    changetype<usize>((value:f32): void => {pads[9].note = value;}),\n    changetype<usize>((value:f32): void => {\n      if(value >  0) {\n\t      padsVolume = value / 100.0;\n      }\n    }),\n    changetype<usize>((value:f32): void => {drivelead.note = value;}),\n    changetype<usize>((value:f32): void => {\n      if(value > 0) {\n\t      drivelead.setPitchbend((value - 64) / 32);\n      }\n    })\n    \n  ];\n\n  changetype<(val: f32) => void>(setChannelValueFunctions[channel])(value);\n}\n\n\nconst mainline = new StereoSignal();\nconst reverbline = new StereoSignal();\nconst freeverb = new Freeverb();\n\nconst delayframes = (SAMPLERATE * (6/8) * 60 / 120) as usize;\nlet delayLeft: DelayLine = new DelayLine(delayframes);\nlet delayRight: DelayLine = new DelayLine(delayframes);\n    \nlet echoline = new StereoSignal();\n\n\nlet eqbandl = new EQBand(20, 19500);\nlet eqbandr = new EQBand(20, 19500);\n\nexport function mixernext(leftSampleBufferPtr: usize, rightSampleBufferPtr: usize): void {  \n    let left: f32 = 0;\n    let right: f32 = 0;\n\n    mainline.clear();\n    reverbline.clear();\n    echoline.clear();\n\n    bass.next();\n    mainline.addStereoSignal(bass.signal, 1.0, 0.5);\n    reverbline.addStereoSignal(bass.signal, 0.0, 0.5);\n\n    lead.next();\n    mainline.addStereoSignal(lead.signal, 0.8, 0.5);\n    echoline.addStereoSignal(lead.signal, 0.8, 0.5);\n\n  \tdrivelead.next();\n    mainline.addStereoSignal(drivelead.signal, 0.1, 0.5);\n    echoline.addStereoSignal(drivelead.signal, 0.4, 0.5);\n\n  \tsinelead.next();\n    mainline.addStereoSignal(sinelead.signal, 1.0, 0.5);\n    echoline.addStereoSignal(sinelead.signal, 1.2, 0.5);\n\n    kick.next();\n    mainline.addStereoSignal(kick.signal, 0.8, 0.5);\n\n    snare.next();\n    mainline.addStereoSignal(snare.signal, 0.8, 0.5);   \n\n    hihat.next();\n    mainline.addStereoSignal(hihat.signal, 0.8, 0.5);\n\n    pads.forEach(pad => {\n        pad.next();\n        mainline.addStereoSignal(pad.signal, 0.45 * padsVolume, 0.5);\n    });\n    \n    echoline.left += delayRight.read() * 0.7;\n    echoline.right += delayLeft.read() * 0.7;\n\n    delayLeft.write_and_advance(echoline.left);\n    delayRight.write_and_advance(echoline.right);\n\n    freeverb.tick(reverbline);\n\n    left = gain * (mainline.left + reverbline.left + echoline.left);\n    right = gain * (mainline.right + reverbline.right + echoline.right);\n\n  \tif (ENABLE_MULTIBAND_COMPRESSOR) {\n        tribandstereocompressor.process(left,right,0.45, 0.6, 0.9 , 1.20, 1.05, 1.0);\n        left = tribandstereocompressor.stereosignal.left;\n        right  = tribandstereocompressor.stereosignal.right;\n    } else {\n        left = eqbandl.process(left);\n        right = eqbandr.process(right);\n    }\n\n    store<f32>(leftSampleBufferPtr, left);\n    store<f32>(rightSampleBufferPtr, right);    \n}","mixes/protracker.mix.ts":"import { EQBand } from \"../fx/eqband\";\n\nimport { Snare } from \"../instruments/snare.class\";\nimport { SawBass3 } from \"../instruments/bass/sawbass3\";\nimport { Eftang } from \"../instruments/lead/eftang\";\nimport { StereoSignal } from \"../synth/stereosignal.class\";\nimport { Kick } from \"../instruments/kick.class\";\nimport { BrassyLead } from \"../instruments/lead/brassy\";\nimport { Hihat } from \"../instruments/hihat.class\";\nimport { FlatPad } from \"../instruments/pad/flatpad.class\";\nimport { createInstrumentArray } from '../common/mixcommon';\nimport { Freeverb } from \"../fx/freeverb\";\n\nexport const PATTERN_SIZE_SHIFT: usize = 4;\nexport const BEATS_PER_PATTERN_SHIFT: usize = 2;\n\nconst gain: f32 = 0.2;\n\nconst bass = new SawBass3();\nconst lead = new Eftang();\nconst kick = new Kick();\nconst snare = new Snare();\nconst hihat = new Hihat();\nconst brassylead = new BrassyLead();\nconst pads: FlatPad[] = createInstrumentArray<FlatPad>(4, () => new FlatPad());\n\nexport function setChannelValue(channel: usize, value: f32): void {\n    switch(channel) {\n        case 0:\n            bass.note = value;\n            break;\n        case 1:\n            lead.note = value;\n            break;\n        case 2:\n            kick.note = value;\n            break;\n        case 3:\n            snare.note = value;\n            break;\n        case 4:\n            hihat.note = value;\n            break;\n        case 5:\n            brassylead.note = value;\n            break;\n        case 6:\n        case 7:\n        case 8:\n        case 9:\n            pads[channel-6].note = value;\n            break;       \n            \n    }\n    \n}\n\n\nconst mainline = new StereoSignal();\nconst reverbline = new StereoSignal();\nconst freeverb = new Freeverb();\n\nlet eqbandl = new EQBand(20, 19500);\nlet eqbandr = new EQBand(20, 19500);\n\nexport function mixernext(leftSampleBufferPtr: usize, rightSampleBufferPtr: usize): void {  \n    let left: f32 = 0;\n    let right: f32 = 0;\n\n    mainline.clear();\n    reverbline.clear();\n\n    bass.next();\n    mainline.addStereoSignal(bass.signal, 0.2, 0.5);\n    reverbline.addStereoSignal(bass.signal, 0.1, 0.5);\n\n    lead.next();\n    mainline.addStereoSignal(lead.signal, 0.2, 0.5);\n    reverbline.addStereoSignal(lead.signal, 0.02, 0.5);\n\n    kick.next();\n    mainline.addStereoSignal(kick.signal, 0.2, 0.5);\n\n    snare.next();\n    mainline.addStereoSignal(snare.signal, 0.2, 0.5);   \n\n    hihat.next();\n    mainline.addStereoSignal(hihat.signal, 0.2, 0.5);\n\n    brassylead.next();\n    mainline.addStereoSignal(brassylead.signal, 0.5, 0.5);\n    reverbline.addStereoSignal(brassylead.signal, 0.1, 0.5);\n\n    pads.forEach(pad => {\n        pad.next();\n        mainline.addStereoSignal(pad.signal, 0.5, 0.5);\n        \n    });\n    \n    freeverb.tick(reverbline);\n\n    left = gain * (mainline.left + reverbline.left );\n    right = gain * (mainline.right + reverbline.right );\n\n    left = eqbandl.process(left);\n    right = eqbandr.process(right);\n    \n    store<f32>(leftSampleBufferPtr, left);\n    store<f32>(rightSampleBufferPtr, right);    \n}","mixes/shuffle.mix.ts":"import { StereoSignal } from \"../synth/stereosignal.class\";\n\nimport { Freeverb } from \"../fx/freeverb\";\nimport { DelayLine } from \"../fx/delayline\";\nimport { SAMPLERATE } from \"../environment\";\n\nimport { TriBandStereoCompressor } from \"../fx/tribandstereocompressor\";\nimport { EQBand } from \"../fx/eqband\";\nimport { SubPiano } from \"../instruments/piano/subpiano\";\nimport { Kick2 } from \"../instruments/drums/kick2.class\";\nimport { Snare } from \"../instruments/snare.class\";\nimport { DeepBass } from \"../instruments/bass/deepbass\";\nimport { Eftang } from \"../instruments/lead/eftang\";\nimport { SoftPad } from \"../instruments/pad/softpad.class\";\nimport { Hihat } from \"../instruments/hihat.class\";\nimport { SineLead } from \"../instruments/lead/sinelead\";\nimport { DriveLead } from \"../instruments/drivelead.class\";\n\nexport const PATTERN_SIZE_SHIFT: usize = 3;\nexport const BEATS_PER_PATTERN_SHIFT: usize = 0;\n\nconst gain: f32 = 0.13;\nconst ENABLE_MULTIBAND_COMPRESSOR = true;\n\nlet freeverb = new Freeverb();\n\nconst delayframes = (SAMPLERATE * (3/8) * 60 / 70) as usize;\nlet delayLeft: DelayLine = new DelayLine(delayframes);\nlet delayRight: DelayLine = new DelayLine(delayframes);\n    \nlet echoline = new StereoSignal();\nlet reverbline = new StereoSignal();\nlet mainline = new StereoSignal();\n\nlet tribandstereocompressor = new TriBandStereoCompressor(20,500,7000,19500);\nlet eqbandl = new EQBand(20, 19500);\nlet eqbandr = new EQBand(20, 19500);\n\nfunction createInstrumentArray<T>(length: i32, factoryFunc: () => T): T[] {\n    const arr = new Array<T>(length);\n    for(let n  = 0; n < length;n++) {\n        arr[n] = factoryFunc();\n    }\n    return arr;\n}\n\nconst pianos: SubPiano[] = createInstrumentArray<SubPiano>(8, () => new SubPiano());\nconst pads: SoftPad[] = createInstrumentArray<SoftPad>(8, () => new SoftPad());\nconst driveleads: DriveLead[] = createInstrumentArray<DriveLead>(3, () => new DriveLead());\n\nconst kick = new Kick2();\nconst bass = new DeepBass();\nconst eftang = new Eftang();\nconst snare = new Snare();\nconst hihat = new Hihat();\nconst sinelead = new SineLead();\n\nexport function setChannelValue(channel: usize, value: f32): void {\n    switch(true) {\n        case (channel < 8):\n            pianos[channel].note = value;\n            break;\n        case channel === 8:\n            kick.note = value;\n            break;\n        case channel === 9:\n            snare.note = value;\n            break;\n        case channel === 10:\n            hihat.note = value;\n            break;\n        case channel === 11:\n            bass.note = value\n            break;\n        case channel === 12:\n            eftang.note = value;\n            break;\n        case channel < 21:\n            pads[channel - 13].note = value;\n            break;\n        case channel === 21:\n            sinelead.note = value;\n            break;\n        case channel < 25:\n            driveleads[channel - 22].note = value;\n            break;\n        case channel === 25:\n            if(value > 1) {\n                for(let n = 0; n<driveleads.length; n++) {\n                    driveleads[n].setPitchbend(value - 64);\n                }\n            }\n            break;\n    }\n}\n\nexport function mixernext(leftSampleBufferPtr: usize, rightSampleBufferPtr: usize): void {  \n    mainline.clear()\n    reverbline.clear();\n    echoline.clear();\n    \n    for(let n = 0;n<pianos.length;n++) {\n        const piano = pianos[n];\n        piano.next();\n        mainline.addStereoSignal(piano.signal, 0.4, 0.5);\n        reverbline.addStereoSignal(piano.signal, 0.1, 0.5);    \n    }\n    for(let n = 0;n<pads.length;n++) {\n        const pad = pads[n];\n        pad.next();\n        mainline.addStereoSignal(pad.signal, 0.4, 0.5);\n        echoline.addStereoSignal(pad.signal, 0.4, 0.5);    \n    }\n\n    for(let n = 0;n<driveleads.length;n++) {\n        const drivelead = driveleads[n];\n        drivelead.next();\n        \n        const pan = ((n + 1) * 0.25) as f32;\n        mainline.addStereoSignal(drivelead.signal, 0.1, pan);\n        echoline.addStereoSignal(drivelead.signal, 0.45, 1 - pan);    \n    }\n\n    kick.next();\n    mainline.addStereoSignal(kick.signal, 1.5, 0.5);\n    reverbline.addStereoSignal(kick.signal, 0.2, 0.5); \n\n    hihat.next();\n    mainline.addStereoSignal(hihat.signal, 1.5, 0.5);\n    // reverbline.addStereoSignal(hihat.signal, 0.0, 0.5); \n\n    bass.next();\n    mainline.addStereoSignal(bass.signal, 4.5, 0.5);\n    reverbline.addStereoSignal(bass.signal, 0.3, 0.5);    \n\n    eftang.next();\n    mainline.addStereoSignal(eftang.signal, 2.1, 0.5);\n    echoline.addStereoSignal(eftang.signal, 1.8, 0.5);    \n\n    sinelead.next();\n    mainline.addStereoSignal(sinelead.signal, 2.4, 0.5);\n    echoline.addStereoSignal(sinelead.signal, 2.0, 0.5);    \n\n    snare.next();\n    mainline.addStereoSignal(snare.signal, 1.0, 0.5);\n    reverbline.addStereoSignal(snare.signal, 0.01, 0.5); \n\n    echoline.left += delayRight.read() * 0.7;\n    echoline.right += delayLeft.read() * 0.7;\n        \n    delayLeft.write_and_advance(echoline.left);\n    delayRight.write_and_advance(echoline.right);\n\n    reverbline.addStereoSignal(echoline, 0.5, 0.5);\n    \n    freeverb.tick(reverbline);\n        \n    let left = gain * (mainline.left + echoline.left + reverbline.left);\n    let right = gain * (mainline.right + echoline.right + reverbline.right);\n\n    if (ENABLE_MULTIBAND_COMPRESSOR) {\n        tribandstereocompressor.process(left,right,0.45, 1.0, 0.9 , 1.20, 1.05, 1.0);\n        left = tribandstereocompressor.stereosignal.left;\n        right  = tribandstereocompressor.stereosignal.right;\n    } else {\n        left = eqbandl.process(left);\n        right = eqbandr.process(right);\n    }\n\n    // clip\n    if (Math.abs(left) > 1.0) {\n        left = 1.0;\n    }\n\n    if (Math.abs(right) > 1.0) {\n        right = 1.0;\n    }\n\n    store<f32>(leftSampleBufferPtr, left);\n    store<f32>(rightSampleBufferPtr, right);    \n}","mixes/simple.mix.ts":"import { SawOscillator, Instrument, Noise, BiQuadFilter, FilterType, \n    StereoSignal,\n    Freeverb, SineOscillator, Envelope, notefreq } from \"./globalimports\";\n  import { SAMPLERATE } from '../environment';\n  \n  export const PATTERN_SIZE_SHIFT: usize = 4;\n  export const BEATS_PER_PATTERN_SHIFT: usize = 2;\n  \n  const mainline = new StereoSignal();\n  const reverbline = new StereoSignal();\n  const freeverb = new Freeverb();\n  \n  class Kick extends Instrument {\n      private velocity: f32;\n      envelope: Envelope = new Envelope(0.0, 0.2, 0, 0.2);\n      filterenvelope: Envelope = new Envelope(0.0, 0.05, 0.05, 0.1);\n      sawoscillator: SawOscillator = new SawOscillator();\n      noise: Noise = new Noise();\n      \n      filter: BiQuadFilter = new BiQuadFilter();\n      \n      set note(note: f32) {        \n          if(note > 1) {            \n              this.sawoscillator.frequency = 150;\n              this.velocity = note / 16;   \n              this.envelope.attack();           \n              this.filterenvelope.attack();             \n          } else {\n              this.envelope.release();\n              this.filterenvelope.release();\n          }\n      }\n  \n      next(): void {        \n          let env: f32 = this.envelope.next();\n          this.sawoscillator.frequency = 20.0 + (env * 150.0);\n          \n          this.filter.update_coeffecients(FilterType.LowPass, SAMPLERATE, \n              40 + (this.filterenvelope.next() * 2000), 0.2);\n  \n          let osc1: f32 = this.envelope.next() * this.velocity * this.sawoscillator.next() * 0.8 + this.noise.next();\n  \n          osc1 = this.filter.process(osc1);\n          \n            const val = env * osc1;\n        \n          mainline.left+=val;\n          mainline.right+=val;\n      } \n  }\n  \n  class Lead extends Instrument {\n    osc: SineOscillator = new SineOscillator();\n    env: Envelope = new Envelope(0.1,0.1,1.0,0.1);\n    \n    set note(note: f32) {\n      if(note > 1) {\n          this.osc.frequency = notefreq(note);\n        this.env.attack();\n      } else if (note === 0) {\n        this.env.release();\n      }\n    }\n    @inline\n    next(): void {\n      const val = this.osc.next() * this.env.next() * 0.3;\n      mainline.left += val;\n      mainline.right += val;\n    }\n  }\n  \n  \n  const voices: Instrument[] = [\n        new Kick(),\n      new Lead(),\n        new Lead(),\n        new Lead(),\n        new Lead()\n  ];\n  \n  export function setChannelValue(channel: usize, value: f32): void {\n    voices[channel].note = value;\n  }\n  \n  \n  @inline\n  export function mixernext(leftSampleBufferPtr: usize, rightSampleBufferPtr: usize): void {  \n    mainline.clear();\n    reverbline.clear();\n  \n    for(var n=0;n<voices.length;n++) {\n      voices[n].next();\n    }\n  \n    freeverb.tick(reverbline);\n  \n    store<f32>(leftSampleBufferPtr, mainline.left + reverbline.left);\n    store<f32>(rightSampleBufferPtr, mainline.right + reverbline.right);    \n  }","mixes/test.mix.ts":"// This mix was used in the song \"Groove is in the code\"\n\nimport { StereoSignal } from \"../synth/stereosignal.class\";\n\nimport { Freeverb } from \"../fx/freeverb\";\nimport { TestInstrument } from \"../instruments/testinstrument.class\";\nimport { SawBass } from \"../instruments/sawbass.class\";\nimport { Pad } from \"../instruments/pad.class\";\nimport { Kick } from \"../instruments/kick.class\";\nimport { Snare } from \"../instruments/snare.class\";\nimport { DriveLead } from \"../instruments/drivelead.class\";\n\nimport { Hihat } from \"../instruments/hihat.class\";\nimport { DelayLine } from \"../fx/delayline\";\nimport { SAMPLERATE } from \"../environment\";\nimport { SquareLead } from \"../instruments/squarelead.class\";\n\nimport { TriBandStereoCompressor } from \"../fx/tribandstereocompressor\";\n\nexport const PATTERN_SIZE_SHIFT: usize = 4;\nexport const BEATS_PER_PATTERN_SHIFT: usize = 2;\n\nconst gain: f32 = 0.15;\nconst ENABLE_MULTIBAND_COMPRESSOR = false;\n\nlet flute = new TestInstrument();\nlet drivelead = new DriveLead();\nlet bass = new SawBass();\nlet pad1 = new Pad();\nlet pad2 = new Pad();\nlet pad3 = new Pad();\nlet kick = new Kick();\nlet snare = new Snare();\nlet hihat = new Hihat();\nlet squarelead = new SquareLead();\n\nlet freeverb = new Freeverb();\n\nlet delayLeft: DelayLine = new DelayLine(SAMPLERATE * 0.5 as usize);\nlet delayRight: DelayLine = new DelayLine(SAMPLERATE * 0.5 as usize);\n    \nlet echoline = new StereoSignal();\nlet reverbline = new StereoSignal();\nlet mainline = new StereoSignal();\n\nlet tribandstereocompressor = new TriBandStereoCompressor(15,500,8000,19000);\n\nexport function setChannelValue(channel: usize, value: f32): void {\n    switch(channel) {\n        case 0:\n            flute.note = value;\n            break;\n        case 1:\n            bass.note = value;\n            break;\n        case 2:\n            pad1.note = value;\n            break;\n        case 3:\n            pad2.note = value;\n            break;\n        case 4:\n            pad3.note = value;\n            break;\n        case 5:\n            kick.note = value;\n            break;\n        case 6:\n            snare.note = value;\n            break;\n        case 7:\n            drivelead.note = value;\n            break;\n        case 8:\n            hihat.note = value;\n            break;\n        case 9:\n            squarelead.note = value;\n            break;\n    }\n    \n}\n\nexport function mixernext(leftSampleBufferPtr: usize, rightSampleBufferPtr: usize): void {  \n    mainline.clear()\n    reverbline.clear();\n    echoline.clear();\n    \n    flute.next();\n    pad1.next(); \n    pad2.next();\n    pad3.next(); \n    kick.next();\n    snare.next();\n    hihat.next();\n    bass.next(); \n    drivelead.next();\n    squarelead.next();\n\n    mainline.addStereoSignal(flute.signal, 0.7, 0.0);\n    echoline.addStereoSignal(flute.signal, 0.6, 1.0);\n    \n    mainline.addStereoSignal(pad1.signal, 0.58, 0.25);\n    echoline.addStereoSignal(pad1.signal, 0.35, 0.25); \n    mainline.addStereoSignal(pad2.signal, 0.58, 0.5);\n    echoline.addStereoSignal(pad2.signal, 0.30, 0.5);\n    mainline.addStereoSignal(pad3.signal, 0.58, 0.75);\n    echoline.addStereoSignal(pad3.signal, 0.30, 0.75);\n\n    mainline.addStereoSignal(kick.signal, 1.6, 0.5);\n    reverbline.addStereoSignal(kick.signal, 0.05, 0.0);\n    \n    mainline.addStereoSignal(snare.signal, 0.38, 0.6);\n    echoline.addStereoSignal(snare.signal, 0.1, 0.4);\n   \n    mainline.addStereoSignal(hihat.signal, 0.7, 0.4);\n    reverbline.addStereoSignal(hihat.signal, 0.05, 0.6);\n\n    mainline.addStereoSignal(bass.signal, 1.2, 0.5);\n    reverbline.addStereoSignal(bass.signal, 0.1, 0.0);\n\n    mainline.addStereoSignal(drivelead.signal, 0.17, 0.4);\n    echoline.addStereoSignal(drivelead.signal, 0.4, 0.6);\n\n    mainline.addStereoSignal(squarelead.signal,0.6, 0.6);\n    echoline.addStereoSignal(squarelead.signal, 0.6, 0.0);\n\n    echoline.left += delayRight.read() * 0.5;\n    echoline.right += delayLeft.read() * 0.5;\n        \n    delayLeft.write_and_advance(echoline.left);\n    delayRight.write_and_advance(echoline.right);\n\n    reverbline.addStereoSignal(echoline, 0.5, 0.5);\n    \n    freeverb.tick(reverbline);\n        \n    let left = gain * (mainline.left + echoline.left + reverbline.left);\n    let right = gain * (mainline.right + echoline.right + reverbline.right);\n\n    if (ENABLE_MULTIBAND_COMPRESSOR) {\n        tribandstereocompressor.process(left,right,0.3, 0.3, 0.5 , 2.0, 0.80, 0.9);\n        left = tribandstereocompressor.stereosignal.left;\n        right = tribandstereocompressor.stereosignal.right;\n    } else {\n        left = left;\n        right = right;\n    }\n\n    store<f32>(leftSampleBufferPtr, left);\n    store<f32>(rightSampleBufferPtr, right);    \n}","mixes/webchip.mix.ts":"import { StereoSignal } from \"../synth/stereosignal.class\";\n\nimport { Freeverb } from \"../fx/freeverb\";\nimport { DelayLine } from \"../fx/delayline\";\nimport { SAMPLERATE } from \"../environment\";\n\nimport { TriBandStereoCompressor } from \"../fx/tribandstereocompressor\";\nimport { EQBand } from \"../fx/eqband\";\nimport { SubPiano } from \"../instruments/piano/subpiano\";\nimport { Kick2 } from \"../instruments/drums/kick2.class\";\nimport { Snare2 } from \"../instruments/drums/snare2.class\";\nimport { SawBass3 } from \"../instruments/bass/sawbass3\";\nimport { Eftang } from \"../instruments/lead/eftang\";\nimport { SoftPad } from \"../instruments/pad/softpad.class\";\nimport { Hihat } from \"../instruments/hihat.class\";\nimport { SineLead } from \"../instruments/lead/sinelead\";\n\nexport const PATTERN_SIZE_SHIFT: usize = 4;\nexport const BEATS_PER_PATTERN_SHIFT: usize = 2;\n\nconst gain: f32 = 0.13;\nconst ENABLE_MULTIBAND_COMPRESSOR = false;\n\nlet freeverb = new Freeverb();\n\nconst delayframes = (SAMPLERATE * (2/3) * 60 / 110) as usize;\nlet delayLeft: DelayLine = new DelayLine(delayframes);\nlet delayRight: DelayLine = new DelayLine(delayframes);\n    \nlet echoline = new StereoSignal();\nlet reverbline = new StereoSignal();\nlet mainline = new StereoSignal();\n\nlet tribandstereocompressor = new TriBandStereoCompressor(20,500,7000,19500);\nlet eqbandl = new EQBand(20, 19500);\nlet eqbandr = new EQBand(20, 19500);\n\nfunction createInstrumentArray<T>(length: i32, factoryFunc: () => T): T[] {\n    const arr = new Array<T>(length);\n    for(let n  = 0; n < length;n++) {\n        arr[n] = factoryFunc();\n    }\n    return arr;\n}\n\nconst pianos: SubPiano[] = createInstrumentArray<SubPiano>(8, () => new SubPiano());\nconst pads: SoftPad[] = createInstrumentArray<SoftPad>(8, () => new SoftPad());\n\nconst kick = new Kick2();\nconst bass = new SawBass3();\nconst eftang = new Eftang();\nconst snare = new Snare2();\nconst hihat = new Hihat();\nconst sinelead = new SineLead();\n\nexport function setChannelValue(channel: usize, value: f32): void {\n    switch(true) {\n        case (channel < 8):\n            pianos[channel].note = value;\n            break;\n        case channel === 8:\n            kick.note = value;\n            break;\n        case channel === 9:\n            snare.note = value;\n            break;\n        case channel === 10:\n            hihat.note = value;\n            break;\n        case channel === 11:\n            bass.note = value\n            break;\n        case channel === 12:\n            eftang.note = value;\n            break;\n        case channel < 21:\n            pads[channel - 13].note = value;\n            break;\n        case channel === 21:\n            sinelead.note = value;\n            break;\n    }\n}\n\nexport function mixernext(leftSampleBufferPtr: usize, rightSampleBufferPtr: usize): void {  \n    mainline.clear()\n    reverbline.clear();\n    echoline.clear();\n    \n    for(let n = 0;n<pianos.length;n++) {\n        const piano = pianos[n];\n        piano.next();\n        mainline.addStereoSignal(piano.signal, 0.4, 0.5);\n        reverbline.addStereoSignal(piano.signal, 0.1, 0.5);    \n    }\n    for(let n = 0;n<pads.length;n++) {\n        const pad = pads[n];\n        pad.next();\n        mainline.addStereoSignal(pad.signal, 0.4, 0.5);\n        echoline.addStereoSignal(pad.signal, 0.4, 0.5);    \n    }\n\n    kick.next();\n    mainline.addStereoSignal(kick.signal, 1.5, 0.5);\n    reverbline.addStereoSignal(kick.signal, 0.2, 0.5); \n\n    hihat.next();\n    mainline.addStereoSignal(hihat.signal, 1.5, 0.5);\n    reverbline.addStereoSignal(hihat.signal, 0.2, 0.5); \n\n    bass.next();\n    mainline.addStereoSignal(bass.signal, 4, 0.5);\n    reverbline.addStereoSignal(bass.signal, 0.1, 0.5);    \n\n    eftang.next();\n    mainline.addStereoSignal(eftang.signal, 2.3, 0.5);\n    echoline.addStereoSignal(eftang.signal, 1.8, 0.5);    \n\n    sinelead.next();\n    mainline.addStereoSignal(sinelead.signal, 2.4, 0.5);\n    echoline.addStereoSignal(sinelead.signal, 2.0, 0.5);    \n\n    snare.next();\n    mainline.addStereoSignal(snare.signal, 1.0, 0.5);\n    reverbline.addStereoSignal(snare.signal, 0.2, 0.5); \n\n    echoline.left += delayRight.read() * 0.5;\n    echoline.right += delayLeft.read() * 0.5;\n        \n    delayLeft.write_and_advance(echoline.left);\n    delayRight.write_and_advance(echoline.right);\n\n    reverbline.addStereoSignal(echoline, 0.5, 0.5);\n    \n    freeverb.tick(reverbline);\n        \n    let left = gain * (mainline.left + echoline.left + reverbline.left);\n    let right = gain * (mainline.right + echoline.right + reverbline.right);\n\n    if (ENABLE_MULTIBAND_COMPRESSOR) {\n        tribandstereocompressor.process(left,right,0.45, 1.0, 0.9 , 1.3, 1.05, 1.0);\n        left = tribandstereocompressor.stereosignal.left;\n        right  = tribandstereocompressor.stereosignal.right;\n    } else {\n        left = eqbandl.process(left);\n        right = eqbandr.process(right);\n    }\n\n    // clip\n    if (Math.abs(left) > 1.0) {\n        left = 1.0;\n    }\n\n    if (Math.abs(right) > 1.0) {\n        right = 1.0;\n    }\n\n    store<f32>(leftSampleBufferPtr, left);\n    store<f32>(rightSampleBufferPtr, right);    \n}","synth/biquad.ts":"import { SAMPLERATE } from \"../environment\";\nimport { cos, PI, sin } from \"../math/sin\";\n\n// Taken from https://docs.rs/crate/biquad/0.2.0/source/src/\n\nexport const Q_BUTTERWORTH = 0.7071067811865475 as f32; // 1/Math.sqrt(2)\n\nexport enum FilterType {\n    SinglePoleLowPass = 1 as i8,\n    LowPass = 2 as i8,\n    HighPass = 3 as i8,\n    Notch = 4 as i8\n}\n\nexport class Coefficients {\n    // Denominator coefficients\n    a1: f32;\n    a2: f32;\n\n    // Nominator coefficients\n    b0: f32;\n    b1: f32;\n    b2: f32;\n\n    phaseSamples: f32;\n    magnitude: f32;\n\n    calculatePhaseAndMagnitudeForFreq(freq: f32): void {\n        const w: f32 = 2 * Mathf.PI * freq / SAMPLERATE;\n      \n        const cos1: f32 = Mathf.cos(-1 * w);\n        const cos2: f32 = Mathf.cos(-2 * w);\n      \n        const sin1: f32 = Mathf.sin(-1 * w);\n        const sin2: f32 = Mathf.sin(-2 * w);\n      \n        const realZeros: f32 = this.b0 + this.b1 * cos1 + this.b2 * cos2;\n        const imagZeros: f32 = this.b1 * sin1 + this.b2 * sin2;\n      \n        const realPoles: f32 = 1 + this.a1 * cos1 + this.a2 * cos2;\n        const imagPoles: f32 = this.a1 * sin1 + this.a2 * sin2;\n      \n        const divider: f32 = realPoles * realPoles + imagPoles * imagPoles;\n      \n        const realHw: f32 = (realZeros * realPoles + imagZeros * imagPoles) / divider;\n        const imagHw: f32 = (imagZeros * realPoles - realZeros * imagPoles) / divider;\n      \n        this.magnitude = Mathf.sqrt(realHw * realHw + imagHw * imagHw);\n\n        const phase: f32 = Mathf.atan2(imagHw, realHw);\n      \n        this.phaseSamples = -(phase / (2*Mathf.PI)) * (SAMPLERATE / freq);\n    }\n}\n\nexport class BiQuadFilter {\n    y1: f32 = 0;\n    y2: f32 = 0;\n    x1: f32 = 0;\n    x2: f32 = 0;\n    s1: f32 = 0;\n    s2: f32 = 0;\n    readonly coeffs: Coefficients = new Coefficients();\n\n    processForm2(input: f32): f32 {\n        let out = this.s1 + this.coeffs.b0 * input;\n        this.s1 = this.s2 + this.coeffs.b1 * input - this.coeffs.a1 * out;\n        this.s2 = this.coeffs.b2 * input - this.coeffs.a2 * out;\n\n        return out;\n    }\n\n    process(input: f32): f32 {\n        let out = this.coeffs.b0 * input + this.coeffs.b1 * this.x1 + this.coeffs.b2 * this.x2\n            - this.coeffs.a1 * this.y1\n            - this.coeffs.a2 * this.y2;\n\n        this.x2 = this.x1;\n        this.x1 = input;\n        this.y2 = this.y1;\n        this.y1 = out;\n\n        return out;\n    }\n\n    clearBuffers(): void {\n        this.y1 = 0;\n        this.y2 = 0;\n        this.x1 = 0;\n        this.x2 = 0;\n        this.s1 = 0;\n        this.s2 = 0;            \n    }\n\n    /// Creates coefficients based on the biquad filter type, sampling and cutoff frequency, and Q\n    /// value. Note that the cutoff frequency must be smaller than half the sampling frequency and\n    /// that Q may not be negative, this will result in an `Err()`.\n    update_coeffecients(\n        filtertype: FilterType,\n        fsHertz: f32,\n        f0Hertz: f32,\n        q_value: f32\n    ): void {\n        const fLimit = (fsHertz / 2.0) - 1000;\n        if (f0Hertz > fLimit) {\n            f0Hertz = fLimit;\n        }\n\n        if (q_value < 0.0) {\n            q_value = 0;\n        }\n\n        let omega: f32 = 2.0 * PI * f0Hertz / fsHertz;\n        let alpha: f32;\n        let omega_s: f32;\n        let omega_c: f32;\n        let b0: f32;\n        let b1: f32;\n        let b2: f32;\n        let a0: f32;\n        let a1: f32;\n        let a2: f32;\n\n\n        switch (filtertype) {\n            case FilterType.SinglePoleLowPass:\n                alpha = omega / (omega + 1.0);\n\n                this.coeffs.a1 = alpha - 1.0;\n                this.coeffs.a2 = 0.0;\n                this.coeffs.b0 = alpha;\n                this.coeffs.b1 = 0.0;\n                this.coeffs.b2 = 0.0;\n\n                break;\n            case FilterType.LowPass:\n                // The code for omega_s/c and alpha is currently duplicated due to the single pole\n                // low pass filter not needing it and when creating coefficients are commonly\n                // assumed to be of low computational complexity.\n                omega_s = sin(omega);\n                omega_c = cos(omega);\n                alpha = omega_s / (2.0 * q_value);\n\n                b0 = (1.0 - omega_c) * 0.5;\n                b1 = 1.0 - omega_c;\n                b2 = (1.0 - omega_c) * 0.5;\n                a0 = 1.0 + alpha;\n                a1 = -2.0 * omega_c;\n                a2 = 1.0 - alpha;\n\n                this.coeffs.a1 = a1 / a0;\n                this.coeffs.a2 = a2 / a0;\n                this.coeffs.b0 = b0 / a0;\n                this.coeffs.b1 = b1 / a0;\n                this.coeffs.b2 = b2 / a0;\n\n                break;\n            case FilterType.HighPass:\n                omega_s = sin(omega);\n                omega_c = cos(omega);\n                alpha = omega_s / (2.0 * q_value);\n\n                b0 = (1.0 + omega_c) * 0.5;\n                b1 = -(1.0 + omega_c);\n                b2 = (1.0 + omega_c) * 0.5;\n                a0 = 1.0 + alpha;\n                a1 = -2.0 * omega_c;\n                a2 = 1.0 - alpha;\n\n                this.coeffs.a1 = a1 / a0;\n                this.coeffs.a2 = a2 / a0;\n                this.coeffs.b0 = b0 / a0;\n                this.coeffs.b1 = b1 / a0;\n                this.coeffs.b2 = b2 / a0;\n\n                break;\n            case FilterType.Notch:\n                omega_s = sin(omega);\n                omega_c = cos(omega);\n                alpha = omega_s / (2.0 * q_value);\n\n                b0 = 1.0;\n                b1 = -2.0 * omega_c;\n                b2 = 1.0;\n                a0 = 1.0 + alpha;\n                a1 = -2.0 * omega_c;\n                a2 = 1.0 - alpha;\n\n                this.coeffs.a1 = a1 / a0;\n                this.coeffs.a2 = a2 / a0;\n                this.coeffs.b0 = b0 / a0;\n                this.coeffs.b1 = b1 / a0;\n                this.coeffs.b2 = b2 / a0;\n\n                break;\n        }\n    }\n}\n\nexport class LoPassBiQuadFilter extends BiQuadFilter {\n    update(frequency: f32, Q: f32): void {\n        this.update_coeffecients(FilterType.LowPass, SAMPLERATE, frequency , Q);\n    }\n}\n\nexport class HiPassBiQuadFilter extends BiQuadFilter {\n    update(frequency: f32, Q: f32): void {\n        this.update_coeffecients(FilterType.HighPass, SAMPLERATE, frequency , Q);\n    }\n}\n","synth/bpm.ts":"import { SAMPLERATE } from \"../environment\";\n\nexport function beatToFrame(beat: f64, bpm: f32): usize {\n    return (SAMPLERATE * beat * 60 / bpm) as usize;\n}\n","synth/clip.ts":"// From https://ccrma.stanford.edu/~jos/pasp/Soft_Clipping.html#29695\n\n/**\n * soft clip signal with 1/3 headroom as result\n * @param signal signal to be clipped\n */\nexport function softclip(signal: f32): f32 {\n    if(signal > 1.0) {\n        return 2.0/3.0;\n    } else if(signal < -1.0) {\n        return -2.0/3.0;\n    } else {\n        return (signal - ((signal * signal * signal) / 3.0));\n    }\n}\n\nexport function hardclip(signal: f32): f32 {\n    if(signal > 1.0) {\n        return 1.0;\n    } else if(signal < -1.0) {\n        return -1.0;\n    } else {\n        return signal;\n    }\n}","synth/decibel.ts":"export function decibelToGain(dB: f32): f32 {\n    return NativeMathf.pow(10, dB/20.0);\n}\n\nexport function midiLevelToDecibel(midiLevel: u8): f32 {\n    return 40 * NativeMathf.log10(midiLevel as f32/127);\n}\n\nexport function midiLevelToGain(midiLevel: u8): f32 {\n    return decibelToGain(midiLevelToDecibel(midiLevel));\n}","synth/envelope.class.ts":"import { SAMPLERATE } from \"../environment\";\n\nexport enum EnvelopeState {\n    ATTACK = 0,\n    DECAY = 1,\n    SUSTAIN = 2,\n    RELEASE = 3,\n    DONE = 4\n}\n\nexport class Envelope {\n    attackStep: f32;\n    decayStep: f32;\n    sustainLevel: f32;\n    releaseStep: f32;\n    \n    val: f32 = 0;\n    state: EnvelopeState = EnvelopeState.DONE;\n\n    constructor(attackTime: f32, decayTime: f32, sustainLevel: f32, releaseTime: f32) {\n        this.attackStep = 1.0 / (attackTime * SAMPLERATE);\n        this.decayStep = 1.0 / (decayTime * SAMPLERATE);\n        this.releaseStep = 1.0 / (releaseTime * SAMPLERATE);\n        this.sustainLevel = sustainLevel;\n    }\n\n    next(): f32 {\n        switch(this.state) {\n            case EnvelopeState.ATTACK:\n                this.val += this.attackStep;\n                if(this.val >= 1.0) {\n                    this.val = 1.0;\n                    this.state = EnvelopeState.DECAY;\n                }\n                break;\n            case EnvelopeState.DECAY:\n                this.val -= this.decayStep;\n                if(this.val <= this.sustainLevel) {\n                    this.val = this.sustainLevel;\n                    this.state = EnvelopeState.SUSTAIN;\n                }\n                break;\n            case EnvelopeState.SUSTAIN:\n                break;\n            case EnvelopeState.RELEASE:\n                this.val -= this.releaseStep;\n                if(this.val <= 0) {\n                    this.val = 0;\n                    this.state = EnvelopeState.DONE;\n                }\n                break;\n            case EnvelopeState.DONE:\n                break;\n        }\n        return this.val;\n    }\n\n    attack(): void {\n        this.state = EnvelopeState.ATTACK;\n    }\n    \n    release(): void {\n        this.state = EnvelopeState.RELEASE;\n    }\n\n    isDone(): boolean {\n        return this.state === EnvelopeState.DONE;\n    }\n}","synth/ifftoscillator.class.ts":"\nimport { SAMPLERATE } from '../environment';\nimport { FFT } from '../math/fft';\n\nexport class IFFTOscillator {\n    position: f32 = 0;\n    positionincrement: f32 = 0;\n    buffersize: f32;\n    buffermask: u32;\n    fft: FFT;\n    scalefactor: f32;\n\n    constructor(buffersize_shift: i32) {\n        this.fft = new FFT(buffersize_shift);\n        this.buffersize = (1 << buffersize_shift) as f32;\n        this.buffermask = ~(0xffffffff << buffersize_shift);\n        this.scalefactor = (this.buffersize / 2) - 1;\n    }\n\n    set frequency(frequency: f32) {\n        this.positionincrement = (frequency * this.buffersize) / SAMPLERATE;\n    }\n\n    createWave(real: f32[], imaginary: f32[]): void {        \n        for (let n = 1; n <= real.length &&\n                n <= imaginary.length &&\n                n < (this.fft.buffer.length / 2) - 1; n++) {\n            this.fft.buffer[n].re = -real[n - 1] * this.scalefactor;\n            this.fft.buffer[this.fft.buffer.length - n].re = real[n -1] * this.scalefactor;\n\n            this.fft.buffer[n].im = -imaginary[n -1] * this.scalefactor;\n            this.fft.buffer[this.fft.buffer.length - n].im = imaginary[n -1] * this.scalefactor;\n        }\n    }\n\n    next(): f32 {\n        const bufferposfloor = NativeMathf.floor(this.position);\n        const bufferpos = bufferposfloor as i32;\n        const t = this.position - bufferposfloor;\n\n        const x0 = this.fft.buffer[(bufferpos - 1) & this.buffermask].re;\n        const x1 = this.fft.buffer[bufferpos].re;\n        const x2 = this.fft.buffer[(bufferpos + 1) & this.buffermask].re;\n        const x3 = this.fft.buffer[(bufferpos + 2) & this.buffermask].re;\n        \n        // cubic interpolation\n                \n        const a0 = x3 - x2 - x0 + x1;\n        const a1 = x0 - x1 - a0;\n        const a2 = x2 - x0;\n        const a3 = x1;\n        const ret = (a0 * (t * t * t)) + (a1 * (t * t)) + (a2 * t) + (a3);\n\n        // increment position\n        this.position += this.positionincrement;\n        this.position %= this.buffersize;\n        \n        return ret;    \n    }\n}\n","synth/noise.class.ts":"let x: i32 = 123456789;\nlet y: i32=234567891;\nlet z: i32=345678912;\nlet w: i32=456789123;\nlet c: i32=0; \n\nexport class Noise {\n    \n    next(): f32 {            \n      y ^= (y<<5); y ^= (y>>7); y ^= (y<<22); \n\n      let t = z+w+c; z = w;\n      c = t < 0 ? 1 : 0;\n      w = t & 2147483647; \n  \n      x += 1411392427; \n  \n      let rnd: f32 = ((x + y + w) & 0xffff) as f32;\n      return ((rnd / (1 << 16 as f32))) - 0.5;\n    }\n  }\n  ","synth/note.ts":"const pitchstep: f64 = 1.0004513695322617; // Math.pow(2, (1/128) / 12);\nconst c0: f64 = 8.175798915643707; // 440 * Math.pow(2, -69 / 12);\nlet pitchtable = __new(128 * 128 * 4, idof<Array<f32>>());\nlet pitch: f64 = c0;\n\nfor (let n: usize = 0; n < (128 * 128); n++) {\n    store<f32>(pitchtable + (n << 2), pitch as f32);\n    pitch *= pitchstep;\n}\n\nexport function notefreq(note: f32): f32 {\n    let pitchtableIndex: usize = (note * 128.0) as usize;\n    return load<f32>(pitchtable + (pitchtableIndex << 2));\n}","synth/pan.class.ts":"import { StereoSignal } from \"./stereosignal.class\";\n\nconst HALF_OF_SQRT_2 = NativeMathf.sqrt(2) / 2;\n\nexport class Pan {\n    leftLevel: f32;\n    rightLevel: f32;\n    \n    constructor() {\n        this.setPan(0.5);    \n    }\n\n    /**\n     * Don't use as part of the rendering process. Use to calculate pan levels on controller changes\n     * @param pan from 0.0 (left) to 1.0 (right). 0.5 is center\n     */\n    setPan(pan: f32): void {\n        const angle = (pan - 0.5) * NativeMathf.PI / 2;\n        // left channel\n        this.leftLevel = HALF_OF_SQRT_2 * (NativeMathf.cos(angle) - NativeMathf.sin(angle));\n        // right channel\n        this.rightLevel = HALF_OF_SQRT_2 * (NativeMathf.cos(angle) + NativeMathf.sin(angle));\n    }\n}\n","synth/sawoscillator.class.ts":"\nimport { SAMPLERATE } from '../environment';\n\nexport class SawOscillator {\n    position: u32 = 0;\n    frequency: f32 = 0;\n\n    next(): f32 {\n      if(this.frequency > 0) {\n        let ret = (this.position as f32 / 0x10000 as f32) - 0.5;\n        this.position = (((this.position as f32) + (this.frequency/SAMPLERATE)\n                            * 0x10000 as f32) as u32) & 0xffff;\n        \n        \n        return ret as f32;\n      } else {\n        return 0;\n      }\n    }\n  }\n  ","synth/shaper.ts":"/**\n * Taken from https://github.com/hzdgopher/64klang/blob/master/Player/Player/SynthNode.cpp#L2050\n */\n\nconst NOISEGEN_B0: f32 = 0.99765014648437500;\n\nexport class WaveShaper {\n    drive: f32 = 0.5;\n    \n    process(input: f32): f32 {     \n        // clamp to -1..1 (a little less)\n        let f: f32 = this.drive < NOISEGEN_B0 ? this.drive > -NOISEGEN_B0 ?\n                        this.drive : -NOISEGEN_B0 : \n                        NOISEGEN_B0;\n\n        // k = 2*amount/(1-amount);\n        let v = (f+f)/(1.0-f);\n\n        // process f(x) = (1+k)*x/(1+k*abs(x))\n        return (1.0 + v) *\n                    input/\n                (1.0 + v * min<f32>(abs<f32>(input), 1.0));   \n    }\n}","synth/sineoscillator.class.ts":"\nimport { SAMPLERATE } from '../environment';\nimport { sin, PI } from '../math/sin';\n\nexport class SineOscillator {\n    position: u32 = 0;\n    frequency: f32 = 0;\n\n    next(): f32 {\n      let ret = sin(PI * 2 * (this.position as f32) / (1 << 16 as f32));\n      this.position = (((this.position as f32) + (this.frequency/SAMPLERATE)\n                          * 0x10000 as f32) as u32) & 0xffff;\n      \n      return ret as f32;\n    }\n  }\n  ","synth/squareoscillator.class.ts":"\nimport { SAMPLERATE } from '../environment';\n\nexport class SquareOscillator {\n    position: u32 = 0;\n    frequency: f32 = 0;\n\n    next(): f32 {\n      if(this.frequency > 0) {\n        let ret: f32 = this.position as f32 > 0x8000 ? 0.5 : -0.5;\n        this.position = (((this.position as f32) + (this.frequency/SAMPLERATE)\n                            * 0x10000 as f32) as u32) & 0xffff;\n        \n        \n        return ret;\n      } else {\n        return 0;\n      }\n    }\n}\n  ","synth/stereosignal.class.ts":"import { Pan } from './pan.class';\n\nexport class StereoSignal {\n    left: f32 = 0;\n    right: f32 = 0;\n\n    clear(): void {\n        this.left = 0;\n        this.right = 0;\n    }\n\n    /**\n     * Add left and right values directly to the signal\n     * @param left\n     * @param right \n     */\n    @inline\n    add(left: f32, right:f32): void {\n        this.left += left;\n        this.right += right;\n    }\n\n    /**\n     * Add stereo signal with simple (not proper) panning\n     * @param signal \n     * @param level \n     * @param pan 0.0 - 1.0\n     */\n    addStereoSignal(signal: StereoSignal, level: f32, pan: f32): void {\n        this.left += signal.left * pan * level;\n        this.right += signal.right * (1 - pan) * level;\n    }\n\n    addMonoSignal(signal: f32, level: f32, pan: f32): void {\n        this.left += signal * pan * level;\n        this.right += signal * (1 - pan) * level;\n    }\n}","synth/triangleoscillator.class.ts":"import { SAMPLERATE } from '../environment';\n\nexport class TriangleOscillator {\n    position: i32 = 0;\n    frequency: f32 = 0;\n\n    next(): f32 {\n        if (this.frequency > 0) {\n            const pos: i32 = this.position;\n            let ret: f32;\n            if (pos < 0x8000) {\n                ret = (pos as f32 / 0x8000 as f32);\n            } else {\n                ret = (- (pos - 0x8000) as f32 / 0x8000 as f32) + 1.0;\n            }\n\n            this.position = (((this.position as f32) + (this.frequency / SAMPLERATE)\n                * 0x10000 as f32) as i32) & 0xffff;\n\n            return ret * 2 - 1 as f32;\n        } else {\n            return 0;\n        }\n    }\n}\n","synth/waveguide.ts":"import { SAMPLERATE } from \"../environment\";\nimport { DelayLineFloat } from \"../fx/delayline\";\nimport { MonoAudioPlayer } from \"../midi/instruments/audioplayer\";\nimport { BiQuadFilter, FilterType, LoPassBiQuadFilter, Q_BUTTERWORTH } from \"./biquad\";\nimport { Envelope } from \"./envelope.class\";\nimport { notefreq } from \"./note\";\n\nlet seed: i32 = 1;\n\nexport function noise(): f32 {\n    seed = (seed * 1103515245 + 12345) & 0x7fffffff;\n    return ((seed as f32 % 1000000 / 1000000) - 0.5) as f32;\n}\n\nexport class WaveGuide {\n    envExciter: Envelope;\n    filterExciter: BiQuadFilter = new BiQuadFilter();\n    delay: DelayLineFloat = new DelayLineFloat((SAMPLERATE / notefreq(1)) as i32);\n    filterFeedback: BiQuadFilter = new BiQuadFilter();\n    feedbackLevel: f32;\n    feedbackFilterFreq: f32;\n    freq: f32;\n    exciterenvlevel: f32;\n\n    constructor(exciterAttack: f32, exciterRelease: f32, exciterFilterFreq: f32, feedbackLevel: f32) {\n        this.envExciter = new Envelope(exciterAttack,\n            exciterRelease, 0,\n            exciterRelease);\n        this.filterExciter.update_coeffecients(FilterType.LowPass, SAMPLERATE,\n            exciterFilterFreq, Q_BUTTERWORTH);\n\n        this.feedbackLevel = feedbackLevel;\n    }\n\n    setFilterExciterFreq(freq: f32): void {\n        this.filterExciter.update_coeffecients(FilterType.LowPass, SAMPLERATE,\n            freq, Q_BUTTERWORTH);\n\n    }\n\n    start(freq: f32, feedbackFilterFreq: f32): void {\n        if (freq != this.freq) {\n            this.freq = freq;\n            const maxFeedbackFilterFreq: f32 = 20000;\n            if (feedbackFilterFreq > maxFeedbackFilterFreq as f32) {\n                feedbackFilterFreq = maxFeedbackFilterFreq as f32;\n            } else if (feedbackFilterFreq < 10) {\n                feedbackFilterFreq = 10;\n            }\n            this.filterFeedback.update_coeffecients(FilterType.LowPass, SAMPLERATE,\n                feedbackFilterFreq, Q_BUTTERWORTH);\n\n            this.filterFeedback.coeffs.calculatePhaseAndMagnitudeForFreq(freq);\n            const filterphase = this.filterFeedback.coeffs.phaseSamples;\n\n            this.filterFeedback.clearBuffers();            \n            this.filterExciter.clearBuffers();\n\n            this.feedbackFilterFreq = feedbackFilterFreq;\n            this.delay.setNumFramesAndClear(\n                (SAMPLERATE /\n                    (freq)\n                ) - filterphase\n            );\n            this.envExciter.val = 0;\n\n        }\n        this.exciterenvlevel = 1;\n        this.envExciter.attack();\n\n    }\n\n    process(): f32 {\n        const envexciter = this.envExciter.next() * this.exciterenvlevel;\n        let exciterSignal: f32 = noise() * envexciter;\n        exciterSignal = this.filterExciter.process(exciterSignal);\n\n        const feedback = this.delay.read();\n        let signal = exciterSignal + feedback;\n\n        signal = this.filterFeedback.processForm2(signal);\n        this.delay.write_and_advance(\n            signal * this.feedbackLevel\n        );\n        return signal;\n\n    }\n}\n\nexport class AuxExciterWaveGuide {\n    delay: DelayLineFloat = new DelayLineFloat((SAMPLERATE / notefreq(1)) as i32);\n    filterFeedback: BiQuadFilter = new BiQuadFilter();\n    feedbackFilterFreq: f32;\n    feedbackLevel: f32;\n    freq: f32;\n\n    constructor(public exciter: WaveGuide) {\n\n    }\n\n    start(freq: f32, feedbackFilterFreq: f32): void {\n        if (freq != this.freq) {\n            this.freq = freq;\n            const maxFeedbackFilterFreq: f32 = 20000;\n            if (feedbackFilterFreq > maxFeedbackFilterFreq as f32) {\n                feedbackFilterFreq = maxFeedbackFilterFreq as f32;\n            } else if (feedbackFilterFreq < 10) {\n                feedbackFilterFreq = 10;\n            }\n            this.filterFeedback.update_coeffecients(FilterType.LowPass, SAMPLERATE,\n                feedbackFilterFreq, Q_BUTTERWORTH);\n            this.filterFeedback.coeffs.calculatePhaseAndMagnitudeForFreq(freq);\n            const filterphase: f32 = this.filterFeedback.coeffs.phaseSamples;\n\n            this.filterFeedback.clearBuffers();\n            \n            this.feedbackFilterFreq = feedbackFilterFreq;\n            this.delay.setNumFramesAndClear(\n                (SAMPLERATE /\n                    (freq)\n                ) - filterphase\n            );\n\n        }\n    }\n\n    process(): f32 {\n        let exciterSignal: f32 = this.exciter.process();\n\n        const feedback = this.delay.read();\n        let signal = exciterSignal + feedback;\n\n        signal = this.filterFeedback.processForm2(signal);\n        this.delay.write_and_advance(\n            signal * this.feedbackLevel\n        );\n        return signal;\n    }\n}\n\nexport class AudioExciterWaveGuide {\n    delay: DelayLineFloat = new DelayLineFloat((SAMPLERATE / notefreq(1)) as i32);\n    filterFeedback: BiQuadFilter = new BiQuadFilter();\n    exciterFilter: LoPassBiQuadFilter = new LoPassBiQuadFilter();\n    feedbackFilterFreq: f32;\n    feedbackLevel: f32;\n    freq: f32;\n\n    constructor(public exciter: MonoAudioPlayer) {\n\n    }\n\n    start(freq: f32, feedbackFilterFreq: f32): void {\n        this.exciter.restart();\n        if (freq != this.freq) {\n            this.freq = freq;\n            const maxFeedbackFilterFreq: f32 = 20000;\n            if (feedbackFilterFreq > maxFeedbackFilterFreq as f32) {\n                feedbackFilterFreq = maxFeedbackFilterFreq as f32;\n            } else if (feedbackFilterFreq < 10) {\n                feedbackFilterFreq = 10;\n            }\n            this.filterFeedback.update_coeffecients(FilterType.LowPass, SAMPLERATE,\n                feedbackFilterFreq, Q_BUTTERWORTH);\n            this.filterFeedback.coeffs.calculatePhaseAndMagnitudeForFreq(freq);\n            const filterphase: f32 = this.filterFeedback.coeffs.phaseSamples;\n\n            this.filterFeedback.clearBuffers();\n            this.exciterFilter.clearBuffers();\n    \n            this.feedbackFilterFreq = feedbackFilterFreq;\n            this.delay.setNumFramesAndClear(\n                (SAMPLERATE /\n                    (freq)\n                ) - filterphase\n            );\n        }\n    }\n\n    reset(): void {\n        this.delay.reset();;\n        this.filterFeedback.clearBuffers();\n        this.exciterFilter.clearBuffers();\n    }\n\n    process(): f32 {\n        let exciterSignal: f32 = this.exciter.nextframe();\n        exciterSignal = this.exciterFilter.process(exciterSignal);\n\n        const feedback = this.delay.read();\n        let signal = exciterSignal + feedback;\n\n        signal = this.filterFeedback.processForm2(signal);\n        this.delay.write_and_advance(\n            signal * this.feedbackLevel\n        );\n        return signal;\n    }\n}\n\nexport class CustomExciterWaveGuide {\n    delay: DelayLineFloat = new DelayLineFloat((SAMPLERATE / notefreq(1)) as i32);\n    filterFeedback: BiQuadFilter = new BiQuadFilter();\n    feedbackFilterFreq: f32;\n    feedbackLevel: f32;\n    freq: f32;\n    exciterSignal: f32;\n\n    start(freq: f32, feedbackFilterFreq: f32): void {\n        if (freq != this.freq) {\n            this.freq = freq;\n            const maxFeedbackFilterFreq: f32 = 20000;\n            if (feedbackFilterFreq > maxFeedbackFilterFreq as f32) {\n                feedbackFilterFreq = maxFeedbackFilterFreq as f32;\n            } else if (feedbackFilterFreq < 10) {\n                feedbackFilterFreq = 10;\n            }\n            this.filterFeedback.update_coeffecients(FilterType.LowPass, SAMPLERATE,\n                feedbackFilterFreq, Q_BUTTERWORTH);\n            this.filterFeedback.coeffs.calculatePhaseAndMagnitudeForFreq(freq);\n            const filterphase: f32 = this.filterFeedback.coeffs.phaseSamples;\n\n            this.filterFeedback.clearBuffers();\n            \n            this.feedbackFilterFreq = feedbackFilterFreq;\n            this.delay.setNumFramesAndClear(\n                (SAMPLERATE /\n                    (freq)\n                ) - filterphase\n            );\n        }\n    }\n\n    process(): f32 {\n        const feedback = this.delay.read();\n        let signal = this.exciterSignal + feedback;\n\n        signal = this.filterFeedback.processForm2(signal);\n        this.delay.write_and_advance(\n            signal * this.feedbackLevel\n        );\n        return signal;\n    }\n}","wasi_main.ts":"import { fd_write, iovec} from 'bindings/wasi';\nimport { allocateSampleBuffer, getTick, setBPM, setPatternsPtr, setInstrumentPatternListPtr, fillSampleBufferInterleaved } from './index';\n\nconst patterns: i8[] = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,26,1,1,1,33,1,36,38,0,36,1,33,36,0,38,1,33,1,45,1,0,0,33,1,36,1,48,1,36,48,0,50,100,0,0,0,100,0,0,10,100,0,0,0,100,0,0,0,90,20,90,20,90,20,90,20,90,20,90,20,90,20,90,20,0,0,0,0,60,0,0,0,0,0,0,0,60,0,0,0,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,62,1,1,1,0,0,0,0,0,0,0,0,62,1,1,1,64,1,1,1,0,0,0,0,0,0,0,0,64,1,1,1,62,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,64,1,1,64,0,0,0,0,62,1,1,62,0,0,0,0,66,1,1,1,0,0,0,0,0,0,0,0,66,1,1,1,67,1,1,1,0,0,0,0,0,0,0,0,67,1,1,1,66,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,67,1,1,67,0,0,0,0,67,1,1,67,0,0,0,0,57,1,1,1,0,0,0,0,0,0,0,0,57,1,1,1,60,1,1,1,0,0,0,0,0,0,0,0,71,1,1,1,69,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,72,1,1,72,0,0,0,0,71,1,1,71,0,0,0,0,0,0,0,0,60,0,0,0,0,0,0,30,60,0,0,40,0,0,57,1,62,1,57,1,62,1,1,64,1,1,60,1,1,1,59,1,60,1,59,1,60,1,1,59,1,1,57,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67,1,67,1,67,1,67,1,1,69,1,1,66,0,62,64,67,0,71,0,0,74,0,67,0,0,0,0,0,0,31,1,43,1,0,0,0,0,26,38,0,41,0,41,43,0,26,1,38,1,0,0,0,0,21,33,0,36,0,36,38,0,29,1,41,1,0,0,0,0,24,36,0,39,0,39,41,0,24,1,36,1,0,0,0,0,19,31,0,34,0,34,36,0,0,0,67,0,67,0,67,71,0,72,0,71,0,67,65,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,65,0,65,62,0,65,0,67,0,69,0,0,67,0,0,64,0,62,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,65,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,64,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,67,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,69,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,71,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,72,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,75,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,65,62,0,65,0,67,0,69,0,0,67,0,0,0,72,0,72,71,0,72,0,74,0,71,0,0,67,0,0,0,0,62,74,0,62,74,0,62,0,69,1,1,67,0,0,0,0,0,0,0,0,0,0,0,0,0,0,62,0,67,0,74,72,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,71,1,1,1,67,1,1,1,0,0,0,0,1,1,1,1,71,1,1,1,67,1,1,1,69,1,1,1,72,1,1,1,1,1,1,1,1,1,1,1,71,1,69,1,67,1,1,1,1,1,1,1,1,1,1,1,1,1,64,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,16,32,48,64,0,0,0,0,0,0,0,0,0,0,0,32,40,48,64,0,0,0,0,0,0,0,0,0,0,0,0,74,1,1,1,1,1,1,1,1,1,1,1,1,1,1,77,1,1,1,1,1,1,1,1,1,1,1,1,76,1,74,1,72,1,1,1,1,1,1,1,1,1,1,1,1,1,79,1,2,16,32,48,64,0,0,0,0,0,0,0,0,80,96,32,36,40,48,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,80,96,112,127,0,0,0,0,0,20,0,30,60,0,0,20,0,20,0,30,60,20,60,40,81,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,64,0,48,32,16,0,0,0,0,64,0,0,0,0,0,0,57,0,57,0,62,0,62,0,69,0,69,0,72,74,0,0,0,0,0,0,0,0,0,0,0,0,0,0,79,78,74,69,0,0,0,0,62,69,0,0,0,0,0,0,0,0,0,0,0,0,0,0,60,0,0,10,0,10,0,0,60,0,0,25,0,20,0,0,60,10,0,10,0,10,35,0,60,10,0,35,0,0,69,0,69,0,74,0,74,0,81,0,81,0,83,0,83,0,81,0,81,0,74,0,76,0,74,0,74,0,0,0,0,0,62,1,1,1,69,1,71,1,1,1,69,1,1,1,64,1,1,69,1,1,62,1,1,1,1,1,1,1,0,0,64,0,0,0,0,0,0,0,2,32,64,0,0,0,0,0,64,1,1,69,1,1,62,1,1,1,64,1,66,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,67,1,1,1,66,1,1,1,64,1,62,1,1,1,59,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,32,48,64,0,0,69,0,69,0,74,86,74,0,81,0,81,0,83,91,83,0,81,0,81,0,74,86,76,0,74,86,91,90,86,81,83,0,81,0,81,0,74,0,76,0,74,0,74,0,86,0,69,1,1,1,0,0,0,0,0,0,0,0,69,1,1,1,67,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,69,1,1,69,0,0,0,0,67,1,1,67,0,0,0,0,71,1,1,1,0,0,0,0,0,0,0,0,71,1,1,1,72,1,1,1,0,0,0,0,0,0,0,0,72,1,1,1,71,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,72,1,1,67,0,0,0,0,72,1,1,67,0,0,0,0,65,1,1,1,0,0,0,0,0,0,0,0,76,1,1,1,74,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,77,1,1,72,0,0,0,0,76,1,1,71,0,0,0,0,31,1,1,1,38,1,41,43,0,41,1,38,41,0,43,1,38,1,50,1,0,0,38,1,41,1,53,1,41,53,0,55,0,0,74,0,74,0,79,0,79,0,86,0,86,0,88,0,88,0,86,0,86,0,79,0,81,0,79,0,79,0,0,0,0,0,74,0,74,0,79,91,79,0,86,0,86,0,88,96,88,0,86,0,86,0,79,91,81,0,79,91,96,95,91,86,0,0,67,1,1,1,74,1,76,1,1,1,74,1,1,1,69,1,1,74,1,1,67,1,1,1,1,1,1,1,0,0,88,0,86,0,86,0,79,0,81,0,79,0,79,0,91,0,69,1,1,74,1,1,67,1,1,1,69,1,71,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,72,1,1,1,71,1,1,1,69,1,67,1,1,1,64,1,1,1,26,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,100,0,0,0,100,0,0,30,100,0,0,0,100,0,0,0,90,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,60,1,1,1,0,0,0,0,0,0,0,0,60,1,1,1,57,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,66,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,69,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,69,74,81,0,74,81,86,0,0,0,0,0,0,0,0,91,90,86,81,0,0,0,0,0,0,0,0,0,0,0,0,93,86,81,78,74,69,74,78,0,0,0,0,0,74,81,74,81,78,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];\nconst instrumentspatternlists: i8[] = [1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,25,26,27,28,25,26,27,28,25,26,27,28,25,26,27,28,25,26,27,28,25,26,27,28,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,25,26,27,28,25,26,27,28,25,26,27,28,25,26,27,28,25,26,27,28,25,26,27,28,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,88,88,88,89,88,88,88,89,1,1,1,100,0,0,0,0,0,0,0,0,20,21,22,23,20,21,22,24,0,0,0,0,0,0,0,0,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,0,0,0,0,0,0,63,0,20,21,22,23,20,21,22,24,0,0,0,0,0,0,0,0,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,105,35,106,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,29,30,31,0,29,30,40,41,29,30,31,0,29,30,31,0,29,30,31,0,29,30,31,0,0,0,0,0,61,62,0,0,0,0,0,0,0,0,0,0,29,30,31,0,29,30,40,41,29,30,31,0,29,30,31,0,29,30,31,0,29,30,31,0,0,0,0,0,0,0,0,0,66,67,0,0,66,67,0,0,66,67,75,76,66,77,75,76,90,91,92,93,90,96,92,93,107,108,109,110,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,101,101,101,6,5,5,5,5,5,5,5,19,5,5,5,5,5,5,5,19,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,58,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,19,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,58,5,5,5,5,64,64,64,65,64,64,64,65,64,64,64,65,64,64,64,65,64,64,64,65,64,64,64,65,64,64,64,65,0,0,0,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,102,7,8,9,10,7,8,9,10,7,8,9,10,7,8,9,10,32,33,33,34,32,33,33,34,32,33,33,34,32,33,33,34,32,33,33,34,32,33,33,34,7,8,9,10,7,8,9,10,7,8,9,10,7,8,9,10,32,33,33,34,32,33,33,34,32,33,33,34,32,33,33,34,32,33,33,34,32,33,33,34,7,8,9,10,7,8,9,10,7,8,9,10,7,8,9,10,7,8,9,10,7,8,9,10,12,78,79,80,12,78,79,80,7,8,9,0,11,12,13,14,11,12,13,14,11,12,13,14,11,12,13,14,35,36,36,35,35,36,36,35,35,36,36,35,35,36,36,35,35,36,36,35,35,36,36,35,11,12,13,14,11,12,13,14,11,12,13,14,11,12,13,14,35,36,36,35,35,36,36,35,35,36,36,35,35,36,36,35,35,36,36,35,35,36,36,35,11,12,13,14,11,12,13,14,11,12,13,14,11,12,13,14,11,12,13,14,11,12,13,14,81,82,83,84,81,82,83,84,11,12,13,0,15,16,17,18,15,16,17,18,15,16,17,18,15,16,17,18,37,38,38,38,37,38,38,38,37,38,38,38,37,38,38,38,37,38,38,38,37,38,38,38,15,16,17,18,15,16,17,18,15,16,17,18,15,16,17,18,37,38,38,38,37,38,38,38,37,38,38,38,37,38,38,38,37,38,38,38,37,38,38,38,15,16,17,18,15,16,17,18,15,16,17,18,15,16,17,18,15,16,17,18,15,16,17,18,7,85,86,87,7,85,86,87,15,103,104,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,0,0,0,32,0,0,0,32,0,0,0,32,0,0,0,32,0,0,0,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,0,0,0,32,0,0,0,32,0,0,0,32,0,0,0,32,0,0,0,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0,6,0,0,0,6,0,0,0,39,0,0,0,39,0,0,0,39,0,0,0,39,0,0,0,39,0,0,0,39,0,0,0,6,0,0,0,6,0,0,0,6,0,0,0,6,0,0,0,39,0,0,0,39,0,0,0,39,0,0,0,39,0,0,0,39,0,0,0,39,0,0,0,6,0,0,0,6,0,0,0,6,0,0,0,6,0,0,0,6,0,0,0,6,0,0,0,6,0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,43,44,43,45,43,44,43,46,37,47,48,49,52,53,54,49,59,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,43,44,43,45,43,44,43,46,37,47,48,49,52,53,54,49,22,0,0,0,0,0,0,0,68,69,0,0,68,71,72,73,68,69,0,0,68,71,72,73,94,95,0,0,94,97,98,99,105,35,106,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,51,51,0,55,56,51,57,60,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,51,51,0,55,56,51,57,0,0,0,0,0,0,0,0,70,0,0,0,70,0,74,0,70,0,0,0,70,0,74,0,70,0,0,0,70,0,74,0,0,0,50,0];\n\n\n// ./node_modules/.bin/asc --runtime none assembly/wasi_main.ts --noAssert --use abort= -O3 -o build/index.wasm\n// wasmer build/index.wasm | sox -S -t raw -b 32 -e float -r 44100 -c 2 - -d\nexport function _start(): void {\n    const samplebuf = allocateSampleBuffer(128);\n    setPatternsPtr(load<usize>(changetype<usize>(patterns)));\n    setInstrumentPatternListPtr(load<usize>(changetype<usize>(instrumentspatternlists)), 116, 19);\n    setBPM(123);\n    \n    const iov = new iovec();\n    iov.buf = samplebuf;\n    iov.buf_len = 128 * 8;\n    \n    const written_ptr = changetype<usize>(new ArrayBuffer(sizeof<usize>()));\n    \n    let previousTick: f64;\n    do {\n        previousTick = getTick();\n        fillSampleBufferInterleaved();\n        fd_write(1, changetype<usize>(iov), 1, written_ptr);\n    } while(previousTick < getTick())\n}"}