Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Vibrato Pedal. Implements a pitch bend via an LFO’d delay. Expression…
… control increases the effect amount with signal amplitude.
- Loading branch information
Showing
with
90 additions
and 0 deletions.
- +1 −0 lib/Engine_Pedalboard.sc
- +26 −0 lib/fx/Vibrato.sc
- +1 −0 lib/ui/board.lua
- +62 −0 lib/ui/pedals/vibrato.lua
| @@ -0,0 +1,26 @@ | ||
| VibratoPedal : Pedal { | ||
| *id { ^\vibrato; } | ||
|
|
||
| *fxArguments { ^[\rate, \depth, \expression]; } | ||
|
|
||
| *fxDef {^{|wet| | ||
| var expression, envelopeFollower, envMultiplier, rate, depth, mul, minRate, maxDepth, maxDelay; | ||
| // Track the amplitude, so we vibrato more and faster when the signal is louder | ||
| envelopeFollower = Lag.ar(EnvFollow.ar((wet * 6).clip(-1, 1), 0.999), 0.14); | ||
| // Expression scales how much the envelope influences our vibrato | ||
| expression = \expression.kr(0.5); | ||
| envMultiplier = (1 - expression) + (envelopeFollower * expression); | ||
| // Delay the vibrato until after the attack portion of a typical envelope | ||
| envMultiplier = DelayN.ar(envMultiplier, 0.1, 0.07); | ||
| // Rate is how many vibratos per second | ||
| minRate = 0.75; | ||
| rate = LinExp.ar(\rate.kr(0.5) * envMultiplier, 0, 1, minRate, 60); | ||
| // Depth is pitch bend range in cents | ||
| maxDepth = 30; | ||
| depth = LinExp.ar(\depth.kr(0.5) * envMultiplier, 0, 1, 3.3, maxDepth); | ||
| // Mul calculates the amplitude of the LFO for our delay to achieve the given rate and depth | ||
| mul = ((2 ** (depth * 1200.reciprocal)) - 1)/(4 * rate); | ||
| maxDelay = (((2 ** (maxDepth * 1200.reciprocal)) - 1)/(4 * minRate)) * 2.5; | ||
| wet = DelayC.ar(wet, maxDelay, SinOsc.ar(rate, 2, mul, mul + ControlRate.ir.reciprocal)); | ||
| }} | ||
| } |
| @@ -0,0 +1,62 @@ | ||
| --- VibratoPedal | ||
| -- @classmod VibratoPedal | ||
|
|
||
| local UI = require "ui" | ||
| local Pedal = include("lib/ui/pedals/pedal") | ||
| local Controlspecs = include("lib/ui/util/controlspecs") | ||
|
|
||
| local VibratoPedal = Pedal:new() | ||
| -- Must match this pedal's .sc file's *id | ||
| VibratoPedal.id = "vibrato" | ||
|
|
||
| function VibratoPedal:new(bypass_by_default) | ||
| local i = Pedal:new(bypass_by_default) | ||
| setmetatable(i, self) | ||
| self.__index = self | ||
|
|
||
| i.sections = { | ||
| {"Rate & Depth", "Expression"}, | ||
| i:_default_section(), | ||
| } | ||
| i:_complete_initialization() | ||
|
|
||
| return i | ||
| end | ||
|
|
||
| function VibratoPedal:name(short) | ||
| return short and "VIBE" or "Vibrato" | ||
| end | ||
|
|
||
| function VibratoPedal.params() | ||
| local id_prefix = VibratoPedal.id | ||
|
|
||
| local rate_control = { | ||
| id = id_prefix .. "_rate", | ||
| name = "Rate", | ||
| type = "control", | ||
| controlspec = Controlspecs.MIX, | ||
| } | ||
| local depth_control = { | ||
| id = id_prefix .. "_depth", | ||
| name = "Depth", | ||
| type = "control", | ||
| controlspec = Controlspecs.MIX, | ||
| } | ||
| local expression_control = { | ||
| id = id_prefix .. "_expression", | ||
| name = "Expression", | ||
| type = "control", | ||
| controlspec = Controlspecs.MIX, | ||
| } | ||
|
|
||
| -- Default mix of 100% | ||
| local default_params = Pedal._default_params(id_prefix) | ||
| default_params[1][2].controlspec = Controlspecs.mix(100) | ||
|
|
||
| return { | ||
| {{rate_control, depth_control}, {expression_control}}, | ||
| default_params, | ||
| } | ||
| end | ||
|
|
||
| return VibratoPedal |