Pilcrow Records

Scripter Javascript Tutorial

javascriptmusiclogicscripterbookexcerpttutorial

90 Using Functions For Long or Complicated Code

In the following example, the code is very easy to read, but lines 19–20 are challenging to read. Sometimes that’s just the way code works out, and that it’s painful to read compared to the rest of the code is actually a good thing because it means the rest of the code is well-developed.

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)
		}
}

For large or complicated test or code blocks, a function can be used to manage readability:

function ProcessMIDI() {

	// get the current position of the cursor and project play state
	var timingInfo = GetTimingInfo();

	if ( timingInfo.playing ) {
		var currBlockStart = Math.floor( timingInfo.blockStartBeat );
		if (  inNewBar( timingInfo ) ) {  			
			Trace( lastBlockStart + " - " + currBlockStart )
		}
}

function inNewBar( timingInfo ) {
	if (  currBlockStart != lastBlockStart \&\& 
		( currBlockStart <= 1 || 
		currBlockStart \% timingInfo.meterNumerator == 0 ) 
	) {
		return true;
	}
	return false;
}

The structure of the big Bar test has not changed, and it won’t change unless Apple decides to change the TimingInfo object’s structure or how timing information is specified. So, the calculation is put into its own function which makes the actual use of it as simple as a single function call and not multiple comparisons. Any context needed to work on that part of the code is already provided by the name of the function and the fact that timingInfo is passed into it.