Extra "ports" of juce-based plugins using the distrho build system
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.

339 lines
17KB

  1. LiveSndwarp.csd
  2. Iain McCurdy (2012)
  3. Description and Instructions
  4. ----------------------------
  5. This instrument implements live granulation of an audio input stream using the sndwarp opcode.
  6. Live audio from the first input channel (left input if stereo) is written into a function table from which sndwarp reads
  7. audio. (If 'stereo in/out' is chosen from 'In/Out Mode' then audio from the second/right channel is written into a second
  8. table.) The key is that manual pointer read mode is used with sndwarp (as opposed to time-stretch mode) and that the read
  9. pointer follows on behind the pointer which is used to write audio into the function table(s). Some care is needed to ensure
  10. that the read pointer does not 'overtake' the write pointer (which would result in dicontinuities in the audio it reads).
  11. This could be possible if pitch transposition upwards of grains is used as the grain pointer is then moving faster than the
  12. write pointer. This example prevents this from happening internally so the user does not need to worry. The user can also
  13. define a random offset for the grain read pointer using the 'Grain Delay' settings. Delay times are randomly chosen
  14. according to a 'betarand' distribution the 'beta' of which the user can set: if distribution shape is 1 the distribution is
  15. uniform, if it is 2 the distribution is linear and beyond 2 it is increasingly exponential.
  16. Note that 'Size' (grain size) and 'Size Rnd.' (random grain size) are i-rate variables so that changing them requires
  17. reinitialisation in the orchestra. For this reason discontinuity in the audio output can be heard when they are modified.
  18. Grain Size and Size Random (bandwith) are in sample frames. Divide by sample rate to derive a value in seconds.
  19. Pitch transposition can be set using either the 'Pitch' knob (ratio multiplier) or 'Semis' (transposition in semitones).
  20. Changes made to 'Semis' will be reflected in the setting of the 'Pitch' knob, but not vice versa.
  21. Pitch can also be controlled through MIDI input (in which case 'Pitch' and 'Semis' will be ignored). Using MIDI will
  22. polyphony will be possible. If you intend to use MIDI to start and stop sndwarp instances, turn 'On/Off [MIDI]' off.
  23. You can also adjust the MIDI note at which unison (no transposition) will occur using the 'Uni.Note' knob.
  24. Sound output from sndwarp can be fed back into the input to be mixed with the live audio in. The amount of feedback can be
  25. controlled using the 'Feedback' slider. Using high levels of feedback can result in overloading but this will also be
  26. dependent upon other factors such as random delay time, grain size (window size), density and transposition so user caution
  27. is advised. If the 'clip' button is activated the feedback signal will be clipped at the clip level set (a ratio of then
  28. maximum amplitude) providing at least some control over a runaway feedback loop. Note that 'Clip Lev.' defines the amplitude
  29. at which clipping begins, therefore lower settings will result in the signal being clipped sooner. The feedback signal can
  30. also be filtered by a lowpass filter.
  31. If 'balance' is activated the output of sndwarp is dynamically balanced with the input signal. This can be useful for
  32. compensating for increases in amplitude caused when 'Number of Overlaps' (grain density) is increased. There are 3
  33. mono/stereo modes: 'mono in - mono out (x2)', 'mono in - stereo out' (stereo effect is created using sndwarp's built-in
  34. window/grain size randomisation, and 'stereo in - stereo out' mode.
  35. The buffer size used in the example is just under 23 seconds long (function table size 1048576 at sr=44100). This could be
  36. enlarged if required but bear in mind that sndwarp needs a power of two table size.
  37. Activating 'Freeze' will pause writing of live audio to the function table and allow the user to manually navigate through
  38. the buffered audio. The feedback loop will also be deactivated when 'freeze' is active.
  39. <Cabbage>
  40. form caption("Live Sndwarp") size(530, 465), pluginID("lwrp")
  41. groupbox bounds( 0, 0, 300,100), text("Master"), colour(30, 30, 40), fontcolour(255,125,125){
  42. checkbox bounds( 10, 28, 110, 20), colour("yellow"), channel("OnOff"), value(1), text("On/Off [MIDI]"), trackercolour("red")
  43. label bounds( 22, 53, 80, 13), text("In/Out Mode")
  44. combobox bounds( 10, 69, 100, 20), channel("monostereo"), value(2), text("mono","stereo out","stereo in/out")
  45. rslider bounds(115, 30, 60, 60), text("In Gain"), channel("InGain"), range(0, 2.00, 1, 0.5), trackercolour("red")
  46. rslider bounds(175, 30, 60, 60), text("Out Gain"), channel("amp"), range(0, 2.00, 1, 0.5), trackercolour("red")
  47. rslider bounds(235, 30, 60, 60), text("Mix"), channel("mix"), range(0, 1.00, 1), trackercolour("red")
  48. }
  49. groupbox bounds(300, 0, 230,100), text("Feedback - CAUTION!"), colour(25, 25, 35), fontcolour(250,120,120){
  50. rslider bounds(305, 30, 60, 60), text("Amount"), channel("feedback"), range(0, 1.00, 0), trackercolour("red")
  51. checkbox bounds(365, 35, 70, 20), colour("yellow"), channel("clip"), value(1), text("Clip"), trackercolour("red")
  52. checkbox bounds(365, 65, 70, 20), colour("yellow"), channel("LPF_On"), value(0), text("LPF"), trackercolour("red")
  53. rslider bounds(410, 30, 60, 60), text("Clip Lev."), channel("ClipLev"), range(0.01, 1, 0.5, 0.5), trackercolour("red")
  54. rslider bounds(465, 30, 60, 60), text("LPF"), channel("Cutoff"), range(20, 20000, 4000, 0.5), trackercolour("red")
  55. }
  56. groupbox bounds( 0,100, 530,100), text("Grains"), colour(35, 35, 45), fontcolour(255,130,130){
  57. rslider bounds( 5,130, 60, 60), text("Size"), channel("wsize"), range(1, 88200, 7000, 0.25), trackercolour("red")
  58. rslider bounds( 65,130, 60, 60), text("Size Rnd."), channel("rnd"), range(0, 30000, 1000, 0.375), trackercolour("red")
  59. rslider bounds(125,130, 60, 60), text("Pitch"), channel("pch"), range(0.01, 8, 1, 0.5), trackercolour("red")
  60. rslider bounds(185,130, 60, 60), text("Semis"), channel("semis"), range(-48, 48, 0,1,1), trackercolour("red")
  61. rslider bounds(245,130, 60, 60), text("Density"), channel("olaps"), range(1, 100, 10, 1, 1), trackercolour("red")
  62. label bounds(305,125, 100, 13), text("Grain Envelope")
  63. combobox bounds(305,141, 100, 20), channel("wfn"), value(1), text("Half Sine","Perc. 1","Perc. 2","Gate","Rev. Perc. 1 ","Rev. Perc. 2")
  64. checkbox bounds(315,170, 100, 20), colour("yellow"), channel("balance"), value(0), text("Balance")
  65. rslider bounds(405,130, 60, 60), text("Delay"), channel("dly"), range(0, 5, 0.01, 0.5), trackercolour("red")
  66. rslider bounds(465,130, 60, 60), text("Distr."), channel("beta"), range(1, 16.0, 1, 0.5), trackercolour("red")
  67. }
  68. groupbox bounds( 0,200,530,135), text("Freeze"), colour(45, 45, 55), fontcolour(255,100,100){
  69. label bounds(234,230, 80, 17), text("FREEZE"), fontcolour("LightBlue")
  70. label bounds(233,231, 80, 17), text("FREEZE"), fontcolour(105,105,255)
  71. checkbox bounds(225,249, 80, 30), colour(115,115,255), channel("freeze"), value(0)
  72. rslider bounds( 10,227, 60, 60), text("Port.Time"), channel("ManPtrPort"), range(0, 1.00, 0.5), trackercolour("red")
  73. hslider bounds( 10,280,510, 40), channel("ManPtr"), range(-1.00, 0, 0, 1, 0.001), trackercolour("red")
  74. label bounds(220,315,100, 13), text("Manual Pointer")
  75. }
  76. groupbox bounds( 0,335, 80,100), text("MIDI"), colour(30, 30, 40), fontcolour(255,100,100){
  77. rslider bounds( 10,365, 60, 60), text("Uni.Note"), channel("UniNote"), range(0, 127, 72,1,1), trackercolour("red")
  78. keyboard bounds( 80,335,450,100)
  79. }
  80. image bounds( 5, 440, 215, 20), colour(75, 85, 90, 100), plant("credit"), line(0){
  81. label bounds(0.03, 0.1, .9, .7), text("Author: Iain McCurdy |2012|"), colour("white")
  82. </Cabbage>
  83. <CsoundSynthesizer>
  84. <CsOptions>
  85. ;-d -n
  86. -dm0 -n -+rtmidi=null -M0
  87. </CsOptions>
  88. <CsInstruments>
  89. sr = 44100 ;SAMPLE RATE
  90. ksmps = 32 ;NUMBER OF AUDIO SAMPLES IN EACH CONTROL CYCLE
  91. nchnls = 2 ;NUMBER OF CHANNELS (2=STEREO)
  92. 0dbfs = 1
  93. massign 0,2
  94. gibuffer ftgen 0, 0, 1048576, 2, 0 ;Buffer table. Roughly 23 seconds duration.
  95. gibufferR ftgen 0, 0, 1048576, 2, 0 ;right channel
  96. ;GRAIN ENVELOPE WINDOW FUNCTION TABLES:
  97. giwfn1 ftgen 0, 0, 131072, 9, .5, 1, 0 ; HALF SINE
  98. giwfn2 ftgen 0, 0, 131072, 7, 0, 3072, 1, 128000, 0 ; PERCUSSIVE - STRAIGHT SEGMENTS
  99. giwfn3 ftgen 0, 0, 131072, 5, .001, 3072, 1, 128000, 0.001 ; PERCUSSIVE - EXPONENTIAL SEGMENTS
  100. giwfn4 ftgen 0, 0, 131072, 7, 0, 1536, 1, 128000, 1, 1536, 0 ; GATE - WITH ANTI-CLICK RAMP UP AND RAMP DOWN SEGMENTS
  101. giwfn5 ftgen 0, 0, 131072, 7, 0, 128000,1, 3072, 0 ; REVERSE PERCUSSIVE - STRAIGHT SEGMENTS
  102. giwfn6 ftgen 0, 0, 131072, 5, .001, 128000,1, 3072, 0.001 ; REVERSE PERCUSSIVE - EXPONENTIAL SEGMENTS
  103. instr 1
  104. gkOnOff chnget "OnOff"
  105. ktrigger trigger gkOnOff,0.5,0
  106. schedkwhen ktrigger,0,0,2,0,-1
  107. ginsamp = ftlen(gibuffer)-1 ;index of the final sample in the function table
  108. gkamp chnget "amp"
  109. gkInGain chnget "InGain"
  110. gkmix chnget "mix"
  111. gkbalance chnget "balance"
  112. gkmonostereo chnget "monostereo"
  113. gkfback chnget "feedback"
  114. gkclip chnget "clip"
  115. gkClipLev chnget "ClipLev"
  116. gkCutoff chnget "Cutoff"
  117. gkpch chnget "pch"
  118. gkLPF_On chnget "LPF_On"
  119. gkwsize chnget "wsize"
  120. gkrnd chnget "rnd"
  121. gkolap chnget "olaps"
  122. gkwfn chnget "wfn"
  123. gkdly chnget "dly"
  124. gkbeta chnget "beta"
  125. gkfreeze chnget "freeze"
  126. gkManPtrPort chnget "ManPtrPort"
  127. gkManPtr chnget "ManPtr"
  128. gkUniNote chnget "UniNote"
  129. ktrigger trigger gkfreeze,0.5,1 ;if 'freeze' switch is turned off...
  130. if ktrigger==1 then
  131. chnset 1-ktrigger,"ManPtr" ;reset Manual Pointer slider to its default (maximum) position
  132. endif
  133. ain inch 1 ;read audio input from the left input channel
  134. ain = ain*gkInGain ;scale input signal according to 'In Gain' control position
  135. outch 1,ain*(1-gkmix) ;send some dry signal to output according to dry/wet 'Mix' control position
  136. gaFBackSig,gaFBackSigR init 0 ;audio feedback signal (initialised for first performance iteration)
  137. /*dc offset filter feedback signal*/
  138. aFBackSig dcblock2 gaFBackSig ;filter dc offset from left channel feedback signal
  139. if gkmonostereo==3 then ;if 'stereo in' mode is active...
  140. aFBackSigR dcblock2 gaFBackSigR ;filter dc offset from right channel feedback signal
  141. endif
  142. /*lowpass filter feedback signal*/
  143. if gkLPF_On==1 then ;if lowpass filter button is on...
  144. aFBackSig tone aFBackSig,gkCutoff ;...filter left feedback channel
  145. if gkmonostereo==3 then ;if 'stereo in' mode is active...
  146. aFBackSigR tone aFBackSigR,gkCutoff ;lowpass filter the right channel
  147. endif
  148. endif
  149. /*clip feedback signal*/
  150. if gkclip==1 then ;if clip switch is on...
  151. ktrig changed gkClipLev ;if clip level control is adjusted generate a trigger impulse (momentary '1')
  152. if ktrig==1 then ;if a trigger impulse has been received...
  153. reinit UPDATE_CLIP_L ;reinitialise clip opcode (clip level is i-rate only)
  154. endif
  155. UPDATE_CLIP_L:
  156. aFBackSig clip aFBackSig, 0, 0dbfs*i(gkClipLev) ;clip left feedback signal at maximum amplitude using bram de jong method
  157. if gkmonostereo==3 then ;and if stereo in/out mode is also chosen
  158. aFBackSigR clip aFBackSigR, 0, 0dbfs*i(gkClipLev) ;clip right channel feedback signal
  159. rireturn
  160. endif
  161. endif
  162. gaphsW phasor (sr*(1-gkfreeze))/ginsamp ;pointer 0 - 1 ;create a moving phase value that will be used to point to locations in a function table where input audio signal will be written
  163. /*write audio from left input to function table*/
  164. if gkfreeze==0 then
  165. tablew ain+aFBackSig,gaphsW,gibuffer,1 ;write input audio to table
  166. endif
  167. /*if stereo in - stereo out mode*/
  168. if gkmonostereo==3 then ;if stereo in/out mode has been chosen...
  169. aR inch 2 ;read right channel audio input
  170. aR = aR*gkInGain ;rescale its amplitude with 'Input Gain' slider
  171. if gkfreeze==0 then
  172. tablew aR+aFBackSigR,gaphsW,gibufferR,1 ;write right channel audio input audio to table
  173. endif
  174. outch 2,aR*(1-gkmix) ;if 'stereo in' mode is selected, send some right channel dry signal to output according to dry/wet 'Mix' control position
  175. else
  176. outch 2,ain*(1-gkmix) ;otherwise not 'stereo in' mode so just send some left channel dry signal to output
  177. endif
  178. clear gaFBackSig,gaFBackSigR ;clear feedback signals
  179. endin
  180. instr 2
  181. iMIDIActiveValue = 1 ;IF MIDI ACTIVATED
  182. iMIDIflag = 0 ;IF FLTK ACTIVATED
  183. mididefault iMIDIActiveValue, iMIDIflag ;IF NOTE IS MIDI ACTIVATED REPLACE iMIDIflag WITH iMIDIActiveValue
  184. kMIDIflag init iMIDIflag
  185. if gkOnOff==0&&iMIDIflag==0 then
  186. turnoff
  187. endif
  188. if iMIDIflag==1 then
  189. icps cpsmidi
  190. kpch = icps/cpsmidinn(gkUniNote)
  191. else
  192. kpch = gkpch
  193. endif
  194. kporttime linseg 0,0.001,0.03 ;portamento time. Rises quickly from zero to a held value.
  195. kpch portk kpch,kporttime ;Apply portamento smoothing to changes made to the pitch multiplier
  196. apch interp kpch ;interpolate pitch multiplier variable to create an a-rate version. This will produce higher quality results when pitch is modulated.
  197. kManPtr portk gkManPtr,kporttime*10*gkfreeze*gkManPtrPort
  198. ktrig changed gkwsize,gkrnd,gkolap,gkwfn ;if any of the list of input args. change, generate a trigger impulse (momentary '1'). The input args are all i-rate in sndwarp so reinitialisation will be required for their changes to register.
  199. if ktrig==1 then ;if a trigger hass been generated...
  200. reinit UPDATE_SNDWARP ;... begin a reinitialisation pass from the given label
  201. endif
  202. UPDATE_SNDWARP: ;a label. Reinitialisation begins from here.
  203. imode = 1 ;sndwarp mode. (1=pointer mode, timestretch mode not so useful in a live audio in application)
  204. ibeg = 0 ;point in the function table from which to begin reading audio (0=beginning)
  205. iwsize = i(gkwsize) ;window (grain) size in samples
  206. irnd = i(gkrnd) ;window (grain) size randomisation bandwidth in samples
  207. iolap = i(gkolap) ;number of grain overlaps
  208. kRndDly betarand gkdly,1,gkbeta ;random grain delay time
  209. if gkmonostereo!=0 then
  210. kRndDlyR betarand gkdly,1,gkbeta ;random grain delay time
  211. endif
  212. iMaxDur = (iwsize+irnd)/sr ;maximum grain duration in seconds
  213. kTransComp limit iMaxDur*(kpch-1),0,ginsamp/sr
  214. kdelay = (kTransComp+kRndDly) / (ginsamp/sr) ;delay time required when reading grains from the function table
  215. if gkmonostereo!=0 then
  216. kdelayR = (kTransComp+kRndDlyR) / (ginsamp/sr) ;delay time required when reading grains from the function table
  217. endif
  218. if gkfreeze==1 then
  219. kdelay = kdelay + (sr/(ginsamp)*1.75*iwsize/sr) ;if freeze mode is active regress the read pointer a small amount
  220. if gkmonostereo!=0 then
  221. kdelayR = kdelayR + (sr/(ginsamp)*1.75*iwsize/sr) ;if freeze mode is active regress the read pointer a small amount
  222. endif
  223. endif
  224. aphsR wrap (gaphsW-kdelay+kManPtr)*(ginsamp/sr),0,(ginsamp-iwsize-irnd)/sr ;location from which to read grain. This is always directly related to the poistion of the write pointer.
  225. aphsR_R wrap (gaphsW-kdelayR+kManPtr)*(ginsamp/sr),0,(ginsamp-iwsize-irnd)/sr ;location from which to read grain. This is always directly related to the poistion of the write pointer.
  226. iwfn = giwfn1+i(gkwfn)-1 ;Grain amplitude windowing shape
  227. /*sndwarp*/
  228. asig,ac sndwarp 1, aphsR, apch, gibuffer, ibeg, iwsize, irnd, iolap, iwfn, imode
  229. if gkbalance==1 then ;if 'balance switch is on...
  230. asig balance asig,ac ;... amplitude balance the signal
  231. endif
  232. if gkmonostereo==1 then ;if 'mono' mode seleced...
  233. gaFBackSig = gaFBackSig+(asig*gkfback) ;create feedback signal for next iteration. (This will be written into the function table along with the live audio in.)
  234. aR = asig
  235. elseif gkmonostereo==2 then ;or if 'stereo out' mode
  236. aR,acR sndwarp 1, aphsR_R, apch, gibuffer, ibeg, iwsize, irnd, iolap, iwfn, imode
  237. if gkbalance==1 then
  238. aR balance aR,acR
  239. endif
  240. gaFBackSig = gaFBackSig+((asig+aR)*gkfback) ;create feedback signal, a mixture of the left and right sndwarp output channels
  241. else ;otherwise 'stereo in/out' mode
  242. aR,acR sndwarp 1, aphsR_R, apch, gibufferR, ibeg, iwsize, irnd, iolap, iwfn, imode
  243. if gkbalance==1 then
  244. aR balance aR,acR
  245. endif
  246. gaFBackSig = gaFBackSig+(asig*gkfback) ;left channel feedback signal
  247. gaFBackSig = gaFBackSig+(aR*gkfback) ;right channel feedback signal
  248. endif
  249. rireturn ;return from reinitialisation
  250. aAntiClick linsegr 0,0.03,1,0.03,0
  251. outs asig*gkamp*gkmix*aAntiClick, aR*gkamp*gkmix*aAntiClick ;send audio to outputs
  252. endin
  253. instr UpdateWidgets
  254. ksemis chnget "semis" ;read in 'semis' widget
  255. ktrig1 changed ksemis ;if 'semis' knob is moved...
  256. if ktrig1==1 then
  257. chnset semitone(ksemis), "pch" ;update 'Pitch' knob with the value of semis (converted to a ratio)
  258. endif
  259. endin
  260. </CsInstruments>
  261. <CsScore>
  262. i 1 0 [3600*24*7]
  263. ;i 2 0 [3600*24*7]
  264. i "UpdateWidgets" 0 [3600*24*7]
  265. </CsScore>
  266. </CsoundSynthesizer>