Pilcrow Records

Scripter Javascript Tutorial

javascriptmusiclogicscripterbookexcerpttutorial

85 Use Global Variables Sparingly

In Scripter, any variable called outside of any function is in the global space, which means it can be called from anywhere else in the script. This can be very convenient, but it also means that how a global variable is being used may not be clear while in the code contained in a function. Obviously, there are variables which need to be global, like the PluginParameters array and NeedsTimingInfo boolean used by Scripter, and there are aspects to music which are universally true no matter the context, like Middle C. But in order to keep that context of how a variable is being used, it should be managed in the same scope of the code block where it is being used. Global variables help in the following situations:

When data needs to be tracked across instances of the HandleMIDI() and ProcessMIDI() functions as the playhead moves:

var NeedsTimingInfo = true;

var activeNotes = [];
var lastBlockStart;

function HandleMIDI( event ) {
	if ( event instanceof NoteOn ) { 
		activeNotes.push( event );
	} else if ( event instanceof NoteOff ) {
		// remove the note from activeNotes
	}
}

function ProcessMIDI() {
	var timingInfo = GetTimingInfo();

	if ( timingInfo.playing ) {
		var currBlockStart = Math.floor(timingInfo.blockStartBeat);
		if (  currBlockStart != lastBlockStart \&\& 
		( currBlockStart <= 1 || currBlockStart \% timingInfo.meterNumerator == 0 ) ) {  			
			Trace(lastBlockStart + " - " + currBlockStart)
		}
}

In the above example, two custom (non-Scripter) variables are tracked: activeNotes and lastBlockStart. activeNotes is used to track what notes are currently playing, so it needs to be tracked across HandleMIDI() calls by Scripter. lastBlockStart is tracking the last process block start to help calculate when the playhead has entered a new bar. Both of those variables are created outside of those two functions so they can be maintained between calls. All of the other variables needed for these situations are in their respective function’s scope.

When data is about a defining characteristic of music which never changes, like Middle C, or the minimum and maximum values for MIDI, creating global constants is very helpful, especially when creating self-documenting code:

const MIDDLE_C = 60;
const MIDI_PITCH_MIN = 0;
const MIDI_PITCH_MAX = 127;