From 28c9bffe4d6a0360b52457e3bd1d6eab4ab1c174 Mon Sep 17 00:00:00 2001 From: Eric Rosenbaum Date: Mon, 7 Nov 2016 17:30:00 -0500 Subject: [PATCH] vocoder effect, because ROBOTS --- src/vocoder.js | 272 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 272 insertions(+) create mode 100644 src/vocoder.js diff --git a/src/vocoder.js b/src/vocoder.js new file mode 100644 index 0000000..1963c8a --- /dev/null +++ b/src/vocoder.js @@ -0,0 +1,272 @@ +var Tone = require('tone'); + +var modulatorNode = null; +var carrierNode = null; +var vocoding = false; + +var FILTER_QUALITY = 6; // The Q value for the carrier and modulator filters + +// These are "placeholder" gain nodes - because the modulator and carrier will get swapped in +// as they are loaded, it's easier to connect these nodes to all the bands, and the "real" +// modulator & carrier AudioBufferSourceNodes connect to these. +var modulatorInput = null; +var carrierInput = null; + +var modulatorGain = null; +var modulatorGainValue = 1.0; + +// noise node added to the carrier signal +var noiseBuffer = null; +var noiseNode = null; +var noiseGain = null; +var noiseGainValue = 0.2; + +// Carrier Synth oscillator stuff +var oscillatorNode = null; +var oscillatorType = 4; // CUSTOM +var oscillatorGain = null; +var oscillatorGainValue = 1.0; +var oscillatorDetuneValue = 0; +var FOURIER_SIZE = 4096; +var SAWTOOTHBOOST = 0.40; + +// These are the arrays of nodes - the "columns" across the frequency band "rows" +var modFilterBands = null; // tuned bandpass filters +var modFilterPostGains = null; // post-filter gains. +var heterodynes = null; // gain nodes used to multiply bandpass X sine +var powers = null; // gain nodes used to multiply prev out by itself +var lpFilters = null; // tuned LP filters to remove doubled copy of product +var lpFilterPostGains = null; // gain nodes for tuning input to waveshapers +var carrierBands = null; // tuned bandpass filters, same as modFilterBands but in carrier chain +var carrierFilterPostGains = null; // post-bandpass gain adjustment +var carrierBandGains = null; // these are the "control gains" driven by the lpFilters + +var vocoderBands; +var numVocoderBands; + +var hpFilterGain = null; + +var outputGain; + +function Vocoder() { + Tone.Effect.call(this); + + outputGain = new Tone.Gain(); + + this.generateVocoderBands(55, 7040, 28); + this.initBandpassFilters(); + this.createCarrier(); + + this.effectSend.connect(modulatorInput); + outputGain.connect(this.effectReturn); +} + +Tone.extend(Vocoder, Tone.Effect); + +// this function will algorithmically re-calculate vocoder bands, distributing evenly +// from startFreq to endFreq, splitting evenly (logarhythmically) into a given numBands. +// The function places this info into the vocoderBands and numVocoderBands variables. +Vocoder.prototype.generateVocoderBands = function (startFreq, endFreq, numBands) { + // Remember: 1200 cents in octave, 100 cents per semitone + + var totalRangeInCents = 1200 * Math.log( endFreq / startFreq ) / Math.LN2; + var centsPerBand = totalRangeInCents / numBands; + var scale = Math.pow( 2, centsPerBand / 1200 ); // This is the scaling for successive bands + + vocoderBands = []; + var currentFreq = startFreq; + + for (var i=0; i0)?i:-i)/32768; + + for (var i=0; i