aboutsummaryrefslogtreecommitdiff
path: root/site/udo/fnml
diff options
context:
space:
mode:
authorRichard <q@1bpm.net>2025-04-13 18:48:02 +0100
committerRichard <q@1bpm.net>2025-04-13 18:48:02 +0100
commit9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22 (patch)
tree291bd79ce340e67affa755a8a6b4f6a83cce93ea /site/udo/fnml
downloadapps.csound.1bpm.net-9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22.tar.gz
apps.csound.1bpm.net-9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22.tar.bz2
apps.csound.1bpm.net-9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22.zip
initial
Diffstat (limited to 'site/udo/fnml')
-rwxr-xr-xsite/udo/fnml/clay_workings.csd58
-rwxr-xr-xsite/udo/fnml/instrument_automel.udo89
-rwxr-xr-xsite/udo/fnml/instrument_gchord1.udo260
-rwxr-xr-xsite/udo/fnml/instrument_portchord.udo132
-rwxr-xr-xsite/udo/fnml/instrument_sineblips.udo81
-rwxr-xr-xsite/udo/fnml/instrument_tikbank.udo78
-rwxr-xr-xsite/udo/fnml/instrument_tikclay.udo118
-rwxr-xr-xsite/udo/fnml/instrument_vocal.udo73
-rwxr-xr-xsite/udo/fnml/transition_click.udo143
-rwxr-xr-xsite/udo/fnml/transition_mburn.udo186
-rwxr-xr-xsite/udo/fnml/transition_snare.udo140
-rwxr-xr-xsite/udo/fnml/transition_snare_preSOUNDDB.udo133
-rwxr-xr-xsite/udo/fnml/transition_test.csd39
-rwxr-xr-xsite/udo/fnml/transitional/base.udo141
14 files changed, 1671 insertions, 0 deletions
diff --git a/site/udo/fnml/clay_workings.csd b/site/udo/fnml/clay_workings.csd
new file mode 100755
index 0000000..e11e64b
--- /dev/null
+++ b/site/udo/fnml/clay_workings.csd
@@ -0,0 +1,58 @@
+<CsoundSynthesizer>
+<CsOptions>
+-odac
+</CsOptions>
+<CsInstruments>
+sr = 44100
+kr = 4410
+nchnls = 2
+0dbfs = 1
+seed 0
+
+#include "sounddb.udo"
+#include "uniqueid.udo"
+#include "bussing.udo"
+
+gicoll_clay[], gicollclay_id sounddb_getcollection "Clay.Hit"
+
+instr play_clay_roll
+ instanceid = uniqueid()
+ icollsize = lenarray(gicoll_clay)
+ ifreqmax = 100
+ kmetrofreq expseg ifreqmax*0.4, p3*0.3, ifreqmax*0.8, p3*0.4, ifreqmax, p4*0.4, ifreqmax*0.5
+ kmetro metro kmetrofreq
+ if (kmetro == 1) then
+ kdbid = gicoll_clay[round:k(random:k(0, icollsize - 1))]
+ schedulek "_play_clay_hit", random(0, 1/kmetrofreq), 1, kdbid, instanceid
+ endif
+
+ kamp expseg 0.001, p3*0.4, 1, p3*0.1, 1, p3*0.4, 0.001
+
+ aL, aR bus_read sprintf("clay_hit%d", instanceid)
+ aL pareq aL, 15000, 4, 0.6
+ aR pareq aR, 15000, 4, 0.6
+ aL *= kamp
+ aR *= kamp
+ outs aL, aR
+endin
+
+
+
+instr _play_clay_hit
+ idbid = p4
+ instanceid = p5
+ ifn = gisounddb[idbid][0]
+ idur = gisounddb[idbid][2]
+ p3 = idur
+
+ aL, aR loscil 0.2, 1, ifn, 1
+ ipan = random(0, 1)
+ bus_mix(sprintf("clay_hit%d", instanceid), aL*ipan, aR*(1-ipan))
+endin
+
+
+</CsInstruments>
+<CsScore>
+i"play_clay_roll" 0 6
+</CsScore>
+</CsoundSynthesizer> \ No newline at end of file
diff --git a/site/udo/fnml/instrument_automel.udo b/site/udo/fnml/instrument_automel.udo
new file mode 100755
index 0000000..437acc0
--- /dev/null
+++ b/site/udo/fnml/instrument_automel.udo
@@ -0,0 +1,89 @@
+#ifndef UDO_FNMI_AUTOMEL
+#define UDO_FNMI_AUTOMEL ##
+
+#include "sequencing_table.udo"
+#include "sequencing_melodic.udo"
+#include "bussing.udo"
+
+instr _play_fnmi_automel1
+ icollectionid = p4
+ Sbus = p5
+ ifreqmult = p6
+ inote = mel_randomnote()
+ if (random(0, 1) >= 0.5) then
+ inote += 12
+ endif
+
+ idowaveset = (random(0, 1) >= 0.8) ? 1 : 0
+ if (idowaveset == 1) then
+ if (random(0, 1) >= 0.6) then
+ p3 *= random(1.2, 1.8)
+ endif
+ endif
+
+ ifileid, ipitchratio sounddb_mel_nearestnote icollectionid, inote
+ ifn, ichannels, iduration, irmsnorm sounddb_get ifileid
+
+ ireadtype = round(random(0, 2))
+
+ if (ireadtype == 0) then
+ aL, aR loscil 1, ipitchratio * ifreqmult, ifn, 1
+ else
+ atime line 0, p3, iduration * random(0.5, 1)
+ if (ireadtype == 1) then
+ imincerfftsize = pow(2, round(random(8, 11)))
+ aL, aR mincer atime, random(0.7, 1.1), ipitchratio * ifreqmult, ifn, 0, imincerfftsize
+ elseif (ireadtype == 2) then
+ iwsize = random(441, 4410)
+ aL, aR sndwarpst 1, atime, ipitchratio * ifreqmult * (ftsr(ifn) / sr), ifn, 0, iwsize, iwsize * 0.1, 4, gifnHalfSine, 1
+ endif
+ endif
+ aamp linseg 1, p3*0.9, 1, p3*0.1, 0
+
+ if (random(0, 1) >= 0.6) then
+ aL, aR ringmod1 aL, aR, cpsmidinn(inote) * 2
+ endif
+
+ aL *= aamp
+ aR *= aamp
+ if (idowaveset == 1) then
+ kwaveseta line 0, p3, round(random(2, 5))
+ aL waveset aL, kwaveseta
+ aR waveset aR, kwaveseta
+ endif
+ if (random(0, 1) >= 0.7) then
+ aL distort aL, 0.5, gifnSine
+ aR distort aR, 0.5, gifnSine
+ aL *= 0.4
+ aR *= 0.4
+ endif
+
+ bus_mix(Sbus, aL, aR)
+endin
+
+/*
+ aL, aR automel1 icollectionid1, kchance=1, kdivisions=4, icollectionid2=icollectionid1, kfreqmult=1
+*/
+opcode automel1, aa, iVJjJ
+ icollectionid1, kchance, kdivisions, icollectionid2, kfreqmult xin
+ kdivisions = (kdivisions == -1) ? 4 : kdivisions
+ kfreqmult = (kfreqmult == -1) ? 1 : kfreqmult
+ kcollectionid init icollectionid1
+ Sbus = sprintf("fnmautomel%d", uniqueid())
+ ktrig seq_table gifn_tabseq_all, 0, 4, kchance
+ instrnum = nstrnum("_play_fnmi_automel1") + uniquefrac()
+ if (ktrig == 1 && active:k(instrnum) == 0) then
+ if (icollectionid2 != -1) then
+ if (random:k(0, 1) >= 0.5) then
+ kcollectionid = icollectionid1
+ else
+ kcollectionid = icollectionid2
+ endif
+ endif
+ schedulek(instrnum, 0, gkseq_quartertime * random:k(0.5, 4), kcollectionid, Sbus, kfreqmult)
+ endif
+ aL, aR bus_read Sbus
+ xout aL, aR
+endop
+
+#end
diff --git a/site/udo/fnml/instrument_gchord1.udo b/site/udo/fnml/instrument_gchord1.udo
new file mode 100755
index 0000000..e8c5905
--- /dev/null
+++ b/site/udo/fnml/instrument_gchord1.udo
@@ -0,0 +1,260 @@
+#ifndef UDO_FNMI_GCHORD1
+#define UDO_FNMI_GCHORD1 ##
+/*
+ Portamento glitch-out textural chord player
+
+ This file is part of the SONICS UDO collection by Richard Knight 2021
+ License: GPL-2.0-or-later
+ http://1bpm.net
+*/
+#include "wavetables.udo"
+#include "sequencing_melodic_portamento.udo"
+#include "sounddb.udo"
+#include "bussing.udo"
+#include "frequency_tools.udo"
+#include "uniqueid.udo"
+
+/*
+ sounddb glitchy chord player
+ aL, aR fnmi_gchord1 icollectionid, iattacktime, ireleasetime, icompressmode, kchangechance [, ipitchratio=1, ireadtype=0, ireloadtime=10]
+ aL, aR fnmi_gchord1 Scollection, iattacktime, ireleasetime, icompressmode, kchangechance [, ipitchratio=1, ireadtype=0, ireloadtime=10]
+
+ aL, aR audio output
+
+ icollectionid sounddb collection ID to use
+ Scollection sounddb collection name to use
+ iattacktime start fade in time
+ ireleasetime fade out time on host instrument note end
+ icompressmode 0 = none ; 1 = harshwall ; 2 = normal
+ kchangechance glitchy item change rate chance (1 = every quarter beat)
+ ipitchratio default pitch augmentation ratio
+ ireadtype 0 = sndwarp ; 1 = mincer
+ ireloadtime seconds between reloads of subinstruments to ensure variation in source sound
+*/
+
+opcode fnmi_gchord1, aa, iiiikpoj
+ icollectionid, iattacktime, ireleasetime, icompressmode, kchangechance, ipitchratio, ireadtype, ireloadtime xin
+ ilen = p3
+ ireloadtime = (ireloadtime == -1) ? 10 : ireloadtime
+ instanceid = uniqueid()
+
+ iusedinstruments[] uniqueinstrnums "_fnmi_gchord1_notehold", ftlen(gimel_freqs)
+
+ ; set up notehold instruments
+ index = 0
+ while (index < lenarray(iusedinstruments)) do
+ schedule iusedinstruments[index], 0, ilen, index, icollectionid, ireleasetime, instanceid, ipitchratio, ireadtype
+ index += 1
+ od
+
+
+ ; reload random notehold instrument at periodic intervals (ie to change source sound)
+ klastchangetime init 0
+ ktime timeinsts
+ if (ktime - klastchangetime > ireloadtime) then
+ kindex = round:k(random(0, lenarray(iusedinstruments)-1))
+ kinstrument = iusedinstruments[kindex]
+ turnoff2 kinstrument, 4, 1
+ schedulek kinstrument, ireleasetime*0.5, ilen-ktime, kindex, icollectionid, ireleasetime, instanceid, ipitchratio, ireadtype
+ klastchangetime = ktime
+ endif
+
+
+ ; if host instrument of opcode ends, turn off all notehold instances
+ kreleasing init 0
+ if (release:k() == 1 && kreleasing == 0) then
+ kreleasing = 1
+ kindex = 0
+ while (kindex < lenarray(iusedinstruments)) do
+ turnoff2 iusedinstruments[kindex], 4, 1
+ kindex += 1
+ od
+ endif
+
+ ; if at end of host instrument note length, add release time for relevant fade out
+ if (lastcycle:k() == 1) then
+ xtratim ireleasetime
+ endif
+
+
+ ; trigger for variations in individual notehold instruments
+ idivisions = 4
+ as, aps syncphasor -(gkseq_beathz*idivisions), a(gkseq_beat)
+ ktrig trigger k(as), 0.1, 0
+ chnset ktrig, sprintf("fnmi_gchord1_qtrig%d", instanceid)
+
+
+ ; 'global' change chance for the notehold instruments
+ chnset kchangechance, sprintf("fnmi_gchord1_changechance%d", instanceid)
+
+ ; feed from the notehold instruments
+ aL, aR bus_read sprintf("fnmi_gchord1_out%d", instanceid)
+
+ if (icompressmode == 1) then
+ acomp noise 0.2, 0.4
+ aL balance aL, acomp
+ aR balance aL, acomp
+ elseif (icompressmode == 2) then
+ aL compress aL, aL, -5, 40, 40, 6, 0, 0.1, 0
+ aR compress aR, aR, -5, 40, 40, 6, 0, 0.1, 0
+ aL *= 30
+ aR *= 30
+ endif
+
+ aL dcblock aL
+ aR dcblock aR
+
+ iattacktime = max(0.00001, iattacktime) ; can't be 0 for linseg
+ kamp linsegr 0, iattacktime, 1, ilen - iattacktime, 1, ireleasetime, 0
+
+ xout aL*kamp, aR*kamp
+endop
+
+; overload for named collection
+opcode fnmi_gchord1, aa, Siiikpoj
+ Scollection, iattacktime, ireleasetime, icompressmode, kchangechance, ipitchratio, ireadtype, ireloadtime xin
+ aL, aR fnmi_gchord1 sounddb_getcollectionid(Scollection), iattacktime, ireleasetime, icompressmode, kchangechance, ipitchratio, ireadtype, ireloadtime
+ xout aL, aR
+endop
+
+
+
+/*
+ Used internally by fnmi_gchord1 for sound generation and return via channel
+*/
+instr _fnmi_gchord1_notehold
+ index = p4
+ icollectionid = p5
+ ireleasetime = p6
+ instanceid = p7
+ iuserpitchratio = p8
+ ireadtype = p9
+ kamp table index, gimel_amps
+
+ aL init 0
+ aR init 0
+ if (kamp > 0) then ; all processing
+ kamp *= 0.32 ;0.05
+ kfreq table index, gimel_freqs
+ ibasenote random 30, 50
+ ifileid, ipitchratio sounddb_mel_nearestnote icollectionid, ibasenote
+ ifn = gisounddb[ifileid][0]
+
+ ipitchratio *= ((ireadtype == 0) ? (ftsr(ifn) / sr) : 1) * iuserpitchratio ; sr adjustment for sndwarp required
+ ilen = ftlen(ifn) / ftsr(ifn)
+
+ ; pitch lfo
+ alfo oscil 2.1, 0.15, gifnSine
+ kfreq += k(alfo)
+
+ kpitchratio = (kfreq / cpsmidinn(ibasenote)) * ipitchratio
+
+ istart = random(0, 0.1) ;* ilen
+ iend = random(istart+0.1, 0.4) ; 0.9
+
+ kreadmode init 0
+
+ if (kreadmode == 0) then
+ atime = (abs(oscil(iend-istart, random(0.001, 0.1), gifnSine, random(0, 1)))) * ilen ; TODO: don't think + istart is required here
+ elseif (kreadmode == 1) then
+ atime = (istart * ilen) + ((phasor(random(2, 10)) * (ilen * (iend - istart))))
+ else
+ atime = (istart * ilen) + ((phasor(-random(2, 10)) * (ilen * (iend - istart))))
+ endif
+
+ if (ireadtype == 0) then
+ aL, aR sndwarpst kamp, atime, interp(kpitchratio), ifn, istart, 441*random(1, 100), 44*random(1, 10), 8, gifnHalfSine, 1
+ elseif (ireadtype == 1) then
+ aL, aR mincer atime, kamp, kpitchratio, ifn, 0
+ endif
+
+ kdo_crush init 0
+ kdo_diff init 0
+ kdo_delaytuner init 0
+ kdo_ringmod init 0
+ kdelmult init 8
+ kcrushrange init 4
+ kringmodmult init 2
+ khpfreq init 150
+ kpan init random(0, 1)
+
+ if (kdo_crush == 1) then
+ kcrush = abs:k(oscil:k(kcrushrange, random(0.01, 0.3))) + kcrushrange
+ kcrushamount = abs:k(oscil:k(0.7, random(0.001, 0.2), gifnSaw, random(0, 1)))
+ aLbc, aRbc bitcrush aL, aR, kcrush
+ aL += aLbc * kcrushamount
+ aR += aRbc * kcrushamount
+ endif
+
+ if (kdo_ringmod == 1) then
+ aL, aR ringmod1 aL, aR, kfreq*kringmodmult ;portk(kfreq*kringmodmult, 0.01)
+ endif
+
+ if (kdo_delaytuner == 1) then
+ kdelaytuneramount = abs:k(oscil:k(0.5, random(0.001, 0.2), gifnSine, random(0, 1)))
+ aLdt, aRdt delaytuner aL, aR, max:k(1, kpitchratio)*kdelmult, 0.9 ; portk(kdelmult, 0.1)
+ aL += aLdt * kdelaytuneramount
+ aR += aRdt * kdelaytuneramount
+ endif
+
+ aL butterhp aL, khpfreq
+ aR butterhp aR, khpfreq
+
+ if (kdo_diff == 1) then
+ aL diff aL
+ endif
+
+ ktrig = chnget:k(sprintf("fnmi_gchord1_qtrig%d", instanceid))
+ kchangechance = chnget:k(sprintf("fnmi_gchord1_changechance%d", instanceid))
+
+ if (ktrig == 1 && random:k(0, 1) < kchangechance) then
+ if (random:k(0, 1) > 0.9) then
+ kreadmode = round:k(random:k(0, 2))
+ endif
+
+ if (random:k(0, 1) > 0.9) then
+ khpfreq = random:k(250, 2500)
+ endif
+
+ if (random:k(0, 1) > 0.9) then
+ kdelmult = round:k(random:k(8, 16))
+ endif
+
+ if (random:k(0, 1) > 0.9) then
+ kcrushrange = round:k(random:k(2, 64))
+ endif
+
+ if (random:k(0, 1) > 0.95) then
+ kdo_crush = 1 - kdo_crush
+ endif
+
+ if (random:k(0, 1) > 0.95) then
+ kdo_delaytuner = 1 - kdo_delaytuner
+ endif
+
+ if (random:k(0, 1) > 0.95) then
+ kdo_ringmod = 1 - kdo_ringmod
+ endif
+
+ if (random:k(0, 1) > 0.95) then
+ kringmodmult = pow:k(2, round:k(random:k(-1, 2))) ; 3 up to 8
+ endif
+
+ if (random:k(0, 1) > 0.9) then
+ kpan = random:k(0, 1)
+ endif
+
+ if (random:k(0, 1) > 0.9) then
+ kdo_diff = 1 - kdo_diff
+ endif
+ endif
+
+ aL *= kpan
+ aR *= (1-kpan)
+ endif ; if amp > 0
+
+ krelamp linsegr 1, p3, 1, ireleasetime, 0
+ bus_mix(sprintf("fnmi_gchord1_out%d", instanceid), aL*krelamp, aR*krelamp)
+endin
+
+#end
diff --git a/site/udo/fnml/instrument_portchord.udo b/site/udo/fnml/instrument_portchord.udo
new file mode 100755
index 0000000..fd8b682
--- /dev/null
+++ b/site/udo/fnml/instrument_portchord.udo
@@ -0,0 +1,132 @@
+#ifndef UDO_FNMI_PORTCHORD
+#define UDO_FNMI_PORTCHORD ##
+/*
+ Portamento recursive chord players
+
+ This file is part of the SONICS UDO collection by Richard Knight 2021
+ License: GPL-2.0-or-later
+ http://1bpm.net
+*/
+
+#include "__config__.udo"
+#include "sequencing_melodic_persistence.udo"
+#include "sequencing_melodic_portamento.udo"
+#include "wavetables.udo"
+#include "sounddb.udo"
+
+
+/*
+ Play continuous chords from melodic sequencer with portamento, using oscil as an instrument and a specified wavetable
+
+ aL, aR portchord_wave [iwavefn=gifnSine, ifreqmult=1, ivibdepth=1, ivibrate=3, index=0]
+
+ aL, aR stereo outputs
+ iwavefn the f-table to use with oscil
+ ifreqmult frequency multiplier of the chord note frequencies to be applied
+ ivibdepth vibrato depth
+ ivibrate vibrato rate in Hz
+ index internal start index of the chord notes; could also be used to specify starting note offset
+*/
+opcode portchord_wave, aa, jpjjo
+ iwavefn, ifreqmult, ivibdepth, ivibrate, index xin
+
+ iwavefn = (iwavefn == -1) ? gifnSine : iwavefn
+ ivibdepth = (ivibdepth == -1) ? 1 : ivibdepth
+ ivibrate = (ivibrate == -1) ? 3 : ivibrate
+
+ kamp table index, gimel_amps
+ kfreq table index, gimel_freqs
+
+ klfo = oscil:k(ivibdepth, ivibrate) ;oscil:k(7, 5)
+ kfreq += klfo
+ kfreq *= ifreqmult
+
+ ;kamp portk kamp, (i(gkseq_beattime) * gimel_portamento_beatratio) ; fade out when change
+
+ aL oscil kamp*0.1, kfreq, iwavefn
+ ipan = random(0, 1)
+ aR = aL * ipan
+ aL *= (1 - ipan)
+
+ if (index + 1 < ftlen(gimel_amps)) then
+ aLx, aRx portchord_wave iwavefn, ifreqmult, ivibdepth, ivibrate, index + 1
+ aL += aLx
+ aR += aRx
+ endif
+
+ xout aL, aR
+endop
+
+
+
+/*
+ Play continuous chords from melodic sequencer with portamento, using a sounddb collection as source sounds
+
+ aL, aR portchord_sound icollectionid [, imode=1, kfreqmult=1, ifftsize=giFFTsize, index=0]
+
+ aL, aR stereo outputs
+ icollectionid collection ID from sounddb to use for the playback
+ imode 0 = read with sndwarp; 1 = read with mincer
+ kfreqmult frequency multiplier of the chord note frequencies to be applied
+ ifftsize FFT size to use when imode = 1 ; default to global setting in __config__.udo
+ index internal start index of the chord notes; could also be used to specify starting note offset
+*/
+opcode portchord_sound, aa, ipPjo
+ icollectionid, imode, kfreqmult, ifftsize, index xin
+
+ ifftsize = (ifftsize == -1) ? giFFTsize : ifftsize
+
+ inote = round(random(50, 80))
+ ibasefreq = cpsmidinn(inote)
+ ifileid, ipitchratio sounddb_mel_nearestnote icollectionid, inote
+
+ ifn = gisounddb[ifileid][0]
+ ichannels = gisounddb[ifileid][1]
+ idur = gisounddb[ifileid][2]
+ irmsnorm = gisounddb[ifileid][3]
+
+ kampb table index, gimel_amps
+ kfreq table index, gimel_freqs
+
+ kamp portk kampb, (i(gkseq_beattime) * gimel_portamento_beatratio) ; fade out when change
+
+ kpitch = (kfreq / ibasefreq) * ipitchratio * kfreqmult ; actual pitch adjustment
+
+ istart = random(0.05, 0.2)
+ iend = random(istart+0.1, 0.8)
+ atime = (abs(oscil(iend - istart, random(0.001, 0.1), gifnSine, random(0, 1))) + istart) * idur
+
+
+ klfo = oscil:k(random(0.0001, 0.009), random(1, 5)) + 1
+ kpitch *= klfo
+
+ if (kamp != 0) then
+ if (imode == 0) then
+ kpitch *= (ftsr(ifn) / sr) ; adjustment for sndwarp required
+
+ ;apitch interp kpitch
+ aL, aR sndwarpst kamp, atime, kpitch, ifn, istart, 4410, 441, 8, gifnHalfSine, 1
+
+ else
+ if (ichannels == 2) then
+ aL, aR mincer atime, kamp, kpitch, ifn, 0, ifftsize
+ else
+ aL mincer atime, kamp, kpitch, ifn, 0, ifftsize
+ aR = aL
+ endif
+ endif
+ endif
+
+ aL *= (1 - irmsnorm) * 0.5
+ aR *= (1 - irmsnorm) * 0.5
+
+ ; recursion for all chord parts
+ if (index + 1 < ftlen(gimel_amps)) then
+ aLx, aRx portchord_sound icollectionid, imode, kfreqmult, ifftsize, index + 1
+ aL += aLx
+ aR += aRx
+ endif
+ xout aL, aR
+endop
+
+#end
diff --git a/site/udo/fnml/instrument_sineblips.udo b/site/udo/fnml/instrument_sineblips.udo
new file mode 100755
index 0000000..5990909
--- /dev/null
+++ b/site/udo/fnml/instrument_sineblips.udo
@@ -0,0 +1,81 @@
+#ifndef UDO_FNMI_SINEBLIP
+#define UDO_FNMI_SINEBLIP ##
+/*
+ Stochastic sequenced sine blip instrument
+
+ This file is part of the SONICS UDO collection by Richard Knight 2021
+ License: GPL-2.0-or-later
+ http://1bpm.net
+*/
+
+#include "bussing.udo"
+#include "sequencing_melodic.udo"
+
+
+/*
+ Randomised sine blip playback internal instrument
+*/
+instr _fnmi_sineblip
+ Sbus = p4
+ inote = mel_randomnote:i() + 12
+ if (random(0, 1) > 0.5) then
+ inote += 12
+ endif
+
+ if (random(0, 1) > 0.5) then
+ inote += 12
+ endif
+
+ if (random(0, 1) > 0.5) then
+ inote += 12
+ endif
+
+ if (random(0, 1) > 0.99) then
+ inote += 1
+ endif
+ ibasefreq = cpsmidinn(inote)
+ ifreqL = ibasefreq + random(-5, 5)
+ ifreqR = ibasefreq + random(-5, 5)
+ iampL = random(0.5, 1)
+ iampR = random(0.5, 1)
+ aL oscil iampL, ifreqL
+ aR oscil iampR, ifreqR
+
+ if (random(0, 1) > 0.5) then
+ kamp line 1, p3, 0
+ else
+ kamp linseg 1, p3*0.9, 1, p3*0.1, 0
+ endif
+ bus_mix(Sbus, aL*0.6*kamp, aR*0.6*kamp)
+endin
+
+
+/*
+ Randomised sine blip playback scheduler
+*/
+instr fnmi_sineblips
+ if (p4 == 0) then
+ Sbus = "main"
+ else
+ Sbus = p4
+ endif
+
+ if (p5 == 0) then
+ iqtime = i(gkseq_quartertime)
+ else
+ iqtime = p5
+ endif
+
+ inum = random(2, 8)
+ itimeindex = random(0, 8)
+ index = 0
+ while (index < inum) do
+ itime = seq_swingtime:i(iqtime * itimeindex, itimeindex)
+ schedule "_fnmi_sineblip", itime, random(0.05, 0.1), Sbus
+ itimeindex += random(1, 4)
+ index += 1
+ od
+ xtratim iqtime * itimeindex
+endin
+
+#end
diff --git a/site/udo/fnml/instrument_tikbank.udo b/site/udo/fnml/instrument_tikbank.udo
new file mode 100755
index 0000000..895c8b0
--- /dev/null
+++ b/site/udo/fnml/instrument_tikbank.udo
@@ -0,0 +1,78 @@
+#ifndef UDO_FNMI_TIKBANK
+#define UDO_FNMI_TIKBANK ##
+
+
+
+#include "sounddb.udo"
+#include "bussing.udo"
+#include "uniqueid.udo"
+
+
+instr _tik_play
+ ifn = p4
+ ipitch = p5
+ ipan = p6
+ instanceid = p7
+
+ aL, aR loscil 0.4, ipitch, ifn, 1
+ bus_mix(sprintf("tikaudio%d", instanceid), aL*ipan, aR*(1-ipan))
+endin
+
+
+instr _tik_item
+ ifn = p4
+ idur = p5
+ ipitch = p6
+ instanceid = p7
+ index = p8
+
+ kfreq chnget sprintf("tikitemfreq_%d_%d", instanceid, index)
+ ipan = random(0, 1)
+
+ if (kfreq != 0) then
+ kmetro metro kfreq*2, random(0, 1)
+ if (kmetro == 1) then
+ schedulek "_tik_play", 0, idur, ifn, ipitch, ipan, instanceid
+ endif
+ endif
+endin
+
+
+opcode tik_bank, iaa, i[]ipj
+ icollection[], inum, ipitch, instanceid xin
+
+ if (instanceid == -1) then
+ instanceid = uniqueid()
+ endif
+
+ iusedinstruments[] uniqueinstrnums "_tik_item", inum
+
+ index = 0
+ ifileindex = 0
+ while (index < lenarray(iusedinstruments)) do
+ idbindex = icollection[ifileindex]
+ ifn = gisounddb[idbindex][0]
+ idur = gisounddb[idbindex][2] / ipitch
+
+ schedule iusedinstruments[index], 0, p3, ifn, idur, ipitch, instanceid, index
+ if (ifileindex + 1 < lenarray(icollection)) then
+ ifileindex += 1
+ else
+ ifileindex = 0
+ endif
+ index += 1
+ od
+
+ if (release:k() == 1) then
+ kindex = 0
+ while (kindex < lenarray(iusedinstruments)) do
+ turnoff2 iusedinstruments[kindex], 4, 1
+ kindex += 1
+ od
+ endif
+
+ aL, aR bus_read sprintf("tikaudio%d", instanceid)
+ xout instanceid, aL, aR
+endop
+
+#end
diff --git a/site/udo/fnml/instrument_tikclay.udo b/site/udo/fnml/instrument_tikclay.udo
new file mode 100755
index 0000000..73a6e5d
--- /dev/null
+++ b/site/udo/fnml/instrument_tikclay.udo
@@ -0,0 +1,118 @@
+#ifndef UDO_FNMI_TIKCLAY
+#define UDO_FNMI_TIKCLAY ##
+
+#include "sounddb.udo"
+#include "bussing.udo"
+#include "wavetables.udo"
+#include "uniqueid.udo"
+#include "sequencing_melodic.udo"
+
+gitikfn_clay[], gicl_clay sounddb_getcollection "Clay.Hit"
+
+instr _tik_clay_play
+ instanceid = p4
+ ifileid = p5
+ ipitch = p6
+ iwsize = p7
+ irandw = p8
+ ipan = p9
+ iresonfreq = p10
+ idoreson = p11
+
+ ifn = gisounddb[ifileid][0]
+ idur = gisounddb[ifileid][2]
+ istart = idur * random(0, 0.1)
+ atime linseg istart, p3, idur*0.9
+ kamp linseg 1, p3*0.8, 1, p3*0.2, 0
+ aL, aR sndwarpst 1, atime, ipitch, ifn, istart, iwsize, irandw, 2, gifnHalfSine, 1
+
+ if (idoreson == 1) then
+ aLr resony aL, iresonfreq, 6, 16, 10
+ aRr resony aR, iresonfreq, 6, 16, 10
+ aL balance aLr, aL
+ aR balance aRr, aR
+ endif
+
+ ilpf = random(2000, 22050)
+ aL butterlp aL, ilpf
+ aR butterlp aR, ilpf
+ bus_mix(sprintf("tikclayaudio%d", instanceid), aL*ipan*kamp, aR*(1-ipan)*kamp)
+endin
+
+
+instr _tik_clay_item
+ instanceid = p4
+ index = p5
+ kreset init 1
+
+ kfreq = chnget:k(sprintf("tikclay_%d_%d", instanceid, index))
+
+ if (kfreq == 0) then
+ if (kreset == 0) then
+ kreset = 1
+ endif
+ kplaying = 0
+ else
+ kplaying = 1
+ endif
+
+ if (kreset == 1) then
+ kfileid = gitikfn_clay[round:k(random:k(0, lenarray:k(gitikfn_clay) - 1))]
+ kdur = random:k(0.4, 1.3) * gisounddb[kfileid][2]
+ kpitch = random:k(0.1, 2.2)
+ kwsize = random:k(44, 441)
+ krandw = kwsize / 10
+ kpan = random:k(0, 1)
+ kresonfreq = cpsmidinn:k(mel_randomnote:k()) * 2
+ if (random:k(0, 1) >= 0.5) then
+ kresonfreq *= 2
+ endif
+ kreset = 0
+ endif
+
+ if (kplaying == 1) then
+ kmetro metro kfreq, random(0, 1)
+ if (kmetro == 1) then
+ kresonchance = chnget:k(sprintf("tikclay_resonchance_%d", instanceid))
+ kdoreson = (random:k(0, 0.99999) < kresonchance) ? 1 : 0
+ schedulek "_tik_clay_play", 0, kdur, instanceid, kfileid, kpitch, kwsize, krandw, kpan, kresonfreq, kdoreson
+ endif
+ endif
+endin
+
+
+opcode tik_clay_bank, iaa, i
+ inum xin
+
+ icollection[] = gitikfn_clay
+ instanceid = uniqueid()
+
+ iusedinstruments[] uniqueinstrnums "_tik_clay_item", inum
+
+ index = 0
+ ifileindex = 0
+ while (index < lenarray(iusedinstruments)) do
+ ifileid = icollection[ifileindex]
+
+ schedule iusedinstruments[index], 0, p3, instanceid, index
+ if (ifileindex + 1 < lenarray(icollection)) then
+ ifileindex += 1
+ else
+ ifileindex = 0
+ endif
+ index += 1
+ od
+
+ if (release:k() == 1) then
+ kindex = 0
+ while (kindex < lenarray(iusedinstruments)) do
+ turnoff2 iusedinstruments[kindex], 4, 1
+ kindex += 1
+ od
+ endif
+
+ aL, aR bus_read sprintf("tikclayaudio%d", instanceid)
+ xout instanceid, aL, aR
+endop
+
+#end
diff --git a/site/udo/fnml/instrument_vocal.udo b/site/udo/fnml/instrument_vocal.udo
new file mode 100755
index 0000000..f5ac011
--- /dev/null
+++ b/site/udo/fnml/instrument_vocal.udo
@@ -0,0 +1,73 @@
+#ifndef UDO_FNMI_VOCAL
+#define UDO_FNMI_VOCAL ##
+
+#include "wavetables.udo"
+#include "sequencing_melodic.udo"
+#include "sounddb.udo"
+#include "bussing.udo"
+
+
+i_[], gifnmi_vocal_collectionid sounddb_getcollection "VocalAhh1"
+
+
+opcode fnmi_vocal_chord, aa, kpj
+ ktrig, iaddoctave, ireadattackratio xin
+ icollectionid = gifnmi_vocal_collectionid
+ ireadattackratio = (ireadattackratio == -1) ? 0.1 : ireadattackratio
+ if (ktrig == 1) then
+ klen = mel_length:k()
+ knotenum = table:k(0, gimel_current_notes)
+ kpanstep = 1 / knotenum
+ kindex = 0
+ while (kindex < knotenum) do
+ kpan = kpanstep * kindex
+ schedulek "fnmi_vocal", 0, klen, icollectionid, table:k(kindex+1, gimel_current_notes), kpan, ireadattackratio
+ if (iaddoctave == 1) then
+ schedulek "fnmi_vocal", 0, klen, icollectionid, table:k(kindex+1, gimel_current_notes) + 12, 1-kpan, ireadattackratio
+ endif
+ kindex += 1
+ od
+ endif
+ aL, aR bus_read "fnmi_vocal_chord"
+ xout aL, aR
+endop
+
+/*
+instr tester
+ ktrig = 0
+ if (gkmel_section_change == 1) then
+ ktrig = 1
+ endif
+ aL, aR fnmi_vocal_chord ktrig
+ outs aL, aR
+endin
+*/
+
+instr fnmi_vocal
+ icollectionid = p4
+ inote = p5
+ ipan = p6
+ ireadattackratio = p7
+ ifileid, ipitchratio sounddb_mel_nearestnote icollectionid, inote
+ ifn = gisounddb[ifileid][0]
+ ilen = gisounddb[ifileid][2]
+ idur = p3
+ kamp linseg 1, idur*0.1, 1, idur*0.5, 1, idur*0.4, 0
+ ireadrate random 0.01, 1
+
+ ivibrate = random(0.25, 4)
+ klfo oscil 0.006, ivibrate, gifnSine
+ kpitchratio = ipitchratio + klfo
+
+ atime = abs:a(oscil:a(0.68, ireadrate))
+ if (ireadattackratio != 0) then
+ atime = (delay:a(atime, idur*ireadattackratio) + linseg:a(0, idur*ireadattackratio, 0.1)) * ilen
+ endif
+
+ aL, aR mincer atime, kamp*0.2, kpitchratio, ifn, 1, 2048
+ aL butterhp aL, 340
+ aR butterhp aR, 340
+ bus_mix("fnmi_vocal_chord", aL*ipan, aR*(1-ipan))
+endin
+
+#end
diff --git a/site/udo/fnml/transition_click.udo b/site/udo/fnml/transition_click.udo
new file mode 100755
index 0000000..c39338c
--- /dev/null
+++ b/site/udo/fnml/transition_click.udo
@@ -0,0 +1,143 @@
+#ifndef UDO_TRANSITION_CLICK
+#define UDO_TRANSITION_CLICK ##
+
+#include "sequencing_scheduled.udo"
+#include "sequencing_melodic_portamento.udo"
+#include "uniqueid.udo"
+#include "bussing.udo"
+#include "sounddb.udo"
+
+
+gifnmt_clickfn[] sounddb_getcollection "Snare.Regular,Hihat.Closed"
+
+
+instr fnmt_clickplay
+ istartbeats = p4 ; number of beats before next event point as specified in iwaitmode
+ iwaitmode = p5 ; -1 = start of next bar, -2 = start of next bargroup , any other = number of total beats before event point
+ iampmode = p6 ; 0 = linear, 1 = exponential, 2 = random (randomises each individually)
+ idorelease = p7 ; do release, 0 or 1
+ idotune = p8 ; do tuning, 0 or 1
+ idorandom = p9 ; do random sound selection for each click
+ Sbus = strget(p10) ; bus to send to ; defaults to "main"
+ SonHit = strget(p11) ; instrument to call when hit point is reached
+
+
+ if (strcmp(Sbus, "") == 0) then
+ Sbus = "main"
+ endif
+
+ p3 = 600
+
+ if (iwaitmode == -1) then
+ kwaittrig = bar_lastbeatxof(istartbeats)
+ elseif (iwaitmode == -2) then
+ kwaittrig = bargroup_lastbeatxof(istartbeats)
+ else
+ kwaittrig = lastbeatxof(iwaitmode, istartbeats)
+ endif
+ if (kwaittrig == 1) then
+ schedulek "_fnmt_clickplay", 0, i(gkseq_beattime) * istartbeats, iampmode, idorelease, idotune, idorandom, Sbus, SonHit
+ turnoff
+ endif
+endin
+
+
+
+instr _fnmt_clickplay
+ imode = p4 ; 0 = linear, 1 = exponential, 2 = random (randomises each individually)
+ idorelease = p5
+ idotune = p6
+ idorandom = p7
+ Sbus = p8
+ SonHit = p9
+
+ ichannelid = uniqueid()
+ ibeattime = i(gkseq_beattime)
+ itempo = i(gkseq_tempo)
+ ireltime = (idorelease == 1) ? random(ibeattime, ibeattime*4) : 0
+ imtime = p3
+ ibeathz = itempo / 60
+
+ if (strcmp(SonHit, "") != 0) then
+ schedule(SonHit, imtime, 1)
+ endif
+
+ if (imode == 0 || (imode == 2 && random(0, 1) >= 0.5)) then
+ kfreq linsegr ibeathz * round(random(4, 16)), imtime, ibeathz * round(random(4, 16)), ireltime, ibeathz * round(random(4, 16))
+ else
+ kfreq expsegr ibeathz * round(random(4, 16)), imtime, ibeathz * round(random(4, 16)), ireltime, ibeathz * round(random(4, 16))
+ endif
+
+ iminpitch = 6
+ imaxpitch = 20
+ if (imode == 0 || (imode == 2 && random(0, 1) >= 0.5)) then
+ kpitch linsegr random(iminpitch, imaxpitch), imtime, random(iminpitch, imaxpitch), ireltime, random(iminpitch, imaxpitch)
+ else
+ kpitch expsegr random(iminpitch, imaxpitch), imtime, random(iminpitch, imaxpitch), ireltime, random(iminpitch, imaxpitch)
+ endif
+
+ if (imode == 0 || (imode == 2 && random(0, 1) >= 0.5)) then
+ kpan linsegr random(0, 1), imtime, random(0, 1), ireltime, random(0, 1)
+ else
+ kpan expsegr random(0.0001, 1), imtime, random(0.0001, 1), ireltime, random(0.0001, 1)
+ endif
+
+ if (imode == 0 || (imode == 2 && random(0, 1) >= 0.5)) then
+ kamp linsegr 0, p3, 1, ireltime, 0
+ else
+ kamp expsegr 0.0001, imtime, 1, ireltime, 0.0001
+ endif
+
+
+ if (idorandom == 1) then
+ ifn = -1
+ ichans = -1
+ idur = 1
+ else
+ ifileid = gifnmt_clickfn[round(random(0, lenarray(gifnmt_clickfn) - 1))]
+ ifn = gisounddb[ifileid][0]
+ ichans = gisounddb[ifileid][1]
+ idur = gisounddb[ifileid][2]
+ endif
+
+
+ kmetro metro kfreq
+ if (kmetro == 1) then
+ schedulek "_fnmt_clickitem", 0, idur / kpitch, ifn, kamp, kpitch, kpan, ichannelid, ichans
+ endif
+
+ aL, aR bus_read sprintf("fnmt_click%d", ichannelid)
+
+ if (idotune == 1) then
+ aL, aR mel_tune_portamento aL, aR, 0, 2
+ endif
+
+ bus_mix(Sbus, aL, aR)
+endin
+
+instr _fnmt_clickitem
+ ifn = p4
+ iamp = p5
+ ipitch = p6
+ ipan = p7
+ ichannelid = p8
+ ichans = p9
+
+ if (ifn == -1) then ; random sound
+ ifileid = gifnmt_clickfn[round(random(0, lenarray(gifnmt_clickfn) - 1))]
+
+ ifn = gisounddb[ifileid][0]
+ ichans = gisounddb[ifileid][1]
+ p3 = gisounddb[ifileid][2] / ipitch
+ endif
+
+ if (ichans == 2) then
+ a1, a_ loscil iamp, ipitch, ifn, 1
+ else
+ a1 loscil iamp, ipitch, ifn, 1
+ endif
+ aL, aR pan2 a1, ipan
+ bus_mix(sprintf("fnmt_click%d", ichannelid), aL, aR)
+endin
+
+#end
diff --git a/site/udo/fnml/transition_mburn.udo b/site/udo/fnml/transition_mburn.udo
new file mode 100755
index 0000000..f8d35f1
--- /dev/null
+++ b/site/udo/fnml/transition_mburn.udo
@@ -0,0 +1,186 @@
+#ifndef UDO_TRANSITION_MBURN
+#define UDO_TRANSITION_MBURN ##
+
+
+/*
+
+ TODO: use database loads for sounds ie
+
+
+ #include "sound_sdb.udo"
+
+ gifnmt_mbstart[][] sdb_getcollection "MBurn1.Start"
+ gifnmt_mbmid[][] sdb_getcollection "MBurn1.Middle"
+ gifnmt_mbend[][] sdb_getcollection "MBurn1.End"
+*/
+
+#include "sound_db.udo" ; for local sound loads
+#include "sequencing_scheduled.udo"
+#include "sequencing_melodic_portamento.udo" ; for tuning
+#include "wavetables.udo" ; for tuning
+#include "bussing.udo"
+#include "host_tools.udo" ; for dir_random
+#include "uniqueid.udo" ; for channels
+
+
+gifnmt_mbstart[] rdb_loaddir dir_random("2021/mBurn-New/Start")
+gifnmt_mbmid[] rdb_loaddir dir_random("2021/mBurn-New/Middle")
+gifnmt_mbend[] rdb_loaddir dir_random("2021/mBurn-New/End")
+
+
+/*
+ Play mBurn transition
+
+ p4 number of beats before next event as specified in iwaitmode
+ p5 wait mode: -1 = start of next bar, -2 = start of next bargroup , any other = number of total beats before event point (0 = immediate)
+ p6 tune mode: 0 = none, 1 = all, 2 = random
+ p7 bus name to send output to (0 = main)
+*/
+instr fnmt_mburnplay
+ istartbeats = p4
+ iwaitmode = p5
+ itunemode = p6
+
+ if (p7 == 0) then
+ Sbus = "main"
+ else
+ Sbus = p7
+ endif
+
+ p3 = 600
+
+ if (iwaitmode == -1) then
+ kwaittrig = bar_lastbeatxof(istartbeats)
+ elseif (iwaitmode == -2) then
+ kwaittrig = bargroup_lastbeatxof(istartbeats)
+ elseif (iwaitmode == 0) then
+ kwaittrig init 1
+ else
+ kwaittrig = lastbeatxof(iwaitmode, istartbeats)
+ endif
+
+ if (kwaittrig == 1) then
+ schedulek "_fnmt_mburnplay", 0, i(gkseq_beattime) * istartbeats, itunemode, Sbus
+ turnoff
+ endif
+
+endin
+
+
+instr _fnmt_mburnitem
+ ifn = p4
+ imode = p5
+ itune = p6
+ ichannel = p7
+ ireverseread = p8
+ iampmode = p9 ; ; 0 = linear amp, 1 = exponential amp, 2 = no envelope
+ isounddur = p10
+
+
+ ; start
+ if (imode == 1) then
+ if (iampmode == 0) then
+ kamp linseg 0, p3, 1
+ elseif (iampmode == 1) then
+ kamp expseg 0.00001, p3, 1
+ else
+ kamp init 1
+ endif
+
+ ; middle
+ elseif (imode == 2) then
+ if (iampmode == 2) then ; mid = no env choice really
+ kamp init 1
+ else
+ kamp linseg 1, p3*0.8, 1, p3*0.2, 0
+ endif
+
+ ; end
+ elseif (imode == 3) then
+ if (iampmode == 0) then
+ kamp linseg 1, p3, 0 ;linseg 0, p3*0.1, 1, p3*0.5, 1, p3*0.4, 0
+ elseif (iampmode == 1) then
+ kamp expseg 1, p3, 0.00001
+ else
+ kamp init 1
+ endif
+ endif
+
+ atime line 0, p3, isounddur
+
+ if (ireverseread == 1) then
+ atime = isounddur - atime
+ endif
+
+ arepitch init 1;linseg 1, p3, 0.5
+
+ iwinsize = round(random(441, 4410))
+ irandwin = iwinsize / 10
+ aL, aR sndwarpst 1, atime, arepitch, ifn, 0, iwinsize, irandwin, 4, gifnHalfSine, 1
+
+ if (itune >= 1) then
+ ;aL, aR mel_tune aL, aR, gifnSaw, 10, 512, 4
+ aL, aR mel_tune_portamento aL, aR, gifnSine, 16, 1024, 4
+ endif
+ aL = aL*kamp
+ aR = aR*kamp
+ chnmix aL, sprintf("mburn%dL", ichannel)
+ chnmix aR, sprintf("mburn%dR", ichannel)
+endin
+
+
+instr _fnmt_mburnplay
+ itunemode = p4
+ Sbus = p5
+
+ ichannelid = uniqueid()
+ idorelease = 1
+
+ ibeattime = i(gkseq_beattime)
+
+ istartdur = p3
+ imiddur = random(ibeattime, ibeattime*2)
+ ienddur = (idorelease == 1) ? random(ibeattime, ibeattime*4) : 0
+
+
+
+ istartfn[] get_sound gifnmt_mbstart[round(random(0, lenarray(gifnmt_mbstart) - 1))]
+ imidfn[] get_sound gifnmt_mbmid[round(random(0, lenarray(gifnmt_mbmid) - 1))]
+
+ if (idorelease == 1) then
+ iendfn[] get_sound gifnmt_mbend[round(random(0, lenarray(gifnmt_mbend) - 1))]
+ endif
+
+ if (itunemode == 0) then
+ itunestart = 0
+ itunemid = 0
+ ituneend = 0
+ elseif (itunemode == 1) then
+ itunestart = 1
+ itunemid = 1
+ ituneend = 1
+ elseif (itunemode == 2) then
+ itunestart = round(random(0, 1))
+ itunemid = round(random(0, 1))
+ ituneend = round(random(0, 1))
+ endif
+
+ iampmodestart = 0 ; 0 = linear amp, 1 = exponential amp
+ iampmodeend = 0 ; 0 = linear amp, 1 = exponential amp
+ ireversereadstart = round(random(0, 1))
+ ireversereadend = round(random(0, 1))
+
+ event_i "i", "_fnmt_mburnitem", 0, istartdur, istartfn[0], 1, itunestart, ichannelid, ireversereadstart, iampmodestart, istartfn[3]
+ event_i "i", "_fnmt_mburnitem", istartdur, imiddur, imidfn[0], 2, itunemid, ichannelid, 0, 1, imidfn[3]
+
+ if (idorelease == 1) then
+ event_i "i", "_fnmt_mburnitem", istartdur, ienddur, iendfn[0], 3, ituneend, ichannelid, ireversereadend, iampmodeend, iendfn[3]
+ xtratim ienddur + 3
+ endif
+
+
+ aL, aR bus_read sprintf("mburn%d", ichannelid)
+ bus_mix(Sbus, aL, aR)
+endin
+
+#end
diff --git a/site/udo/fnml/transition_snare.udo b/site/udo/fnml/transition_snare.udo
new file mode 100755
index 0000000..16ed2e2
--- /dev/null
+++ b/site/udo/fnml/transition_snare.udo
@@ -0,0 +1,140 @@
+#ifndef UDO_TRANSITION_SNARE
+#define UDO_TRANSITION_SNARE ##
+
+#include "sequencing_scheduled.udo"
+#include "sequencing_melodic_portamento.udo"
+#include "uniqueid.udo"
+#include "bussing.udo"
+#include "sounddb.udo"
+
+gifnmt_rollfndamp[] sounddb_getcollection "Snare.Dampened"
+gifnmt_rollfnregular[] sounddb_getcollection "Snare.Regular"
+gifnmt_rollfnrimhard[] sounddb_getcollection "Snare.Rim.Hard"
+gifnmt_rollfnrimsoft[] sounddb_getcollection "Snare.Rim.Soft"
+gifnmt_rollfnunrestrained[] sounddb_getcollection "Snare.Unrestrained"
+
+
+instr fnmt_rollplay
+ istartbeats = p4 ; number of beats before next event as specified in iwaitmode
+ iwaitmode = p5 ; -1 = start of next bar, -2 = start of next bargroup , any other = number of total beats before event point
+ iampmode = p6 ; 0 = linear, 1 = exponential, 2 = random (randomises each individually)
+ idorelease = p7 ; do release, 0 or 1
+ idotune = p8 ; do tuning, 0 or 1
+ idorandom = p9 ; do random sound selection for each click
+ Sbus = strget(p10) ; bus to send to ; defaults to "main"
+ SonHit = strget(p11) ; instrument to call when hit point is reached
+
+ if (strcmp(Sbus, "") == 0) then
+ Sbus = "main"
+ endif
+
+ p3 = 600
+
+ if (iwaitmode == -1) then
+ kwaittrig = bar_lastbeatxof(istartbeats)
+ elseif (iwaitmode == -2) then
+ kwaittrig = bargroup_lastbeatxof(istartbeats)
+ else
+ kwaittrig = lastbeatxof(iwaitmode, istartbeats)
+ endif
+
+ if (kwaittrig == 1) then
+ schedulek "_fnmt_rollplay1", 0, i(gkseq_beattime) * istartbeats, iampmode, idorelease, idotune, idorandom, Sbus, SonHit
+ turnoff
+ endif
+endin
+
+
+
+instr _fnmt_rollplay1
+ imode = p4 ; 0 = linear, 1 = exponential, 2 = random (randomises each individually)
+ idorelease = p5
+ idotune = p6
+ idorandom = p7
+ Sbus = p8
+ SonHit = p9
+
+ ichannelid = uniqueid()
+ if (idotune == 1) then ; TODO: separate channel for tuned ones
+ ichannelidtuned = uniqueid()
+ endif
+
+ ibeattime = i(gkseq_beattime)
+ itempo = i(gkseq_tempo)
+ ibeathz = itempo / 60
+ ireltime = (idorelease == 1) ? random(ibeattime, ibeattime*4) : 0
+ imtime = p3
+
+ if (strcmp(SonHit, "") != 0) then
+ schedule(SonHit, imtime, 1)
+ endif
+
+ krelease release
+
+ if (imode == 0 || (imode == 2 && random(0, 1) >= 0.5)) then
+ kfreq linsegr ibeathz * round(random(4, 16)), imtime, ibeathz * round(random(4, 16)), ireltime, ibeathz * round(random(4, 16))
+ else
+ kfreq expsegr ibeathz * round(random(4, 16)), imtime, ibeathz * round(random(4, 16)), ireltime, ibeathz * round(random(4, 16))
+ endif
+
+ if (imode == 0 || (imode == 2 && random(0, 1) >= 0.5)) then
+ kamp linsegr 0, p3, 1, ireltime, 0
+ else
+ kamp expsegr 0.0001, imtime, 1, ireltime, 0.0001
+ endif
+
+ ichancepercent = 100
+
+ kmetro metro kfreq
+ ktrig = (kmetro == 1 && random:k(0, 100) < ichancepercent) ? 1: 0
+
+ ksampleset = 1
+ if (krelease == 1) then
+ ksampleset = 0
+ endif
+
+ if (ktrig == 1) then
+ event "i", "_fnmt_rollitem", 0, 1, ksampleset, kamp, ichannelid
+ endif
+
+ aL, aR bus_read sprintf("fnmt_roll%d", ichannelid)
+
+ if (idotune == 1) then
+ aL, aR mel_tune_portamento aL, aR, 0, 16
+ aL butterhp aL, 120
+ aR butterhp aR, 120
+ endif
+
+ bus_mix(Sbus, aL, aR)
+endin
+
+
+
+instr _fnmt_rollitem
+ isampleset = p4
+ iamp = p5
+ ichannelid = p6
+ if (isampleset == 0) then
+ ifileid = gifnmt_rollfndamp[round(random(0, lenarray(gifnmt_rollfndamp) - 1))]
+
+ elseif (isampleset == 1) then
+ ifileid = gifnmt_rollfnrimhard[round(random(0, lenarray(gifnmt_rollfnrimhard) - 1))]
+
+ endif
+
+ ;index = round(random(0, gimaxes[isampleset] - 1))
+ ;ifn = gisamples[isampleset][index]
+ ;p3 = (ftlen(ifn) / ftsr(ifn)) + 0.1
+
+ p3 = gisounddb[ifileid][2]
+ ifn = gisounddb[ifileid][0]
+ if (gisounddb[ifileid][1] == 2) then
+ aL, aR loscil iamp, 1, ifn, 1
+ else
+ aL loscil iamp, 1, ifn, 1
+ aR = aL
+ endif
+ bus_mix(sprintf("fnmt_roll%d", ichannelid), aL, aR)
+endin
+
+#end
diff --git a/site/udo/fnml/transition_snare_preSOUNDDB.udo b/site/udo/fnml/transition_snare_preSOUNDDB.udo
new file mode 100755
index 0000000..70df4e2
--- /dev/null
+++ b/site/udo/fnml/transition_snare_preSOUNDDB.udo
@@ -0,0 +1,133 @@
+#ifndef UDO_TRANSITION_SNARE
+#define UDO_TRANSITION_SNARE ##
+
+#include "sequencing_scheduled.udo"
+#include "sequencing_melodic_portamento.udo"
+#include "uniqueid.udo"
+#include "bussing.udo"
+#include "sound_sdb.udo"
+
+gifnmt_rollfndamp[][] sdb_getcollection "Snare.Dampened"
+gifnmt_rollfnregular[][] sdb_getcollection "Snare.Regular"
+gifnmt_rollfnrimhard[][] sdb_getcollection "Snare.Rim.Hard"
+gifnmt_rollfnrimsoft[][] sdb_getcollection "Snare.Rim.Soft"
+gifnmt_rollfnunrestrained[][] sdb_getcollection "Snare.Unrestrained"
+
+
+instr fnmt_rollplay
+ istartbeats = p4 ; number of beats before next event as specified in iwaitmode
+ iwaitmode = p5 ; -1 = start of next bar, -2 = start of next bargroup , any other = number of total beats before event point
+ iampmode = p6 ; 0 = linear, 1 = exponential, 2 = random (randomises each individually)
+ idorelease = p7 ; do release, 0 or 1
+ idotune = p8 ; do tuning, 0 or 1
+ idorandom = p9 ; do random sound selection for each click
+
+ if (p10 == 0) then
+ Sbus = "main"
+ else
+ Sbus = p10
+ endif
+
+ p3 = 600
+
+ if (iwaitmode == -1) then
+ kwaittrig = bar_lastbeatxof(istartbeats)
+ elseif (iwaitmode == -2) then
+ kwaittrig = bargroup_lastbeatxof(istartbeats)
+ else
+ kwaittrig = lastbeatxof(iwaitmode, istartbeats)
+ endif
+
+ if (kwaittrig == 1) then
+ schedulek "_fnmt_rollplay1", 0, i(gkseq_beattime) * istartbeats, iampmode, idorelease, idotune, idorandom, Sbus
+ turnoff
+ endif
+endin
+
+
+
+instr _fnmt_rollplay1
+ imode = p4 ; 0 = linear, 1 = exponential, 2 = random (randomises each individually)
+ idorelease = p5
+ idotune = p6
+ idorandom = p7
+ Sbus = p8
+
+ ichannelid = uniqueid()
+ if (idotune == 1) then ; TODO: separate channel for tuned ones
+ ichannelidtuned = uniqueid()
+ endif
+
+ ibeattime = i(gkseq_beattime)
+ itempo = i(gkseq_tempo)
+ ibeathz = itempo / 60
+ ireltime = (idorelease == 1) ? random(ibeattime, ibeattime*4) : 0
+ imtime = p3
+
+ krelease release
+
+ if (imode == 0 || (imode == 2 && random(0, 1) >= 0.5)) then
+ kfreq linsegr ibeathz * round(random(4, 16)), imtime, ibeathz * round(random(4, 16)), ireltime, ibeathz * round(random(4, 16))
+ else
+ kfreq expsegr ibeathz * round(random(4, 16)), imtime, ibeathz * round(random(4, 16)), ireltime, ibeathz * round(random(4, 16))
+ endif
+
+ if (imode == 0 || (imode == 2 && random(0, 1) >= 0.5)) then
+ kamp linsegr 0, p3, 1, ireltime, 0
+ else
+ kamp expsegr 0.0001, imtime, 1, ireltime, 0.0001
+ endif
+
+ ichancepercent = 100
+
+ kmetro metro kfreq
+ ktrig = (kmetro == 1 && random:k(0, 100) < ichancepercent) ? 1: 0
+
+ ksampleset = 1
+ if (krelease == 1) then
+ ksampleset = 0
+ endif
+
+ if (ktrig == 1) then
+ event "i", "_fnmt_rollitem", 0, 1, ksampleset, kamp, ichannelid
+ endif
+
+ aL, aR bus_read sprintf("fnmt_roll%d", ichannelid)
+
+ if (idotune == 1) then
+ aL, aR mel_tune_portamento aL, aR, 0, 16
+ aL butterhp aL, 120
+ aR butterhp aR, 120
+ endif
+
+ bus_mix(Sbus, aL, aR)
+endin
+
+
+
+instr _fnmt_rollitem
+ isampleset = p4
+ iamp = p5
+ ichannelid = p6
+ if (isampleset == 0) then
+ isound[] get_sound gifnmt_rollfndamp[round(random(0, lenarray(gifnmt_rollfndamp) - 1))][0]
+ elseif (isampleset == 1) then
+ isound[] get_sound gifnmt_rollfnrimhard[round(random(0, lenarray(gifnmt_rollfnrimhard) - 1))][0]
+ endif
+
+ ;index = round(random(0, gimaxes[isampleset] - 1))
+ ;ifn = gisamples[isampleset][index]
+ ;p3 = (ftlen(ifn) / ftsr(ifn)) + 0.1
+
+ p3 = isound[3]
+ ifn = isound[0]
+ if (isound[2] == 2) then
+ aL, aR loscil iamp, 1, ifn, 1
+ else
+ aL loscil iamp, 1, ifn, 1
+ aR = aL
+ endif
+ bus_mix(sprintf("fnmt_roll%d", ichannelid), aL, aR)
+endin
+
+#end
diff --git a/site/udo/fnml/transition_test.csd b/site/udo/fnml/transition_test.csd
new file mode 100755
index 0000000..d8c7542
--- /dev/null
+++ b/site/udo/fnml/transition_test.csd
@@ -0,0 +1,39 @@
+<CsoundSynthesizer>
+<CsOptions>
+-odac
+</CsOptions>
+<CsInstruments>
+sr = 44100
+kr = 4410
+nchnls = 2
+0dbfs = 1
+seed 0
+
+#include "fnml/transition_click.udo"
+#include "fnml/transition_snare.udo"
+#include "fnml/transition_mburn.udo"
+#include "bussing.udo"
+
+instr debug
+ a1 metronome
+ outs a1, a1
+endin
+
+
+instr master
+ ;schedule "fnmt_clickplay", 1, 1, 6, -1, 2, 1, 0, 0, "main"
+ ;schedule "fnmt_rollplay", 1, 1, 6, -1, 2, 1, 0, 0, "main"
+ schedule "fnmt_mburnplay", 1, 1, 6, -1, 0, "main"
+
+ aL, aR bus_read "clicktest"
+ aL, aR freeverb aL, aR, 0.7, 0.4
+ outs aL, aR
+endin
+
+
+</CsInstruments>
+<CsScore>
+i"master" 0 510
+i"debug" 0 501
+</CsScore>
+</CsoundSynthesizer> \ No newline at end of file
diff --git a/site/udo/fnml/transitional/base.udo b/site/udo/fnml/transitional/base.udo
new file mode 100755
index 0000000..ba40fbc
--- /dev/null
+++ b/site/udo/fnml/transitional/base.udo
@@ -0,0 +1,141 @@
+#ifndef UDO_FNML_TRANSITIONBASE
+#define UDO_FNML_TRANSITIONBASE ##
+
+instr fnm_transitionplayer
+ if (gifirsttransition == 1) then
+ StransInstrument = "fnm_trans5"
+ gifirsttransition = 0
+ else
+ StransInstrument = arr_random(gSfnm_transitionitems)
+ endif
+ schedule StransInstrument, 0, 36000
+
+ kreleasing init 0
+ if (release:k() == 1 && kreleasing == 0) then
+ turnoff2 StransInstrument, 0, 1
+ kreleasing = 1
+ endif
+ aL, aR bus_read "fnm_transition"
+ bus_mix("master", aL, aR)
+endin
+
+instr fnm_sectionplayer
+ SnoteInstrument = arr_random(gSfnm_chorditems)
+ SbassInstrument = arr_random(gSfnm_bassitems)
+ SaugInstrument = arr_random(gSfnm_augmentitems)
+ iplaybass = (random(0, 1) >= 0.44) ? 1 : 0
+ iplayaugment = (random(0, 1) >= 0.34) ? 1 : 0
+
+
+ if (random(0, 1) >= 0.5) then
+ ifadeintime = random(0.1, 3)
+ else
+ ifadeintime = 0
+ endif
+ index = 0
+ while (index < table:i(0, gimel_current_notes)) do
+ inoteaugment = (random(0, 1) >= 0.7) ? 12 : 0
+ schedule SnoteInstrument, 0, p3, table:i(index+1, gimel_current_notes) + inoteaugment, ifadeintime
+ index += 1
+ od
+ if (iplaybass == 1) then
+ ibassnoteindex = round(random(1, 3))
+ schedule SbassInstrument, 0, p3, table:i(ibassnoteindex, gimel_current_notes) - 24
+ endif
+ if (iplayaugment == 1) then
+ schedule SaugInstrument, 0, p3
+ endif
+
+ aL, aR bus_read "fnm_chordnote"
+ if (random(0, 1) > 0.6) then
+ aLc, aRc simplechorus aL, aR, 0.004, 0.001
+ aL += aLc
+ aR += aRc
+ endif
+ aL butterhp aL, 120
+ aR butterhp aR, 120
+
+ if (iplaybass == 1) then
+ aLb, aRb bus_read "fnm_chordbass"
+ aL += aLb
+ aR += aRb
+ endif
+
+ if (iplayaugment == 1) then
+ aLa, aRa bus_read "fnm_augment"
+ aL += aLa
+ aR += aRa
+ endif
+
+ kamp linseg 1, p3, 1, 0.1, 0
+ aL *= kamp
+ aR *= kamp
+
+ kduck = port(gkduck, 0.1)
+ aL *= (1 - kduck)
+ aR *= (1 - kduck)
+ bus_mix("master", aL*0.8, aR*0.8)
+
+ kreleasing init 0
+ if (release:k() == 1 && kreleasing == 0) then
+ turnoff2 SnoteInstrument, 0, 1
+ if (iplaybass == 1) then
+ turnoff2 SbassInstrument, 0, 1
+ endif
+ if (iplayaugment == 1) then
+ turnoff2 SaugInstrument, 0, 1
+ endif
+ kreleasing = 1
+ endif
+endin
+
+
+instr fnm_sectionmanager
+ gkmel_pause = 1
+
+ ksectionstart init 0.01
+ ksectionchange = 0
+ ktransitioner = chnget:k("fnm_transition")
+ kadvance = chnget:k("fnm_advance")
+ krepeat = chnget:k("fnm_repeat")
+
+ if (changed:k(ktransitioner) == 1) then
+ if (ktransitioner == 0) then
+ turnoff2 "fnm_transitionplayer", 0, 1
+ if (random:k(0, 1) > 0.5) then ; have ultimate transition
+ if (random:k(0, 1) > 0.5) then ; no other output during ultimate transition
+ turnoff2 "fnm_sectionplayer", 0, 1
+ endif
+ gkutransitiontime = random:k(0.2, 1)
+ schedulek("fnm_ultimatetransitionplayer", 0, gkutransitiontime)
+ ksectionstart = gkutransitiontime
+ else
+ gkutransitiontime = 0
+ ksectionstart = 0.01
+ endif
+ ksectionchange = 1
+ else
+ schedulek("fnm_transitionplayer", 0, 36000)
+ endif
+ endif
+
+ if (ksectionchange == 1 || (changed:k(kadvance) == 1 && kadvance == 1) || (changed:k(krepeat) == 1 && krepeat == 1)) then
+ if (krepeat == 1) then
+ ksectionstart = 0
+ endif
+ turnoff2 "fnm_sectionplayer", 0, 1
+ if (krepeat != 1) then
+ gkmel_advance_trig = 1
+ endif
+ schedulek("fnm_sectionplayer", ksectionstart, 36000)
+ endif
+
+ kreleasing init 0
+ if (release:k() == 1 && kreleasing == 0) then
+ turnoff2 "fnm_sectionplayer", 0, 1
+ kreleasing = 1
+ endif
+
+endin
+
+#end \ No newline at end of file