export default function (audioCtx, destination, time, {level, tone, decay}) { // parameters const outputLevel = equalPower(level); const vcfFreq = 200 + tone * 20; const decayTime = decay * 5 + 50; // audio modules const vco = new VCO(SINE, audioCtx); vco.frequency.value = START_FREQ; const vcf = new VCF(LOWPASS, audioCtx); vcf.frequency.value = vcfFreq; vcf.Q.value = 1; const click = new PulseTrigger(audioCtx); const vca = new VCA(audioCtx); vca.amplitude.value = 0; const outputVCA = new VCA(audioCtx); outputVCA.amplitude.value = outputLevel + 0.4; const softClipper = new SoftClipper(0.6, audioCtx); // envelopes const oscEnv = new ADGenerator(EXPONENTIAL, 0.11, decayTime, START_FREQ, FREQ_AMT); const ampEnv = new ADGenerator(LINEAR, 2, decayTime, 0.0, 1.0); // module routing vco.connect(vca); click.connect(vca); vca.connect(vcf); vcf.connect(softClipper); softClipper.connect(outputVCA); // envelope routing oscEnv.connect(vco.frequency); ampEnv.connect(vca.amplitude); // output routing outputVCA.connect(destination); // envelope/oscillator triggering vco.start(time); ampEnv.trigger(time); oscEnv.trigger(time); click.trigger(time, audioCtx); // cleanup window.setTimeout(() => { vco.oscillator.stop(); outputVCA.disconnect(); }, (time - audioCtx.currentTime) + 1000); return outputVCA; }
export default function(audioCtx, destination, time, outputLevel, decay) { // audio modules const oscBank = new SquareOscBank(audioCtx); const midFilter = new VCF(BANDPASS, audioCtx); midFilter.frequency.value = MID_FILTER_FREQ; const highFilter = new VCF(HIGHPASS, audioCtx); highFilter.frequency.value = HIGH_FILTER_FREQ; const outputVCA = new VCA(audioCtx); outputVCA.amplitude.value = outputLevel; const modVCA = new VCA(audioCtx); // modulators const env = new ADGenerator(LINEAR, 0.1, decay, 0, 1); // audio routing oscBank.connect(midFilter); midFilter.connect(modVCA); modVCA.connect(highFilter); highFilter.connect(outputVCA); // modulation routing env.connect(modVCA.amplitude); // output routing outputVCA.connect(destination); // envelope/oscillator triggering oscBank.start(time); env.trigger(time); // cleanup window.setTimeout(() => { oscBank.stop(); outputVCA.disconnect(); }, (time - audioCtx.currentTime) + 1000); return outputVCA; }
export default function(audioCtx, destination, time, { level, tone, decay }) { // parameters const outputLevel = equalPower(level); const lowDecay = decay * 8.5 + 700; // tone ratio const lowEnvAmt = 0.666 - (tone / 100) * 0.666; const midEnvAmt = 0.333; const highEnvAmt = 0.666 - (1 - tone / 100) * 0.666; // audio modules const oscBank = new SquareOscBank(audioCtx); const lowBandFilter = new VCF(BANDPASS, audioCtx); lowBandFilter.frequency.value = LOW_FILTER_FREQ; const lowVCA = new VCA(audioCtx); const lowHighpassFilter = new VCF(HIGHPASS, audioCtx); lowHighpassFilter.frequency.value = LOW_FILTER_FREQ; const midHighBandFilter = new VCF(BANDPASS, audioCtx); midHighBandFilter.frequency.value = MID_HIGH_FILTER_FREQ; const midVCA = new VCA(audioCtx); const midHighpassFilter = new VCF(HIGHPASS, audioCtx); midHighpassFilter.frequency.value = MID_HIGH_FILTER_FREQ; const highFilter = new VCF(HIGHPASS, audioCtx); highFilter.frequency.value = HIGH_FILTER_FREQ; const highVCA = new VCA(audioCtx); const outputVCA = new VCA(audioCtx); outputVCA.amplitude.value = outputLevel; // modulators // NOTE: for tone control adjust the amounts of each band's env amount instead of having a dedicated mixer node const lowEnv = new ADGenerator(EXPONENTIAL, 0.1, lowDecay, 0, lowEnvAmt); const midEnv = new ADGenerator(EXPONENTIAL, 0.1, MID_DECAY, 0, midEnvAmt); const highEnv = new ADGenerator(EXPONENTIAL, 0.1, HIGH_DECAY, 0, highEnvAmt); // band splitting oscBank.connect(lowBandFilter); oscBank.connect(midHighBandFilter); // low band routing lowBandFilter.connect(lowVCA); lowVCA.connect(lowHighpassFilter); lowHighpassFilter.connect(outputVCA); // mid band routing midHighBandFilter.connect(midVCA); midVCA.connect(midHighpassFilter); midHighpassFilter.connect(outputVCA); // high band routing midHighBandFilter.connect(highVCA); highVCA.connect(highFilter); highFilter.connect(outputVCA); // modulation routing lowEnv.connect(lowVCA.amplitude); midEnv.connect(midVCA.amplitude); highEnv.connect(highVCA.amplitude); // output routing outputVCA.connect(destination); // envelope/oscillator triggering oscBank.start(time); lowEnv.trigger(time); midEnv.trigger(time); highEnv.trigger(time); // cleanup window.setTimeout(() => { oscBank.stop(); outputVCA.disconnect(); }, time - audioCtx.currentTime + 2000); return outputVCA; }