1// imported by echo.dsp and echomt.dsp
2
3import("stdfaust.lib");
4
5echo_group(x) = x; // Let layout2.dsp lay us out
6   knobs_group(x) = ekg(x);
7   switches_group(x)  = esg(x);
8
9dmax = 32768; // one and done
10dmaxs = float(dmax)/44100.0;
11
12Nnines = 1.8; // Increase until you get the desired maximum amount of smoothing when fbs==1
13//fastpow2 = ffunction(float fastpow2(float), "fast_pow2.h", "");
14fbspr(fbs) = 1.0 - pow(2.0, (-3.33219*Nnines*fbs)); // pole radius of feedback smoother
15inputSelect(gi) = _,0 : select2(gi);
16echo_mono(dmax,curdel,tapdel,fb,fbspr,gi) = inputSelect(gi) : (+:si.smooth(fbspr)
17				   <: de.fdelay(dmax,curdel),
18				      de.fdelay(dmax,tapdel))
19				      ~(*(fb),!) : !,_;
20
21tau2pole(tau) = ba.if(tau>0, exp(-1.0/(tau*ma.SR)), 0.0);
22t60smoother(dEchoT60) = si.smooth(tau2pole(dEchoT60/6.91));
23
24dEchoT60 = knobs_group(vslider("[1] DelayT60 [midi:ctrl 60] [style:knob]", 0.5, 0, 100, 0.001));
25dEchoSamplesRaw = knobs_group(vslider("[0] Delay [midi:ctrl 4] [style:knob]", 0.5, 0.001, (dmaxs-0.001), 0.001)) * ma.SR;
26dEchoSamples = dEchoSamplesRaw : t60smoother(dEchoT60);
27warpRaw = knobs_group(vslider("[0] Warp [midi:ctrl 62] [style:knob]", 0, -1.0, 1.0, 0.001));
28
29scrubAmpRaw = 0;
30
31scrubPhaseRaw = 0;
32fb = knobs_group(vslider("[2] Feedback [midi:ctrl 3] [style:knob]", .3, 0.0, 1.0, 0.0001));
33amp = knobs_group(vslider("[3] Amp [midi:ctrl 2] [style:knob]", .5, 0, 1, 0.001)) : si.smooth(ba.tau2pole(ampT60/6.91));
34
35ampT60 = 0.15661;
36fbs = knobs_group(vslider("[5] [midi:ctrl 76] FeedbackSm [style:knob]", 0, 0, 1, 0.00001));
37gi = switches_group(1-vslider("[7] [midi:ctrl 105] EnableEcho[style:knob]",0,0,1,1)); // "ground input" switches input to zeros
38
39// Warp and Scrubber stuff:
40enableEcho = (scrubAmpRaw > 0.00001);
41triggerScrubOn = (enableEcho - enableEcho') > 0;  // enableEcho went 0 to 1
42triggerScrubOff = (enableEcho - enableEcho') < 0; // enableEcho went 1 to 0
43// Ramps up only during scrub "hold" time and is otherwise zero:
44counter = (enableEcho * (triggerScrubOn : + ~ +(1) * enableEcho : -(2))) & (dmax-1);
45// implementation that continues scrubbing where it left off:
46
47scrubPhase = scrubPhaseRaw : t60smoother(dEchoT60*(1-triggerScrubOff));
48scrubAmp = scrubAmpRaw : t60smoother(dEchoT60*(1-triggerScrubOff));
49warp = warpRaw : t60smoother(dEchoT60);
50dTapSamplesRaw = dEchoSamplesRaw * (1.0 + warp + scrubPhase * scrubAmp) + float(counter);
51dTapSamples = dTapSamplesRaw : t60smoother(dEchoT60*(1-triggerScrubOff));
52
53process = _ <: _, amp * echo_mono(dmax,dEchoSamples,dTapSamples,fb,fbspr(fbs),gi) : +;
54// This layout loosely follows the MiniMoog-V
55// Arturia-only features are labeled
56// Original versions also added where different
57
58// Need vrocker and hrocker toggle switches in Faust!
59// Need orange and blue color choices
60//   Orange => Connect modulation sources to their destinations
61//    Blue  => Turn audio sources On and Off
62// - and later -
63//   White  => Turn performance features On and Off
64//   Black  => Select between modulation sources
65//   Julius Smith for Analog Devices 3/1/2017
66
67vrocker(x) = checkbox("%%x [style:vrocker]");
68hrocker(x) = checkbox("%%x [style:hrocker]");
69vrockerblue(x) = checkbox("%x  [style:vrocker] [color:blue]");
70vrockerblue(x) = checkbox("%x [style:vrocker] [color:blue]");
71 // USAGE: vrockerorange("[0] ModulationEnable");
72
73hrockerblue(x) = checkbox("%%x [style:hrocker] [color:blue]");
74vrockerred(x) = checkbox("%%x [style:vrocker] [color:red]");
75hrockerred(x) = checkbox("%%x [style:hrocker] [color:red]");
76
77declare designer "Robert A. Moog";
78
79mmg(x) = hgroup("",x); // Minimoog + Effects
80  synthg(x) = mmg(vgroup("[0] Minimoog",x));
81  fxg(x) = mmg(hgroup("[1] Effects",x));
82  mg(x) = synthg(hgroup("[0]",x));
83    cg(x) = mg(vgroup("[0] Controllers",x)); // Formerly named "Modules" but "Minimoog" group-title is enough
84      vg(x) = cg(hgroup("[0] Master Volume", x));
85      dg(x) = cg(hgroup("[1] Oscillator Tuning & Switching", x));
86        // Tune knob = master tune
87        dsg(x) = dg(vgroup("[1] Switches", x));
88	  // Oscillator Modulation HrockerRed => apply Modulation Mix output to osc1&2 pitches
89	  // [MOVED here from osc3 group] Osc 3 Control VrockerRed => use osc3 as LFO instead of osc3
90      gmmg(x) = cg(hgroup("[2] Glide and ModMix", x));
91        // Glide knob [0:10] = portamento speed
92        // Modulation Mix knob [0:10] (between Osc3 and Noise) = mix of noise and osc3 modulating osc1&2 pitch and/or VCF freq
93    og(x) = mg(vgroup("[1] Oscillator Bank", x));
94      osc1(x) = og(hgroup("[1] Oscillator 1", x));
95        // UNUSED Control switch (for alignment) - Could put Oscillator Modulation switch there
96        // Range rotary switch: LO (slow pulses or rhythm), 32', 16', 8', 4', 2'
97        // Frequency <something> switch: LED to right
98        // Waveform rotary switch: tri, impulse/bent-triangle, saw, pulseWide, pulseMed, pulseNarrow
99      osc2(x) = og(hgroup("[2] Oscillator 2", x));
100        // UNUSED (originall) or Osc 2 Control VrockerRed
101        // Range rotary switch: LO, 32', 16', 8', 4', 2'
102        // Detuning knob: -7 to 7 [NO SWITCH]
103        // Waveform rotary switch: tri, impulse(?), saw, pulseWide, pulseMed, pulseNarrow
104      osc3(x) = og(hgroup("[3] Oscillator 3", x));
105        // Osc 3 Control VrockerRed => use osc3 as LFO instead of osc3
106        // Range rotary switch: LO, 32', 16', 8', 4', 2'
107        // Detuning knob: -7 to 7 [NO SWITCH]
108        // Waveform rotary switch: tri, impulse(?), saw, pulseWide, pulseMed, pulseNarrow
109    mixg(x) = mg(vgroup("[2] Mixer", x));
110      // Each row 5 slots to maintain alignment and include red rockers joining VCF area:
111      mr1(x) = mixg(hgroup("[0] Osc1", x)); // mixer row 1 =
112      // Osc1 Volume and Osc1 HrockerBlue & _ & _ & Filter Modulation HrockerRed
113      // Filter Modulation => Modulation Mix output to VCF freq
114      mr2(x) = mixg(hgroup("[1] Ext In, KeyCtl", x)); // row 2 = Ext In HrockerBlue and Vol and Overload LED and Keyboard Ctl HrockerRed 1
115      mr3(x) = mixg(hgroup("[2] Osc2", x)); // = Osc2 Volume and Osc2 HrockerBlue and Keyboard Ctl HrockerRed 2
116      // Keyboard Control Modulation 1&2 => 0, 1/3, 2/3, all of Keyboard Control Signal ("gate?") applied to VCF freq
117      mr4(x) = mixg(hgroup("[3] Noise", x)); // = Noise HrockerBlue and Volume and Noise Type VrockerBlue
118        mr4cbg(x) = mr4(vgroup("[1]", x)); // = Noise Off and White/Pink selection
119	// two rockers
120      mr5(x) = mixg(hgroup("[4] Osc3", x)); //  Osc3 Volume and Osc3 HrockerBlue
121    modg(x) = mg(vgroup("[3] Modifiers", x));
122      vcfg(x) = modg(vgroup("[0] Filter", x));
123        vcf1(x) = vcfg(hgroup("[0] [tooltip:freq, Q, ContourScale]", x));
124	  vcf1cbg(x) = vcf1(vgroup("[0] [tooltip:two checkboxes]", x));
125          // Filter Modulation switch
126          // VCF Off switch
127        // Corner Frequency knob
128        // Filter Emphasis knob
129        // Amount of Contour knob
130        vcf2(x) = vcfg(hgroup("[1] Filter Contour [tooltip:AttFilt, DecFilt, Sustain Level for Filter Contour]", x));
131        // Attack Time knob
132        // Decay Time knob
133        // Sustain Level knob
134      ng(x) = modg(hgroup("[1] Loudness Contour", x));
135        // Attack Time knob
136        // Decay Time knob
137        // Sustain Level knob
138    echog(x) = fxg(hgroup("[4] Echo",x));
139      ekg(x) = echog(vgroup("[0] Knobs",x));
140      esg(x) = echog(vgroup("[1] Switches",x));
141    flg(x) = fxg(hgroup("[5] Flanger",x));
142      flkg(x) = flg(vgroup("[0] Knobs",x));
143      flsg(x) = flg(vgroup("[1] Switches",x));
144    chg(x) = fxg(hgroup("[6] Chorus",x));
145      ckg(x) = chg(vgroup("[0] Knobs",x));
146      csg(x) = chg(vgroup("[1] Switches",x));
147    rg(x) = fxg(hgroup("[7] Reverb",x));
148      rkg(x) = rg(vgroup("[0] Knobs",x));
149      rsg(x) = rg(vgroup("[1] Switches",x));
150    outg(x) = fxg(vgroup("[8] Output", x));
151      volg(x) = outg(hgroup("[0] Volume Main Output", x));
152        // Volume knob [0-10]
153	// Unison switch (Arturia) or Output connect/disconnect switch (original)
154	//   When set, all voices are stacked and instrument is in mono mode
155      tunerg(x) = outg(hgroup("[1] A-440 Switch", x));
156      vdtpolyg(x) = outg(hgroup("[2] Voice Detune / Poly", x));
157        // Voice Detune knob [0-10] (Arturia) or
158	// Polyphonic switch [red LED below] (Arturia)
159	//   When set, instrument is in polyphonic mode with one oscillator per key
160    clipg(x) = fxg(vgroup("[9] Soft Clip", x));
161	// Soft Clipping switch [red LED above]
162  kg(x) = synthg(hgroup("[1] Keyboard Group", x)); // Keyboard was 3 1/2 octaves
163    ws(x) = kg(vgroup("[0] Wheels and Switches", x));
164      s1g(x) = ws(hgroup("[0] Jacks and Rockers", x));
165        jg(x) = s1g(vgroup("[0] MiniJacks",x));
166        gdlg(x) = s1g(vgroup("[1] Glide/Decay/Legato Enables",x)); // Arturia
167	// Glide Hrocker (see original Button version below)
168	// Decay Hrocker (see original Button version below) => Sets Release (R) of ADSR to either 0 or Decay (R)
169	// Legato Hrocker (not in original)
170      s2g(x) = ws(hgroup("[1] [tooltip:Wheels+]", x));
171        bg(x) = s2g(vgroup("[0] [tooltip:Bend Enable and Range]", x));
172        wg(x) = s2g(hgroup("[1] [tooltip:Bend and Mod Wheels]", x));
173	// Using Glide/Decay/Legato enables above following Arturia:
174	//   dg(x) = s2g(hgroup("[2] Glide and Decay momentary pushbuttons", x));
175	//   Glide Button injects portamento as set by Glide knob
176	//   Decay Button uses decay of Loudness Contour (else 0)
177    keys(x) = kg(hgroup("[1] [tooltip:Keys]", x));
178      gg(x) = keys(hgroup("[0] [tooltip: Gates]",x));
179      // leave slot 1 open for sustain (below)
180