const gate = new Float64Array(bufferSize);

const EnvelopeFollower = ({ input, output, attack, decay, sustain, release, threshold, hold }) => {
  const processEnvelope = useEnvelope();
  const lastGate = useVal(0);
  const trigger = useMonoSignal(input.length);
  trigger.fill(0);
  for (let i = 0; i < input.length; i++) {
    const absInputSample = Math.abs(input[i]);
    if (absInputSample > threshold[i]) {
      gate[i] = 1;
      if (lastGate.current !== 1) {
        trigger[i] = 1;
      }
    } else if (absInputSample < threshold[i] * (1 - hold[i])) {
      gate[i] = 0;
    } else {
      gate[i] = lastGate.current;
    }
    lastGate.current = gate[i];
  }
  output.set(
    processEnvelope(
      trigger,
      gate,
      attack,
      decay,
      sustain,
      release,
    )
  );
}

this.constructDevice = () => constructPerChannelDevice({
  implementation: EnvelopeFollower,
  inputs: {
    input: stereo('In'),
    threshold: zeroOneSetting('Trigger', 0.3),
    hold: zeroOneSetting('Hold', 0.3),
    attack: adsrTimeSetting('Attack', 1),
    decay: adsrTimeSetting('Decay', 100),
    sustain: zeroOneSetting('Sustain', 0.5),
    release: adsrTimeSetting('Release', 50),
  },
  outputs: {
    output: { ...mono('Out'), min: 0 },
  }
});
