; Honk.csd
; Written by Iain McCurdy, 2014
;
; Instrument based on the wgbowedbar opcode (bowed bar).
; As with many physical modelling opcodes the results can be unpredicatable sometimes resulting in silence and at other times resulting in overloading.
; I have endeavoured to protect against overloads. Controller ranges have been tuned to provide the most interesting results but extensive experimentation is still recommended.
;
; Input (Amplitude)
; -----------------
; This controls the amplitude of vibrations caused by the bow upon the bar. Note that this is not a linear 'level' control.
; 'Amplitude' - this is a manual control for amplitude
; 'Velocity' - this controls how midi key velocity affects amplitude
; 'Env' - this controls the amount of envelope influence upon amplitude. (If zero, 'Dec.Tim.' and 'Sus.Lev' will have no effect.)
; 'Att.Tim' - time taken to rise to a maximum value before implementing the decay stage
; 'Dec.Tim' - time taken to decay to the sustain level
; 'Sus.Lev' - the sustain level for amplitude
; 'Rel.Tim' - the release time for amplitude
;
; Output
; ------
; Controls pertaining to the output of the instrument
; 'Width' - width of a stereo effect using slowly modulating delays. When set to zero the output (before reverb) is monophonic.
; 'Rvb.Send' - amount of signal sent to a reverb effect
; 'Rvb.Size' - room size of the reverb effect (reverbsc)
;
; Bow Position
; ------------
; 'Position' - manual control of bowing position along the bar
; 'Depth' - depth of random modulation of bowing position
; 'Rate' - rate of random modulation of bowing position
;
; Bow Pressure
; ------------
; 'Pressure' - manual control of bowing pressure
; 'Velocity' - influence of key velocity upon bow pressure.
; This value (range zero - 'velocity') is added to the manual pressure control (and limited to be within the range zero - 1).
; Therefore for maximum velocity influence, set 'Velocity' to 1, 'Pressure' to zero and 'Depth' (see below) to zero.
; 'Depth' - depth of random modulation of bowing pressure
; 'Rate' - rate of random modulation of bowing pressure
;
; System
; ------
; 'Feedback' - gain of filter in the model. This will affect the abiltity of the instrument to achieve and sustain resonance.
; 'Discord' - an integration constant used in the setup of the model. Audibly varies dischord. This control changes at i-rate therefore changing it during a note will cause discontinuities.
form caption("Honk") size(700, 440), pluginid("Honk"), colour("LightGrey")
; amplitude
image bounds( 0, 0,440, 90), colour(50,50,100), outlinecolour("LightGrey"), outlinethickness(1), shape("sharp"), plant("amplitude"){
label bounds( 5, 5,380, 12), text("Input"), fontcolour(white)
rslider bounds( 10, 20, 60, 60), text("Amplitude"), channel("amp"), range(0, 1.00, 0.85), TrackerColour("Silver"), textcolour("white"), colour("white"), outlinecolour(100,100,100)
rslider bounds( 70, 20, 60, 60), text("Velocity"), channel("vel"), range(0, 1.00, 0.66), TrackerColour("Silver"), textcolour("white"), colour("white"), outlinecolour(100,100,100)
rslider bounds(130, 20, 60, 60), text("Env."), channel("AEnv"), range(0, 1.00, 0), TrackerColour("Silver"), textcolour("white"), colour("white"), outlinecolour(100,100,100)
rslider bounds(190, 20, 60, 60), text("Att.Tim."), channel("AAttTim"), range(0, 2.00, 0.1, 0.5), TrackerColour("Silver"), textcolour("white"), colour("white"), outlinecolour(100,100,100)
rslider bounds(250, 20, 60, 60), text("Dec.Tim."), channel("ADecTim"), range(0.001, 5.00, 0.1, 0.5), TrackerColour("Silver"), textcolour("white"), colour("white"), outlinecolour(100,100,100)
rslider bounds(310, 20, 60, 60), text("Sus.Lev."), channel("ASusLev"), range(0, 1.00, 1), TrackerColour("Silver"), textcolour("white"), colour("white"), outlinecolour(100,100,100)
rslider bounds(370, 20, 60, 60), text("Rel.Tim."), channel("ARelTim"), range(0, 2.00, 0.1,0.5,0.001), TrackerColour("Silver"), textcolour("white"), colour("white"), outlinecolour(100,100,100)
}
; output
image bounds(440, 0,260, 90), colour(50,50,100), outlinecolour("LightGrey"), outlinethickness(1), shape("sharp"), plant("output"){
label bounds( 5, 5,250, 12), text("Output"), fontcolour(white)
rslider bounds( 10, 20, 60, 60), text("Width"), channel("width"), range(0, 1.00, 0.3), TrackerColour("Silver"), textcolour("white"), colour("white"), outlinecolour(100,100,100)
rslider bounds( 70, 20, 60, 60), text("Rvb.Send"), channel("RvbSend"), range(0, 1.00, 0.2), TrackerColour("Silver"), textcolour("white"), colour("white"), outlinecolour(100,100,100)
rslider bounds(130, 20, 60, 60), text("Rvb.Size"), channel("RvbSize"), range(0.5, 0.99, 0.6), TrackerColour("Silver"), textcolour("white"), colour("white"), outlinecolour(100,100,100)
rslider bounds(190, 20, 60, 60), text("Level"), channel("OutGain"), range(0, 10.00, 0.5,0.5), TrackerColour("Silver"), textcolour("white"), colour("white"), outlinecolour(100,100,100)
}
; bow position
image bounds( 0, 90,700, 90), colour(50,50,100), outlinecolour("LightGrey"), outlinethickness(1), shape("sharp"), plant("bowposition"){
label bounds( 5, 5,690, 12), text("Bowing Position"), fontcolour(white)
hslider bounds( 10, 30,565, 30), text("Manual"), channel("pos"), range(0, 1.00, 0.7), TrackerColour("Silver"), textcolour("white"), colour("white")
line bounds(580, 8,100, 2), colour("grey")
label bounds(595, 5, 72, 10), text("MODULATION"), colour(50,50,100), fontcolour("white")
rslider bounds(570, 20, 60, 60), text("Depth"), channel("PosModDep"),range(0, 0.50, 0.25), TrackerColour("Silver"), textcolour("white"), colour("white"), outlinecolour(100,100,100)
rslider bounds(630, 20, 60, 60), text("Rate"), channel("PosModRte"),range(0.01, 50.00, 3,0.5,0.01), TrackerColour("Silver"), textcolour("white"), colour("white"), outlinecolour(100,100,100)
}
; bow pressure
image bounds( 0,180,700, 90), colour(50,50,100), outlinecolour("LightGrey"), outlinethickness(1), shape("sharp"), plant("bowpressure"){
label bounds( 5, 5,690, 12), text("Bowing Pressure"), fontcolour(white)
hslider bounds( 10, 30,505, 30), text("Manual"), channel("bowpres"), range(0, 1, 0.45), TrackerColour("Silver"), textcolour("white"), colour("white")
rslider bounds(510, 20, 60, 60), text("Velocity"), channel("BowPresVel"),range(0, 1.00, 0), TrackerColour("Silver"), textcolour("white"), colour("white"), outlinecolour(100,100,100)
line bounds(580, 8,100, 2), colour("grey")
label bounds(595, 5, 72, 10), text("MODULATION"), colour(50,50,100), fontcolour("white")
rslider bounds(570, 20, 60, 60), text("Depth"), channel("BowPresDep"),range(0, 0.50, 0.25), TrackerColour("Silver"), textcolour("white"), colour("white"), outlinecolour(100,100,100)
rslider bounds(630, 20, 60, 60), text("Rate"), channel("BowPresRte"),range(0.01, 50.00, 3.5,0.5,0.01), TrackerColour("Silver"), textcolour("white"), colour("white"), outlinecolour(100,100,100)
}
; system
image bounds( 0,270,700, 90), colour(50,50,100), outlinecolour("LightGrey"), outlinethickness(1), shape("sharp"), plant("system"){
label bounds( 5, 5,690, 12), text("System"), fontcolour(white)
hslider bounds( 10, 20,685, 30), text("F.back"), channel("gain"), range(0, 1.00, 0.95), TrackerColour("Silver"), textcolour("white"), colour("white")
hslider bounds( 10, 50,685, 30), text("Discord"), channel("const"), range(0, 1.50, 0.97), TrackerColour("Silver"), textcolour("white"), colour("white")
}
keyboard pos( 0, 360), size(700, 80)
-dm0 -n -+rtmidi=NULL -M0
sr = 44100
ksmps = 32
nchnls = 2
;0dbfs = 1
gasendL,gasendR init 0
/* MAPPING TO SCALE AMPLITUDES ACCORDING TO BOW PRESSURE (HIGHER BOW PRESSURES DEMAND AMPLITUDE ATTENUATIONS) */
giPresScale ftgen 0, 0, 128*4, 16, 1, 78*4, 0, 1, 50*4, -1, 0.01
/* UDO TO CONTAIN EXPLOSIONS IN AMPLITUDE */
opcode AmpLimit,a,aiii
asig,imax,iatt,irel xin
krms init 0
kGainCtrl init 1
if krms>imax then
kGainCtrl limit kGainCtrl - iatt, 0, 1
else
kGainCtrl limit kGainCtrl + irel, 0, 1
endif
asig = asig * kGainCtrl
krms rms asig
xout asig
endop
instr 1 ; WGBOWEDBAR INSTRUMENT
kporttime linseg 0,0.001,0.05 ; portamento time used to smooth value changes from widgets
gkamp chnget "amp"
gkvel chnget "vel"
/* BOW POSITION */
gkpos chnget "pos" ; bow position
kpos portk gkpos, kporttime
gkPosModDep chnget "PosModDep"
gkPosModRte chnget "PosModRte"
if gkPosModDep>0 then ; if modulation depth greater than zero...
kPosMod rspline -gkPosModDep,gkPosModDep,gkPosModRte*0.5,gkPosModRte
kpos limit kpos + kPosMod, 0, 1
endif
/* BOW PRESSURE */
gkbowpres chnget "bowpres"
kbowpres portk gkbowpres, kporttime
gkBowPresDep chnget "BowPresDep"
gkBowPresRte chnget "BowPresRte"
if gkBowPresDep>0 then ; if modulation depth greater than zero...
kBowPresMod rspline -gkBowPresDep,gkBowPresDep,gkBowPresRte*0.5,gkBowPresRte
kbowpres limit kbowpres + kBowPresMod, 0, 1
endif
iBowPresVel chnget "BowPresVel" ; velocity influence of
iVelPres ampmidi iBowPresVel ; velocity to bow pressure
kbowpres limit kbowpres + iVelPres, 0, 1 ; limit to prevent out of range values that could result from the combination of manual, random and velocity control of bow pressure
kBowPresScale tablei kbowpres,giPresScale,1 ; read pressure amplitude scale value from table (n.b. higher bow pressure values demand amplitude scaling)
kBowPresScale portk kBowPresScale, kporttime ; smooth changes in bow pressure amplitude scaling
kbowpres scale kbowpres, 0.2, 20.00 ; remap bow pressure value from 0 - 1 to 0.2 - 20
gkAEnv chnget "AEnv" ; amount of envelope influence. If this is zero, 'Att.Tim.', 'Dec.Tim' 'Sus.Lev." and 'Rel.Tim.' will have no influence
gkAAttTim chnget "AAttTim"
gkADecTim chnget "ADecTim"
gkASusLev chnget "ASusLev"
gkARelTim chnget "ARelTim"
gkRvbSend chnget "RvbSend"
gkRvbSize chnget "RvbSize"
gkwidth chnget "width"
gkamp portk gkamp, kporttime
/* AMPLITUDE ENVELOPE */
if i(gkAAttTim)>0 then ; if zero attack time, skip attack stage in envelope
kAmpEnv linsegr 0,i(gkAAttTim),1,i(gkADecTim),i(gkASusLev),i(gkARelTim),0
else
kAmpEnv linsegr 1,i(gkADecTim),i(gkASusLev),i(gkARelTim),0 ; with attack stage
endif
kAmpEnv ntrpol 1,kAmpEnv,gkAEnv ; mix of envelope influence: 0=no_envelope_influence 1=full_envelope_influence
aAmpEnv interp kAmpEnv
gkamp = gkamp * aAmpEnv ; scale manual amplitude control with envelope
icps cpsmidi ; READ MIDI PITCH VALUES - THIS VALUE CAN BE MAPPED TO GRAIN DENSITY AND/OR PITCH DEPENDING ON THE SETTING OF THE MIDI MAPPING SWITCHES
ivel veloc 0,1 ; READ NOTE VELOCITY. WILL BE WITHIN THE RANGE 0 AND 1
iamp ampmidi i(gkvel)*(-4)
gkamp scale gkamp,0,4
kamp limit iamp + gkamp, 0,10
gkgain chnget "gain" ; called 'feedback' in the GUI
gkconst chnget "const" ; called 'Discord' in the GUI
kSwitch changed gkconst
if kSwitch=1 then ;IF I-RATE VARIABLE CHANGE TRIGGER IS '1'...
reinit UPDATE ;BEGIN A REINITIALISATION PASS FROM LABEL 'UPDATE'
endif
UPDATE:
abowedbar wgbowedbar kamp, icps, kpos, kbowpres, gkgain, i(gkconst), 0, 0, 20
rireturn ;RETURN FROM REINITIALISATION PASS TO PERFORMANCE TIME PASSES
/* OUTPUT LEVEL CONTROL */
gkOutGain chnget "OutGain" ; called 'Level' in the GUI. Controls output level.
aenv linsegr 1, i(gkARelTim), 0 ;ANTI-CLICK ENVELOPE
abowedbar = abowedbar * gkOutGain * aenv * kBowPresScale
/* CALL THE AmpLimit UDO */
; INPUT | AMP_LIMIT | ATTACK | RELEASE
abowedbar AmpLimit abowedbar, 0.9*0dbfs, 0.01, 0.01
/* STEREO WIDENING */
if gkwidth>0 then
kRndDelL rspline 0, 0.01*gkwidth, 0.4, 0.8
kRndDelR rspline 0, 0.01*gkwidth, 0.4, 0.8
kRndDelL limit kRndDelL, 0, 0.01
kRndDelR limit kRndDelR, 0, 0.01
aRndDelL interp kRndDelL
aRndDelR interp kRndDelR
aL vdelay abowedbar, 0.1+(aRndDelL*1000), 0.1 + 10
aR vdelay abowedbar, 0.1+(aRndDelR*1000), 0.1 + 10
gasendL = gasendL + (aL * gkRvbSend)
gasendR = gasendR + (aR * gkRvbSend)
outs aL, aR
else ; WIDTH CONTROL IS ZERO (NO STEREO EFFECT)
gasendL = gasendL + (abowedbar * gkRvbSend)
gasendR = gasendR + (abowedbar * gkRvbSend)
outs abowedbar, abowedbar
endif
endin
instr 99
aL,aR reverbsc gasendL,gasendR,gkRvbSize,4000
outs aL,aR
clear gasendL,gasendR
endin
i 1 0 0.1 ; INITIALISES THE ALGORITHM (OTHERWISE THE FIRST NOTE PLAYED DOESN'T SOUND)
i 99 0 3600 ; REVERB