Poor man's clip launching keyboard - generic script for launching clips from a set of notes

Post Reply New Topic
RELATED
PRODUCTS

Post

Hello there,

I've been thinking about getting one of those grid controllers, but I really can't afford one right now. At least not one of the more fancier ones, anyway. A poor guy like myself, I need to make do with what I got and so I thought I'd make use of my keyboard for launching clips. Well, perhaps not so much for launching, but for recording.

So I came up with a script for the purpose.

It's enabled from the Studio I/O panel and when it's on, notes from C0 to G0 are reserved for selecting clips (eight of them) of the currently selected track. F#0 starts playing the selected clip, or if there's no content, it will start recording to it. A0 starts recording and A#0 stops the clip from playing. Since it takes up nearly an octave and I need to transpose on my keyboard to reach that 0 octave, there's settings in the Studio I/O panel to transpose the notes that do get through, either down an octave or up one or two octaves. This saves the hassle of putting a Note Pitch Shifter as the first device in the track. Transposition is disabled if the clip launcher functionality is disabled.

It works best with setting up the post recording actions first, for example to start playing back after an appropriate period of recording.

Here's what it looks right now. It's part of the larger script that I've made for my keyboard, but the one I'm providing here is a more generic variety. If you save it and put it in your controller script folder, you'll find it under the Generic folder under the controller settings in the Preferences. Make "Poor man's clip launching keyboard" your input device and you should be good to go.

Code: Select all

loadAPI(1);

host.defineController("Generic", "Poor man's clip launching keyboard", "0.02", "5b7f3500-3815-4c0b-8bbd-2746a479ecec");
host.defineMidiPorts(1, 0);

var clipNotes = [24, 34]; // notes from C0 to A#0 are reserved for the clip launcher functionality
// these tables are used for enabling/disabling the clip launcher functionality and for transposing the keyboard input
var minusTable = []; var minusTableOctDown = []; var minusTableOct1 = []; var minusTableOct2 = []; var regularTable = [];
// 128 items, values from 0..127
for (i=0; i<128; i++) { regularTable.push(i); minusTableOctDown.push(i); minusTable.push(i); minusTableOct1.push(i); minusTableOct2.push(i); };
// items in range of the clipNotes are set to -1, this will disable them
for (i=clipNotes[0]; i <= clipNotes[1]; i++) { minusTable[i] = -1; minusTableOctDown[i] = -1; minusTableOct1[i] = -1; minusTableOct2[i] = -1; }; 
// transpose everything above the last clip launcher note
for (i=clipNotes[1]; i <= 127; i++) { minusTableOct1[i] = (i+12); minusTableOct2[i] = (i+24); }; // up one and two octaves
for (i=clipNotes[1]; i <= 127; i++) { minusTableOctDown[i] = (i-12); }; // down an octave
// truncate at the end of the key range so that we don't go above MIDI specs
for (i=115; i <= 127; i++) { minusTableOct1[i] = 127; };
for (i=103; i <= 127; i++) { minusTableOct2[i] = 127; }; 

var _clipIndex = ''; var _poorMan = true; // script's internal variables

function init() {
   host.getMidiInPort(0).setMidiCallback(onMidi);
   host.getMidiInPort(0).setSysexCallback(onSysex);
   generic = host.getMidiInPort(0).createNoteInput("", "??????");
   generic.setShouldConsumeEvents(false);
   cursorTrack = host.createCursorTrack(4,8); // cursor track with 4 sends and 8 clips

   doc = host.getDocumentState(); // document settings available in the Studio I/O panel
   poorMan = doc.getEnumSetting("Poor man", "", ["True-born", "Not really"], "True-born");
   poorMan.addValueObserver(function (value) {
      if (value == "True-born") { // enable the clip launcher functionality
         _poorMan = true;
         generic.setKeyTranslationTable(minusTable);
         transposition.enable(); // activating the clip launcher functionality enables transposition
      }
      else { // disable the clip launcher functionality and function like a regular keyboard
         _poorMan = false;
         generic.setKeyTranslationTable(regularTable);
         transposition.disable(); // won't transpose if it's working like a regular keyboard
      }
   });
   transposition = doc.getEnumSetting("Transpose", "", ["-1", "0", "+1", "+2"], "0");
   transposition.addValueObserver(function (value) {
         if (_poorMan) {
            if (value == "0") { generic.setKeyTranslationTable(minusTable); } // don't transpose
            else if (value == "-1") { generic.setKeyTranslationTable(minusTableOctDown); } // transpose down an octave
            else if (value == "+1") { generic.setKeyTranslationTable(minusTableOct1); } // up an octave
            else if (value == "+2") { generic.setKeyTranslationTable(minusTableOct2); } // up two octaves
         }
   });
   poorManClips = cursorTrack.getClipLauncherSlots();
   // _clipIndex always points to the index of the cursor track's selected clip
   poorManClips.addIsSelectedObserver(function(clipIndex, selected) { if (selected) {_clipIndex = clipIndex; } });
}

function onMidi(status, data1, data2) {
   if (isNoteOn(status) && _poorMan) {
        switch(data1) {
            case 24: poorManClips.select(0); break; // C0 -> clip 1
            case 25: poorManClips.select(1); break; // C#0
            case 26: poorManClips.select(2); break; // D0
            case 27: poorManClips.select(3); break; // D#0
            case 28: poorManClips.select(4); break; // E0
            case 29: poorManClips.select(5); break; // F0
            case 30: poorManClips.select(6); break; // F#0
            case 31: poorManClips.select(7); break; // G0 -> clip 8
            case 32: poorManClips.launch(_clipIndex); break; // G#0 -> launch clip or if the slot is empty, start recording
            case 33: poorManClips.record(_clipIndex); break; // A0 -> record to selected clip
            case 34: poorManClips.stop(); break; // A#0 -> stop the clip
        }
    }
}

function onSysex(data) {
}

function exit()
{
}
Effectively, it creates a keyboard split in which you got one octave on the left hand side for controlling clips and the rest of the keyboard available for playing. Pretty quick to get around, since the hands are on the keys already.

It's rather gimmicky, to be honest. Especially the dance around the translation table variables at the top of the script. I'll eventually nick someone's proper copy function to make deep copies of the variables, but it works for now. Right now it doesn't have a function to delete the selected clip (mainly because I'm rather fond of my B0 key) but it's not difficult to add that.

I suppose it's a good start for someone who wants to disable a set of notes from their keyboard and do something else with those than use them for input, or if you want to transpose a set of notes, that's in there too.

The script is also attached to this post, download below.
You do not have the required permissions to view the files attached to this post.

Post Reply

Return to “Controller Scripting”