diff options
author | Richard <q@1bpm.net> | 2025-04-13 18:48:02 +0100 |
---|---|---|
committer | Richard <q@1bpm.net> | 2025-04-13 18:48:02 +0100 |
commit | 9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22 (patch) | |
tree | 291bd79ce340e67affa755a8a6b4f6a83cce93ea /site/app/twist/developer_documentation.html | |
download | apps.csound.1bpm.net-9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22.tar.gz apps.csound.1bpm.net-9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22.tar.bz2 apps.csound.1bpm.net-9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22.zip |
initial
Diffstat (limited to 'site/app/twist/developer_documentation.html')
-rw-r--r-- | site/app/twist/developer_documentation.html | 742 |
1 files changed, 742 insertions, 0 deletions
diff --git a/site/app/twist/developer_documentation.html b/site/app/twist/developer_documentation.html new file mode 100644 index 0000000..f44f778 --- /dev/null +++ b/site/app/twist/developer_documentation.html @@ -0,0 +1,742 @@ +<html>
+<head>
+ <script type="text/javascript" src="https://apps.csound.1bpm.net/code/jquery.js"></script>
+ <style type="text/css">
+ body {
+ font-family: Arial, sans-serif;
+ }
+
+ table {
+ border-collapse: collapse;
+ }
+
+ td {
+ border: 1px solid black;
+ }
+
+ pre {
+ font-family: Monospace, Courier, sans-serif;
+ background-color: #ccffff;
+ }
+
+ #container_overview {
+ background-color: #ddddff;
+ }
+
+ #container_json {
+ background-color: #ddffdd;
+ }
+
+ #container_csound {
+ background-color: #ddffff;
+ }
+
+ #container_examples {
+ background-color: #ffffdd;
+ }
+
+ </style>
+ <script type="text/javascript">
+ var documentation = {};
+ documentation.opcodes = [
+ {
+ name: "twst_param",
+ ins: [
+ ["Sname", "Name of the parameter to obtain"]
+ ],
+ outs: [
+ ["kvalue", "Value of the parameter"]
+ ],
+ description: "Obtain a parameter at k-rate. The name should correspond to the {json(channel)} in the definition for the given transform",
+ exampleJson: {
+ name: "Oscillator",
+ instr: "twst_tf_example_osc",
+ parameters: [
+ {name: "Frequency", min: 20, max: 8000, dfault: 440}
+ ]
+ },
+ exampleCsound: 'aL, aR, ileft, iright twst_getinput\nkfreq twst_param "frequency"\nif (ileft == 1) then\n\t aL oscil 1, kfreq\nendif\nif (iright == 1) then\n\taR oscil 1, kfreq\nendif\nouts aL, aR'
+ },
+ {
+ name: "twst_parami",
+ ins: [
+ ["Sname", "Name of the parameter to obtain"]
+ ],
+ outs: [
+ ["ivalue", "Value of the parameter"]
+ ],
+ description: "Obtain a parameter at init time. The name should correspond to the {json(channel)} in the definition for the given transform",
+ exampleJson: {
+ name: "Oscillator",
+ instr: "twst_tf_example_osc",
+ parameters: [
+ {name: "Frequency", min: 20, max: 8000, dfault: 440}
+ ]
+ },
+ exampleCsound: 'ifreq twst_parami "frequency"\naout oscil 1, ifreq\nouts aout, aout'
+ },
+ {
+ name: "twst_tf_isoffline",
+ outs: [
+ ["ioffline", "Whether processing is offline"]
+ ],
+ description: "Get a boolean signifying whether the current operation is a commit (1) or audition (0)",
+ exampleJson: {
+ name: "Reverse",
+ instr: "twst_tfi_example_reverse",
+ parameters: []
+ },
+ exampleCsound: 'ileft, iright, istartsamp, iendsamp, idocut, ilength twst_tf_getstate\nifnL, ifnR twst_tfi_getfn\nioffline twst_tf_isoffline\napos linseg (iendsamp - istartsamp) - 1, ilength, 0\nif (ileft == 1) then\n\tif (ioffline == 1) then\n\t\tifntempL ftgentmp 0, 0, -ftlen(ifnL), -2, 0\n\t\ttableicopy ifntempL, ifnL\n\t\taL table3 apos, ifntempL\n\telse\n\t\taL table3 apos, ifnL\n\tendif\nendif\nif (iright == 1) then\n\tif (ioffline == 1) then\n\t\tifntempR ftgentmp 0, 0, -ftlen(ifnR), -2, 0\n\t\ttableicopy ifntempR, ifnR\n\t\taR table3 apos, ifntempR\n\telse\n\t\taR table3 apos, ifnR\n\tendif\nendif\nouts aL, aR'
+ },
+ {
+ name: "twst_getinput",
+ outs: [
+ ["aL", "Left channel"],
+ ["aR", "Right channel"],
+ ["ileft", "Whether the left channel is to be processed"],
+ ["iright", "Whether the right channel is to be processed"]
+ ],
+ description: "Get input audio and channel flags for the current transform process. The transform should utilise ileft and iright, which are set to either 0 or 1, to process the inputs accordingly. If the instrument does not process audio (ie, generates new audio), then this opcode can still be used to obtain ileft and iright. This can also be obtained from {csound(twst_tf_getstate)}",
+ exampleJson: {
+ name: "Gain",
+ instr: "twst_tf_example_gain",
+ parameters: [
+ {name: "Gain"}
+ ]
+ },
+ exampleCsound: 'aL, aR, ileft, iright twst_getinput\nkgain twst_param "gain"\nif (ileft == 1) then\n\taL *= kgain\nendif\nif (iright == 1) then\n\taR *= kgain\nendif\nouts aL, aR'
+ },
+ {
+ name: "twst_getfinput",
+ ins: [
+ ["fftsize", "FFT size", "{preset(fftsize)}"]
+ ],
+ outs: [
+ ["fL", "Left channel"],
+ ["fR", "Right channel"],
+ ["aL", "Left channel"],
+ ["aR", "Right channel"],
+ ["ileft", "Whether the left channel is to be processed"],
+ ["iright", "Whether the right channel is to be processed"]
+ ],
+ description: "Get input audio as a PVS stream along with channel flags for the current transform process. The transform should utilise ileft and iright, which are set to either 0 or 1, to process the inputs accordingly. FFT size is optional and obtains the value from {preset(fftsize)} if not specified. Frequency/phase lock is also applied according to the parameter in the preset group {presetgroup(pvsynth)}",
+ exampleJson: {
+ name: "Repitcher",
+ instr: "twst_tf_example_pvscale",
+ parameters: [
+ {name: "Pitch scaling", channel: "scale", min: 0.5, max: 2, dfault: 1},
+ {presetgroup: "pvanal"},
+ {presetgroup: "pvsynth"}
+ ]
+ },
+ exampleCsound: 'fL, fR, aL, aR, ileft, iright twst_getfinput\nkscale twst_param "scale"\nif (ileft == 1) then\n\tfoutL pvscale fL, kscale\n\taL twst_tf_fresynth foutL\nendif\nif (iright == 1) then\n\tfoutL pvscale fL, kscale\n\taR twst_tf_fresynth foutR\nendif\nouts aL, aR'
+ },
+ {
+ name: "twst_tf_fresynth",
+ ins: [
+ ["fsig", "Input PVS stream"]
+ ],
+ outs: [
+ ["aout", "Resynthesised audio"]
+ ],
+ description: "Resynthesise the PVS stream provided using the values of parameter preset group {presetgroup(pvsynth)}",
+ exampleJson: {
+ name: "Repitcher",
+ instr: "twst_tf_example_pvscale",
+ parameters: [
+ {name: "Pitch scaling", channel: "scale", min: 0.5, max: 2, dfault: 1},
+ {presetgroup: "pvanal"},
+ {presetgroup: "pvsynth"},
+ {preset: "applymode"}
+ ]
+ },
+ exampleCsound: 'fL, fR, aL, aR, ileft, iright twst_getfinput\nkscale twst_param "scale"\nif (ileft == 1) then\n\tfoutL pvscale fL, kscale\n\taL twst_tf_fresynth foutL\nendif\nif (iright == 1) then\n\tfoutL pvscale fL, kscale\n\taR twst_tf_fresynth foutR\nendif\nouts aL, aR'
+ },
+ {
+ name: "twst_tf_pitchscale",
+ outs: [
+ ["kpitchscale", "Pitch scaling ratio (1 = normal; 2 = one octave above)"]
+ ],
+ description: "Obtain the pitch scaling value from the parameter preset group {presetgroup(pitchscale)}",
+ exampleJson: {
+ name: "Repitcher",
+ instr: "twst_tf_example_pvscale",
+ parameters: [
+ {presetgroup: "pvanal"},
+ {presetgroup: "pvsynth"},
+ {presetgroup: "pitchscale"}
+ ]
+ },
+ exampleCsound: 'fL, fR, aL, aR, ileft, iright twst_getfinput\nkscale twst_tf_pitchscale\nif (ileft == 1) then\n\tfoutL pvscale fL, kscale\n\taL twst_tf_fresynth foutL\nendif\nif (iright == 1) then\n\tfoutL pvscale fL, kscale\n\taR twst_tf_fresynth foutR\nendif\nouts aL, aR'
+ },
+ {
+ name: "twst_tf_pitchscale_custom",
+ ins: [
+ ["SchanPrepend", "String to prepend the preset channel name with"]
+ ],
+ outs: [
+ ["kpitchscale", "Pitch scaling ratio (1 = normal; 2 = one octave above)"]
+ ],
+ description: "Obtain the pitch scaling value from the parameter preset group {presetgroup(pitchscale)} but with channel names prepended with the specified string, to be used with the {json(channelprepend)} attribute",
+ exampleJson: {
+ name: "Repitcher",
+ instr: "twst_tf_example_pvscale",
+ parameters: [
+ {presetgroup: "pvanal"},
+ {presetgroup: "pvsynth"},
+ {presetgroup: "pitchscale", channelprepend: "custom"}
+ ]
+ },
+ exampleCsound: 'fL, fR, aL, aR, ileft, iright twst_getfinput\nkscale twst_tf_pitchscale \"custom\"\nif (ileft == 1) then\n\tfoutL pvscale fL, kscale\n\taL twst_tf_fresynth foutL\nendif\nif (iright == 1) then\n\tfoutL pvscale fL, kscale\n\taR twst_tf_fresynth foutR\nendif\nouts aL, aR'
+ },
+ {
+ name: "twst_tf_freq",
+ outs: [
+ ["kfreq", "Frequency in Hz"]
+ ],
+ description: "Obtain the frequency value at k-rate from the parameter preset group {presetgroup(notefreq)}",
+ exampleJson: {
+ name: "Oscillator",
+ instr: "twst_tf_example_osc",
+ parameters: [
+ {presetgroup: "notefreq"}
+ ]
+ },
+ exampleCsound: 'kfreq twst_tf_freq\naout oscil 1, kfreq\nouts aout, aout'
+ },
+ {
+ name: "twst_tf_freqi",
+ outs: [
+ ["ifreq", "Frequency in Hz"]
+ ],
+ description: "Obtain the frequency value at init time from the parameter preset group {presetgroup(notefreq)}, which should also have the {json(automatable)} attribute set to false",
+ exampleJson: {
+ name: "Oscillator",
+ instr: "twst_tf_example_osc",
+ parameters: [
+ {presetgroup: "notefreq", automatable: false},
+ {preset: "applymode"}
+ ]
+ },
+ exampleCsound: 'ifreq twst_tf_freqi\naout oscil 1, ifreq\nouts aout, aout'
+ },
+ {
+ name: "twst_tf_freq_custom",
+ ins: [
+ ["SchanPrepend", "String to prepend the preset channel name with"]
+ ],
+ outs: [
+ ["kfreq", "Frequency in Hz"]
+ ],
+ description: "Obtain the frequency value at k-rate from the parameter preset group {presetgroup(notefreq)} but with channel names prepended with the specified string, to be used with the {json(channelprepend)} attribute",
+ exampleJson: {
+ name: "Oscillator",
+ instr: "twst_tf_example_osc",
+ parameters: [
+ {presetgroup: "notefreq", channelprepend: "custom"}
+ ]
+ },
+ exampleCsound: 'kfreq twst_tf_freq_custom "custom"\naout oscil 1, kfreq\nouts aout, aout'
+ },
+ {
+ name: "twst_tf_freqi_custom",
+ ins: [
+ ["SchanPrepend", "String to prepend the preset channel name with"]
+ ],
+ outs: [
+ ["ifreq", "Frequency in Hz"]
+ ],
+ description: "Obtain the frequency value at init time from the parameter preset group {presetgroup(notefreq)} but with channel names prepended with the specified string, to be used with the {json(channelprepend)} attribute",
+ exampleJson: {
+ name: "Oscillator",
+ instr: "twst_tf_example_osc",
+ parameters: [
+ {presetgroup: "notefreq", channelprepend: "custom", automatable: false}
+ ]
+ },
+ exampleCsound: 'ifreq twst_tf_freqi_custom "custom"\naout oscil 1, ifreq\nouts aout, aout'
+ },
+ {
+ name: "twst_tf_getwaveform",
+ ins: [
+ ["inumber", "Reference number of the wave", "{preset(wave)}"]
+ ],
+ outs: [
+ ["ifn", "f-table number"]
+ ],
+ description: "Obtain an f-table at init time from the parameter preset {preset(wave)}. This can be overridden with {p(inumber)}, a value which corresponds to the array of available waveforms which is [Sine, Saw, Pulse, Triangle]",
+ exampleJson: {
+ name: "Oscillator",
+ instr: "twst_tf_example_osc",
+ parameters: [
+ {preset: "wave", automatable: false}
+ ]
+ },
+ exampleCsound: 'ifn twst_tf_getwaveform\naout oscil 1, 440, ifn\outs aout, aout'
+ },
+ {
+ name: "twst_tf_getwaveformk",
+ ins: [
+ ["inumber", "Reference number of the wave", "{preset(wave)}"]
+ ],
+ outs: [
+ ["kfn", "f-table number"]
+ ],
+ description: "Obtain an f-table at k-rate from the parameter preset group {preset(wave)}. This can be overridden with inumber, a value which corresponds to the array of available waveforms which is [Sine, Saw, Pulse, Triangle]",
+ exampleJson: {
+ name: "Oscillator",
+ instr: "twst_tf_example_osc",
+ parameters: [
+ {preset: "wave"},
+ {preset: "applymode"}
+ ]
+ },
+ exampleCsound: 'kfn twst_tf_getwaveformk\naout oscilikt 1, 440, kfn\outs aout, aout'
+ },
+ {
+ name: "twst_tf_getwintype",
+ outs: [
+ ["ifn", "f-table number"]
+ ],
+ description: "Obtain an f-table at init time from the parameter preset group {preset(wintype)}. This may be Hanning, Hamming or Half sine as selected in the UI",
+ exampleJson: {
+ name: "Sndwarp",
+ instr: "twst_tfi_exsndwarp",
+ parameters: [
+ {name: "Time scale", channel: "timescale", min: 0.1, max: 10, dfault: 1, automatable: false},
+ {preset: "wintype", automatable: false}
+ ]
+ },
+ exampleCsound: 'ileft, iright, istartsamp, iendsamp, idocut, ilength twst_tf_getstate\nitimescale = twst_parami("timescale")\nifnWindow = twst_tf_getwintype()\np3 = ilength * itimescale\natime linseg 0, p3, ilength\nifnL, ifnR twst_tfi_getfn\nif (ileft == 1) then\n\taL sndwarp 1, atime, 1, ifnL, 0, 4410, 441, 4, ifnWindow, 1\nendif\nif (iright == 1) then\n\taR sndwarp 1, atime, apitchscale, ifnR, 0, 4410, 441, 4, ifnWindow, 1\nendif\nouts aL, aR'
+ },
+ {
+ name: "twst_tf_getwintypek",
+ outs: [
+ ["kfn", "f-table number"]
+ ],
+ description: "Obtain an f-table at k-rate from the parameter preset group {preset(wintype)}. This may be Hanning, Hamming or Half sine as selected in the UI",
+ exampleJson: {
+ name: "Wintype",
+ instr: "twst_tf_wintype",
+ parameters: [
+ {preset: "wintype"}
+ ]
+ },
+ exampleCsound: 'kfnWindow = twst_tf_getwintypek()\naout oscil 1, 440\naenv oscilikt 1, 10, kfnWindow\naout *= aenv\nouts aout, aout'
+ },
+ {
+ name: "twst_getcrossinput",
+ outs: [
+ ["aL", "Left channel from instance"],
+ ["aR", "Right channel from instance"],
+ ["ileft", "whether the left channel is selected"],
+ ["iright", "whether the right channel is selected"]
+ ],
+ description: "Obtain an audio stream from the file instance selected in a parameter preset {preset(instance)}. ileft and iright correspond to the selected channels, and the audio is played according to the parameter preset {preset(looptype)}",
+ exampleJson: {
+ name: "Multiplier",
+ instr: "twst_tf_multiplier",
+ inputs: 2,
+ parameters: [
+ {preset: "instance"},
+ {preset: "instanceloop"}
+ ]
+ },
+ exampleCsound: 'aL, aR, ileft, iright twst_getinput\naxL, axR, ixleft, ixright twst_getcrossinput\nif (ileft == 1 && ixleft == 1) then\n\taL *= axL\nendif\nif (iright == 1 && ixright == 1) then\n\taR *= axR\nendif\nouts aL, aR'
+ },
+ {
+ name: "twst_getfcrossinput",
+ outs: [
+ ["fL", "Left channel from instance"],
+ ["fR", "Right channel from instance"],
+ ["ileft", "whether the left channel is selected"],
+ ["iright", "whether the right channel is selected"]
+ ],
+ description: "Obtain a PVS stream from the file instance selected in a parameter preset {preset(instance)}. ileft and iright correspond to the selected channels, and the audio is played according to the parameter preset {preset(looptype)}. The FFT size is taken from {preset(fftsize)}",
+ exampleJson: {
+ name: "Morpher",
+ instr: "twst_tf_exmorph",
+ inputs: 2,
+ parameters: [
+ {preset: "instance", name: "Cross instance"},
+ {preset: "instanceloop"},
+ {name: "Amplitude amount", channel: "amp", description: "Amplitude interpolation", dfault: 1, min: 0, max: 1},
+ {name: "Frequency amount", channel: "freq", description: "Frequency interpolation", dfault: 1, min: 0, max: 1},
+ {presetgroup: "pvanal"},
+ {presetgroup: "pvsynth"},
+ {preset: "applymode"}
+ ]
+ },
+ exampleCsound: 'fL, fR, aL, aR, ileft, iright twst_getfinput\nfLo, fRo, ilefto, irighto twst_getfcrossinput\nkamp = twst_param:k("amp")\nkfreq = twst_param:k("freq")\n\nif (ileft == 1 && ilefto == 1) then\n\tfoutL pvsmorph fL, fLo, kamp, kfreq\n\taL twst_tf_fresynth foutL\nendif\n\nif (iright == 1 && irighto == 1) then\n\tfoutR pvsmorph fR, fRo, kamp, kfreq\n\taR twst_tf_fresynth foutR\nendif\nouts aL, aR'
+ },
+ {
+ name: "twst_getcrossdata",
+ outs: [
+ ["ifnL", "f-table containing left channel audio"],
+ ["ifnR", "f-table containing right channel audio"],
+ ["istart", "selection start in samples"],
+ ["ilen", "selection length in samples"],
+ ["ileft", "whether the left channel is selected"],
+ ["iright", "whether the right channel is selected"]
+ ],
+ description: "Obtain data from the file instance selected in a parameter preset {preset(instance)}. The f-tables are the complete file, and the start and length correspond to the selected area. ileft and iright also correspond to the selected channels",
+ exampleJson: {
+ name: "Multiplier",
+ instr: "twst_tf_multiplier",
+ inputs: 2,
+ parameters: [
+ {preset: "instance"},
+ {preset: "instanceloop"}
+ ]
+ },
+ exampleCsound: 'ixfnL, ixfnR, ixstart, ixlen, ixleft, ixright twst_getcrossdata\nprint ixlen\naL, aR, ileft, iright twst_getinput\naxL, axR, ixleft, ixright twst_getcrossinput\nif (ileft == 1 && ixleft == 1) then\n\taL *= axL\nendif\nif (iright == 1 && ixright == 1) then\n\taR *= axR\nendif\nouts aL, aR'
+ },
+ {
+ name: "twst_tfi_getcrossfn",
+ outs: [
+ ["ifnL", "f-table containing left channel audio"],
+ ["ifnR", "f-table containing right channel audio"],
+ ],
+ description: "Obtain an f-table from the file instance selected in a parameter preset {preset(instance)}, which has been sliced from the original file, based on the selection area. This may be necessary for some opcodes that read from a f-table, such as those that have no control over the read point, when used for convolution or cross synthesis",
+ exampleJson: {
+ name: "Convolve",
+ instr: "twst_tfi_exdconv",
+ inputs: 2,
+ parameters: [
+ {preset: "instance"},
+ {name: "Size ratio", min: 0.00001, max: 1, dfault: 0.1, lagHint: -1, channel: "sizeratio", automatable: false},
+ {presetgroup: "applymode"}
+ ]
+ },
+ exampleCsound: 'aL, aR, ileft, iright twst_getinput \nifnLo, ifnRo twst_tfi_getcrossfn\nisizeratio = twst_parami("sizeratio")\nif (ileft == 1) then\n\taL dconv aL, isizeratio * ftlen(ifnLo), ifnLo\nendif\nif (iright == 1) then\n\taR dconv aR, isizeratio * ftlen(ifnRo), ifnRo\nendif\nouts aL, aR'
+ },
+ {
+ name: "twst_tfi_getfn",
+ outs: [
+ ["ifnL", "f-table containing left channel audio"],
+ ["ifnR", "f-table containing right channel audio"],
+ ],
+ description: "Obtain f-tables which have been sliced from the original file, based on the selection area. This may be necessary for some opcodes that read from a f-table, such as those that have no control over the read point",
+ exampleJson: {
+ name: "Sndwarp",
+ instr: "twst_tfi_exsndwarp",
+ parameters: [
+ {name: "Time scale", channel: "timescale", min: 0.1, max: 10, dfault: 1, automatable: false},
+ {preset: "wintype", automatable: false}
+ ]
+ },
+ exampleCsound: 'ileft, iright, istartsamp, iendsamp, idocut, ilength twst_tf_getstate\nitimescale = twst_parami("timescale")\nifnWindow = twst_tf_getwintype()\np3 = ilength * itimescale\natime linseg 0, p3, ilength\nifnL, ifnR twst_tfi_getfn\nif (ileft == 1) then\n\taL sndwarp 1, atime, 1, ifnL, 0, 4410, 441, 4, ifnWindow, 1\nendif\nif (iright == 1) then\n\taR sndwarp 1, atime, apitchscale, ifnR, 0, 4410, 441, 4, ifnWindow, 1\nendif\nouts aL, aR'
+ },
+ {
+ name: "twst_setlatencysamples",
+ ins: [
+ ["isamples", "Number of samples latency"]
+ ],
+ description: "Set the expected processing latency in samples. This is then used to offset any writing and output accordingly. This should ideally be used for any buffered or windowed operations. However, {csound(twst_getfinput)} already sets this based on the FFT size",
+ exampleJson: {
+ name: "Hilbert pitch scale",
+ instr: "twst_tf_exhilbertpitchscale",
+ parameters: [
+ {presetgroup: "pitchscale"},
+ {preset: "fftsize"},
+ {preset: "applymode"}
+ ]
+ },
+ exampleCsound: 'aL, aR, ileft, iright twst_getinput\nifftsize = twst_parami("fftsize")\nkscale = twst_tf_pitchscale()\ntwst_setlatencysamples(ifftsize)\n\nif (ileft == 1) then\n\tahL1, ahL2 hilbert2 aL, ifftsize, ifftsize / 4\n\tamL, afmL fmanal ahL1, ahL2\n\taLx oscil amL, afmL * kscale\nendif\nif (iright == 1) then\n\tahR1, ahR2 hilbert2 aR, ifftsize, ifftsize / 4\n\tamR, afmR fmanal ahR1, ahR2\n\taRx oscil amR, afmR * kscale\nendif\nouts aLx, aRx'
+ },
+ {
+ name: "twst_setlatencyseconds",
+ ins: [
+ ["iseconds", "Number of seconds latency"]
+ ],
+ description: "Set the expected processing latency in seconds. This is then used to offset any writing and output accordingly. This should ideally be used for any buffered or windowed operations. However, {csound(twst_getfinput)} already sets this based on the FFT size",
+ exampleJson: {
+ name: "Hilbert pitch scale",
+ instr: "twst_tf_exhilbertpitchscale",
+ parameters: [
+ {presetgroup: "pitchscale"},
+ {preset: "fftsize"},
+ {preset: "applymode"}
+ ]
+ },
+ exampleCsound: 'aL, aR, ileft, iright twst_getinput\nifftsize = twst_parami("fftsize")\nkscale = twst_tf_pitchscale()\ntwst_setlatencyseconds(1 / ifftsize)\n\nif (ileft == 1) then\n\tahL1, ahL2 hilbert2 aL, ifftsize, ifftsize / 4\n\tamL, afmL fmanal ahL1, ahL2\n\taLx oscil amL, afmL * kscale\nendif\nif (iright == 1) then\n\tahR1, ahR2 hilbert2 aR, ifftsize, ifftsize / 4\n\tamR, afmR fmanal ahR1, ahR2\n\taRx oscil amR, afmR * kscale\nendif\nouts aLx, aRx'
+ },
+ {
+ name: "twst_getlatencyseconds",
+ outs: [
+ ["iseconds", "Number of seconds latency"]
+ ],
+ description: "Obtain the expected processing latency in seconds, as previously set by {csound(twst_setlatencysamples)}, {csound(twst_setlatencyseconds)} or {csound(twst_getfinput)}",
+ exampleJson: {
+ name: "Hilbert pitch scale",
+ instr: "twst_tf_exhilbertpitchscale",
+ parameters: [
+ {presetgroup: "pitchscale"},
+ {preset: "fftsize"},
+ {preset: "applymode"}
+ ]
+ },
+ exampleCsound: 'aL, aR, ileft, iright twst_getinput\nifftsize = twst_parami("fftsize")\nkscale = twst_tf_pitchscale()\ntwst_setlatencysamples(ifftsize)\nprint twst_getlatencyseconds()\nif (ileft == 1) then\n\tahL1, ahL2 hilbert2 aL, ifftsize, ifftsize / 4\n\tamL, afmL fmanal ahL1, ahL2\n\taLx oscil amL, afmL * kscale\nendif\nif (iright == 1) then\n\tahR1, ahR2 hilbert2 aR, ifftsize, ifftsize / 4\n\tamR, afmR fmanal ahR1, ahR2\n\taRx oscil amR, afmR * kscale\nendif\nouts aLx, aRx'
+ },
+ {
+ name: "twst_tf_setplayposition",
+ ins: [
+ ["kposition", "Playback position ratio"]
+ ],
+ description: "Override the displayed playback position. The supplied kposition must be between 0 and 1, and corresponds to the selected area being played or auditioned. Normal operation would be equivalent to line(0, p3, 1)",
+ exampleJson: {
+ name: "Direct time sndwarp",
+ instr: "twst_tfi_directsndwarp",
+ parameters: [
+ {name: "Read time", channel: "readtime"},
+ {preset: "wintype", automatable: false}
+ ]
+ },
+ exampleCsound: 'ileft, iright, istartsamp, iendsamp, idocut, ilength twst_tf_getstate\nktime = twst_param:k("readtime")\ntwst_tf_setplayposition ktime\natime = a(ktime * ilength)\nifnWindow = twst_tf_getwintype()\nifnL, ifnR twst_tfi_getfn\nif (ileft == 1) then\n\taL sndwarp 1, atime, 1, ifnL, 0, 4410, 441, 4, ifnWindow, 1\nendif\nif (iright == 1) then\n\taR sndwarp 1, atime, apitchscale, ifnR, 0, 4410, 441, 4, ifnWindow, 1\nendif\nouts aL, aR'
+ },
+ {
+ name: "twst_tf_getstate",
+ outs: [
+ ["ileft", "Whether the left channel is selected"],
+ ["iright", "Whether the right channel is selected"],
+ ["istart", "Start sample number of selection"],
+ ["iend", "End sample number of selection"],
+ ["ilens", "Length of selection in seconds"]
+ ],
+ description: "Obtain details about the current selection. If the source is mono, only ileft will be equal to 1",
+ exampleJson: {
+ name: "Direct time sndwarp",
+ instr: "twst_tfi_directsndwarp",
+ parameters: [
+ {name: "Read time", channel: "readtime"},
+ {preset: "wintype", automatable: false}
+ ]
+ },
+ exampleCsound: 'ileft, iright, istartsamp, iendsamp, idocut, ilength twst_tf_getstate\nktime = twst_param:k("readtime")\ntwst_tf_setplayposition ktime\natime = a(ktime * ilength)\nifnWindow = twst_tf_getwintype()\nifnL, ifnR twst_tfi_getfn\nif (ileft == 1) then\n\taL sndwarp 1, atime, 1, ifnL, 0, 4410, 441, 4, ifnWindow, 1\nendif\nif (iright == 1) then\n\taR sndwarp 1, atime, apitchscale, ifnR, 0, 4410, 441, 4, ifnWindow, 1\nendif\nouts aL, aR'
+ }
+ ];
+
+ function linkage(text) {
+ var re = /{(preset|presetgroup|json|csound)\((.*?)\)}/g;
+ do {
+ match = re.exec(text);
+ if (match) {
+ text = text.replaceAll(match[0], "<a href=\"#" + match[1] + "_" + match[2] + "\">" + match[2] + "</a>");
+ }
+ } while (match);
+ return text;
+ }
+
+ function buildOpcodes() {
+ var elTarget = $("#opcodes");
+ for (let index in documentation.opcodes) {
+ let o = documentation.opcodes[index];
+ var html = ""
+ if (o.outs) {
+ var names = [];
+ for (var x of o.outs) names.push(x[0]);
+ html += "<i>" + names.join(", ") + "</i> "
+ }
+ html += "<b>" + o.name + "</b>";
+ if (o.ins) {
+ var names = [];
+ for (var x of o.ins) {
+ if (x[2]) { // has default
+ names.push("[" + x[0] + "=" + x[2] + "]");
+ } else {
+ names.push(x[0]);
+ }
+ }
+ html += " <i>" + names.join(", ") + "</i>"
+ }
+
+ $("<p />").html(linkage(html)).attr("id", "csound_" + o.name).appendTo(elTarget);
+ if (o.ins || o.outs) {
+ var ul = $("<ul />").appendTo(elTarget);
+ if (o.outs) {
+ for (var x of o.outs) {
+ var html = "<i>" + x[0] + "</i> " + x[1];
+ $("<li />").html(linkage(html)).appendTo(ul);
+ }
+ }
+ if (o.ins) {
+ for (var x of o.ins) {
+ var html = "<i>" + x[0] + "</i> " + x[1];
+ if (x[2]) html += " <i>[default: " + x[2] + "</i>]"
+ $("<li />").html(linkage(html)).appendTo(ul);
+ }
+ }
+ }
+ elTarget.append($("<p />").html(linkage(o.description)));
+
+ if (o.exampleCsound && o.exampleJson) {
+ var cs = "instr " + o.exampleJson.instr + "\n\t$TWST_TRANSFORM\n"
+ cs += o.exampleCsound.replace(/^/gm, "\t");
+ cs += "\nendin"
+ var exampleCsound = $("<pre />").hide().text(cs).attr("id", "csex_" + index);
+ let exampleCsoundShown = false;
+ $("<a />").attr("href", "#").text("Csound example").click(function(e) {
+ e.preventDefault();
+ if (!exampleCsoundShown) {
+ $("#csex_" + index).show();
+ exampleCsoundShown = true;
+ } else {
+ $("#csex_" + index).hide();
+ exampleCsoundShown = false;
+ }
+ }).appendTo($("<p />").appendTo(elTarget));
+ exampleCsound.appendTo(elTarget);
+ var exampleJson = $("<pre />").hide().text(JSON.stringify(o.exampleJson, null, "\t")).attr("id", "jsex_" + index);
+ let exampleJsonShown = false;
+ $("<a />").attr("href", "#").text("Corresponding definition example").click(function(e) {
+ e.preventDefault();
+ if (!exampleJsonShown) {
+ $("#jsex_" + index).show();
+ exampleJsonShown = true;
+ } else {
+ $("#jsex_" + index).hide();
+ exampleJsonShown = false;
+ }
+ }).appendTo($("<p />").appendTo(elTarget));
+ exampleJson.appendTo(elTarget);
+ }
+
+ elTarget.append($("<hr />"));
+ }
+ }
+
+
+ $(function() {
+ buildOpcodes();
+ });
+ </script>
+
+</head>
+<body>
+ <h1>Extending twist</h1>
+ <div id="container_overview">
+ <h2>Overview</h2>
+ Twist can quite easily be extended to feature additional transforms. These can be tested and used on the fly with the <i>developer console</i> within twist, and are encouraged to be submitted for inclusion in the live application which can be done <a href="https://csound.1bpm.net/contact/?type=twist_submit">here</a>, via the <i>Help > Submit transform code</i> menu option, or via the link in the <i>developer console</i><br /><br />
+ In order to write new transforms for twist, familiarity with JSON and Csound is required. The UI components including parameters available to the end user are defined with JSON (detailed in the <a href="#json">transform definition</a> section, and the actual audio processing is defined with Csound code (detailed in the <a href="#csound">audio processing with Csound</a> section. Additional twist opcodes are provided to the developer in order to ease integration.<br />
+ Each transform requires a transform definition as a JSON object, and at least one Csound instrument. While each section describes the API to be used, full examples are provided in the <a href="#opcodes">Csound opcode</a> subsection.
+
+
+ </div><div id="container_json">
+ <h2 id="json">Transform definition with JSON</h2>
+ The transform definition is a JSON object, which should at the very least have the keys <a href="#json_name">name</a> and <a href="#json_instr">instr</a> defined. The possible keys for the top-level transform definition are as follows, and if a default value is applicable it is shown to the right of the equals sign in the name column:
+
+ <table><tbody>
+ <tr><td><h5 id="json_name">name</h5></td><td>Name as seen in the twist user interface</td></tr>
+ <tr><td><h5 id="json_instr">instr</h5></td><td>Csound named instrument, which is to be called to carry out the processing</td></tr>
+ <tr><td><h5>inputs = 1</h5></td><td>Number of input files the transform requires. This defaults to 1 but may be set to 2 for cross-processing transforms and such</td></tr>
+ <tr><td><h5>description = ""</h5></td><td>Description of the transform</td></tr>
+ <tr><td><h5>author = ""</h5></td><td>Author name and other relevant details</td></tr>
+ <tr><td><h5>parameters = []</h5></td><td><a href="#parameter">Parameter definitions</a> in an array</td></tr>
+ <tr><td><h5>twine = false</h5></td><td>Whether the transform will be available as a twine insert. Only <a href="#csound_rule_tfi">transforms using live input</a> can be used for this purpose</td></tr>
+ <tr><td><h5>unstable = false</h5></td><td>Should be set to true if the transform is expected to be unstable and may cause crashes. This will result in a warning displayed when the transform is loaded</td></tr>
+ </tbody></table>
+
+
+ <h4 id="parameter">Parameter definition</h4>
+ The parameter definition is a JSON object, which may have any of the following keys. If min == 0, max == 1 and step == 1, the parameter appears as a checkbox which provides the value 1 when checked and 0 when unchecked. If <a href="#parameter_options">options</a> is supplied, then the parameter appears as a drop-down select box. In other cases the parameter is displayed as a range slider with an adjacent number input box.<br /><br />
+ The only required key for a parameter definition is <a href="#parameter_name">name</a>. In this case, a parameter would be with a range of 0 to 1, with the default step amount and sending on the channel with the lowercase equivalent of the name.<br /><br />
+ The possible keys for a parameter definition are as follows, and if a default value is applicable it is shown to the right of the equals sign in the name column:
+
+ <table><tbody>
+ <tr><td><h5 id="parameter_name">name</h5></td><td>Name of the parameter to be shown in the interface</td></tr>
+ <tr><td><h5>description = ""</h5></td><td>Description of the parameter</td></tr>
+ <tr><td><h5 id="parameter_channel">channel = name.toLowerCase()</h5></td><td>Channel name which should correspond to that which is requested by <a href="#csound_twst_param">twst_param</a> in the <a href="#json_instr">transform instrument</a>. Defaults to the lowercase parameter name</td></tr>
+ <tr><td><h5>min = 0</h5></td><td>Numeric minimum accepted value</td></tr>
+ <tr><td><h5>max = 1</h5></td><td>Numeric maximum accepted value</td></tr>
+ <tr><td><h5>step = 0.0000001</h5></td><td>Incremental allowance of the value, should numeric</td></tr>
+ <tr><td><h5 id="parameter_dfault">dfault = 1</h5></td><td>Numeric default value</td></tr>
+ <tr><td><h5 id="parameter_options">options = null</h5></td><td>Array containing options to be displayed in a drop-down select box. If supplied, the minimum, maximum and step values are redundant. <a href="#parameter_dfault">dfault</a> corresponds to the index of the array to be the default value. If <a href="#parameter_asvalue">asvalue</a> is set, then the value supplied to Csound will be the value provided in the options array; otherwise it will be the index of the value</td></tr>
+ <tr><td><h5 id="parameter_asvalue">asvalue = false</h5></td><td>Whether the selected item from <a href="#parameter_options">options</a> should be provided to Csound as the actual value rather than the array index</td></tr>
+ <tr><td><h5>hidden = false</h5></td><td>Whether the parameter should be hidden. May be useful passing static data from the interface to Csound</td></tr>
+ <tr><td><h5>conditions = null</h5></td><td>An array of <a href="#condition">Condition</a> objects which are all to be met for the parameter to be shown</td></tr>
+ <tr><td><h5>hostrange = false</h5></td><td>For child parameters (namely those in modulations), whether the min, max, step, dfault, options and asvalue attributes should be inherited from the parent</td></tr>
+ <tr><td><h5 id="parameter_preset">preset = null</h5></td><td>The name of a <a href="#preset">preset</a> to be used. Any definition attributes provided by the preset may be overriden</td></tr>
+ <tr><td><h5 id="parameter_presetgroup">presetgroup = null</h5></td><td>The name of a <a href="#presetgroup">presetgroup</a> to be used, which will provide a number of parameters in place of the current definition
+ <tr><td><h5>nameprepend = null</h5></td><td>The string which will be prepended to parameter names, if presetgroup is specified
+ <tr><td><h5>channelprepend = null</h5></td><td>The string which will be prepended to parameter channels, if presetgroup is specified
+ </tbody></table>
+
+ <hr />
+ <h4 id="condition">Condition</h4>
+ The condition definition is a JSON object, which should include all of the following keys:
+ <table><tbody>
+ <tr><td><h5>channel</h5></td><td>Parameter <a href="#parameter_channel">channel</a> to evaluate</td></tr>
+ <tr><td><h5>operator</h5></td><td>Operator type, which may be eq (equal), neq (not equal), lt (less than), gt (greater than), le (less than or equal to) or ge (greater than or equal to)</td></tr>
+ <tr><td><h5>value</h5></td><td>Static value to check against the above</td></tr>
+ </tbody></table>
+
+ <hr />
+ <h4 id="preset">Presets</h4>
+ These are available as values to specify in the <a href="#parameter_presetgroup">presetgroup</a> parameter attribute and alter set the parameter up as follows
+ <table><tbody>
+ <tr><td><h5>amp</h5></td><td>Amplitude slider with min: 0 and max: 1, channel: "amp"</td></tr>
+ <tr><td><h5 id="preset_fftsize">fftsize</h5></td><td>FFT size drop down which may be transparently utilised by <a href="#csound_twst_getfinput">twst_getfinput</a> and <a href="#csound_twst_getfcrossinput">twst_getfcrossinput</a>, or accessed directly via the channel "fftsize" or the specified channel name with <a href="#csound_twst_param">twst_param</a></td></tr>
+ <tr><td><h5 id="preset_wave">wave</h5></td><td>f-table selector which may be transparently utilised by <a href="#csound_twst_tf_getwaveform">twst_tf_getwaveform</a>, <a href="#csound_twst_tf_getwaveformk">twst_tf_getwaveformk</a>, or accessed directly via the channel "wave" or the specified channel name with <a href="#csound_twst_param">twst_param</a> or <a href="#csound_twst_paramk">twst_paramk</a></td></tr>
+ <tr><td><h5>applymode</h5></td><td>Apply mode drop down, which may be Replace, Mix, Modulate or Demodulate. Used internally by twist at the rendering stage</td></tr>
+ <tr><td><h5>note</h5></td><td>MIDI note number drop-down, displaying note names between MIDI note number 21 (A0) and 127 (G#9) and returning the MIDI note number to the channel</td></tr>
+ <tr><td><h5 id="preset_wintype">wintype</h5></td><td>Window type drop-down which may be utilised by <a href="#csound_twst_tf_getwintype">twst_tf_getwintype</a>, <a href="#csound_twst_tf_getwintypek">twst_tf_getwintypek</a> or accessed directly via the channel "wintype" or the specified channel name with <a href="#csound_twst_param">twst_param</a> or <a href="#csound_twst_paramk">twst_paramk</a></td></tr>
+ <tr><td><h5 id="preset_instance">instance</h5></td><td>Drop down selecting a file open in twist, other than that which is currently open. Utilised interally by <a href="#csound_twst_getcrossinput">twst_getcrossinput</a> and <a href="#csound_twst_getfcrossinput">twst_getfcrossinput</a></td></tr>
+ <tr><td><h5 id="preset_instanceloop">instanceloop</h5></td><td>Drop down selecting either None, Forward, Backward or Ping-pong to denote the loop type of the other selected instance, used internally for cross-processing transforms within <a href="#csound_twst_getcrossinput">twst_getcrossinput</a>, <a href="#csound_twst_getfcrossinput">twst_getfcrossinput</a> and <a href="#csound_twst_getfcrossdata">twst_getfcrossdata</a></td></tr>
+ </tbody></table>
+
+ <hr />
+ <h4 id="presetgroup">Preset groups</h4>
+ These are available as values to specify in the <a href="#parameter_presetgroup">presetgroup</a> parameter attribute.
+ <table><tbody>
+ <tr><td><h5>pvanal</h5></td><td>Provides <a href="#preset_fftsize">FFT size</a> and a frequency/phase locking checkbox, used internally in the provision of PVS stream data within <a href="#csound_twst_getfinput">twst_getfinput</a> and <a href="#csound_twst_getfcrossinput">twst_getfcrossinput</a></td></tr>
+ <tr><td><h5>pvresmode</h5></td><td>Provides parameters which control the resynthesis approach as used by <a href="#csound_twst_tf_fresynth">twst_tf_fresynth</a>. A drop down permits selection between overlap-add and additive approaches, with the latter showing several further parameters when selected</td></tr>
+ <tr><td><h5 id="presetgroup_pitchscale">pitchscale</h5></td><td>Provides a scaling mode drop down with semitones or ratio as options. The selected scaling is presented via <a href="#csound_twst_tf_pitchscale">twst_tf_pitchscale</a> as a ratio</td></tr>
+ <tr><td><h5 id="presetgroup_notefreq">notefreq</h5></td><td>Shows an option of selecting a note name from a drop down, or specifying the frequency in Hz. The computed frequency is provided to Csound via <a href="#csound_twst_tf_freq">twst_tf_freq</a> and <a href="#csound_twst_tf_freqi">twst_tf_freqi</a></td></tr>
+ </tbody></table>
+
+
+ </div><div id="container_csound">
+
+ <h2 id="csound">Audio processing with Csound</h2>
+ Audio processing is carried out for the corresponding JSON transform definition by invoking the Csound instrument specified in the <a href="#json_instr">instr</a> key. Multiple Csound instruments and opcodes may be utilised, however it should be noted that the Csound instrument is called using <i>subinstr</i>, and offline/commit processing is carried out using audio rate processing within a k-rate loop. The only known limitation this imposes is that additional/auxilliary instruments may not usually be called from the initial instrument in a way that would affect synchronisation of the offline processing aspect - ie, opcodes such as <i>schedule</i> and <i>event</i> should not be used except in careful circumstances where the synchronisation is respected - for example where the scheduled instrument only complete init time processing, or completes in a single k-cycle. However, auxilliary instruments may be called using <i>subinstr</i>.<br /><br />
+ Instruments can generate audio, utilise direct feed of audio, or access table data directly. The latter is useful if the output should be a different duration to the input. <br />
+ A number of opcodes to ease integration with the UI and transform definition are provided by twist, detailed below with examples in the <a href="#opcodes">Opcode reference</a> subsection.
+ <h3>Rules and style guide</h3>
+ The rules and style guide should be adhered to where appropriate, especially if opcodes are to be submitted for inclusion in the live application.
+ <ul>
+ <li id="csound_rule_tfi">Instruments referenced by the transform definition should be named prepended with <i>twst_tf_</i> if they generate audio or use direct input (obtained with <a href="#csound_twst_getinput">twst_getinput</a> or <a href="#csound_twst_getfinput">twst_getfinput</a>) - or prepended with <i>twst_tfi_</i> if table access is to be used (with <a href="#csound_twst_tfi_getfn">twst_tfi_getfn</a></li>
+ <li>The first line of the instrument must be <i>$TWST_TRANSFORM</i> to mark it as a twist transform</li>
+ <li>Auxilliary instruments and user-defined opcodes should be named prepended with the name of the initial instrument</li>
+ <li>Instruments may generate audio or process audio input obtained from calls to <a href="#csound_twst_getinput">twst_getinput</a>, <a href="#csound_twst_getfinput">twst_getfinput</a> or <a href="#csound_twst_tfi_getfn">twst_tfi_getfn</a></li>
+ <li>Instruments must emit stereo audio signals using the <i>outs</i> opcode. Depending on the processing action, either of the outputs may be a silent signal or the same as the input</li>
+ <li>Instruments should be prepared to process or generate left and right channels according to the <i>ileft</i> and <i>iright</i> values from the call to <a href="#csound_twst_getinput">twst_getinput</a>, <a href="#csound_twst_getfinput">twst_getfinput</a> or <a href="#csound_twst_tf_getstate">twst_tf_getstate</a>. A channel not applicable to the request must still be emitted, but may be a silent signal or the same as the input - the audition/commit process will only use the output for the channel requested by the user in the UI</li>
+ <li>Any global objects created must not persist after the instrument has finished. For example, <i>ftgentmp</i> must be used rather than <i>ftgen</i> - unless <i>ftfree</i> is used on the f-table accordingly</li>
+ <li><i>print</i> opcodes and other console output opcodes should not be used except for debugging purposes</li>
+ <li>0dbfs is set at 1, so anything reliant on this should adhere accordingly</li>
+ <li>Opcodes are limited to those available in the Csound WASM build - this is generally everything, but one noted example of an exclusion is <i>fractalnoise</i>. If otherwise unexplainable errors are encountered, this may be due to an unavailable opcode</li>
+ </ul>
+ <h3>Opcode reference</h3>
+ <div id="opcodes"></div>
+
+ </div><div id="container_examples">
+
+ <h2>Examples from the live application</h2>
+ All of the JSON transform definitions <a href="../twirl/appdata.js">can be seen here</a>, under the <i>transforms</i> key.<br />
+ Csound code in the live application is split across several files which are as follows. Each file generally corresponds to the section in the JSON.
+ <ul>
+ <li><a href="/udo/twist/transforms/amplitude.udo">amplitude</a></li>
+ <li><a href="/udo/twist/transforms/cross_processing.udo">cross_processing</a></li>
+ <li><a href="/udo/twist/transforms/delay.udo">delay</a></li>
+ <li><a href="/udo/twist/transforms/filter.udo">filter</a></li>
+ <li><a href="/udo/twist/transforms/frequency.udo">frequency</a></li>
+ <li><a href="/udo/twist/transforms/amplitude.udo">amplitude</a></li>
+ <li><a href="/udo/twist/transforms/general.udo">general</a></li>
+ <li><a href="/udo/twist/transforms/generate.udo">generate</a></li>
+ <li><a href="/udo/twist/transforms/granular.udo">granular</a></li>
+ <li><a href="/udo/twist/transforms/harmonic.udo">harmonic</a></li>
+ <li><a href="/udo/twist/transforms/reverb.udo">reverb</a></li>
+ <li><a href="/udo/twist/transforms/spectral.udo">spectral</a></li>
+ <li><a href="/udo/twist/transforms/warping.udo">warping</a></li>
+ </ul>
+</body>
+</html>
\ No newline at end of file |