1import("stdfaust.lib");
2
3///////////////////////////////////////////////////////////////////////////////////////////////////
4//
5// A very simple subtractive synthesizer with 1 VCO 1 VCF.
6// The VCO Waveform is variable between Saw and Square
7// The frequency is modulated by an LFO
8// The envelope control volum and filter frequency
9//
10///////////////////////////////////////////////////////////////////////////////////////////////////
11// ANALOG IMPLEMENTATION:
12//
13// ANALOG_0	: waveform (Saw to square)
14// ANALOG_1	: Filter Cutoff frequency
15// ANALOG_2	: Filter resonance (Q)
16// ANALOG_3	: Filter Envelope Modulation
17//
18// MIDI:
19// CC 79	: Filter keyboard tracking (0 to X2, default 1)
20//
21// Envelope
22// CC 73	: Attack
23// CC 76	: Decay
24// CC 77	: Sustain
25// CC 72	: Release
26//
27// CC 78	: LFO frequency (0.001Hz to 10Hz)
28// CC 1		: LFO Amplitude (Modulation)
29//
30///////////////////////////////////////////////////////////////////////////////////////////////////
31//
32// HUI //////////////////////////////////////////////////
33// Keyboard
34midigate = button("gate");
35midifreq = nentry("freq[unit:Hz]", 440, 20, 20000, 1);
36midigain = nentry("gain", 0.5, 0, 0.5, 0.01);// MIDI KEYBOARD
37
38// pitchwheel
39bend = ba.semi2ratio(hslider("bend [midi:pitchwheel]",0,-2,2,0.01));
40
41// VCO
42wfFade = hslider("waveform[BELA: ANALOG_0]",0.5,0,1,0.001):si.smoo;
43
44// VCF
45res = hslider("resonnance[BELA: ANALOG_2]",0.5,0,1,0.001):si.smoo;
46fr = hslider("fc[BELA: ANALOG_1]", 15, 15, 12000, 0.001):si.smoo;
47track = hslider("tracking[midi:ctrl 79]", 1, 0, 2, 0.001);
48envMod = hslider("envMod[BELA: ANALOG_3]",50,0,100,0.01):si.smoo;
49
50// ENV
51att = 0.01 * (hslider("attack[midi:ctrl 73]",0.1,0.1,400,0.001));
52dec = 0.01 * (hslider("decay[midi:ctrl 76]",60,0.1,400,0.001));
53sust = hslider ("sustain[midi:ctrl 77]",0.2,0,1,0.001);
54rel = 0.01 * (hslider("release[midi:ctrl 72]",100,0.1,400,0.001));
55
56// LFO
57lfoFreq = hslider("lfoFreq[midi:ctrl 78]",6,0.001,10,0.001):si.smoo;
58modwheel = hslider("modwheel[midi:ctrl 1]",0,0,0.5,0.001):si.smoo;
59
60// PROCESS /////////////////////////////////////////////
61allfreq = (midifreq * bend) + LFO;
62// VCF
63cutoff = ((allfreq * track) + fr + (envMod * midigain * env)) : min(ma.SR/8);
64
65// VCO
66oscillo(f) = (os.sawtooth(f)*(1-wfFade))+(os.square(f)*wfFade);
67
68// VCA
69volume = midigain * env;
70
71// Enveloppe
72env	= en.adsre(att,dec,sust,rel,midigate);
73
74// LFO
75LFO = os.lf_triangle(lfoFreq)*modwheel*10;
76
77// SYNTH ////////////////////////////////////////////////
78synth = (oscillo(allfreq) : ve.moog_vcf(res,cutoff)) * volume;
79
80//#################################################################################################//
81//##################################### EFFECT SECTION ############################################//
82//#################################################################################################//
83//
84// Simple FX chaine build for a mono synthesizer.
85// It controle general volume and pan.
86// FX Chaine is:
87//		Drive
88//		Flanger
89//		Reverberation
90//
91// This version use ANALOG IN to controle some of the parameters.
92// Other parameters continue to be available by MIDI or OSC.
93//
94///////////////////////////////////////////////////////////////////////////////////////////////////
95// ANALOG IMPLEMENTATION:
96//
97// ANALOG_4	: Distortion Drive
98// ANALOG_5	: Flanger Dry/Wet
99// ANALOG_6	: Reverberation Dry/Wet
100// ANALOG_7	: Reverberation Room size
101//
102// MIDI:
103// CC 7		: Volume
104// CC 10	: Pan
105//
106// CC 13	: Flanger Delay
107// CC 13	: Flanger Delay
108// CC 94	: Flanger Feedback
109//
110// CC 95	: Reverberation Damp
111// CC 90	: Reverberation Stereo Width
112//
113///////////////////////////////////////////////////////////////////////////////////////////////////
114
115// VOLUME:
116volFX = hslider("volume[midi:ctrl 7]",1,0,1,0.001);	// Should be 7 according to MIDI CC norm.
117
118// EFFECTS /////////////////////////////////////////////
119drive = hslider("drive[BELA: ANALOG_4]",0.3,0,1,0.001);
120
121
122// Flanger
123curdel = hslider("flangDel[midi:ctrl 13]",4,0.001,10,0.001);
124fb = hslider("flangFeedback[midi:ctrl 94]",0.7,0,1,0.001);
125fldw = hslider("dryWetFlang[BELA: ANALOG_5]",0.5,0,1,0.001);
126flanger = efx
127	with {
128		fldel = (curdel + (os.lf_triangle(1) * 2)) : min(10);
129		efx = _ <: _, pf.flanger_mono(10,fldel,1,fb,0) : dry_wet(fldw);
130	};
131
132// Panoramic:
133panno = _ : sp.panner(hslider("pan[midi:ctrl 10]",0.5,0,1,0.001)) : _,_;
134
135// REVERB (from freeverb_demo)
136reverb = _,_ <: (*(g)*fixedgain, *(g)*fixedgain :
137	re.stereo_freeverb(combfeed, allpassfeed, damping, spatSpread)),
138	*(1-g), *(1-g) :> _,_
139    with {
140        scaleroom   = 0.28;
141        offsetroom  = 0.7;
142        allpassfeed = 0.5;
143        scaledamp   = 0.4;
144        fixedgain   = 0.1;
145        origSR = 44100;
146
147        damping = vslider("Damp[midi:ctrl 95]",0.5, 0, 1, 0.025)*scaledamp*origSR/ma.SR;
148        combfeed = vslider("RoomSize[BELA: ANALOG_7]", 0.7, 0, 1, 0.025)*scaleroom*origSR/ma.SR + offsetroom;
149        spatSpread = vslider("Stereo[midi:ctrl 90]",0.6,0,1,0.01)*46*ma.SR/origSR;
150        g = vslider("dryWetReverb[BELA: ANALOG_6]", 0.4, 0, 1, 0.001);
151        // (g = Dry/Wet)
152    };
153
154// Dry-Wet (from C. LEBRETON)
155dry_wet(dw,x,y) = wet*y + dry*x
156    with {
157        wet = 0.5*(dw+1.0);
158        dry = 1.0-wet;
159    };
160
161// ALL
162effect = _ *(volFX) : ef.cubicnl_nodc(drive, 0.1) : flanger : panno : reverb;
163
164// PROCESS /////////////////////////////////////////////
165process = synth;
166