This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
examples:pangoscript [2025/04/17 17:55] Lyra Letournea |
examples:pangoscript [2025/04/17 18:11] (current) Lyra Letournea [Examples from Users] |
||
---|---|---|---|
Line 80: | Line 80: | ||
===== Examples from Users ===== | ===== Examples from Users ===== | ||
- | The following examples are from the userbase, at the permission of the users. | + | The following examples are from the userbase, at the permission of the users. Scripts many not have been validated by pangolin internally, and opinions expressed, and explanations are directly from the user not pangolin. |
==== Jeff Vyduna ==== | ==== Jeff Vyduna ==== | ||
Line 148: | Line 148: | ||
| | ||
Takes a fader or rotary pot on a MIDI controller, such as on a APC40mk2 or Traktor F1, and scale the global cue speed to snap to a 2^X speed multiplier (25%, 50%, 100%, 200%, 400%, etc). For example, if you've made cues with a 4 beat duration, this lets you us a MIDI control to instantly change their duration to 8, 16, or 32 beats (as well as 2, 1, 1/2, 1/4 of a beat). | Takes a fader or rotary pot on a MIDI controller, such as on a APC40mk2 or Traktor F1, and scale the global cue speed to snap to a 2^X speed multiplier (25%, 50%, 100%, 200%, 400%, etc). For example, if you've made cues with a 4 beat duration, this lets you us a MIDI control to instantly change their duration to 8, 16, or 32 beats (as well as 2, 1, 1/2, 1/4 of a beat). | ||
+ | |||
+ | === Rotary relative encoder to 2^X cue speeds === | ||
+ | |||
+ | // Quantize an relative encoder input to 100*2^n cue speed. | ||
+ | | ||
+ | // SUMMARY | ||
+ | | ||
+ | // Takes MIDI values 1 (incr) and 127 (decr) to select a 2^i speed | ||
+ | // multiplier for i in [-4, 4]. This produces multipliers of: | ||
+ | // 100% * [1/16, 1/8, 1/4, 1/2, 1, 2, 4, 8, 16] | ||
+ | | ||
+ | | ||
+ | // DETAILED DESCRIPTION | ||
+ | | ||
+ | // This script lets you set your cue speed to multiples of 2. For example. | ||
+ | // if you had a cue designed for 1-beat duration, you can snap instantly to | ||
+ | // scaling the duration slower to 2, 4, 8 beats, or faster to 1/2, 1/4, | ||
+ | // etc., by setting MasterCueSpeed to 200%, 400%, 50%, etc. | ||
+ | | ||
+ | // The script is configured to use input from a rotary incremental encoder | ||
+ | // in " | ||
+ | // " | ||
+ | // clockwise increment) and 127 (counterclockwise decrrement). | ||
+ | | ||
+ | // I commonly use a Traktor Kontrol F1 which has its default (unshifted) | ||
+ | // encoder assigned to MIDI Control Channel 13 value 41 (hex BC 29 xx), | ||
+ | // so this script is pasted into the MIDI-to-PangoScript slot there. | ||
+ | // This controller also allows you to push the encoder down as a momentary | ||
+ | // button. I use this to reset the master cue speed to 100% on receiving | ||
+ | // value 63. On Traktor, you configure this value (and turn-relative mode) | ||
+ | // in the Controller Editor software. | ||
+ | | ||
+ | // This script also displays the current effect duration in beats on the | ||
+ | // MIDI contorller. The Traktor F1 has a 2-digit numeric display that I've | ||
+ | // configured to display values sent to it on the same MIDI channel. | ||
+ | | ||
+ | // To store the current duration between inputs, you must use a Global | ||
+ | // Variable. To set this up, paste the following (uncommented) in your | ||
+ | // MIDI Controller' | ||
+ | | ||
+ | // GLOBALVAR gCueSpeedFrac | ||
+ | // gCueSpeedFrac = 1.0 | ||
+ | | ||
+ | | ||
+ | var cueSpeedDelta | ||
+ | cueSpeedDelta = 0 | ||
+ | | ||
+ | // Scale incoming MIDI value to decr = -1, push = 0, incr = 1 | ||
+ | cueSpeedDelta = ExtValue(1, | ||
+ | | ||
+ | // Uncomment for debugging. Displays text on the laser preview window. | ||
+ | // DisplayPreview " | ||
+ | | ||
+ | if (cueSpeedDelta > 0.5) gCueSpeedFrac = gCueSpeedFrac * 2 // Knob incr | ||
+ | if (cueSpeedDelta < -0.5) gCueSpeedFrac = gCueSpeedFrac / 2 // Knob decr | ||
+ | if ((cueSpeedDelta >= -0.5) & (cueSpeedDelta <= 0.5)) gCueSpeedFrac = 1 // Knob push -> reset | ||
+ | if (gCueSpeedFrac > 17.0) gCueSpeedFrac = 16 | ||
+ | if (gCueSpeedFrac < .06) gCueSpeedFrac = .0625 | ||
+ | | ||
+ | // Uncomment for debugging: | ||
+ | // DisplayPreview " | ||
+ | | ||
+ | // Display beat duration (period) on a Kontrol F1 7-segment display. | ||
+ | // This assumes a default effect duration of 1 beat, so 50% speed runs FX | ||
+ | // for 2 beats, and the display will show " | ||
+ | // duration, but because there' | ||
+ | // leading period (.) indicator: " | ||
+ | | ||
+ | var cueSpeedDispVal | ||
+ | cueSpeedDispVal = 0 | ||
+ | cueSpeedDispVal = round(1.0 / gCueSpeedFrac) // .5 = 50%, display period of " | ||
+ | | ||
+ | // Display faster speeds over 100% as fractions of a beat. | ||
+ | // 102 = " | ||
+ | if (gCueSpeedFrac > 1.0) cueSpeedDispVal = 100 + round(gCueSpeedFrac) | ||
+ | MidiOutLong(0xBC, | ||
+ | | ||
+ | // Finally, set the actual cue speed. You may wish to use AnimationSpeed | ||
+ | // instead, or MasterFXSpeed to only speed up FX and not cues. | ||
+ | MasterCueSpeed 100 * gCueSpeedFrac | ||
+ | | ||
+ | exit | ||
+ | |||
+ | Takes a rotary incremental (relative mode) encoder on a MIDI controller, such as on a APC40mk2 or Traktor F1, and scale the metronome for beat-based effects in selected QuickFX rows to snap to a 2^X time scale multiplier. For example, if you've made effects with a 2 beat nominal duration, this lets you twist a knob and instantly change their duration to 2, 4, 8, or 16 beats (as well as 1, 1/2, 1/4, or 1/16th of a beat). | ||
+ | |||
+ | === Advance a QuickFX, toggling through multiple layers === | ||
+ | |||
+ | // Advance the currently running QuickFX from the color layers, | ||
+ | // which are layers 1 and 2 in many QuickFX layouts. | ||
+ | // Use this script in a MIDI-to-PangoScript slot. | ||
+ | | ||
+ | // As configured below, it will toggle advance through the first 24 colors | ||
+ | // in layer 1, then in layer 2, then back to layer one (including a state where both layers are off) | ||
+ | | ||
+ | // Scripts like this that store some state in a golbal variable should have | ||
+ | // that variable defined in the controller initialization script. Copy these these and uncomment: | ||
+ | // GLOBALVAR gColorFXIdx | ||
+ | // gColorFXIdx = 0 | ||
+ | | ||
+ | gColorFXIdx = gColorFXIdx + 1 // advance on MIDI trigger | ||
+ | gColorFXIdx = gColorFXIdx % 49 | ||
+ | | ||
+ | MidiOutLong(0xBC, | ||
+ | | ||
+ | if (gColorFXIdx > 24) GOTO Layer2 | ||
+ | | ||
+ | SetFX 2, 0 | ||
+ | SetFX 1, gColorFXIdx | ||
+ | | ||
+ | exit | ||
+ | | ||
+ | | ||
+ | Layer2: | ||
+ | | ||
+ | SetFX 1, 0 | ||
+ | SetFX 2, gColorFXIdx - 24 | ||
+ | | ||
+ | exit | ||
+ | |||
+ | Many workspaces keep the default scheme of having the first two QuickFX layers apply colors. On some compact MIDI controllers, | ||
+ | |||
+ | === Relative encoder for fine Channel adjustment === | ||
+ | |||
+ | // Fine control from a relative encoder | ||
+ | // Place this script in a MIDI-to-PangoScript slot. | ||
+ | // and be sure to change the channel number in several places below | ||
+ | | ||
+ | // Channels are displayed in the UI as 0 to 100 | ||
+ | // but can be set as 0-1000 values using ChannelOut | ||
+ | // Channel.< | ||
+ | VAR ChannelNumber, | ||
+ | ChannelNumber = 5 | ||
+ | ChVal = int(Channels.5.Value * 1000) | ||
+ | // | ||
+ | // | ||
+ | | ||
+ | VAR MidiVal | ||
+ | MidiVal = ExtValue(0, | ||
+ | DisplayPreview " | ||
+ | | ||
+ | if (MidiVal > 64) GOTO Incr | ||
+ | | ||
+ | if (ChVal <= 0) GOTO Done | ||
+ | ChannelOut ChannelNumber, | ||
+ | // | ||
+ | GOTO Done | ||
+ | | ||
+ | Incr: | ||
+ | if (ChVal >= 1000) GOTO Done | ||
+ | ChannelOut ChannelNumber, | ||
+ | // | ||
+ | | ||
+ | Done: | ||
+ | // | ||
+ | |||
+ | Beyond channels show up as values between 0 and 100 in the Channels tab, but are internally stored as a normalized 0..1 float. This makes them useful tools for linking to any parameter that takes an input. Sometimes you want much finer control over a parameter than 127 values from MIDI (and few controllers support 14-bit MSB+LSB). You may have experienced this when linking MIDI controllers to Z rotation - it's steppy and I've resorted to enabling physics to dampen the motion which helps a little but is still imprecise. I was recently preparring for a film shoot where I needed fine control over some large value ranges (precise points counts in a resampler to help tune rolling shutter banding). By configuring my rotary encoder to send incremental up/down values, you can route it to parameter inputs through Channels using arbitrary fine resolution using the internal float value. | ||
+ | |||
+ | === Select Groups mode Destination cues from APC40 mkii Track/Clip Stop buttons === | ||
+ | |||
+ | // Activate a Destination cue (Groups) on APC40 mk2's Track Select button or Clip Stop button | ||
+ | | ||
+ | // Requires GlobalVar lastDestinationCueNumber - Define these in the controller init scripts! | ||
+ | // GlobalVar lastDestinationCueNumber | ||
+ | // lastDestinationCueNumber = 0 | ||
+ | | ||
+ | // For this script, Destination Cues page MUST be in page 1 of the whole workspace | ||
+ | // Select a desitnation cue; CueDown is the only trigger possible -- MouseDown doesn' | ||
+ | // Cancel all other track and clip stop indicator LEDs | ||
+ | // Illuminate the correct light | ||
+ | // Handle if a destination cue was clicked again by holding internal state | ||
+ | | ||
+ | // You must set this correctly for each button you add this script to | ||
+ | Var destinationCueNumber | ||
+ | destinationCueNumber = 1 | ||
+ | | ||
+ | Var isSecondRow | ||
+ | isSecondRow = (destinationCueNumber > 8) & (destinationCueNumber <=16) | ||
+ | | ||
+ | // StartCue doesn' | ||
+ | CueDown 1, destinationCueNumber // Page 1 must be " | ||
+ | | ||
+ | // Turn off all lights in this group | ||
+ | // Using a loop was too slow for the device or PangoScript. :-/ | ||
+ | MidiOut 0x90, 0x33, 0x00 | ||
+ | MidiOut 0x91, 0x33, 0x00 | ||
+ | MidiOut 0x92, 0x33, 0x00 | ||
+ | MidiOut 0x93, 0x33, 0x00 | ||
+ | MidiOut 0x94, 0x33, 0x00 | ||
+ | MidiOut 0x95, 0x33, 0x00 | ||
+ | MidiOut 0x96, 0x33, 0x00 | ||
+ | MidiOut 0x97, 0x33, 0x00 | ||
+ | | ||
+ | MidiOut 0x90, 0x34, 0x00 | ||
+ | MidiOut 0x91, 0x34, 0x00 | ||
+ | MidiOut 0x92, 0x34, 0x00 | ||
+ | MidiOut 0x93, 0x34, 0x00 | ||
+ | MidiOut 0x94, 0x34, 0x00 | ||
+ | MidiOut 0x95, 0x34, 0x00 | ||
+ | MidiOut 0x96, 0x34, 0x00 | ||
+ | MidiOut 0x97, 0x34, 0x00 | ||
+ | | ||
+ | | ||
+ | // Turn on this button' | ||
+ | MidiOut 0x90 + ((destinationCueNumber - 1) % 8), 0x33 + isSecondRow, | ||
+ | light | ||
+ | | ||
+ | // Handle repeat press of same cue | ||
+ | if (lastDestinationCueNumber = destinationCueNumber) Goto ToggleThisDestination | ||
+ | | ||
+ | destinationPlaying = 1 // Global. A new destination was clicked, so it's playing | ||
+ | | ||
+ | Goto FinishUp | ||
+ | | ||
+ | | ||
+ | ToggleThisDestination: | ||
+ | destinationPlaying = 1 - destinationPlaying // global | ||
+ | if (destinationPlaying = 0) MidiOut 0x90 + ((destinationCueNumber - 1) % 8), 0x33 + isSecondRow, | ||
+ | | ||
+ | FinishUp: | ||
+ | lastDestinationCueNumber = destinationCueNumber | ||
+ | |||
+ | I like Groups mode, though it still has several bugs around destination/ | ||
---- | ---- | ||
[[guided-learning: | [[guided-learning: | ||
+ | |||
+ |