You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

321 lines
19KB

  1. Clavinet.csd - an emulation of the Hohner Clavinet D6
  2. -----------------------------------------------------
  3. Pickup Selection
  4. ----------------
  5. CA - neck pickup only (pickup A)
  6. CB - bridge pickup only (pickup B)
  7. DA - both pickups in phase
  8. DB - bridge pickup (pickup B) 180 degrees out of phase w.r.t the neck pickup
  9. Setup
  10. -----
  11. Pick A - position of the first pickup (range 0 - 1). Typically referred to as the 'neck' pickup
  12. Pick B - position of the second pickup (range 0 - 1). Typically referred to as the 'bridge' pickup
  13. (NB. the relevant pickup has to be 'active' according to the CD AB switches in order for you to be able to here changes to it pickup position.)
  14. Mod.A - the pickup position can also modulated by an LFO. This control controls the depth of this modulation
  15. Mod.B - Depth of this modulation for the second pickup
  16. Rate A - Rate of modulation for the first pickup
  17. Rate B - Rate of modulation for the second pickup
  18. Env.A - The pickup position can be modulated by a simple single segment envelope. This is typically used to add an particualar attack nuance to the sound. This control controls the initial amplitude of this envelope (can be positive or negative). The envelope always ends at zero.
  19. Env.B - Envelope amplitude for the second pickup.
  20. Time A - Duration of the envelope segment for the first pickup
  21. Time B - Duration of the envelope segment for the second pickup
  22. Pluck - location of the 'pluck' (range 0 - 1). Should be close to zero for a typical clavinet behaviour
  23. Damp - string vibration damping that is applied while a note is being held. String damping is also dependent upon the note played using a 'key tracking' function table 'girefl'. In general lower notes should experience greater damping.
  24. HPF - this controls the cutoff frequency of a highpass filter that the signal passes through.
  25. The value supplied here is multiplied by the fundemental frequency of the note played to derive the cutoff frequency.
  26. Therefore if a value of '2' is supplied the cutoff will always by twice the fundemental, i.e. the frequency of the first harmonic/second partial.
  27. This control can be used to remove the emphasis of the fundemental partial.
  28. If this control is at its minimum setting the filter is bypassed.
  29. LPF - behaves in a similar way to HPF but in respect to a lowpass filter. This control, if reduced, can be used to soften the brightness of a note's attack.
  30. If this control is at its maximum setting the filter is bypassed.
  31. Inharm - applies inharmonicity to the spectrum produced by repluck. Negative values compress the spectrum, positive values expand the spectrum and zero leaves the spectrum unaffected.
  32. Release
  33. -------
  34. * Poorly maintained clavinets exhibit a release 'pluck' as the rubber pad which strikes and frets is lifted from the string when the key is released. The is on account of the rubber pad wearing out.
  35. Ampl - amplitude of the release 'pluck'
  36. Tone - a tone control applied to the release 'pluck' (this will also affect amplitude)
  37. D.Time - time it takes for full damping to be applied (this control has a subtle effect)
  38. Damp - amount of damping that is applied to string vibrations whenever a key is
  39. released (this amount of damping is achieved after 'D.Time' seconds). Note that the 'Damp'
  40. control in the 'Setup' pop-up panel also has an impact upon the release damping.
  41. A.Time - amplitude release time. If this is too short, vibration damping may not be heard and the above controls may not appear to do anything
  42. Filters
  43. -------
  44. The D6 Clavinet design incorporates four bandpass filters which can be switched in or out of the circuit.
  45. Emphasising four different frequency bands from high to low they are named 'brilliant', 'treble', 'medium' and 'soft'
  46. Cutoff frequencies (fco), levels and Q values for each of the four filters can be adjusted.
  47. Obviously the relevant filter has to be activated in order to be able to hear changes made to its settings.
  48. The four filters are in a parallel arrangement as opposed to being in series.
  49. <Cabbage>
  50. form caption("Clavinet"), size(550, 195), pluginID("clav"), colour(228,156,28)
  51. snapshot bounds(260, 46,200, 25), master(1), items("Clavinet 1", "Clavinet 2", "Clavinet 3", "Clavinet 4", "Clavinet 5", "Clavinet 6", "Clavinet 7", "Clavinet 8", "Clavinet 9", "Clavinet 10")
  52. ; filter switches
  53. checkbox bounds( 10, 5, 70, 15), text("Brilliant") channel("brilliant"), FontColour(50,50,50), colour("lime")
  54. checkbox bounds( 10, 25, 70, 15), text("Treble") channel("treble"), FontColour(50,50,50), colour("lime"), value(1)
  55. checkbox bounds( 10, 45, 70, 15), text("Medium") channel("medium"), FontColour(50,50,50), colour("lime")
  56. checkbox bounds( 10, 65, 70, 15), text("Soft") channel("soft"), FontColour(50,50,50), colour("lime")
  57. ; pickup configuration switches
  58. checkbox bounds( 80, 5, 70, 15), text("C/D") channel("C_D"), FontColour(50,50,50), colour("lime"), value(1)
  59. checkbox bounds( 80, 25, 70, 15), text("A/B") channel("A_B"), FontColour(50,50,50), colour("lime"), value(1)
  60. ; controls pertaining to the setup of the instrument (pickup positions, pluck position, damping etc.) accessed in a pop-up panel
  61. groupbox bounds(150, 8, 172, 305), colour(228,156,28), plant("Setup), line(0), popup(1)
  62. {
  63. rslider bounds( 5, 8, 55, 55), text("Pick A"), colour(195,126, 0), FontColour(50,50,50), channel("pickA"), range(0, 1.00, 0.25, 1, 0.001)
  64. rslider bounds( 55, 8, 55, 55), text("Pick B"), colour(195,126, 0), FontColour(50,50,50), channel("pickB"), range(0, 1.00, 0.07, 1, 0.001)
  65. rslider bounds( 5, 68, 55, 55), text("Mod A"), colour(225,156, 28), FontColour(50,50,50), channel("ModA"), range(0,0.50, 0.03, 0.5, 0.001)
  66. rslider bounds( 55, 68, 55, 55), text("Mod B"), colour(225,156, 28), FontColour(50,50,50), channel("ModB"), range(0,0.50, 0.03, 0.5, 0.001)
  67. rslider bounds( 5,128, 55, 55), text("Rate A"), colour(255,186, 58), FontColour(50,50,50), channel("RateA"), range(0,14.00, 0.2, 0.5, 0.001)
  68. rslider bounds( 55,128, 55, 55), text("Rate B"), colour(255,186, 58), FontColour(50,50,50), channel("RateB"), range(0,14.00, 0.15, 0.5, 0.001)
  69. rslider bounds( 5,188, 55, 55), text("Env.A"), colour(255,216, 88), FontColour(50,50,50), channel("EnvA"), range(-1, 1.00, 0)
  70. rslider bounds( 55,188, 55, 55), text("Env.B"), colour(255,216, 88), FontColour(50,50,50), channel("EnvB"), range(-1, 1.00, 0)
  71. rslider bounds( 5,248, 55, 55), text("Time A"), colour(255,246,118), FontColour(50,50,50), channel("TimeA"), range(0, 1.00, 0.05, 0.5, 0.001)
  72. rslider bounds( 55,248, 55, 55), text("Time B"), colour(255,246,118), FontColour(50,50,50), channel("TimeB"), range(0, 1.00, 0.05, 0.5, 0.001)
  73. line bounds(110, 25, 1, 260), colour( 50, 50, 50)
  74. rslider bounds(112, 8, 55, 55), text("Pluck"), colour(195,126, 0), FontColour(50,50,50), channel("plk"), range(0, 1.00, 0.005, 0.5, 0.0001)
  75. rslider bounds(112, 68, 55, 55), text("Damp"), colour(225,156, 28), FontColour(50,50,50), channel("SusDamp"), range(-1.00, 1.00, 0)
  76. rslider bounds(112,128, 55, 55), text("HPF"), colour(255,186, 58), FontColour(50,50,50), channel("HPF"), range(0,16.0, 0)
  77. rslider bounds(112,188, 55, 55), text("LPF"), colour(255,216, 88), FontColour(50,50,50), channel("LPF"), range(1.0,72, 72, 0.375, 0.0001)
  78. rslider bounds(112,248, 55, 55), text("Inharm."),colour(255,216, 88), FontColour(50,50,50), channel("inharm"), range(-0.99,0.99, 0)
  79. }
  80. ; controls pertaining to the release stage of a note accessed in a pop-up panel
  81. groupbox bounds(260, 8, 265, 65), colour(228,156,28), plant("Release"), line(0), popup(1)
  82. {
  83. rslider bounds( 5, 8, 55, 55), text("Ampl."), colour(255,186,58), FontColour(50,50,50), channel("RelAmpl"), range(0, 20.00, 2)
  84. rslider bounds( 55, 8, 55, 55), text("Tone"), colour(255,186,58), FontColour(50,50,50), channel("RelTone"), range(100, 8000, 1000)
  85. rslider bounds(105, 8, 55, 55), text("D.Time"), colour(255,186,58), FontColour(50,50,50), channel("RelDTime"), range(0.001, 1, 0.01, 0.5, 0.001)
  86. rslider bounds(155, 8, 55, 55), text("Damp"), colour(255,186,58), FontColour(50,50,50), channel("RelDamp"), range(0.10, 0.99, 0.95)
  87. rslider bounds(205, 8, 55, 55), text("A.Time"), colour(255,186,58), FontColour(50,50,50), channel("RelATime"), range(0.01,20, 0.05, 0.5, 0.01)
  88. }
  89. ; controls pertaining to the setup of the instrument's bandpass filters accessed in a pop-up panel
  90. groupbox bounds(150, 46, 230, 195), colour(228,156,28), plant("Filters"), line(0), popup(1)
  91. {
  92. label bounds( 10, 5, 60, 12), text("Brilliant"), colour("white"), FontColour(50,50,50)
  93. label bounds( 69, 5, 60, 12), text("Treble"), colour("white"), FontColour(50,50,50)
  94. label bounds(121, 5, 60, 12), text("Medium"), colour("white"), FontColour(50,50,50)
  95. label bounds(185, 5, 60, 12), text("Soft"), colour("white"), FontColour(50,50,50)
  96. checkbox bounds( 26, 18, 10, 10), channel("brilliant"), colour("lime"), value(0), shape("ellipse")
  97. checkbox bounds( 81, 18, 10, 10), channel("treble"), colour("lime"), value(0), shape("ellipse")
  98. checkbox bounds(136, 18, 10, 10), channel("medium"), colour("lime"), value(0), shape("ellipse")
  99. checkbox bounds(191, 18, 10, 10), channel("soft"), colour("lime"), value(0), shape("ellipse")
  100. rslider bounds( 5, 30, 55, 55), channel("fco1"), text("fco.1"), colour(235,166,38), FontColour(50,50,50), range(50,5000,2500,0.5)
  101. rslider bounds( 60, 30, 55, 55), channel("fco2"), text("fco.2"), colour(235,166,38), FontColour(50,50,50), range(50,5000,1000,0.5)
  102. rslider bounds(115, 30, 55, 55), channel("fco3"), text("fco.3"), colour(235,166,38), FontColour(50,50,50), range(50,5000, 500,0.5)
  103. rslider bounds(170, 30, 55, 55), channel("fco4"), text("fco.4"), colour(235,166,38), FontColour(50,50,50), range(50,5000, 200,0.5)
  104. rslider bounds( 5, 85, 55, 55), channel("gain1"), text("Gain 1"), colour(255,216,88), FontColour(50,50,50), range(0.50,30, 3,0.5)
  105. rslider bounds( 60, 85, 55, 55), channel("gain2"), text("Gain 2"), colour(255,216,88), FontColour(50,50,50), range(0.50,30,2.3,0.5)
  106. rslider bounds(115, 85, 55, 55), channel("gain3"), text("Gain 3"), colour(255,216,88), FontColour(50,50,50), range(0.50,30,1.3,0.5)
  107. rslider bounds(170, 85, 55, 55), channel("gain4"), text("Gain 4"), colour(255,216,88), FontColour(50,50,50), range(0.50,30,1.4,0.5)
  108. rslider bounds( 5,140, 55, 55), channel("Q1"), text("Q 1"), colour(255,255,138), FontColour(50,50,50), range(0.50,30,1.25,0.5)
  109. rslider bounds( 60,140, 55, 55), channel("Q2"), text("Q 2"), colour(255,255,138), FontColour(50,50,50), range(0.50,30,1 ,0.5)
  110. rslider bounds(115,140, 55, 55), channel("Q3"), text("Q 3"), colour(255,255,138), FontColour(50,50,50), range(0.50,30,1 ,0.5)
  111. rslider bounds(170,140, 55, 55), channel("Q4"), text("Q 4"), colour(255,255,138), FontColour(50,50,50), range(0.50,30,2 ,0.5)
  112. line bounds( 59, 25, 1, 150), colour(50,50,50)
  113. line bounds(114, 25, 1, 150), colour(50,50,50)
  114. line bounds(169, 25, 1, 150), colour(50,50,50)
  115. }
  116. rslider bounds(470, 5, 75, 75), text("Level"), colour(255,186,58), FontColour(50,50,50), channel("level"), range(0, 8.00, 0.5, 0.5)
  117. keyboard bounds(10, 85, 530,80)
  118. image bounds(5, 170, 420, 20), colour(75, 85, 90, 50), plant("credit"){
  119. label bounds(0.03, 0.1, .6, .7), text("Author: Iain McCurdy |2013|"), colour("white"), FontColour(50,50,50)
  120. }
  121. </Cabbage>
  122. <CsoundSynthesizer>
  123. <CsOptions>
  124. -dm0 -n -+rtmidi=null -M0
  125. </CsOptions>
  126. <CsInstruments>
  127. sr = 44100
  128. ksmps = 16
  129. nchnls = 2
  130. 0dbfs = 1
  131. ; table used to map of note played to bridge relection
  132. girefl ftgen 0,0,128,-27, 0,0.4, 36,0.4, 72,0.01, 127,0.01
  133. gisine ftgen 0,0,4096,10,1
  134. gitri ftgen 0,0,4096,7,0,1024,1,2046,-1,1024,0
  135. opcode FreqShifter,a,aki
  136. ain,kfshift,ifn xin ;READ IN INPUT ARGUMENTS
  137. areal, aimag hilbert ain ;HILBERT OPCODE OUTPUTS TWO PHASE SHIFTED SIGNALS, EACH 90 OUT OF PHASE WITH EACH OTHER
  138. asin oscili 1, kfshift, ifn, 0
  139. acos oscili 1, kfshift, ifn, 0.25
  140. ;RING MODULATE EACH SIGNAL USING THE QUADRATURE OSCILLATORS AS MODULATORS
  141. amod1 = areal * acos
  142. amod2 = aimag * asin
  143. ;UPSHIFTING OUTPUT
  144. aFS = (amod1 - amod2)
  145. xout aFS ;SEND AUDIO BACK TO CALLER INSTRUMENT
  146. endop
  147. instr 1
  148. ibrilliant chnget "brilliant" ; filter switch
  149. itreble chnget "treble" ; filter switch
  150. imedium chnget "medium" ; filter switch
  151. isoft chnget "soft" ; filter switch
  152. iC_D chnget "C_D" ; single/dual pickup selector
  153. iA_B chnget "A_B" ; neck/bridge pickup selector
  154. gklevel chnget "level" ; output volume control
  155. icps cpsmidi ; cps read from midi
  156. inum notnum ; note number read from midi
  157. ivel veloc 0,1 ; velocity read from midi
  158. ; pluck position is an i-rate variable so a mechanism is created to re-initialise the instrument if it is changed in realtime
  159. kplk chnget "plk" ; pluck position
  160. ktrig changed kplk ; if GUI knob changes, generate a trigger
  161. if ktrig==1 then ; if triggered...
  162. reinit UPDATE ; reinitialise...
  163. endif
  164. UPDATE: ; ...from here (until the end of the instrument)
  165. iplk = i(kplk) ; cast k-rate pluck position to i-rate variable
  166. ; pickup positions
  167. kpickA chnget "pickA" ; neck pickup position
  168. kpickB chnget "pickB" ; bridge pickup position
  169. ; string vibration damping / reflectivity
  170. irefl table inum,girefl ; read reflectivity for this note from function table (lower notes will experience more damping)
  171. iRelDTime chnget "RelDTime" ; release damping time: time for damping state to be established
  172. iRelDamp chnget "RelDamp" ; amount of damping upon release
  173. krefl linsegr irefl,iRelDTime,iRelDamp ; upon note release vibrations are damped quickly and dramatically
  174. kSusDamp chnget "SusDamp" ; user controlled modulation of string vibration damping
  175. krefl limit krefl+kSusDamp,0.001,0.999 ; consolidate reflection/damping value and limit possible values to prevent out of range values
  176. iamp = ivel*0.3
  177. kenv expseg 1, 0.01,0.001,1,0.001 ; create an amplitude envelope for the noise burst
  178. axcite pinkish kenv-0.001 ; create a pink noise signal
  179. axcite tone axcite,icps*2
  180. krelease release ; sense release of note
  181. iRelAmpl chnget "RelAmpl" ; release pluck amplitude
  182. iRelTone chnget "RelTone" ; tone of the release pluck
  183. if krelease==1 then ; if key is released...
  184. axcite mpulse iRelAmpl,0 ; audio impulse is created as an implementation of the release pluck impulse
  185. axcite butlp axcite,iRelTone ; lowpass filter the impulse
  186. endif
  187. kModA chnget "ModA" ; pickup position modulation depth
  188. kModB chnget "ModB"
  189. kRateA chnget "RateA" ; pickup position modulation rate
  190. kRateB chnget "RateB"
  191. iEnvA chnget "EnvA" ; pickup position envelope modulation depth
  192. iEnvB chnget "EnvB"
  193. iTimeA chnget "TimeA" ; pickup position envelope modulation time
  194. iTimeB chnget "TimeB"
  195. kenv1 transeg iEnvA,iTimeA,-4,0 ; envelope applied to the pickup position (pickup A)
  196. kenv2 transeg iEnvB,iTimeB,-4,0 ; envelope applied to the pickup position (pickup B)
  197. kmod1 oscili kModA,kRateA,gitri ; lfo used to modulate pickup position (pickup A)
  198. kmod2 oscili kModB,kRateB,gitri ; lfo used to modulate pickup position (pickup B)
  199. kpickA limit kpickA + kmod1 + kenv1, 0, 1 ; consolidate pickup position between fixed value, lfo and envelope. Also protect against out of range values. (pickup A)
  200. kpickB limit kpickB + kmod2 + kenv2, 0, 1 ; consolidate pickup position between fixed value, lfo and envelope. Also protect against out of range values. (pickup B)
  201. iinharm chnget "inharm" ; inharmonicity of the tone. negative values compress the spectrum, positive values expand it. Compensation will be applied to the fundemental so that it will remain consistent.
  202. iFShift = icps*iinharm ; amount of frequency shift (in CPS)
  203. a1 repluck iplk, iamp, icps-iFShift, kpickA, krefl, axcite ; employ plucked string model (pickup A)
  204. a2 repluck iplk, iamp, icps-iFShift, kpickB, krefl, axcite ; employ plucked string model (pickup B)
  205. if(iinharm!=0) then ; only apply frequency shifting if inharmonicity is anything other than zero
  206. a1 FreqShifter a1,iFShift,gisine ; call frequency shifting UDO
  207. a2 FreqShifter a2,iFShift,gisine
  208. endif
  209. if(iC_D==0&&iA_B==0) then ;CA - neck pickup only
  210. asig = a1
  211. elseif(iC_D==0&&iA_B==1) then ;CB - bridge pickup only
  212. asig = a2
  213. elseif(iC_D==1&&iA_B==0) then ;DA - both pickups in phase
  214. asig = a1 + a2
  215. elseif(iC_D==1&&iA_B==1) then ;DB - both pickups. Pickup B 180 degrees out of phase
  216. asig = a1 - a2
  217. endif
  218. ; velocity to brightness
  219. icf = (ivel*6)+8 ; cutoff frequency in 'oct' format
  220. asig butlp asig,cpsoct(icf) ; lowpass filter audio signal
  221. ; filter switches
  222. kfco1 chnget "fco1" ; filter cutoffs
  223. kfco2 chnget "fco2"
  224. kfco3 chnget "fco3"
  225. kfco4 chnget "fco4"
  226. kQ1 chnget "Q1" ; filter q's
  227. kQ2 chnget "Q2"
  228. kQ3 chnget "Q3"
  229. kQ4 chnget "Q4"
  230. kgain1 chnget "gain1" ; filter gains
  231. kgain2 chnget "gain2"
  232. kgain3 chnget "gain3"
  233. kgain4 chnget "gain4"
  234. ; filters
  235. amix = 0 ; audio mix of filter outputs (reset to silence upon each iteration)
  236. if(ibrilliant==1) then ; if 'brilliant' selected...
  237. afilt rbjeq asig, kfco1, 1, kQ1, 1, 4 ; bandpass filter sound
  238. amix = amix + (afilt * kgain1) ; add a scaled amount of filtered signal to filter mix signal
  239. endif
  240. if(itreble==1) then ; if 'treble' selected...
  241. afilt rbjeq asig, kfco2, 1, kQ2, 1, 4 ; bandpass filter sound
  242. amix = amix + (afilt * kgain2) ; add a scaled amount of filtered signal to filter mix signal
  243. endif
  244. if(imedium==1) then ; if 'medium' selected...
  245. afilt rbjeq asig, kfco3, 1, kQ3, 1, 4 ; bandpass filter sound
  246. amix = amix + (afilt * kgain3) ; add a scaled amount of filtered signal to filter mix signal
  247. endif
  248. if(isoft==1) then ; if 'soft' selected...
  249. afilt rbjeq asig, kfco4, 1, kQ4, 1, 4 ; bandpass filter sound
  250. amix = amix + (afilt * kgain4) ; add a scaled amount of filtered signal to filter mix signal
  251. endif
  252. if((ibrilliant + itreble + imedium + isoft)==0) then ; if no filters selected...
  253. amix = asig ; ...just send unfiltered audio to filter section output
  254. endif
  255. ; key following highpass filter
  256. kHPF chnget "HPF" ; highpass filter multiple
  257. if kHPF>0 then ; if HPF control is greater than 1...
  258. kcf limit icps*kHPF,20,sr/2 ; prevent out of range values which would cause the filter to 'blow up'
  259. amix buthp amix,kcf ; filter tone relative to note fundemental
  260. endif
  261. ; key following lowpass filter
  262. kLPF chnget "LPF" ; lowpass filter multiple
  263. if kLPF<72 then ; if LPF control is greater than 1...
  264. kcf limit icps*kLPF,20,sr/2 ; prevent out of range values which would cause the filter to 'blow up'
  265. amix butlp amix,kcf ; filter tone relative to note fundemental
  266. endif
  267. ; release envelope
  268. iRelATime chnget "RelATime" ; amplitude release time
  269. aenv linsegr 1, iRelATime, 0 ; amplitude release envelope (senses key release before entering final/only segment)
  270. ; output signal
  271. aout = amix * aenv * gklevel ; apply release envelope and level control
  272. outs aout, aout ; send audio to outputs
  273. endin
  274. </CsInstruments>
  275. <CsScore>
  276. f 0 [60*60*24*7] ; keep performance going for up to a week
  277. </CsScore>
  278. </CsoundSynthesizer>