Legato
File: Rhapsodist/Processors/Legato.js.
Note
The algorithms here are subject to change as they are refined.
Overview
Models legato, portamento, and retrigger transitions with pitch/volume fades and a scripted step sequence.
A transition steps semitone-by-semitone toward the target, capped by StepsMax unless gliding. A harder attack produces a faster transition, and step timing is shaped rather than evenly spaced.
Notes played within roughly 25ms of each other are treated as a chord, not a legato transition.
Releasing back to a still-held earlier note re-triggers a transition toward it; releasing the currently playing note stops it normally.
Mute behaviour
Because Legato plays the target note itself rather than passing the incoming note through, Mute does more than block new notes: it also stops any transition already in progress and cleanly ends the currently-sounding artificial note.
Parameters
| ID | Description |
|---|---|
Mute | Disables the processor; see Mute behaviour above. |
Glide | Switches between legato mode (off) and glide mode (on), each with its own timing/offset/pitch settings below. |
LegatoPitch | Fine pitch offset applied per step in legato mode, 0–100. |
GlidePitch | Fine pitch offset applied per step in glide mode, 0–100. |
StepsMax | Caps the number of semitone steps triggered during a legato transition, 2–12 (12 = no limit). Also enables/disables LegatoOffset (enabled above 2). Has no effect in glide mode, where the full interval is always stepped. |
LegatoTimeMin | Duration for a one-semitone legato transition, 5–100 ms. |
LegatoTimeMax | Duration for an octave-or-more legato transition, 50–1000 ms. |
LegatoOffset | Sample start offset, in samples, for intermediate legato steps, -1–65535. |
TargetOffset | Sample start offset, in samples, for the final note of a legato transition, -1–65535. |
GlideTimeMin | Duration for a one-semitone glide transition, 200–1000 ms. |
GlideTimeMax | Duration for an octave-or-more glide transition, 500–2000 ms. |
GlideOffset | Sample start offset, in samples, for glide notes, -1–65535. |
-1 on an offset knob tells HISE to use the sample’s own configured Sample Start Offset.
Usage
Load into a sampler’s MIDI Processor chain and tune the legato/glide timing and offset knobs to taste.
Internal Reference
| Function | Description | Returns |
|---|---|---|
playLegatoNote(velocity: number) | Plays (or crossfades into) the next step of the current transition. It works out the next note, its pitch/gain fade, and start offset. It then starts the timer for the following step, or stops it if the target note has been reached. Also fires on the timer callback. | — |
getPitchBend(direction: number) | Returns the per-step fine pitch offset for the current mode (GlidePitch or LegatoPitch), signed by direction and jittered by up to 10 cents. | number |
getStartOffset(note: number) | Returns the sample start offset to use for the given step: GlideOffset in glide mode, otherwise TargetOffset for the final note or LegatoOffset for intermediate steps. | number |
getNumSteps(interval: number) | Returns how many steps the transition will take: the full interval in glide mode, otherwise the smaller of interval and StepsMax. | number |
getStep(numSteps: number) | Returns the semitone offset from origin for the current stepIndex, spread evenly across numSteps. | number |
setBaseDurations(arr: Array, min: number, max: number) | Rebuilds a 12-entry duration table (legatoDurations or glideDurations) between min and max, shaped by a fixed easing curve, whenever the corresponding time-min/time-max knobs change. | — |
getTransitionDuration(velocity: number, interval: number) | Looks up the base duration for the note interval from legatoDurations/glideDurations and scales it down for harder-velocity attacks, down to a 4 ms floor. | number |
getStepDuration(stepIndex: number, numSteps: number, max: number) | Returns the duration of one individual step within the overall transition duration, shaped so steps aren’t evenly spaced. | number |