freakimkaefig/Music-XML-Analyzer

View on GitHub
public/js/controllers/ScoreController.js

Summary

Maintainability
F
5 days
Test Coverage
/** @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;
}