diff options
Diffstat (limited to 'site/udo/twist/twist.udo')
-rwxr-xr-x | site/udo/twist/twist.udo | 1304 |
1 files changed, 1304 insertions, 0 deletions
diff --git a/site/udo/twist/twist.udo b/site/udo/twist/twist.udo new file mode 100755 index 0000000..34fa7cb --- /dev/null +++ b/site/udo/twist/twist.udo @@ -0,0 +1,1304 @@ +#ifndef UDO_TWIST
+#define UDO_TWIST ##
+/*
+ Twist
+ Waveform editor and transformer
+
+ This file is part of the SONICS UDO collection by Richard Knight 2024
+ License: GPL-2.0-or-later
+ http://1bpm.net
+*/
+
+
+#include "/table_tools.udo"
+#include "/host_platform.udo"
+#include "/wavetables.udo"
+#include "/interop.udo"
+#include "/bussing.udo"
+#include "/chop.udo"
+#include "/transient_detect.udo"
+
+#ifdef TWST_FAILONLAG
+#include "/lagdetect.udo"
+#end
+
+gitwst_userstopped = 0
+imaxinstances = 16
+gitwst_instanceindex = 0
+gitwst_channels[] init imaxinstances
+gitwst_duration[] init imaxinstances
+gitwst_bufferL[] init imaxinstances
+gitwst_bufferR[] init imaxinstances
+
+gitwst_copyBufferL = 0
+gitwst_copyBufferR = 0
+
+gitwst_tf_state[] init 7
+
+#include "/twist/checkpointing.udo"
+
+opcode twst_clearbuffers, 0, jj
+ ibufferL, ibufferR xin
+ ibufferL = (ibufferL == -1) ? gitwst_bufferL[gitwst_instanceindex] : ibufferL
+ ibufferR = (ibufferR == -1) ? gitwst_bufferR[gitwst_instanceindex] : ibufferR
+
+ if (ibufferL > 0 && ftexists(ibufferL) == 1) then
+ ftfree ibufferL, 1
+ endif
+ if (ibufferR > 0 && ftexists(ibufferR) == 1) then
+ ftfree ibufferR, 1
+ endif
+endop
+
+opcode twst_samplestoratio, ii, iij
+ istart, iend, instanceindex xin
+ instanceindex = (instanceindex == -1) ? gitwst_instanceindex : instanceindex
+ itotallen = ftlen(gitwst_bufferL[instanceindex])
+ if (istart > 1 && iend > 1) then
+ istart /= itotallen
+ iend /= itotallen
+ endif
+ xout istart, iend
+endop
+
+opcode twst_getstartend, iii, iij
+ istart, iend, instanceindex xin
+ instanceindex = (instanceindex == -1) ? gitwst_instanceindex : instanceindex
+ itotallen = ftlen(gitwst_bufferL[instanceindex])
+ if (istart <= 1 && iend <= 1) then
+ istart *= itotallen
+ iend *= itotallen
+ ilen = int(iend - istart)
+ istart = int(istart)
+ iend = int(iend)
+ else
+ istart = max(0, istart)
+ iend = min(itotallen, iend)
+ ilen = iend - istart
+ endif
+ xout istart, ilen, iend
+endop
+
+opcode twst_getstartend, ii, iij
+ istart, iend, instanceindex xin
+ istart, ilen, iend twst_getstartend istart, iend, instanceindex
+ xout istart, ilen
+endop
+
+#include "/twist/transform_api.udo"
+
+opcode twst_createoverviewsextra, S, iSjjjp
+ icbid, Sextra, iselstart, iselend, instanceindex, istatus xin
+ instanceindex = (instanceindex == -1) ? gitwst_instanceindex : instanceindex
+
+ iduration = ftlen(gitwst_bufferL[instanceindex]) / ftsr(gitwst_bufferL[instanceindex])
+ if (qnan(iduration) == 1) then
+ iduration = 1
+ endif
+ gitwst_duration[instanceindex] = iduration
+ Sresponse = sprintf("{\"cbid\":%d,\"status\":%d,\"waveL\":%d,\"duration\":%f,\"undolevel\":%d", icbid, istatus, gitwst_bufferL[instanceindex], iduration, gitwst_checkpointstate[instanceindex])
+ if (gitwst_channels[instanceindex] == 2) then
+ Sresponse = strcat(Sresponse, sprintf(",\"waveR\":%d", gitwst_bufferR[instanceindex]))
+ endif
+
+ if (iselstart != -1 && iselend != -1) then
+ iselstart, iselend twst_samplestoratio iselstart, iselend, instanceindex
+ Sresponse = strcat(Sresponse, sprintf(",\"selstart\":%f,\"selend\":%f", iselstart, iselend))
+ endif
+
+ if (strcmp(Sextra, "") != 0) then
+ Sresponse = strcat(Sresponse, strcat(",", Sextra))
+ endif
+
+ xout strcat(Sresponse, "}")
+endop
+
+opcode twst_createoverviews, S, ijjp
+ icbid, iselstart, iselend, istatus xin
+ Sresponse twst_createoverviewsextra icbid, "", iselstart, iselend, -1, istatus
+ xout Sresponse
+endop
+
+
+opcode twst_failresponse, S, ij
+ icbid, istatus xin
+ xout sprintf("{\"cbid\":%d,\"status\":%d}", icbid, istatus)
+endop
+
+instr twst_successresponse
+ icbid = p4
+ io_sendstring("callback", sprintf("{\"cbid\":%d,\"status\":1}", icbid))
+ turnoff
+endin
+
+instr twst_checkalive
+ icbid = p4
+ io_sendstring("callback", sprintf("{\"cbid\": %d}", icbid))
+ turnoff
+endin
+
+opcode twst_setapplymode, aa, iaaaa
+ iuniqueid, aLorig, aRorig, aLnew, aRnew xin
+ kapplymode chnget sprintf("applymode%d", iuniqueid)
+ kdry chnget sprintf("applymodedry%d", iuniqueid)
+ kwet chnget sprintf("applymodewet%d", iuniqueid)
+ khpf chnget sprintf("applymodehpf%d", iuniqueid)
+ klpf chnget sprintf("applymodelpf%d", iuniqueid)
+
+ ; applymode 0 is replace
+ if (kapplymode == 1) then ; mix
+ aLnew = (aLorig * kdry) + (aLnew * kwet)
+ aRnew = (aRorig * kdry) + (aRnew * kwet)
+ elseif (kapplymode == 2) then ; modulate
+ aLnew = aLorig * aLnew
+ aRnew = aRorig * aRnew
+ elseif (kapplymode == 3) then ; demodulate
+ aLnew = tanh(aLorig / aLnew)
+ aRnew = tanh(aRorig / aRnew)
+ elseif (kapplymode == 4) then ; filter mix
+ kbw = klpf - khpf
+ kfreq = khpf + (kbw / 2)
+ aLbp butterbp aLnew, kfreq, kbw
+ aLbr butterbr aLorig, kfreq, kbw
+ aRbp butterbp aRnew, kfreq, kbw
+ aRbr butterbr aRorig, kfreq, kbw
+ aLnew = aLbp + aLbr
+ aRnew = aRbp + aRbr
+ endif
+ xout aLnew, aRnew
+endop
+
+
+opcode twst_playback, iaaiiiii, iiiSiioooOPo
+ istart, iend, ichannel, Stransform, ioffline, iautomating, icrossfadein, icrossfadeout, iuniqueid xin
+ itransforming = strcmp(Stransform, "")
+ if (istart == iend) then
+ istart = istart
+ iend = 1
+ endif
+
+ istatus = 1
+ itfi = (strcmp(strsub(Stransform, 5, 8), "tfi") == 0) ? 1 : 0
+ ibuflen = ftlen(gitwst_bufferL[gitwst_instanceindex])
+ istartsamp = ibuflen * istart
+ iendsamp = ibuflen * iend
+ iendsampw = iendsamp
+ ilensamp = iendsamp - istartsamp
+ iextracycles = 0
+ idurations = ilensamp / ftsr(gitwst_bufferL[gitwst_instanceindex])
+ p3 = idurations
+ icrossfadeins = idurations * icrossfadein
+ icrossfadeouts = idurations * icrossfadeout
+
+ ileft = 1
+ iright = 1
+ if (ichannel == 0 || gitwst_channels[gitwst_instanceindex] == 1) then
+ iright = 0
+ elseif (ichannel == 1 && gitwst_channels[gitwst_instanceindex] == 2) then
+ ileft = 0
+ endif
+
+ if (ioffline == 1) then
+ idelaysamples = gitwst_tf_state[5]
+ if (idelaysamples > 0) then
+ idelays = idelaysamples / sr
+ iextracycles = round(kr * idelays)
+ else
+ idelays = 0
+ endif
+ else
+ idelaysamples = 0
+ iextracycles = 0
+ idelays = 0
+ endif
+
+ gitwst_tf_state[0] = ileft
+ gitwst_tf_state[1] = iright
+ gitwst_tf_state[2] = istartsamp
+ gitwst_tf_state[3] = iendsamp
+ gitwst_tf_state[5] = 0 ; latency for fft processing etc
+ gitwst_tf_state[6] = ioffline
+
+ aL init 0
+ aR init 0
+ ifnL = gitwst_bufferL[gitwst_instanceindex]
+ ifnR = gitwst_bufferR[gitwst_instanceindex]
+ ifnTargetL = gitwst_bufferL[gitwst_instanceindex]
+ ifnTargetR = gitwst_bufferR[gitwst_instanceindex]
+
+ if (itfi == 1) then
+ idocut = 0
+ if (istart != 0 && iend != 1) then
+ idocut = 1
+ endif
+
+ ; only 4 pfields in subinstr allowed
+ gitwst_tf_state[4] = idocut
+ aoutL, aoutR subinstr Stransform, iuniqueid
+ ; aoutL, aoutR twst_setapplymode iuniqueid, aL, aR, aoutL, aoutR ; no applymode for tfi
+ if (iautomating == 1) then
+ a_ subinstr "twst_automaterun"
+ endif
+
+ if (ioffline == 1) then
+ itargetlen = int(p3 * sr)
+ iextracycles += (p3 * kr)
+ iendsampw = istartsamp + itargetlen
+
+ if (p3 != idurations) then
+ inewlen = (ftlen(gitwst_bufferL[gitwst_instanceindex]) - ilensamp) + itargetlen
+ if (inewlen >= gihost_max32bitftlen) then ; limitation with WASM Csound build at the moment
+ istatus = -2
+ goto complete
+ endif
+
+ ifnTargetL ftgen 0, 0, -inewlen, -2, 0
+ ifnTargetR ftgen 0, 0, -inewlen, -2, 0
+
+ if (istartsamp != 0) then ; copy part before commit
+ indexr = 0
+ indexw = 0
+ while (indexw < istartsamp - 1) do
+ if (ileft == 1) then
+ tabw_i tab_i(indexr, gitwst_bufferL[gitwst_instanceindex]), indexw, ifnTargetL
+ endif
+ if (iright == 1) then
+ tabw_i tab_i(indexr, gitwst_bufferR[gitwst_instanceindex]), indexw, ifnTargetR
+ endif
+ indexr += 1
+ indexw += 1
+ od
+
+/* aliasing from ftslice???
+ if (ileft == 1) then
+ ftslicei gitwst_bufferL[gitwst_instanceindex], ifnTargetL, 0, istartsamp, 1
+ endif
+ if (iright == 1) then
+ ftslicei gitwst_bufferR[gitwst_instanceindex], ifnTargetR, 0, istartsamp, 1
+ endif
+*/
+ endif
+
+ if (iendsampw < ftlen(ifnTargetL)) then ; copy part after commit
+ indexr = iendsamp + 1
+ indexw = iendsampw + 1
+ while (indexw < inewlen - 1) do
+ if (ileft == 1) then
+ tabw_i tab_i(indexr, gitwst_bufferL[gitwst_instanceindex]), indexw, ifnTargetL
+ endif
+ if (iright == 1) then
+ tabw_i tab_i(indexr, gitwst_bufferR[gitwst_instanceindex]), indexw, ifnTargetR
+ endif
+ indexr += 1
+ indexw += 1
+ od
+ endif
+ else
+ inewlen = ibuflen
+ endif
+ endif
+ idurations = p3
+
+ else ; is not tfi
+ inewlen = ibuflen ;ilensamp
+ aposr linseg istartsamp, idurations, iendsampw ;iendsamp
+
+ if (ileft == 1) then
+ aL table3 aposr, ifnL
+ endif
+ if (iright == 1) then
+ aR table3 aposr, ifnR
+ endif
+
+ if (itransforming == 1) then
+ if (iautomating == 1) then
+ a_ subinstr "twst_automaterun"
+ endif
+ chnset aL, "twstfeedL"
+ chnset aR, "twstfeedR"
+ aoutL, aoutR subinstr Stransform, iuniqueid
+ aoutL, aoutR twst_setapplymode iuniqueid, aL, aR, aoutL, aoutR
+ else
+ aoutL = aL
+ aoutR = aR
+ endif
+ endif ; end not tfi
+
+ if (ioffline == 0) then
+ chnset -1, "twst_tfplayposratio"
+ kplayposratio chnget "twst_tfplayposratio"
+ if (kplayposratio >= 0) then
+ chnset (kplayposratio * (iend - istart)) + istart, "twst_playposratio"
+ else
+ ktimeenv linseg istart, p3, iend
+ chnset ktimeenv, "twst_playposratio"
+ endif
+ endif
+
+
+ if ((icrossfadein != 0 || icrossfadeout != 0) && (icrossfadein + icrossfadeout) < 1) then
+ icrossfadeins = max(0.0000001, icrossfadeins) ; god damn times can't seem to be 0 in linseg
+ icrossfademids = idurations - (icrossfadeins + icrossfadeouts)
+ icrossfademids = max(0.0000001, icrossfademids)
+ icrossfadeouts = max(0.0000001, icrossfadeouts)
+
+ if (itfi == 1) then
+ imidsamp1 = istartsamp + (icrossfadeins * sr)
+ imidsamp2 = iendsamp - (icrossfadeouts * sr)
+ if (idelays != 0) then
+ aposr linseg istartsamp, idelays, istartsamp, icrossfadeins, imidsamp1, icrossfademids, imidsamp2, icrossfadeouts, iendsamp
+ else
+ aposr linseg istartsamp, icrossfadeins, imidsamp1, icrossfademids, imidsamp2, icrossfadeouts, iendsamp
+ endif
+ if (ileft == 1) then
+ aL table3 aposr, ifnL
+ endif
+ if (iright = 1) then
+ aR table3 aposr, ifnR
+ endif
+
+ endif
+
+ if (idelays != 0) then
+ acrossfade linseg 0, idelays, 0, icrossfadeins, 1, icrossfademids, 1, icrossfadeouts, 0
+ else
+ acrossfade linseg 0, icrossfadeins, 1, icrossfademids, 1, icrossfadeouts, 0
+ endif
+
+ if (ileft == 1) then
+ aoutL = (aL * (1 - acrossfade)) + (aoutL * acrossfade)
+ endif
+ if (iright == 1) then
+ aoutR = (aR * (1 - acrossfade)) + (aoutR * acrossfade)
+ endif
+ endif
+
+ if (chnget:i("twst_dcblockoutputs") == 1) then
+ aoutL dcblock2 aoutL
+ aoutR dcblock2 aoutR
+ endif
+
+ if (chnget:i("twst_tanhoutputs") == 1) then
+ aoutL tanh aoutL
+ aoutR tanh aoutR
+ endif
+
+ anull init 0
+ if (ioffline == 1) then
+ if (itfi == 1) then
+ iendsampw = (idurations * sr) + istartsamp
+ endif
+
+ if (idelays != 0) then
+ aposw linseg istartsamp, idelays, istartsamp, idurations, iendsampw
+ else
+ aposw linseg istartsamp, idurations, iendsampw
+ endif
+
+ if (ileft == 1) then
+ tablew aoutL, aposw, ifnTargetL
+ endif
+ if (iright == 1) then
+ tablew aoutR, aposw, ifnTargetR
+ endif
+ amonitorL = anull
+ amonitorR = anull
+ else
+ amonitorL = aoutL
+ if (gitwst_channels[gitwst_instanceindex] == 1) then
+ amonitorR = amonitorL
+ else
+ amonitorR = aoutR
+ endif
+ endif
+
+ inewlen = ftlen((ifnTargetL > 0) ? ifnTargetL : ifnTargetR)
+
+complete:
+ xout istatus, amonitorL, amonitorR, ifnTargetL, ifnTargetR, iextracycles, istartsamp / inewlen, iendsampw / inewlen
+endop
+
+
+
+instr twst_setinstance
+ icbid = p4
+ gitwst_instanceindex = p5
+ io_sendstring("callback", sprintf("{\"cbid\":%d,\"status\":1}", icbid))
+ turnoff
+endin
+
+opcode twst_copy, k, opjj
+ istart, iend, ichannel, instanceindex xin
+ instanceindex = (instanceindex == -1) ? gitwst_instanceindex : instanceindex
+
+ istart, ilen, iend twst_getstartend istart, iend
+
+ twst_clearbuffers(gitwst_copyBufferL, gitwst_copyBufferR)
+ gitwst_copyBufferL = -1
+ gitwst_copyBufferR = -1
+
+ if (gitwst_channels[instanceindex] == 2 && ichannel == -1) then
+ kdone, gitwst_copyBufferL, gitwst_copyBufferR chop_copyk istart, ilen, gitwst_bufferL[instanceindex], gitwst_bufferR[instanceindex]
+ elseif (ichannel == 1) then
+ kdone, gitwst_copyBufferR, i_ chop_copyk istart, ilen, gitwst_bufferR[instanceindex]
+ else
+ kdone, gitwst_copyBufferL, i_ chop_copyk istart, ilen, gitwst_bufferL[instanceindex]
+ endif
+ xout kdone
+endop
+
+instr twst_copy
+ icbid = p4
+ istart = p5
+ iend = p6
+ ichannel = p7
+ inocheckpoint = p8
+
+ kdone twst_copy istart, iend, ichannel
+ if (kdone == 1) then
+ schedulek("twst_successresponse", 0, 1, icbid)
+ turnoff
+ endif
+endin
+
+
+opcode twst_trim, k, opjj
+ istart, iend, ichannel, instanceindex xin
+ instanceindex = (instanceindex == -1) ? gitwst_instanceindex : instanceindex
+ istart, ilen, iend twst_getstartend istart, iend
+
+ kdone init 0
+ kdone, gitwst_bufferL[instanceindex], gitwst_bufferR[instanceindex] chop_trimk istart, ilen, gitwst_bufferL[instanceindex], gitwst_bufferR[instanceindex]
+ xout kdone
+endop
+
+instr twst_trim
+ icbid = p4
+ istart = p5
+ iend = p6
+ ichannel = p7
+ inocheckpoint = p8
+
+ if (inocheckpoint == 0) then
+ twst_checkpoint()
+ endif
+
+ kdone twst_trim istart, iend, ichannel
+ if (kdone == 1) then
+ schedulek("twst_overviews_response", 0, 1, icbid, 0, 1)
+ turnoff
+ endif
+endin
+
+
+opcode twst_cut, ki, opjj
+ istart, iend, ichannel, instanceindex xin
+ instanceindex = (instanceindex == -1) ? gitwst_instanceindex : instanceindex
+ istart, ilen, iend twst_getstartend istart, iend
+
+ twst_clearbuffers(gitwst_copyBufferL, gitwst_copyBufferR)
+ gitwst_copyBufferL = -1
+ gitwst_copyBufferR = -1
+ kdone init 0
+
+ if (gitwst_channels[instanceindex] == 2) then
+ if (ichannel == -1) then
+ kdone, gitwst_copyBufferL, gitwst_copyBufferR, gitwst_bufferL[instanceindex], gitwst_bufferR[instanceindex] chop_cutk istart, ilen, gitwst_bufferL[instanceindex], gitwst_bufferR[instanceindex]
+ elseif (ichannel == 0) then
+ kdone1, gitwst_copyBufferL, i_ chop_copyk istart, ilen, gitwst_bufferL[instanceindex]
+ kdone chop_setsilencek istart, ilen, gitwst_bufferL[instanceindex], -1, kdone1
+ elseif (ichannel == 1) then
+ kdone1, gitwst_copyBufferR, i_ chop_copyk istart, ilen, gitwst_bufferR[instanceindex]
+ kdone chop_setsilencek istart, ilen, gitwst_bufferR[instanceindex], -1, kdone1
+ endif
+ else
+ kdone, gitwst_copyBufferL, i_, gitwst_bufferL[instanceindex], i_ chop_cutk istart, ilen, gitwst_bufferL[instanceindex]
+ endif
+
+ inewlen = ftlen(gitwst_bufferL[instanceindex])
+ xout kdone, istart / inewlen
+endop
+
+
+
+instr twst_overviews_response
+ icbid = p4
+ iselstart = p5
+ iselend = p6
+ io_sendstring("callback", twst_createoverviews(icbid, iselstart, iselend))
+ turnoff
+endin
+
+instr twst_cut
+ icbid = p4
+ istart = p5
+ iend = p6
+ ichannel = p7
+ inocheckpoint = p8
+
+ if (inocheckpoint == 0) then
+ twst_checkpoint()
+ endif
+
+ kdone, istart twst_cut istart, iend, ichannel
+ if (kdone == 1) then
+ schedulek("twst_overviews_response", 0, 1, icbid, istart, istart)
+ turnoff
+ endif
+endin
+
+
+opcode twst_delete, ki, opjj
+ istart, iend, ichannel, instanceindex xin
+ instanceindex = (instanceindex == -1) ? gitwst_instanceindex : instanceindex
+ istart, ilen, iend twst_getstartend istart, iend
+ kdone init 0
+
+ if (gitwst_channels[instanceindex] == 2) then
+ if (ichannel == -1) then
+ kdone, gitwst_bufferL[instanceindex], gitwst_bufferR[instanceindex] chop_deletek istart, ilen, gitwst_bufferL[instanceindex], gitwst_bufferR[instanceindex]
+ elseif (ichannel == 0) then
+ kdone chop_setsilencek istart, ilen, gitwst_bufferL[instanceindex]
+ elseif (ichannel == 1) then
+ kdone chop_setsilencek istart, ilen, gitwst_bufferR[instanceindex]
+ endif
+ else
+ kdone, gitwst_bufferL[instanceindex], i_ chop_deletek istart, ilen, gitwst_bufferL[instanceindex]
+ endif
+
+ inewlen = ftlen(gitwst_bufferL[instanceindex])
+ xout kdone, istart / inewlen
+endop
+
+
+instr twst_delete
+ icbid = p4
+ istart = p5
+ iend = p6
+ ichannel = p7
+ inocheckpoint = p8
+
+ if (inocheckpoint == 0) then
+ twst_checkpoint()
+ endif
+
+ kdone, istart twst_delete istart, iend, ichannel
+ if (kdone == 1) then
+ schedulek("twst_overviews_response", 0, 1, icbid, istart, istart)
+ turnoff
+ endif
+endin
+
+opcode twst_trypaste, ikii, ojjpo
+ istart, ichannel, instanceindex, inumber, imix xin
+ instanceindex = (instanceindex == -1) ? gitwst_instanceindex : instanceindex
+ istart, ilen, iend twst_getstartend istart, 1
+ inewlen = ftlen(gitwst_bufferL[instanceindex]) + (ftlen(gitwst_copyBufferL) * inumber)
+
+ if (inewlen >= gihost_max32bitftlen) then ; limitation with WASM Csound build at the moment
+ iresponse = -2
+ goto complete
+ elseif (gitwst_copyBufferL < 1 && gitwst_copyBufferR < 1) then
+ iresponse = -1
+ goto complete
+ endif
+
+ kdone init 0
+ if (gitwst_channels[instanceindex] == 1) then
+ kdone, gitwst_bufferL[instanceindex], i_, ipastelen chop_pastek gitwst_copyBufferL, -1, gitwst_bufferL[instanceindex], -1, istart, inumber, imix
+ elseif (gitwst_copyBufferR > 0 && ichannel == -1) then
+ kdone, gitwst_bufferL[instanceindex], gitwst_bufferR[instanceindex], ipastelen chop_pastek gitwst_copyBufferL, gitwst_copyBufferR, gitwst_bufferL[instanceindex], gitwst_bufferR[instanceindex], istart, inumber, imix
+ elseif (ichannel == 0) then
+ isrc = (gitwst_copyBufferL > 0) ? gitwst_copyBufferL : gitwst_copyBufferR
+ kdone1, gitwst_bufferL[instanceindex], gitwst_bufferR[instanceindex], ipastelen chop_pastek isrc, isrc, gitwst_bufferL[instanceindex], gitwst_bufferR[instanceindex], istart, inumber, imix
+ kdone chop_setsilencek istart, ilen, gitwst_bufferR[instanceindex], -1, kdone1
+ elseif (ichannel == 1) then
+ isrc = (gitwst_copyBufferR > 0) ? gitwst_copyBufferR : gitwst_copyBufferL
+ kdone1, gitwst_bufferL[instanceindex], gitwst_bufferR[instanceindex], ipastelen chop_pastek isrc, isrc, gitwst_bufferL[instanceindex], gitwst_bufferR[instanceindex], istart, inumber, imix
+ kdone chop_setsilencek istart, ilen, gitwst_bufferL[instanceindex], -1, kdone1
+ endif
+ iresponse = 1
+ inewlen = ftlen(gitwst_bufferL[instanceindex])
+
+complete:
+ xout iresponse, kdone, istart, (istart + ipastelen)
+endop
+
+opcode twst_paste, k, ojjp
+ istart, ichannel, instanceindex, inumber xin
+ istatus, kdone, istart, iend twst_trypaste istart, ichannel, instanceindex, inumber
+ xout kdone
+endop
+
+
+instr twst_paste
+ icbid = p4
+ istart = p5
+ iend = p6
+ ichannel = p7
+ inocheckpoint = p8
+
+ if (inocheckpoint == 0) then
+ twst_checkpoint()
+ endif
+
+ istatus, kdone, istart, iend twst_trypaste istart, ichannel
+ if (istatus < 0) then
+ io_sendstring("callback", twst_failresponse(icbid, istatus))
+ turnoff
+ else
+ if (kdone == 1) then
+ schedulek("twst_overviews_response", 0, 1, icbid, istart, iend)
+ turnoff
+ endif
+ endif
+endin
+
+
+
+instr twst_pastespecial
+ icbid = p4
+ istart = p5
+ iend = p6
+ ichannel = p7
+ inocheckpoint = p8
+
+ if (inocheckpoint == 0) then
+ twst_checkpoint()
+ endif
+
+ inumber = chnget:i(sprintf("%s_repetitions0", nstrstr(p1)))
+ inumber = (inumber < 1) ? 1 : inumber
+ imix = chnget:i(sprintf("%s_mixpaste0", nstrstr(p1)))
+ istatus, kdone, istart, iend twst_trypaste istart, ichannel, -1, inumber, imix
+ if (istatus < 0) then
+ io_sendstring("callback", twst_failresponse(icbid, istatus))
+ turnoff
+ else
+ if (kdone == 1) then
+ schedulek("twst_overviews_response", 0, 1, icbid, istart, iend)
+ turnoff
+ endif
+ endif
+endin
+
+
+instr twst_nexttransientresponse
+ icbid = p4
+ iselstart = p5
+ iselend = p6
+ if (iselstart == -1 && iselend == -1) then
+ io_sendstring("callback", sprintf("{\"cbid\":%d}", icbid))
+ else
+ io_sendstring("callback", sprintf("{\"cbid\":%d,\"selstart\":%f,\"selend\":%f}", icbid, iselstart, iselend))
+ endif
+ turnoff
+endin
+
+instr twst_nexttransient
+ icbid = p4
+ istart = p5
+ iend = p6
+ ichannel = p7
+ p3 = 60
+
+ instanceindex = gitwst_instanceindex
+ isamps = ftlen(gitwst_bufferL[instanceindex])
+
+ istartsamp = iend * isamps
+ idurationsamp = isamps - istartsamp
+ idurations = idurationsamp / sr
+
+ ileft = 1
+ iright = 1
+ if (ichannel == 0 || gitwst_channels[gitwst_instanceindex] == 1) then
+ iright = 0
+ elseif (ichannel == 1 && gitwst_channels[gitwst_instanceindex] == 2) then
+ ileft = 0
+ endif
+
+ ktimek timeinstk
+ ikcycles = idurationsamp / ksmps
+ if (ktimek == 1) then
+ kcount init 0
+ while (kcount < ikcycles) do
+ apos linseg istartsamp, idurations, isamps
+ if (ileft == 1 && iright == 1) then
+ asig = (table3:a(apos, gitwst_bufferL[instanceindex]) + table3:a(apos, gitwst_bufferR[instanceindex])) * 0.5
+ elseif (iright == 1) then
+ asig = table3:a(apos, gitwst_bufferR[instanceindex])
+ else
+ asig = table3:a(apos, gitwst_bufferL[instanceindex])
+ endif
+ ktrig transientdetect asig
+ if (ktrig == 1 && kcount != 0) then
+ kselend = ((kcount * ksmps) + istartsamp) / isamps
+ kselstart = (istart == iend) ? kselend : istart
+ schedulek("twst_nexttransientresponse", 0, 1, icbid, kselstart, kselend)
+ turnoff
+ endif
+ kcount += 1
+ od
+ else
+ schedulek("twst_nexttransientresponse", 0, 1, icbid, -1, -1)
+ turnoff
+ endif
+endin
+
+
+instr twst_undo
+ icbid = p4
+ istatus twst_undo
+ if (istatus < 0) then
+ Sresponse = twst_failresponse(icbid)
+ else
+ Sresponse = twst_createoverviews(icbid)
+ endif
+
+ io_sendstring("callback", Sresponse)
+ turnoff
+endin
+
+
+instr twst_destroytables
+ ifnL = p4
+ ifnR = p5
+ twst_clearbuffers(ifnL, ifnR)
+ turnoff
+endin
+
+
+opcode twst_loadfile, ik, Sj
+ Spath, instanceindex xin
+ instanceindex = (instanceindex == -1) ? gitwst_instanceindex : instanceindex
+ kdone init 0
+ if (filevalid(Spath) != 1) then
+ iresponse = -1
+ goto complete
+ endif
+
+ ifilesr = filesr(Spath)
+ ifilechannels = filenchnls(Spath)
+ ilens = filelen(Spath)
+ ilen = round(ilens * ifilesr)
+
+ if (ilen >= gihost_max32bitftlen || ilens * sr >= gihost_max32bitftlen) then ; limitation with WASM Csound build at the moment
+ iresponse = -2
+ goto complete
+ endif
+
+ twst_checkpoint_clear(instanceindex)
+
+ twst_clearbuffers(gitwst_bufferL[instanceindex], gitwst_bufferR[instanceindex])
+ gitwst_channels[instanceindex] = ifilechannels
+
+ gitwst_bufferL[instanceindex] = ftgen(0, 0, -ilen, 1, Spath, 0, 0, 1)
+ if (gitwst_channels[instanceindex] == 2) then
+ gitwst_bufferR[instanceindex] = ftgen(0, 0, -ilen, 1, Spath, 0, 0, 2)
+ gitwst_bufferL[instanceindex], gitwst_bufferR[instanceindex], kdone tab_samplerateconvert gitwst_bufferL[instanceindex], gitwst_bufferR[instanceindex]
+ imono = 0
+ else
+ gitwst_bufferL[instanceindex], kdone tab_samplerateconvert gitwst_bufferL[instanceindex]
+ imono = 1
+ endif
+
+
+ iresponse = 1
+complete:
+ xout iresponse, kdone
+endop
+
+
+/*
+opcode twst_loadfile, ik, Sj
+ Spath, instanceindex xin
+ instanceindex = (instanceindex == -1) ? gitwst_instanceindex : instanceindex
+ kdone init 0
+ if (filevalid(Spath) != 1) then
+ iresponse = -1
+ goto complete
+ endif
+
+ ifilesr = filesr(Spath)
+ ifilechannels = filenchnls(Spath)
+ ilens = filelen(Spath)
+ ilen = round(ilens * ifilesr)
+
+ if (ilen >= gihost_max32bitftlen || ilens * sr >= gihost_max32bitftlen) then ; limitation with WASM Csound build at the moment
+ iresponse = -2
+ goto complete
+ endif
+
+ twst_checkpoint_clear(instanceindex)
+
+ gitwst_channels[instanceindex] = ifilechannels
+ twst_clearbuffers(gitwst_bufferL[instanceindex], gitwst_bufferR[instanceindex])
+
+ gitwst_bufferL[instanceindex] = ftgen(0, 0, -ilen, 1, Spath, 0, 0, 1)
+ if (gitwst_channels[instanceindex] == 2) then
+ gitwst_bufferR[instanceindex] = ftgen(0, 0, -ilen, 1, Spath, 0, 0, 2)
+ imono = 0
+ else
+ imono = 1
+ endif
+
+ if (sr != ifilesr) then ; different sr causes issues in table reading opcodes, convert..
+ inewlen = ilens * sr
+ ifnnewL ftgen 0, 0, -inewlen, -2, 0
+ if (imono == 0) then
+ ifnnewR ftgen 0, 0, -inewlen, -2, 0
+ endif
+ ktimek timeinstk
+ ikcycles = ilens * kr
+ if (ktimek == 1) then
+ kcount = 0
+ while (kcount < ikcycles) do
+ aposw linseg 0, ilens, inewlen - 1
+ aposr linseg 0, ilens, ilen - 1
+ asig table3 aposr, gitwst_bufferL[instanceindex]
+ tablew asig, aposw, ifnnewL
+ if (imono == 0) then
+ asig table3 aposr, gitwst_bufferR[instanceindex]
+ tablew asig, aposw, ifnnewR
+ endif
+ kcount += 1
+ od
+ else
+ kdone = 1
+ endif
+
+ ftfree gitwst_bufferL[instanceindex], 1
+ gitwst_bufferL[instanceindex] = ifnnewL
+ if (imono == 0) then
+ ftfree gitwst_bufferR[instanceindex], 1
+ gitwst_bufferR[instanceindex] = ifnnewR
+ endif
+ else
+ kdone = 1
+ endif
+
+ iresponse = 1
+complete:
+ xout iresponse, kdone
+endop
+*/
+
+instr twst_loadclipboard
+ icbid = p4
+ p3 = 60
+
+ instanceindex = gitwst_instanceindex
+ twst_clearbuffers(gitwst_bufferL[instanceindex], gitwst_bufferR[instanceindex])
+
+ ilen = ftlen(gitwst_copyBufferL)
+ ifnL ftgen 0, 0, -ilen, -2, 0
+ tableicopy ifnL, gitwst_copyBufferL
+ gitwst_bufferL[instanceindex] = ifnL
+ if (gitwst_copyBufferR > 0 && ftexists(gitwst_copyBufferR) == 1) then
+ ifnR ftgen 0, 0, -ilen, -2, 0
+ tableicopy ifnR, gitwst_copyBufferR
+ gitwst_bufferR[instanceindex] = ifnR
+ gitwst_channels[instanceindex] = 2
+ else
+ gitwst_channels[instanceindex] = 1
+ gitwst_bufferR[instanceindex] = 0
+ endif
+ schedule("twst_overviews_response", 0, 1, icbid, 0, 0)
+ turnoff
+endin
+
+instr twst_loadftable
+ icbid = p4
+ ifnL = p5
+ ifnR = p6
+ iclearbuffers = p7
+ p3 = 60
+ instanceindex = gitwst_instanceindex
+
+ if (ifnL <= 0 || ftexists(ifnL) == 0 || (ifnR > 0 && ftexists(ifnR) == 0)) then
+ io_sendstring("callback", twst_failresponse(icbid, -1))
+ turnoff
+ endif
+
+ twst_checkpoint_clear(instanceindex)
+
+ if (iclearbuffers == 1) then
+ twst_clearbuffers(gitwst_bufferL[instanceindex], gitwst_bufferR[instanceindex])
+ endif
+
+ gitwst_bufferL[instanceindex] = ifnL
+ if (ifnR > 0) then
+ gitwst_bufferR[instanceindex] = ifnR
+ gitwst_channels[instanceindex] = 2
+ else
+ gitwst_channels[instanceindex] = 1
+ endif
+
+ schedule("twst_overviews_response", 0, 1, icbid, 0, 0)
+ turnoff
+endin
+
+instr twst_getbuffers
+ icbid = p4
+ instanceindex = gitwst_instanceindex
+ if (gitwst_channels[instanceindex] == 2) then
+ Stables = sprintf("[%d,%d]", gitwst_bufferL[instanceindex], gitwst_bufferR[instanceindex])
+ else
+ Stables = sprintf("[%d]", gitwst_bufferL[instanceindex])
+ endif
+ io_sendstring("callback", sprintf("{\"cbid\":%d,\"status\":1,\"tables\":%s}", icbid, Stables))
+ turnoff
+endin
+
+
+instr twst_loadfile
+ icbid = p4
+ p3 = 120
+ Spath = strget(p5)
+ istatus, kdone twst_loadfile Spath, -1, 1
+ if (istatus < 0) then
+ Sresponse = twst_failresponse(icbid, istatus)
+ io_sendstring("callback", Sresponse)
+ turnoff
+ else
+ if (kdone == 1) then
+ schedulek("twst_overviews_response", 0, 1, icbid, 0, 0)
+ turnoff
+ endif
+ endif
+endin
+
+
+
+/*
+instr twst_loadfile
+ icbid = p4
+ Spath = strget(p5)
+ if (filevalid(Spath) != 1) then
+ Sresponse = twst_failresponse(icbid)
+ else
+ twst_clearbuffers()
+ gitwst_channels[gitwst_instanceindex] = filenchnls(Spath)
+ gitwst_bufferL[gitwst_instanceindex] = ftgen(0, 0, 0, 1, Spath, 0, 0, 1)
+ if (gitwst_channels[gitwst_instanceindex] == 2) then
+ gitwst_bufferR[gitwst_instanceindex] = ftgen(0, 0, 0, 1, Spath, 0, 0, 2)
+ endif
+ Sresponse = twst_createoverviews(icbid)
+ endif
+ io_sendstring("callback", Sresponse)
+ turnoff
+endin
+*/
+
+
+
+opcode twst_createempty, i, ijj
+ iduration, ichannels, instanceindex xin
+ ichannels = (ichannels == -1) ? 2 : ichannels
+ instanceindex = (instanceindex == -1) ? gitwst_instanceindex : instanceindex
+ twst_clearbuffers(gitwst_bufferL[instanceindex], gitwst_bufferR[instanceindex])
+ idurationsamps = iduration * sr
+
+ if (idurationsamps >= gihost_max32bitftlen) then ; limitation with WASM Csound build at the moment
+ iresponse = -2
+ goto complete
+ endif
+
+ twst_checkpoint_clear(instanceindex)
+
+ gitwst_bufferL[instanceindex] ftgen 0, 0, -idurationsamps, -2, 0
+ if (ichannels == 2) then
+ gitwst_channels[instanceindex] = 2
+ gitwst_bufferR[instanceindex] ftgen 0, 0, -idurationsamps, -2, 0
+ else
+ gitwst_channels[instanceindex] = 1
+ endif
+ iresponse = 1
+complete:
+ xout iresponse
+endop
+
+
+instr twst_createempty
+ icbid = p4
+ iduration = p5
+ ichannels = p6
+ p3 = 60
+ istatus twst_createempty iduration, ichannels
+ if (istatus < 0) then
+ io_sendstring("callback", twst_failresponse(icbid, istatus))
+ else
+ schedule("twst_overviews_response", 0, 1, icbid, 0, 0)
+ endif
+ turnoff
+endin
+
+
+instr twst_savefile_response
+ icbid = p4
+ io_sendstring("callback", sprintf("{\"cbid\":%d,\"status\":1}", icbid))
+ turnoff
+endin
+
+
+instr twst_savefile
+ icbid = p4
+ p3 = 60
+ Spath = strget(p5)
+ ktimek timeinstk
+ idurations = ftlen(gitwst_bufferL[gitwst_instanceindex]) / ftsr(gitwst_bufferL[gitwst_instanceindex])
+ ikcycles = idurations * kr
+ if (ktimek == 1) then
+ kcount init 0
+ while (kcount < ikcycles) do
+ apos lphasor 1
+ aL table apos, gitwst_bufferL[gitwst_instanceindex]
+ if (gitwst_channels[gitwst_instanceindex] == 1) then
+ fout Spath, 14, aL
+ else
+ aR table3 apos, gitwst_bufferR[gitwst_instanceindex]
+ fout Spath, 14, aL, aR
+ endif
+ kcount += 1
+ od
+ else
+ schedulek("twst_savefile_response", 0, 1, icbid)
+ turnoff
+ endif
+endin
+
+
+
+instr twst_auditioncomplete_response
+ icbid = p4
+ istatus = 0
+ if (gitwst_userstopped == 1) then
+ istatus = 3
+ endif
+ io_sendstring("callback", sprintf("{\"cbid\":%d,\"status\":%d}", icbid, istatus))
+ turnoff
+endin
+
+instr twst_stop
+ gitwst_userstopped = 1
+ turnoff2 "twst_audition", 0, 1
+ turnoff2 "twst_record", 0, 1
+ turnoff
+endin
+
+#ifdef TWST_FAILONLAG
+instr twst_auditionlag_response
+ icbid = p4
+ turnoff2 "twst_audition", 0, 0
+ io_sendstring("callback", sprintf("{\"cbid\":%d,\"status\":-1}", icbid))
+ turnoff
+endin
+#end
+
+instr twst_play
+ schedule("twst_audition", 0, p3, p4, p5, p6, p7, "", 0)
+ turnoff
+endin
+
+instr twst_audition
+ icbid = p4
+ gitwst_userstopped = 0
+ io_sendstring("callback", sprintf("{\"cbid\":%d,\"status\":1}", icbid))
+ istart = p5
+ iend = p6
+ if (istart == iend) then
+ iend = 1
+ endif
+ ichannel = p7
+ Stransform = strget(p8)
+ iautomating = p9
+ icrossfadein = p10
+ icrossfadeout = p11
+ iuniqueid = p12
+ iapplymode chnget sprintf("applymode%d", iuniqueid)
+ kapplymodedry chnget sprintf("applymodedry%d", iuniqueid)
+ kapplymodewet chnget sprintf("applymodewet%d", iuniqueid)
+
+ i_, aL, aR, i_, i_, iextracycles, i_, i_ twst_playback istart, iend, ichannel, Stransform, 0, iautomating, icrossfadein, icrossfadeout, iuniqueid
+
+ gitwst_currentplayduration = p3
+
+#ifdef TWST_FAILONLAG
+ if (strcmp(Stransform, "") != 0) then
+ klagging lagdetect 0.8
+ if (klagging == 1) then
+ schedulek("twst_auditionlag_response", 0, 1, icbid)
+ endif
+ endif
+#end
+
+ kreleasing init 0
+ ktimek timeinstk
+ iduration = (p3 * kr) + (iextracycles / sr)
+ krelease release
+ if (kreleasing == 0 && (krelease == 1 || ktimek >= iduration)) then
+ kreleasing = 1
+ schedulek("twst_auditioncomplete_response", 0, 1, icbid)
+ turnoff
+ endif
+
+ outs aL, aR
+endin
+
+
+instr twst_recordcomplete_response
+ icbid = p4
+ iselstart = p5
+ iselend = p6
+ io_sendstring("callback", twst_createoverviews(icbid, iselstart, iselend, 2))
+endin
+
+instr twst_record
+ icbid = p4
+ gitwst_userstopped = 0
+ io_sendstring("callback", sprintf("{\"cbid\":%d,\"status\":1}", icbid))
+ istart = p5
+ iend = p6
+ if (istart == iend) then
+ iend = 1
+ endif
+ ichannel = p7
+ ibuflen = ftlen(gitwst_bufferL[gitwst_instanceindex])
+ istartsamp, ilensamp, iendsamp twst_getstartend istart, iend, gitwst_instanceindex
+ ilens = ilensamp / sr
+ p3 = ilens
+
+ twst_checkpoint()
+
+ apos linseg istartsamp, ilens, iendsamp
+ aL init 0
+ aR init 0
+
+ if (gitwst_channels[gitwst_instanceindex] == 1) then
+ if (ichannel == 1) then
+ aL inch 2
+ else
+ aL inch 1
+ endif
+ tablew aL, apos, gitwst_bufferL[gitwst_instanceindex]
+ else
+ if (ichannel == -1 || ichannel == 0) then
+ aL inch 1
+ tablew aL, apos, gitwst_bufferL[gitwst_instanceindex]
+ endif
+ if (ichannel == -1 || ichannel == 1) then
+ aR inch 2
+ tablew aR, apos, gitwst_bufferR[gitwst_instanceindex]
+ endif
+ endif
+
+ chnset k(aL), "recordmonitorL"
+ chnset k(aR), "recordmonitorR"
+
+ ktimeenv linseg istart, p3, iend
+ chnset ktimeenv, "twst_playposratio"
+ kreleasing init 0
+ ktimek timeinstk
+ iduration = p3 * kr
+ if (kreleasing == 0 && (release:k() == 1 || ktimek >= iduration)) then
+ kreleasing = 1
+ klastwritten = k(apos)
+ schedulek("twst_recordcomplete_response", 0, 1, icbid, istart, klastwritten / ibuflen)
+ turnoff
+ endif
+endin
+
+
+
+instr twst_commit_response
+ icbid = p4
+ ifnL = p5
+ ifnR = p6
+ iselstart = p7
+ iselend = p8
+ if (ifnL > 0 && ifnL != gitwst_bufferL[gitwst_instanceindex]) then
+ if (gitwst_bufferL[gitwst_instanceindex] > 0 && ftexists(gitwst_bufferL[gitwst_instanceindex]) == 1) then
+ ftfree gitwst_bufferL[gitwst_instanceindex], 0
+ endif
+ gitwst_bufferL[gitwst_instanceindex] = ifnL
+ endif
+ if (ifnR > 0 && ifnR != gitwst_bufferR[gitwst_instanceindex]) then
+ if (gitwst_bufferR[gitwst_instanceindex] > 0 && gitwst_bufferR[gitwst_instanceindex] == 1) then
+ ftfree gitwst_bufferR[gitwst_instanceindex], 0
+ endif
+ gitwst_bufferR[gitwst_instanceindex] = ifnR
+ endif
+
+ io_sendstring("callback", twst_createoverviews(icbid, iselstart, iselend))
+ turnoff
+endin
+
+instr twst_commit
+ icbid = p4
+ istart = p5
+ iend = p6
+ if (istart == iend) then
+ istart = 0
+ iend = 1
+ endif
+ ichannel = p7
+ Stransform = strget(p8)
+ iautomating = p9
+ icrossfadein = p10
+ icrossfadeout = p11
+ inoCheckpoint = p12
+ iuniqueid = p13
+
+ ibuflen = ftlen(gitwst_bufferL[gitwst_instanceindex])
+ istartsamp = ibuflen * istart
+ iendsamp = ibuflen * iend
+ idurations = (iendsamp - istartsamp) / ftsr(gitwst_bufferL[gitwst_instanceindex])
+
+ if (inoCheckpoint == 0) then
+ twst_checkpoint()
+ endif
+
+ iblocks = 100
+ ikcycles = round(idurations * kr)
+ if (ikcycles < iblocks) then
+ ikcyclesperblock = ikcycles
+ else
+ ikcyclesperblock = round(ikcycles / iblocks)
+ endif
+ ktotalcount init 0
+ klastpercent init 100
+
+ kreleasing init 0
+ ifnL = 0
+ ifnR = 0
+
+ if (ktotalcount < ikcycles) then
+ kcount = 0
+ while (kcount < ikcyclesperblock) do
+ istatus, a_, a_, ifnL, ifnR, iextracycles, iselstart, iselend twst_playback istart, iend, ichannel, Stransform, 1, iautomating, icrossfadein, icrossfadeout, iuniqueid
+ if (istatus <= 0) then
+ io_sendstring("callback", twst_failresponse(icbid, istatus))
+ turnoff
+ endif
+ ikcycles += iextracycles ; weird in loop but it's a k loop, so i is set here...
+
+ kcount += 1
+ ktotalcount += 1
+ od
+ kpercent = round((100 / ikcycles) * ktotalcount)
+ if (kpercent != klastpercent) then
+ io_send "percent", kpercent
+ klastpercent = kpercent
+ endif
+ else
+ schedulek("twst_commit_response", 0, 1, icbid, ifnL, ifnR, iselstart, iselend)
+ turnoff
+ endif
+endin
+
+
+#include "/twist/automation.udo"
+#include "/twist/transforms.udo"
+
+
+#end
|