// eChucK Wind Instrument Model // Copyright 2010 Les Hall // The Patch // // air source with noise Noise n => ADSR adsr; Step DCLevel => adsr => Gain source; 0.03 => n.gain; 44.0 / 64.0 => DCLevel.next; adsr.set(18.7::ms, 0.5::ms, 1.0, 143.4::ms); // // Jet Driver Gain JetIn => Dyno limiter => Gain sum => Gain x1 => Gain x2; Step offset => sum; sum => Gain pow => Gain diff => Gain JetOut; sum => diff; x1 => pow; x2 => pow; -1 => JetIn.gain; limiter.limit(); -0.5 => offset.next; 3 => pow.op; 2 => diff.op; 1 => JetOut.gain; // // Embouchure Delay DelayA Edelay; 100::ms => Edelay.max; // // Bore delay DelayA Bdelay => LPF lpf; 100::ms => Bdelay.max; 8370 => lpf.freq; // // closed loop source => JetIn; JetOut => Edelay; Edelay => Bdelay; lpf => Gain Egain => JetIn; // Embrochure Feedback lpf => Gain Bgain => Bdelay; // Bore Feedback lpf => HPF hpf => dac; 0.5 => Egain.gain; 0.44 => Bgain.gain; 329.8 => hpf.freq; 0.5 => dac.gain; // Boolean Sequencer Class class BooleanSequencer { // variables int switches[]; // the switch settings int b; // the binary counter int sum; // sum of switches that match int bitMask; // rollover bit mask // set switches fun void set(int array[]) { array @=> switches; } fun void setBits(int n) { (Math.pow(2, n) - 1) $ int => bitMask; } // reset counter fun void reset() { 0 => b; } // perform one iteration of the sequencer fun void iterate() { 0 => sum; for (int i; i sum; } 1 +=> b; // increment b bitMask & b => b; // make b an 8 bit counter } // get the sum fun int getSum() { return sum; } // get the gate fun int getGate() { if (sum > 0) { return true; } else { return false; } } } BooleanSequencer BS; // set up and perform the song BS.set([5, 7, 11, 16, 20, 24, 27, 36, 42, 47, 52, 59]); BS.setBits(6); float VCOInputVoltage; float VCOControlCurrent; float VCOFreq; float BBDDelay; float VCFInputVoltage; float VCFControlCurrent; float VCFFreq; while(true) { BS.iterate(); // receive VCO stim and convert to delay duration BS.getSum() * 3.0 / 10.0 => VCOInputVoltage; Math.pow(2.0, VCOInputVoltage) / 8.0 / 1000.0 => VCOControlCurrent; VCOControlCurrent * 1000000000.0 + 10000.0 => VCOFreq; 512.0 / VCOFreq => BBDDelay; <<<"VCOInputVoltage:", VCOInputVoltage, " VCOFreq:", VCOFreq, " BBDDelay:", BBDDelay>>>; BBDDelay::second => Bdelay.delay; 0.5*BBDDelay::second => Edelay.delay; // receive VCF stim and convert to filter frequency //BS.getSum() * 3.0 / 10.0 => VCFInputVoltage; //Math.pow(2.0, VCFInputVoltage) / 8.0 / 1000.0 => VCFControlCurrent; //20000000.0 * VCFControlCurrent => VCFFreq; //VCFFreq => lpf.freq; // gate the output and drive the adsr 50::ms => now; if (BS.getGate()) { adsr.keyOn(); } 700::ms => now; adsr.keyOff(); 250::ms => now; }