From 9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22 Mon Sep 17 00:00:00 2001 From: Richard Date: Sun, 13 Apr 2025 18:48:02 +0100 Subject: initial --- site/udo/twist/automation.udo | 241 +++++ site/udo/twist/checkpointing.udo | 127 +++ site/udo/twist/checkpointing_hold.udo | 196 ++++ site/udo/twist/transform_api.udo | 421 ++++++++ site/udo/twist/transforms.udo | 25 + site/udo/twist/transforms/amplitude.udo | 179 ++++ site/udo/twist/transforms/cross_processing.udo | 176 ++++ site/udo/twist/transforms/delay.udo | 72 ++ site/udo/twist/transforms/filter.udo | 172 ++++ site/udo/twist/transforms/frequency.udo | 65 ++ site/udo/twist/transforms/general.udo | 28 + site/udo/twist/transforms/generate.udo | 363 +++++++ site/udo/twist/transforms/granular.udo | 138 +++ site/udo/twist/transforms/harmonic.udo | 142 +++ site/udo/twist/transforms/reverb.udo | 80 ++ site/udo/twist/transforms/spectral.udo | 642 ++++++++++++ site/udo/twist/transforms/warping.udo | 210 ++++ site/udo/twist/twist.udo | 1304 ++++++++++++++++++++++++ 18 files changed, 4581 insertions(+) create mode 100755 site/udo/twist/automation.udo create mode 100755 site/udo/twist/checkpointing.udo create mode 100755 site/udo/twist/checkpointing_hold.udo create mode 100755 site/udo/twist/transform_api.udo create mode 100755 site/udo/twist/transforms.udo create mode 100755 site/udo/twist/transforms/amplitude.udo create mode 100755 site/udo/twist/transforms/cross_processing.udo create mode 100755 site/udo/twist/transforms/delay.udo create mode 100755 site/udo/twist/transforms/filter.udo create mode 100755 site/udo/twist/transforms/frequency.udo create mode 100755 site/udo/twist/transforms/general.udo create mode 100755 site/udo/twist/transforms/generate.udo create mode 100755 site/udo/twist/transforms/granular.udo create mode 100755 site/udo/twist/transforms/harmonic.udo create mode 100755 site/udo/twist/transforms/reverb.udo create mode 100755 site/udo/twist/transforms/spectral.udo create mode 100755 site/udo/twist/transforms/warping.udo create mode 100755 site/udo/twist/twist.udo (limited to 'site/udo/twist') diff --git a/site/udo/twist/automation.udo b/site/udo/twist/automation.udo new file mode 100755 index 0000000..39585fb --- /dev/null +++ b/site/udo/twist/automation.udo @@ -0,0 +1,241 @@ +#ifndef TWST_AUTOMATION +#define TWST_AUTOMATION ## +/* + Twist waveform editor and transformer + Automation and modulation + + This file is part of the SONICS UDO collection by Richard Knight 2024 + License: GPL-2.0-or-later + http://1bpm.net +*/ + + +opcode twst_xa_rms, 0, S + Schannel xin + kscale chnget strcat(Schannel, "xrmsscale") + kporttime chnget strcat(Schannel, "porttime") + + aL, aR, ileft, iright _twst_getcrossinput "xrms" + if (ileft == 1 && iright == 1) then + kvalue rms (aL + aR) / 2 + elseif (ileft == 1) then + kvalue rms aL + else + kvalue rms aR + endif + + kvalue *= kscale + if (kporttime > 0) then + kresultvalue portk kvalue, kporttime + else + kresultvalue = kvalue + endif + chnset kresultvalue, Schannel +endop + +opcode twst_xa_pitchamdf, 0, S + Schannel xin + kscale chnget strcat(Schannel, "xpitchscale") + ipitchmin chnget strcat(Schannel, "xpitchmin") + ipitchmax chnget strcat(Schannel, "xpitchmax") + kporttime chnget strcat(Schannel, "porttime") + aL, aR, ileft, iright _twst_getcrossinput "xpitch" + + if (ileft == 1 && iright == 1) then + kcps, krms pitchamdf (aL + aR) / 2, ipitchmin, ipitchmax + elseif (ileft == 1) then + kcps, krms pitchamdf aL, ipitchmin, ipitchmax + else + kcps, krms pitchamdf aR, ipitchmin, ipitchmax + endif + + kvalue = ((ipitchmin + max:k(0, kcps)) / (ipitchmax - ipitchmin)) * kscale + if (kporttime > 0) then + kresultvalue portk kvalue, kporttime + else + kresultvalue = kvalue + endif + chnset kresultvalue, Schannel +endop + +opcode twst_xa_pitch1, 0, S + Schannel xin + kscale chnget strcat(Schannel, "xpitchscale") + ihopsize chnget strcat(Schannel, "xpitchhopsize") + kporttime chnget strcat(Schannel, "porttime") + + ipitchmin = 20 + ipitchmax = sr / 2 + ihopsize = pow(2, ihopsize) + + aL, aR, ileft, iright _twst_getcrossinput "xpitch" + if (ileft == 1 && iright == 1) then + kcps, kamp ptrack (aL + aR) / 2, ihopsize + elseif (ileft == 1) then + kcps, kamp ptrack aL, ihopsize + else + kcps, kamp ptrack aR, ihopsize + endif + + kvalue = ((ipitchmin + max:k(0, kcps)) / (ipitchmax - ipitchmin)) * kscale + if (kporttime > 0) then + kresultvalue portk kvalue, kporttime + else + kresultvalue = kvalue + endif + chnset kresultvalue, Schannel +endop + +opcode twst_xa_pitch2, 0, S + Schannel xin + kscale chnget strcat(Schannel, "xpitchscale") + iperiod chnget strcat(Schannel, "xpitchperiod") + ipitchmin = octcps(chnget:i(strcat(Schannel, "xpitchmin"))) + ipitchmax = octcps(chnget:i(strcat(Schannel, "xpitchmax"))) + iampthresh chnget strcat(Schannel, "xpitchampthresh") + kporttime chnget strcat(Schannel, "porttime") + + aL, aR, ileft, iright _twst_getcrossinput "xpitch" + if (ileft == 1 && iright == 1) then + koct, kamp pitch (aL + aR) / 2, iperiod, ipitchmin, ipitchmax, iampthresh + elseif (ileft == 1) then + koct, kamp pitch aL, iperiod, ipitchmin, ipitchmax, iampthresh + else + koct, kamp pitch aR, iperiod, ipitchmin, ipitchmax, iampthresh + endif + + kcps cpsoct koct + kvalue = ((ipitchmin + max:k(0, kcps)) / (ipitchmax - ipitchmin)) * kscale + if (kporttime > 0) then + kresultvalue portk kvalue, kporttime + else + kresultvalue = kvalue + endif + chnset kresultvalue, Schannel +endop + +opcode twst_xa_centroid, 0, S + Schannel xin + kscale chnget strcat(Schannel, "xcentroidscale") + ifftsize chnget strcat(Schannel, "xcentroidfftsize") + kperiod chnget strcat(Schannel, "xcentroidperiod") + kporttime chnget strcat(Schannel, "porttime") + ipitchmin = 20 + ipitchmax = sr / 2 + ktrig metro 1 / kperiod + + aL, aR, ileft, iright _twst_getcrossinput "xcentroid" + if (ileft == 1 && iright == 1) then + kcent centroid (aL + aR) / 2, ktrig, ifftsize + elseif (ileft == 1) then + kcent centroid aL, ktrig, ifftsize + else + kcent centroid aL, ktrig, ifftsize + endif + + kvalue = ((ipitchmin + max:k(0, kcent)) / (ipitchmax - ipitchmin)) * kscale + if (kporttime > 0) then + kresultvalue portk kvalue, kporttime + else + kresultvalue = kvalue + endif + chnset kresultvalue, Schannel +endop + +opcode twst_mod_jitter, 0, S + Schannel xin + kbase chnget strcat(Schannel, "base") + kamp chnget strcat(Schannel, "amp") + kfreqmin chnget strcat(Schannel, "freqmin") + kfreqmax chnget strcat(Schannel, "freqmax") + imin chnget strcat(Schannel, "min") + imax chnget strcat(Schannel, "max") + kval jitter kamp, kfreqmin, kfreqmax + kval = kbase + (kval * (imax - imin)) + kval = min:k(max:k(kval, imin), imax) + chnset kval, Schannel +endop + +opcode twst_mod_jitter2, 0, S + Schannel xin + kbase chnget strcat(Schannel, "base") + ktotalamp chnget strcat(Schannel, "totalamp") + kamp1 chnget strcat(Schannel, "amp1") + kfreq1 chnget strcat(Schannel, "freq1") + kamp2 chnget strcat(Schannel, "amp2") + kfreq2 chnget strcat(Schannel, "freq2") + kamp3 chnget strcat(Schannel, "amp3") + kfreq3 chnget strcat(Schannel, "freq3") + imin chnget strcat(Schannel, "min") + imax chnget strcat(Schannel, "max") + kval jitter2 ktotalamp, kamp1, kfreq1, kamp2, kfreq2, kamp3, kfreq3, 1 + kval = kbase + (kval * (imax - imin)) + kval = min:k(max:k(kval, imin), imax) + chnset kval, Schannel +endop + +opcode twst_mod_lfo, 0, S + Schannel xin + krate chnget strcat(Schannel, "rate") + kbase chnget strcat(Schannel, "base") + kgain chnget strcat(Schannel, "gain") + imin chnget strcat(Schannel, "min") + imax chnget strcat(Schannel, "max") + kfn twst_tf_getwaveformk chnget:k(strcat(Schannel, "wave")) + kval = kbase + (oscilikt:k(kgain, krate, kfn) * (imax - imin)) + kval = min:k(max:k(kval, imin), imax) + chnset kval, Schannel +endop + +opcode twst_mod_line, 0, S + Schannel xin + ilatency twst_getlatencyseconds + ifirst chnget strcat(Schannel, "first") + ilast chnget strcat(Schannel, "last") + if (ilatency > 0) then + ksig linseg ifirst, ilatency, ifirst, p3, ilast + else + ksig linseg ifirst, p3, ilast + endif + + chnset ksig, Schannel +endop + +opcode twst_mod_random, 0, S + Schannel xin + krate chnget strcat(Schannel, "rate") + kmin chnget strcat(Schannel, "min") + kmax chnget strcat(Schannel, "max") + kporttime chnget strcat(Schannel, "porttime") + + imin chnget strcat(Schannel, "min") + imax chnget strcat(Schannel, "max") + initval random imin, imax + + kval init initval + ktrig metro krate + if (ktrig == 1) then + kval = random:k(kmin, kmax) + endif + kportval portk kval, kporttime + chnset kportval, Schannel +endop + + +instr twst_automationprepare + icbid = p4 + itemnum = pcount() + index = 5 + Sinstr = "instr twst_automaterun\n" + while (index < itemnum + 1) do + + Sinstr = strcat(strcat(Sinstr, strget(p(index))), "\n") + index += 1 + od + Sinstr = strcat(Sinstr, "a_ init 0\nout a_\nendin\n") + ires compilestr Sinstr + io_sendstring("callback", sprintf("{\"cbid\":%d,\"status\":%d}", icbid, (ires == 0) ? 1 : 0)) +endin + + +#end \ No newline at end of file diff --git a/site/udo/twist/checkpointing.udo b/site/udo/twist/checkpointing.udo new file mode 100755 index 0000000..39c45e8 --- /dev/null +++ b/site/udo/twist/checkpointing.udo @@ -0,0 +1,127 @@ +#ifndef UDO_TWIST_CHECKPOINTING +#define UDO_TWIST_CHECKPOINTING ## + +gitwst_maxundolevels = 32 +gitwst_checkpoints[][] init imaxinstances, gitwst_maxundolevels +gitwst_checkpointstate[] init imaxinstances +gitwst_checkpointencodemult = 10000 + + +opcode twst_checkpoint_encode, i, ii + ifnL, ifnR xin + iencoded = (ifnL * gitwst_checkpointencodemult) + (ifnR / gitwst_checkpointencodemult) + xout iencoded +endop + +opcode twst_checkpoint_decode, ii, i + iencoded xin + ifnL = int(iencoded) / gitwst_checkpointencodemult + ifnR = frac(iencoded) * gitwst_checkpointencodemult + xout ifnL, ifnR +endop + +opcode twst_checkpoint_clear, 0, j + instanceindex xin + instanceindex = (instanceindex == -1) ? gitwst_instanceindex : instanceindex + icheckpointnumber = gitwst_checkpointstate[instanceindex] + while (icheckpointnumber >= 0) do + ifnL, ifnR twst_checkpoint_decode gitwst_checkpoints[instanceindex][icheckpointnumber] + if (ifnL > 0 && ftexists(ifnL) == 1) then + ftfree ifnL, 0 + endif + if (ifnR > 0 && ftexists(ifnR) == 1) then + ftfree ifnR, 0 + endif + icheckpointnumber -= 1 + od + gitwst_checkpointstate[instanceindex] = 0 +endop + +opcode twst_checkpoint, 0, j + instanceindex xin + imaxundo chnget "twst_maxundo" + imaxundo = (imaxundo == -1) ? gitwst_maxundolevels : imaxundo + if (imaxundo == 0 || imaxundo > gitwst_maxundolevels) then + goto complete + endif + + instanceindex = (instanceindex == -1) ? gitwst_instanceindex : instanceindex + icheckpointnumber = gitwst_checkpointstate[instanceindex] + if (icheckpointnumber >= imaxundo) then + ifnL, ifnR twst_checkpoint_decode gitwst_checkpoints[instanceindex][0] + if (ifnL > 0 && ftexists(ifnL) == 1) then + ftfree ifnL, 0 + endif + if (ifnR > 0 && ftexists(ifnR) == 1) then + ftfree ifnR, 0 + endif + index = 1 + itemp[] getrow gitwst_checkpoints, instanceindex + while (index <= imaxundo) do + gitwst_checkpoints[instanceindex][index - 1] = itemp[index] + index += 1 + od + gitwst_checkpointstate[instanceindex] = icheckpointnumber ;- 1 + else + gitwst_checkpointstate[instanceindex] = icheckpointnumber + 1 + endif + + ifnL = gitwst_bufferL[instanceindex] + ifnR = gitwst_bufferR[instanceindex] + ilen = ftlen(ifnL) + + ifnCheckpointL ftgen 0, 0, ilen, 2, 0 + tableicopy ifnCheckpointL, ifnL + if (ifnR > 0) then + ifnCheckpointR ftgen 0, 0, ilen, 2, 0 + tableicopy ifnCheckpointR, ifnR + else + ifnCheckpointR = 0 + endif + + iencoded twst_checkpoint_encode ifnCheckpointL, ifnCheckpointR + gitwst_checkpoints[instanceindex][icheckpointnumber] = iencoded + +complete: +endop + +opcode twst_undo, i, jp + instanceindex, iapplyundo xin + instanceindex = (instanceindex == -1) ? gitwst_instanceindex : instanceindex + + icheckpointnumber = gitwst_checkpointstate[instanceindex] + + icheckpointnumber -= 1 + if (icheckpointnumber < 0) then + istatus = -1 + goto complete + endif + + gitwst_checkpointstate[instanceindex] = icheckpointnumber + ifnL, ifnR twst_checkpoint_decode gitwst_checkpoints[instanceindex][icheckpointnumber] + + if (iapplyundo == 1) then ; apply or just step back and forget + if (ifnL > 0 && ftexists(ifnL) = 1) then + ftfree gitwst_bufferL[instanceindex], 0 + gitwst_bufferL[instanceindex] = ifnL + endif + if (ifnR > 0 && ftexists(ifnR) == 1) then + ftfree gitwst_bufferR[instanceindex], 0 + gitwst_bufferR[instanceindex] = ifnR + endif + else + if (ifnL > 0 && ftexists(ifnL) = 1) then + ftfree ifnL, 0 + endif + if (ifnL > 0 && ftexists(ifnR) = 1) then + ftfree ifnR, 0 + endif + endif + + istatus = 1 + +complete: + xout istatus +endop + +#end diff --git a/site/udo/twist/checkpointing_hold.udo b/site/udo/twist/checkpointing_hold.udo new file mode 100755 index 0000000..523d423 --- /dev/null +++ b/site/udo/twist/checkpointing_hold.udo @@ -0,0 +1,196 @@ +#ifndef UDO_TWIST_CHECKPOINTING +#define UDO_TWIST_CHECKPOINTING ## + +; file checkpointing broken due to WASM FS issue, but keep in memory maybe better anyway + +#ifdef TWIST_FTCHECKPOINTING + +gitwst_checkpoints[][] init imaxinstances, gitwst_maxundolevels +gitwst_checkpointstate[] init imaxinstances +gitwst_checkpointencodemult = 10000 + +opcode twst_checkpoint, 0, j + instanceindex xin + imaxundo chnget "maxundo" + imaxundo = (imaxundo == -1) ? gitwst_maxundolevels : imaxundo + if (imaxundo == 0 || imaxundo > gitwst_maxundolevels) then + goto complete + endif + + instanceindex = (instanceindex == -1) ? gitwst_instanceindex : instanceindex + icheckpointnumber = gitwst_checkpointstate[instanceindex] + + if (icheckpointnumber >= imaxundo) then + ftfree gitwst_checkpoints[instanceindex][0], 0 + index = 1 + while (index < gitwst_maxundolevels) do + gitwst_checkpoints[instanceindex][index - 1] = gitwst_checkpoints[instanceindex][index] + index += 1 + od + else + gitwst_checkpointstate[instanceindex] = icheckpointnumber + 1 + endif + + ifnL = gitwst_bufferL[instanceindex] + ifnR = gitwst_bufferR[instanceindex] + ilen = ftlen(ifnL) + + ifnCheckpointL ftgen 0, 0, ilen, 2, 0 + tableicopy ifnCheckpointL, ifnL + ifnEncodedL = ifnCheckpointL * gitwst_checkpointencodemult + if (ifnR > 0) then + ifnCheckpointR ftgen 0, 0, ilen, 2, 0 + tableicopy ifnCheckpointR, ifnR + ifnEncodedR = ifnCheckpointR / gitwst_checkpointencodemult + else + ifnEncodedR = 0 + endif + + iencoded = ifnEncodedL + ifnEncodedR + gitwst_checkpoints[instanceindex][icheckpointnumber] = iencoded + +complete: +endop + +opcode twst_undo, i, j + instanceindex xin + instanceindex = (instanceindex == -1) ? gitwst_instanceindex : instanceindex + Sloaded = "" + + icheckpointnumber = gitwst_checkpointstate[instanceindex] + + icheckpointnumber -= 1 + if (icheckpointnumber < 0) then + istatus = -1 + goto complete + endif + + icheckpointEncoded = gitwst_checkpoints[instanceindex][icheckpointnumber] + ifnCheckpointL = icheckpointEncoded / gitwst_checkpointencodemult + ifnCheckpointR = icheckpointEncoded * gitwst_checkpointencodemult + + ftfree gitwst_bufferL[instanceindex], 0 + gitwst_bufferL[instanceindex] = ifnCheckpointL + + if (ifnCheckpointR > 0) then + ftfree gitwst_bufferR[instanceindex], 0 + gitwst_bufferR[instanceindex] = ifnCheckpointR + endif + + istatus = 1 + +complete: + xout istatus +endop + +#else + +gitwst_checkpoint[][] init imaxinstances, 2 +gitwst_checkpointlengths[][] init imaxinstances, gitwst_maxundolevels +opcode twst_checkpointfilename, S, jj + instanceindex, icheckpointnumber xin + instanceindex = (instanceindex == -1) ? gitwst_instanceindex : instanceindex + icheckpointnumber = (icheckpointnumber == -1) ? gitwst_checkpoint[instanceindex][0] : icheckpointnumber + Sfile = sprintf("checkpoint-%d-%d", instanceindex, icheckpointnumber) + Sfile = strcat(host_tempdir(), strcat("/", Sfile)) + xout Sfile +endop + +opcode twst_checkpoint, 0, j + instanceindex xin + imaxundo chnget "maxundo" + if (imaxundo == 0 || imaxundo > gitwst_maxundolevels) then + goto complete + endif + + instanceindex = (instanceindex == -1) ? gitwst_instanceindex : instanceindex + icheckpointnumber = gitwst_checkpoint[instanceindex][0] + icheckpointoffset = gitwst_checkpoint[instanceindex][1] + + if (icheckpointoffset + icheckpointnumber >= imaxundo) then + Sdelete = twst_checkpointfilename(icheckpointoffset) + io_sendstring("callback", sprintf("{\"cbid\":%d,\"delete\": [\"%s\", \"%s.len\"]}", giwst_globalcbid, Sdelete, Sdelete)) + icheckpointoffset += 1 + gitwst_checkpoint[instanceindex][1] = icheckpointoffset + endif + + Sfile = twst_checkpointfilename(instanceindex) + + gitwst_checkpointlengths[instanceindex][icheckpointnumber - icheckpointoffset] = ftlen(gitwst_bufferL[instanceindex]) + /* can't use this as WASM not writing/closing files properly + ilen = ftlen(gitwst_bufferL[instanceindex]) + ihf fiopen strcat(Sfile, ".len"), 0 + fouti ihf, 0, 0, ilen + ficlose ihf* + ; nor this ;fprints strcat(Sfile, ".len"), "%d\n", ftlen(gitwst_bufferL[instanceindex]) + */ + + if (gitwst_channels[instanceindex] == 1) then + ftsave Sfile, 0, gitwst_bufferL[instanceindex] + else + ftsave Sfile, 0, gitwst_bufferL[instanceindex], gitwst_bufferR[instanceindex] + endif + gitwst_checkpoint[instanceindex][0] = icheckpointnumber + 1 +complete: +endop + +opcode twst_undo, iS, j + instanceindex xin + instanceindex = (instanceindex == -1) ? gitwst_instanceindex : instanceindex + Sloaded = "" + + icheckpointnumber = gitwst_checkpoint[instanceindex][0] + icheckpointoffset = gitwst_checkpoint[instanceindex][1] + + if (icheckpointnumber - icheckpointoffset <= 0) then + istatus = -1 + goto complete + endif + + icheckpointnumber -= 1 + gitwst_checkpoint[instanceindex][0] = icheckpointnumber + Sfile = twst_checkpointfilename(instanceindex) + + ilen = gitwst_checkpointlengths[instanceindex][icheckpointnumber - icheckpointoffset] + /* can't use this as WASM not writing/closing files properly thus checkpoint step doesn't write + SlenFile = strcat(Sfile, ".len") + if (filevalid(Sfile) != 1 || filevalid(SlenFile) != 1) then + istatus = -2 + goto complete + endif + + ilen init 0 + ihf fiopen SlenFile, 1 + fini ihf, 0, 1, ilen + ficlose ihf + */ + + if (ilen == 0) then + istatus = -3 + goto complete + endif + + if (ilen != ftlen(gitwst_bufferL[instanceindex])) then + twst_clearbuffers gitwst_bufferL[instanceindex], gitwst_bufferR[instanceindex] + gitwst_bufferL[instanceindex] ftgen 0, 0, -ilen, -2, 0 + if (gitwst_channels[instanceindex] == 2) then + gitwst_bufferR[instanceindex] ftgen 0, 0, -ilen, -2, 0 + else + gitwst_bufferR[instanceindex] = 0 + endif + endif + + if (gitwst_channels[instanceindex] == 1) then + ftload Sfile, 0, gitwst_bufferL[instanceindex] + else + ftload Sfile, 0, gitwst_bufferL[instanceindex], gitwst_bufferR[instanceindex] + endif + Sloaded = Sfile + istatus = 1 + +complete: + xout istatus, Sloaded +endop +#end + +#end \ No newline at end of file diff --git a/site/udo/twist/transform_api.udo b/site/udo/twist/transform_api.udo new file mode 100755 index 0000000..9b916e3 --- /dev/null +++ b/site/udo/twist/transform_api.udo @@ -0,0 +1,421 @@ +#ifndef UDO_TWIST_TRANSFORMAPI +#define UDO_TWIST_TRANSFORMAPI ## + +#define TWST_TRANSFORM #i_ = p4# + +opcode twst_param, k, S + Sname xin + Schannel = sprintf("%s_%s%d", nstrstr(p1), Sname, p4) + kvalue chnget Schannel + xout kvalue +endop + +opcode twst_parami, i, S + Sname xin + Schannel = sprintf("%s_%s%d", nstrstr(p1), Sname, p4) + ivalue chnget Schannel + xout ivalue +endop + +opcode twst_getinput, aaii, 0 + aL chnget "twstfeedL" + aR chnget "twstfeedR" + xout aL, aR, gitwst_tf_state[0], gitwst_tf_state[1] +endop + +opcode twst_setlatencysamples, 0, i + isamples xin + gitwst_tf_state[5] = isamples +endop + +opcode twst_setlatencyseconds, 0, i + iseconds xin + twst_setlatencysamples iseconds * sr +endop + +opcode twst_getlatencyseconds, i, 0 + xout gitwst_tf_state[5] / sr +endop + +opcode twst_tf_pitchscale_custom, k, S + SchanPrepend xin + if (twst_param:k(strcat(SchanPrepend, "pitchscalemode")) == 1) then + ksemitones = twst_param:k(strcat(SchanPrepend, "pitchsemitones")) + kscale = pow:k(2, ksemitones / 12) + else + kscale = twst_param:k(strcat(SchanPrepend, "pitchscale")) + endif + xout kscale +endop + +opcode twst_tf_pitchscale, k, 0 + xout twst_tf_pitchscale_custom("") +endop + +opcode twst_tf_freq_custom, k, S + SchanPrepend xin + if (twst_param:k(strcat(SchanPrepend, "freqmode")) == 1) then + kfreq = cpsmidinn:k(twst_param:k(strcat(SchanPrepend, "note"))) + else + kfreq = twst_param:k(strcat(SchanPrepend, "freq")) + endif + xout kfreq +endop + +opcode twst_tf_freq, k, 0 + xout twst_tf_freq_custom("") +endop + +opcode twst_tf_freqi_custom, i, S + SchanPrepend xin + if (twst_parami(strcat(SchanPrepend, "freqmode")) == 1) then + ifreq = cpsmidinn:i(twst_parami(strcat(SchanPrepend,"note"))) + else + ifreq = twst_parami(strcat(SchanPrepend,"freq")) + endif + xout ifreq +endop + +opcode twst_tf_freqi, i, 0 + xout twst_tf_freqi_custom("") +endop + +opcode twst_tf_setplayposition, 0, k + kplayposratio xin + chnset kplayposratio, "twst_tfplayposratio" +endop + +opcode twst_tf_getwintype, i, j + iwintype xin + if (iwintype == -1) then + iwintype = twst_parami("wintype") + endif + ifnWindow = gifnHanning + if (iwintype == 1) then + ifnWindow = gifnHamming + elseif (iwintype == 2) then + ifnWindow = gifnHalfSine + endif + xout ifnWindow +endop + +opcode twst_tf_getwintypek, k, 0 + kwintype = twst_param:k("wintype") + kfnWindow = gifnHanning + if (kwintype == 1) then + kfnWindow = gifnHamming + elseif (kwintype == 2) then + kfnWindow = gifnHalfSine + endif + xout kfnWindow +endop + +opcode twst_tf_getwaveform, i, j + iwave xin + if (iwave == -1) then + iwave = twst_parami("wave") + endif + ifn = gifnSine + if (iwave == 1) then + ifn = gifnSquare + elseif (iwave == 2) then + ifn = gifnSaw + elseif (iwave == 3) then + ifn = gifnPulse + elseif (iwave == 4) then + ifn = gifnTriangle + endif + xout ifn +endop + +opcode twst_tf_getwaveformk, k, J + kwave xin + kwave = (kwave == -1) ? twst_param:k("wave") : kwave + kfn = gifnSine + if (kwave == 1) then + kfn = gifnSquare + elseif (kwave == 2) then + kfn = gifnSaw + elseif (kwave == 3) then + kfn = gifnPulse + elseif (kwave == 4) then + kfn = gifnTriangle + endif + xout kfn +endop + +opcode twst_getfinput, ffaaii, jJ + ifftsize, kpvslock xin + ifftsize = (ifftsize == -1) ? twst_parami("fftsize") : ifftsize + kpvslock = (kpvslock == -1) ? twst_param:k("pvslock") : kpvslock + iwintype = twst_parami("pvswintype") + idecimation = twst_parami("pvsdecimation") + iwinsizem = twst_parami("pvswinsizem") + + iwinsize = ifftsize * iwinsizem + twst_setlatencysamples(iwinsize) ;idecimation) + aL, aR, ileft, iright twst_getinput + + if (ileft == 0) then + fL pvsinit ifftsize + else + fLbase pvsanal aL, ifftsize, ifftsize / idecimation, iwinsize, 1 + fL pvslock fLbase, kpvslock + endif + + if (iright == 0) then + fR pvsinit ifftsize + else + fRbase pvsanal aR, ifftsize, ifftsize / idecimation, iwinsize, 1 + fR pvslock fRbase, kpvslock + endif + xout fL, fR, aL, aR, ileft, iright +endop + +/* TODO: LPC unstable with WASM +opcode twst_getfinput, ffaaii, jJ + ifftsize, kpvslock xin + ifftsize = (ifftsize == -1) ? twst_parami("fftsize") : ifftsize + kpvslock = (kpvslock == -1) ? twst_param:k("pvslock") : kpvslock + ipvstype = twst_parami("pvstype") + iwintype = twst_parami("pvswintype") + iwinlpcfn = twst_tf_getwintype(twst_parami("pvswintypelpc")) + idecimation = twst_parami("pvsdecimation") + iwinsizem = twst_parami("pvswinsizem") + iorderm = twst_parami("pvsorderm") + + if (ipvstype == 1) then + ifftsize = min(ifftsize, 1024) ; crashes in WASM with high FFT size and LPC + endif + + iorder = min(max(1, round(ifftsize * iorderm)), ifftsize) + iwinsize = ifftsize * iwinsizem + twst_setlatencysamples(iwinsize) ;idecimation) + aL, aR, ileft, iright twst_getinput + + if (ileft == 0) then + fL pvsinit ifftsize + else + if (ipvstype == 0) then + fLbase pvsanal aL, ifftsize, ifftsize / idecimation, iwinsize, 1 + else + fLbase pvslpc aL, ifftsize, ifftsize / idecimation, iorder, iwinlpcfn + endif + fL pvslock fLbase, kpvslock + endif + + if (iright == 0) then + fR pvsinit ifftsize + else + if (ipvstype == 0) then + fRbase pvsanal aR, ifftsize, ifftsize / idecimation, iwinsize, 1 + else + fRbase pvslpc aR, ifftsize, ifftsize / idecimation, iorder, iwinlpcfn + endif + fR pvslock fRbase, kpvslock + endif + xout fL, fR, aL, aR, ileft, iright +endop +*/ + + +; ileft, iright, istartsamp, iendsamp, idocut, ilength twst_tf_getstate +opcode twst_tf_getstate, iiiiii, 0 + ilengths = ((gitwst_tf_state[3] - gitwst_tf_state[2]) / sr) + xout gitwst_tf_state[0], gitwst_tf_state[1], gitwst_tf_state[2], gitwst_tf_state[3], gitwst_tf_state[4], ilengths +endop + +opcode twst_tf_isoffline, i, 0 + xout gitwst_tf_state[6] +endop + +opcode twst_tfi_getfn, ii, jjjjjj + instanceindex, ileft, iright, istartsamp, iendsamp, idocut xin + instanceindex = (instanceindex == -1) ? gitwst_instanceindex : instanceindex + ileft = (ileft == -1) ? gitwst_tf_state[0] : ileft + iright = (iright == -1) ? gitwst_tf_state[1] : iright + istartsamp = (istartsamp == -1) ? gitwst_tf_state[2] : istartsamp + iendsamp = (iendsamp == -1) ? gitwst_tf_state[3] : iendsamp + idocut = (idocut == -1) ? gitwst_tf_state[4] : idocut + if (idocut == 1) then + itargetlen = iendsamp - istartsamp ;int(p3 * sr) + if (ileft == 1) then + ifnL ftgentmp 0, 0, -itargetlen, -2, 0 + ftslicei gitwst_bufferL[instanceindex], ifnL, istartsamp, iendsamp, 1 + else + ifnL = 0 + endif + if (iright == 1) then + ifnR ftgentmp 0, 0, -itargetlen, -2, 0 + ftslicei gitwst_bufferR[instanceindex], ifnR, istartsamp, iendsamp, 1 + else + ifnR = 0 + endif + else + ifnL = gitwst_bufferL[instanceindex] + ifnR = gitwst_bufferR[instanceindex] + endif + xout ifnL, ifnR +endop + +opcode _twst_getcrossdata, iiiiiii, S + SchannelPrefix xin + if (strcmp(SchannelPrefix, "") == 0) then + ichannel = twst_parami("instchan") + instanceindex = twst_parami("instance") + istart = twst_parami("inststart") + iend = twst_parami("instend") + else + ichannel chnget strcat(SchannelPrefix, sprintf("instchan%d", p4)) + instanceindex chnget strcat(SchannelPrefix, sprintf("instance%d", p4)) + istart chnget strcat(SchannelPrefix, sprintf("inststart%d", p4)) + iend chnget strcat(SchannelPrefix, sprintf("instend%d", p4)) + endif + idoleft = 1 + idoright = 1 + if (ichannel == 0 || gitwst_channels[instanceindex] == 1) then + idoright = 0 + elseif (ichannel == 1 && gitwst_channels[instanceindex] == 2) then + idoleft = 0 + endif + if (istart == iend) then + istart = 0 + iend = 1 + endif + istart, ilen twst_getstartend istart, iend, instanceindex + ifnL = gitwst_bufferL[instanceindex] + ifnR = gitwst_bufferR[instanceindex] + + xout idoleft, idoright, ifnL, ifnR, instanceindex, istart, ilen +endop + +opcode _twst_getcrossdata, iiiiii, S + SchannelPrefix xin + ileft, iright, ifnL, ifnR, instanceindex, istart, iend _twst_getcrossdata SchannelPrefix + xout ifnL, ifnR, istart, iend - istart, ileft, iright +endop + +opcode twst_getcrossdata, iiiiii, 0 + ifnL, ifnR, istart, ilen, idoleft, idoright _twst_getcrossdata "" + xout ifnL, ifnR, istart, ilen, idoleft, idoright +endop + +opcode twst_tfi_getcrossfn, ii, 0 + ileft, iright, ifnL, ifnR, instanceindex, istart, ilen _twst_getcrossdata "" + idocut = (ftlen(ifnL) == ilen) ? 0 : 1 + ifnLtemp, ifnRtemp twst_tfi_getfn instanceindex, ileft, iright, istart, istart + ilen, idocut + if (gitwst_channels[instanceindex] == 1) then + ifnRtemp = ifnLtemp + endif + xout ifnLtemp, ifnRtemp +endop + +opcode _twst_getcrossinput, aaii, S + SchannelPrefix xin + ifnL, ifnR, istart, ilen, idoleft, idoright _twst_getcrossdata SchannelPrefix + if (strcmp(SchannelPrefix, "") == 0) then + ilooptype = twst_parami("otlooptype") + else + ichannel chnget strcat(SchannelPrefix, sprintf("looptype%d", p4)) + endif + apos lphasor 1, 0, ilen, ilooptype + apos += istart + + if (idoleft == 1) then + aL table3 apos, ifnL + endif + if (idoright == 1) then + aR table3 apos, ifnR + endif + + if (idoright == 0) then + aR = aL + endif + if (idoleft == 0) then + aL = aR + endif + xout aL, aR, idoleft, idoright +endop + +opcode twst_getcrossinput, aaii, 0 + aL, aR, idoleft, idoright _twst_getcrossinput "" + xout aL, aR, idoleft, idoright +endop + +opcode twst_getfcrossinput, ffii, 0 + aL, aR, ileft, iright twst_getcrossinput + ifftsize = twst_parami("fftsize") + kpvslock = twst_param:k("pvslock") + idecimation = twst_parami("pvsdecimation") + iwinsizem = twst_parami("pvswinsizem") + iwinsize = ifftsize * iwinsizem + + if (ileft == 0) then + fL pvsinit ifftsize + else + fLbase pvsanal aL, ifftsize, ifftsize / idecimation, iwinsize, 1 + fL pvslock fLbase, kpvslock + endif + + if (iright == 0) then + fR pvsinit ifftsize + else + fRbase pvsanal aR, ifftsize, ifftsize / idecimation, iwinsize, 1 + fR pvslock fRbase, kpvslock + endif + xout fL, fR, ileft, iright +endop + +opcode twst_tf_fresynth, a, f + fsig xin + imode = twst_parami("pvresmode") + if (imode == 0) then + aout pvsynth fsig + else + ifftsize = twst_parami("fftsize") + ioscnum = max(round((ifftsize * 0.5) * twst_parami("pvaoscnum")) - 1, 1) + kfmod = twst_param:k("pvafreqmod") + ibinoffset = round(ifftsize * 0.5 * twst_parami("pvabinoffset")) + ibinincr = twst_parami("pvabinincr") + ioscnum = ioscnum - ibinoffset + ioscnum = min(((ifftsize * 0.5) / ibinincr), ioscnum) + aout pvsadsyn fsig, ioscnum, kfmod, ibinoffset, ibinincr + endif + xout aout +endop + +opcode twst_getrandombuffers, kk, k + kstereounique xin + kfnL = -1 + kfnR = -1 + + if (kstereounique == 0) then + while (kfnL == -1) do + kindex = round:k(random:k(0, lenarray(gitwst_bufferL) - 1)) + if (ftexists:k(gitwst_bufferL[kindex]) == 1) then + kfnL = gitwst_bufferL[kindex] + if (ftexists:k(gitwst_bufferR[kindex]) == 1) then + kfnR = gitwst_bufferR[kindex] + else + kfnR = kfnL + endif + endif + od + else + while (kfnL == -1) do + kfn = gitwst_bufferL[round:k(random:k(0, lenarray(gitwst_bufferL) - 1))] + if (ftexists:k(kfn) == 1) then + kfnL = kfn + endif + od + while (kfnR == -1) do + kfn = gitwst_bufferR[round:k(random:k(0, lenarray(gitwst_bufferR) - 1))] + if (ftexists:k(kfn) == 1) then + kfnR = kfn + endif + od + endif + xout kfnL, kfnR +endop + +#end diff --git a/site/udo/twist/transforms.udo b/site/udo/twist/transforms.udo new file mode 100755 index 0000000..2587d18 --- /dev/null +++ b/site/udo/twist/transforms.udo @@ -0,0 +1,25 @@ +#ifndef TWST_TRANSFORMS +#define TWST_TRANSFORMS ## +/* + Twist waveform editor and transformer + Transforms + + This file is part of the SONICS UDO collection by Richard Knight 2024 + License: GPL-2.0-or-later + http://1bpm.net +*/ + +#include "/twist/transforms/amplitude.udo" +#include "/twist/transforms/cross_processing.udo" +#include "/twist/transforms/delay.udo" +#include "/twist/transforms/filter.udo" +#include "/twist/transforms/frequency.udo" +#include "/twist/transforms/general.udo" +#include "/twist/transforms/generate.udo" +#include "/twist/transforms/granular.udo" +#include "/twist/transforms/harmonic.udo" +#include "/twist/transforms/reverb.udo" +#include "/twist/transforms/spectral.udo" +#include "/twist/transforms/warping.udo" + +#end \ No newline at end of file diff --git a/site/udo/twist/transforms/amplitude.udo b/site/udo/twist/transforms/amplitude.udo new file mode 100755 index 0000000..d477b4f --- /dev/null +++ b/site/udo/twist/transforms/amplitude.udo @@ -0,0 +1,179 @@ +#include "/twist/transform_api.udo" +#include "/frequency_tools.udo" + +opcode _twst_tf_normalise_analyse, i, iii + ifn, istartsamp, iendsamp xin + iscale = 0 + imaxpos = 0 + imaxneg = 0 + while (istartsamp < iendsamp) do + ival table istartsamp, ifn + if (ival > 0 && ival > imaxpos) then + imaxpos = ival + elseif (ival < 0 && ival < imaxneg) then + imaxneg = ival + endif + istartsamp += 1 + od + iscale = ((1 / max(abs(imaxneg), abs(imaxpos)))) + xout iscale +endop + +instr twst_tf_normalise + $TWST_TRANSFORM + i_, i_, istartsamp, iendsamp, idocut, ilength twst_tf_getstate + aL, aR, ileft, iright twst_getinput + istereoequal = twst_parami("equal") + kuserscale = twst_param:k("scale") + + if (ileft == 1) then + iscalingL _twst_tf_normalise_analyse gitwst_bufferL[gitwst_instanceindex], istartsamp, iendsamp + endif + if (iright == 1) then + iscalingR _twst_tf_normalise_analyse gitwst_bufferR[gitwst_instanceindex], istartsamp, iendsamp + endif + + if (istereoequal == 1 && ileft == 1 && iright == 1) then + iscaling = min(iscalingL, iscalingR) + aL *= iscaling * kuserscale + aR *= iscaling * kuserscale + elseif (ileft == 1) then + aL *= iscalingL * kuserscale + elseif (iright == 1) then + aR *= iscalingR * kuserscale + endif + + outs aL, aR +endin + +instr twst_tf_amplitude + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kgain = twst_param:k("gain") + kbalance = twst_param:k("balance") + if (ileft == 1) then + kb = max:k(1, (1 - kbalance) * 2) + aL *= kgain * kb + endif + if (iright == 1) then + kb = max:k(1, kbalance * 2) + aR *= kgain * kb + endif + outs aL, aR +endin + +instr twst_tf_strobe + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + krate = twst_param:k("rate") + kholdtime = twst_param:k("holdtime") + kwindowed = twst_param:k("windowed") + + ktrig metro krate + ktrig trighold ktrig, kholdtime + kamp = 1 - ktrig + + if (kwindowed == 1) then + kenv portk kamp, kholdtime * 0.5 + else + kenv = kamp + endif + + if (ileft == 1) then + aL *= kenv + endif + if (iright == 1) then + aR *= kenv + endif + outs aL, aR +endin + +instr twst_tf_bitcrush + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kcrush = twst_param:k("crush") + if (ileft == 1) then + aL bitcrush aL, kcrush + elseif (iright == 1) then + aR bitcrush aR, kcrush + endif + outs aL, aR +endin + + +instr twst_tf_suppress + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kmode = twst_param:k("mode") + kthreshold = twst_param:k("threshold") + + if (ileft == 1) then + if (kmode == 0) then + aL limit aL, -kthreshold, kthreshold + elseif (kmode == 1) then + aL wrap aL, -kthreshold, kthreshold + elseif (kmode == 2) then + aL mirror aL, -kthreshold, kthreshold + endif + endif + if (iright == 1) then + if (kmode == 0) then + aR limit aR, -kthreshold, kthreshold + elseif (kmode == 1) then + aR wrap aR, -kthreshold, kthreshold + elseif (kmode == 2) then + aR mirror aR, -kthreshold, kthreshold + endif + endif + outs aL, aR +endin + +instr twst_tf_pdclip + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kwidth = twst_param:k("width") + kcentre = twst_param:k("centre") + ibipolar = twst_parami("bipolar") + ifullscale = twst_parami("fullscale") + + if (ileft == 1) then + aL pdclip aL, kwidth, kcentre, ibipolar, ifullscale + endif + if (iright == 1) then + aR pdclip aR, kwidth, kcentre, ibipolar, ifullscale + endif + outs aL, aR +endin + +instr twst_tf_distort + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kamount = twst_param:k("amount") + ihp = twst_parami("halfpower") + ifn twst_tf_getwaveform + + if (ileft == 1) then + aL distort aL, kamount, ifn, ihp + endif + if (iright == 1) then + aL distort aR, kamount, ifn, ihp + endif + outs aL, aR +endin + +instr twst_tf_distort1 + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kpregain = twst_param:k("pregain") + kpostgain = twst_param:k("postgain") + kshape1 = twst_param:k("shape1") + kshape2 = twst_param:k("shape2") + + if (ileft == 1) then + aL distort1 aL, kpregain, kpostgain, kshape1, kshape2, 1 + endif + if (iright == 1) then + aL distort1 aR, kpregain, kpostgain, kshape1, kshape2, 1 + endif + outs aL, aR +endin diff --git a/site/udo/twist/transforms/cross_processing.udo b/site/udo/twist/transforms/cross_processing.udo new file mode 100755 index 0000000..203c393 --- /dev/null +++ b/site/udo/twist/transforms/cross_processing.udo @@ -0,0 +1,176 @@ +#include "/twist/transform_api.udo" +#include "/mfcc_match.udo" +#include "/fftconvolve.udo" +#include "/chop.udo" + + +instr twst_tf_crossrearrange + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kminsamples = twst_param:k("minsamples") + kmaxsamples = twst_param:k("maxsamples") + kstereounique = twst_param:k("stereounique") + krate = twst_param:k("rate") + + ktrig metro krate + async init 0 + + if (ktrig == 1) then + kfnLo, kfnRo twst_getrandombuffers kstereounique + ktablen = tableng:k(kfnLo) + klen = min:k(random:k(kminsamples, kmaxsamples), ktablen) + kstart = random:k(0, ktablen - klen) + async = 1 + else + async = 0 + endif + + apos, a_ syncphasor 1 / (klen / sr), async + areadpos = (apos * klen) + kstart + + if (ileft == 1) then + aL tablekt areadpos, kfnLo + endif + if (iright == 1) then + aR tablekt areadpos, kfnRo + endif + + outs aL, aR +endin + +instr twst_tf_directconvolve + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + ifnLo, ifnRo twst_tfi_getcrossfn + kamp = twst_parami("amp") + isizeratio = twst_parami("sizeratio") + if (ileft == 1) then + aL dconv aL * kamp, isizeratio * ftlen(ifnLo), ifnLo + endif + if (iright == 1) then + aR dconv aR * kamp, isizeratio * ftlen(ifnRo), ifnRo + endif + outs aL, aR +endin + +instr twst_tf_blockconvolve + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + aLo, aRo, ilefto, irighto twst_getcrossinput + ifftsize = twst_parami("fftsize") + ioverlap = twst_parami("overlap") + ihopsize = ifftsize / ioverlap + + if (ileft == 1 && ilefto == 1) then + aL blockconvolve aL, aLo, ifftsize, ihopsize + endif + if (iright == 1 && irighto == 1) then + aR blockconvolve aR, aRo, ifftsize, ihopsize + endif + outs aL, aR +endin + +/* not in WASM at current +instr twst_tf_tvconv + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + aLo, aRo, ilefto, irighto twst_getcrossinput + kapply1 = twst_param:k("apply1") + kapply2 = twst_param:k("apply2") + imode = twst_parami("mode") + iparts = twst_parami("parts") + idftfiltersize = twst_parami("dftfiltersize") + ifirfiltersize = twst_parami("firfiltersize") + + if (imode == 1) then + iparts = 1 + ifiltersize = ifirfiltersize + else + ifiltersize = idftfiltersize + endif + + if (ileft == 1 && ilefto == 1) then + aL tvconv aL, aLo, kapply1, kapply2, iparts, ifiltersize + endif + + if (iright == 1 && irighto == 1) then + aR tvconv aR, aRo, kapply1, kapply2, iparts, ifiltersize + endif + outs aL, aR +endin +*/ + +instr twst_tf_crosssynth + $TWST_TRANSFORM + fL, fR, aL, aR, ileft, iright twst_getfinput + fLo, fRo, ilefto, irighto twst_getfcrossinput + kamp1 = twst_param:k("amp1") + kamp2 = twst_param:k("amp2") + + if (ileft == 1 && ilefto == 1) then + foutL pvscross fL, fLo, kamp1, kamp2 + aL twst_tf_fresynth foutL + endif + + if (iright == 1 && irighto == 1) then + foutR pvscross fR, fRo, kamp1, kamp2 + aR twst_tf_fresynth foutR + endif + outs aL, aR +endin + + +instr twst_tf_morph + $TWST_TRANSFORM + fL, fR, aL, aR, ileft, iright twst_getfinput + fLo, fRo, ilefto, irighto twst_getfcrossinput + kamp = twst_param:k("amp") + kfreq = twst_param:k("freq") + + if (ileft == 1 && ilefto == 1) then + foutL pvsmorph fL, fLo, kamp, kfreq + aL twst_tf_fresynth foutL + endif + + if (iright == 1 && irighto == 1) then + foutR pvsmorph fR, fRo, kamp, kfreq + aR twst_tf_fresynth foutR + endif + outs aL, aR +endin + +instr twst_tf_mfccmatch + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + ifnoL, ifnoR twst_tfi_getcrossfn + ifftsize = twst_parami("fftsize") + ifreqmin = twst_parami("freqmin") + ifreqmax = twst_parami("freqmax") + ibands = twst_parami("bands") + kstretch = twst_param:k("stretch") + kauditionreadyL init 0 + kauditionreadyR init 0 + ktimek timeinstk + + if (ileft == 1) then + kdone, ifnAnalysisL mfm_analysecorpus ktimek, ifnoL, ifreqmin, ifreqmax, ifftsize, ibands, -1, 1 + if (kdone == 1) then + kauditionreadyL = 1 + aoutL mfm_matchplay aL, ifnoL, ifnAnalysisL, kstretch, ifreqmin, ifreqmax, ifftsize, ibands + endif + else + kauditionreadyL = 1 + endif + if (iright == 1) then + kdone, ifnAnalysisR mfm_analysecorpus ktimek, ifnoR, ifreqmin, ifreqmax, ifftsize, ibands, -1, 1 + if (kdone == 1) then + kauditionreadyR = 1 + aoutR mfm_matchplay aR, ifnoR, ifnAnalysisR, kstretch, ifreqmin, ifreqmax, ifftsize, ibands + endif + else + kauditionreadyR = 1 + endif + + chnset (kauditionreadyL & kauditionreadyR), "auditionready" + outs aoutL, aoutR +endin diff --git a/site/udo/twist/transforms/delay.udo b/site/udo/twist/transforms/delay.udo new file mode 100755 index 0000000..5d59612 --- /dev/null +++ b/site/udo/twist/transforms/delay.udo @@ -0,0 +1,72 @@ +#include "/twist/transform_api.udo" + +instr twst_tf_vdelay + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kdelay = twst_param:k("delay") * 1000 + kfeedback = twst_param:k("feedback") + adelay = a(kdelay) + + if (ileft == 1) then + afbkL init 0 + aLd vdelay3 aL + afbkL, adelay, 1000 + afbkL = aLd * kfeedback + aL = aLd + endif + if (iright == 1) then + afbkR init 0 + aRd vdelay3 aR + afbkR, adelay, 1000 + afbkR = aRd * kfeedback + aR = aRd + endif + outs aL, aR +endin + +instr twst_tf_flanger + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kdelay = twst_param:k("delay") + kfeedback = twst_param:k("feedback") + + adelay = a(kdelay) + if (ileft == 1) then + aL flanger aL, adelay, kfeedback + endif + if (iright == 1) then + aR flanger aR, adelay, kfeedback + endif + outs aL, aR +endin + +instr twst_tf_phaser1 + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kfreq = twst_param:k("freq") + iord = twst_parami("order") + kfeedback = twst_param:k("feedback") + if (ileft == 1) then + aL phaser1 aL, kfreq, iord, kfeedback + endif + if (iright == 1) then + aR phaser1 aR, kfreq, iord, kfeedback + endif + outs aL, aR +endin + +instr twst_tf_phaser2 + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kfreq = twst_param:k("freq") + kq = twst_param:k("q") + iord = twst_parami("order") + imode = twst_parami("mode") + ksep = twst_param:k("sep") + kfeedback = twst_param:k("feedback") + if (ileft == 1) then + aL phaser2 aL, kfreq, kq, iord, imode, ksep, kfeedback + endif + if (iright == 1) then + aR phaser2 aR, kfreq, kq, iord, imode, ksep, kfeedback + endif + outs aL, aR +endin diff --git a/site/udo/twist/transforms/filter.udo b/site/udo/twist/transforms/filter.udo new file mode 100755 index 0000000..38fad69 --- /dev/null +++ b/site/udo/twist/transforms/filter.udo @@ -0,0 +1,172 @@ +#include "/twist/transform_api.udo" + +instr twst_tf_lpf + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kfreq = twst_param:k("frequency") + if (ileft == 1) then + aL butterlp aL, kfreq + endif + if (iright == 1) then + aR butterlp aR, kfreq + endif + outs aL, aR +endin + +instr twst_tf_hpf + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kfreq = twst_param:k("frequency") + if (ileft == 1) then + aL butterhp aL, kfreq + endif + if (iright == 1) then + aR butterhp aR, kfreq + endif + outs aL, aR +endin + +instr twst_tf_bpf + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kfreq = twst_param:k("frequency") + kbw = twst_param:k("bandwidth") + if (ileft == 1) then + aL butterbp aL, kfreq, kbw + endif + if (iright == 1) then + aR butterbp aR, kfreq, kbw + endif + outs aL, aR +endin + +instr twst_tf_pareq + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kfreq = twst_param:k("frequency") + kgain = twst_param:k("gain") + kq = twst_param:k("q") + if (ileft == 1) then + aL pareq aL, kfreq, kgain, kq + endif + if (iright == 1) then + aR pareq aR, kfreq, kgain, kq + endif + outs aL, aR +endin + +instr twst_tf_dcblock + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + if (ileft == 1) then + aL dcblock2 aL + endif + if (iright = 1) then + aR dcblock2 aR + endif + outs aL, aR +endin + +/* not in WASM +{ + name: "Non-linear filter", + instr: "twst_tf_nlfilter", + parameters: [ + {name: "Parameter a", channel: "pa", min: 0, max: 1, dfault: 0.3}, + {name: "Parameter b", channel: "pb", min: -1, max: 1, dfault: 0.1}, + {name: "Parameter d", channel: "pd", min: 0, max: 1, dfault: 0.7}, + {name: "Parameter C", channel: "pC", min: 0, max: 1, dfault: 0.12}, + {name: "Parameter L", channel: "pL", min: 1, max: 220, dfault: 20}, + {preset: "applymode"} + ] +}, + +instr twst_tf_nlfilter + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kpa = twst_param:k("pa") + kpb = twst_param:k("pb") + kpd = twst_param:k("pd") + kpC = twst_param:k("pC") + kpL = twst_param:k("pL") + nfilt + if (ileft == 1) then + aL nfilt2 aL, kpa, kpb, kpd, kpC, kpL + endif + if (iright == 1) then + aR nfilt2 aR, kpa, kpb, kpd, kpC, kpL + endif + outs aL, aR +endin +*/ + +instr twst_tf_mooghpf + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kfreq = twst_param:k("freq") + if (ileft == 1) then + aL mvchpf aL, kfreq + endif + if (iright == 1) then + aR mvchpf aR, kfreq + endif + outs aL, aR +endin + +instr twst_tf_mooglpf + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kfreq = twst_param:k("freq") + kres = twst_param:k("resonance") + kmode = twst_param:k("mode") + if (ileft == 1) then + if (kmode == 0) then + aL mvclpf1 aL, kfreq, kres + elseif (kmode == 1) then + aL mvclpf2 aL, kfreq, kres + elseif (kmode == 2) then + aL mvclpf3 aL, kfreq, kres + endif + endif + if (iright == 1) then + if (kmode == 0) then + aR mvclpf1 aR, kfreq, kres + elseif (kmode == 1) then + aR mvclpf2 aR, kfreq, kres + elseif (kmode == 2) then + aR mvclpf3 aR, kfreq, kres + endif + endif + outs aL, aR +endin + +instr twst_tf_waveguide1 + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kfreq = twst_param:k("freq") + kcutoff = twst_param:k("cutoff") + kfeedback = twst_param:k("feedback") + if (ileft == 1) then + aL wguide1 aL, kfreq, kcutoff, kfeedback + endif + if (iright == 1) then + aR wguide1 aR, kfreq, kcutoff, kfeedback + endif + outs aL, aR +endin + +instr twst_tf_tbvcf + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kfreq = twst_param:k("freq") + kres = twst_param:k("resonance") + kdist = twst_param:k("dist") + kasym = twst_param:k("asym") + if (ileft == 1) then + aL tbvcf aL, kfreq, kres, kdist, kasym + endif + if (iright == 1) then + aR tbvcf aR, kfreq, kres, kdist, kasym + endif + outs aL, aR +endin diff --git a/site/udo/twist/transforms/frequency.udo b/site/udo/twist/transforms/frequency.udo new file mode 100755 index 0000000..a56b808 --- /dev/null +++ b/site/udo/twist/transforms/frequency.udo @@ -0,0 +1,65 @@ +#include "/twist/transform_api.udo" +#include "/frequency_tools.udo" + +instr twst_tf_freqshift1 + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kshift = twst_param:k("shift") + if (ileft == 1 && iright == 1) then + aL, aR freqshift1 aL, aR, kshift + elseif (ileft == 1) then + aL freqshift1 aL, kshift + elseif (iright == 1) then + aR freqshift1 aR, kshift + endif + outs aL, aR +endin + +instr twst_tf_freqshift2 + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kshift = twst_param:k("shift") + if (ileft == 1 && iright == 1) then + aL, aR freqshift2 aL, aR, kshift + elseif (ileft == 1) then + aL freqshift2 aL, kshift + elseif (iright == 1) then + aR freqshift2 aR, kshift + endif + outs aL, aR +endin + +instr twst_tf_ringmod + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kfreq = twst_param:k("frequency") + if (ileft == 1 && iright == 1) then + aL, aR ringmod1 aL, aR, kfreq + elseif (ileft == 1) then + aL ringmod1 aL, kfreq + elseif (iright == 1) then + aR ringmod1 aR, kfreq + endif + outs aL, aR +endin + +instr twst_tf_exciter + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kfreqlow = twst_tf_freq_custom("low") + kfreqhigh = twst_tf_freq_custom("high") + kharmonics = twst_param:k("harmonics") + kblend = twst_param:k("blend") + + if (kfreqhigh < kfreqlow) then + kfreqhigh = kfreqlow + endif + + if (ileft == 1) then + aL exciter aL, kfreqlow, kfreqhigh, kharmonics, kblend + endif + if (iright == 1) then + aR exciter aR, kfreqlow, kfreqhigh, kharmonics, kblend + endif + outs aL, aR +endin diff --git a/site/udo/twist/transforms/general.udo b/site/udo/twist/transforms/general.udo new file mode 100755 index 0000000..b46f570 --- /dev/null +++ b/site/udo/twist/transforms/general.udo @@ -0,0 +1,28 @@ +#include "/twist/transform_api.udo" + +instr twst_tfi_reverse + $TWST_TRANSFORM + ileft, iright, istartsamp, iendsamp, idocut, ilength twst_tf_getstate + ifnL, ifnR twst_tfi_getfn + ioffline twst_tf_isoffline + apos linseg (iendsamp - istartsamp) - 1, ilength, 0 + if (ileft == 1) then + if (ioffline == 1) then + ifntempL ftgentmp 0, 0, -ftlen(ifnL), -2, 0 + tableicopy ifntempL, ifnL + aL table3 apos, ifntempL + else + aL table3 apos, ifnL + endif + endif + if (iright == 1) then + if (ioffline == 1) then + ifntempR ftgentmp 0, 0, -ftlen(ifnR), -2, 0 + tableicopy ifntempR, ifnR + aR table3 apos, ifntempR + else + aR table3 apos, ifnR + endif + endif + outs aL, aR +endin diff --git a/site/udo/twist/transforms/generate.udo b/site/udo/twist/transforms/generate.udo new file mode 100755 index 0000000..e7355a8 --- /dev/null +++ b/site/udo/twist/transforms/generate.udo @@ -0,0 +1,363 @@ +#include "/addsub.udo" + +instr twst_tf_gensilence + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + a0 init 0 + if (ileft == 1) then + aL = a0 + endif + if (iright == 1) then + aR = a0 + endif + outs aL, aR +endin + + +instr twst_tf_genadditive + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + ifreq = twst_parami("minfreq") + ifreqmax = twst_parami("maxfreq") + ifreqstepmult = twst_parami("step") + ifreqstepmultrand = twst_parami("steprand") + iamp = twst_parami("amp") + iampmult = twst_parami("ampmult") + + if (ileft == 1) then + aL as_additive ifreq, ifreqmax, ifreqstepmult, ifreqstepmultrand, iamp, iampmult + endif + if (iright == 1) then + aR as_additive ifreq, ifreqmax, ifreqstepmult, ifreqstepmultrand, iamp, iampmult + endif + outs aL, aR +endin + +instr twst_tf_gentone + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kamp = twst_param:k("amp") + kfreq twst_tf_freq + kfn twst_tf_getwaveformk + + aosc oscilikt kamp, kfreq, kfn + if (ileft == 1) then + aL = aosc + endif + if (iright == 1) then + aR = aosc + endif + outs aL, aR +endin + + +opcode twst_tf_gensimpleadditive, a, kkkkkio + kamp, kmultiplier, kfreq, kstepmult, kampprofile, iharmonics, index xin + if (kampprofile == 0) then + kgain = 1 + else + kgain = (1 - (index / iharmonics)) + endif + aosc oscili (1 / iharmonics) * kgain, (kfreq * kmultiplier) + if (index < iharmonics) then + arec twst_tf_gensimpleadditive, min:k(kfreq * kstepmult, sr / 2), kstepmult, kampprofile, iharmonics, index + 1 + aosc += arec + endif + xout aosc * kamp +endop + +instr twst_tf_gensimpleadditive + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kamp = twst_param:k("amp") + kfreq twst_tf_freq + kmultiplier = twst_param:k("multiplier") + kstepmult = twst_param:k("stepmultiplier") + kampprofile = twst_param:k("ampprofile") + iharmonics = twst_parami("harmonics") + + if (ileft == 1) then + aL twst_tf_gensimpleadditive kamp, kmultiplier, kfreq, kstepmult, kampprofile, iharmonics + endif + if (iright == 1) then + aR twst_tf_gensimpleadditive kamp, kmultiplier, kfreq, kstepmult, kampprofile, iharmonics + endif + outs aL, aR +endin + +opcode twst_tf_genfeedback, a, kkkk + kfeedback, kfreq, kpostgain, kbw xin + asig init 0 + asig += noise(0.00001, 0) + adel delay asig, 0.0001 + asig += (adel * kfeedback) + asig butterbp asig, kfreq, kbw + asig butterbp asig, kfreq, kbw + asig tanh ain + asig *= kpostgain + xout asig +endop + +instr twst_tf_genfeedback + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kamp = twst_param:k("amp") + kfeedback = twst_param:k("feedback") + kfreq twst_tf_freq + kpostgain = twst_param:k("postgain") + kbw = twst_param:k("bandwidth") + if (ileft == 1) then + aL twst_tf_genfeedback kfeedback, kfreq, kpostgain + aL *= kamp + endif + if (iright == 1) then + aR twst_tf_genfeedback kfeedback, kfreq, kpostgain + aR *= kamp + endif + outs aL, aR +endin + + +instr twst_tf_genfm + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kfreq twst_tf_freq + kamp = twst_param:k("amp") + kcarrier = twst_param:k("carrier") + kmod = twst_param:k("modulator") + kindex = twst_param:k("index") + kstereo = twst_param:k("stereovar") + ifn twst_tf_getwaveform + + if (ileft == 0 || iright == 0) then + kstereo = 1 + endif + + if (ileft == 1) then + aL foscili kamp, kfreq, kcarrier * kstereo, kmod * kstereo, kindex * kstereo, ifn + endif + if (iright == 1) then + kstereo = 1 - (kstereo - 1) + aR foscili kamp, kfreq, kcarrier * kstereo, kmod * kstereo, kindex * kstereo, ifn + endif + outs aL, aR +endin + +instr twst_tf_genfmmodel + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kfreq twst_tf_freq + ifmtype = twst_parami("fmtype") + kamp = twst_param:k("amp") + kc1 = twst_param:k("control1") + kc2 = twst_param:k("control2") + kvibdepth = twst_param:k("vibdepth") + kvibrate = twst_param:k("vibrate") + ifn1 twst_tf_getwaveform twst_parami("wave1") + ifn2 twst_tf_getwaveform twst_parami("wave2") + ifn3 twst_tf_getwaveform twst_parami("wave3") + ifn4 twst_tf_getwaveform twst_parami("wave4") + ifnv twst_tf_getwaveform twst_parami("vibwave") + kstereo = twst_param:k("stereovar") + + if (ileft == 0 || iright == 0) then + kstereo = 1 + endif + + if (ileft == 1) then + ifmtypei = (ifmtype == 5) ? round(random(0, 4)) : ifmtype + if (ifmtypei == 0) then + aL fmb3 kamp, kfreq, kc1 * kstereo, kc2 * kstereo, kvibdepth * kstereo, kvibrate * kstereo, ifn1, ifn2, ifn3, ifn4, ifnv + elseif (ifmtypei == 1) then + aL fmbell kamp, kfreq, kc1 * kstereo, kc2 * kstereo, kvibdepth * kstereo, kvibrate * kstereo, ifn1, ifn2, ifn3, ifn4, ifnv + elseif (ifmtypei == 2) then + aL fmpercfl kamp, kfreq, kc1 * kstereo, kc2 * kstereo, kvibdepth * kstereo, kvibrate * kstereo, ifn1, ifn2, ifn3, ifn4, ifnv + elseif (ifmtypei == 3) then + aL fmrhode kamp, kfreq, kc1 * kstereo, kc2 * kstereo, kvibdepth * kstereo, kvibrate * kstereo, ifn1, ifn2, ifn3, ifn4, ifnv + elseif (ifmtypei == 4) then + aL fmwurlie kamp, kfreq, kc1 * kstereo, kc2 * kstereo, kvibdepth * kstereo, kvibrate * kstereo, ifn1, ifn2, ifn3, ifn4, ifnv + endif + endif + if (iright == 1) then + kstereo = 1 - (kstereo - 1) + ifmtypei = (ifmtype == 5) ? round(random(0, 4)) : ifmtype + + if (ifmtypei == 0) then + aR fmb3 kamp, kfreq, kc1 * kstereo, kc2 * kstereo, kvibdepth * kstereo, kvibrate * kstereo, ifn1, ifn2, ifn3, ifn4, ifnv + elseif (ifmtypei == 1) then + aR fmbell kamp, kfreq, kc1 * kstereo, kc2 * kstereo, kvibdepth * kstereo, kvibrate * kstereo, ifn1, ifn2, ifn3, ifn4, ifnv + elseif (ifmtypei == 2) then + aR fmpercfl kamp, kfreq, kc1 * kstereo, kc2 * kstereo, kvibdepth * kstereo, kvibrate * kstereo, ifn1, ifn2, ifn3, ifn4, ifnv + elseif (ifmtypei == 3) then + aR fmrhode kamp, kfreq, kc1 * kstereo, kc2 * kstereo, kvibdepth * kstereo, kvibrate * kstereo, ifn1, ifn2, ifn3, ifn4, ifnv + elseif (ifmtypei == 4) then + aR fmwurlie kamp, kfreq, kc1 * kstereo, kc2 * kstereo, kvibdepth * kstereo, kvibrate * kstereo, ifn1, ifn2, ifn3, ifn4, ifnv + endif + endif + outs aL, aR +endin + + +opcode _twst_tf_genrepluck, a, kkiiikkkkk + kamp, kfn, ipluckpoint, ifreq, ipickuppoint, krefl, kexcitemode, kexcitefn, kexcitefreq, kexciteamp xin + + if (kexcitemode == 0) then + aexcite noise kexciteamp, 0.5 + else + aexcite oscilikt kexciteamp, kexcitefreq, kexcitefn + endif + aout repluck ipluckpoint, kamp, ifreq, ipickuppoint, krefl, aexcite + aout dcblock2 aout + xout aout +endop + +instr twst_tf_genrepluck + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kamp = twst_param:k("amp") + kfn twst_tf_getwaveformk + ipluckpoint = twst_parami("pluckpoint") + ifreq twst_tf_freqi + ipickuppoint = twst_parami("pickpoint") + krefl = twst_param:k("reflection") + kexciteamp = twst_param:k("exciteamp") + kexcitemode = twst_param:k("excitemode") + kexcitefn twst_tf_getwaveformk twst_param:k("excitewave") + kexcitefreq = twst_tf_freq_custom("excite") + + if (ileft == 1) then + aL _twst_tf_genrepluck kamp, kfn, ipluckpoint, ifreq, ipickuppoint, krefl, kexcitemode, kexcitefn, kexcitefreq, kexciteamp + endif + if (iright == 1) then + aR _twst_tf_genrepluck kamp, kfn, ipluckpoint, ifreq, ipickuppoint, krefl, kexcitemode, kexcitefn, kexcitefreq, kexciteamp + endif + outs aL, aR +endin + +instr twst_tf_genwgbow + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kamp = twst_param:k("amp") + kfreq twst_tf_freq + kpres = twst_param:k("pressure") + kpos = twst_param:k("position") + kvibf = twst_param:k("vibfreq") + kvamp = twst_param:k("vibamp") + ifn twst_tf_getwaveform + + if (ileft == 1) then + aL wgbow kamp, kfreq, kpres, kpos, kvibf, kvamp, ifn, 20 + endif + if (iright == 1) then + aR wgbow kamp, kfreq, kpres, kpos, kvibf, kvamp, ifn, 20 + endif + outs aL, aR +endin + +/* not quite right, doesn't create sound as expected +instr twst_tf_genwgbowedbar + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kamp = twst_param:k("amp") + kfreq twst_tf_freq + kpres = twst_param:k("pressure") + kpos = twst_param:k("position") + kgain = twst_param:k("filtergain") + + if (ileft == 1) then + aL wgbowedbar kamp, kfreq, kpos, kpres, kgain + endif + if (iright == 1) then + aR wgbowedbar kamp, kfreq, kpos, kpres, kgain + endif + outs aL, aR +endin + +instr twst_tf_genwgbrass + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kamp = twst_param:k("amp") + kfreq twst_tf_freq + ktension = twst_param:k("tension") + iattack = twst_parami("attack") + kvibf = twst_param:k("vibfreq") + kvamp = twst_param:k("vibamp") + ifn twst_tf_getwaveform + + if (ileft == 1) then + aL wgbrass kamp, kfreq, ktension, iattack, kvibf, kvamp, ifn, 100 + endif + if (iright == 1) then + aR wgbrass kamp, kfreq, ktension, iattack, kvibf, kvamp, ifn, 100 + endif + outs aL, aR +endin +*/ + +instr twst_tf_gennoise + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + ktype = twst_param:k("type") + kamp = twst_param:k("amp") + kbeta = twst_param:k("beta") + + if (ileft == 1) then + if (ktype == 0) then + aL unirand 2 + aL = aL - 1 + elseif (ktype == 1) then + aL pinker + endif + aL *= kamp + endif + if (iright == 1) then + if (ktype == 0) then + aR unirand 2 + aR = aR - 1 + elseif (ktype == 1) then + aR pinker + endif + aR *= kamp + endif + outs aL, aR +endin + +instr twst_tf_genbamboo + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kamp = twst_param:k("amp") + inum = twst_parami("number") + ifreq1 = twst_parami("r1freq") + ifreq2 = twst_parami("r2freq") + ifreq3 = twst_parami("r3freq") + + if (ileft == 1) then + aL bamboo kamp, 0, inum, 0, 0, ifreq1, ifreq2, ifreq3 + endif + if (iright == 1) then + aR bamboo kamp, 0, inum, 0, 0, ifreq1, ifreq2, ifreq3 + endif + outs aL, aR +endin + +/* opcode unavailable in WASM +{name: "Fractal noise", instr: "twst_tf_genfractalnoise", parameters: [ + {name: "Type", options: ["White", "Pink", "Brown"], automatable: true, description: "Type of noise"}, + {preset: "amp"}, + {preset: "applymode"} +]} + +instr twst_tf_genfractalnoise + aL, aR, ileft, iright twst_getinput + ktype = twst_param:k("type") + kamp = twst_param:k("amp") + + if (ileft == 1) then + aL fractalnoise kamp, ktype + endif + if (iright == 1) then + aR fractalnoise kamp, ktype + endif + outs aL, aR +endin +*/ diff --git a/site/udo/twist/transforms/granular.udo b/site/udo/twist/transforms/granular.udo new file mode 100755 index 0000000..c25a517 --- /dev/null +++ b/site/udo/twist/transforms/granular.udo @@ -0,0 +1,138 @@ +#include "/twist/transform_api.udo" +#include "/fx_autoglitch.udo" +#include "/sample_level.udo" + +instr twst_tfi_rearrange + $TWST_TRANSFORM + ileft, iright, istartsamp, iendsamp, idocut, ilength twst_tf_getstate + istereounique = twst_parami("stereounique") + ichops = twst_parami("chopnumber") + ichopmin = twst_parami("chopmin") + ichopmax = twst_parami("chopmax") + ifnL, ifnR twst_tfi_getfn + if (ileft == 1 && iright == 1) then + if (istereounique == 1) then + aL smp_rearrange ichops, ichopmin, ichopmax, ifnL + aR smp_rearrange ichops, ichopmin, ichopmax, ifnR + else + aL, aR smp_rearrange ichops, ichopmin, ichopmax, ifnL, ifnR + endif + elseif (ileft == 1) then + aL smp_rearrange ichops, ichopmin, ichopmax, ifnL + elseif (iright == 1) then + aR smp_rearrange ichops, ichopmin, ichopmax, ifnR + endif + outs aL, aR +endin + +instr twst_tfi_grain + $TWST_TRANSFORM + ileft, iright, istartsamp, iendsamp, idocut, ilength twst_tf_getstate + kamp = twst_param:k("amp") + kpitch = twst_tf_pitchscale() + kdensity = twst_param:k("density") + kgrainsize = twst_param:k("grainsize") + kampvar = twst_param:k("ampvar") + kpitchvar = twst_param:k("pitchvar") + irandom = twst_parami("randomread") + ifnWindow = twst_tf_getwintype() + + ifnL, ifnR twst_tfi_getfn + + kpitch *= (sr / ftlen(ifnL)) + + if (ileft == 1) then + aL grain kamp, kpitch, kdensity, kampvar, kpitchvar, kgrainsize, ifnL, ifnWindow, 0.5, irandom + endif + if (iright == 1) then + aR grain kamp, kpitch, kdensity, kampvar, kpitchvar, kgrainsize, ifnR, ifnWindow, 0.5, irandom + endif + outs aL, aR +endin + +instr twst_tfi_syncgrain + $TWST_TRANSFORM + ileft, iright, istartsamp, iendsamp, idocut, ilength twst_tf_getstate + kamp = twst_param:k("amp") + kfreq = twst_param:k("frequency") + kpitch = twst_tf_pitchscale() + kgrsize = twst_param:k("grainsize") + ioverlaps = twst_parami("overlaps") + itimescale = twst_parami("timescale") + ifnWindow = twst_tf_getwintype() + + iprate = (1 / ioverlaps) * itimescale + p3 = ilength * itimescale + + ifnL, ifnR twst_tfi_getfn + + if (ileft == 1) then + aL syncgrain kamp, kfreq, kpitch, kgrsize, iprate, ifnL, ifnWindow, ioverlaps + endif + if (iright == 1) then + aR syncgrain kamp, kfreq, kpitch, kgrsize, iprate, ifnR, ifnWindow, ioverlaps + endif + outs aL, aR +endin + +instr twst_tf_autoglitch + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kminratio = twst_param:k("minratio") + kchangerate = twst_param:k("changerate") + kchangechance = twst_param:k("changechance") + kporttime = twst_param:k("porttime") + kdo_distortion = twst_param:k("distortion") + kdo_ampchange = twst_param:k("ampchange") + ibuflens = twst_parami("buflens") + kreadmode = twst_param:k("readmode") + istereounique = twst_parami("stereounique") + + twst_setlatencyseconds ibuflens + + if (ileft == 1 && iright == 1) then + aL, aR fx_autoglitch aL, aR, kminratio, kchangerate, kchangechance, kporttime, kdo_distortion, kdo_ampchange, ibuflens, istereounique, kreadmode + elseif (ileft == 1) then + aL fx_autoglitch aL, kminratio, kchangerate, kchangechance, kporttime, kdo_distortion, kdo_ampchange, ibuflens, kreadmode + elseif (iright == 1) then + aR fx_autoglitch aR, kminratio, kchangerate, kchangechance, kporttime, kdo_distortion, kdo_ampchange, ibuflens, kreadmode + endif + outs aL, aR +endin + +instr twst_tfi_retriglitch + $TWST_TRANSFORM + ileft, iright, istartsamp, iendsamp, idocut, ilength twst_tf_getstate + ktriglen = twst_param:k("triglen") + kpitchscale = twst_tf_pitchscale() + kapplywindowing = twst_param:k("applywindowing") + ireadmode = twst_parami("readmode") + kwintype twst_tf_getwintypek + + p3 = ilength + if (ireadmode == 0) then + atime linseg 0, p3, ilength + elseif (ireadmode == 1) then + ktime = twst_param:k("readtime") + twst_tf_setplayposition ktime + atime = a(ktime * ilength) + elseif (ireadmode == 2) then + itimescale = twst_parami("timescale") + p3 = ilength * itimescale + atime linseg 0, p3, ilength + elseif (ireadmode == 3) then + atime linseg ilength, p3, 0 + elseif (ireadmode == 4) then + atime init -1 + endif + + ifnL, ifnR twst_tfi_getfn + + if (ileft == 1) then + aL fx_retrigglitch ifnL, ktriglen, atime, kpitchscale, kapplywindowing, kwintype + endif + if (iright == 1) then + aR fx_retrigglitch ifnR, ktriglen, atime, kpitchscale, kapplywindowing, kwintype + endif + outs aL, aR +endin diff --git a/site/udo/twist/transforms/harmonic.udo b/site/udo/twist/transforms/harmonic.udo new file mode 100755 index 0000000..717de44 --- /dev/null +++ b/site/udo/twist/transforms/harmonic.udo @@ -0,0 +1,142 @@ +#include "/twist/transform_api.udo" + +instr twst_tf_resony + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kfreq twst_tf_freq + kbw = twst_param:k("bandwidth") + inum = twst_parami("num") + ksep = twst_param:k("separation") + isepmode = twst_parami("sepmode") + ibalance = twst_parami("balance") + + if (ileft == 1) then + aLr resony aL, kfreq, kbw, inum, ksep, isepmode + if (ibalance == 1) then + aL balance aLr, aL + else + aL = aLr + endif + endif + if (iright == 1) then + aRr resony aR, kfreq, kbw, inum, ksep, isepmode + if (ibalance == 1) then + aR balance aRr, aR + else + aR = aRr + endif + endif + outs aL, aR +endin + +instr twst_tf_resonx + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kfreq twst_tf_freq + kbw = twst_param:k("bandwidth") + inum = twst_parami("num") + ibalance = twst_parami("balance") + + if (ileft == 1) then + aLr resonx aL, kfreq, kbw, inum + if (ibalance == 1) then + aL balance aLr, aL + else + aL = aLr + endif + endif + if (iright == 1) then + aRr resonx aR, kfreq, kbw, inum + if (ibalance == 1) then + aR balance aRr, aR + else + aR = aRr + endif + endif + outs aL, aR +endin + +instr twst_tf_streson + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kfreq twst_tf_freq + kfeedback = twst_param:k("feedback") + if (ileft == 1) then + aL streson aL, kfreq, kfeedback + endif + if (iright == 1) then + aR streson aR, kfreq, kfeedback + endif + outs aL, aR +endin + +instr twst_tf_mvmfilter + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kfreq = twst_param:k("freq") + kdecay = twst_param:k("decay") + kbalance = twst_param:k("balance") + if (ileft == 1) then + aLf mvmfilter aL, kfreq, kdecay + if (kbalance == 1) then + aL balance aLf, aL + else + aL = aLf + endif + endif + if (iright == 1) then + aRf mvmfilter aR, kfreq, kdecay + if (kbalance == 1) then + aL balance aRf, aR + else + aR = aRf + endif + endif + outs aL, aR +endin + +instr twst_tf_harmon + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kestfreq = twst_param:k("estfreq") + kmaxvar = twst_param:k("maxvar") + kgenfreq1 = twst_param:k("genfreq1") + kgenfreq2 = twst_param:k("genfreq2") + iminfreq = twst_parami("minfreq") + ianalysistime = twst_parami("analysistime") + if (ileft == 1) then + aL harmon aL, kestfreq, kmaxvar, kgenfreq1, kgenfreq2, 0, iminfreq, ianalysistime + endif + if (iright == 1) then + aR harmon aR, kestfreq, kmaxvar, kgenfreq1, kgenfreq2, 0, iminfreq, ianalysistime + endif + outs aL, aR +endin + +instr twst_tf_formantharmon + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kgenfreq1 = twst_param:k("genfreq1") + kgenfreq2 = twst_param:k("genfreq2") + kgenfreq3 = twst_param:k("genfreq3") + kgenfreq4 = twst_param:k("genfreq4") + iminfreq = octcps:i(twst_parami("minfreq")) + ipolarity = twst_parami("polarity") + + ipupdate = twst_parami("pupdate") + iplow = octcps:i(twst_parami("plowfreq")) + iphigh = octcps:i(twst_parami("phighfreq")) + ipthresh = dbamp:i(twst_parami("pthresh")) + ipfrqs = twst_parami("pfrqs") + ipconfirm = twst_parami("pconfirms") + + if (ileft == 1) then + koct, kamp pitch aL, ipupdate, iplow, iphigh, ipthresh, ipfrqs, ipconfirm + aL harmon4 aL, koct, kgenfreq1, kgenfreq2, kgenfreq3, kgenfreq4, 0, iminfreq, ipolarity + endif + if (iright == 1) then + koct, kamp pitch aR, ipupdate, iplow, iphigh, ipthresh, ipfrqs, ipconfirm + aR harmon4 aR, koct, kgenfreq1, kgenfreq2, kgenfreq3, kgenfreq4, 0, iminfreq, ipolarity + endif + outs aL, aR +endin diff --git a/site/udo/twist/transforms/reverb.udo b/site/udo/twist/transforms/reverb.udo new file mode 100755 index 0000000..e6f66ec --- /dev/null +++ b/site/udo/twist/transforms/reverb.udo @@ -0,0 +1,80 @@ +#include "/twist/transform_api.udo" + +instr twst_tf_reverb1 + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + ktime = twst_param:k("time") + if (ileft == 1) then + aL reverb aL, ktime + endif + if (iright == 1) then + aR reverb aR, ktime + endif + outs aL, aR +endin + +instr twst_tf_reverb2 + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + ktime = twst_param:k("time") + khfdamp = twst_param:k("hfdamp") + if (ileft == 1) then + aL nreverb aL, ktime, khfdamp + endif + if (iright == 1) then + aR nreverb aR, ktime, khfdamp + endif + outs aL, aR +endin + +instr twst_tf_reverb3 + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kroomsize = twst_param:k("roomsize") + khfdamp = twst_param:k("hfdamp") + if (ileft != 1) then + aL noise 0.001, 0.5 + endif + if (iright != 1) then + aR noise 0.001, 0.5 + endif + aL, aR freeverb aL, aR, kroomsize, khfdamp + outs aL, aR +endin + +instr twst_tf_reverb4 + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kfeedback = twst_param:k("feedback") + khfdamp = twst_param:k("hfdamp") * (sr / 2) + ipitchmod = twst_parami("pitchmod") + if (ileft != 1) then + aL noise 0.001, 0.5 + endif + if (iright != 1) then + aR noise 0.001, 0.5 + endif + aL, aR reverbsc aL, aR, kfeedback, khfdamp, sr, ipitchmod + outs aL, aR +endin + + +instr twst_tf_reverb5 + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + iwidth = twst_parami("width") + idepth = twst_parami("depth") + iheight = twst_parami("height") + kposx = twst_param:k("posx") * iwidth + kposy = twst_param:k("posy") * idepth + kposz = twst_param:k("posz") * iheight + if (ileft == 1 && iright == 1) then + ainput = (aL + aR) * 0.5 + elseif (ileft != 1) then + ainput = aR + else + ainput = aL + endif + aL, aR babo ainput, kposx, kposy, kposz, iwidth, idepth, iheight + outs aL, aR +endin diff --git a/site/udo/twist/transforms/spectral.udo b/site/udo/twist/transforms/spectral.udo new file mode 100755 index 0000000..b5f2fab --- /dev/null +++ b/site/udo/twist/transforms/spectral.udo @@ -0,0 +1,642 @@ +#include "/twist/transform_api.udo" +#include "/pvs_tabproc.udo" +#include "/spectral_transforms.udo" +#include "/fx_autoglitch.udo" +#include "/host_platform.udo" +#include "/addsub.udo" + +instr twst_tf_tpvinvert + $TWST_TRANSFORM + setksmps(64) + fL, fR, aL, aR, ileft, iright twst_getfinput + kinvertamp = twst_param:k("invertamp") + kinvertfreq = twst_param:k("invertfreq") + + if (ileft == 1) then + kreadyL, itpvdataL tpv_anal fL + tpv_invert kreadyL, itpvdataL, kinvertamp, kinvertfreq + fL tpv_resynth itpvdataL, fL + aL twst_tf_fresynth fL + endif + if (iright == 1) then + kreadyR, itpvdataR tpv_anal fR + tpv_invert kreadyR, itpvdataR, kinvertamp, kinvertfreq + fR tpv_resynth itpvdataR, fR + aR twst_tf_fresynth fR + endif + outs aL, aR +endin + + +instr twst_tf_tpvbubble + $TWST_TRANSFORM + setksmps(64) + fL, fR, aL, aR, ileft, iright twst_getfinput + kchance = twst_param:k("chance") + kstereounique = twst_param:k("stereounique") + + if (ileft == 1) then + kreadyL, itpvdataL tpv_anal fL + tpv_bubble kreadyL, itpvdataL, kchance, kstereounique + fL tpv_resynth itpvdataL, fL + aL twst_tf_fresynth fL + endif + if (iright == 1) then + kreadyR, itpvdataR tpv_anal fR + tpv_bubble kreadyR, itpvdataR, kchance, kstereounique + fR tpv_resynth itpvdataR, fR + aR twst_tf_fresynth fR + endif + outs aL, aR +endin + +instr twst_tf_tpvsmear + $TWST_TRANSFORM + setksmps(64) + fL, fR, aL, aR, ileft, iright twst_getfinput + imaxframes = twst_parami("maxframes") + kframes = twst_param:k("frames") + kavgfreqs = twst_param:k("avgfreqs") + kincludeoriginal = twst_param:k("includeoriginal") + + if (ileft == 1) then + kreadyL, itpvdataL tpv_anal fL + tpv_smear kreadyL, itpvdataL, imaxframes, kframes, kavgfreqs, kincludeoriginal + fL tpv_resynth itpvdataL, fL + aL twst_tf_fresynth fL + endif + if (iright == 1) then + kreadyR, itpvdataR tpv_anal fR + tpv_smear kreadyR, itpvdataR, imaxframes, kframes, kavgfreqs, kincludeoriginal + fR tpv_resynth itpvdataR, fR + aR twst_tf_fresynth fR + endif + outs aL, aR +endin + + +instr twst_tf_tpvscramble + $TWST_TRANSFORM + setksmps(64) + fL, fR, aL, aR, ileft, iright twst_getfinput + kstep = twst_param:k("step") + kdoamp = twst_param:k("scrambleamp") + kdofreq = twst_param:k("scramblefreq") + + if (ileft == 1) then + kreadyL, itpvdataL tpv_anal fL + tpv_scramble kreadyL, itpvdataL, kstep, kdoamp, kdofreq + fL tpv_resynth itpvdataL, fL + aL twst_tf_fresynth fL + endif + if (iright == 1) then + kreadyR, itpvdataR tpv_anal fR + tpv_scramble kreadyR, itpvdataR, kstep, kdoamp, kdofreq + fR tpv_resynth itpvdataR, fR + aR twst_tf_fresynth fR + endif + outs aL, aR +endin + +instr twst_tf_tpvthreshold + $TWST_TRANSFORM + setksmps(64) + fL, fR, aL, aR, ileft, iright twst_getfinput + kthreshold = twst_param:k("threshold") + kdirection = twst_param:k("direction") + + if (ileft == 1) then + kreadyL, itpvdataL tpv_anal fL + tpv_threshold kreadyL, itpvdataL, kthreshold, kdirection + fL tpv_resynth itpvdataL, fL + aL twst_tf_fresynth fL + endif + if (iright == 1) then + kreadyR, itpvdataR tpv_anal fR + tpv_threshold kreadyR, itpvdataR, kthreshold, kdirection + fR tpv_resynth itpvdataR, fR + aR twst_tf_fresynth fR + endif + outs aL, aR +endin + +instr twst_tf_tpvfreeze + $TWST_TRANSFORM + setksmps(64) + fL, fR, aL, aR, ileft, iright twst_getfinput + kfreeze = twst_param:k("freeze") + kfreezeamp = twst_param:k("freezeamp") + kfreezefreq = twst_param:k("freezefreq") + kcrossfade = twst_param:k("crossfade") + + if (ileft == 1) then + kreadyL, itpvdataL tpv_anal fL + tpv_freeze1 kreadyL, itpvdataL, kfreeze, kfreezeamp, kfreezefreq, kcrossfade + fL tpv_resynth itpvdataL, fL + aL twst_tf_fresynth fL + endif + if (iright == 1) then + kreadyR, itpvdataR tpv_anal fR + tpv_freeze1 kreadyR, itpvdataR, kfreeze, kfreezeamp, kfreezefreq, kcrossfade + fR tpv_resynth itpvdataR, fR + aR twst_tf_fresynth fR + endif + outs aL, aR +endin + +instr twst_tf_tpvwrap + $TWST_TRANSFORM + setksmps(64) + fL, fR, aL, aR, ileft, iright twst_getfinput + kwrapampbin = twst_param:k("wrapampbin") + kwrapfreqbin = twst_param:k("wrapfreqbin") + + if (ileft == 1) then + i_, inumbins, i_, i_ pvsinfo fL + kreadyL, itpvdataL tpv_anal fL + tpv_wrap kreadyL, itpvdataL, kwrapampbin * inumbins, kwrapfreqbin * inumbins + fL tpv_resynth itpvdataL, fL + aL twst_tf_fresynth fL + endif + if (iright == 1) then + i_, inumbins, i_, i_ pvsinfo fR + kreadyR, itpvdataR tpv_anal fR + tpv_wrap kreadyR, itpvdataR, kwrapampbin * inumbins, kwrapfreqbin * inumbins + fR tpv_resynth itpvdataR, fR + aR twst_tf_fresynth fR + endif + outs aL, aR +endin + +instr twst_tf_tpvswap + $TWST_TRANSFORM + setksmps(64) + fL, fR, aL, aR, ileft, iright twst_getfinput + kampStart = twst_param:k("ampstart") + kampLength = twst_param:k("amplength") + kampTarget = twst_param:k("amptarget") + kfreqStart = twst_param:k("freqstart") + kfreqLength = twst_param:k("freqlength") + kfreqTarget = twst_param:k("freqtarget") + kwrapmode = twst_param:k("wrapmode") + + if (ileft == 1) then + i_, inumbins, i_, i_ pvsinfo fL + kreadyL, itpvdataL tpv_anal fL + tpv_swap kreadyL, itpvdataL, kampStart * inumbins, kampLength * inumbins, kampTarget * inumbins, kfreqStart * inumbins, kfreqLength * inumbins, kfreqTarget * inumbins, kwrapmode + fL tpv_resynth itpvdataL, fL + aL twst_tf_fresynth fL + endif + if (iright == 1) then + i_, inumbins, i_, i_ pvsinfo fR + kreadyR, itpvdataR tpv_anal fR + tpv_swap kreadyR, itpvdataR, kampStart * inumbins, kampLength * inumbins, kampTarget * inumbins, kfreqStart * inumbins, kfreqLength * inumbins, kfreqTarget * inumbins, kwrapmode + fR tpv_resynth itpvdataR, fR + aR twst_tf_fresynth fR + endif + outs aL, aR +endin + +instr twst_tf_tpvaverage + $TWST_TRANSFORM + setksmps(64) + fL, fR, aL, aR, ileft, iright twst_getfinput + kmax = twst_param:k("maxframes") + kavgamp = twst_param:k("avgamp") + kavgfreq = twst_param:k("avgfreq") + krate = twst_param:k("rate") + + ktrig metro krate + + if (ileft == 1) then + kreadyL, itpvdataL tpv_anal fL + tpv_average kreadyL, itpvdataL, kmax, kavgamp, kavgfreq, ktrig + fL tpv_resynth itpvdataL, fL + aL twst_tf_fresynth fL + endif + if (iright == 1) then + kreadyR, itpvdataR tpv_anal fR + tpv_average kreadyR, itpvdataR, kmax, kavgamp, kavgfreq, ktrig + fR tpv_resynth itpvdataR, fR + aR twst_tf_fresynth fR + endif + outs aL, aR +endin + + +/* +instr twst_tf_stencil + $TWST_TRANSFORM + Spvx = strcat(host_tempdir(), "twist_stencil.pvx") + ifftsize = twst_parami("fftsize") + kran init 0 + ktimek timeinstk + if (ktimek == 1) then + ifnL, ifnR, istart, ilen, ileft, iright twst_getcrossdata + ikcycles = round(ilen / kr) + kcount = 1 + while (kcount < ikcycles) do + aLo, aRo, ileft, iright twst_getcrossinput + if (ileft == 1 && iright == 1) then + ain = (aLo + aRo) * 0.5 + elseif (ileft == 1) then + ain = aLo + elseif (iright == 1) then + ain = aRo + endif + f1 pvsanal ain, ifftsize, ifftsize/4, ifftsize, 1 + pvsfwrite f1, Spvx + kcount += 1 + od + + elseif (ktimek == 1) then + schedulek("_twst_tf_stencilplayback", 0, p3, p4, Spvx) ; TODO : won't work offline + endif + + aL, aR bus_read "stencilplayback" + kreleasing init 0 + if (kreleasing == 0 && release:k() == 1) then + turnoff2 "_twst_tf_stencilplayback", 0, 1 + kreleasing = 1 + endif + + outs aL, aR +endin + +instr _twst_tf_stencilplayback + $TWST_TRANSFORM + Spvx = strget(p5) + fL, fR, aL, aR, ileft, iright twst_getfinput + ifftsize = twst_parami("fftsize") + kgain = twst_param:k("gain") + klevel = twst_param:k("level") + + ifn ftgentmp 0, 0, (ifftsize * 2) + 1, 43, Spvx, 1 + + if (ileft == 1) then + fpsL pvstencil fL, kgain, klevel, ifn + aL twst_tf_fresynth fpsL + endif + if (iright == 1) then + fpsR pvstencil fR, kgain, klevel, ifn + aR twst_tf_fresynth fpsR + endif + bus_mix("stencilplayback", aL, aR) +endin +*/ + +instr twst_tf_spectralshift + $TWST_TRANSFORM + fL, fR, aL, aR, ileft, iright twst_getfinput + kfreqincr = twst_param:k("freqincr") + kporttime = twst_param:k("porttime") + kfreqscale = twst_tf_pitchscale() + istart = twst_parami("start") + iend = twst_parami("end") + ifn = twst_tf_getwaveform() + + if (ileft == 1) then + aL spc_shift fL, kfreqincr, istart, iend, kfreqscale, kporttime, ifn + endif + if (iright == 1) then + aR spc_shift fR, kfreqincr, istart, iend, kfreqscale, kporttime, ifn + endif + outs aL, aR +endin + +instr twst_tf_spectraldelay + $TWST_TRANSFORM + fL, fR, aL, aR, ileft, iright twst_getfinput + kdeltime = twst_param:k("time") + kdeladd = twst_param:k("add") + kporttime = twst_param:k("porttime") + kfreqscale = twst_tf_pitchscale() + istart = twst_parami("start") + iend = twst_parami("end") + ifn = twst_tf_getwaveform() + + if (ileft == 1) then + aL spc_delay fL, kdeltime, kdeladd, istart, iend, kfreqscale, kporttime, ifn + endif + if (iright == 1) then + aR spc_delay fR, kdeltime, kdeladd, istart, iend, kfreqscale, kporttime, ifn + endif + outs aL, aR +endin + +instr twst_tf_spectralgate + $TWST_TRANSFORM + fL, fR, aL, aR, ileft, iright twst_getfinput + kthresh = twst_param:k("threshold") + khold = twst_param:k("hold") + kporttime = twst_param:k("porttime") + kfreqscale = twst_tf_pitchscale() + istart = twst_parami("start") + iend = twst_parami("end") + ifn = twst_tf_getwaveform() + + if (ileft == 1) then + aL spc_gate fL, kthresh, khold, istart, iend, kfreqscale, kporttime, ifn + endif + if (iright == 1) then + aR spc_gate fR, kthresh, khold, istart, iend, kfreqscale, kporttime, ifn + endif + outs aL, aR +endin + +instr twst_tfi_spectralgrain1 + $TWST_TRANSFORM + ileft, iright, istartsamp, iendsamp, idocut, ilength twst_tf_getstate + ifnL, ifnR twst_tfi_getfn + + ireadmode = twst_parami("readmode") + if (ireadmode == 0) then + ktime linseg 0, p3, ilength + elseif (ireadmode == 1) then + ktime = twst_param:k("readtime") + twst_tf_setplayposition ktime + ktime *= ilength + elseif (ireadmode == 2) then + itimescale = twst_parami("timescale") + p3 = ilength * itimescale + ktime linseg 0, p3, ilength + elseif (ireadmode == 3) then + ktime linseg ilength, p3, 0 + endif + + kgraindur = twst_param:k("graindur") + ifftsize = twst_parami("fftsize") + ilayers = twst_parami("layers") + kporttime = twst_param:k("porttime") + kfreqscale = twst_tf_pitchscale() + kfreqrand = twst_param:k("freqrand") + kdurrand = twst_param:k("durrand") + kpitchrand = twst_param:k("pitchrand") + istart = twst_parami("start") + iend = twst_parami("end") + ifn = twst_tf_getwaveform() + twst_setlatencysamples(ifftsize) + + if (ileft == 1) then + aL spc_grain1 ifnL, ktime, kgraindur, ifftsize, ilayers, istart, iend, kfreqscale, kfreqrand, kdurrand, kpitchrand, kporttime, ifn + endif + if (iright == 1) then + aR spc_grain1 ifnR, ktime, kgraindur, ifftsize, ilayers, istart, iend, kfreqscale, kfreqrand, kdurrand, kpitchrand, kporttime, ifn + endif + outs aL, aR +endin + +instr twst_tf_spectralread + $TWST_TRANSFORM + ileft, iright, istartsamp, iendsamp, idocut, ilength twst_tf_getstate + ifftsize = twst_parami("fftsize") + ktime = twst_param:k("readtime") * ilength + twst_tf_setplayposition ktime + twst_setlatencysamples(ifftsize) + + ktimek timeinstk + ilensamps = iendsamp - istartsamp + ikcycles = ilength * kr + kcount init 0 + if (ktimek == 1) then + while (kcount < ikcycles) do + apos linseg 0, ilength, iendsamp + if (ileft == 1 && iright == 1) then + aL table3 apos, gitwst_bufferL[gitwst_instanceindex] + aR table3 apos, gitwst_bufferR[gitwst_instanceindex] + asig = (aL + aR) * 0.5 + elseif (ileft == 1) then + asig table3 apos, gitwst_bufferL[gitwst_instanceindex] + elseif (iright == 1) then + asig table3 apos, gitwst_bufferR[gitwst_instanceindex] + endif + fsig pvsanal asig, ifftsize, ifftsize/4, ifftsize, 1 + ipbuf, k_ pvsbuffer fsig, ilength + kcount += 1 + od + else + if (ileft == 1) then + fL pvsbufread ktime, ipbuf + aL twst_tf_fresynth fL + endif + if (iright == 1) then + fR pvsbufread ktime, ipbuf + aR twst_tf_fresynth fR + endif + endif + outs aL, aR +endin + +instr twst_tf_centroidoscillator + $TWST_TRANSFORM + fL, fR, aL, aR, ileft, iright twst_getfinput + kporttime = twst_param:k("porttime") + kfreqscale = twst_tf_pitchscale() + kfn twst_tf_getwaveformk + + if (ileft == 1) then + kcent pvscent fL + kfreq portk kcent * kfreqscale, kporttime + aL oscilikt 1, kfreq, kfn + endif + if (iright == 1) then + kcent pvscent fR + kfreq portk kcent * kfreqscale, kporttime + aR oscilikt 1, kfreq, kfn + endif + outs aL, aR +endin + +instr twst_tf_binoscillator + $TWST_TRANSFORM + fL, fR, aL, aR, ileft, iright twst_getfinput + kporttime = twst_param:k("porttime") + kbin = twst_param:k("bin") + kfreqscale = twst_tf_pitchscale() + kfn twst_tf_getwaveformk + + if (ileft == 1) then + i_, inumbins, i_, i_ pvsinfo fL + kamp, kfreqbase pvsbin fL, round:k(kbin * inumbins) + kfreq portk kfreqbase * kfreqscale, kporttime + aL oscilikt 1, kfreq, kfn + endif + if (iright == 1) then + i_, inumbins, i_, i_ pvsinfo fR + kamp, kfreqbase pvsbin fL, round:k(kbin * inumbins) + kfreq portk kfreqbase * kfreqscale, kporttime + aR oscilikt 1, kfreq, kfn + endif + outs aL, aR +endin + +opcode _twst_tf_partialreconstruction, a, aikkkikkki + ain, ifftsize, kthresh, kminpoints, kmaxgap, imaxtracks, kampscale, kfreqscale, kmaxtracks, ifn xin + ffreq, fphase pvsifd ain, ifftsize, ifftsize/4, 1 + ftrks partials ffreq, fphase, kthresh, kminpoints, kmaxgap, imaxtracks + aout resyn ftrks, kampscale, kfreqscale, kmaxtracks, ifn + aout dcblock aout + xout aout +endop + +instr twst_tf_partialreconstruction + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + ifftsize = twst_parami("fftsize") + kthresh = twst_param:k("threshold") + kminpoints = twst_param:k("minpoints") + kmaxgap = twst_param:k("maxgap") + imaxtracks = round(twst_parami("anlmaxtracks") * ifftsize * 0.5) + kampscale = twst_param:k("ampscale") + kfreqscale = twst_tf_pitchscale() + kmaxtracks = round:k(twst_param:k("resmaxtracks") * ifftsize * 0.5) + ifn = twst_tf_getwaveform() + twst_setlatencysamples(ifftsize) + + if (ileft == 1) then + aL _twst_tf_partialreconstruction aL, ifftsize, kthresh, kminpoints, kmaxgap, imaxtracks, kampscale, kfreqscale, kmaxtracks, ifn + endif + if (iright == 1) then + aR _twst_tf_partialreconstruction aR, ifftsize, kthresh, kminpoints, kmaxgap, imaxtracks, kampscale, kfreqscale, kmaxtracks, ifn + endif + outs aL, aR +endin + +opcode _twst_tf_residual, a, aii + ain, ifftsize, ihsize xin + ffr, fphs pvsifd ain, ifftsize, ihsize, 1 + ftrk partials ffr, fphs, 0, 1, 3, 500 + aout sinsyn ftrk, 2, 500, gifnSine + asd delayr ifftsize / sr + asig deltapn ifftsize - ihsize + delayw ain + xout asig - aout +endop + +instr twst_tf_residual + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + ifftsize = twst_parami("fftsize") + twst_setlatencysamples(ifftsize) + ihsize = ifftsize / 4 + if (ileft == 1) then + aL _twst_tf_residual aL, ifftsize, ihsize + endif + if (iright == 1) then + aR _twst_tf_residual aR, ifftsize, ihsize + endif + outs aL, aR +endin + +/* not in WASM +instr twst_tf_trace + $TWST_TRANSFORM + fL, fR, aL, aR, ileft, iright twst_getfinput + inumbins = twst_parami("fftsize") / 2 + kbins = twst_param("bins") * inumbins + + if (ileft == 1) then + foutL pvstrace fL, kbins + aL twst_tf_fresynth foutL + endif + if (iright == 1) then + foutR pvstrace fR, kbins + aR twst_tf_fresynth foutR + endif + outs aL, aR +endin +*/ + +instr twst_tf_isolator + $TWST_TRANSFORM + fL, fR, aL, aR, ileft, iright twst_getfinput + kbin = twst_param("bin") + kattenuation = twst_param("attenuation") + kgain = twst_param("accentuation") + + if (ileft == 1) then + foutL pvsarp fL, kbin, kattenuation, kgain + aL twst_tf_fresynth foutL + endif + if (iright == 1) then + foutR pvsarp fR, kbin, kattenuation, kgain + aR twst_tf_fresynth foutR + endif + outs aL, aR +endin + +instr twst_tf_blur + $TWST_TRANSFORM + fL, fR, aL, aR, ileft, iright twst_getfinput + ktime = twst_param:k("time") + if (ileft == 1) then + fL1 pvsblur fL, ktime, 3 + aL twst_tf_fresynth fL1 + endif + if (iright == 1) then + fR1 pvsblur fR, ktime, 3 + aR twst_tf_fresynth fR1 + endif + outs aL, aR +endin + +instr twst_tf_spectralautoglitch + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kchangerate = twst_param:k("changerate") + kchangechance = twst_param:k("changechance") + kporttime = twst_param:k("porttime") + kdo_pitchalter = twst_param:k("pitchalter") + ifftsize = twst_parami("fftsize") + + twst_setlatencysamples ifftsize + + if (ileft == 1) then + aL fx_spectralautoglitch aL, kchangerate, kchangechance, kdo_pitchalter, kporttime, ifftsize + endif + if (iright == 1) then + aR fx_spectralautoglitch aR, kchangerate, kchangechance, kdo_pitchalter, kporttime, ifftsize + endif + outs aL, aR +endin + +instr twst_tf_subtractive + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + ifreq = twst_parami("minfreq") + ifreqmax = twst_parami("maxfreq") + ifreqstepmult = twst_parami("step") + ifreqstepmultrand = twst_parami("steprand") + iamp = twst_parami("amp") + iampmult = twst_parami("ampmult") + + if (ileft == 1) then + aL as_subtractive aL, ifreq, ifreqmax, ifreqstepmult, ifreqstepmultrand, iamp, iampmult + endif + if (iright == 1) then + aR as_subtractive aR, ifreq, ifreqmax, ifreqstepmult, ifreqstepmultrand, iamp, iampmult + endif + outs aL, aR +endin + +instr twst_tf_phasemash + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + ifftsize = twst_parami("fftsize") + kphasemode = twst_param:k("phasereplace") + kphasevalue = twst_param:k("phasevalue") + + if (kphasemode == 0) then + kphasevalue *= 7 + else + kphasevalue = ((kphasevalue * 2) - 1) * 3.141 + endif + + if (ileft == 1) then + aL spc_phasemash aL, kphasemode, kphasevalue, ifftsize + endif + if (iright == 1) then + aR spc_phasemash aR, kphasemode, kphasevalue, ifftsize + endif + outs aL, aR +endin diff --git a/site/udo/twist/transforms/warping.udo b/site/udo/twist/transforms/warping.udo new file mode 100755 index 0000000..3eb4e6e --- /dev/null +++ b/site/udo/twist/transforms/warping.udo @@ -0,0 +1,210 @@ +#include "/twist/transform_api.udo" +#include "/sample_level.udo" + +instr twst_tf_smphold + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kratio = twst_param:k("ratio") + if (ileft == 1) then + aL smp_hold aL, kratio + endif + if (iright == 1) then + aR smp_hold aR, kratio + endif + outs aL, aR +endin + +instr twst_tf_fftpitchscale + $TWST_TRANSFORM + fL, fR, aL, aR, ileft, iright twst_getfinput + kscale = twst_tf_pitchscale() + kformant = twst_param:k("formants") + kcoefs = twst_param:k("formantcoefs") + + if (ileft == 1) then + fL1 pvscale fL, kscale, kformant, 1, kcoefs + aL twst_tf_fresynth fL1 + endif + if (iright == 1) then + fR1 pvscale fR, kscale, kformant, 1, kcoefs + aR twst_tf_fresynth fR1 + endif + outs aL, aR +endin + +opcode _twst_tf_autotune, f, fkkk + fsig, kthreshold, kformant, kcoefs xin + kfreq, kamp pvspitch fsig, kthreshold + if (kfreq > 20) then + knote ftom kfreq + kscale = cpsmidinn:k(int:k(knote)) / kfreq + fsigo pvscale fsig, kscale, kformant, 1, kcoefs + else + fsigo = fsig + endif + xout fsigo +endop + + +instr twst_tf_autotune + $TWST_TRANSFORM + fL, fR, aL, aR, ileft, iright twst_getfinput + kthreshold = twst_param:k("threshold") + kformant = twst_param:k("formants") + kcoefs = twst_param:k("formantcoefs") + + if (ileft == 1) then + fL1 _twst_tf_autotune fL, kthreshold, kformant, kcoefs + aL twst_tf_fresynth fL1 + endif + if (iright == 1) then + fR1 _twst_tf_autotune fR, kthreshold, kformant, kcoefs + aR twst_tf_fresynth fR1 + endif + outs aL, aR +endin + + +instr twst_tf_hilbertpitchscale + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + ifftsize = twst_parami("fftsize") + kscale = twst_tf_pitchscale() + twst_setlatencysamples(ifftsize) + + if (ileft == 1) then + ahL1, ahL2 hilbert2 aL, ifftsize, ifftsize / 4 + amL, afmL fmanal ahL1, ahL2 + aL oscil amL, afmL * kscale + endif + if (iright == 1) then + ahR1, ahR2 hilbert2 aR, ifftsize, ifftsize / 4 + amR, afmR fmanal ahR1, ahR2 + aR oscil amR, afmR * kscale + endif + outs aL, aR +endin + +instr twst_tf_waveset + $TWST_TRANSFORM + aL, aR, ileft, iright twst_getinput + kreps = twst_param:k("reps") + if (ileft == 1) then + aL waveset aL, kreps + endif + if (iright == 1) then + aR waveset aR, kreps + endif + outs aL, aR +endin + +instr twst_tf_freeze + $TWST_TRANSFORM + fL, fR, aL, aR, ileft, iright twst_getfinput + kfreezeamp = twst_param:k("freezeamp") + kfreezefreq = twst_param:k("freezefreq") + if (ileft == 1) then + fL1 pvsfreeze fL, kfreezeamp, kfreezefreq + aL twst_tf_fresynth fL1 + endif + if (iright == 1) then + fR1 pvsfreeze fR, kfreezeamp, kfreezefreq + aR twst_tf_fresynth fR1 + endif + outs aL, aR +endin + +instr twst_tfi_sndwarp + $TWST_TRANSFORM + ileft, iright, istartsamp, iendsamp, idocut, ilength twst_tf_getstate + ireadmode = twst_parami("readmode") + kpitchscale = twst_tf_pitchscale() + iwinsize = twst_parami("winsize") + irandwin = twst_parami("randwin") + ioverlap = twst_parami("overlap") + ifnWindow = twst_tf_getwintype() + + p3 = ilength + if (ireadmode == 0) then + atime linseg 0, p3, ilength + elseif (ireadmode == 1) then + ktime = twst_param:k("readtime") + twst_tf_setplayposition ktime + atime = a(ktime * ilength) + elseif (ireadmode == 2) then + itimescale = twst_parami("timescale") + p3 = ilength * itimescale + atime linseg 0, p3, ilength + elseif (ireadmode == 3) then + atime linseg ilength, p3, 0 + endif + + ifnL, ifnR twst_tfi_getfn + + kpitchscale *= ftsr(ifnL) / sr + apitchscale = a(kpitchscale) + if (ileft == 1) then + aL sndwarp 1, atime, apitchscale, ifnL, 0, iwinsize, irandwin, ioverlap, ifnWindow, 1 + endif + if (iright == 1) then + aR sndwarp 1, atime, apitchscale, ifnR, 0, iwinsize, irandwin, ioverlap, ifnWindow, 1 + endif + outs aL, aR +endin + +instr twst_tfi_mincer + $TWST_TRANSFORM + ileft, iright, istartsamp, iendsamp, idocut, ilength twst_tf_getstate + ifftsize = twst_parami("fftsize") + kpitchscale = twst_tf_pitchscale() + klock = twst_param:k("phaselock") + ireadmode = twst_parami("readmode") + idecimation = twst_parami("decimation") + + p3 = ilength + if (ireadmode == 0) then + atime linseg 0, p3, ilength + elseif (ireadmode == 1) then + ktime = twst_param:k("readtime") + twst_tf_setplayposition ktime + atime = a(ktime * ilength) + elseif (ireadmode == 2) then + itimescale = twst_parami("timescale") + p3 = ilength * itimescale + atime linseg 0, p3, ilength + elseif (ireadmode == 3) then + atime linseg ilength, p3, 0 + endif + + twst_setlatencysamples(ifftsize) + ifnL, ifnR twst_tfi_getfn + if (ileft == 1) then + aL mincer atime, 1, kpitchscale, ifnL, klock, ifftsize, idecimation + endif + if (iright == 1) then + aR mincer atime, 1, kpitchscale, ifnR, klock, ifftsize, idecimation + endif + outs aL, aR +endin + +instr twst_tfi_paulstretch + $TWST_TRANSFORM + ileft, iright, istartsamp, iendsamp, idocut, ilength twst_tf_getstate + + istretch = twst_parami("stretch") + iwinsize = twst_parami("winsize") + iduration = ilength * istretch + p3 = iduration + + twst_setlatencyseconds iwinsize + + ifnL, ifnR twst_tfi_getfn + + if (ileft == 1) then + aL paulstretch istretch, iwinsize, ifnL + endif + if (iright == 1) then + aR paulstretch istretch, iwinsize, ifnR + endif + outs aL, aR +endin 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 -- cgit v1.2.3