BACK

Description

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.

Hear the sample here

The Script


	//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;
	}