synths.lib
Synths library. Its official prefix is sy.
This library provides synthesizer and drum building blocks.
The Synths library is organized into 2 sections:
References
Synthesizers
(sy.)popFilterDrum
A simple percussion instrument based on a "popped" resonant bandpass filter.
popFilterDrum is a standard Faust function.
Usage
popFilterDrum(freq,q,gate) : _
Where:
freq: the resonance frequency of the instrument in Hzq: the q of the res filter (typically, 5 is a good value)gate: the trigger signal (0 or 1)
Test
sy = library("synths.lib");
popFilterDrum_test = sy.popFilterDrum(200, 5, button("popFilterDrum:gate"));
popFilterDrum_slider_test = sy.popFilterDrum(
hslider("popFilterDrum:freq", 200, 50, 1000, 1),
hslider("popFilterDrum:q", 5, 1, 20, 0.1),
button("popFilterDrum:gate")
);
(sy.)dubDub
A simple synth based on a sawtooth wave filtered by a resonant lowpass.
dubDub is a standard Faust function.
Usage
dubDub(freq,ctFreq,q,gate) : _
Where:
freq: frequency of the sawtooth in HzctFreq: cutoff frequency of the filterq: Q of the filtergate: the trigger signal (0 or 1)
Test
sy = library("synths.lib");
ba = library("basics.lib");
ma = library("maths.lib");
dubDub_test = sy.dubDub(220, 800, 2, button("dubDub:gate"));
dubDub_slider_test = sy.dubDub(
hslider("dubDub:freq", 220, 50, 1000, 1),
hslider("dubDub:cutoff", 800, 100, 6000, 1),
hslider("dubDub:q", 2, 0.2, 10, 0.1),
button("dubDub:gate")
);
dubDub_modulated_test = sy.dubDub(220, 100*pow(60, tri), 2, button("dubDub:gate")) with { P = int(ma.SR/10); tri = 1 - abs(2*ba.period(P)/P - 1); };
(sy.)sawTrombone
A simple trombone based on a lowpassed sawtooth wave.
sawTrombone is a standard Faust function.
Usage
sawTrombone(freq,gain,gate) : _
Where:
freq: the frequency in Hzgain: the gain (0-1)gate: the gate (0 or 1)
Test
sy = library("synths.lib");
sawTrombone_test = sy.sawTrombone(196, 0.6, button("sawTrombone:gate"));
sawTrombone_slider_test = sy.sawTrombone(
hslider("sawTrombone:freq", 196, 50, 600, 1),
hslider("sawTrombone:gain", 0.6, 0, 1, 0.01),
button("sawTrombone:gate")
);
(sy.)combString
Simplest string physical model ever based on a comb filter.
combString is a standard Faust function.
Usage
combString(freq,res,gate) : _
Where:
freq: the frequency of the string in Hzres: string T60 (resonance time) in secondgate: trigger signal (0 or 1)
Test
sy = library("synths.lib");
ba = library("basics.lib");
ma = library("maths.lib");
combString_test = sy.combString(220, 4, button("combString:gate"));
combString_slider_test = sy.combString(
hslider("combString:freq", 220, 55, 880, 1),
hslider("combString:res", 4, 0.1, 10, 0.01),
button("combString:gate")
);
combString_modulated_test = sy.combString(220*pow(4, tri), 4, button("combString:gate")) with { P = int(ma.SR/10); tri = 1 - abs(2*ba.period(P)/P - 1); };
combString_jump_test = sy.combString(220*pow(4, sq), 4, button("combString:gate")) with { P = int(ma.SR/10); sq = ba.period(2*P) < P; };
(sy.)additiveDrum
A simple drum using additive synthesis.
additiveDrum is a standard Faust function.
Usage
additiveDrum(freq,freqRatio,gain,harmDec,att,rel,gate) : _
Where:
freq: the resonance frequency of the drum in HzfreqRatio: a list of ratio to choose the frequency of the mode in function offreqe.g.(1 1.2 1.5 ...). The first element should always be one (fundamental).gain: the gain of each mode as a list (1 0.9 0.8 ...). The first element is the gain of the fundamental.harmDec: harmonic decay ratio (0-1): configure the speed at which higher modes decay compare to lower modes.att: attack duration in secondrel: release duration in secondgate: trigger signal (0 or 1)
Test
sy = library("synths.lib");
additiveDrum_test = sy.additiveDrum(180, (1, 1.3, 2.4, 3.2), (1, 0.8, 0.6, 0.4), 0.4, 0.01, 0.4, button("additiveDrum:gate"));
additiveDrum_slider_test = sy.additiveDrum(
hslider("additiveDrum:freq", 180, 60, 600, 1),
(1, 1.3, 2.4, 3.2),
(1, 0.8, 0.6, 0.4),
hslider("additiveDrum:harmDec", 0.4, 0, 1, 0.01),
0.01,
0.4,
button("additiveDrum:gate")
);
(sy.)fm
An FM synthesizer with an arbitrary number of modulators connected as a sequence.
fm is a standard Faust function.
Usage
freqs = (300,400,...);
indices = (20,...);
fm(freqs,indices) : _
Where:
freqs: a list of frequencies where the first one is the frequency of the carrier and the others, the frequency of the modulator(s)indices: the indices of modulation (Nfreqs-1)
Test
sy = library("synths.lib");
ba = library("basics.lib");
ma = library("maths.lib");
fm_test = sy.fm((220, 440, 660), (1.5, 0.8));
fm_modulated_test = sy.fm((220, 440), (1000*tri)) with { P = int(ma.SR/10); tri = 1 - abs(2*ba.period(P)/P - 1); };
(sy.)logicEFM1
Model of one voice of Apple Logic Pro's EFM1, a two-operator FM synthesizer: a sine carrier phase-modulated by a modulator whose waveform morphs through ten wavetables, with volume and modulation envelopes, a key-synced LFO, a sub oscillator, carrier stereo detune and a unison mode. Stereo output.
EFM1 exists only inside Logic Pro, so it cannot be hosted outside it. The model was reverse-engineered from single notes rendered by Logic at 48 kHz, each with one or two controls changed from a neutral patch and every control value read back from Logic. The laws and constants below were fitted to those renders, and the wavetables were read out of them. Against 94 of these renders the model matches the level to 0.03 dB and, for steady tones, the waveform to 0.7 % (median) and 4.4 % (worst case). The implementation notes give the fit per feature and list what was not measured: only 48 kHz, only C notes (C0 to C6), and one or a few settings for several controls.
Usage
logicEFM1(modHarm, carHarm, modFine, carFine, fixedCar, fmInt, modWave,
modEnvFM, modPitch, subLevel, stereoDet, unison,
lfoAmt, lfoRate, velAmt, mainLevel,
vA, vD, vS, vR, mA, mD, mS, mR,
freq, gate, gain) : _,_
Where:
modHarm: modulator harmonic, an integer >= 1 (modulator frequency = modHarm*freq)carHarm: carrier harmonic, an integer >= 0 (carrier frequency = carHarm*freq; 0 gives a 0 Hz carrier)modFine: modulator fine ratio offset (-0.5..0.5), added to modHarmcarFine: carrier fine ratio offset (-0.5..0.5), added to carHarmfixedCar: Fixed Carrier switch (0/1): the carrier sits at C1 (32.70 Hz) times its ratio, independent of freq and the LFOfmInt: FM intensity (0-1)modWave: modulator waveform (0-9): 0 is a sine, and the knob blends the ten wavetables linearlymodEnvFM: modulation envelope to FM intensity (-1..1)modPitch: modulation envelope to modulator pitch (-1..1; up to +-27.5 semitones)subLevel: sub oscillator level (0-1; a sine one octave below freq)stereoDet: carrier stereo detune as displayed (0-50; the carriers move by about 0.75x this many cents)unison: Unison switch (0/1): a second, slightly detuned copy of the voicelfoAmt: LFO amount, bipolar (-1 = full vibrato, +-36 semitones .. +1 = full FM modulation)lfoRate: LFO rate in Hz (0.01-100)velAmt: velocity sensitivity of the level (0-1)mainLevel: output gain (linear; 1 = Logic's 0 dB)vA: volume envelope attack in ms, as Logic displays it (0-10000)vD: volume envelope decay in ms (0-10000)vS: volume envelope sustain (0-1)vR: volume envelope release in ms (0-10000)mA: modulation envelope attack in ms (0-10000)mD: modulation envelope decay in ms (0-10000)mS: modulation envelope sustain (0-1)mR: modulation envelope release in ms (0-10000)freq: note frequency in Hzgate: note gate (0/1)gain: note velocity (MIDI velocity/127)
Test
sy = library("synths.lib");
ba = library("basics.lib");
ma = library("maths.lib");
logicEFM1_test = sy.logicEFM1(1, 2, 0, 0, 0, 0.3, 2.5, 0.5, 0.2, 0.3, 10, 0,
-0.3, 2, 0.3, 1, 10, 500, 0.7, 300, 0, 800, 0.2, 200,
261.63, ba.time < int(0.75*ma.SR), 0.8);
logicEFM1_unison_test = sy.logicEFM1(3, 4, 0, 0, 1, 0.35, 8.9, 0.7, 0, 0.2, 35, 1,
0.8, 1, 0.8, 1, 5, 1200, 0.3, 500, 0, 2000, 0.1, 400,
261.63, ba.time < int(0.75*ma.SR), 0.8);
logicEFM1_slider_test = sy.logicEFM1(1, 2, 0, 0, 0,
hslider("logicEFM1:fmInt", 0.3, 0, 1, 0.01), hslider("logicEFM1:modWave", 2.5, 0, 9, 0.01),
0.5, 0.2, 0.3, 10, 0, -0.3, 2, 0.3, 1, 10, 500, 0.7, 300, 0, 800, 0.2, 200,
hslider("logicEFM1:freq", 261.63, 20, 2000, 0.01), ba.time < int(0.75*ma.SR), 0.8);
logicEFM1_modulated_test = sy.logicEFM1(1, 2, 0, 0, 0, 0.3, 9*tri, 0.5, 0.2, 0.3, 10, 0, -0.3, 2, 0.3, 1, 10, 500, 0.7, 300, 0, 800, 0.2, 200, 261.63, ba.time < int(0.75*ma.SR), 0.8) with { P = int(ma.SR/10); tri = 1 - abs(2*ba.period(P)/P - 1); };
References
- Apple, Logic Pro User Guide, "EFM1".
Drum Synthesis
Drum Synthesis ported in Faust from a version written in Elementary and JavaScript by Nick Thompson.
References
(sy.)kick
Kick drum synthesis via a pitched sine sweep.
Usage
kick(pitch, click, attack, decay, drive, gate) : _
Where:
pitch: the base frequency of the kick drum in Hzclick: the speed of the pitch envelope, tuned for [0.005s, 1s]attack: attack time in seconds, tuned for [0.005s, 0.4s]decay: decay time in seconds, tuned for [0.005s, 4.0s]drive: a gain multiplier going into the saturator. Tuned for [1, 10]gate: the gate which triggers the amp envelope
Test
sy = library("synths.lib");
kick_test = sy.kick(60, 0.2, 0.01, 0.5, 3, button("kick:gate"));
kick_slider_test = sy.kick(
hslider("kick:pitch", 60, 30, 120, 0.1),
hslider("kick:click", 0.2, 0.005, 1, 0.001),
0.01,
0.5,
hslider("kick:drive", 3, 1, 10, 0.1),
button("kick:gate")
);
References
(sy.)clap
Clap synthesis via filtered white noise.
Usage
clap(tone, attack, decay, gate) : _
Where:
tone: bandpass filter cutoff frequency, tuned for [400Hz, 3500Hz]attack: attack time in seconds, tuned for [0s, 0.2s]decay: decay time in seconds, tuned for [0s, 4.0s]gate: the gate which triggers the amp envelope
Test
sy = library("synths.lib");
clap_test = sy.clap(1200, 0.01, 0.6, button("clap:gate"));
clap_slider_test = sy.clap(
hslider("clap:tone", 1200, 400, 3500, 10),
0.01,
0.6,
button("clap:gate")
);
References
(sy.)hat
Hi hat drum synthesis via phase modulation.
Usage
hat(pitch, tone, attack, decay, gate): _
Where:
pitch: base frequency in the range [317Hz, 3170Hz]tone: bandpass filter cutoff frequency, tuned for [800Hz, 18kHz]attack: attack time in seconds, tuned for [0.005s, 0.2s]decay: decay time in seconds, tuned for [0.005s, 4.0s]gate: the gate which triggers the amp envelope
Test
sy = library("synths.lib");
hat_test = sy.hat(800, 5000, 0.005, 0.3, button("hat:gate"));
hat_slider_test = sy.hat(
hslider("hat:pitch", 800, 317, 3170, 1),
hslider("hat:tone", 5000, 800, 18000, 10),
0.005,
0.3,
button("hat:gate")
);