Source: controllers/ScoreController.js

/** @constructor */
MusicXMLAnalyzer.ScoreController = function(){

	var that = {},

	view = null,
	once = true,
	once2 = true,
	stop = false,
	tonika = { 'C':0, 'D':2, 'E':4, 'F':5, 'G':7, 'A':9, 'B':11 },
	$scoreValue = null,
	scoreData = null,

	/**
	 * Init method of ScoreController
	 * @function
     * @public
	 */
	init = function() {
		console.info("MusicXMLAnalyzer.ScoreController.init");
		view = MusicXMLAnalyzer.ScoreView();
		view.init();

		$scoreValue = $('#scoreValue');

		MIDI.loadPlugin({
			soundfontUrl: "../../libs/midijs/soundfont/",
			instrument: "acoustic_grand_piano",
			callback: function() {
			}
		});

		$playScore = $('#playScore');
		$stopScore = $('#stopScore');	

		$stopScore.prop('disabled', true);

		$playScore.click(function(){
			stop = false;
			once2 = true;
			once = true;
			playScore();
			$playScore.prop('disabled', true);
			$stopScore.prop('disabled', false);
		});

		$stopScore.click(function(){
			stop = true;
			$playScore.prop('disabled', false);
			$stopScore.prop('disabled', true);
		});

	}, //end init

	/**
	 * Function to get Duration of Notes
	 * @function
     * @public
	 *
	 * @param 	{string} 	type 	The note type
	 *
	 * @retrun 	{float} 	The duration of the note as float
	 */
	getDuration = function(type){
		var duration;

		if (type == "whole"){
			duration = 1;
		} else if (type === "half") {
			duration = 0.5;
		} else if (type === "quarter") {
			duration = 0.25;
		} else if (type === "eighth") {
			duration = 0.125;
		} else if (type === "16th") {
			duration = 0.0625;
		} else if (type === "32nd") {
			duration = 0.03125;
		} else if (type === "64th") {
			duration = 0.015625;
		}

		return duration;
	},

		/**
	 * Method to get MIDI-Values
	 * @function
     * @public
	 *
	 * @param 	{string} 	step 	The note step
	 * @param 	{string} 	octave 	The notes octave
	 * @param 	{string} 	alter 	The alter value
	 *
	 * @return 	{number} 	The MIDI value
	 */
	getMidiValue = function(step, octave, alter) {
		return (parseInt(octave) * 12) + (tonika[step] + parseInt(alter));
	},

	/**
	* Method to play the created Pattern
	 * @function
     * @public
	*/
	playScore = function() {
		var notesToBePlayed = [];

		//get notes of current score part:
		// var currentPatternNotes = patternModel.getAllNoteElements();
		scoreData = JSON.parse($scoreValue.val());

		MIDI.setVolume(0, 127);

		//determine MIDI values for scoreData
		for(var i = 0; i < scoreData.measures.length; i++){
			for(var j = 0; j < scoreData.measures[i].notes.length; j++){
				// check if rest
				if(scoreData.measures[i].notes[j].type === 'rest'){
					var rest = scoreData.measures[i].notes[j];
					var restDuration = getDuration(scoreData.measures[i].notes[j].duration);
					notesToBePlayed.push({'note': 0, 'noteDuration': restDuration});
				}
				else if(scoreData.measures[i].notes[j].type === 'note'){
					var note = scoreData.measures[i].notes[j];
					var noteDuration = (getDuration(note.pitch.type) !== undefined ? getDuration(note.pitch.type) : 0.25);
					var noteStep = (note.pitch.step !== undefined ? note.pitch.step : 'C');
					var noteOctave = (note.pitch.octave !== undefined ? note.pitch.octave : 4);
					var noteAlter = (note.pitch.alter !== undefined ? note.pitch.alter : 0);
					var noteBeam = (note.pitch.beam !== undefined ? note.pitch.beam : false);

					if (note.pitch.dot) {
						noteDuration += 0.5 * noteDuration;
					}

					var midiNote = getMidiValue(noteStep, noteOctave, noteAlter);
					notesToBePlayed.push({'note': midiNote, 'noteDuration': noteDuration, 'noteBeam' : noteBeam});
				}
			}
		}

		i = 0;
		var playTune = function() {

			if(i < notesToBePlayed.length){
				var note = notesToBePlayed[i].note;
				// how hard the note gets hit
				var velocity = 100;
				// delay is set to fix value
				var delay = 0;
				var timeout = 0;
				if(!once){
					timeout = notesToBePlayed[i-1].noteDuration*2000;
					if(notesToBePlayed[i-1].noteBeam === "begin" || notesToBePlayed[i-1].noteBeam === "continue" ||
						notesToBePlayed[i-1].noteBeam === "end") {
						timeout = (timeout * 2) / 3;
					}
				}
				once = false;

				setTimeout(function(){
					if(stop){
						i = notesToBePlayed.length;
					}
					else{
						if(i === notesToBePlayed.length -1){
								MIDI.noteOn(0, note, velocity, delay);
								MIDI.noteOff(0, note, delay + 0.75);
						}
						else{
							MIDI.noteOn(0, note, velocity, delay);
							MIDI.noteOff(0, note, delay + 0.75);
						}
						i++;
					}
					// recursively call playTune()
					playTune();
				 }, timeout);
			}
			// else when finished - reset play&stop buttons after 1.5 sec
			else{
				setTimeout(function(){

					$playScore.prop('disabled', false);
					$stopScore.prop('disabled', true);
				}, 1500);
			}
		};
		if(once2){
			once2 = false;
			playTune();
		}
	};

	that.init = init;

	return that;
}