Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
2144 lines (1686 sloc) 59.6 KB
/*
Live Coding Functions
Author: Steven Yi
*/
instr S1
ifreq = p4
iamp = p5
endin
instr P1
ibeat = p4
endin
;; TIME
gk_tempo init 120
/** Set tempo of global clock to itempo value in beats per minute. */
opcode set_tempo,0,i
itempo xin
gk_tempo init itempo
endop
/** Returns tempo of global clock in beats per minute. */
opcode get_tempo,i,0
xout i(gk_tempo)
endop
/** Adjust tempo of global clock towards by inewtempo by incr amount. */
opcode go_tempo, 0, ii
inewtempo, incr xin
icurtempo = i(gk_tempo)
itemp init icurtempo
if(inewtempo > icurtempo) ithen
itemp = min:i(inewtempo, icurtempo + abs(incr))
gk_tempo init itemp
elseif (inewtempo < icurtempo) ithen
itemp = max:i(inewtempo, icurtempo - abs(incr))
gk_tempo init itemp
endif
endop
instr Perform
ibeat = p4
schedule("P1", 0, p3, ibeat)
endin
gk_clock_internal init 0
gk_clock_tick init 0
gk_now init 0
/** Returns value of now beat time
(Code used from Thorin Kerr's LivecodeLib.csd) */
opcode now, i, 0
xout i(gk_now)
endop
/** Returns current clock tick at init time */
opcode now_tick, i, 0
xout i(gk_clock_tick)
endop
/** Returns duration of time in given number of beats (quarter notes) */
opcode beats, i, i
inumbeats xin
ibeatdur = divz(60, i(gk_tempo), -1)
xout ibeatdur * inumbeats
endop
/** Returns duration of time in given number of measures (4 quarter notes) */
opcode measures, i, i
inummeasures xin
xout beats(inummeasures * 4)
endop
/** Returns duration of time in given number of ticks (16th notes) */
opcode ticks, i, i
inumbeats xin
ibeatdur = divz(60, i(gk_tempo), -1)
ibeatdur = ibeatdur / 4
xout ibeatdur * inumbeats
endop
/** Returns time from now for next beat, rounding to align
on beat boundary.
(Code used from Thorin Kerr's LivecodeLib.csd) */
opcode next_beat, i, p
ibeatcount xin
inow = now()
ibc = frac(ibeatcount)
inudge = int(ibeatcount)
iresult = inudge + ibc + (round(divz(inow, ibc, inow)) * (ibc == 0 ? 1 : ibc)) - inow
xout beats(iresult)
endop
/** Returns time from now for next measure, rounding to align to measure
boundary. */
opcode next_measure, i,0
inow = now() % 4
ival = 4 - inow
if(ival < 0.25) then
ival += 4
endif
inext = beats(ival)
xout inext
endop
/** Reset clock so that next tick starts at 0 */
opcode reset_clock, 0, 0
gk_clock_internal init 0
gk_clock_tick init -1
gk_now init -(ksmps / sr)
endop
/** Adjust clock by iadjust number of beats.
Value may be positive or negative. */
opcode adjust_clock, 0, i
iadjust xin
gk_now init i(gk_now) + iadjust
endop
instr Clock ;; our clock
;; tick at 1/16th note
kfreq = (4 * gk_tempo) / 60 ;; frequency of 16th note
kdur = 1 / kfreq ;; duration of 16th note in seconds
kstep = (gk_tempo / 60) / kr ;; step size in quarter notes per buffer
kstep16th = kfreq / kr ;; step size in 16th notes per buffer
gk_now += kstep ;; advance beat clock
gk_clock_internal += kstep16th ;; advance 16th note clock
// checks if next buffer will be one where clock will
// trigger. If so, then schedule event for time 0
// which will get processed next buffer.
if(gk_clock_internal + kstep16th >= 1.0 ) then
gk_clock_internal -= 1.0
gk_clock_tick += 1
event("i", "Perform", 0, kdur, gk_clock_tick)
endif
endin
;; Randomization
/** Given a random chance value between 0 and 1, calculates a random value and
returns 1 if value is less than chance value. For example, giving a value of 0.7,
it can read as "70 percent of time, return 1; else 0" */
opcode choose, i, i
iamount xin
ival = 0
if(random(0,1) < limit:i(iamount, 0, 1)) then
ival = 1
endif
xout ival
endop
;; Array Functions
/** Cycles through karray using index. */
opcode cycle, i, ik[]
indx, kvals[] xin
ival = i(kvals, indx % lenarray(kvals))
xout ival
endop
/** Checks to see if item exists within array. Returns 1 if
true and 0 if false. */
opcode contains, i, ii[]
ival, iarr[] xin
indx = 0
iret = 0
while (indx < lenarray:i(iarr)) do
if (iarr[indx] == ival) then
iret = 1
igoto end
endif
indx += 1
od
end:
xout iret
endop
/** Checks to see if item exists within array. Returns 1 if
true and 0 if false. */
opcode contains, i, ik[]
ival, karr[] xin
indx = 0
iret = 0
while (indx < lenarray:i(karr)) do
if (i(karr,indx) == ival) then
iret = 1
igoto end
endif
indx += 1
od
end:
xout iret
endop
/** Create a new array by removing all instances of a
given number from an existing array. */
opcode remove, k[], ik[]
ival, karr[] xin
ifound = 0
indx = 0
while (indx < lenarray:i(karr)) do
if(i(karr, indx) == ival) then
ifound += 1
endif
indx += 1
od
kout[] init (lenarray:i(karr) - ifound)
indx = 0
iwriteIndx = 0
while (indx < lenarray:i(karr)) do
iv = i(karr, indx)
if(iv != ival) then
kout[iwriteIndx] init iv
iwriteIndx += 1
endif
indx += 1
od
xout kout
endop
/** Returns random item from karray. */
opcode rand, i, k[]
kvals[] xin
indx = int(random(0, lenarray(kvals)))
ival = i(kvals, indx)
xout ival
endop
/** Returns random item from String array. */
opcode rand, S, S[]
Svals[] xin
indx = int(random(0, lenarray(Svals)))
Sval = Svals[indx]
xout Sval
endop
/** Returns random item from karray. */
opcode randk, k, k[]
kvals[] xin
kndx = int(random:k(0, lenarray:k(kvals)))
kval = kvals[kndx]
xout kval
endop
/** Returns random item from karray. */
opcode randk, S, S[]
Svals[] xin
kndx = int(random:k(0, lenarray:k(Svals)))
Sval = Svals[kndx]
xout Sval
endop
;; Event
/** Wrapper opcode that calls schedule only if iamp > 0. */
opcode cause, 0, Siiii
Sinstr, istart, idur, ifreq, iamp xin
if(iamp > 0) then
schedule(Sinstr, istart, idur, ifreq, iamp)
endif
endop
;; Beats
/** Given a hexadecimal beat string pattern and optional
itick (defaults to current now_tick()), returns value 1 if
the given tick matches a hit in the hexadecimal beat, or
returns 0 otherwise. */
opcode hexbeat, i, So
Spat, itick xin
if(itick <= 0) then
itick = now_tick()
endif
istrlen = strlen(Spat)
iout = 0
if (istrlen > 0) then
;; 4 bits/beats per hex value
ipatlen = strlen(Spat) * 4
;; get beat within pattern length
itick = itick % ipatlen
;; figure which hex value to use from string
ipatidx = int(itick / 4)
;; figure out which bit from hex to use
ibitidx = itick % 4
;; convert individual hex from string to decimal/binary
ibeatPat = strtol(strcat("0x", strsub(Spat, ipatidx, ipatidx + 1)))
;; bit shift/mask to check onset from hex's bits
iout = (ibeatPat >> (3 - ibitidx)) & 1
endif
xout iout
endop
/** Given hex beat pattern, use given itick to fire
events for given instrument, duration, frequency, and
amplitude */
opcode hexplay, 0, SiSiip
Spat, itick, Sinstr, idur, ifreq, iamp xin
if(iamp > 0 && hexbeat(Spat, itick) == 1) then
schedule(Sinstr, 0, idur, ifreq, iamp )
endif
endop
/** Given hex beat pattern, use global clock to fire
events for given instrument, duration, frequency, and
amplitude */
opcode hexplay, 0, SSiip
Spat, Sinstr, idur, ifreq, iamp xin
itick = i(gk_clock_tick)
if(iamp > 0 && hexbeat(Spat, itick) == 1) then
schedule(Sinstr, 0, idur, ifreq, iamp )
endif
endop
/** Given an octal beat string pattern and optional
itick (defaults to current now_tick()), returns value 1 if
the given tick matches a hit in the octal beat, or
returns 0 otherwise. */
opcode octalbeat, i, Si
Spat, itick xin
;; 3 bits/beats per octal value
ipatlen = strlen(Spat) * 4
;; get beat within pattern length
itick = itick % ipatlen
;; figure which octal value to use from string
ipatidx = int(itick / 3)
;; figure out which bit from octal to use
ibitidx = itick % 3
;; convert individual octal from string to decimal/binary
ibeatPat = strtol(strcat("0", strsub(Spat, ipatidx, ipatidx + 1)))
;; bit shift/mask to check onset from hex's bits
xout (ibeatPat >> (2 - ibitidx)) & 1
endop
opcode octalplay, 0, SiSiip
Spat, ibeat, Sinstr, idur, ifreq, iamp xin
if(octalbeat(Spat, ibeat) == 1) then
schedule(Sinstr, 0, idur, ifreq, iamp )
endif
endop
opcode octalplay, 0, SSiip
Spat, Sinstr, idur, ifreq, iamp xin
itick = i(gk_clock_tick)
if(octalbeat(Spat, itick) == 1) then
schedule(Sinstr, 0, idur, ifreq, iamp )
endif
endop
;; Phase Functions
/** Given count and period, return phase value in range [0-1) */
opcode phs, i, ii
icount, iperiod xin
xout (icount % iperiod) / iperiod
endop
/** Given period in ticks, return current phase of global
clock in range [0-1) */
opcode phs, i, i
iticks xin
xout (i(gk_clock_tick) % iticks) / iticks
endop
/** Given period in beats, return current phase of global
clock in range [0-1) */
opcode phsb, i, i
ibeats xin
iticks = ibeats * 4
xout (i(gk_clock_tick) % iticks) / iticks
endop
/** Given period in measures, return current phase of global
clock in range [0-1) */
opcode phsm, i, i
imeasures xin
iticks = imeasures * 4 * 4
xout (i(gk_clock_tick) % iticks) / iticks
endop
;; Iterative Euclidean Beat Generator
;; Returns string of 1 and 0's
opcode euclid_str, S, ii
ihits, isteps xin
Sleft = "1"
Sright = "0"
ileft = ihits
iright = isteps - ileft
while iright > 1 do
if (iright > ileft) then
iright = iright - ileft
Sleft = strcat(Sleft, Sright)
else
itemp = iright
iright = ileft - iright
ileft = itemp
Stemp = Sleft
Sleft = strcat(Sleft, Sright)
Sright = Stemp
endif
od
Sout = ""
indx = 0
while (indx < ileft) do
Sout = strcat(Sout, Sleft)
indx += 1
od
indx = 0
while (indx < iright) do
Sout = strcat(Sout, Sright)
indx += 1
od
xout Sout
endop
/** Given number of ihits for a period of isteps and an optional
itick (defaults to current now_tick()), returns value 1 if
the given tick matches a hit in the euclidean rhythm, or
returns 0 otherwise. */
opcode euclid, i, iio
ihits, isteps, itick xin
if(itick <= 0) then
itick = now_tick()
endif
Sval = euclid_str(ihits, isteps)
indx = itick % strlen(Sval)
xout strtol(strsub(Sval, indx, indx + 1))
endop
opcode euclidplay, 0, iiiSiip
ihits, isteps, itick, Sinstr, idur, ifreq, iamp xin
if(euclid(ihits, isteps, itick) == 1) then
schedule(Sinstr, 0, idur, ifreq, iamp)
endif
endop
opcode euclidplay, 0, iiSiip
ihits, isteps, Sinstr, idur, ifreq, iamp xin
itick = i(gk_clock_tick)
if(euclid(ihits, isteps, itick) == 1) then
schedule(Sinstr, 0, idur, ifreq, iamp)
endif
endop
;; Phase-based Oscillators
/** Returns cosine of given phase (0-1.0) */
opcode xcos, i,i
iphase xin
xout cos(2 * $M_PI * iphase)
endop
/** Range version of xcos, similar to Impromptu's cosr */
opcode xcos, i,iii
iphase, ioffset, irange xin
xout ioffset + (cos(2 * $M_PI * iphase) * irange)
endop
/** Returns sine of given phase (0-1.0) */
opcode xsin, i,i
iphase xin
xout sin(2 * $M_PI * iphase)
endop
/** Range version of xsin, similar to Impromptu's sinr */
opcode xsin, i,iii
iphase, ioffset, irange xin
xout ioffset + (sin(2 * $M_PI * iphase) * irange)
endop
/** Non-interpolating oscillator. Given phase in range 0-1,
returns value within the give k-array table. */
opcode xosc, i, ik[]
iphase, kvals[] xin
indx = int(lenarray:i(kvals) * (iphase % 1))
xout i(kvals, indx)
endop
/** Non-interpolating oscillator. Given phase duration in beats,
returns value within the give k-array table. (shorthand for xosc(phsb(ibeats), karr) )*/
opcode xoscb, i,ik[]
ibeats, kvals[] xin
xout xosc(phsb(ibeats), kvals)
endop
/** Non-interpolating oscillator. Given phase duration in measures,
returns value within the give k-array table. (shorthand for xosc(phsm(ibeats), karr) )*/
opcode xoscm, i, ik[]
ibeats, kvals[] xin
xout xosc(phsm(ibeats), kvals)
endop
/** Linearly-interpolating oscillator. Given phase in range 0-1,
returns value intepolated within the two closest points of phase within k-array
table. */
opcode xosci, i, ik[]
iphase, kvals[] xin
ilen = lenarray:i(kvals)
indx = ilen * (iphase % 1)
ibase = int(indx)
ifrac = indx - ibase
iv0 = i(kvals, ibase)
iv1 = i(kvals, (ibase + 1) % ilen)
xout iv0 + (iv1 - iv0) * ifrac
endop
/** Linearly-interpolating oscillator. Given phase duration in beats,
returns value intepolated within the two closest points of phase within k-array
table. (shorthand for xosci(phsb(ibeats), karr) )*/
opcode xoscib, i,ik[]
ibeats, kvals[] xin
xout xosci(phsb(ibeats), kvals)
endop
/** Linearly-interpolating oscillator. Given phase duration in measures,
returns value intepolated within the two closest points of phase within k-array
table. (shorthand for xosci(phsm(ibeats), karr) )*/
opcode xoscim, i,ik[]
ibeats, kvals[] xin
xout xosci(phsm(ibeats), kvals)
endop
/** Line (Ramp) oscillator. Given phase in range 0-1, return interpolated value between given istart and iend. */
opcode xlin, i, iii
iphase, istart, iend xin
xout istart + (iend - istart) * iphase
endop
;; Duration Sequences
/** Given a tick value and array of durations, returns new duration value for tick. */
opcode xoscd, i, ik[]
itick, kdurs[] xin
indx = 0
isum = 0
ilen = lenarray:i(kdurs)
ival = 0
while (indx < ilen) do
isum += i(kdurs, indx)
indx += 1
od
itick = itick % isum
indx = 0
ival = 0
icur = 0
while (indx < ilen) do
itemp = i(kdurs, indx)
if(itick < icur + itemp) then
ival = itemp
indx += ilen
else
icur += abs(itemp)
endif
indx += 1
od
xout ival
endop
/** Given an array of durations, returns new duration value for current clock tick. Useful with mod division and cycle for additive/subtractive rhythms. */
opcode xoscd, i, k[]
kdurs[] xin
xout xoscd(now_tick(), kdurs)
endop
/** Given a tick value and array of durations, returns new duration or 0 depending upon whether tick hits a new duration value. Values
may be positive or negative, but not zero. Negative values can be interpreted as rest durations. */
opcode dur_seq, i, ik[]
itick, kdurs[] xin
ival = 0
icur = 0
ilen = lenarray:i(kdurs)
itotal = 0
indx = 0
while (indx < ilen) do
itotal += abs:i(i(kdurs, indx))
indx += 1
od
;print itotal
indx = 0
itick = itick % itotal
while (indx < ilen) do
itemp = i(kdurs, indx)
if(icur == itick) then
ival = itemp
indx += ilen
elseif (icur > itick) then
indx += ilen
else
icur += abs(itemp)
endif
indx += 1
od
xout ival
endop
/** Given an array of durations, returns new duration or 0 depending upon
* whether current clock tick hits a new duration value. Values
may be positive or negative, but not zero. Negative values can be interpreted
as rest durations. */
opcode dur_seq, i, k[]
kdurs[] xin
xout dur_seq(now_tick(), kdurs)
endop
/** 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. */
opcode melodic, iii, ik[]k[]k[]
itick, kdurs[], kpchs[], kamps[] xin
idur = dur_seq(itick, kdurs)
ipch = 0
iamp = 0
indx = 0
itotal = 0
ilen = lenarray:i(kdurs)
while (indx < ilen) do
itotal += abs:i(i(kdurs, indx))
indx += 1
od
itick = itick % itotal
if(idur > 0) then
indx = 0
icur = 0
ivalindx = 0
while (indx < ilen) do
itemp = i(kdurs, indx)
if(icur == itick) then
indx += ilen
elseif (icur > itick) then
indx += ilen
else
if (itemp > 0) then
ivalindx += 1
endif
icur += abs(itemp)
endif
indx += 1
od
ipch = i(kpchs, ivalindx % lenarray:i(kpchs))
iamp = i(kamps, ivalindx % lenarray:i(kamps))
endif
xout idur, ipch, iamp
endop
/** 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. */
opcode melodic, iii, k[]k[]k[]
kdurs[], kpchs[], kamps[] xin
idur, ipch, iamp = melodic(now_tick(), kdurs, kpchs, kamps)
xout idur, ipch, iamp
endop
;; String functions
/**
rotate - Rotates string by irot number of values.
(Inspired by rotate from Charlie Roberts' Gibber.)
*/
opcode rotate, S, Si
Sval, irot xin
ilen = strlen(Sval)
irot = irot % ilen
Sout = strcat(strsub(Sval, irot, ilen), strsub(Sval, 0, irot))
xout Sout
endop
/** 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. */
opcode strrep, S, Si
Sval, inum xin
Sout = Sval
indx = 1
while (indx < inum) do
Sout = strcat(Sout, Sval)
indx += 1
od
xout Sout
endop
;; Channel Helper
/** Sets i-rate value into channel and sets initialization to true. Works together
with xchan */
opcode xchnset, 0, Si
SchanName, ival xin
Sinit = sprintf("%s_initialized", SchanName)
chnset(1, Sinit)
chnset(ival, SchanName)
endop
/** xchan
Initializes a channel with initial value if channel has default value of 0 and
then returns the current value from the channel. Useful in live coding to define
a dynamic point that will be automated or set outside of the instrument that is
using the channel.
Opcode is overloaded to return i- or k- value. Be sure to use xchan:i or xchan:k
to specify which value to use.
*/
opcode xchan, i,Si
SchanName, initVal xin
Sinit = sprintf("%s_initialized", SchanName)
if(chnget:i(Sinit) == 0) then
chnset(1, Sinit)
chnset(initVal, SchanName)
endif
xout chnget:i(SchanName)
endop
/** xchan
Initializes a channel with initial value if channel has default value of 0 and
then returns the current value from the channel. Useful in live coding to define
a dynamic point that will be automated or set outside of the instrument that is
using the channel.
Opcode is overloaded to return i- or k- value. Be sure to use xchan:i or xchan:k
to specify which value to use.
*/
opcode xchan, k,Si
SchanName, initVal xin
Sinit = sprintf("%s_initialized", SchanName)
if(chnget:i(SchanName) == 0) then
chnset(1, Sinit)
chnset(initVal, SchanName)
endif
xout chnget:k(SchanName)
endop
;; SCALE/HARMONY (experimental)
gi_scale_major[] = array(0, 2, 4, 5, 7, 9, 11)
gi_scale_minor[] = array(0, 2, 3, 5, 7, 8, 10)
gi_cur_scale[] = gi_scale_minor
gi_scale_base = 60
gi_chord_offset = 0
/** Set root note of scale in MIDI note number. */
opcode set_root, 0,i
iscale_root xin
gi_scale_base = iscale_root
endop
/** Calculate frequency from root note of scale, using
octave and pitch class. */
opcode from_root, i, ii
ioct, ipc xin
ival = gi_scale_base + (ioct * 12) + ipc
xout cpsmidinn(ival)
endop
/** Set the global scale. Currently supports "maj" for major and "min" for minor scales. */
opcode set_scale, 0,S
Scale xin
if(strcmp("maj", Scale) == 0) then
gi_cur_scale = gi_scale_major
else
gi_cur_scale = gi_scale_minor
endif
endop
/** Calculate frequency from root note of scale, using
octave and scale degree. */
opcode in_scale, i, ii
ioct, idegree xin
ibase = gi_scale_base + (ioct * 12)
idegrees = lenarray(gi_cur_scale)
ioct = int(idegree / idegrees)
indx = idegree % idegrees
if(indx < 0) then
ioct -= 1
indx += idegrees
endif
xout cpsmidinn(ibase + (ioct * 12) + gi_cur_scale[int(indx)])
endop
/** Calculate frequency from root note of scale, using
octave and scale degree. (k-rate version of opcode) */
opcode in_scale, k, kk
koct, kdegree xin
kbase = gi_scale_base + (koct * 12)
idegrees = lenarray(gi_cur_scale)
koct = int(kdegree / idegrees)
kndx = kdegree % idegrees
if(kndx < 0) then
koct -= 1
kndx += idegrees
endif
xout cpsmidinn(kbase + (koct * 12) + gi_cur_scale[int(kndx)])
endop
/** Quantizes given MIDI note number to the given scale
(Base on pc:quantize from Extempore) */
opcode pc_quantize, i, ii[]
ipitch_in, iscale[] xin
inotenum = round:i(ipitch_in)
ipc = inotenum % 12
iout = inotenum
indx = 0
while (indx < 7) do
if(contains(ipc + indx, iscale) == 1) then
iout = inotenum + indx
goto end
elseif (contains(ipc - indx, iscale) == 1) then
iout = inotenum - indx
goto end
endif
indx += 1
od
end:
xout iout
endop
/** Quantizes given MIDI note number to the current active scale
(Base on pc:quantize from Extempore) */
opcode pc_quantize, i, i
ipitch_in xin
ival = pc_quantize(ipitch_in, gi_cur_scale)
xout ival
endop
/* BELOW CHORD SYSTEM IS EXPERIMENTAL */
gi_chord_base = 0
gi_chord_maj[] = array(0,4,7)
gi_chord_maj7[] = array(0,4,7,11)
gi_chord_min[] = array(0,3,7)
gi_chord_min7[] = array(0,3,7,10)
gi_chord_dim[] = array(0,3,6)
gi_chord_dim7[] = array(0,3,6,9)
gi_chord_aug[] = array(0,4,8)
gi_chord_current[] = gi_chord_maj
opcode set_chord, 0, ii[]
ichord_root, ichord_intervals[] xin
gi_chord_base = ichord_root
gi_chord_current = ichord_intervals
endop
opcode set_chord, 0, S
Schord xin
endop
opcode in_chord, i, ii
ioct, idegree xin
ibase = gi_scale_base + (ioct * 12) + gi_chord_base
idegrees = lenarray(gi_chord_current)
ioct = int(idegree / idegrees)
indx = idegree % idegrees
if(indx < 0) then
ioct -= 1
indx += idegrees
endif
xout cpsmidinn(ibase + (ioct * 12) + gi_chord_current[indx])
endop
;; AUDIO
/** Utility opcode for declicking an audio signal. Should only be used in instruments that have positive p3 duration. */
opcode declick, a, a
ain xin
aenv = linseg:a(0, 0.01, 1, p3 - 0.02, 1, 0.01, 0, 0.01, 0)
xout ain * aenv
endop
/** Custom non-interpolating oscil that takes in kfrequency and array to use as oscillator table
data. Outputs k-rate signal. */
opcode oscil, k, kk[]
kfreq, kin[] xin
ilen = lenarray(kin)
kphs = phasor:k(kfreq)
kout = kin[int(kphs * ilen)]
xout kout
endop
;; KILLING INSTANCES
instr KillImpl
Sinstr = p4
if (nstrnum(Sinstr) > 0) then
turnoff2(Sinstr, 0, 0)
endif
turnoff
endin
/** Turns off running instances of named instruments. Useful when livecoding
audio and control signal process instruments. May not be effective if for
temporal recursion instruments as they may be non-running but scheduled in the
event system. In those situations, try using clear_instr to overwrite the
instrument definition. */
opcode kill, 0,S
Sinstr xin
schedule("KillImpl", 0, 0.01, Sinstr)
endop
/** Redefines instr to empty body. Useful for killing
temporal recursion or clock callback functions */
opcode clear_instr, 0,S
Sinstr xin
Sinstr_body = sprintf("instr %s\nendin\n", Sinstr)
ires = compilestr(Sinstr_body)
prints(sprintf("Cleared instrument definition: %s\n",
Sinstr))
endop
/** Starts running a named instrument for indefinite time using p2=0 and p3=-1.
Will first turnoff any instances of existing named instrument first. Useful
when livecoding always-on audio and control signal process instruments. */
opcode start, 0,S
Sinstr xin
if (nstrnum(Sinstr) > 0) then
kill(Sinstr)
schedule(Sinstr, ksmps / sr,-1)
endif
endop
/** Stops a running named instrument, allowing for release segments to operate. */
opcode stop, 0,S
Sinstr xin
if (nstrnum(Sinstr) > 0) then
schedule(-nstrnum(Sinstr), 0, 0)
endif
endop
instr CodeEval
Scode = p4
ires = compilestr(Scode)
endin
/** Evaluate code at a given time */
opcode eval_at_time, 0, Si
Scode, istart xin
iblock init ksmps / sr
;; adjust one block of time difference since this is
;; will need to be added as an event back on to the scheduler
schedule("CodeEval", max:i(0, istart - iblock), 0, Scode)
endop
;; Fades
gi_fade_range init -30
/** Sets the range in db to fade over. By default, range is -30 (i.e., fades from -30dbfs to 0dbfs) */
opcode set_fade_range, 0, i
irange xin
gi_fade_range init irange
endop
/** 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.) */
opcode fade_in, i, ii
ident, inumticks xin
Schan = sprintf("fade_chan_%d", ident)
ival = chnget:i(Schan)
if(ival < 1.0) then
ival = limit:i(ival + (1 / inumticks), 0, 1.0)
chnset(ival, Schan)
iret = ampdbfs((1- ival) * gi_fade_range)
else
iret = ival
endif
xout iret
endop
/** 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.) */
opcode fade_out, i, ii
ident, inumticks xin
Schan = sprintf("fade_chan_%d", ident)
ival = chnget:i(Schan)
iret init 0
if(ival > 0.0) then
ival = limit:i(ival - (1 / inumticks), 0, 1.0)
chnset(ival, Schan)
iret = ampdbfs((1- ival) * gi_fade_range)
else
iret = ival
endif
xout iret
endop
/** Read value from fade channel. Useful if copy/pasting then wanting to just read from fade and control in the original code. */
opcode fade_read, i, i
ident xin
Schan = sprintf("fade_chan_%d", ident)
iret = chnget:i(Schan)
xout iret
endop
/** Set value for fade channel to given value. Should be in range 0-1.0. (Typically one sets to either 0 or 1.) */
opcode set_fade, 0,ii
ident, ival xin
Schan = sprintf("fade_chan_%d", ident)
ival = limit:i(ival, 0, 1.0)
chnset(ival, Schan)
endop
;; Stereo Audio Bus
ga_sbus[] init 16, 2
/** Write two audio signals into stereo bus at given index */
opcode sbus_write, 0,iaa
ibus, al, ar xin
ga_sbus[ibus][0] = al
ga_sbus[ibus][1] = ar
endop
/** Mix two audio signals into stereo bus at given index */
opcode sbus_mix, 0,iaa
ibus, al, ar xin
ga_sbus[ibus][0] = ga_sbus[ibus][0] + al
ga_sbus[ibus][1] = ga_sbus[ibus][1] + ar
endop
/** Clear audio signals from bus channel */
opcode sbus_clear, 0, i
ibus xin
aclear init 0
ga_sbus[ibus][0] = aclear
ga_sbus[ibus][1] = aclear
endop
/** Read audio signals from bus channel */
opcode sbus_read, aa, i
ibus xin
aclear init 0
al = ga_sbus[ibus][0]
ar = ga_sbus[ibus][1]
xout al, ar
endop
;; MIXER
gi_reverb_mixer_on init 0
/** Always-on Mixer instrument with Reverb send channel. Use start("ReverbMixer") to run. Designed
for use with pan_verb_mix to simplify signal-based live coding. */
instr ReverbMixer
gi_reverb_mixer_on init 1
;; dry and reverb send signals
a1, a2 sbus_read 0
a3, a4 sbus_read 1
al, ar reverbsc a3, a4, xchan:k("Reverb.fb", 0.7), xchan:k("Reverb.cut", 12000)
kamp = xchan:k("Mix.amp", 1.0)
a1 = tanh(a1 + al) * kamp
a2 = tanh(a2 + ar) * kamp
out(a1, a2)
sbus_clear(0)
sbus_clear(1)
endin
/** Always-on Mixer instrument with Reverb send channel and feedback delay. Use start("FBReverbMixer") to run. Designed
for use with pan_verb_mix to simplify signal-based live coding. */
instr FBReverbMixer
al, ar sbus_read 0
afb0 init 0
afb1 init 0
gi_reverb_mixer_on init 1
;; dry and reverb send signals
a1, a2 sbus_read 0
a3, a4 sbus_read 1
al, ar reverbsc a3, a4, xchan:k("Reverb.fb", 0.7), xchan:k("Reverb.cut", 12000)
a1 = tanh(a1 + al)
a2 = tanh(a2 + ar)
a1 += afb0
a2 += afb1
kfb_amt = xchan:k("FB.amt", 0.9)
kfb_dur = xchan:k("FB.dur", 4.2) * 1000 ;; time in ms
afb0 = vdelay(a1 * kfb_amt, kfb_dur, 10000)
afb1 = vdelay(a2 * kfb_amt, kfb_dur, 10000)
kamp = xchan:k("Mix.amp", 1.0)
a1 *= kamp
a2 *= kamp
out(a1, a2)
sbus_clear(0)
sbus_clear(1)
endin
/** Utility opcode to pan signal, send dry to mixer, and send amount
of signal to reverb. If ReverbMixer is not on, will output just
panned signal using out opcode. */
opcode pan_verb_mix, 0,akk
asig, kpan, krvb xin
;; Panning and send to mixer
al, ar pan2 asig, kpan
if(gi_reverb_mixer_on == 1) then
sbus_mix(0, al, ar)
sbus_mix(1, al * krvb, ar * krvb)
else
out(al, ar)
endif
endop
/** Utility opcode to send dry stereo to mixer and send amount
of stereo signal to reverb. If ReverbMixer is not on, will output just
panned signal using out opcode. */
opcode reverb_mix, 0, aak
al, ar, krvb xin
if(gi_reverb_mixer_on == 1) then
sbus_mix(0, al, ar)
sbus_mix(1, al * krvb, ar * krvb)
else
out(al, ar)
endif
endop
;; Automation
/** Set a channel value at a given time. p4=ChannelName, p5=value*/
instr ChnSet
Schan = p4
ival = p5
chnset(ival, Schan)
endin
/** Automation instrument for channels. Takes in "ChannelName", start value, end value, and automation type (0=linear, else exponential). */
instr Auto
Schan = p4
istart = p5
iend = p6
itype = p7
kauto init 0
if(itype == 0) then
kauto = line:k(istart, p3, iend)
else
kauto = expon:k(istart, p3, iend)
endif
chnset(kauto, Schan)
endin
/** 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. */
opcode automate, 0, Siiii
Schan, idur, istart, iend, itype xin
schedule("Auto", 0, idur, Schan, istart, iend, itype)
endop
instr FadeOutMix
kauto = ampdbfs:k(line:k(0, p3, -60))
chnset(kauto, "Mix.amp")
endin
/** Utility opcode for end of performances to fade out Mixer over given idur time. idur defaults to 30 seconds. **/
opcode fade_out_mix, 0, o
idur xin
idur = (idur <= 0 ? 30 : idur)
schedule("FadeOutMix", 0, idur)
schedule("ChnSet", idur + 0.1, 0, "Mix.amp", 0)
endop
;; DSP
/** Saturation using tanh */
opcode saturate, a, ak
asig, ksat xin
xout tanh(asig * ksat) / tanh(ksat)
endop
;; SYNTHS
xchnset("rvb.default", 0.1)
xchnset("drums.rvb.default", 0.1)
/** Substractive Synth, 3osc */
instr Sub1
asig = vco2(ampdbfs(-12), p4)
asig += vco2(ampdbfs(-12), p4 * 1.01, 10)
asig += vco2(ampdbfs(-12), p4 * 2, 10)
asig = zdf_ladder(asig, expon(10000, p3, 400), 5)
asig = declick(asig) * p5
pan_verb_mix(asig, xchan:i("Sub1.pan", 0.5), xchan:i("Sub1.rvb", chnget:i("rvb.default")))
endin
/** Subtractive Synth, two saws, fifth freq apart */
instr Sub2
icut = xchan:i("Sub2.cut", sr / 3)
asig = vco2(ampdbfs(-12), p4)
asig += vco2(ampdbfs(-12), p4 * 1.5)
asig = zdf_ladder(asig, expon(icut, p3, 400), 5)
asig = declick(asig) * p5
pan_verb_mix(asig, xchan:i("Sub2.pan", 0.5), xchan:i("Sub2.rvb", chnget:i("rvb.default")))
endin
/** Subtractive Synth, three detuned saws, swells in */
instr Sub3
asig = vco2(p5, p4)
asig += vco2(p5, p4 * 1.01)
asig += vco2(p5, p4 * 0.995)
asig *= 0.33
asig = zdf_ladder(asig, expon(100, p3, 22000), 12)
asig = declick(asig)
pan_verb_mix(asig, xchan:i("Sub3.pan", 0.5), xchan:i("Sub3.rvb", chnget:i("rvb.default")))
endin
/** Subtractive Synth, detuned square/saw, stabby.
Nice as a lead in octave 2, nicely grungy in octave -2, -1
*/
instr Sub4
asig = vco2(0.5, p4 * 2)
asig += vco2(0.5, p4 * 2.01, 10)
asig += vco2(1, p4, 10)
asig += vco2(1, p4 * 0.99)
itarget = p4 * 2
asig = zdf_ladder(asig, expseg(20000, 0.15, itarget, 0.1, itarget), 5)
asig = declick(asig) * p5 * 0.15
pan_verb_mix(asig, xchan:i("Sub4.pan", 0.5), xchan:i("Sub4.rvb", chnget:i("rvb.default")))
endin
/** Subtractive Synth, detuned square/triangle */
instr Sub5
asig = vco2(0.5, p4, 10)
asig += vco2(0.25, p4 * 2.0001, 12)
asig = zdf_ladder(asig, expseg(10000, 0.1, 500, 0.1, 500), 2)
asig = declick(asig) * p5 * 0.75
pan_verb_mix(asig, xchan:i("Sub5.pan", 0.5), xchan:i("Sub5.rvb", chnget:i("rvb.default")))
endin
/** Subtractive Synth, saw, K35 filters */
instr Sub6
asig = vco2(p5, p4)
asig = K35_hpf(asig, limit:i(p4, 30, 16000), 1)
asig = K35_lpf(asig, expseg:k(12000, p3, limit:i(p4 * 8, 30, 12000)), 2.5)
asig = saturate(asig, 4.5)
asig *= p5 * 0.5
asig = declick(asig)
pan_verb_mix(asig, xchan:i("Sub6.pan", 0.5), xchan:i("Sub6.rvb", chnget:i("rvb.default")))
endin
/** Subtractive Synth, saw + tri, K35 filters */
instr Sub7
asig = vco2(p5, p4)
asig += vco2(p5, p4 * 2, 4, 0.5)
asig = K35_hpf(asig, limit:i(p4, 30, 16000), 1)
asig = K35_lpf(asig, expseg:k(12000, p3, limit:i(p4 * 8, 30, 12000)), 2.5)
asig = saturate(asig, 4.5)
asig *= p5 * 0.3
asig = declick(asig)
pan_verb_mix(asig, xchan:i("Sub7.pan", 0.5), xchan:i("Sub7.rvb", chnget:i("rvb.default")))
endin
/** SynthBrass subtractive synth */
instr SynBrass
ipch = p4
asig = vco2(0.25, ipch)
asig += vco2(0.25, ipch * 2.00)
asig = zdf_ladder(asig, expseg(12000, 0.25, 500, 0.05, 500), 4)
asig = declick(asig * p5)
pan_verb_mix(asig, xchan:i("SynBrass.pan", 0.5), xchan:i("SynBrass.rvb", chnget:i("rvb.default")))
endin
/** SuperSaw sound using 9 bandlimited saws (3 sets of detuned saws at octaves)*/
instr SSaw
asig = vco2(1, p4)
asig += vco2(1, p4 * cent(9.04234))
asig += vco2(1, p4 * cent(-7.214342))
asig += vco2(1, p4 * cent(1206.294143))
asig += vco2(1, p4 * cent(1193.732))
asig += vco2(1, p4 * cent(1200))
asig += vco2(1, p4 * cent(2406.294143))
asig += vco2(1, p4 * cent(2393.732))
asig += vco2(1, p4 * cent(2400))
asig *= 0.1
asig = zdf_ladder(asig, expseg(16000, p3 - 0.05, 16000, 0.05, 200), 0.5)
asig *= p5
asig = declick(asig)
pan_verb_mix(asig, xchan:i("SSaw.pan", 0.5), xchan:i("SSaw.rvb", chnget:i("rvb.default")))
endin
/** Modal Synthesis Instrument: Percussive/organ-y sound */
instr Mode1
asig = mpulse(p5, 0)
asig1 = mode(asig, p4, p4 * 0.5)
asig1 += mode(asig, p4 * 2, p4 * 0.25)
asig1 += mode(asig, p4 * 4, p4 * 0.125)
asig = declick(asig1)
pan_verb_mix(asig, xchan:i("Mode1.pan", 0.5), xchan:i("Mode1.rvb", chnget:i("rvb.default")))
endin
/** Pluck sound using impulses, noise, and waveguides*/
instr Plk
asig = mpulse(p5, 1 / p4)
asig += random:a(-0.1, 0.1) * expseg(p5, 0.02, 0.001, p3, 0.001)
aout wguide1 asig, 1/ p4, 10000, 0.8
aout += wguide1(asig, 1/ (2 * p4), 12000, 0.6)
aout = K35_hpf(aout, p4, 0.5)
aout = zdf_ladder(aout, expon(10000, p3, 100), 3)
aout = dcblock2(aout)
asig = declick(aout)
pan_verb_mix(asig, xchan:i("Plk.pan", 0.5), xchan:i("Plk.rvb", chnget:i("rvb.default")))
endin
gi_organ1 = ftgen(0, 0, 65536, 10, 1, 0.5, 0.3, 0.2, 0.05, 0.015)
/** Wavetable Organ sound using additive synthesis */
instr Organ1
asig = oscili(p5, p4, gi_organ1)
asig *= 0.5
asig = declick(asig)
pan_verb_mix(asig, xchan:i("Organ1.pan", 0.5), xchan:i("Organ1.rvb", chnget:i("rvb.default")))
endin
/** Organ sound based on M1 Organ 2 patch */
instr Organ2
asig = vco2(1, p4, 4, 0.25)
asig += vco2(0.8, p4 * 2, 12)
asig += vco2(0.3, p4 * 3, 10)
icutStart = limit:i(xchan:i("Organ2.cut", 2000), 40, sr * 1/2)
icutEnd = limit:i(xchan:i("Organ2.cutEnd", 500), 40, sr * 1/2)
asig = zdf_ladder(asig, expseg(icutStart, 0.08, icutEnd, p3, icutEnd), 2)
asig *= p5 * 0.67
asig = declick(asig)
pan_verb_mix(asig, xchan:i("Organ2.pan", 0.5), xchan:i("Organ2.rvb", chnget:i("rvb.default")))
endin
/** 303-style Bass sound */
instr Bass
acut = 200 + expon(1, p3, 0.001) * 16000
asig = vco2(1, p4)
asig = diode_ladder(asig, acut, 10, 1, 4)
asig = tanh(asig * 4) * p5 * 0.5
asig = declick(asig)
pan_verb_mix(asig, xchan:i("Bass.pan", 0.5), xchan:i("Bass.rvb", chnget:i("rvb.default")))
endin
/** MS20-style Bass Sound */
instr ms20_bass
ipch = p4
iamp = p5
aenv = expseg(1000, 0.1, ipch * 2, p3 - .05, ipch * 2)
asig = vco2(1.0, ipch)
asig = K35_hpf(asig, ipch, 5, 0, 1)
asig = K35_lpf(asig, aenv, 8, 0, 1)
asig *= expon:a(iamp, p3, 0.0001)
pan_verb_mix(asig, xchan:i("ms20_bass.pan", 0.5), xchan:i("ms20_bass.rvb", chnget:i("rvb.default")))
endin
/** VoxHumana Patch */
instr VoxHumana
ipch = p4
iamp = p5
aenv = transegr:a(0, 0.453, 1, 1.0, 2.242, -1, 0)
klfo_pulse_width = lfo(0.125, 5.72, 1)
klfo_saw = lfo(0.021, 5.04, 1)
klfo_pulse = lfo(0.013, 3.5, 1)
asaw = vco2(iamp, ipch * (1 + klfo_saw))
apulse = vco2(iamp, ipch * (1.00004 + klfo_pulse), 2, 0.625 + klfo_pulse_width)
aout = sum(asaw, apulse) * 0.0625 * aenv
ikeyfollow = 1 + exp( (ipch - 50) / 10000)
aout = butterlp(aout, 1986 * ikeyfollow)
pan_verb_mix(aout, xchan:i("VoxHumana.pan", 0.5), xchan:i("VoxHumana.rvb", chnget:i("rvb.default")))
endin
/** FM 3:1 C:M ratio, 2->0.025 index, nice for bass */
instr FM1
icar = xchan("FM1.car", 1)
imod = xchan("FM1.mod", 3)
asig = foscili(p5, p4, icar, imod, expon(2, 0.2, 0.025))
asig = declick(asig) * 0.5
pan_verb_mix(asig, xchan:i("FM1.pan", 0.5), xchan:i("FM1.rvb", chnget:i("rvb.default")))
endin
/** Filtered noise, exponential envelope */
instr Noi
p3 = max:i(p3, 0.4)
asig = pinker() * p5 * expon(1, p3, 0.001) * 0.1
a1 = mode(asig, p4, 80)
a2 = mode(asig, p4 * 2, 40)
a3 = mode(asig, p4 * 3, 30)
a4 = mode(asig, p4 * 4, 20)
asig sum a1, a2, a3, a4
asig = declick(asig) * 0.25
pan_verb_mix(asig, xchan:i("Noi.pan", 0.5), xchan:i("Noi.rvb", chnget:i("rvb.default")))
endin
/** Wobble patched based on Jacob Joaquin's "Tempo-Synced Wobble Bass" */
instr Wobble
/*p3 = max:i(p3, 0.4) */
itri = chnget:i("Wobble.triangle")
if(itri == 0) then
;; unipolar triangle
itri = ftgen(0, 0, 8192, -7, 0, 4096, 1, 4096, 0)
chnset(itri, "Wobble.triangle")
endif
;; dur in ticks (16ths) for wobble lfo
iticks = xchan("Wobble.ticks", 2)
;; modulation max
imod = p4 * 8
klfo = oscili:k(1, 1 / ticks(iticks), itri)
asig = vco2(p5, p4 * 2.018)
asig += vco2(p5, p4, 10)
asig = zdf_ladder(asig, min:k(p4 + (imod * klfo), 22000), 12)
asig *= expon(1, beats(16), 0.001)
asig = declick(asig)
pan_verb_mix(asig, xchan:i("Wobble.pan", 0.5), xchan:i("Wobble.rvb", chnget:i("rvb.default")))
endin
/** Simple Sinewave instrument with exponential envelope */
instr Sine
asig = oscili(expon:a(p5, p3, 0.001), p4)
pan_verb_mix(asig, xchan:i("Sine.pan", 0.5), xchan:i("Sine.rvb", chnget:i("rvb.default")))
endin
;; SQUINE WAVE SYNTHS
/** Squinewave Synth, 2 osc */
instr Squine1
asig squinewave a(p4), expon:a(.8, p3, .1), expon:a(.9, p3, .5), 0, 4
a2 squinewave a(p4 * 1.0019234234), expseg:a(.8, p3, .6), a(0), 0, 4
asig = (asig + a2 * 0.05) * p5 * 0.5
asig = butterhp(asig, p4)
asig *= linen:a(1, .015, p3, .02)
asig = dcblock2(asig)
pan_verb_mix(asig, xchan:i("Squine1.pan", 0.5), xchan:i("Squine1.rvb", chnget:i("rvb.default")))
endin
gi_lc_sine = ftgen(0, 0, 65536, 10, 1)
/** Formant Synth, buzz source, soprano ah formants */
instr Form1
iamp = p5
ifreq = p4
asig = buzz(1, ifreq * (1 + lfo(.003, 4)), (sr / 2) / ifreq, gi_lc_sine)
a1 = butterbp(asig, 800, 80)
a2 = butterbp(asig * ampdbfs(-6), 1150, 90)
a3 = butterbp(asig * ampdbfs(-32), 2900 , 120)
a4 = butterbp(asig * ampdbfs(-20), 3900, 130)
a5 = butterbp(asig * ampdbfs(-50), 4950, 140)
asig = a1 + a2 + a3 + a4 + a5
asig *= 35 * iamp * adsr(0.05, 0, 1, 0.01)
pan_verb_mix(asig, xchan:i("Form1.pan", 0.5), xchan:i("Form1.rvb", chnget:i("rvb.default")))
endin
;; MONOPHONIC SYNTHS
/** Monophone synth using sawtooth wave and 4pole lpf. Use "start("Mono") to run the monosynth, then use MonoNote instrument to play the instrument. */
instr Mono
asig = vco2(xchan:k("Mono.amp", 0.0), portk(xchan:k("Mono.freq", 60), xchan:k("Mono.glide", 0.02)))
asig = zdf_ladder(asig, xchan:k("Mono.cut", 4000), xchan:k("Mono.Q", 10))
kpan = xchan:k("Mono.pan", 0.5)
aL,aR pan2 asig,kpan
pan_verb_mix(asig, xchan:k("Mono.pan", 0.5), xchan:k("Mono.rvb", chnget:i("rvb.default")))
endin
maxalloc("Mono", 1)
/** Note playing instrument for Mono synth. Be careful to use this
and not try to create multiple Mono instruments! */
instr MonoNote
chnset(expon(p5, p3, 0.001), "Mono.amp")
chnset(p4, "Mono.freq")
endin
;; DRUMS
/** Modified clap instrument by Istvan Varga (clap1.orc) */
instr Clap
ifreq = p4 ;; ignore
iamp = p5
ibpfrq = 1046.5 /* bandpass filter frequency */
kbpbwd = port:k(ibpfrq*0.25, 0.03, ibpfrq*4.0) /* bandpass filter bandwidth */
idec = 0.5 /* decay time */
a1 = 1.0
a1_ delay1 a1
a1 = a1 - a1_
a2 delay a1, 0.011
a3 delay a1, 0.023
a4 delay a1, 0.031
a1 tone a1, 60.0
a2 tone a2, 60.0
a3 tone a3, 60.0
a4 tone a4, 1.0 / idec
aenv1 = a1 + a2 + a3 + a4*60.0*idec
a_ unirand 2.0
a_ = aenv1 * (a_ - 1.0)
a_ butterbp a_, ibpfrq, kbpbwd
aout = a_ * 80 * iamp ;;
pan_verb_mix(aout, xchan:k("Clap.pan", 0.7), xchan:k("Clap.rvb", chnget:i("drums.rvb.default")))
endin
gi_808_sine ftgen 0,0,1024,10,1 ;A SINE WAVE
gi_808_cos ftgen 0,0,65536,9,1,1,90 ;A COSINE WAVE
/** Bass Drum - From Iain McCurdy's TR-808.csd */
instr BD ;BASS DRUM
p3 = 2 * xchan("BD.decay", 0.5) ;NOTE DURATION. SCALED USING GUI 'Decay' KNOB
ilevel = xchan("BD.level", 1) * 2
itune = xchan("BD.tune", 0)
;SUSTAIN AND BODY OF THE SOUND
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.
kbend = transeg(0.5,1.2,-4, 0,1,0,0) ;SLIGHT PITCH BEND AT THE START OF THE NOTE
asig = gbuzz(0.5,50*octave(itune)*semitone(kbend),20,1,kmul,gi_808_cos) ;GBUZZ TONE
aenv = transeg:a(1,p3-0.004,-6,0) ;AMPLITUDE ENVELOPE FOR SUSTAIN OF THE SOUND
aatt = linseg:a(0,0.004,1, .01, 1) ;SOFT ATTACK
asig= asig*aenv*aatt
;HARD, SHORT ATTACK OF THE SOUND
aenv = linseg:a(1,0.07,0, .01, 0) ;AMPLITUDE ENVELOPE (FAST DECAY)
acps = expsega(400,0.07,0.001,1,0.001) ;FREQUENCY OF THE ATTACK SOUND. QUICKLY GLISSES FROM 400 Hz TO SUB-AUDIO
aimp = oscili(aenv,acps*octave(itune*0.25),gi_808_sine) ;CREATE ATTACK SOUND
amix = ((asig*0.5)+(aimp*0.35))*ilevel*p5 ;MIX SUSTAIN AND ATTACK SOUND ELEMENTS AND SCALE USING GUI 'Level' KNOB
pan_verb_mix(amix, xchan:k("BD.pan", 0.5), xchan:k("BD.rvb", chnget:i("drums.rvb.default")))
endin
/** Snare Drum - From Iain McCurdy's TR-808.csd */
instr SD ;SNARE DRUM
;SOUND CONSISTS OF TWO SINE TONES, AN OCTAVE APART AND A NOISE SIGNAL
idur = xchan("SD.decay", 1.0)
ilevel = xchan("SD.level", 1)
itune = xchan("SD.tune", 0)
ifrq = 342 ;FREQUENCY OF THE TONES
iNseDur = 0.3 * idur ;DURATION OF THE NOISE COMPONENT
iPchDur = 0.1 * idur ;DURATION OF THE SINE TONES COMPONENT
p3 = iNseDur ;p3 DURATION TAKEN FROM NOISE COMPONENT DURATION (ALWATS THE LONGEST COMPONENT)
;SINE TONES COMPONENT
aenv1 = expseg(1, iPchDur, 0.0001, p3-iPchDur, 0.0001) ;AMPLITUDE ENVELOPE
apitch1 = oscili(1, ifrq * octave(itune), gi_808_sine) ;SINE TONE 1
apitch2 = oscili(0.25, ifrq * 0.5 * octave(itune), gi_808_sine) ;SINE TONE 2 (AN OCTAVE LOWER)
apitch = (apitch1+apitch2)*0.75 ;MIX THE TWO SINE TONES
;NOISE COMPONENT
aenv2 = expon(1,p3,0.0005) ;AMPLITUDE ENVELOPE
anoise = noise(0.75, 0) ;CREATE SOME NOISE
anoise = butbp(anoise, 10000*octave(itune), 10000) ;BANDPASS FILTER THE NOISE SIGNAL
anoise = buthp(anoise, 1000) ;HIGHPASS FILTER THE NOISE SIGNAL
kcf = expseg(5000, 0.1, 3000, p3-0.2, 3000) ;CUTOFF FREQUENCY FOR A LOWPASS FILTER
anoise = butlp(anoise,kcf) ;LOWPASS FILTER THE NOISE SIGNAL
amix = ((apitch*aenv1)+(anoise*aenv2))*ilevel*p5 ;MIX AUDIO SIGNALS AND SCALE ACCORDING TO GUI 'Level' CONTROL
pan_verb_mix(amix, xchan:k("SD.pan", 0.5), xchan:k("SD.rvb", chnget:i("drums.rvb.default")))
endin
/** Open High Hat - From Iain McCurdy's TR-808.csd */
instr OHH ;OPEN HIGH HAT
idur = xchan("OHH.decay", 1.0)
ilevel = xchan("OHH.level", 1)
itune = xchan("OHH.tune", 0)
ioct = octave:i(itune)
kFrq1 = 296*ioct ;FREQUENCIES OF THE 6 OSCILLATORS
kFrq2 = 285*ioct
kFrq3 = 365*ioct
kFrq4 = 348*ioct
kFrq5 = 420*ioct
kFrq6 = 835*ioct
p3 = 0.5*idur ;DURATION OF THE NOTE
;SOUND CONSISTS OF 6 PULSE OSCILLATORS MIXED WITH A NOISE COMPONENT
;PITCHED ELEMENT
aenv linseg 1,p3-0.05,0.1,0.05,0 ;AMPLITUDE ENVELOPE FOR THE PULSE OSCILLATORS
ipw = 0.25 ;PULSE WIDTH
a1 vco2 0.5,kFrq1,2,ipw ;PULSE OSCILLATORS...
a2 vco2 0.5,kFrq2,2,ipw
a3 vco2 0.5,kFrq3,2,ipw
a4 vco2 0.5,kFrq4,2,ipw
a5 vco2 0.5,kFrq5,2,ipw
a6 vco2 0.5,kFrq6,2,ipw
amix sum a1,a2,a3,a4,a5,a6 ;MIX THE PULSE OSCILLATORS
amix reson amix,5000*ioct,5000,1 ;BANDPASS FILTER THE MIXTURE
amix buthp amix,5000 ;HIGHPASS FILTER THE SOUND...
amix buthp amix,5000 ;...AND AGAIN
amix = amix*aenv ;APPLY THE AMPLITUDE ENVELOPE
;NOISE ELEMENT
anoise noise 0.8,0 ;GENERATE SOME WHITE NOISE
aenv linseg 1,p3-0.05,0.1,0.05,0 ;CREATE AN AMPLITUDE ENVELOPE
kcf expseg 20000,0.7,9000,p3-0.1,9000 ;CREATE A CUTOFF FREQ. ENVELOPE
anoise butlp anoise,kcf ;LOWPASS FILTER THE NOISE SIGNAL
anoise buthp anoise,8000 ;HIGHPASS FILTER THE NOISE SIGNAL
anoise = anoise*aenv ;APPLY THE AMPLITUDE ENVELOPE
;MIX PULSE OSCILLATOR AND NOISE COMPONENTS
amix = (amix+anoise)*ilevel*p5*0.55
pan_verb_mix(amix, xchan:k("OHH.pan", 0.5), xchan:k("OHH.rvb", chnget:i("drums.rvb.default")))
endin
/** Closed High Hat - From Iain McCurdy's TR-808.csd */
instr CHH ;CLOSED HIGH HAT
idur = xchan("CHH.decay", 1.0)
ilevel = xchan("CHH.level", 1)
itune = xchan("CHH.tune", 0)
ioct = octave:i(itune)
kFrq1 = 296*ioct ;FREQUENCIES OF THE 6 OSCILLATORS
kFrq2 = 285*ioct
kFrq3 = 365*ioct
kFrq4 = 348*ioct
kFrq5 = 420*ioct
kFrq6 = 835*ioct
idur = 0.088*idur ;DURATION OF THE NOTE
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)
iohh = nstrnum("OHH")
iactive = active(iohh) ;SENSE ACTIVITY OF PREVIOUS INSTRUMENT (OPEN HIGH HAT)
if iactive>0 then ;IF 'OPEN HIGH HAT' IS ACTIVE...
turnoff2 iohh,0,0 ;TURN IT OFF (CLOSED HIGH HAT TAKES PRESIDENCE)
endif
;PITCHED ELEMENT
aenv expsega 1,idur,0.001,1,0.001 ;AMPLITUDE ENVELOPE FOR THE PULSE OSCILLATORS
ipw = 0.25 ;PULSE WIDTH
a1 vco2 0.5,kFrq1,2,ipw ;PULSE OSCILLATORS...
a2 vco2 0.5,kFrq2,2,ipw
a3 vco2 0.5,kFrq3,2,ipw
a4 vco2 0.5,kFrq4,2,ipw
a5 vco2 0.5,kFrq5,2,ipw
a6 vco2 0.5,kFrq6,2,ipw
amix sum a1,a2,a3,a4,a5,a6 ;MIX THE PULSE OSCILLATORS
amix reson amix,5000*ioct,5000,1 ;BANDPASS FILTER THE MIXTURE
amix buthp amix,5000 ;HIGHPASS FILTER THE SOUND...
amix buthp amix,5000 ;...AND AGAIN
amix = amix*aenv ;APPLY THE AMPLITUDE ENVELOPE
;NOISE ELEMENT
anoise noise 0.8,0 ;GENERATE SOME WHITE NOISE
aenv expsega 1,idur,0.001,1,0.001 ;CREATE AN AMPLITUDE ENVELOPE
kcf expseg 20000,0.7,9000,idur-0.1,9000 ;CREATE A CUTOFF FREQ. ENVELOPE
anoise butlp anoise,kcf ;LOWPASS FILTER THE NOISE SIGNAL
anoise buthp anoise,8000 ;HIGHPASS FILTER THE NOISE SIGNAL
anoise = anoise*aenv ;APPLY THE AMPLITUDE ENVELOPE
;MIX PULSE OSCILLATOR AND NOISE COMPONENTS
amix = (amix+anoise)*ilevel*p5*0.55
pan_verb_mix(amix, xchan:k("CHH.pan", 0.5), xchan:k("CHH.rvb", chnget:i("drums.rvb.default")))
endin
/** High Tom - From Iain McCurdy's TR-808.csd */
instr HiTom ;HIGH TOM
idur = xchan("HiTom.decay", 1.0)
ilevel = xchan("HiTom.level", 1)
itune = xchan("HiTom.tune", 0)
ioct = octave:i(itune)
ifrq = 200 * ioct ;FREQUENCY
p3 = 0.5 * idur ;DURATION OF THIS NOTE
;SINE TONE SIGNAL
aAmpEnv transeg 1,p3,-10,0.001 ;AMPLITUDE ENVELOPE FOR SINE TONE SIGNAL
afmod expsega 5,0.125/ifrq,1,1,1 ;FREQUENCY MODULATION ENVELOPE. GIVES THE TONE MORE OF AN ATTACK.
asig oscili -aAmpEnv*0.6,ifrq*afmod,gi_808_sine ;SINE TONE SIGNAL
;NOISE SIGNAL
aEnvNse transeg 1,p3,-6,0.001 ;AMPLITUDE ENVELOPE FOR NOISE SIGNAL
anoise dust2 0.4, 8000 ;GENERATE NOISE SIGNAL
anoise reson anoise,400*ioct,800,1 ;BANDPASS FILTER THE NOISE SIGNAL
anoise buthp anoise,100*ioct ;HIGHPASS FILTER THE NOSIE SIGNAL
anoise butlp anoise,1000*ioct ;LOWPASS FILTER THE NOISE SIGNAL
anoise = anoise * aEnvNse ;SCALE NOISE SIGNAL WITH AMPLITUDE ENVELOPE
;MIX THE TWO SOUND COMPONENTS
amix = (asig + anoise)*ilevel*p5
pan_verb_mix(amix, xchan:k("HiTom.pan", 0.5), xchan:k("HiTom.rvb", chnget:i("drums.rvb.default")))
endin
/** Mid Tom - From Iain McCurdy's TR-808.csd */
instr MidTom ;MID TOM
idur = xchan("MidTom.decay", 1.0)
ilevel = xchan("MidTom.level", 1)
itune = xchan("MidTom.tune", 0)
ioct = octave:i(itune)
ifrq = 133*ioct ;FREQUENCY
p3 = 0.6 * idur ;DURATION OF THIS NOTE
;SINE TONE SIGNAL
aAmpEnv transeg 1,p3,-10,0.001 ;AMPLITUDE ENVELOPE FOR SINE TONE SIGNAL
afmod expsega 5,0.125/ifrq,1,1,1 ;FREQUENCY MODULATION ENVELOPE. GIVES THE TONE MORE OF AN ATTACK.
asig oscili -aAmpEnv*0.6,ifrq*afmod,gi_808_sine ;SINE TONE SIGNAL
;NOISE SIGNAL
aEnvNse transeg 1,p3,-6,0.001 ;AMPLITUDE ENVELOPE FOR NOISE SIGNAL
anoise dust2 0.4, 8000 ;GENERATE NOISE SIGNAL
anoise reson anoise, 400*ioct,800,1 ;BANDPASS FILTER THE NOISE SIGNAL
anoise buthp anoise,100*ioct ;HIGHPASS FILTER THE NOSIE SIGNAL
anoise butlp anoise,600*ioct ;LOWPASS FILTER THE NOISE SIGNAL
anoise = anoise * aEnvNse ;SCALE NOISE SIGNAL WITH AMPLITUDE ENVELOPE
;MIX THE TWO SOUND COMPONENTS
amix = (asig + anoise)*ilevel*p5
pan_verb_mix(amix, xchan:k("MidTom.pan", 0.5), xchan:k("MidTom.rvb", chnget:i("drums.rvb.default")))
endin
/** Low Tom - From Iain McCurdy's TR-808.csd */
instr LowTom ;LOW TOM
idur = xchan("LowTom.decay", 1.0)
ilevel = xchan("LowTom.level", 1)
itune = xchan("LowTom.tune", 0)
ioct = octave:i(itune)
ifrq = 90 * ioct ;FREQUENCY
p3 = 0.7*idur ;DURATION OF THIS NOTE
;SINE TONE SIGNAL
aAmpEnv transeg 1,p3,-10,0.001 ;AMPLITUDE ENVELOPE FOR SINE TONE SIGNAL
afmod expsega 5,0.125/ifrq,1,1,1 ;FREQUENCY MODULATION ENVELOPE. GIVES THE TONE MORE OF AN ATTACK.
asig oscili -aAmpEnv*0.6,ifrq*afmod,gi_808_sine ;SINE TONE SIGNAL
;NOISE SIGNAL
aEnvNse transeg 1,p3,-6,0.001 ;AMPLITUDE ENVELOPE FOR NOISE SIGNAL
anoise dust2 0.4, 8000 ;GENERATE NOISE SIGNAL
anoise reson anoise,40*ioct,800,1 ;BANDPASS FILTER THE NOISE SIGNAL
anoise buthp anoise,100*ioct ;HIGHPASS FILTER THE NOSIE SIGNAL
anoise butlp anoise,600*ioct ;LOWPASS FILTER THE NOISE SIGNAL
anoise = anoise * aEnvNse ;SCALE NOISE SIGNAL WITH AMPLITUDE ENVELOPE
;MIX THE TWO SOUND COMPONENTS
amix = (asig + anoise)*ilevel*p5
pan_verb_mix(amix, xchan:k("LowTom.pan", 0.5), xchan:k("LowTom.rvb", chnget:i("drums.rvb.default")))
endin
/** Cymbal - From Iain McCurdy's TR-808.csd */
instr Cymbal ;CYMBAL
idur = xchan("Cymbal.decay", 1.0)
ilevel = xchan("Cymbal.level", 1)
itune = xchan("Cymbal.tune", 0)
ioct = octave:i(itune)
iFrq1 = 296*ioct ;FREQUENCIES OF THE 6 OSCILLATORS
iFrq2 = 285*ioct
iFrq3 = 365*ioct
iFrq4 = 348*ioct
iFrq5 = 420*ioct
iFrq6 = 835*ioct
p3 = 2*idur ;DURATION OF THE NOTE
;SOUND CONSISTS OF 6 PULSE OSCILLATORS MIXED WITH A NOISE COMPONENT
;PITCHED ELEMENT
aenv expon 1,p3,0.0001 ;AMPLITUDE ENVELOPE FOR THE PULSE OSCILLATORS
ipw = 0.25 ;PULSE WIDTH
a1 vco2 0.5,iFrq1,2,ipw ;PULSE OSCILLATORS...
a2 vco2 0.5,iFrq2,2,ipw
a3 vco2 0.5,iFrq3,2,ipw
a4 vco2 0.5,iFrq4,2,ipw
a5 vco2 0.5,iFrq5,2,ipw
a6 vco2 0.5,iFrq6,2,ipw
amix sum a1,a2,a3,a4,a5,a6 ;MIX THE PULSE OSCILLATORS
amix reson amix,5000 * ioct,5000,1 ;BANDPASS FILTER THE MIXTURE
amix buthp amix,10000 ;HIGHPASS FILTER THE SOUND
amix butlp amix,12000 ;LOWPASS FILTER THE SOUND...
amix butlp amix,12000 ;AND AGAIN...
amix = amix*aenv ;APPLY THE AMPLITUDE ENVELOPE
;NOISE ELEMENT
anoise noise 0.8,0 ;GENERATE SOME WHITE NOISE
aenv expsega 1,0.3,0.07,p3-0.1,0.00001 ;CREATE AN AMPLITUDE ENVELOPE
kcf expseg 14000,0.7,7000,p3-0.1,5000 ;CREATE A CUTOFF FREQ. ENVELOPE
anoise butlp anoise,kcf ;LOWPASS FILTER THE NOISE SIGNAL
anoise buthp anoise,8000 ;HIGHPASS FILTER THE NOISE SIGNAL
anoise = anoise*aenv ;APPLY THE AMPLITUDE ENVELOPE
;MIX PULSE OSCILLATOR AND NOISE COMPONENTS
amix = (amix+anoise)*ilevel*p5*0.85
pan_verb_mix(amix, xchan:k("Cymbal.pan", 0.5), xchan:k("Cymbal.rvb", chnget:i("drums.rvb.default")))
endin
;WAVEFORM FOR TR808 RIMSHOT
giTR808RimShot 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
/** Rimshot - From Iain McCurdy's TR-808.csd */
instr Rimshot ;RIM SHOT
idur = xchan("Rimshot.decay", 1.0)
ilevel = xchan("Rimshot.level", 1)
itune = xchan("Rimshot.tune", 0)
idur = 0.027*idur ;NOTE DURATION
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)
;RING
aenv1 expsega 1,idur,0.001,1,0.001 ;AMPLITUDE ENVELOPE FOR SUSTAIN ELEMENT OF SOUND
ifrq1 = 1700*octave(itune) ;FREQUENCY OF SUSTAIN ELEMENT OF SOUND
aring oscili 1,ifrq1,giTR808RimShot,0 ;CREATE SUSTAIN ELEMENT OF SOUND
aring butbp aring,ifrq1,ifrq1*8
aring = aring*(aenv1-0.001)*0.5 ;APPLY AMPLITUDE ENVELOPE
;NOISE
anoise noise 1,0 ;CREATE A NOISE SIGNAL
aenv2 expsega 1, 0.002, 0.8, 0.005, 0.5, idur-0.002-0.005, 0.0001, 1, 0.0001 ;CREATE AMPLITUDE ENVELOPE
anoise buthp anoise,800 ;HIGHPASS FILTER THE NOISE SOUND
kcf expseg 4000,idur,20 ;CUTOFF FREQUENCY FUNCTION FOR LOWPASS FILTER
anoise butlp anoise,kcf ;LOWPASS FILTER THE SOUND
anoise = anoise*(aenv2-0.001) ;APPLY ENVELOPE TO NOISE SIGNAL
;MIX
amix = (aring+anoise)*ilevel*p5*0.8
pan_verb_mix(amix, xchan:k("Rimshot.pan", 0.5), xchan:k("Rimshot.rvb", chnget:i("drums.rvb.default")))
endin
/** Claves - From Iain McCurdy's TR-808.csd */
instr Claves
idur = xchan("Claves.decay", 1.0)
ilevel = xchan("Claves.level", 1)
itune = xchan("Claves.tune", 0)
ifrq = 2500*octave(itune) ;FREQUENCY OF OSCILLATOR
idur = 0.045 * idur ;DURATION OF THE NOTE
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)
aenv expsega 1,idur,0.001,1,0.001 ;AMPLITUDE ENVELOPE
afmod expsega 3,0.00005,1,1,1 ;FREQUENCY MODULATION ENVELOPE. GIVES THE SOUND A LITTLE MORE ATTACK.
asig oscili -(aenv-0.001),ifrq*afmod,gi_808_sine,0 ;AUDIO OSCILLATOR
asig = asig * 0.4 * ilevel * p5 ;RESCALE AMPLITUDE
pan_verb_mix(asig, xchan:k("Claves.pan", 0.5), xchan:k("Claves.rvb", chnget:i("drums.rvb.default")))
endin
/** Cowbell - From Iain McCurdy's TR-808.csd */
instr Cowbell
idur = xchan("Cowbell.decay", 1.0)
ilevel = xchan("Cowbell.level", 1)
itune = xchan("Cowbell.tune", 0)
ifrq1 = 562 * octave(itune) ;FREQUENCIES OF THE TWO OSCILLATORS
ifrq2 = 845 * octave(itune) ;
ipw = 0.5 ;PULSE WIDTH OF THE OSCILLATOR
ishp = -30
idur = 0.7 ;NOTE DURATION
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)
ishape = -30 ;SHAPE OF THE CURVES IN THE AMPLITUDE ENVELOPE
kenv1 transeg 1,p3*0.3,ishape,0.2, p3*0.7,ishape,0.2 ;FIRST AMPLITUDE ENVELOPE - PRINCIPALLY THE ATTACK OF THE NOTE
kenv2 expon 1,p3,0.0005 ;SECOND AMPLITUDE ENVELOPE - THE SUSTAIN PORTION OF THE NOTE
kenv = kenv1*kenv2 ;COMBINE THE TWO ENVELOPES
itype = 2 ;WAVEFORM FOR VCO2 (2=PULSE)
a1 vco2 0.65,ifrq1,itype,ipw ;CREATE THE TWO OSCILLATORS
a2 vco2 0.65,ifrq2,itype,ipw
amix = a1+a2 ;MIX THE TWO OSCILLATORS
iLPF2 = 10000 ;LOWPASS FILTER RESTING FREQUENCY
kcf expseg 12000,0.07,iLPF2,1,iLPF2 ;LOWPASS FILTER CUTOFF FREQUENCY ENVELOPE
alpf butlp amix,kcf ;LOWPASS FILTER THE MIX OF THE TWO OSCILLATORS (CREATE A NEW SIGNAL)
abpf reson amix, ifrq2, 25 ;BANDPASS FILTER THE MIX OF THE TWO OSCILLATORS (CREATE A NEW SIGNAL)
amix dcblock2 (abpf*0.06*kenv1)+(alpf*0.5)+(amix*0.9) ;MIX ALL SIGNALS AND BLOCK DC OFFSET
amix buthp amix,700 ;HIGHPASS FILTER THE MIX OF ALL SIGNALS
amix = amix * 0.07 * kenv * p5 * ilevel ;RESCALE AMPLITUDE
pan_verb_mix(amix, xchan:k("Cowbell.pan", 0.5), xchan:k("Cowbell.rvb", chnget:i("drums.rvb.default")))
endin
/** Maraca - from Iain McCurdy's TR-808.csd */
instr Maraca ;MARACA
idur = xchan("Maraca.decay", 1.0)
ilevel = xchan("Maraca.level", 1)
itune = xchan("Maraca.tune", 0)
ioct = octave:i(itune)
idur = 0.07*idur ;DURATION 3
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)
iHPF limit 6000*ioct,20,sr/2 ;HIGHPASS FILTER FREQUENCY
iLPF limit 12000*ioct,20,sr/3 ;LOWPASS FILTER FREQUENCY. (LIMIT MAXIMUM TO PREVENT OUT OF RANGE VALUES)
;AMPLITUDE ENVELOPE
iBP1 = 0.4 ;BREAK-POINT 1
iDur1 = 0.014*idur ;DURATION 1
iBP2 = 1 ;BREAKPOINT 2
iDur2 = 0.01 *idur ;DURATION 2
iBP3 = 0.05 ;BREAKPOINT 3
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)
aenv expsega iBP1,iDur1,iBP2,iDur2,iBP3 ;CREATE AMPLITUDE ENVELOPE
anoise noise 0.75,0 ;CREATE A NOISE SIGNAL
anoise buthp anoise,iHPF ;HIGHPASS FILTER THE SOUND
anoise butlp anoise,iLPF ;LOWPASS FILTER THE SOUND
anoise = anoise*aenv*p5*ilevel ;SCALE THE AMPLITUDE
pan_verb_mix(anoise, xchan:k("Maraca.pan", 0.5), xchan:k("Maraca.rvb", chnget:i("drums.rvb.default")))
endin
/** High Conga - From Iain McCurdy's TR-808.csd */
instr HiConga ;HIGH CONGA
idur = xchan("HiConga.decay", 1.0)
ilevel = xchan("HiConga.level", 1)
itune = xchan("HiConga.tune", 0)
ioct = octave:i(itune)
ifrq = 420*ioct ;FREQUENCY OF NOTE
p3 = 0.22*idur ;DURATION OF NOTE
aenv transeg 0.7,1/ifrq,1,1,p3,-6,0.001 ;AMPLITUDE ENVELOPE
afrq expsega ifrq*3,0.25/ifrq,ifrq,1,ifrq ;FREQUENCY ENVELOPE (CREATE A SHARPER ATTACK)
asig oscili -aenv*0.25,afrq,gi_808_sine ;CREATE THE AUDIO OSCILLATOR
asig = asig*p5*ilevel ;SCALE THE AMPLITUDE
pan_verb_mix(asig, xchan:k("HiConga.pan", 0.5), xchan:k("HiConga.rvb", chnget:i("drums.rvb.default")))
endin
/** Mid Conga - From Iain McCurdy's TR-808.csd */
instr MidConga ;MID CONGA
idur = xchan("MidConga.decay", 1.0)
ilevel = xchan("MidConga.level", 1)
itune = xchan("MidConga.tune", 0)
ioct = octave:i(itune)
ifrq = 310*ioct ;FREQUENCY OF NOTE
p3 = 0.33*idur ;DURATION OF NOTE
aenv transeg 0.7,1/ifrq,1,1,p3,-6,0.001 ;AMPLITUDE ENVELOPE
afrq expsega ifrq*3,0.25/ifrq,ifrq,1,ifrq ;FREQUENCY ENVELOPE (CREATE A SHARPER ATTACK)
asig oscili -aenv*0.25,afrq,gi_808_sine ;CREATE THE AUDIO OSCILLATOR
asig = asig*p5*ilevel ;SCALE THE AMPLITUDE
pan_verb_mix(asig, xchan:k("MidConga.pan", 0.5), xchan:k("MidConga.rvb", chnget:i("drums.rvb.default")))
endin
/** Low Conga - From Iain McCurdy's TR-808.csd */
instr LowConga ;LOW CONGA
idur = xchan("LowConga.decay", 1.0)
ilevel = xchan("LowConga.level", 1)
itune = xchan("LowConga.tune", 0)
ioct = octave:i(itune)
ifrq = 227*ioct ;FREQUENCY OF NOTE
p3 = 0.41*idur ;DURATION OF NOTE
aenv transeg 0.7,1/ifrq,1,1,p3,-6,0.001 ;AMPLITUDE ENVELOPE
afrq expsega ifrq*3,0.25/ifrq,ifrq,1,ifrq ;FREQUENCY ENVELOPE (CREATE A SHARPER ATTACK)
asig oscili -aenv*0.25,afrq,gi_808_sine ;CREATE THE AUDIO OSCILLATOR
asig = asig*p5*ilevel ;SCALE THE AMPLITUDE
pan_verb_mix(asig, xchan:k("LowConga.pan", 0.5), xchan:k("LowConga.rvb", chnget:i("drums.rvb.default")))
endin
;; INITIALIZATION OF SYSTEM
start("Clock")
You can’t perform that action at this time.