This script allows you to program a 4-bar chord progression, such that when MIDI input happens, only desired tones are sent "as played". When any other tone is played, the note is replaced by a random selection from an array of note choices. You can use as many tones in either pool of notes as you want. This was an effort to make me a "better" piano player than I actually am by limiting the number of errors I can make.
The sample below is an arpreggiator sending the MIDI stream using one of the stock cycles and holding down an E for 32 bars.
Enjoy.
//needed for GetTimingInfo() to work
var NeedsTimingInfo = true;
//Array of tones to let through as played
var randomNotes;
//Array of tones for other keys
var passThroughTones;
//returns current Bar number based off current beat and time signature denominator
function getBarNumber(beat, sigDenominator) {
var currentBar;
if (beat < (sigDenominator + 1)) {
return 1;
} else {
return Math.ceil(beat / sigDenominator);
}
}
//Code for setting the chord tones and random tones depending on which bar you are in
function ProcessMIDI() {
var info = GetTimingInfo(); //get the timing info from the host
var bar;
var beat;
//set default pass through notes
passThroughTones = new Array('E', 'G#', 'B');
//set default random notes
randomNotes = new Array('C#5', 'E2', 'D#6', 'G#6', 'B4', 'C#6', 'E3');
//if the transport is playing
if (info.playing) {
//get integer value for beat number
beat = Math.floor(info.blockStartBeat);
//find bar number
bar = getBarNumber(beat, 4);
}
//Set different tones for each bar of a 4-bar progression which repeats for 32 bars
if (bar == 2 || bar == 6 || bar == 10 || bar == 14 || bar == 18 || bar == 22 || bar == 26 || bar == 30) {
//change Random Notes for second bar of 4-bar progression
randomNotes = new Array('C4', 'E2', 'D4', 'G3', 'B4', 'C4', 'E3');
//Set pass through tones for second bar of 4-bar progression
passThroughTones = new Array('E', 'G', 'B');
}
if (bar == 3 || bar == 7 || bar == 11 || bar == 15 || bar == 19 || bar == 23 || bar == 27 || bar == 31) {
//change Random Notes for third bar of progression
randomNotes = new Array('B4', 'D2', 'A4', 'F#3', 'A4', 'B4', 'D3');
//change pass through tones
passThroughTones = new Array('D', 'F#', 'A');
}
if (bar == 4 || bar == 8 || bar == 12 || bar == 16 || bar == 20 || bar == 24 || bar == 28 || bar == 32) {
//change Random Notes for fourth bar of progression
randomNotes = new Array('D4', 'C2', 'G#4', 'E3', 'G4', 'D4', 'C3');
//change pass through tones
passThroughTones = new Array('C', 'E', 'G');
}
}
function HandleMIDI(event) {
//store pitch name for event
var pitchName = MIDI.noteName(event.pitch);
//if it is a NoteOn event, evaluate whether to pass-through or randomize
if (event instanceof NoteOn) {
if (shouldPassThrough(MIDI.noteName(event.pitch))) {
event.send();
}
else {
//get a random number
event.pitch = MIDI.noteNumber(randomNotes[(getRandomInt(1, randomNotes.length) - 1)]);
event.send();
}
}
else {
event.send();
}
}
function shouldPassThrough (noteName) {
//Code to look for match with pass through tones
for(var i=0; i < passThroughTones.length; i++)
{
if (noteName.indexOf(passThroughTones[i]) == 0){return true;}
}
return false;
}
//generate random integer between two numbers
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}