jevstrudel.git / packages / csound / livecode.orc
livecode.orc2226 lines · 62.6 KB · raw
1/*
2  Live Coding Functions
3  Author: Steven Yi
4*/ 
5
6instr S1
7  ifreq = p4
8  iamp = p5
9endin
10
11instr P1
12  ibeat = p4
13endin
14
15;; TIME
16
17gk_tempo init 120 
18
19
20/** Set tempo of global clock to itempo value in beats per minute. */
21opcode set_tempo,0,i
22  itempo xin
23  gk_tempo init itempo
24endop
25
26/** Returns tempo of global clock in beats per minute. */
27opcode get_tempo,i,0
28  xout i(gk_tempo)
29endop
30
31/** Adjust tempo of global clock towards by inewtempo by incr amount. */
32opcode go_tempo, 0, ii
33  inewtempo, incr xin
34
35  icurtempo = i(gk_tempo)
36  itemp init icurtempo 
37
38  if(inewtempo > icurtempo) ithen
39    itemp = min:i(inewtempo, icurtempo + abs(incr))
40    gk_tempo init itemp 
41  elseif (inewtempo < icurtempo) ithen
42    itemp = max:i(inewtempo, icurtempo - abs(incr))
43    gk_tempo init itemp 
44  endif
45endop
46
47instr Perform
48  ibeat = p4
49
50  schedule("P1", 0, p3, ibeat) 
51endin
52
53
54gk_clock_internal init 0
55gk_clock_tick init 0
56gk_now init 0
57
58/** Returns value of now beat time
59   (Code used from Thorin Kerr's LivecodeLib.csd) */
60opcode now, i, 0
61  xout i(gk_now)
62endop
63
64/** Returns current clock tick at init time */
65opcode now_tick, i, 0
66  xout i(gk_clock_tick)
67endop
68
69/** Returns duration of time in given number of beats (quarter notes) */
70opcode beats, i, i
71  inumbeats xin
72  ibeatdur = divz(60, i(gk_tempo), -1)
73  xout ibeatdur * inumbeats
74endop
75
76/** Returns duration of time in given number of measures (4 quarter notes) */
77opcode measures, i, i
78  inummeasures xin
79  xout beats(inummeasures * 4)
80endop
81
82/** Returns duration of time in given number of ticks (16th notes) */
83opcode ticks, i, i
84  inumbeats xin
85  ibeatdur = divz(60, i(gk_tempo), -1)
86  ibeatdur = ibeatdur / 4
87  xout ibeatdur * inumbeats
88endop
89
90/** Returns time from now for next beat, rounding to align
91    on beat boundary. 
92   (Code used from Thorin Kerr's LivecodeLib.csd) */
93opcode next_beat, i, p
94  ibeatcount xin
95  inow = now()
96  ibc = frac(ibeatcount)
97  inudge = int(ibeatcount)
98  iresult = inudge + ibc + (round(divz(inow, ibc, inow)) * (ibc == 0 ? 1 : ibc)) - inow
99  xout beats(iresult)
100endop
101
102/** Returns time from now for next measure, rounding to align to measure  
103    boundary. */
104opcode next_measure, i,0
105  inow = now() % 4
106  ival = 4 - inow 
107  if(ival < 0.25) then
108    ival += 4
109  endif
110  inext = beats(ival)
111  xout inext
112endop
113
114/** Reset clock so that next tick starts at 0 */
115opcode reset_clock, 0, 0
116  gk_clock_internal init 0 
117  gk_clock_tick init -1 
118  gk_now init -(ksmps / sr)
119endop
120
121/** Adjust clock by iadjust number of beats.
122    Value may be positive or negative. */
123opcode adjust_clock, 0, i 
124  iadjust xin
125  gk_now init i(gk_now) + iadjust 
126endop
127
128
129instr Clock ;; our clock  
130  ;; tick at 1/16th note
131  kfreq = (4 * gk_tempo) / 60     ;; frequency of 16th note
132  kdur = 1 / kfreq                ;; duration of 16th note in seconds 
133  kstep = (gk_tempo / 60) / kr    ;; step size in quarter notes per buffer
134  kstep16th = kfreq / kr          ;; step size in 16th notes per buffer
135  gk_now += kstep                 ;; advance beat clock
136  gk_clock_internal += kstep16th  ;; advance 16th note clock
137
138  // checks if next buffer will be one where clock will
139  // trigger.  If so, then schedule event for time 0 
140  // which will get processed next buffer. 
141  if(gk_clock_internal + kstep16th >= 1.0 ) then
142    gk_clock_internal -= 1.0 
143    gk_clock_tick += 1 
144    event("i", "Perform", 0, kdur, gk_clock_tick)
145  endif
146endin
147
148;; Randomization
149
150/** Given a random chance value between 0 and 1, calculates a random value and
151returns 1 if value is less than chance value. For example, giving a value of 0.7,
152it can read as "70 percent of time, return 1; else 0" */
153opcode choose, i, i
154  iamount xin
155  ival = 0
156
157  if(random(0,1) < limit:i(iamount, 0, 1)) then
158    ival = 1 
159  endif
160  xout ival
161endop
162
163;; Array Functions
164
165/** Cycles through karray using index. */
166opcode cycle, i, ik[]
167  indx, kvals[] xin
168  ival = i(kvals, indx % lenarray(kvals))
169  xout ival
170endop
171
172
173/** Checks to see if item exists within array. Returns 1 if
174  true and 0 if false. */
175opcode contains, i, ii[]
176  ival, iarr[] xin
177  indx = 0
178  iret = 0
179  while (indx < lenarray:i(iarr)) do
180    if (iarr[indx] == ival) then
181      iret = 1
182      igoto end
183    endif
184    indx += 1
185  od
186end:
187  xout iret
188endop 
189
190/** Checks to see if item exists within array. Returns 1 if
191  true and 0 if false. */
192opcode contains, i, ik[]
193  ival, karr[] xin
194  indx = 0
195  iret = 0
196  while (indx < lenarray:i(karr)) do
197    if (i(karr,indx) == ival) then
198      iret = 1
199      igoto end
200    endif
201    indx += 1
202  od
203end:
204  xout iret
205endop 
206
207/** Create a new array by removing all instances of a
208given number from an existing array. */ 
209opcode remove, k[], ik[]
210  ival, karr[] xin
211 
212  ifound = 0
213  indx = 0
214  while (indx < lenarray:i(karr)) do
215  	if(i(karr, indx) == ival) then
216      ifound += 1
217    endif
218    indx += 1
219  od
220
221  kout[] init (lenarray:i(karr) - ifound)
222    
223  indx = 0
224  iwriteIndx = 0
225  
226  while (indx < lenarray:i(karr)) do
227    iv = i(karr, indx)
228    if(iv != ival) then
229      kout[iwriteIndx] init iv
230      iwriteIndx += 1
231    endif
232    indx += 1
233  od
234    
235  xout kout
236endop
237
238/** Returns random item from karray. */
239opcode rand, i, k[]
240  kvals[] xin
241  indx = int(random(0, lenarray(kvals)))
242  ival = i(kvals, indx)
243  xout ival
244endop
245
246/** Returns random item from String array. */
247opcode rand, S, S[]
248  Svals[] xin
249  indx = int(random(0, lenarray(Svals)))
250  Sval = Svals[indx]
251  xout Sval
252endop
253
254/** Returns random item from karray. */
255opcode randk, k, k[]
256  kvals[] xin
257  kndx = int(random:k(0, lenarray:k(kvals)))
258  kval = kvals[kndx]
259  xout kval
260endop
261
262/** Returns random item from karray. */
263opcode randk, S, S[]
264  Svals[] xin
265  kndx = int(random:k(0, lenarray:k(Svals)))
266  Sval = Svals[kndx]
267  xout Sval
268endop
269
270
271;; Event
272
273/** Wrapper opcode that calls schedule only if iamp > 0 and ifreq > 0. */
274opcode cause, 0, Siiii
275  Sinstr, istart, idur, ifreq, iamp xin
276  if(ifreq > 0 && iamp > 0) then
277    schedule(Sinstr, istart, idur, ifreq, iamp)
278  endif
279endop
280
281;; Beats
282
283/** Given a hexadecimal beat string pattern and optional
284itick (defaults to current now_tick()), returns value 1 if
285the given tick matches a hit in the hexadecimal beat, or 
286returns 0 otherwise. */
287opcode hexbeat, i, So
288  Spat, itick xin
289
290  if(itick <= 0) then
291    itick = now_tick()
292  endif
293
294  istrlen = strlen(Spat)
295
296  iout = 0
297
298  if (istrlen > 0) then
299    ;; 4 bits/beats per hex value
300    ipatlen = strlen(Spat) * 4
301    ;; get beat within pattern length
302    itick = itick % ipatlen
303    ;; figure which hex value to use from string
304    ipatidx = int(itick / 4)
305    ;; figure out which bit from hex to use
306    ibitidx = itick % 4 
307    
308    ;; convert individual hex from string to decimal/binary
309    ibeatPat = strtol(strcat("0x", strsub(Spat, ipatidx, ipatidx + 1))) 
310
311    ;; bit shift/mask to check onset from hex's bits
312    iout = (ibeatPat >> (3 - ibitidx)) & 1 
313  endif
314
315  xout iout
316
317endop
318
319
320/** Given hex beat pattern, use given itick to fire 
321  events for given instrument, duration, frequency, and
322  amplitude */
323opcode hexplay, 0, SiSiip
324  Spat, itick, Sinstr, idur, ifreq, iamp xin
325
326  if(ifreq > 0 && iamp > 0 && strlen(Sinstr) > 0 && hexbeat(Spat, itick) == 1) then
327    schedule(Sinstr, 0, idur, ifreq, iamp )
328  endif
329endop
330
331/** Given hex beat pattern, use global clock to fire 
332  events for given instrument, duration, frequency, and
333  amplitude */
334opcode hexplay, 0, SSiip
335  Spat, Sinstr, idur, ifreq, iamp xin
336
337  itick = i(gk_clock_tick)
338
339  if(ifreq > 0 && iamp > 0 && strlen(Sinstr) > 0 && hexbeat(Spat, itick) == 1) then
340    schedule(Sinstr, 0, idur, ifreq, iamp )
341  endif
342endop
343
344
345/** Given an octal beat string pattern and optional
346itick (defaults to current now_tick()), returns value 1 if
347the given tick matches a hit in the octal beat, or 
348returns 0 otherwise. */
349opcode octalbeat, i, Si
350  Spat, itick xin
351
352  ;; 3 bits/beats per octal value
353  ipatlen = strlen(Spat) * 4
354  ;; get beat within pattern length
355  itick = itick % ipatlen
356  ;; figure which octal value to use from string
357  ipatidx = int(itick / 3)
358  ;; figure out which bit from octal to use
359  ibitidx = itick % 3 
360  
361  ;; convert individual octal from string to decimal/binary
362  ibeatPat = strtol(strcat("0", strsub(Spat, ipatidx, ipatidx + 1))) 
363
364  ;; bit shift/mask to check onset from hex's bits
365  xout (ibeatPat >> (2 - ibitidx)) & 1 
366
367endop
368
369opcode octalplay, 0, SiSiip
370  Spat, ibeat, Sinstr, idur, ifreq, iamp xin
371
372  if(octalbeat(Spat, ibeat) == 1) then
373    schedule(Sinstr, 0, idur, ifreq, iamp )
374  endif
375endop
376
377opcode octalplay, 0, SSiip
378  Spat, Sinstr, idur, ifreq, iamp xin
379
380  itick = i(gk_clock_tick)
381
382  if(octalbeat(Spat, itick) == 1) then
383    schedule(Sinstr, 0, idur, ifreq, iamp )
384  endif
385endop
386
387;; Phase Functions
388
389/** Given count and period, return phase value in range [0-1) */
390opcode phs, i, ii
391  icount, iperiod xin
392  xout (icount % iperiod) / iperiod 
393endop
394
395/** Given period in ticks, return current phase of global
396  clock in range [0-1) */
397opcode phs, i, i
398  iticks xin
399  xout (i(gk_clock_tick) % iticks) / iticks
400endop
401
402/** Given period in beats, return current phase of global
403  clock in range [0-1) */
404opcode phsb, i, i
405  ibeats xin
406  iticks = ibeats * 4
407  xout (i(gk_clock_tick) % iticks) / iticks
408endop
409
410/** Given period in measures, return current phase of global
411  clock in range [0-1) */
412opcode phsm, i, i
413  imeasures xin
414  iticks = imeasures * 4 * 4
415  xout (i(gk_clock_tick) % iticks) / iticks
416endop
417
418
419;; Iterative Euclidean Beat Generator
420;; Returns string of 1 and 0's
421opcode euclid_str, S, ii
422  ihits, isteps xin
423
424  Sleft = "1"
425  Sright = "0"
426
427  ileft = ihits
428  iright = isteps - ileft
429
430  while iright > 1 do
431    if (iright > ileft) then
432      iright = iright - ileft 
433      Sleft = strcat(Sleft, Sright)
434    else
435      itemp = iright
436      iright = ileft - iright
437      ileft = itemp 
438      Stemp = Sleft
439      Sleft = strcat(Sleft, Sright)
440      Sright = Stemp
441    endif
442  od
443
444  Sout = ""
445  indx = 0 
446  while (indx < ileft) do
447    Sout = strcat(Sout, Sleft)
448    indx += 1
449  od
450  indx = 0 
451  while (indx < iright) do
452    Sout = strcat(Sout, Sright)
453    indx += 1
454  od
455
456  xout Sout
457endop
458
459
460/** Given number of ihits for a period of isteps and an optional
461itick (defaults to current now_tick()), returns value 1 if
462the given tick matches a hit in the euclidean rhythm, or 
463returns 0 otherwise. */
464opcode euclid, i, iio
465  ihits, isteps, itick  xin
466
467  if(itick <= 0) then
468    itick = now_tick()
469  endif
470
471  Sval = euclid_str(ihits, isteps)
472  indx = itick % strlen(Sval)
473  xout strtol(strsub(Sval, indx, indx + 1))
474endop
475
476opcode euclidplay, 0, iiiSiip
477  ihits, isteps, itick, Sinstr, idur, ifreq, iamp xin
478
479  if(euclid(ihits, isteps, itick) == 1) then
480    schedule(Sinstr, 0, idur, ifreq, iamp)
481  endif
482endop
483
484
485opcode euclidplay, 0, iiSiip
486  ihits, isteps, Sinstr, idur, ifreq, iamp xin
487
488  itick = i(gk_clock_tick)
489
490  if(euclid(ihits, isteps, itick) == 1) then
491    schedule(Sinstr, 0, idur, ifreq, iamp)
492  endif
493endop
494
495;; Phase-based Oscillators 
496
497/** Returns cosine of given phase (0-1.0) */
498opcode xcos, i,i
499  iphase  xin
500  xout cos(2 * $M_PI * iphase)
501endop
502
503/** Range version of xcos, similar to Impromptu's cosr */
504opcode xcos, i,iii
505  iphase, ioffset, irange  xin
506  xout ioffset + (cos(2 * $M_PI * iphase) * irange)
507endop
508
509/** Returns sine of given phase (0-1.0) */
510opcode xsin, i,i
511  iphase  xin
512  xout sin(2 * $M_PI * iphase)
513endop
514
515/** Range version of xsin, similar to Impromptu's sinr */
516opcode xsin, i,iii
517  iphase, ioffset, irange  xin
518  xout ioffset + (sin(2 * $M_PI * iphase) * irange)
519endop
520
521/** Non-interpolating oscillator. Given phase in range 0-1, 
522returns value within the give k-array table. */
523opcode xosc, i, ik[]
524  iphase, kvals[]  xin
525  indx = int(lenarray:i(kvals) * (iphase % 1))  
526  xout i(kvals, indx)
527endop
528
529
530/** Non-interpolating oscillator. Given phase duration in beats, 
531returns value within the give k-array table. (shorthand for xosc(phsb(ibeats), karr) )*/
532opcode xoscb, i,ik[]
533  ibeats, kvals[] xin
534  xout xosc(phsb(ibeats), kvals)
535endop
536
537/** Non-interpolating oscillator. Given phase duration in measures, 
538returns value within the give k-array table. (shorthand for xosc(phsm(ibeats), karr) )*/
539opcode xoscm, i, ik[]
540  ibeats, kvals[] xin
541  xout xosc(phsm(ibeats), kvals)
542endop
543
544
545/** Linearly-interpolating oscillator. Given phase in range 0-1, 
546returns value intepolated within the two closest points of phase within k-array
547table. */
548opcode xosci, i, ik[]
549  iphase, kvals[]  xin
550  ilen = lenarray:i(kvals)
551  indx = ilen * (iphase % 1)
552  ibase = int(indx)  
553  ifrac = indx - ibase 
554
555  iv0 = i(kvals, ibase)  
556  iv1 = i(kvals, (ibase + 1) % ilen) 
557  xout iv0 + (iv1 - iv0) * ifrac
558endop
559
560
561/** Linearly-interpolating oscillator. Given phase duration in beats, 
562returns value intepolated within the two closest points of phase within k-array
563table. (shorthand for xosci(phsb(ibeats), karr) )*/
564opcode xoscib, i,ik[]
565  ibeats, kvals[] xin
566  xout xosci(phsb(ibeats), kvals)
567endop
568
569/** Linearly-interpolating oscillator. Given phase duration in measures, 
570returns value intepolated within the two closest points of phase within k-array
571table. (shorthand for xosci(phsm(ibeats), karr) )*/
572opcode xoscim, i,ik[]
573  ibeats, kvals[] xin
574  xout xosci(phsm(ibeats), kvals)
575endop
576
577/** Line (Ramp) oscillator. Given phase in range 0-1, return interpolated value between given istart and iend. */
578opcode xlin, i, iii
579  iphase, istart, iend xin
580  xout istart + (iend - istart) * iphase
581endop
582
583;; Duration Sequences
584
585/** Given a tick value and array of durations, returns new duration value for tick. */
586opcode xoscd, i, ik[]
587  itick, kdurs[] xin
588  indx = 0
589  isum = 0
590  ilen = lenarray:i(kdurs)
591  ival = 0
592
593  while (indx < ilen) do
594    isum += i(kdurs, indx)
595    indx += 1
596  od
597
598  itick = itick % isum
599  indx = 0
600  ival = 0
601  icur = 0
602
603  while (indx < ilen) do
604    itemp = i(kdurs, indx) 
605
606    if(itick < icur + itemp) then
607      ival = itemp 
608      indx += ilen
609    else
610      icur += abs(itemp)
611    endif
612    
613    indx += 1
614  od
615
616  xout ival 
617
618 endop 
619
620
621/** Given an array of durations, returns new duration value for current clock tick. Useful with mod division and cycle for additive/subtractive rhythms. */
622opcode xoscd, i, k[]
623  kdurs[] xin
624  xout xoscd(now_tick(), kdurs)
625endop
626
627
628/** Given a tick value and array of durations, returns new duration or 0 depending upon whether tick hits a new duration value. Values
629may be positive or negative, but not zero. Negative values can be interpreted as rest durations. */
630opcode dur_seq, i, ik[]
631  itick, kdurs[] xin
632  ival = 0
633  icur = 0
634  ilen = lenarray:i(kdurs)
635  itotal = 0
636
637  indx = 0
638  while (indx < ilen) do
639    itotal += abs:i(i(kdurs, indx))
640    indx += 1
641  od
642
643  ;print itotal
644
645  indx = 0
646  itick = itick % itotal
647
648  while (indx < ilen) do
649    itemp = i(kdurs, indx) 
650    if(icur == itick) then
651      ival = itemp 
652      indx += ilen
653    elseif (icur > itick) then
654      indx += ilen 
655    else
656      icur += abs(itemp)
657    endif
658    
659    indx += 1
660  od
661  xout ival 
662endop
663
664
665/** Given an array of durations, returns new duration or 0 depending upon
666 * whether current clock tick hits a new duration value. Values
667may be positive or negative, but not zero. Negative values can be interpreted
668as rest durations. */
669opcode dur_seq, i, k[]
670  kdurs[] xin
671  xout dur_seq(now_tick(), kdurs)
672endop
673
674/** Experimental opcode for generating melodic lines given array of durations, pitches, and amplitudes. Durations follow dur_seq practice that negative values are rests. Pitch and amp array indexing wraps according to their array lengths given index of non-rest duration value currently fired. */ 
675opcode melodic, iii, ik[]k[]k[]
676  itick, kdurs[], kpchs[], kamps[] xin
677
678  idur = dur_seq(itick, kdurs)
679  ipch = 0
680  iamp = 0
681
682  indx = 0
683  itotal = 0
684  ilen = lenarray:i(kdurs)
685
686  while (indx < ilen) do
687    itotal += abs:i(i(kdurs, indx))
688    indx += 1
689  od
690
691  itick = itick % itotal
692
693  if(idur > 0) then
694    indx = 0
695    icur = 0
696    ivalindx = 0
697
698    while (indx < ilen) do
699      itemp = i(kdurs, indx) 
700
701      if(icur == itick) then
702        indx += ilen
703      elseif (icur > itick) then
704        indx += ilen 
705      else
706        if (itemp > 0) then
707          ivalindx += 1 
708        endif
709
710        icur += abs(itemp)
711      endif
712      
713      indx += 1
714    od
715
716    ipch = i(kpchs, ivalindx % lenarray:i(kpchs))
717    iamp = i(kamps, ivalindx % lenarray:i(kamps))
718  endif
719
720  xout idur, ipch, iamp
721endop
722
723/** Experimental opcode for generating melodic lines given array of durations, pitches, and amplitudes. Durations follow dur_seq practice that negative values are rests. Pitch and amp array indexing wraps according to their array lengths given index of non-rest duration value currently fired. */ 
724opcode melodic, iii, k[]k[]k[]
725  kdurs[], kpchs[], kamps[] xin
726  idur, ipch, iamp = melodic(now_tick(), kdurs, kpchs, kamps)
727  xout idur, ipch, iamp
728endop
729
730;; String functions
731
732/** 
733  rotate - Rotates string by irot number of values.  
734  (Inspired by rotate from Charlie Roberts' Gibber.)
735*/
736opcode rotate, S, Si
737  Sval, irot xin
738
739  ilen = strlen(Sval)
740  irot = irot % ilen
741  Sout = strcat(strsub(Sval, irot, ilen), strsub(Sval, 0, irot))
742  xout Sout
743endop
744
745
746/** Repeats a given String x number of times. For example, `Sval = strrep("ab6a", 2)` will produce the value of "ab6aab6a". Useful in working with Hex beat strings.  */
747opcode strrep, S, Si
748  Sval, inum xin
749    
750  Sout = Sval
751  indx = 1
752  while (indx < inum) do
753    Sout = strcat(Sout, Sval) 
754    indx += 1
755  od
756
757  xout Sout
758endop
759
760
761;; Channel Helper
762
763/** Sets i-rate value into channel and sets initialization to true. Works together 
764  with xchan */
765opcode xchnset, 0, Si
766  SchanName, ival xin
767  Sinit = sprintf("%s_initialized", SchanName)
768  chnset(1, Sinit)
769  chnset(ival, SchanName)
770endop
771
772/** xchan 
773  Initializes a channel with initial value if channel has default value of 0 and
774  then returns the current value from the channel. Useful in live coding to define
775  a dynamic point that will be automated or set outside of the instrument that is
776  using the channel. 
777
778  Opcode is overloaded to return i- or k- value. Be sure to use xchan:i or xchan:k
779  to specify which value to use. 
780*/
781opcode xchan, i,Si
782  SchanName, initVal xin
783   
784  Sinit = sprintf("%s_initialized", SchanName)
785  if(chnget:i(Sinit) == 0) then
786    chnset(1, Sinit)
787    chnset(initVal, SchanName)
788  endif
789  xout chnget:i(SchanName)
790endop
791
792/** xchan 
793  Initializes a channel with initial value if channel has default value of 0 and
794  then returns the current value from the channel. Useful in live coding to define
795  a dynamic point that will be automated or set outside of the instrument that is
796  using the channel. 
797
798  Opcode is overloaded to return i- or k- value. Be sure to use xchan:i or xchan:k
799  to specify which value to use. 
800*/
801opcode xchan, k,Si
802  SchanName, initVal xin
803    
804  Sinit = sprintf("%s_initialized", SchanName)
805  if(chnget:i(SchanName) == 0) then
806    chnset(1, Sinit)
807    chnset(initVal, SchanName)
808  endif
809  xout chnget:k(SchanName)
810endop
811
812;; SCALE/HARMONY (experimental)
813
814gi_scale_major[] = array(0, 2, 4, 5, 7, 9, 11) 
815gi_scale_minor[] = array(0, 2, 3, 5, 7, 8, 10)
816
817gi_cur_scale[] = gi_scale_minor
818gi_scale_base = 60
819gi_chord_offset = 0
820
821/** Set root note of scale in MIDI note number. */
822opcode set_root, 0,i 
823  iscale_root xin
824  gi_scale_base = iscale_root
825endop
826
827/** Calculate frequency from root note of scale, using 
828octave and pitch class. */
829opcode from_root, i, ii
830  ioct, ipc xin
831  ival = gi_scale_base + (ioct * 12) + ipc
832  xout cpsmidinn(ival)
833endop
834
835/** Set the global scale.  Currently supports "maj" for major and "min" for minor scales. */
836opcode set_scale, 0,S
837  Scale xin
838  if(strcmp("maj", Scale) == 0) then
839    gi_cur_scale = gi_scale_major
840  else
841    gi_cur_scale = gi_scale_minor
842  endif
843endop
844
845/** Calculate frequency from root note of scale, using 
846octave and scale degree. */
847opcode in_scale, i, ii
848  ioct, idegree xin
849
850  ibase = gi_scale_base + (ioct * 12)
851
852  idegrees = lenarray(gi_cur_scale)
853
854  ioct = int(idegree / idegrees)
855  indx = idegree % idegrees
856
857  if(indx < 0) then
858    ioct -= 1
859    indx += idegrees
860  endif
861
862  xout cpsmidinn(ibase + (ioct * 12) + gi_cur_scale[int(indx)]) 
863endop
864
865/** Calculate frequency from root note of scale, using 
866octave and scale degree. (k-rate version of opcode) */
867opcode in_scale, k, kk 
868  koct, kdegree xin
869
870  kbase = gi_scale_base + (koct * 12)
871
872  idegrees = lenarray(gi_cur_scale)
873
874  koct = int(kdegree / idegrees)
875  kndx = kdegree % idegrees
876
877  if(kndx < 0) then
878    koct -= 1
879    kndx += idegrees
880  endif
881
882  xout cpsmidinn(kbase + (koct * 12) + gi_cur_scale[int(kndx)]) 
883endop
884
885/** Quantizes given MIDI note number to the given scale 
886    (Base on pc:quantize from Extempore) */
887opcode pc_quantize, i, ii[]
888  ipitch_in, iscale[] xin
889  inotenum = round:i(ipitch_in)
890  ipc = inotenum % 12
891  iout = inotenum
892  
893  
894  indx = 0
895  while (indx < 7) do
896    if(contains(ipc + indx, iscale) == 1) then
897      iout = inotenum + indx
898      goto end
899    elseif (contains(ipc - indx, iscale) == 1) then
900      iout = inotenum - indx
901      goto end
902    endif
903    indx += 1
904  od
905  end:
906  xout iout
907endop
908
909/** Quantizes given MIDI note number to the current active scale 
910    (Base on pc:quantize from Extempore) */
911opcode pc_quantize, i, i
912  ipitch_in xin
913  ival = pc_quantize(ipitch_in, gi_cur_scale)
914  xout ival
915endop  
916
917/* BELOW CHORD SYSTEM IS EXPERIMENTAL */
918
919gi_chord_base = 0 
920gi_chord_maj[] = array(0,4,7)
921gi_chord_maj7[] = array(0,4,7,11)
922gi_chord_min[] = array(0,3,7)
923gi_chord_min7[] = array(0,3,7,10)
924gi_chord_dim[] = array(0,3,6)
925gi_chord_dim7[] = array(0,3,6,9)
926gi_chord_aug[] = array(0,4,8)
927gi_chord_current[] = gi_chord_maj 
928
929opcode set_chord, 0, ii[]
930  ichord_root, ichord_intervals[] xin
931  gi_chord_base = ichord_root
932  gi_chord_current = ichord_intervals
933endop
934
935opcode set_chord, 0, S 
936  Schord xin
937endop
938
939opcode in_chord, i, ii
940  ioct, idegree xin
941
942  ibase = gi_scale_base + (ioct * 12) + gi_chord_base
943
944  idegrees = lenarray(gi_chord_current)
945
946  ioct = int(idegree / idegrees)
947  indx = idegree % idegrees
948
949  if(indx < 0) then
950    ioct -= 1
951    indx += idegrees
952  endif
953
954  xout cpsmidinn(ibase + (ioct * 12) + gi_chord_current[indx]) 
955endop
956
957;; AUDIO
958
959/** Utility opcode for declicking an audio signal. Should only be used in instruments that have positive p3 duration. */
960opcode declick, a, a
961  ain xin
962  aenv = linseg:a(0, 0.01, 1, p3 - 0.02, 1, 0.01, 0, 0.01, 0)
963  xout ain * aenv
964endop
965
966/** Custom non-interpolating oscil that takes in kfrequency and array to use as oscillator table
967data. Outputs k-rate signal. */
968opcode oscil, k, kk[]
969  kfreq, kin[] xin
970  ilen = lenarray(kin)
971  kphs = phasor:k(kfreq)
972  kout = kin[int(kphs * ilen) % ilen]
973  xout kout
974endop
975
976
977;; KILLING INSTANCES
978
979instr KillImpl
980  Sinstr = p4 
981  if (nstrnum(Sinstr) > 0) then
982    turnoff2(Sinstr, 0, 0)
983  endif
984  turnoff
985endin
986
987/** Turns off running instances of named instruments.  Useful when livecoding
988  audio and control signal process instruments. May not be effective if for
989  temporal recursion instruments as they may be non-running but scheduled in the
990  event system. In those situations, try using clear_instr to overwrite the
991  instrument definition. */
992opcode kill, 0,S
993  Sinstr xin
994  schedule("KillImpl", 0, 0.01, Sinstr)
995endop
996
997/** Redefines instr to empty body. Useful for killing
998  temporal recursion or clock callback functions */
999opcode clear_instr, 0,S
1000  Sinstr xin
1001  Sinstr_body = sprintf("instr %s\nendin\n", Sinstr)
1002  ires = compilestr(Sinstr_body)
1003  prints(sprintf("Cleared instrument definition: %s\n", 
1004          Sinstr))
1005endop
1006
1007/** Starts running a named instrument for indefinite time using p2=0 and p3=-1. 
1008  Will first turnoff any instances of existing named instrument first.  Useful
1009  when livecoding always-on audio and control signal process instruments. */
1010opcode start, 0,S
1011  Sinstr xin
1012
1013  if (nstrnum(Sinstr) > 0) then
1014    kill(Sinstr)
1015    schedule(Sinstr, ksmps / sr,-1)
1016  endif
1017endop
1018
1019/** Stops a running named instrument, allowing for release segments to operate. */
1020opcode stop, 0,S
1021  Sinstr xin
1022
1023  if (nstrnum(Sinstr) > 0) then
1024    schedule(-nstrnum(Sinstr), 0, 0)
1025  endif
1026endop
1027
1028instr CodeEval
1029  Scode = p4
1030  ires = compilestr(Scode)
1031endin
1032
1033/** Evaluate code at a given time */
1034opcode eval_at_time, 0, Si 
1035  Scode, istart xin
1036  iblock init ksmps / sr
1037  ;; adjust one block of time difference since this is
1038  ;; will need to be added as an event back on to the scheduler
1039  schedule("CodeEval", max:i(0, istart - iblock), 0, Scode)
1040endop
1041
1042
1043;; Fades 
1044
1045gi_fade_range init -30
1046
1047
1048/** Sets the range in db to fade over. By default, range is -30 (i.e., fades from -30dbfs to 0dbfs) */
1049opcode set_fade_range, 0, i
1050  irange xin
1051  gi_fade_range init irange
1052endop
1053
1054/** Given a fade channel identifier (number) and number of ticks to fade over time, advances from current fade channel value towards 0dbfs (1.0) using the globally set fade range. (By default starts fading in from -30dBfs and stops at 0dbfs.) */
1055opcode fade_in, i, ii
1056  ident, inumticks xin
1057  Schan = sprintf("fade_chan_%d", ident)
1058  ival = chnget:i(Schan)
1059  if(ival < 1.0) then
1060    ival = limit:i(ival + (1 / inumticks), 0, 1.0) 
1061    chnset(ival, Schan)
1062    iret = ampdbfs((1- ival) * gi_fade_range)
1063  else
1064    iret = ival
1065  endif
1066
1067  xout iret 
1068endop
1069
1070/** Given a fade channel identifier (number) and number of ticks to fade over time, advances from current fade channel value towards 0 using the globally set fade range. (By default starts fading out from 0dBfs and stops at -30dbfs.) */
1071opcode fade_out, i, ii
1072  ident, inumticks xin
1073  Schan = sprintf("fade_chan_%d", ident)
1074
1075  ival = chnget:i(Schan)
1076  iret init 0
1077
1078  if(ival > 0.0) then
1079    ival = limit:i(ival - (1 / inumticks), 0, 1.0) 
1080    chnset(ival, Schan)
1081    iret = ampdbfs((1- ival) * gi_fade_range)
1082  else
1083    iret = ival
1084  endif
1085
1086  xout iret 
1087endop
1088
1089/** Read value from fade channel. Useful if copy/pasting then wanting to just read from fade and control in the original code. */
1090opcode fade_read, i, i
1091  ident xin
1092  Schan = sprintf("fade_chan_%d", ident)
1093  iret = chnget:i(Schan)
1094  xout iret 
1095endop
1096
1097/**  Set value for fade channel to given value. Should be in range 0-1.0.  (Typically one sets to either 0 or 1.) */
1098opcode set_fade, 0,ii
1099  ident, ival xin
1100  Schan = sprintf("fade_chan_%d", ident)
1101  ival = limit:i(ival, 0, 1.0) 
1102  chnset(ival, Schan)
1103endop
1104
1105;; Stereo Audio Bus
1106
1107ga_sbus[] init 16, 2
1108
1109/** Write two audio signals into stereo bus at given index */
1110opcode sbus_write, 0,iaa
1111  ibus, al, ar xin
1112  ga_sbus[ibus][0] = al
1113  ga_sbus[ibus][1] = ar
1114endop
1115
1116/** Mix two audio signals into stereo bus at given index */
1117opcode sbus_mix, 0,iaa
1118  ibus, al, ar xin
1119  ga_sbus[ibus][0] = ga_sbus[ibus][0] + al
1120  ga_sbus[ibus][1] = ga_sbus[ibus][1] + ar
1121endop
1122
1123/** Clear audio signals from bus channel */
1124opcode sbus_clear, 0, i
1125  ibus xin
1126  aclear init 0
1127  ga_sbus[ibus][0] = aclear
1128  ga_sbus[ibus][1] = aclear
1129endop
1130
1131/** Read audio signals from bus channel */
1132opcode sbus_read, aa, i
1133  ibus xin
1134  aclear init 0
1135  al = ga_sbus[ibus][0] 
1136  ar = ga_sbus[ibus][1] 
1137  xout al, ar
1138endop
1139
1140;; MIXER
1141
1142gi_reverb_mixer_on init 0
1143
1144/** Always-on Mixer instrument with Reverb send channel. Use start("ReverbMixer") to run. Designed 
1145    for use with pan_verb_mix to simplify signal-based live coding. */
1146instr ReverbMixer
1147
1148  gi_reverb_mixer_on init 1
1149
1150  ;; dry and reverb send signals
1151  a1, a2 sbus_read 0
1152  a3, a4 sbus_read 1
1153  
1154  al, ar reverbsc a3, a4, xchan:k("Reverb.fb", 0.7), xchan:k("Reverb.cut", 12000)
1155  
1156  kamp = xchan:k("Mix.amp", 1.0)
1157  
1158  a1 = tanh(a1 + al) * kamp
1159  a2 = tanh(a2 + ar) * kamp
1160  
1161  out(a1, a2)
1162  
1163  sbus_clear(0)
1164  sbus_clear(1)
1165endin
1166
1167
1168/** Always-on Mixer instrument with Reverb send channel and feedback delay. Use start("FBReverbMixer") to run. Designed 
1169    for use with pan_verb_mix to simplify signal-based live coding. */
1170instr FBReverbMixer 
1171  al, ar sbus_read 0
1172  
1173  afb0 init 0
1174  afb1 init 0
1175
1176  gi_reverb_mixer_on init 1
1177
1178  ;; dry and reverb send signals
1179  a1, a2 sbus_read 0
1180  a3, a4 sbus_read 1
1181  
1182  al, ar reverbsc a3, a4, xchan:k("Reverb.fb", 0.7), xchan:k("Reverb.cut", 12000)
1183
1184  a1 = tanh(a1 + al + afb0) 
1185  a2 = tanh(a2 + ar + afb1)
1186 
1187  kfb_amt = xchan:k("FB.amt", 0.9)
1188  kfb_dur = xchan:k("FB.dur", 4.2) * 1000 ;; time in ms
1189
1190  afb0 = vdelay(a1 * kfb_amt, kfb_dur, 10000)
1191  afb1 = vdelay(a2 * kfb_amt, kfb_dur, 10000)
1192
1193  kamp = xchan:k("Mix.amp", 1.0)
1194  a1 *= kamp
1195  a2 *= kamp
1196  
1197  out(a1, a2)
1198  
1199  sbus_clear(0)
1200  sbus_clear(1)
1201
1202endin
1203
1204/** Utility opcode to pan signal, send dry to mixer, and send amount 
1205    of signal to reverb. If ReverbMixer is not on, will output just 
1206    panned signal using out opcode. */
1207opcode pan_verb_mix, 0,akk
1208  asig, kpan, krvb xin
1209   ;; Panning and send to mixer
1210  al, ar pan2 asig, kpan
1211 
1212  if(gi_reverb_mixer_on == 1) then
1213    sbus_mix(0, al, ar)
1214    sbus_mix(1, al * krvb, ar * krvb)
1215  else 
1216    out(al, ar)
1217  endif
1218endop
1219
1220/** Utility opcode to send dry stereo to mixer and send amount 
1221    of stereo signal to reverb. If ReverbMixer is not on, will output just 
1222    panned signal using out opcode. */
1223opcode reverb_mix, 0, aak
1224  al, ar, krvb xin
1225 
1226  if(gi_reverb_mixer_on == 1) then
1227    sbus_mix(0, al, ar)
1228    sbus_mix(1, al * krvb, ar * krvb)
1229  else 
1230    out(al, ar)
1231  endif
1232endop
1233
1234;; Automation
1235
1236/** Set a channel value at a given time. p4=ChannelName, p5=value*/ 
1237instr ChnSet
1238  Schan = p4
1239  ival = p5
1240  chnset(ival, Schan)
1241endin
1242
1243/** Automation instrument for channels. Takes in "ChannelName", start value, end value, and automation type (0=linear, else exponential). */ 
1244instr Auto 
1245  Schan = p4
1246  istart = p5
1247  iend = p6
1248  itype = p7
1249  kauto init 0
1250
1251  if(itype == 0) then
1252    kauto = line:k(istart, p3, iend)
1253  else
1254    kauto = expon:k(istart, p3, iend)
1255  endif
1256
1257  chnset(kauto, Schan)
1258endin
1259
1260/** Automate channel value over time. Takes in "ChannelName", duration, start value, end value, and automation type (0=linear, else exponential). For exponential, signs of istart and end must match and neither can be zero. */ 
1261opcode automate, 0, Siiii
1262  Schan, idur, istart, iend, itype xin
1263  schedule("Auto", 0, idur, Schan, istart, iend, itype)
1264endop
1265
1266instr FadeOutMix
1267  kauto = ampdbfs:k(line:k(0, p3, -60))
1268  chnset(kauto, "Mix.amp")
1269endin
1270
1271/** Utility opcode for end of performances to fade out Mixer over given idur time. idur defaults to 30 seconds. **/
1272opcode fade_out_mix, 0, o
1273  idur xin
1274  idur = (idur <= 0 ? 30 : idur)
1275  schedule("FadeOutMix", 0, idur) 
1276  schedule("ChnSet", idur + 0.1, 0, "Mix.amp", 0)
1277endop
1278
1279;; DSP
1280
1281/** Saturation using tanh */
1282opcode saturate, a, ak
1283  asig, ksat xin
1284  xout tanh(asig * ksat) / tanh(ksat)
1285endop
1286
1287;; SYNTHS
1288
1289xchnset("rvb.default", 0.1)
1290xchnset("drums.rvb.default", 0.1)
1291
1292/** Substractive Synth, 3osc */
1293instr Sub1
1294  asig = vco2(ampdbfs(-12), p4)
1295  asig += vco2(ampdbfs(-12), p4 * 1.01, 10)
1296  asig += vco2(ampdbfs(-12), p4 * 2, 10)
1297  asig = zdf_ladder(asig, expon(10000, p3, 400), 5)
1298  asig = declick(asig) * p5
1299  pan_verb_mix(asig, xchan:i("Sub1.pan", 0.5), xchan:i("Sub1.rvb", chnget:i("rvb.default")))
1300endin
1301
1302
1303/** Subtractive Synth, two saws, fifth freq apart */
1304instr Sub2
1305  icut = xchan:i("Sub2.cut", sr / 3)
1306  asig = vco2(ampdbfs(-12), p4) 
1307  asig += vco2(ampdbfs(-12), p4 * 1.5) 
1308  asig = zdf_ladder(asig, expon(icut, p3, 400), 5)
1309  asig = declick(asig) * p5
1310  pan_verb_mix(asig, xchan:i("Sub2.pan", 0.5), xchan:i("Sub2.rvb", chnget:i("rvb.default")))
1311endin
1312
1313
1314/** Subtractive Synth, three detuned saws, swells in */
1315instr Sub3 
1316  asig = vco2(p5, p4)
1317  asig += vco2(p5, p4 * 1.01)
1318  asig += vco2(p5, p4 * 0.995)
1319  asig *= 0.33 
1320  asig = zdf_ladder(asig, expon(100, p3, 22000), 12) 
1321  asig = declick(asig)
1322  pan_verb_mix(asig, xchan:i("Sub3.pan", 0.5), xchan:i("Sub3.rvb", chnget:i("rvb.default")))
1323endin
1324
1325/** Subtractive Synth, detuned square/saw, stabby. 
1326   Nice as a lead in octave 2, nicely grungy in octave -2, -1
1327*/
1328instr Sub4 
1329  asig = vco2(0.5, p4 * 2)
1330  asig += vco2(0.5, p4 * 2.01, 10)
1331  asig += vco2(1, p4, 10)
1332  asig += vco2(1, p4 * 0.99)
1333  itarget = p4 * 2
1334  asig = zdf_ladder(asig, expseg(20000, 0.15, itarget, 0.1, itarget), 5)
1335  asig = declick(asig) * p5 * 0.15
1336  pan_verb_mix(asig, xchan:i("Sub4.pan", 0.5), xchan:i("Sub4.rvb", chnget:i("rvb.default")))
1337endin
1338
1339
1340/** Subtractive Synth, detuned square/triangle */
1341instr Sub5
1342  asig = vco2(0.5, p4, 10)
1343  asig += vco2(0.25, p4 * 2.0001, 12)
1344  asig = zdf_ladder(asig, expseg(10000, 0.1, 500, 0.1, 500), 2)
1345  asig = declick(asig) * p5 * 0.75
1346  pan_verb_mix(asig, xchan:i("Sub5.pan", 0.5), xchan:i("Sub5.rvb", chnget:i("rvb.default")))
1347endin
1348
1349/** Subtractive Synth, saw, K35 filters */
1350instr Sub6
1351  asig = vco2(p5, p4)
1352
1353  asig = K35_hpf(asig, limit:i(p4, 30, 16000), 1)
1354  asig = K35_lpf(asig, expseg:k(12000, p3, limit:i(p4 * 8, 30, 12000)), 2.5)
1355  
1356  asig = saturate(asig, 4.5)
1357  asig *= p5 * 0.5
1358  
1359  asig = declick(asig)
1360  
1361  pan_verb_mix(asig, xchan:i("Sub6.pan", 0.5), xchan:i("Sub6.rvb", chnget:i("rvb.default")))
1362endin
1363
1364/** Subtractive Synth, saw + tri, K35 filters */
1365instr Sub7
1366  asig = vco2(p5, p4)
1367  asig += vco2(p5, p4 * 2, 4, 0.5)
1368
1369  asig = K35_hpf(asig, limit:i(p4, 30, 16000), 1)
1370  asig = K35_lpf(asig, expseg:k(12000, p3, limit:i(p4 * 8, 30, 12000)), 2.5)
1371  
1372  asig = saturate(asig, 4.5)
1373  asig *= p5 * 0.3
1374  
1375  asig = declick(asig)
1376  
1377  pan_verb_mix(asig, xchan:i("Sub7.pan", 0.5), xchan:i("Sub7.rvb", chnget:i("rvb.default")))
1378endin
1379
1380/** Subtractive Synth, square + saw + tri, diode ladder filter */
1381instr Sub8
1382  asig = vco2(p5, p4, 10)
1383  asig += vco2(p5 * 0.5, p4 * 2)
1384  asig += vco2(p5 * 0.15, p4 * 3.5, 12)  
1385  
1386  aenv = expon:a(1, 0.15, 0.001)
1387  asig = saturate(asig, 10)
1388  asig = diode_ladder(asig, 4000 + aenv * 4000, 12)
1389  asig = zdf_2pole(asig, p5, 0.25, 1)
1390  asig *= linen:a(1, 0, p3, .001) * 0.5
1391  pan_verb_mix(asig, xchan:i("Sub8.pan", 0.5), xchan:i("Sub8.rvb", chnget:i("rvb.default")))
1392endin
1393
1394/** SynthBrass subtractive synth */ 
1395instr SynBrass
1396  ipch = p4
1397
1398  asig = vco2(0.25, ipch)
1399  asig += vco2(0.25, ipch * 2.00)
1400  asig = zdf_ladder(asig, expseg(12000, 0.25, 500, 0.05, 500), 4)
1401  asig = declick(asig * p5)
1402
1403  pan_verb_mix(asig, xchan:i("SynBrass.pan", 0.5), xchan:i("SynBrass.rvb", chnget:i("rvb.default")))
1404endin
1405
1406/** Synth Harp subtracitve Synth */
1407instr SynHarp
1408  
1409  asig = vco2(p5, p4)
1410  asig += vco2(p5, p4 * 0.9993423423)
1411  asig += vco2(p5, p4 * 1.00093029423048) 
1412  
1413  ioct = octcps(p4)
1414  
1415  asig = zdf_ladder(asig, cpsoct(limit(linseg:a(ioct + 4, 0.015, ioct + 2, 0.2, ioct), 4.25, 14)), 0.5)
1416  asig = zdf_2pole(asig, p4 * 0.5, 0.5, 1)    
1417  
1418  asig *= linen:a(1, 0.012, p3, 0.01)
1419  
1420  pan_verb_mix(asig, xchan:i("SynHarp.pan", 0.5), xchan:i("SynHarp.rvb", chnget:i("rvb.default")))
1421endin
1422 
1423/** SuperSaw sound using 9 bandlimited saws (3 sets of detuned saws at octaves)*/
1424instr SSaw
1425  asig = vco2(1, p4)
1426  asig += vco2(1, p4 * cent(9.04234))
1427  asig += vco2(1, p4 * cent(-7.214342))
1428  
1429  asig += vco2(1, p4 * cent(1206.294143))
1430  asig += vco2(1, p4 * cent(1193.732))
1431  asig += vco2(1, p4 * cent(1200))
1432  
1433  asig += vco2(1, p4 * cent(2406.294143))
1434  asig += vco2(1, p4 * cent(2393.732))
1435  asig += vco2(1, p4 * cent(2400))
1436  
1437  asig *= 0.1
1438  icut = xchan:i("SSaw.cut", 16000)
1439  asig = zdf_ladder(asig, expseg(icut, p3 - 0.05, icut, 0.05, 200), 0.5)
1440  asig *= p5 
1441  asig = declick(asig)
1442
1443  pan_verb_mix(asig, xchan:i("SSaw.pan", 0.5), xchan:i("SSaw.rvb", chnget:i("rvb.default")))
1444endin
1445
1446/** Modal Synthesis Instrument: Percussive/organ-y sound */
1447instr Mode1
1448  asig = mpulse(p5, 0)
1449
1450  asig1 = mode(asig, p4, p4 * 0.5)
1451  asig1 += mode(asig, p4 * 2, p4 * 0.25)
1452  asig1 += mode(asig, p4 * 4, p4 * 0.125)
1453
1454  asig = declick(asig1) 
1455
1456  pan_verb_mix(asig, xchan:i("Mode1.pan", 0.5), xchan:i("Mode1.rvb", chnget:i("rvb.default")))
1457endin
1458
1459/** Pluck sound using impulses, noise, and waveguides*/
1460instr Plk 
1461  asig = mpulse(p5, 1 / p4)
1462  asig += random:a(-0.1, 0.1) * expseg(p5, 0.02, 0.001, p3, 0.001)
1463  
1464  aout wguide1 asig, 1/ p4, 10000, 0.8
1465  aout += wguide1(asig, 1/ (2 * p4), 12000, 0.6)
1466
1467  aout = K35_hpf(aout, p4, 0.5)
1468  aout = zdf_ladder(aout, expon(10000, p3, 100), 3)
1469  aout = dcblock2(aout)
1470  
1471  asig = declick(aout) 
1472  
1473  pan_verb_mix(asig, xchan:i("Plk.pan", 0.5), xchan:i("Plk.rvb", chnget:i("rvb.default")))
1474endin
1475
1476gi_organ1 = ftgen(0, 0, 65536, 10, 1, 0.5, 0.3, 0.2, 0.05, 0.015)
1477/** Wavetable Organ sound using additive synthesis */
1478instr Organ1
1479  asig = oscili(p5, p4, gi_organ1)
1480  asig *= 0.5
1481  asig = declick(asig)
1482
1483  pan_verb_mix(asig, xchan:i("Organ1.pan", 0.5), xchan:i("Organ1.rvb", chnget:i("rvb.default")))
1484endin
1485
1486/** Organ sound based on M1 Organ 2 patch */
1487instr Organ2
1488  asig = vco2(1, p4, 4, 0.25)
1489  asig += vco2(0.8, p4 * 2, 12)
1490  asig += vco2(0.3, p4 * 3, 10)
1491     
1492  icutStart = limit:i(xchan:i("Organ2.cut", 2000), 40, sr * 1/2)
1493  icutEnd = limit:i(xchan:i("Organ2.cutEnd", 500), 40, sr * 1/2)
1494  asig = zdf_ladder(asig, expseg(icutStart, 0.08, icutEnd, p3, icutEnd), 2)
1495  
1496  asig *= p5 * 0.67
1497  asig = declick(asig)
1498  
1499  pan_verb_mix(asig, xchan:i("Organ2.pan", 0.5), xchan:i("Organ2.rvb", chnget:i("rvb.default")))
1500endin
1501
1502giorgan_claribel_flute = ftgen(0, 0, 65536, 10, 1, ampdbfs(-30), ampdbfs(-35), ampdbfs(-40), ampdbfs(-32), ampdbfs(-40), ampdbfs(-42))
1503
1504/** Wavetable Organ using Flute 8' and Flute 4', wavetable based on Claribel Flute 
1505    http://www.pykett.org.uk/the_tonal_structure_of_organ_flutes.htm */
1506instr Organ3 
1507  asig = oscili(p5, p4, giorgan_claribel_flute)
1508  asig += oscili(p5, p4 * 2, giorgan_claribel_flute)  
1509  ;asig += oscili(p5, p4 * 0.5)
1510  
1511  asig *= linen:a(1, .02, p3, .01)
1512
1513  pan_verb_mix(asig, xchan:i("Organ3.pan", 0.5), xchan:i("Organ3.rvb", chnget:i("rvb.default")))
1514endin
1515
1516/** Subtractive Bass sound */
1517
1518instr Bass
1519
1520  asig = vco2(p5, p4, 10)
1521  asig += vco2(p5 * 0.25, p4 * 0.9992342342, 10)  
1522  asig += vco2(p5 * 0.5, p4 * 2.000234234)
1523  aenv = linseg:a(1, 0.2, 0.1, p3 - 0.2, 0) * 6
1524  asig = zdf_ladder(asig, cpsoct(5 + aenv), 4 )
1525  
1526  asig *= linen:a(0.7, 0, p3, 0.01)
1527  
1528  pan_verb_mix(asig, xchan:i("Bass.pan", 0.5), xchan:i("Bass.rvb", chnget:i("rvb.default")))
1529
1530endin
1531
1532/** MS20-style Bass Sound */
1533
1534instr ms20_bass 
1535  ipch = p4 
1536  iamp = p5 
1537  aenv = expseg(1000, 0.1, ipch * 2, p3 - .05, ipch * 2)
1538
1539  asig = vco2(1.0, ipch)
1540  asig = K35_hpf(asig, ipch, 5, 0, 1)
1541  asig = K35_lpf(asig, aenv, 8, 0, 1)
1542
1543  asig *= expon:a(iamp, p3, 0.0001) 
1544
1545  pan_verb_mix(asig, xchan:i("ms20_bass.pan", 0.5), xchan:i("ms20_bass.rvb", chnget:i("rvb.default")))
1546endin
1547
1548
1549/** VoxHumana Patch */
1550
1551instr VoxHumana 
1552  ipch = p4 
1553  iamp = p5 
1554  aenv = transegr:a(0, 0.453, 1, 1.0, 2.242, -1, 0)
1555
1556  klfo_pulse_width = lfo(0.125, 5.72, 1)
1557  klfo_saw = lfo(0.021, 5.04, 1)
1558  klfo_pulse = lfo(0.013, 3.5, 1)
1559
1560  asaw = vco2(iamp, ipch * (1 + klfo_saw))
1561  apulse = vco2(iamp, ipch * (1.00004 + klfo_pulse), 2, 0.625 + klfo_pulse_width)
1562
1563  aout = sum(asaw, apulse) * 0.0625 * aenv
1564
1565  ikeyfollow = 1 + exp( (ipch - 50) / 10000)
1566
1567  aout = butterlp(aout, 1986 * ikeyfollow)
1568
1569  pan_verb_mix(aout, xchan:i("VoxHumana.pan", 0.5), xchan:i("VoxHumana.rvb", chnget:i("rvb.default")))
1570endin
1571
1572/** FM 3:1 C:M ratio, 2->0.025 index, nice for bass */
1573instr FM1 
1574  icar = xchan("FM1.car", 1)
1575  imod = xchan("FM1.mod", 3)
1576  asig = foscili(p5, p4, icar, imod, expon(2, 0.2, 0.025))
1577  asig = declick(asig) * 0.5
1578  pan_verb_mix(asig, xchan:i("FM1.pan", 0.5), xchan:i("FM1.rvb", chnget:i("rvb.default")))
1579endin
1580
1581/** Filtered noise, exponential envelope */
1582instr Noi 
1583  p3 = max:i(p3, 0.4) 
1584  asig = pinker() * p5 * expon(1, p3, 0.001) * 0.1
1585
1586  a1 = mode(asig, p4, 80)
1587  a2 = mode(asig, p4 * 2, 40)
1588  a3 = mode(asig, p4 * 3, 30)
1589  a4 = mode(asig, p4 * 4, 20)
1590
1591  asig sum a1, a2, a3, a4
1592
1593  asig = declick(asig) * 0.25
1594
1595  pan_verb_mix(asig, xchan:i("Noi.pan", 0.5), xchan:i("Noi.rvb", chnget:i("rvb.default")))
1596endin
1597
1598
1599/** Wobble patched based on Jacob Joaquin's "Tempo-Synced Wobble Bass" */
1600instr Wobble
1601  /*p3 = max:i(p3, 0.4) */
1602
1603  itri = chnget:i("Wobble.triangle")
1604  if(itri == 0) then
1605    ;; unipolar triangle
1606    itri = ftgen(0, 0, 8192, -7, 0, 4096, 1, 4096, 0)
1607    chnset(itri, "Wobble.triangle")
1608  endif
1609
1610  ;; dur in ticks (16ths) for wobble lfo 
1611  iticks = xchan("Wobble.ticks", 2)
1612  ;; modulation max
1613  imod = p4 * 8 
1614
1615  klfo = oscili:k(1, 1 / ticks(iticks), itri)
1616
1617  asig = vco2(p5, p4 * 2.018)
1618  asig += vco2(p5, p4, 10)
1619  asig = zdf_ladder(asig, min:k(p4 + (imod * klfo), 22000), 12) 
1620  asig *= expon(1, beats(16), 0.001)
1621  asig = declick(asig)
1622  pan_verb_mix(asig, xchan:i("Wobble.pan", 0.5), xchan:i("Wobble.rvb", chnget:i("rvb.default")))
1623
1624endin
1625
1626/** Simple Sine-wave instrument with exponential envelope */
1627instr Sine
1628  asig = oscili(p5, p4)
1629  asig *= expseg:a(0.1, 0.001, 1, 0.1, 0.001, p3, 0.001)
1630  pan_verb_mix(asig, xchan:i("Sine.pan", 0.5), xchan:i("Sine.rvb", chnget:i("rvb.default")))
1631endin
1632
1633/** Simple Square-wave instrument with exponential envelope */
1634instr Square
1635  asig = vco2(p5, p4, 10)
1636  asig *= expseg:a(0.1, 0.005, 1, 0.1, 0.001, p3, 0.001)
1637  pan_verb_mix(asig, xchan:i("Square.pan", 0.5), xchan:i("Square.rvb", chnget:i("rvb.default")))
1638endin
1639
1640/** Simple Sawtooth-wave instrument with exponential envelope */
1641instr Saw
1642  asig = vco2(p5, p4)
1643  asig *= expseg:a(0.1, 0.005, 1, 0.1, 0.001, p3, 0.001)
1644  pan_verb_mix(asig, xchan:i("Saw.pan", 0.5), xchan:i("Saw.rvb", chnget:i("rvb.default")))
1645endin
1646
1647
1648;; SQUINE WAVE SYNTHS
1649
1650/** Squinewave Synth, 2 osc */
1651instr Squine1
1652  asig squinewave a(p4), expon:a(.8, p3, .1), expon:a(.9, p3, .5), 0, 4
1653  a2 squinewave a(p4 * 1.0019234234), expseg:a(.8, p3, .6), a(0), 0, 4
1654
1655  asig = (asig + a2 * 0.05) * p5 * 0.5
1656  asig = butterhp(asig, p4)
1657  asig *= linen:a(1, .015, p3, .02) 
1658  asig = dcblock2(asig)
1659
1660  pan_verb_mix(asig, xchan:i("Squine1.pan", 0.5), xchan:i("Squine1.rvb", chnget:i("rvb.default")))
1661  
1662endin
1663
1664gi_lc_sine = ftgen(0, 0, 65536, 10, 1)
1665
1666/** Formant Synth, buzz source, soprano ah formants */
1667instr Form1 
1668  iamp = p5
1669  ifreq = p4
1670  asig = buzz(1, ifreq * (1 + lfo(.003, 4)), (sr / 2) / ifreq, gi_lc_sine)
1671  
1672  a1 = butterbp(asig, 800, 80)
1673  a2 = butterbp(asig * ampdbfs(-6), 1150, 90)
1674  a3 = butterbp(asig * ampdbfs(-32), 2900 , 120)
1675  a4 = butterbp(asig * ampdbfs(-20), 3900, 130)
1676  a5 = butterbp(asig * ampdbfs(-50), 4950, 140)
1677
1678  asig = a1 + a2 + a3 + a4 + a5
1679  asig *= 35 * iamp * adsr(0.05, 0, 1, 0.01)
1680  
1681  pan_verb_mix(asig, xchan:i("Form1.pan", 0.5), xchan:i("Form1.rvb", chnget:i("rvb.default")))
1682endin
1683
1684;; MONOPHONIC SYNTHS
1685
1686/** Monophone synth using sawtooth wave and 4pole lpf. Use "start("Mono") to run the monosynth, then use MonoNote instrument to play the instrument. */
1687instr Mono
1688  asig = vco2(xchan:k("Mono.amp", 0.0), portk(xchan:k("Mono.freq", 60), xchan:k("Mono.glide", 0.02)))
1689  asig = zdf_ladder(asig, xchan:k("Mono.cut", 4000), xchan:k("Mono.Q", 10))
1690  
1691  kpan = xchan:k("Mono.pan", 0.5)
1692  aL,aR pan2  asig,kpan             
1693
1694  pan_verb_mix(asig, xchan:k("Mono.pan", 0.5), xchan:k("Mono.rvb", chnget:i("rvb.default")))
1695endin
1696maxalloc("Mono", 1)
1697
1698/** Note playing instrument for Mono synth. Be careful to use this
1699and not try to create multiple Mono instruments! */
1700instr MonoNote
1701  chnset(expon(p5, p3, 0.001), "Mono.amp")
1702  chnset(p4, "Mono.freq")
1703endin
1704
1705
1706;; DRUMS
1707
1708/** Bandpass-filtered impulse glitchy click sound. p4 = center frequency (e.g., 3000, 6000) */
1709instr Click 
1710  asig = mpulse(1, 0)
1711  asig = zdf_2pole(asig, p4, 3, 3)
1712  
1713  asig *= p5 * 4      ;; adjust amp 
1714  asig *= linen:a(1, 0, p3, 0.01)
1715  
1716  pan_verb_mix(asig, xchan:i("Click.pan", 0.5), xchan:i("Click.rvb", chnget:i("rvb.default")))
1717endin
1718
1719/** Highpass-filtered noise+saw sound. Use NoiSaw.cut channel to adjust cutoff. */
1720instr NoiSaw 
1721  asig = random:a(-1, 1)
1722  asig += vco2(1, 100)
1723  asig = zdf_2pole(asig, xchan:i("NoiSaw.cut", 3000), 1, 3)
1724  
1725  asig *= p5 * 0.5
1726  asig *= expseg:a(1, 0.1, 0.001, p3, 0.0001)
1727  
1728  asig *= linen:a(1, 0, p3, 0.01)
1729  
1730  pan_verb_mix(asig, xchan:i("NoiSaw.pan", 0.5), xchan:i("NoiSaw.rvb", chnget:i("rvb.default")))
1731endin
1732
1733/** Modified clap instrument by Istvan Varga (clap1.orc) */
1734instr Clap
1735  ifreq = p4 ;; ignore
1736  iamp = p5
1737
1738  ibpfrq  =  1046.5       /* bandpass filter frequency */
1739  kbpbwd =  port:k(ibpfrq*0.25, 0.03, ibpfrq*4.0)   /* bandpass filter bandwidth */
1740  idec  =  0.5          /* decay time        */
1741
1742  a1  =  1.0
1743  a1_ delay1 a1
1744  a1  =  a1 - a1_
1745  a2  delay a1, 0.011
1746  a3  delay a1, 0.023
1747  a4  delay a1, 0.031
1748
1749  a1  tone a1, 60.0
1750  a2  tone a2, 60.0
1751  a3  tone a3, 60.0
1752  a4  tone a4, 1.0 / idec
1753
1754  aenv1 =  a1 + a2 + a3 + a4*60.0*idec
1755
1756  a_  unirand 2.0
1757  a_  =  aenv1 * (a_ - 1.0)
1758  a_  butterbp a_, ibpfrq, kbpbwd
1759
1760  aout = a_ * 80 * iamp ;; 
1761  pan_verb_mix(aout, xchan:k("Clap.pan", 0.7), xchan:k("Clap.rvb", chnget:i("drums.rvb.default")))
1762endin
1763
1764
1765
1766gi_808_sine  ftgen 0,0,1024,10,1   ;A SINE WAVE
1767gi_808_cos ftgen 0,0,65536,9,1,1,90  ;A COSINE WAVE 
1768
1769/** Bass Drum - From Iain McCurdy's TR-808.csd */
1770instr BD  ;BASS DRUM
1771  p3  = 2 * xchan("BD.decay", 0.5)              ;NOTE DURATION. SCALED USING GUI 'Decay' KNOB
1772
1773  ilevel = xchan("BD.level", 1) * 2
1774  itune = xchan("BD.tune", 0)
1775
1776  ;SUSTAIN AND BODY OF THE SOUND
1777  kmul = transeg(0.2,p3*0.5,-15,0.01, p3*0.5,0,0)         ;PARTIAL STRENGTHS MULTIPLIER USED BY GBUZZ. DECAYS FROM A SOUND WITH OVERTONES TO A SINE TONE.
1778  kbend = transeg(0.5,1.2,-4, 0,1,0,0)            ;SLIGHT PITCH BEND AT THE START OF THE NOTE 
1779  asig = gbuzz(0.5,50*octave(itune)*semitone(kbend),20,1,kmul,gi_808_cos)   ;GBUZZ TONE
1780  aenv = transeg:a(1,p3-0.004,-6,0)             ;AMPLITUDE ENVELOPE FOR SUSTAIN OF THE SOUND
1781  aatt = linseg:a(0,0.004,1, .01, 1)              ;SOFT ATTACK
1782  asig= asig*aenv*aatt
1783
1784  ;HARD, SHORT ATTACK OF THE SOUND
1785  aenv  = linseg:a(1,0.07,0, .01, 0)              ;AMPLITUDE ENVELOPE (FAST DECAY)            
1786  acps = expsega(400,0.07,0.001,1,0.001)            ;FREQUENCY OF THE ATTACK SOUND. QUICKLY GLISSES FROM 400 Hz TO SUB-AUDIO
1787  aimp = oscili(aenv,acps*octave(itune*0.25),gi_808_sine)       ;CREATE ATTACK SOUND
1788  
1789  amix  = ((asig*0.5)+(aimp*0.35))*ilevel*p5      ;MIX SUSTAIN AND ATTACK SOUND ELEMENTS AND SCALE USING GUI 'Level' KNOB
1790  
1791  pan_verb_mix(amix, xchan:k("BD.pan", 0.5), xchan:k("BD.rvb", chnget:i("drums.rvb.default")))
1792endin
1793
1794
1795/** Snare Drum - From Iain McCurdy's TR-808.csd */
1796instr SD  ;SNARE DRUM
1797  
1798  ;SOUND CONSISTS OF TWO SINE TONES, AN OCTAVE APART AND A NOISE SIGNAL
1799  idur = xchan("SD.decay", 1.0) 
1800  ilevel = xchan("SD.level", 1) 
1801  itune = xchan("SD.tune", 0)
1802
1803  ifrq    = 342   ;FREQUENCY OF THE TONES
1804  iNseDur = 0.3 * idur  ;DURATION OF THE NOISE COMPONENT
1805  iPchDur = 0.1 * idur  ;DURATION OF THE SINE TONES COMPONENT
1806  p3  = iNseDur   ;p3 DURATION TAKEN FROM NOISE COMPONENT DURATION (ALWATS THE LONGEST COMPONENT)
1807  
1808  ;SINE TONES COMPONENT
1809  aenv1 = expseg(1, iPchDur, 0.0001, p3-iPchDur, 0.0001)    ;AMPLITUDE ENVELOPE
1810  apitch1 = oscili(1, ifrq * octave(itune), gi_808_sine)      ;SINE TONE 1
1811  apitch2 = oscili(0.25, ifrq * 0.5 * octave(itune), gi_808_sine)   ;SINE TONE 2 (AN OCTAVE LOWER)
1812  apitch  = (apitch1+apitch2)*0.75        ;MIX THE TWO SINE TONES
1813
1814  ;NOISE COMPONENT
1815  aenv2 = expon(1,p3,0.0005)          ;AMPLITUDE ENVELOPE
1816  anoise = noise(0.75, 0)           ;CREATE SOME NOISE
1817  anoise = butbp(anoise, 10000*octave(itune), 10000)    ;BANDPASS FILTER THE NOISE SIGNAL
1818  anoise = buthp(anoise, 1000)          ;HIGHPASS FILTER THE NOISE SIGNAL
1819  kcf = expseg(5000, 0.1, 3000, p3-0.2, 3000)     ;CUTOFF FREQUENCY FOR A LOWPASS FILTER
1820  anoise = butlp(anoise,kcf)                      ;LOWPASS FILTER THE NOISE SIGNAL
1821  amix  = ((apitch*aenv1)+(anoise*aenv2))*ilevel*p5 ;MIX AUDIO SIGNALS AND SCALE ACCORDING TO GUI 'Level' CONTROL
1822
1823  pan_verb_mix(amix, xchan:k("SD.pan", 0.5), xchan:k("SD.rvb", chnget:i("drums.rvb.default")))
1824endin
1825
1826
1827/** Open High Hat - From Iain McCurdy's TR-808.csd */
1828instr OHH ;OPEN HIGH HAT
1829
1830  idur = xchan("OHH.decay", 1.0)  
1831  ilevel = xchan("OHH.level", 1) 
1832  itune = xchan("OHH.tune", 0)
1833  ioct = octave:i(itune)
1834
1835
1836  kFrq1 = 296*ioct  ;FREQUENCIES OF THE 6 OSCILLATORS
1837  kFrq2 = 285*ioct  
1838  kFrq3 = 365*ioct  
1839  kFrq4 = 348*ioct  
1840  kFrq5 = 420*ioct  
1841  kFrq6 = 835*ioct  
1842  p3  = 0.5*idur    ;DURATION OF THE NOTE
1843  
1844  ;SOUND CONSISTS OF 6 PULSE OSCILLATORS MIXED WITH A NOISE COMPONENT
1845  ;PITCHED ELEMENT
1846  aenv  linseg  1,p3-0.05,0.1,0.05,0    ;AMPLITUDE ENVELOPE FOR THE PULSE OSCILLATORS
1847  ipw = 0.25        ;PULSE WIDTH
1848  a1  vco2  0.5,kFrq1,2,ipw     ;PULSE OSCILLATORS...
1849  a2  vco2  0.5,kFrq2,2,ipw
1850  a3  vco2  0.5,kFrq3,2,ipw
1851  a4  vco2  0.5,kFrq4,2,ipw
1852  a5  vco2  0.5,kFrq5,2,ipw
1853  a6  vco2  0.5,kFrq6,2,ipw
1854  amix  sum a1,a2,a3,a4,a5,a6   ;MIX THE PULSE OSCILLATORS
1855  amix  reson amix,5000*ioct,5000,1 ;BANDPASS FILTER THE MIXTURE
1856  amix  buthp amix,5000     ;HIGHPASS FILTER THE SOUND...
1857  amix  buthp amix,5000     ;...AND AGAIN
1858  amix  = amix*aenv     ;APPLY THE AMPLITUDE ENVELOPE
1859  
1860  ;NOISE ELEMENT
1861  anoise  noise 0.8,0       ;GENERATE SOME WHITE NOISE
1862  aenv  linseg  1,p3-0.05,0.1,0.05,0    ;CREATE AN AMPLITUDE ENVELOPE
1863  kcf expseg  20000,0.7,9000,p3-0.1,9000  ;CREATE A CUTOFF FREQ. ENVELOPE
1864  anoise  butlp anoise,kcf      ;LOWPASS FILTER THE NOISE SIGNAL
1865  anoise  buthp anoise,8000     ;HIGHPASS FILTER THE NOISE SIGNAL
1866  anoise  = anoise*aenv     ;APPLY THE AMPLITUDE ENVELOPE
1867  
1868  ;MIX PULSE OSCILLATOR AND NOISE COMPONENTS
1869  amix  = (amix+anoise)*ilevel*p5*0.55
1870
1871  pan_verb_mix(amix, xchan:k("OHH.pan", 0.5), xchan:k("OHH.rvb", chnget:i("drums.rvb.default")))
1872endin
1873
1874
1875/** Closed High Hat - From Iain McCurdy's TR-808.csd */
1876instr CHH ;CLOSED HIGH HAT
1877  idur = xchan("CHH.decay", 1.0)  
1878  ilevel = xchan("CHH.level", 1) 
1879  itune = xchan("CHH.tune", 0)
1880  ioct = octave:i(itune)
1881
1882  kFrq1 = 296*ioct  ;FREQUENCIES OF THE 6 OSCILLATORS
1883  kFrq2 = 285*ioct  
1884  kFrq3 = 365*ioct  
1885  kFrq4 = 348*ioct  
1886  kFrq5 = 420*ioct  
1887  kFrq6 = 835*ioct  
1888  idur  = 0.088*idur    ;DURATION OF THE NOTE
1889  p3  limit idur,0.1,10   ;LIMIT THE MINIMUM DURATION OF THE NOTE (VERY SHORT NOTES CAN RESULT IN THE INDICATOR LIGHT ON-OFF NOTE BEING TO0 SHORT)
1890
1891  iohh = nstrnum("OHH")
1892  iactive = active(iohh)      ;SENSE ACTIVITY OF PREVIOUS INSTRUMENT (OPEN HIGH HAT) 
1893  if iactive>0 then     ;IF 'OPEN HIGH HAT' IS ACTIVE...
1894   turnoff2 iohh,0,0    ;TURN IT OFF (CLOSED HIGH HAT TAKES PRESIDENCE)
1895  endif
1896
1897  ;PITCHED ELEMENT
1898  aenv  expsega 1,idur,0.001,1,0.001    ;AMPLITUDE ENVELOPE FOR THE PULSE OSCILLATORS
1899  ipw = 0.25        ;PULSE WIDTH
1900  a1  vco2  0.5,kFrq1,2,ipw     ;PULSE OSCILLATORS...     
1901  a2  vco2  0.5,kFrq2,2,ipw
1902  a3  vco2  0.5,kFrq3,2,ipw
1903  a4  vco2  0.5,kFrq4,2,ipw
1904  a5  vco2  0.5,kFrq5,2,ipw
1905  a6  vco2  0.5,kFrq6,2,ipw
1906  amix  sum a1,a2,a3,a4,a5,a6   ;MIX THE PULSE OSCILLATORS
1907  amix  reson amix,5000*ioct,5000,1 ;BANDPASS FILTER THE MIXTURE
1908  amix  buthp amix,5000     ;HIGHPASS FILTER THE SOUND...
1909  amix  buthp amix,5000     ;...AND AGAIN
1910  amix  = amix*aenv     ;APPLY THE AMPLITUDE ENVELOPE
1911  
1912  ;NOISE ELEMENT
1913  anoise  noise 0.8,0       ;GENERATE SOME WHITE NOISE
1914  aenv  expsega 1,idur,0.001,1,0.001    ;CREATE AN AMPLITUDE ENVELOPE
1915  kcf expseg  20000,0.7,9000,idur-0.1,9000  ;CREATE A CUTOFF FREQ. ENVELOPE
1916  anoise  butlp anoise,kcf      ;LOWPASS FILTER THE NOISE SIGNAL
1917  anoise  buthp anoise,8000     ;HIGHPASS FILTER THE NOISE SIGNAL
1918  anoise  = anoise*aenv     ;APPLY THE AMPLITUDE ENVELOPE
1919  
1920  ;MIX PULSE OSCILLATOR AND NOISE COMPONENTS
1921  amix  = (amix+anoise)*ilevel*p5*0.55
1922
1923  pan_verb_mix(amix, xchan:k("CHH.pan", 0.5), xchan:k("CHH.rvb", chnget:i("drums.rvb.default")))
1924endin
1925
1926/** High Tom - From Iain McCurdy's TR-808.csd */
1927instr HiTom ;HIGH TOM
1928  idur = xchan("HiTom.decay", 1.0)  
1929  ilevel = xchan("HiTom.level", 1) 
1930  itune = xchan("HiTom.tune", 0)
1931  ioct = octave:i(itune)
1932
1933  ifrq      = 200 * ioct  ;FREQUENCY
1934  p3      = 0.5 * idur      ;DURATION OF THIS NOTE
1935
1936  ;SINE TONE SIGNAL
1937  aAmpEnv transeg 1,p3,-10,0.001        ;AMPLITUDE ENVELOPE FOR SINE TONE SIGNAL
1938  afmod expsega 5,0.125/ifrq,1,1,1      ;FREQUENCY MODULATION ENVELOPE. GIVES THE TONE MORE OF AN ATTACK.
1939  asig  oscili  -aAmpEnv*0.6,ifrq*afmod,gi_808_sine   ;SINE TONE SIGNAL
1940
1941  ;NOISE SIGNAL
1942  aEnvNse transeg 1,p3,-6,0.001       ;AMPLITUDE ENVELOPE FOR NOISE SIGNAL
1943  anoise  dust2 0.4, 8000       ;GENERATE NOISE SIGNAL
1944  anoise  reson anoise,400*ioct,800,1 ;BANDPASS FILTER THE NOISE SIGNAL
1945  anoise  buthp anoise,100*ioct   ;HIGHPASS FILTER THE NOSIE SIGNAL
1946  anoise  butlp anoise,1000*ioct    ;LOWPASS FILTER THE NOISE SIGNAL
1947  anoise  = anoise * aEnvNse      ;SCALE NOISE SIGNAL WITH AMPLITUDE ENVELOPE
1948  
1949  ;MIX THE TWO SOUND COMPONENTS
1950  amix  = (asig + anoise)*ilevel*p5
1951
1952  pan_verb_mix(amix, xchan:k("HiTom.pan", 0.5), xchan:k("HiTom.rvb", chnget:i("drums.rvb.default")))
1953endin
1954
1955/** Mid Tom - From Iain McCurdy's TR-808.csd */
1956instr MidTom ;MID TOM
1957  idur = xchan("MidTom.decay", 1.0) 
1958  ilevel = xchan("MidTom.level", 1) 
1959  itune = xchan("MidTom.tune", 0)
1960  ioct = octave:i(itune)
1961
1962  ifrq      = 133*ioct    ;FREQUENCY
1963  p3      = 0.6 * idur      ;DURATION OF THIS NOTE
1964
1965  ;SINE TONE SIGNAL
1966  aAmpEnv transeg 1,p3,-10,0.001        ;AMPLITUDE ENVELOPE FOR SINE TONE SIGNAL
1967  afmod expsega 5,0.125/ifrq,1,1,1      ;FREQUENCY MODULATION ENVELOPE. GIVES THE TONE MORE OF AN ATTACK.
1968  asig  oscili  -aAmpEnv*0.6,ifrq*afmod,gi_808_sine   ;SINE TONE SIGNAL
1969
1970  ;NOISE SIGNAL
1971  aEnvNse transeg 1,p3,-6,0.001       ;AMPLITUDE ENVELOPE FOR NOISE SIGNAL
1972  anoise  dust2 0.4, 8000       ;GENERATE NOISE SIGNAL
1973  anoise  reson anoise, 400*ioct,800,1  ;BANDPASS FILTER THE NOISE SIGNAL
1974  anoise  buthp anoise,100*ioct   ;HIGHPASS FILTER THE NOSIE SIGNAL
1975  anoise  butlp anoise,600*ioct   ;LOWPASS FILTER THE NOISE SIGNAL
1976  anoise  = anoise * aEnvNse      ;SCALE NOISE SIGNAL WITH AMPLITUDE ENVELOPE
1977  
1978  ;MIX THE TWO SOUND COMPONENTS
1979  amix  = (asig + anoise)*ilevel*p5
1980
1981  pan_verb_mix(amix, xchan:k("MidTom.pan", 0.5), xchan:k("MidTom.rvb", chnget:i("drums.rvb.default")))
1982endin
1983
1984/** Low Tom - From Iain McCurdy's TR-808.csd */
1985instr LowTom  ;LOW TOM
1986  idur = xchan("LowTom.decay", 1.0) 
1987  ilevel = xchan("LowTom.level", 1) 
1988  itune = xchan("LowTom.tune", 0)
1989  ioct = octave:i(itune)
1990
1991  ifrq      = 90 * ioct ;FREQUENCY
1992  p3    = 0.7*idur    ;DURATION OF THIS NOTE
1993
1994  ;SINE TONE SIGNAL
1995  aAmpEnv transeg 1,p3,-10,0.001        ;AMPLITUDE ENVELOPE FOR SINE TONE SIGNAL
1996  afmod expsega 5,0.125/ifrq,1,1,1      ;FREQUENCY MODULATION ENVELOPE. GIVES THE TONE MORE OF AN ATTACK.
1997  asig  oscili  -aAmpEnv*0.6,ifrq*afmod,gi_808_sine   ;SINE TONE SIGNAL
1998
1999  ;NOISE SIGNAL
2000  aEnvNse transeg 1,p3,-6,0.001       ;AMPLITUDE ENVELOPE FOR NOISE SIGNAL
2001  anoise  dust2 0.4, 8000       ;GENERATE NOISE SIGNAL
2002  anoise  reson anoise,40*ioct,800,1    ;BANDPASS FILTER THE NOISE SIGNAL
2003  anoise  buthp anoise,100*ioct   ;HIGHPASS FILTER THE NOSIE SIGNAL
2004  anoise  butlp anoise,600*ioct   ;LOWPASS FILTER THE NOISE SIGNAL
2005  anoise  = anoise * aEnvNse      ;SCALE NOISE SIGNAL WITH AMPLITUDE ENVELOPE
2006  
2007  ;MIX THE TWO SOUND COMPONENTS
2008  amix  = (asig + anoise)*ilevel*p5
2009
2010  pan_verb_mix(amix, xchan:k("LowTom.pan", 0.5), xchan:k("LowTom.rvb", chnget:i("drums.rvb.default")))
2011endin
2012
2013
2014
2015/** Cymbal - From Iain McCurdy's TR-808.csd */
2016instr Cymbal  ;CYMBAL
2017  idur = xchan("Cymbal.decay", 1.0) 
2018  ilevel = xchan("Cymbal.level", 1) 
2019  itune = xchan("Cymbal.tune", 0)
2020  ioct = octave:i(itune)
2021
2022  iFrq1 = 296*ioct  ;FREQUENCIES OF THE 6 OSCILLATORS
2023  iFrq2 = 285*ioct
2024  iFrq3 = 365*ioct
2025  iFrq4 = 348*ioct     
2026  iFrq5 = 420*ioct
2027  iFrq6 = 835*ioct
2028  p3  = 2*idur  ;DURATION OF THE NOTE
2029
2030  ;SOUND CONSISTS OF 6 PULSE OSCILLATORS MIXED WITH A NOISE COMPONENT
2031  ;PITCHED ELEMENT
2032  aenv  expon 1,p3,0.0001   ;AMPLITUDE ENVELOPE FOR THE PULSE OSCILLATORS 
2033  ipw = 0.25      ;PULSE WIDTH      
2034  a1  vco2  0.5,iFrq1,2,ipw   ;PULSE OSCILLATORS...  
2035  a2  vco2  0.5,iFrq2,2,ipw
2036  a3  vco2  0.5,iFrq3,2,ipw
2037  a4  vco2  0.5,iFrq4,2,ipw
2038  a5  vco2  0.5,iFrq5,2,ipw 
2039  a6  vco2  0.5,iFrq6,2,ipw
2040
2041  amix  sum a1,a2,a3,a4,a5,a6   ;MIX THE PULSE OSCILLATORS
2042  amix  reson amix,5000 * ioct,5000,1 ;BANDPASS FILTER THE MIXTURE
2043  amix  buthp amix,10000      ;HIGHPASS FILTER THE SOUND
2044  amix  butlp amix,12000      ;LOWPASS FILTER THE SOUND...
2045  amix  butlp amix,12000      ;AND AGAIN...
2046  amix  = amix*aenv     ;APPLY THE AMPLITUDE ENVELOPE
2047  
2048  ;NOISE ELEMENT
2049  anoise  noise 0.8,0       ;GENERATE SOME WHITE NOISE
2050  aenv  expsega 1,0.3,0.07,p3-0.1,0.00001 ;CREATE AN AMPLITUDE ENVELOPE
2051  kcf expseg  14000,0.7,7000,p3-0.1,5000  ;CREATE A CUTOFF FREQ. ENVELOPE
2052  anoise  butlp anoise,kcf      ;LOWPASS FILTER THE NOISE SIGNAL
2053  anoise  buthp anoise,8000     ;HIGHPASS FILTER THE NOISE SIGNAL
2054  anoise  = anoise*aenv     ;APPLY THE AMPLITUDE ENVELOPE            
2055
2056  ;MIX PULSE OSCILLATOR AND NOISE COMPONENTS
2057  amix  = (amix+anoise)*ilevel*p5*0.85
2058
2059  pan_verb_mix(amix, xchan:k("Cymbal.pan", 0.5), xchan:k("Cymbal.rvb", chnget:i("drums.rvb.default")))
2060endin
2061
2062;WAVEFORM FOR TR808 RIMSHOT
2063giTR808RimShot  ftgen 0,0,1024,10, 0.971,0.269,0.041,0.054,0.011,0.013,0.08,0.0065,0.005,0.004,0.003,0.003,0.002,0.002,0.002,0.002,0.002,0.001,0.001,0.001,0.001,0.001,0.002,0.001,0.001  
2064
2065/** Rimshot - From Iain McCurdy's TR-808.csd */
2066instr Rimshot ;RIM SHOT
2067
2068  idur = xchan("Rimshot.decay", 1.0)  
2069  ilevel = xchan("Rimshot.level", 1) 
2070  itune = xchan("Rimshot.tune", 0)
2071
2072  idur  = 0.027*idur    ;NOTE DURATION
2073  p3  limit idur,0.1,10     ;LIMIT THE MINIMUM DURATION OF THE NOTE (VERY SHORT NOTES CAN RESULT IN THE INDICATOR LIGHT ON-OFF NOTE BEING TO0 SHORT)
2074
2075  ;RING
2076  aenv1 expsega 1,idur,0.001,1,0.001    ;AMPLITUDE ENVELOPE FOR SUSTAIN ELEMENT OF SOUND
2077  ifrq1 = 1700*octave(itune)    ;FREQUENCY OF SUSTAIN ELEMENT OF SOUND
2078  aring oscili  1,ifrq1,giTR808RimShot,0    ;CREATE SUSTAIN ELEMENT OF SOUND  
2079  aring butbp aring,ifrq1,ifrq1*8 
2080  aring = aring*(aenv1-0.001)*0.5     ;APPLY AMPLITUDE ENVELOPE
2081
2082  ;NOISE
2083  anoise  noise 1,0         ;CREATE A NOISE SIGNAL
2084  aenv2 expsega 1, 0.002, 0.8, 0.005, 0.5, idur-0.002-0.005, 0.0001, 1, 0.0001  ;CREATE AMPLITUDE ENVELOPE
2085  anoise  buthp anoise,800      ;HIGHPASS FILTER THE NOISE SOUND
2086  kcf expseg  4000,idur,20        ;CUTOFF FREQUENCY FUNCTION FOR LOWPASS FILTER
2087  anoise  butlp anoise,kcf      ;LOWPASS FILTER THE SOUND
2088  anoise  = anoise*(aenv2-0.001)  ;APPLY ENVELOPE TO NOISE SIGNAL
2089
2090  ;MIX
2091  amix  = (aring+anoise)*ilevel*p5*0.8
2092
2093  pan_verb_mix(amix, xchan:k("Rimshot.pan", 0.5), xchan:k("Rimshot.rvb", chnget:i("drums.rvb.default")))
2094endin
2095
2096
2097/** Claves - From Iain McCurdy's TR-808.csd */
2098instr Claves  
2099  idur = xchan("Claves.decay", 1.0) 
2100  ilevel = xchan("Claves.level", 1) 
2101  itune = xchan("Claves.tune", 0)
2102
2103  ifrq  = 2500*octave(itune)  ;FREQUENCY OF OSCILLATOR
2104  idur  = 0.045   * idur    ;DURATION OF THE NOTE
2105  p3  limit idur,0.1,10     ;LIMIT THE MINIMUM DURATION OF THE NOTE (VERY SHORT NOTES CAN RESULT IN THE INDICATOR LIGHT ON-OFF NOTE BEING TO0 SHORT)      
2106  aenv  expsega 1,idur,0.001,1,0.001    ;AMPLITUDE ENVELOPE
2107  afmod expsega 3,0.00005,1,1,1     ;FREQUENCY MODULATION ENVELOPE. GIVES THE SOUND A LITTLE MORE ATTACK.
2108  asig  oscili  -(aenv-0.001),ifrq*afmod,gi_808_sine,0  ;AUDIO OSCILLATOR
2109  asig  = asig * 0.4 * ilevel * p5    ;RESCALE AMPLITUDE
2110
2111  pan_verb_mix(asig, xchan:k("Claves.pan", 0.5), xchan:k("Claves.rvb", chnget:i("drums.rvb.default")))
2112endin
2113
2114
2115/** Cowbell - From Iain McCurdy's TR-808.csd */
2116instr Cowbell 
2117  idur = xchan("Cowbell.decay", 1.0)  
2118  ilevel = xchan("Cowbell.level", 1) 
2119  itune = xchan("Cowbell.tune", 0)
2120
2121  ifrq1 = 562 * octave(itune) ;FREQUENCIES OF THE TWO OSCILLATORS
2122  ifrq2 = 845 * octave(itune) ;
2123  ipw   = 0.5         ;PULSE WIDTH OF THE OSCILLATOR  
2124  ishp  = -30   
2125  idur  = 0.7         ;NOTE DURATION
2126  p3  = 0.7*idur      ;LIMIT THE MINIMUM DURATION OF THE NOTE (VERY SHORT NOTES CAN RESULT IN THE INDICATOR LIGHT ON-OFF NOTE BEING TO0 SHORT)
2127  ishape  = -30       ;SHAPE OF THE CURVES IN THE AMPLITUDE ENVELOPE
2128  kenv1 transeg 1,p3*0.3,ishape,0.2, p3*0.7,ishape,0.2  ;FIRST AMPLITUDE ENVELOPE - PRINCIPALLY THE ATTACK OF THE NOTE
2129  kenv2 expon 1,p3,0.0005       ;SECOND AMPLITUDE ENVELOPE - THE SUSTAIN PORTION OF THE NOTE
2130  kenv  = kenv1*kenv2     ;COMBINE THE TWO ENVELOPES
2131  itype = 2       ;WAVEFORM FOR VCO2 (2=PULSE)
2132  a1  vco2  0.65,ifrq1,itype,ipw    ;CREATE THE TWO OSCILLATORS
2133  a2  vco2  0.65,ifrq2,itype,ipw
2134  amix  = a1+a2       ;MIX THE TWO OSCILLATORS 
2135  iLPF2 = 10000       ;LOWPASS FILTER RESTING FREQUENCY
2136  kcf expseg  12000,0.07,iLPF2,1,iLPF2  ;LOWPASS FILTER CUTOFF FREQUENCY ENVELOPE
2137  alpf  butlp amix,kcf      ;LOWPASS FILTER THE MIX OF THE TWO OSCILLATORS (CREATE A NEW SIGNAL)
2138  abpf  reson amix, ifrq2, 25     ;BANDPASS FILTER THE MIX OF THE TWO OSCILLATORS (CREATE A NEW SIGNAL)
2139  amix  dcblock2  (abpf*0.06*kenv1)+(alpf*0.5)+(amix*0.9) ;MIX ALL SIGNALS AND BLOCK DC OFFSET
2140  amix  buthp amix,700      ;HIGHPASS FILTER THE MIX OF ALL SIGNALS
2141  amix  = amix * 0.07 * kenv * p5 * ilevel  ;RESCALE AMPLITUDE
2142
2143  pan_verb_mix(amix, xchan:k("Cowbell.pan", 0.5), xchan:k("Cowbell.rvb", chnget:i("drums.rvb.default")))
2144endin
2145
2146/** Maraca - from Iain McCurdy's TR-808.csd */ 
2147instr Maraca  ;MARACA
2148  idur = xchan("Maraca.decay", 1.0) 
2149  ilevel = xchan("Maraca.level", 1) 
2150  itune = xchan("Maraca.tune", 0)
2151  ioct = octave:i(itune)
2152
2153  idur  = 0.07*idur       ;DURATION 3
2154  p3  limit idur,0.1,10       ;LIMIT THE MINIMUM DURATION OF THE NOTE (VERY SHORT NOTES CAN RESULT IN THE INDICATOR LIGHT ON-OFF NOTE BEING TO0 SHORT)
2155  iHPF  limit 6000*ioct,20,sr/2 ;HIGHPASS FILTER FREQUENCY  
2156  iLPF  limit 12000*ioct,20,sr/3  ;LOWPASS FILTER FREQUENCY. (LIMIT MAXIMUM TO PREVENT OUT OF RANGE VALUES)
2157  ;AMPLITUDE ENVELOPE
2158  iBP1  = 0.4         ;BREAK-POINT 1
2159  iDur1 = 0.014*idur      ;DURATION 1
2160  iBP2  = 1         ;BREAKPOINT 2
2161  iDur2 = 0.01 *idur      ;DURATION 2
2162  iBP3  = 0.05          ;BREAKPOINT 3
2163  p3  limit idur,0.1,10       ;LIMIT THE MINIMUM DURATION OF THE NOTE (VERY SHORT NOTES CAN RESULT IN THE INDICATOR LIGHT ON-OFF NOTE BEING TO0 SHORT)
2164  aenv  expsega iBP1,iDur1,iBP2,iDur2,iBP3    ;CREATE AMPLITUDE ENVELOPE
2165  anoise  noise 0.75,0          ;CREATE A NOISE SIGNAL
2166  anoise  buthp anoise,iHPF       ;HIGHPASS FILTER THE SOUND
2167  anoise  butlp anoise,iLPF       ;LOWPASS FILTER THE SOUND
2168  anoise  = anoise*aenv*p5*ilevel ;SCALE THE AMPLITUDE
2169
2170  pan_verb_mix(anoise, xchan:k("Maraca.pan", 0.5), xchan:k("Maraca.rvb", chnget:i("drums.rvb.default")))
2171endin
2172
2173/** High Conga - From Iain McCurdy's TR-808.csd */
2174instr HiConga ;HIGH CONGA
2175  idur = xchan("HiConga.decay", 1.0)  
2176  ilevel = xchan("HiConga.level", 1) 
2177  itune = xchan("HiConga.tune", 0)
2178  ioct = octave:i(itune)
2179
2180  ifrq    = 420*ioct    ;FREQUENCY OF NOTE
2181  p3    = 0.22*idur     ;DURATION OF NOTE
2182  aenv  transeg 0.7,1/ifrq,1,1,p3,-6,0.001  ;AMPLITUDE ENVELOPE
2183  afrq  expsega ifrq*3,0.25/ifrq,ifrq,1,ifrq  ;FREQUENCY ENVELOPE (CREATE A SHARPER ATTACK)
2184  asig  oscili  -aenv*0.25,afrq,gi_808_sine   ;CREATE THE AUDIO OSCILLATOR
2185  asig  = asig*p5*ilevel  ;SCALE THE AMPLITUDE
2186  
2187  pan_verb_mix(asig, xchan:k("HiConga.pan", 0.5), xchan:k("HiConga.rvb", chnget:i("drums.rvb.default")))
2188endin
2189
2190/** Mid Conga - From Iain McCurdy's TR-808.csd */
2191instr MidConga  ;MID CONGA
2192  idur = xchan("MidConga.decay", 1.0) 
2193  ilevel = xchan("MidConga.level", 1) 
2194  itune = xchan("MidConga.tune", 0)
2195  ioct = octave:i(itune)
2196
2197  ifrq    = 310*ioct    ;FREQUENCY OF NOTE
2198  p3    = 0.33*idur     ;DURATION OF NOTE
2199  aenv  transeg 0.7,1/ifrq,1,1,p3,-6,0.001  ;AMPLITUDE ENVELOPE 
2200  afrq  expsega ifrq*3,0.25/ifrq,ifrq,1,ifrq  ;FREQUENCY ENVELOPE (CREATE A SHARPER ATTACK)
2201  asig  oscili  -aenv*0.25,afrq,gi_808_sine   ;CREATE THE AUDIO OSCILLATOR
2202  asig  = asig*p5*ilevel    ;SCALE THE AMPLITUDE
2203
2204  pan_verb_mix(asig, xchan:k("MidConga.pan", 0.5), xchan:k("MidConga.rvb", chnget:i("drums.rvb.default")))
2205endin
2206
2207/** Low Conga - From Iain McCurdy's TR-808.csd */
2208instr LowConga  ;LOW CONGA
2209  idur = xchan("LowConga.decay", 1.0) 
2210  ilevel = xchan("LowConga.level", 1) 
2211  itune = xchan("LowConga.tune", 0)
2212  ioct = octave:i(itune)
2213
2214  ifrq    = 227*ioct    ;FREQUENCY OF NOTE
2215  p3    = 0.41*idur     ;DURATION OF NOTE   
2216  aenv  transeg 0.7,1/ifrq,1,1,p3,-6,0.001  ;AMPLITUDE ENVELOPE 
2217  afrq  expsega ifrq*3,0.25/ifrq,ifrq,1,ifrq  ;FREQUENCY ENVELOPE (CREATE A SHARPER ATTACK)
2218  asig  oscili  -aenv*0.25,afrq,gi_808_sine   ;CREATE THE AUDIO OSCILLATOR
2219  asig  = asig*p5*ilevel  ;SCALE THE AMPLITUDE
2220
2221  pan_verb_mix(asig, xchan:k("LowConga.pan", 0.5), xchan:k("LowConga.rvb", chnget:i("drums.rvb.default")))
2222endin
2223
2224;; INITIALIZATION OF SYSTEM
2225
2226start("Clock")