Docs CHOPs & sensing
TopToMidi
Samples an image at points you define and turns the pixel values into MIDI notes in a musical scale, with trigger gating, retrigger control, a MIDI-learned custom scale and output to a MIDI Out or VST CHOP.
∿ CHOPs & sensing ◆ Patreon:Base
This tool unlocks with Patreon. It installs through the same picker as everything else and unlocks with the Patreon Base tier or higher, connected from inside TouchDesigner. Everything else in the toolkit stays free and MIT, and the membership is what keeps that work moving.
What it is
TopToMidi plays your visuals. A sampler (a SOP's points, or a TOP's pixels) says where the input image is read; each sample point becomes a note. In Index mode a point triggers its own note whenever its pixel passes the threshold, so a pattern sweeping across the picture plays an arpeggio. In Value mode the pixel's brightness picks the note, quantised to Steps. The notes are mapped into a scale from a root note and octave, with custom scales you type in, or a scale learned live from a MIDI keyboard so you can duet with the picture. Trigger gating keeps busy scenes from spraying notes.
The notes go out to a MIDI Out CHOP, an Audio VST CHOP, or both, and ride out as a CHOP for anything else.
It is a member of the FNS operator family: pick it from the FNS tab of the OP Create dialog and it lands as one node.
Setup
Every scale except MIDI Scale is computed with the Python package mingus, which TouchDesigner does not bundle. The tool ships its own pip requirements file (the requirements DAT inside it) and installs it through TouchDesigner's Python Environment Manager. The Setup page's Status says whether mingus is available. When it is missing:
- With a Python vEnv or Conda environment linked through the Python Environment Manager, press Install mingus. The tool writes
TopToMidi.requirements.txtbeside your .toe and hands it to the environment manager, which installs it into the linked environment in the background; Status reports the result. When the project has an environment context file, the requirements file is also registered in it, so a machine that opens the project with Auto Setup On Startup installs it on its own. - With no environment, create one in the Python Environment Manager (palette: tdPyEnvManager), then press Install mingus.
Nothing blocks TouchDesigner while this happens, and the tool never installs anything without the pulse.
Inputs and outputs
- in2 (TOP): the image to sample.
- out_viz (TOP): the sampling points drawn over the input.
- out_sampled (TOP) and out_sampled_CHOP (CHOP): the sampled values.
- out_notes (CHOP): the generated notes.
Processing while idle
Note processing runs only while a MIDI Out or VST CHOP is configured or the outputs are wired. MIDI learning runs only while a MIDI In CHOP is set. Steps follows the number of sample points while note processing runs.
Parameters
Input
| Control | Type / default | What it does |
|---|---|---|
SamplerSampler |
operatorempty | TOP or SOP operator to define the pixel positions for sampling. These can be animated too, of course! |
Offset 0.5Origo |
on / offoff | By default many SOPs are centered around the origin. This quick toggle shifts the Sampler’s center to (0.5, 0.5). |
Sample PreviewOpen2 |
button | Opens a UI window to visualize and manually adjust the sampling points. Move them around with Left-Click+Dragging ; Scale with Scroll-Wheel (or +-), Reset with Middle-Click. It also has some options on the bottom left to always show the points, toggle Offset 0.5 and Reset the adjustments |
Sample ChannelRgb |
menuLuminance | Which attribute of the input image to perform further processing on. |
ThresholdThresh |
number0 | Pre-processes the input image by thresholding between two values. This will also have an effect on when a note is triggered in Index Mapping Mode. |
Re-RangeRerange |
on / offoff | Re-ranges the thresholded image to 0-1. This parameter is only interesting in Value Mapping Mode. |
Mapping ModeMode |
menu0 | This is the most important parameter to determine the mapping of pixel values to MIDI notes, before assigning to a Scale. Index: The point/pixel indices of the Sampler determine the pitch of the notes, upon triggered by the sampled value reaching the Threshold. Notes are sustained while in the range. It is important to set a good Threshold with Index mode. Important to note that the number of Steps is determined by the number of points. Be careful not to use big textures or SOPs with many points (anyway MIDI is limited to 128 notes). Value: The sampled values determine the pitch of the notes, where the quantization is determined by the Steps parameter. It means if you have identical sampled values they will trigged the same note twice. Re-Range of the Threshold is suggested to be kept on usually. In this mode you are more free to set more sampling points! |
| Trigger Options | ||
Re-Trigger Gate LengthRetriggergatelen |
number0.2 | Overall gate window in seconds. At 0 every trigger passes straight through. Above 0 the sampled pattern is held for this long after a trigger, so a new trigger (or a release) can happen at most once per window; changes that arrive inside the window are applied when it closes. |
Trigger Gate LengthTriggergatelength |
number0.2 | Seconds a sample point has to stay above the threshold before its note turns on. 0 = immediately. |
Min Sustain LengthMinsustain |
number0 | Minimum seconds a note stays on once triggered, even if the sample point drops below the threshold sooner. |
Re-Trigger DelayRetrigger |
number0 | Minimum seconds between two triggers of the same note. A new trigger inside this time is ignored. |
Scale
| Control | Type / default | What it does |
|---|---|---|
ScaleScale |
menuMajor | Determines the Scale Mode the triggered notes are mapped to. Scales determine a number of notes in a Scale, starting from a root note (Key). You can also define Custom Scales which will also show up in the dropdown! MIDI Scale is a special one, see later. |
KeyRootnote |
menu, editableempty | Sets the musical root note of the Scale. Can type any musical note notation, even wild things like A#bbb## (thanks to the mingus library). But usually the drop-down list should be more reasonable :) |
OctaveOctave |
number4 | The octave of the root note. |
StepsSteps |
number1 | Number of MIDI notes to generate. In Index mode it is fixed to the number of sampling points. In Value mode it is the "quantization" of the pitch determined by the sampled pixel values. |
Extend ModeExtendmode |
on / offoff | When having more steps than the number of notes in the Scale, having this on will extend subsequent steps to the next octaves. Otherwise the same scale notes in the starting octave are repeated. |
Edit Custom ScalesOpen |
button | Opens a Table DAT where in each column you can define a custom scale name where each note can be defined in the rows below using standard musical notation. For example: C#3. |
Keytrack LookupVelocitylookup |
operatorempty | A multi-sample CHOP reference which can define the MIDI velocity based on the pitch. |
| MIDI Scale | ||
MIDI In CHOPMidiref |
operatorempty | Optional MIDI In CHOP (a MIDI keyboard) for MIDI Scale learn and live mode. Empty by default; name a sibling MIDI In CHOP, e.g. midiin1. |
MIDI Scale LearnMidilearn |
on / offoff | Can define a Custom Scale by hitting notes one-by-one on your MIDI In instrument. |
MIDI LiveMidilive |
on / offoff | Follows the keys currently held on the MIDI In CHOP as the scale, in real time (MIDI Scale only), instead of the learned one. |
Live Octave OffsetLiveoctaveoffset |
number0 | Octaves added to the notes taken live from the MIDI In CHOP while MIDI Live is on, so the tool can play along above (or below) the keys you hold. |
Sync StepsSyncsteps |
on / offoff | Syncs the number of steps to the number of incoming notes. This is not available when Extend Mode is on. |
RandomizeRandomize |
on / offoff | Randomize the order of notes. |
SeedSeed |
number0 | Seed of the randomization. |
Output
| Control | Type / default | What it does |
|---|---|---|
MIDI ActiveActive |
on / offon | Activates MIDI Out CHOP. |
MIDI Out CHOPMidioutchop |
operatorempty | MIDI Out CHOP to send notes to, referenced directly (no Null after it). Empty by default: drop a MIDI Out CHOP beside this tool and name it here, e.g. midiout1 for a sibling. |
ChannelCh |
number0 | MIDI channel to output notes on. |
VST ActiveVstactive |
on / offoff | Activates VST CHOP. |
VST CHOPVstchop |
operatorempty | Optional Audio VST CHOP to play notes on, referenced directly (no Null after it). Empty by default; name a sibling Audio VST CHOP, e.g. audiovst1. |
ChannelVstchannel |
number1 | VST channel to output notes on. |
Setup
| Control | Type / default | What it does |
|---|---|---|
StatusStatusread-only |
textempty | Read-only. Whether the Python package mingus (needed for every scale except MIDI Scale) is available, and what to do if it is not. |
Install mingusInstall |
button | Installs mingus into the Python environment linked by TouchDesigner's Python Environment Manager, in the background. Needs a linked Python vEnv; the Status line says when one is missing. |
Re-checkRecheck |
button | Looks for mingus again, e.g. after installing it by hand from the Python Environment Manager CLI. |
Python Env Manager HelpEnvhelp |
button | Opens the documentation of TouchDesigner's Python Environment Manager (tdPyEnvManager). |
About
| Control | Type / default | What it does |
|---|---|---|
HelpTestopenhelp |
button | Opens documentation. |