|
|
- // Copyright (c) 2014-2017 Walter Bender
- // Copyright (c) 2015 Yash Khandelwal
- //
- // This program is free software; you can redistribute it and/or
- // modify it under the terms of the The GNU Affero General Public
- // License as published by the Free Software Foundation; either
- // version 3 of the License, or (at your option) any later version.
- //
- // You should have received a copy of the GNU Affero General Public
- // License along with this library; if not, write to the Free Software
- // Foundation, 51 Franklin Street, Suite 500 Boston, MA 02110-1335 USA
-
- const DEFAULTVOLUME = 50;
- const TONEBPM = 240; // Seems to be the default.
- const TARGETBPM = 90; // What we'd like to use for beats per minute
- const DEFAULTDELAY = 500; // milleseconds
- const TURTLESTEP = -1; // Run in step-by-step mode
- const NOTEDIV = 8; // Number of steps to divide turtle graphics
- const OSCVOLUMEADJUSTMENT = 1.5 // The oscillator runs hot. We need
- // to scale back its volume.
-
- const NOMICERRORMSG = 'The microphone is not available.';
- const NANERRORMSG = 'Not a number.';
- const NOSTRINGERRORMSG = 'Not a string.';
- const NOBOXERRORMSG = 'Cannot find box';
- const NOACTIONERRORMSG = 'Cannot find action.';
- const NOINPUTERRORMSG = 'Missing argument.';
- const NOSQRTERRORMSG = 'Cannot take square root of negative number.';
- const ZERODIVIDEERRORMSG = 'Cannot divide by zero.';
- const EMPTYHEAPERRORMSG = 'empty heap.';
- const INVALIDPITCH = 'Not a valid pitch name';
- const POSNUMBER = 'Argument must be a positive number';
-
- function Logo () {
- this.canvas = null;
- this.blocks = null;
- this.turtles = null;
- this.stage = null;
- this.refreshCanvas = null;
- this.textMsg = null;
- this.errorMsg = null;
- this.hideMsgs = null;
- this.onStopTurtle = null;
- this.onRunTurtle = null;
- this.getStageX = null;
- this.getStageY = null;
- this.getStageMouseDown = null;
- this.getCurrentKeyCode = null;
- this.clearCurrentKeyCode = null;
- this.meSpeak = null;
- this.saveLocally = null;
-
- this.pitchTimeMatrix = null;
- this.pitchDrumMatrix = null;
- this.rhythmRuler = null;
- this.pitchStaircase = null;
- this.tempo = null;
- this.pitchSlider = null;
- this.modeWidget = null;
- this.statusMatrix = null;
-
- this.evalFlowDict = {};
- this.evalArgDict = {};
- this.evalParameterDict = {};
- this.evalSetterDict = {};
- this.evalOnStartList = {};
- this.evalOnStopList = {};
- this.eventList = {};
-
- this.boxes = {};
- this.actions = {};
- this.returns = [];
- this.turtleHeaps = {};
- this.invertList = {};
-
- // When we leave a clamp block, we need to dispatch a signal.
- this.endOfClampSignals = {};
-
- this.time = 0;
- this.firstNoteTime = null;
- this.waitTimes = {};
- this.turtleDelay = 0;
- this.sounds = [];
- this.cameraID = null;
- this.stopTurtle = false;
- this.lastKeyCode = null;
- this.saveTimeout = 0;
-
- // Music-related attributes
- this.notesPlayed = {};
-
- // pitch-drum matrix
- this.showPitchDrumMatrix = false;
- this.inPitchDrumMatrix = false;
-
- //rhythm-ruler
- this.inRhythmRuler = false;
- this.rhythmRulerMeasure = null;
-
- this.inPitchStaircase = false;
-
- this.inTempo = false;
-
- this.inPitchSlider = false;
-
- this._currentDrumBlock = null;
-
- // pitch-rhythm matrix
- this.inMatrix = false;
- this.keySignature = {};
- this.tupletRhythms = [];
- this.addingNotesToTuplet = false;
- this.drumBlocks = [];
- this.pitchBlocks = [];
- this.inNoteBlock = [];
- this.whichNoteBlock = [];
-
- // parameters used by pitch
- this.transposition = {};
-
- // parameters used by notes
- this._masterBPM = TARGETBPM;
- this.defaultBPMFactor = TONEBPM / this._masterBPM;
-
- this.beatFactor = {};
- this.dotCount = {};
- this.noteBeat = {};
- this.oscList = {};
- this.noteDrums = {};
- this.notePitches = {};
- this.noteOctaves = {};
- this.noteCents = {};
- this.noteHertz = {};
- this.noteTranspositions = {};
- this.noteBeatValues = {};
-
- this.lastNotePlayed = {};
- this.noteStatus = {};
-
- this.pitchNumberOffset = 39; // C4
-
- // graphics listeners during note play
- this.forwardListener = {};
- this.rightListener = {};
- this.arcListener = {};
-
- // status of note being played
- // Deprecated (ref lastNotePlayed)
- this.currentNotes = {};
- this.currentOctaves = {};
-
- // parameters used by the note block
- this.bpm = {};
- this.turtleTime = [];
- this.noteDelay = 0;
- this.playedNote = {};
- this.playedNoteTimes = {};
- this.pushedNote = {};
- this.duplicateFactor = {};
- this.skipFactor = {};
- this.skipIndex = {};
- this.crescendoDelta = {};
- this.crescendoVolume = {};
- this.crescendoInitialVolume = {};
- this.intervals = {};
- this.perfect = {};
- this.diminished = {};
- this.augmented = {};
- this.major = {};
- this.minor = {};
- this.staccato = {};
- this.swing = {};
- this.swingTarget = {};
- this.swingCarryOver = {};
- this.tie = {};
- this.tieNote = {};
- this.tieCarryOver = {};
- this.polyVolume = {};
- this.validNote = true;
- this.drift = {};
- this.drumStyle = {};
- this.voices = {};
- this.backward = {};
- this.vibratoIntensity = {};
- this.vibratoRate = {};
- this.justCounting = {};
- // When counting notes or generating lilypond output...
- this.suppressOutput = {};
-
- // scale factor for turtle graphics embedded in notes
- this.dispatchFactor = {};
-
- // tuplet
- this.tuplet = false;
- this.tupletParams = [];
-
- // pitch to drum mapping
- this.pitchDrumTable = {};
-
- // parameters used by notations
- this.checkingLilypond = false;
- this.checkingLilypond = false;
- this.lilypondNotes = {};
- this.lilypondStaging = {};
- this.lilypondOutput = getLilypondHeader();
- this.runningLilypond = false;
- this.numerator = 3;
- this.denominator = 4;
-
- if (_THIS_IS_MUSIC_BLOCKS_) {
- // Load the default synthesizer
- this.synth = new Synth();
- this.synth.loadSynth('poly');
- } else {
- this.turtleOscs = {};
- }
-
- // Mode widget
- this._modeBlock = null;
-
- // Status matrix
- this.inStatusMatrix = false;
- this.updatingStatusMatrix = false;
- this.statusFields = [];
-
- // When running in step-by-step mode, the next command to run is
- // queued here.
- this.stepQueue = {};
- this.unhighlightStepQueue = {};
-
- // Control points for bezier curves
- this.cp1x = {};
- this.cp1y = {};
- this.cp2x = {};
- this.cp2y = {};
-
- this.svgOutput = '';
- this.svgBackground = true;
-
- if (_THIS_IS_MUSIC_BLOCKS_) {
- this.mic = new Tone.UserMedia();
- this.limit = 1024;
- this.analyser = new Tone.Analyser({
- "type" : "waveform",
- "size" : this.limit
- });
- this.mic.connect(this.analyser);
- } else {
- try {
- this.mic = new p5.AudioIn()
- } catch (e) {
- console.log(e);
- console.log(NOMICERRORMSG);
- this.mic = null;
- }
- }
-
- this.setCanvas = function (canvas) {
- this.canvas = canvas;
- return this;
- };
-
- this.setBlocks = function (blocks) {
- this.blocks = blocks;
- return this;
- };
-
- this.setTurtles = function (turtles) {
- this.turtles = turtles;
- return this;
- };
-
- this.setStage = function (stage) {
- this.stage = stage;
- return this;
- };
-
- this.setRefreshCanvas = function (refreshCanvas) {
- this.refreshCanvas = refreshCanvas;
- return this;
- };
-
- this.setTextMsg = function (textMsg) {
- this.textMsg = textMsg;
- return this;
- };
-
- this.setHideMsgs = function (hideMsgs) {
- this.hideMsgs = hideMsgs;
- return this;
- };
-
- this.setErrorMsg = function (errorMsg) {
- this.errorMsg = errorMsg;
- return this;
- };
-
- this.setOnStopTurtle = function (onStopTurtle) {
- this.onStopTurtle = onStopTurtle;
- return this;
- };
-
- this.setOnRunTurtle = function (onRunTurtle) {
- this.onRunTurtle = onRunTurtle;
- return this;
- };
-
- this.setGetStageX = function (getStageX) {
- this.getStageX = getStageX;
- return this;
- };
-
- this.setGetStageY = function (getStageY) {
- this.getStageY = getStageY;
- return this;
- };
-
- this.setGetStageMouseDown = function (getStageMouseDown) {
- this.getStageMouseDown = getStageMouseDown;
- return this;
- };
-
- this.setGetCurrentKeyCode = function (getCurrentKeyCode) {
- this.getCurrentKeyCode = getCurrentKeyCode;
- return this;
- };
-
- this.setClearCurrentKeyCode = function (clearCurrentKeyCode) {
- this.clearCurrentKeyCode = clearCurrentKeyCode;
- return this;
- };
-
- this.setMeSpeak = function (meSpeak) {
- this.meSpeak = meSpeak;
- return this;
- };
-
- this.setSaveLocally = function (saveLocally) {
- this.saveLocally = saveLocally;
- return this;
- };
-
- // Used to pause between each block as the program executes.
- this.setTurtleDelay = function (turtleDelay) {
- this.turtleDelay = turtleDelay;
- this.noteDelay = 0;
- };
-
- // Used to pause between each note as the program executes.
- this.setNoteDelay = function (noteDelay) {
- this.noteDelay = noteDelay;
- this.turtleDelay = 0;
- };
-
- this.step = function () {
- // Take one step for each turtle in excuting Logo commands.
- for (var turtle in this.stepQueue) {
- if (this.stepQueue[turtle].length > 0) {
- if (turtle in this.unhighlightStepQueue && this.unhighlightStepQueue[turtle] != null) {
- if (this.blocks.visible) {
- this.blocks.unhighlight(this.unhighlightStepQueue[turtle]);
- }
- this.unhighlightStepQueue[turtle] = null;
- }
- var blk = this.stepQueue[turtle].pop();
- if (blk != null) {
- this._runFromBlockNow(this, turtle, blk, 0, null);
- }
- }
- }
- };
-
- this.stepNote = function () {
- // Step through one note for each turtle in excuting Logo
- // commands, but run through other blocks at full speed.
- var tempStepQueue = {};
- var notesFinish = {};
- var thisNote = {};
- var that = this;
- __stepNote();
-
- function __stepNote() {
- for (var turtle in that.stepQueue) {
- // Have we already played a note for this turtle?
- if (turtle in that.playedNote && that.playedNote[turtle]) {
- continue;
- }
- if (that.stepQueue[turtle].length > 0) {
- if (turtle in that.unhighlightStepQueue && that.unhighlightStepQueue[turtle] != null) {
- if (that.blocks.visible) {
- that.blocks.unhighlight(that.unhighlightStepQueue[turtle]);
- }
- that.unhighlightStepQueue[turtle] = null;
- }
- var blk = that.stepQueue[turtle].pop();
- if (blk != null && blk !== notesFinish[turtle]) {
- var block = that.blocks.blockList[blk];
- if (block.name === 'newnote') {
- tempStepQueue[turtle] = blk;
- notesFinish[turtle] = last(block.connections);
- if (notesFinish[turtle] == null) { // end of flow
- notesFinish[turtle] = last(that.turtles.turtleList[turtle].queue) && last(that.turtles.turtleList[turtle].queue).blk;
- // catch case of null - end of project
- }
- // that.playedNote[turtle] = true;
- that.playedNoteTimes[turtle] = that.playedNoteTimes[turtle] || 0;
- thisNote[turtle] = Math.pow(that.parseArg(that, turtle, block.connections[1], blk, null), -1);
- that.playedNoteTimes[turtle] += thisNote[turtle];
- // Keep track of how long the note played for, so we can go back and play it again if needed
- }
- that._runFromBlockNow(that, turtle, blk, 0, null);
- } else {
- that.playedNote[turtle] = true;
- }
- }
- }
-
- // At this point, some turtles have played notes and others
- // have not. We need to keep stepping until they all have.
- var keepGoing = false;
- for (var turtle in that.stepQueue) {
- if (that.stepQueue[turtle].length > 0 && !that.playedNote[turtle]) {
- keepGoing = true;
- break;
- }
- }
- if (keepGoing) {
- __stepNote();
- // that.step();
- } else {
- var notesArray = [];
- for (var turtle in that.playedNote) {
- that.playedNote[turtle] = false;
- notesArray.push(that.playedNoteTimes[turtle]);
- }
-
- // If some notes are supposed to play for longer, add
- // them back to the queue
- var shortestNote = Math.min.apply(null, notesArray);
- var continueFrom;
- for (var turtle in that.playedNoteTimes) {
- if (that.playedNoteTimes[turtle] > shortestNote) {
- continueFrom = tempStepQueue[turtle];
- // Subtract the time, as if we haven't played it yet
- that.playedNoteTimes[turtle] -= thisNote[turtle];
- } else {
- continueFrom = notesFinish[turtle];
- }
- that._runFromBlock(that, turtle, continueFrom, 0, null);
- }
- if (shortestNote === Math.max.apply(null, notesArray)) {
- that.playedNoteTimes = {};
- }
- }
- };
- };
-
- this.doStopTurtle = function () {
- // The stop button was pressed. Stop the turtle and clean up a
- // few odds and ends.
- this.stopTurtle = true;
- this.turtles.markAsStopped();
-
- for (var sound in this.sounds) {
- this.sounds[sound].stop();
- }
- this.sounds = [];
-
- if (_THIS_IS_MUSIC_BLOCKS_) {
- this.synth.stopSound('default');
- this.synth.stop();
- }
-
- if (this.cameraID != null) {
- doStopVideoCam(this.cameraID, this.setCameraID);
- }
-
- this.onStopTurtle();
- this.blocks.bringToTop();
-
- this.stepQueue = {};
- this.unhighlightQueue = {};
- };
-
- this._clearParameterBlocks = function () {
- for (var blk in this.blocks.blockList) {
- if (this.blocks.blockList[blk].parameter) {
- this.blocks.blockList[blk].text.text = '';
- this.blocks.blockList[blk].container.updateCache();
- }
- }
- this.refreshCanvas();
- };
-
- this._updateParameterBlock = function (that, turtle, blk) {
- // Update the label on parameter blocks.
- if (this.blocks.blockList[blk].protoblock.parameter) {
- var name = this.blocks.blockList[blk].name;
- var value = 0;
- switch (name) {
- case 'and':
- case 'or':
- case 'not':
- case 'less':
- case 'greater':
- case 'equal':
- if (this.blocks.blockList[blk].value) {
- value = _('true');
- } else {
- value = _('false');
- }
- break;
- case 'random':
- case 'mod':
- case 'sqrt':
- case 'int':
- case 'plus':
- case 'minus':
- case 'multiply':
- case 'power':
- value = toFixed2(this.blocks.blockList[blk].value);
- break;
- case 'divide':
- value = this.blocks.blockList[blk].value;
- break;
- case 'namedbox':
- var name = this.blocks.blockList[blk].privateData;
- if (name in this.boxes) {
- value = this.boxes[name];
- } else {
- this.errorMsg(NOBOXERRORMSG, blk, name);
- }
- break;
- case 'box':
- var cblk = this.blocks.blockList[blk].connections[1];
- var boxname = this.parseArg(that, turtle, cblk, blk);
- if (boxname in this.boxes) {
- value = this.boxes[boxname];
- } else {
- this.errorMsg(NOBOXERRORMSG, blk, boxname);
- }
- break;
- case 'x':
- value = toFixed2(this.turtles.turtleList[turtle].x);
- break;
- case 'y':
- value = toFixed2(this.turtles.turtleList[turtle].y);
- break;
- case 'heading':
- value = toFixed2(this.turtles.turtleList[turtle].orientation);
- break;
- case 'color':
- case 'hue':
- value = toFixed2(this.turtles.turtleList[turtle].color);
- break;
- case 'shade':
- value = toFixed2(this.turtles.turtleList[turtle].value);
- break;
- case 'grey':
- value = toFixed2(this.turtles.turtleList[turtle].chroma);
- break;
- case 'pensize':
- value = toFixed2(this.turtles.turtleList[turtle].stroke);
- break;
- case 'time':
- var d = new Date();
- value = (d.getTime() - this.time) / 1000;
- break;
- case 'mousex':
- value = toFixed2(this.getStageX());
- break;
- case 'mousey':
- value = toFixed2(this.getStageY());
- break;
- case 'keyboard':
- value = this.lastKeyCode;
- break;
- case 'loudness':
- if (that.mic == null) {
- that.errorMsg(NOMICERRORMSG);
- value = 0;
- } else {
- if (_THIS_IS_TURTLE_BLOCKS) {
- value = Math.round(that.mic.getLevel() * 1000);
- } else {
- var values = that.analyser.analyse();
- var sum = 0;
- for (var k = 0; k < that.limit; k++){
- sum += (values[k] * values[k]);
- }
- value = Math.round(Math.sqrt(sum / that.limit));
- }
- }
- break;
- case 'consonantstepsizeup':
- if (this.lastNotePlayed[turtle] !== null) {
- var len = this.lastNotePlayed[turtle][0].length;
- value = getStepSizeUp(this.keySignature[turtle], this.lastNotePlayed[turtle][0].slice(0, len - 1));
- } else {
- value = getStepSizeUp(this.keySignature[turtle], 'A');
- }
- break;
- case 'consonantstepsizedown':
- if (this.lastNotePlayed[turtle] !== null) {
- var len = this.lastNotePlayed[turtle][0].length;
- value = getStepSizeDown(this.keySignature[turtle], this.lastNotePlayed[turtle][0].slice(0, len - 1));
- } else {
- value = getStepSizeDown(this.keySignature[turtle], 'A');
- }
- break;
- case 'transpositionfactor':
- value = this.transposition[turtle];
- break;
- case 'staccatofactor':
- value = last(this.staccato[turtle]);
- break;
- case 'slurfactor':
- value = -last(this.staccato[turtle]);
- break;
- case 'beatfactor':
- value = this.beatFactor[turtle];
- break;
- case 'elapsednotes':
- value = this.notesPlayed[turtle];
- break;
- case 'duplicatefactor':
- value = this.duplicateFactor[turtle];
- break;
- case 'skipfactor':
- value = this.skipFactor[turtle];
- break;
- case 'notevolumefactor':
- // FIX ME: bias and scaling
- value = last(this.polyVolume[turtle]);
- break;
- case 'turtlepitch':
- if (this.lastNotePlayed[turtle] !== null) {
- var len = this.lastNotePlayed[turtle][0].length;
- value = pitchToNumber(this.lastNotePlayed[turtle][0].slice(0, len - 1), parseInt(this.lastNotePlayed[turtle][0].slice(len - 1)), this.keySignature[turtle]) - that.pitchNumberOffset;
- } else {
- console.log('Could not find a note for turtle ' + turtle);
- value = pitchToNumber('A', 4, this.keySignature[turtle]) - that.pitchNumberOffset;
- }
- break;
- // Deprecated
- case 'currentnote':
- value = this.currentNotes[turtle];
- break;
- // Deprecated
- case 'currentoctave':
- value = this.currentoctave[turtle];
- break;
- case 'bpmfactor':
- if (this.bpm[turtle].length > 0) {
- value = last(this.bpm[turtle]);
- } else {
- value = this._masterBPM;
- }
- break;
- default:
- if (name in this.evalParameterDict) {
- eval(this.evalParameterDict[name]);
- } else {
- return;
- }
- break;
- }
-
- if (typeof(value) === 'string') {
- if (value.length > 6) {
- value = value.substr(0, 5) + '...';
- }
- this.blocks.blockList[blk].text.text = value;
- } else if (name === 'divide') {
- this.blocks.blockList[blk].text.text = mixedNumber(value);
- }
-
- this.blocks.blockList[blk].container.updateCache();
- this.refreshCanvas();
- }
- };
-
- this.runLogoCommands = function (startHere, env) {
- // Save the state before running.
- this.saveLocally();
-
- for (var arg in this.evalOnStartList) {
- eval(this.evalOnStartList[arg]);
- }
-
- this.stopTurtle = false;
- this.blocks.unhighlightAll();
- this.blocks.bringToTop(); // Draw under blocks.
-
- this.hideMsgs();
-
- // We run the Logo commands here.
- var d = new Date();
- this.time = d.getTime();
- this.firstNoteTime = null;
-
- // Ensure we have at least one turtle.
- if (this.turtles.turtleList.length === 0) {
- this.turtles.add(null);
- }
-
- for (var turtle in this.forwardListener) {
- for (var b in this.forwardListener[turtle]) {
- for (var i = 0; i < this.forwardListener[turtle][b].length; i++) {
- this.stage.removeEventListener('_forward_' + turtle, this.forwardListener[turtle][b][i], false);
- }
- }
- }
-
- for (var turtle in this.rightListener) {
- for (var b in this.rightListener[turtle]) {
- for (var i = 0; i < this.rightListener[turtle][b].length; i++) {
- this.stage.removeEventListener('_right_' + turtle, this.rightListener[turtle][b][i], false);
- }
- }
- }
-
- for (var turtle in this.arcListener) {
- for (var b in this.arcListener[turtle]) {
- for (var i = 0; i < this.arcListener[turtle][b].length; i++) {
- this.stage.removeEventListener('_arc_' + turtle, this.arcListener[turtle][b][i], false);
- }
- }
- }
-
- this._masterBPM = TARGETBPM;
- this.defaultBPMFactor = TONEBPM / this._masterBPM;
-
- // Each turtle needs to keep its own wait time and music
- // states.
- for (var turtle = 0; turtle < this.turtles.turtleList.length; turtle++) {
- this.turtleTime[turtle] = 0;
- this.waitTimes[turtle] = 0;
- this.endOfClampSignals[turtle] = {};
- this.cp1x[turtle] = 0;
- this.cp1y[turtle] = 100;
- this.cp2x[turtle] = 100;
- this.cp2y[turtle] = 100;
- this.inNoteBlock[turtle] = 0;
- this.transposition[turtle] = 0;
- this.noteBeat[turtle] = [];
- this.noteCents[turtle] = [];
- this.noteHertz[turtle] = [];
- this.lastNotePlayed[turtle] = null;
- this.noteStatus[turtle] = null;
- this.noteDrums[turtle] = [];
- this.notePitches[turtle] = [];
- this.noteOctaves[turtle] = [];
- this.currentNotes[turtle] = 'G';
- this.currentOctaves[turtle] = 4;
- this.noteTranspositions[turtle] = [];
- this.noteBeatValues[turtle] = [];
- this.forwardListener[turtle] = {};
- this.rightListener[turtle] = {};
- this.arcListener[turtle] = {};
- this.beatFactor[turtle] = 1;
- this.dotCount[turtle] = 0;
- this.invertList[turtle] = [];
- this.duplicateFactor[turtle] = 1;
- this.skipFactor[turtle] = 1;
- this.skipIndex[turtle] = 0;
- this.notesPlayed[turtle] = 0;
- this.keySignature[turtle] = 'C ' + _('major');
- this.pushedNote[turtle] = false;
- this.polyVolume[turtle] = [DEFAULTVOLUME];
- this.oscList[turtle] = [];
- this.bpm[turtle] = [];
- this.crescendoDelta[turtle] = [];
- this.crescendoInitialVolume[turtle] = [];
- this.crescendoVolume[turtle] = [];
- this.intervals[turtle] = [];
- this.perfect[turtle] = [];
- this.diminished[turtle] = [];
- this.augmented[turtle] = [];
- this.major[turtle] = [];
- this.minor[turtle] = [];
- this.staccato[turtle] = [];
- this.swing[turtle] = [];
- this.swingTarget[turtle] = [];
- this.swingCarryOver[turtle] = 0;
- this.tie[turtle] = false;
- this.tieNote[turtle] = [];
- this.tieCarryOver[turtle] = 0;
- this.drift[turtle] = 0;
- this.drumStyle[turtle] = [];
- this.voices[turtle] = [];
- this.pitchDrumTable[turtle] = {};
- this.backward[turtle] = [];
- this.vibratoIntensity[turtle] = [];
- this.vibratoRate[turtle] = [];
- this.dispatchFactor[turtle] = 1;
- this.justCounting[turtle] = false;
- this.suppressOutput[turtle] = this.runningLilypond;
- }
-
- this.pitchNumberOffset = 39; // C4
-
- if (!this.suppressOutput[turtle]) {
- this._setSynthVolume(DEFAULTVOLUME, Math.max(this.turtles.turtleList.length - 1), 0);
- }
-
- this.inPitchDrumMatrix = false;
- this.inMatrix = false;
- this.inRhythmRuler = false;
- this.rhythmRulerMeasure = null;
- this._currentDrumBlock = null;
- this.inStatusMatrix = false;
- this.pitchBlocks = [];
- this.drumBlocks = [];
- this.tuplet = false;
- this._modeBlock = null;
-
- // Remove any listeners that might be still active
- for (var turtle = 0; turtle < this.turtles.turtleList.length; turtle++) {
- for (var listener in this.turtles.turtleList[turtle].listeners) {
- this.stage.removeEventListener(listener, this.turtles.turtleList[turtle].listeners[listener], false);
- }
- this.turtles.turtleList[turtle].listeners = {};
- }
-
- // First we need to reconcile the values in all the value
- // blocks with their associated textareas.
- // FIXME: Do we still need this check???
- for (var blk = 0; blk < this.blocks.blockList.length; blk++) {
- if (this.blocks.blockList[blk].label != null) {
- if (this.blocks.blockList[blk].labelattr != null && this.blocks.blockList[blk].labelattr.value !== '♮') {
- this.blocks.blockList[blk].value = this.blocks.blockList[blk].label.value + this.blocks.blockList[blk].labelattr.value;
- } else {
- this.blocks.blockList[blk].value = this.blocks.blockList[blk].label.value;
- }
- }
- }
-
- // Init the graphic state.
- for (var turtle = 0; turtle < this.turtles.turtleList.length; turtle++) {
- this.turtles.turtleList[turtle].container.x = this.turtles.turtleX2screenX(this.turtles.turtleList[turtle].x);
- this.turtles.turtleList[turtle].container.y = this.turtles.turtleY2screenY(this.turtles.turtleList[turtle].y);
- }
-
- // Set up status block
- if (docById('statusDiv').style.visibility === 'visible') {
- this.statusMatrix.init(this);
- }
-
- // Execute turtle code here... Find the start block (or the
- // top of each stack) and build a list of all of the named
- // action stacks.
- var startBlocks = [];
- this.blocks.findStacks();
- this.actions = {};
- for (var blk = 0; blk < this.blocks.stackList.length; blk++) {
- if (this.blocks.blockList[this.blocks.stackList[blk]].name === 'start' || this.blocks.blockList[this.blocks.stackList[blk]].name === 'drum') {
- // Don't start on a start block in the trash.
- if (!this.blocks.blockList[this.blocks.stackList[blk]].trash) {
- // Don't start on a start block with no connections.
- if (this.blocks.blockList[this.blocks.stackList[blk]].connections[1] != null) {
- startBlocks.push(this.blocks.stackList[blk]);
- }
- }
- } else if (this.blocks.blockList[this.blocks.stackList[blk]].name === 'action') {
- // Does the action stack have a name?
- var c = this.blocks.blockList[this.blocks.stackList[blk]].connections[1];
- var b = this.blocks.blockList[this.blocks.stackList[blk]].connections[2];
- if (c != null && b != null) {
- // Don't use an action block in the trash.
- if (!this.blocks.blockList[this.blocks.stackList[blk]].trash) {
- this.actions[this.blocks.blockList[c].value] = b;
- }
- }
- }
- }
-
- this.svgOutput = '';
- this.svgBackground = true;
-
- this.parentFlowQueue = {};
- this.unhightlightQueue = {};
- this.parameterQueue = {};
-
- if (this.turtleDelay === 0) {
- // Don't update parameters when running full speed.
- this._clearParameterBlocks();
- }
-
- this.onRunTurtle();
-
- // And mark all turtles as not running.
- for (var turtle = 0; turtle < this.turtles.turtleList.length; turtle++) {
- this.turtles.turtleList[turtle].running = false;
- }
-
- // (2) Execute the stack.
- // A bit complicated because we have lots of corner cases:
- if (startHere != null) {
- // console.log('startHere is ' + this.blocks.blockList[startHere].name);
-
- // If a block to start from was passed, find its
- // associated turtle, i.e., which turtle should we use?
- var turtle = 0;
- while(this.blocks.turtles.turtleList[turtle].trash && turtle < this.turtles.turtleList.length) {
- turtle += 1;
- }
- if (this.blocks.blockList[startHere].name === 'start' || this.blocks.blockList[startHere].name === 'drum') {
- var turtle = this.blocks.blockList[startHere].value;
- // console.log('starting on start with turtle ' + turtle);
- // } else {
- // console.log('starting on ' + this.blocks.blockList[startHere].name + ' with turtle ' + turtle);
- }
-
- this.turtles.turtleList[turtle].queue = [];
- this.parentFlowQueue[turtle] = [];
- this.unhightlightQueue[turtle] = [];
- this.parameterQueue[turtle] = [];
- this.turtles.turtleList[turtle].running = true;
- this._runFromBlock(this, turtle, startHere, 0, env);
- } else if (startBlocks.length > 0) {
- // If there are start blocks, run them all.
- for (var b = 0; b < startBlocks.length; b++) {
- var turtle = this.blocks.blockList[startBlocks[b]].value;
- this.turtles.turtleList[turtle].queue = [];
- this.parentFlowQueue[turtle] = [];
- this.unhightlightQueue[turtle] = [];
- this.parameterQueue[turtle] = [];
- if (!this.turtles.turtleList[turtle].trash) {
- this.turtles.turtleList[turtle].running = true;
- this._runFromBlock(this, turtle, startBlocks[b], 0, env);
- }
- }
- } else {
- // console.log('nothing to run');
- if (this.suppressOutput[turtle]) {
- this.errorMsg(NOACTIONERRORMSG, null, _('start'));
- this.suppressOutput[turtle] = false;
- this.checkingLilypond = false;
- // Reset cursor.
- document.body.style.cursor = 'default';
- }
- }
- this.refreshCanvas();
- };
-
- this._runFromBlock = function (that, turtle, blk, isflow, receivedArg) {
- if (blk == null) {
- return;
- }
-
- var delay = that.turtleDelay + that.waitTimes[turtle];
- that.waitTimes[turtle] = 0;
-
- if (!that.stopTurtle) {
- if (that.turtleDelay === TURTLESTEP) {
- // Step mode
- if (!(turtle in that.stepQueue)) {
- that.stepQueue[turtle] = [];
- }
- that.stepQueue[turtle].push(blk);
- } else {
- setTimeout(function () {
- that._runFromBlockNow(that, turtle, blk, isflow, receivedArg);
- }, delay);
- }
- }
- };
-
- this._blockSetter = function (blk, value, turtle) {
- var turtleObj = this.turtles.turtleList[turtle];
-
- switch (this.blocks.blockList[blk].name) {
- case 'x':
- turtleObj.doSetXY(value, turtleObj.x);
- break;
- case 'y':
- turtleObj.doSetXY(turtleObj.y, value);
- break;
- case 'heading':
- turtleObj.doSetHeading(value);
- break;
- case 'color':
- turtleObj.doSetColor(value);
- break;
- case 'shade':
- turtleObj.doSetValue(value);
- break;
- case 'grey':
- turtleObj.doSetChroma(value);
- break;
- case 'pensize':
- turtleObj.doSetPensize(value);
- break;
- case 'namedbox':
- var name = this.blocks.blockList[blk].privateData;
- if (name in this.boxes) {
- this.boxes[name] = value;
- } else {
- this.errorMsg(NOBOXERRORMSG, blk, name);
- }
- break;
- case 'box':
- var cblk = this.blocks.blockList[blk].connections[1];
- var name = this.parseArg(this, turtle, cblk, blk);
- if (name in this.boxes) {
- this.boxes[name] = value;
- } else {
- this.errorMsg(NOBOXERRORMSG, blk, name);
- }
- break;
- case 'bpmfactor':
- var len = this.bpm[turtle].length;
- if (len > 0) {
- this.bpm[turtle][len - 1] = value;
- }
- break;
- case 'transpositionfactor':
- var len = this.transposition[turtle].length;
- if (len > 0) {
- this.transposition[turtle][len - 1] = value;
- }
- break;
- case 'staccatofactor':
- var len = this.staccato[turtle].length;
- if (len > 0) {
- this.staccato[turtle][len - 1] = value;
- }
- break;
- case 'slurfactor':
- // Slur is stored as a negative staccato.
- var len = this.staccato[turtle].length;
- if (len > 0) {
- this.staccato[turtle][len - 1] = -value;
- }
- break;
- case 'beatfactor':
- this.beatFactor[turtle] = value;
- break;
- case 'duplicatefactor':
- var len = this.duplicateFactor[turtle].length;
- if (len > 0) {
- this.duplicateFactor[turtle][len - 1] = value;
- }
- break;
- case 'skipfactor':
- var len = this.skipFactor[turtle].length;
- if (len > 0) {
- this.skipFactor[turtle][len - 1] = value;
- }
- break;
- case 'turtlepitch':
- var obj = numberToPitch(value + this.pitchNumberOffset);
- this.lastNotePlayed[turtle] = [obj[0]+obj[1], this.lastNotePlayed[turtle][1]];
- break;
- // Deprecated
- case 'currentnote':
- // A bit ugly because the setter call added the value
- // to the current note.
- var len = this.currentNotes[turtle].length;
- value = parseInt(value.slice(len));
- var newNoteObj = getNote(this.currentNotes[turtle], this.currentOctaves[turtle], value, this.keySignature[turtle]);
- this.currentNotes[turtle] = newNoteObj[0];
- this.currentOctaves[turtle] = newNoteObj[1];
- break;
- // Deprecated
- case 'currentoctave':
- this.currentOctaves[turtle] = Math.round(value);
- if (this.currentOctaves[turtle] < 1) {
- this.currentOctaves[turtle] = 1;
- }
- break;
- case 'notevolumefactor':
- var len = this.transposition[turtle].length;
- this.polyVolume[turtle][len - 1] = value;
- this._setSynthVolume(value, turtle);
- break;
- default:
- if (this.blocks.blockList[blk].name in this.evalSetterDict) {
- eval(this.evalSetterDict[this.blocks.blockList[blk].name]);
- break;
- }
- this.errorMsg(_('Block does not support incrementing.'), blk);
- }
- };
-
- this._runFromBlockNow = function (that, turtle, blk, isflow, receivedArg, queueStart) {
- // Run a stack of blocks, beginning with blk.
-
- // Sometimes we don't want to unwind the entire queue.
- if (queueStart === undefined) {
- queueStart = 0;
- }
-
- // (1) Evaluate any arguments (beginning with connection[1]);
- var args = [];
- if (that.blocks.blockList[blk].protoblock.args > 0) {
- for (var i = 1; i < that.blocks.blockList[blk].protoblock.args + 1; i++) {
- if (that.blocks.blockList[blk].protoblock.dockTypes[i] === 'in' && that.blocks.blockList[blk].connections[i] == null){
- console.log('skipping null inflow args');
- } else {
- args.push(that.parseArg(that, turtle, that.blocks.blockList[blk].connections[i], blk, receivedArg));
- }
- }
- }
-
- // (2) Run function associated with the block;
- if (that.blocks.blockList[blk].isValueBlock()) {
- var nextFlow = null;
- } else {
- // All flow blocks have a nextFlow, but it can be null
- // (i.e., end of a flow).
- if (that.backward[turtle].length > 0) {
- // We only run backwards in the "first generation" children.
- if (that.blocks.blockList[last(that.backward[turtle])].name === 'backward') {
- var c = 1;
- } else {
- var c = 2;
- }
- if (!that.blocks.sameGeneration(that.blocks.blockList[last(that.backward[turtle])].connections[c], blk)) {
- var nextFlow = last(that.blocks.blockList[blk].connections);
- } else {
- var nextFlow = that.blocks.blockList[blk].connections[0];
- if (that.blocks.blockList[nextFlow].name === 'action' || that.blocks.blockList[nextFlow].name === 'backward') {
- nextFlow = null;
- } else {
- if (!that.blocks.sameGeneration(that.blocks.blockList[last(that.backward[turtle])].connections[c], nextFlow)) {
- var nextFlow = last(that.blocks.blockList[blk].connections);
- } else {
- var nextFlow = that.blocks.blockList[blk].connections[0];
- }
- }
- }
- } else {
- var nextFlow = last(that.blocks.blockList[blk].connections);
- }
-
- if (nextFlow === -1) {
- nextFlow = null;
- }
-
- var queueBlock = new Queue(nextFlow, 1, blk, receivedArg);
- if (nextFlow != null) { // This could be the last block
- that.turtles.turtleList[turtle].queue.push(queueBlock);
- }
- }
-
- // Some flow blocks have childflows, e.g., repeat.
- var childFlow = null;
- var childFlowCount = 0;
- var actionArgs = [];
-
- if (that.blocks.visible) {
- that.blocks.highlight(blk, false);
- }
-
- switch (that.blocks.blockList[blk].name) {
- case 'dispatch':
- // Dispatch an event.
- if (args.length === 1) {
- // If the event is not in the event list, add it.
- if (!(args[0] in that.eventList)) {
- var event = new Event(args[0]);
- that.eventList[args[0]] = event;
- }
- that.stage.dispatchEvent(args[0]);
- }
- break;
- case 'listen':
- if (args.length === 2) {
- if (!(args[1] in that.actions)) {
- that.errorMsg(NOACTIONERRORMSG, blk, args[1]);
- that.stopTurtle = true;
- } else {
- var __listener = function (event) {
- if (that.turtles.turtleList[turtle].running) {
- var queueBlock = new Queue(that.actions[args[1]], 1, blk);
- that.parentFlowQueue[turtle].push(blk);
- that.turtles.turtleList[turtle].queue.push(queueBlock);
- } else {
- // Since the turtle has stopped
- // running, we need to run the stack
- // from here.
- if (isflow) {
- that._runFromBlockNow(that, turtle, that.actions[args[1]], isflow, receivedArg);
- } else {
- that._runFromBlock(that, turtle, that.actions[args[1]], isflow, receivedArg);
- }
- }
- };
-
- // If there is already a listener, remove it
- // before adding the new one.
- that._setListener(turtle, args[0], __listener);
- }
- }
- break;
- case 'start':
- case 'drum':
- if (args.length === 1) {
- childFlow = args[0];
- childFlowCount = 1;
- }
- break;
- case 'nameddo':
- var name = that.blocks.blockList[blk].privateData;
- if (name in that.actions) {
- if (!that.justCounting[turtle]) {
- lilypondLineBreak(that, turtle);
- }
-
- if (that.backward[turtle].length > 0) {
- childFlow = that.blocks.findBottomBlock(that.actions[name]);
- var actionBlk = that.blocks.findTopBlock(that.actions[name]);
- that.backward[turtle].push(actionBlk);
-
- var listenerName = '_backward_action_' + turtle + '_' + blk;
-
- var nextBlock = this.blocks.blockList[actionBlk].connections[2];
- if (nextBlock == null) {
- that.backward[turtle].pop();
- } else {
- that.endOfClampSignals[turtle][nextBlock] = [listenerName];
- }
-
- var __listener = function (event) {
- that.backward[turtle].pop();
- };
-
- that._setListener(turtle, listenerName, __listener);
- } else {
- childFlow = that.actions[name];
- }
-
- childFlowCount = 1;
- } else {
- that.errorMsg(NOACTIONERRORMSG, blk, name);
- that.stopTurtle = true;
- }
- break;
- // If we clicked on an action block, treat it like a do
- // block.
- case 'action':
- case 'do':
- if (args.length > 0) {
- if (args[0] in that.actions) {
- if (!that.justCounting[turtle]) {
- lilypondLineBreak(that, turtle);
- }
- childFlow = that.actions[args[0]];
- childFlowCount = 1;
- } else {
- console.log('action ' + args[0] + ' not found');
- that.errorMsg(NOACTIONERRORMSG, blk, args[0]);
- that.stopTurtle = true;
- }
- }
- break;
- case 'nameddoArg':
- var name = that.blocks.blockList[blk].privateData;
- while(actionArgs.length > 0) {
- actionArgs.pop();
- }
- if (that.blocks.blockList[blk].argClampSlots.length > 0) {
- for (var i = 0; i < that.blocks.blockList[blk].argClampSlots.length; i++){
- var t = (that.parseArg(that, turtle, that.blocks.blockList[blk].connections[i + 1], blk, receivedArg));
- actionArgs.push(t);
- }
- }
- if (name in that.actions) {
- if (!that.justCounting[turtle]) {
- lilypondLineBreak(that, turtle);
- }
-
- if (that.backward[turtle].length > 0) {
- childFlow = that.blocks.findBottomBlock(that.actions[name]);
- var actionBlk = that.blocks.findTopBlock(that.actions[name]);
- that.backward[turtle].push(actionBlk);
-
- var listenerName = '_backward_action_' + turtle + '_' + blk;
-
- var nextBlock = this.blocks.blockList[actionBlk].connections[2];
- if (nextBlock == null) {
- that.backward[turtle].pop();
- } else {
- that.endOfClampSignals[turtle][nextBlock] = [listenerName];
- }
-
- var __listener = function (event) {
- that.backward[turtle].pop();
- };
-
- that._setListener(turtle, listenerName, __listener);
- } else {
- childFlow = that.actions[name]
- }
-
- childFlowCount = 1;
- } else{
- that.errorMsg(NOACTIONERRORMSG, blk, name);
- that.stopTurtle = true;
- }
- break;
- case 'doArg':
- while(actionArgs.length > 0) {
- actionArgs.pop();
- }
- if (that.blocks.blockList[blk].argClampSlots.length > 0) {
- for (var i = 0; i < that.blocks.blockList[blk].argClampSlots.length; i++){
- var t = (that.parseArg(that, turtle, that.blocks.blockList[blk].connections[i + 2], blk, receivedArg));
- actionArgs.push(t);
- }
- }
- if (args.length >= 1) {
- if (args[0] in that.actions) {
- if (!that.justCounting[turtle]) {
- lilypondLineBreak(that, turtle);
- }
- actionName = args[0];
- childFlow = that.actions[args[0]];
- childFlowCount = 1;
- } else {
- that.errorMsg(NOACTIONERRORMSG, blk, args[0]);
- that.stopTurtle = true;
- }
- }
- break;
- case 'forever':
- if (args.length === 1) {
- childFlow = args[0];
- // If we are running in non-interactive mode, we
- // need to put a bounds on "forever".
- if (that.suppressOutput[turtle]) {
- childFlowCount = 10;
- } else {
- childFlowCount = -1;
- }
- }
- break;
- case 'hidden':
- case 'hiddennoflow':
- // Hidden block is used at end of clamps and actions to
- // trigger listeners.
- break;
- case 'break':
- that._doBreak(turtle);
- // Since we pop the queue, we need to unhighlight our
- // parent.
- var parentBlk = that.blocks.blockList[blk].connections[0];
- if (parentBlk != null) {
- that.unhightlightQueue[turtle].push(parentBlk);
- }
- break;
- case 'wait':
- if (args.length === 1) {
- that._doWait(turtle, args[0]);
- }
- break;
- case 'print':
- if (!that.inStatusMatrix) {
- if (args.length === 1) {
- if (args[0] !== null) {
- that.textMsg(args[0].toString());
- }
- }
- }
- break;
- case 'speak':
- if (args.length === 1) {
- if (that.meSpeak) {
- var text = args[0];
- var new_text = "";
- for (var i = 0; i < text.length; i++){
- if ((text[i] >= 'a' && text[i] <= 'z') || (text[i] >= 'A' && text[i] <= 'Z') || text[i] === ',' || text[i] === '.' || text[i] === ' ')
- new_text += text[i];
- }
- that.meSpeak.speak(new_text);
- }
- }
- break;
- case 'repeat':
- if (args.length === 2) {
- if (typeof(args[0]) === 'string') {
- that.errorMsg(NANERRORMSG, blk);
- that.stopTurtle = true;
- } else if (args[0] <= 0) {
- that.errorMsg(POSNUMBER,blk);
- } else {
- childFlow = args[1];
- childFlowCount = Math.floor(args[0]);
- }
- }
- break;
- case 'clamp':
- if (args.length === 1) {
- childFlow = args[0];
- childFlowCount = 1;
- }
- break;
- case 'until':
- // Similar to 'while'
- if (args.length === 2) {
- // Queue the child flow.
- childFlow = args[1];
- childFlowCount = 1;
- if (!args[0]) {
- // We will add the outflow of the until block
- // each time through, so we pop it off so as
- // to not accumulate multiple copies.
- var queueLength = that.turtles.turtleList[turtle].queue.length;
- if (queueLength > 0) {
- if (that.turtles.turtleList[turtle].queue[queueLength - 1].parentBlk === blk) {
- that.turtles.turtleList[turtle].queue.pop();
- }
- }
- // Requeue.
- var parentBlk = that.blocks.blockList[blk].connections[0];
- var queueBlock = new Queue(blk, 1, parentBlk);
- that.parentFlowQueue[turtle].push(parentBlk);
- that.turtles.turtleList[turtle].queue.push(queueBlock);
- } else {
- // Since an until block was requeued each
- // time, we need to flush the queue of all but
- // the last one, otherwise the child of the
- // until block is executed multiple times.
- var queueLength = that.turtles.turtleList[turtle].queue.length;
- for (var i = queueLength - 1; i > 0; i--) {
- if (that.turtles.turtleList[turtle].queue[i].parentBlk === blk) {
- that.turtles.turtleList[turtle].queue.pop();
- }
- }
- }
- }
- break;
- case 'waitFor':
- if (args.length === 1) {
- if (!args[0]) {
- // Requeue.
- var parentBlk = that.blocks.blockList[blk].connections[0];
- var queueBlock = new Queue(blk, 1, parentBlk);
- that.parentFlowQueue[turtle].push(parentBlk);
- that.turtles.turtleList[turtle].queue.push(queueBlock);
- that._doWait(0.05);
- } else {
- // Since a wait for block was requeued each
- // time, we need to flush the queue of all but
- // the last one, otherwise the child of the
- // while block is executed multiple times.
- var queueLength = that.turtles.turtleList[turtle].queue.length;
- for (var i = queueLength - 1; i > 0; i--) {
- if (that.turtles.turtleList[turtle].queue[i].parentBlk === blk) {
- that.turtles.turtleList[turtle].queue.pop();
- }
- }
- }
- }
- break;
- case 'if':
- if (args.length === 2) {
- if (args[0]) {
- childFlow = args[1];
- childFlowCount = 1;
- }
- }
- break;
- case 'ifthenelse':
- if (args.length === 3) {
- if (args[0]) {
- childFlow = args[1];
- childFlowCount = 1;
- } else {
- childFlow = args[2];
- childFlowCount = 1;
- }
- }
- break;
- case 'while':
- // While is tricky because we need to recalculate
- // args[0] each time, so we requeue the While block
- // itself.
- if (args.length === 2) {
- if (args[0]) {
- // We will add the outflow of the while block
- // each time through, so we pop it off so as
- // to not accumulate multiple copies.
- var queueLength = that.turtles.turtleList[turtle].queue.length;
- if (queueLength > 0) {
- if (that.turtles.turtleList[turtle].queue[queueLength - 1].parentBlk === blk) {
- that.turtles.turtleList[turtle].queue.pop();
- }
- }
-
- var parentBlk = that.blocks.blockList[blk].connections[0];
- var queueBlock = new Queue(blk, 1, parentBlk);
- that.parentFlowQueue[turtle].push(parentBlk);
- that.turtles.turtleList[turtle].queue.push(queueBlock);
-
- // and queue the interior child flow.
- childFlow = args[1];
- childFlowCount = 1;
- } else {
- // Since a while block was requeued each time,
- // we need to flush the queue of all but the
- // last one, otherwise the child of the while
- // block is executed multiple times.
- var queueLength = that.turtles.turtleList[turtle].queue.length;
- for (var i = queueLength - 1; i > 0; i--) {
- if (that.turtles.turtleList[turtle].queue[i].parentBlk === blk) {
- // if (that.turtles.turtleList[turtle].queue[i].blk === blk) {
- that.turtles.turtleList[turtle].queue.pop();
- }
- }
- }
- }
- break;
- case 'storein':
- if (args.length === 2) {
- that.boxes[args[0]] = args[1];
- }
- break;
- case 'incrementOne':
- var i = 1;
- case 'increment':
- // If the 2nd arg is not set, default to 1.
- if (args.length === 2) {
- var i = args[1];
- }
-
- if (args.length >= 1) {
- var settingBlk = that.blocks.blockList[blk].connections[1];
- that._blockSetter(settingBlk, args[0] + i, turtle);
- }
- break;
- case 'clear':
- that.svgBackground = true;
- that.turtles.turtleList[turtle].doClear(true, true);
- break;
- case 'setxy':
- if (args.length === 2) {
- if (typeof(args[0]) === 'string' || typeof(args[1]) === 'string') {
- that.errorMsg(NANERRORMSG, blk);
- that.stopTurtle = true;
- } else if (that.inMatrix) {
- that.pitchTimeMatrix.addRowBlock(blk);
- if (that.pitchBlocks.indexOf(blk) === -1) {
- that.pitchBlocks.push(blk);
- }
- that.pitchTimeMatrix.rowLabels.push(that.blocks.blockList[blk].name);
- that.pitchTimeMatrix.rowArgs.push([args[0], args[1]]);
- } else {
- that.turtles.turtleList[turtle].doSetXY(args[0], args[1]);
- }
- }
- break;
- case 'arc':
- if (args.length === 2) {
- if (typeof(args[0]) === 'string' || typeof(args[1]) === 'string') {
- that.errorMsg(NANERRORMSG, blk);
- that.stopTurtle = true;
- } else if (that.inMatrix) {
- that.pitchTimeMatrix.addRowBlock(blk);
- if (that.pitchBlocks.indexOf(blk) === -1) {
- that.pitchBlocks.push(blk);
- }
- that.pitchTimeMatrix.rowLabels.push(that.blocks.blockList[blk].name);
- that.pitchTimeMatrix.rowArgs.push([args[0], args[1]]);
- } else if (that.inNoteBlock[turtle] > 0) {
- if (!that.suppressOutput[turtle]) {
- var delta = args[0] / NOTEDIV;
- var listenerName = '_arc_' + turtle + '_' + that.whichNoteBlock[turtle];
-
- var __listener = function (event) {
- that.turtles.turtleList[turtle].doArc(delta * that.dispatchFactor[turtle], args[1]);
- };
-
- if (that.whichNoteBlock[turtle] in that.arcListener[turtle]) {
- that.arcListener[turtle][that.whichNoteBlock[turtle]].push(__listener);
- } else {
- that.arcListener[turtle][that.whichNoteBlock[turtle]] = [__listener];
- }
-
- that.stage.addEventListener(listenerName, __listener, false);
- }
- } else {
- that.turtles.turtleList[turtle].doArc(args[0], args[1]);
- }
- }
- break;
- case 'bezier':
- if (args.length === 2) {
- if (typeof(args[0]) === 'string' || typeof(args[1]) === 'string') {
- that.errorMsg(NANERRORMSG, blk);
- that.stopTurtle = true;
- } else {
- that.turtles.turtleList[turtle].doBezier(that.cp1x[turtle], that.cp1y[turtle], that.cp2x[turtle], that.cp2y[turtle], args[0], args[1]);
- }
- }
- break;
- case 'controlpoint1':
- if (args.length === 2) {
- if (typeof(args[0]) === 'string' || typeof(args[1]) === 'string') {
- that.errorMsg(NANERRORMSG, blk);
- that.stopTurtle = true;
- } else {
- that.cp1x[turtle] = args[0];
- that.cp1y[turtle] = args[1];
- }
- }
- break;
- case 'controlpoint2':
- if (args.length === 2) {
- if (typeof(args[0]) === 'string' || typeof(args[1]) === 'string') {
- that.errorMsg(NANERRORMSG, blk);
- that.stopTurtle = true;
- } else {
- that.cp2x[turtle] = args[0];
- that.cp2y[turtle] = args[1];
- }
- }
- break;
- case 'return':
- if (args.length === 1) {
- that.returns.push(args[0]);
- }
- break;
- case 'returnToUrl':
- var URL = window.location.href;
- var urlParts;
- var outurl;
- if (URL.indexOf('?') > 0) {
- var urlParts = URL.split('?');
- if (urlParts[1].indexOf('&') >0) {
- var newUrlParts = urlParts[1].split('&');
- for (var i = 0; i < newUrlParts.length; i++) {
- if (newUrlParts[i].indexOf('=') > 0) {
- var tempargs = newUrlParts[i].split('=');
- switch (tempargs[0].toLowerCase()) {
- case 'outurl':
- outurl = tempargs[1];
- break;
- }
- }
- }
- }
- }
- if (args.length === 1) {
- var jsonRet = {};
- jsonRet['result'] = args[0];
- var json= JSON.stringify(jsonRet);
- var xmlHttp = new XMLHttpRequest();
- xmlHttp.open('POST',outurl, true);
- // Call a function when the state changes.
- xmlHttp.onreadystatechange = function () {
- if(xmlHttp.readyState === 4 && xmlHttp.status === 200) {
- alert(xmlHttp.responseText);
- }
- };
-
- xmlHttp.send(json);
- }
- break;
- case 'forward':
- if (args.length === 1) {
- if (typeof(args[0]) === 'string') {
- that.errorMsg(NANERRORMSG, blk);
- that.stopTurtle = true;
- } else if (that.inMatrix) {
- that.pitchTimeMatrix.addRowBlock(blk);
- if (that.pitchBlocks.indexOf(blk) === -1) {
- that.pitchBlocks.push(blk);
- }
- that.pitchTimeMatrix.rowLabels.push(that.blocks.blockList[blk].name);
- that.pitchTimeMatrix.rowArgs.push(args[0]);
- } else if (that.inNoteBlock[turtle] > 0) {
- if (!that.suppressOutput[turtle]) {
- var dist = args[0] / NOTEDIV;
- var listenerName = '_forward_' + turtle + '_' + that.whichNoteBlock[turtle];
-
- var __listener = function (event) {
- that.turtles.turtleList[turtle].doForward(dist * that.dispatchFactor[turtle]);
- };
-
- if (that.whichNoteBlock[turtle] in that.forwardListener[turtle]) {
- that.forwardListener[turtle][that.whichNoteBlock[turtle]].push(__listener);
- } else {
- that.forwardListener[turtle][that.whichNoteBlock[turtle]] = [__listener];
- }
-
- that.stage.addEventListener(listenerName, __listener, false);
- }
- } else {
- that.turtles.turtleList[turtle].doForward(args[0]);
- }
- }
- break;
- case 'back':
- if (args.length === 1) {
- if (typeof(args[0]) === 'string') {
- that.errorMsg(NANERRORMSG, blk);
- that.stopTurtle = true;
- } else if (that.inMatrix) {
- that.pitchTimeMatrix.addRowBlock(blk);
- if (that.pitchBlocks.indexOf(blk) === -1) {
- that.pitchBlocks.push(blk);
- }
- that.pitchTimeMatrix.rowLabels.push(that.blocks.blockList[blk].name);
- that.pitchTimeMatrix.rowArgs.push(args[0]);
- } else if (that.inNoteBlock[turtle] > 0) {
- if (!that.suppressOutput[turtle]) {
- var dist = -args[0] / NOTEDIV;
- var listenerName = '_forward_' + turtle + '_' + that.whichNoteBlock[turtle];
-
- var __listener = function (event) {
- that.turtles.turtleList[turtle].doForward(dist * that.dispatchFactor[turtle]);
- };
-
- if (that.whichNoteBlock[turtle] in that.forwardListener[turtle]) {
- that.forwardListener[turtle][that.whichNoteBlock[turtle]].push(__listener);
- } else {
- that.forwardListener[turtle][that.whichNoteBlock[turtle]] = [__listener];
- }
-
- that.stage.addEventListener(listenerName, __listener, false);
- }
- } else {
- that.turtles.turtleList[turtle].doForward(-args[0]);
- }
- }
- break;
- case 'right':
- if (args.length === 1) {
- if (typeof(args[0]) === 'string') {
- that.errorMsg(NANERRORMSG, blk);
- that.stopTurtle = true;
- } else if (that.inMatrix) {
- that.pitchTimeMatrix.addRowBlock(blk);
- if (that.pitchBlocks.indexOf(blk) === -1) {
- that.pitchBlocks.push(blk);
- }
- that.pitchTimeMatrix.rowLabels.push(that.blocks.blockList[blk].name);
- that.pitchTimeMatrix.rowArgs.push(args[0]);
- } else if (that.inNoteBlock[turtle] > 0) {
- if (!that.suppressOutput[turtle]) {
- var delta = args[0] / NOTEDIV;
- var listenerName = '_right_' + turtle + '_' + that.whichNoteBlock[turtle];
-
- var __listener = function (event) {
- that.turtles.turtleList[turtle].doRight(delta * that.dispatchFactor[turtle]);
- };
-
- if (that.whichNoteBlock[turtle] in that.rightListener[turtle]) {
- that.rightListener[turtle][that.whichNoteBlock[turtle]].push(__listener);
- } else {
- that.rightListener[turtle][that.whichNoteBlock[turtle]] = [__listener];
- }
-
- that.stage.addEventListener(listenerName, __listener, false);
- }
- } else {
- that.turtles.turtleList[turtle].doRight(args[0]);
- }
- }
- break;
- case 'left':
- if (args.length === 1) {
- if (typeof(args[0]) === 'string') {
- that.errorMsg(NANERRORMSG, blk);
- that.stopTurtle = true;
- } else if (that.inMatrix) {
- that.pitchTimeMatrix.addRowBlock(blk);
- if (that.pitchBlocks.indexOf(blk) === -1) {
- that.pitchBlocks.push(blk);
- }
- that.pitchTimeMatrix.rowLabels.push(that.blocks.blockList[blk].name);
- that.pitchTimeMatrix.rowArgs.push(args[0]);
- } else if (that.inNoteBlock[turtle] > 0) {
- if (!that.suppressOutput[turtle]) {
- var delta = -args[0] / NOTEDIV;
- var listenerName = '_right_' + turtle + '_' + that.whichNoteBlock[turtle];
-
- var __listener = function (event) {
- that.turtles.turtleList[turtle].doRight(delta * that.dispatchFactor[turtle]);
- };
-
- if (that.whichNoteBlock[turtle] in that.rightListener[turtle]) {
- that.rightListener[turtle][that.whichNoteBlock[turtle]].push(__listener);
- } else {
- that.rightListener[turtle][that.whichNoteBlock[turtle]] = [__listener];
- }
-
- that.stage.addEventListener(listenerName, __listener, false);
- }
- } else {
- that.turtles.turtleList[turtle].doRight(-args[0]);
- }
- }
- break;
- case 'setheading':
- if (args.length === 1) {
- if (typeof(args[0]) === 'string') {
- that.errorMsg(NANERRORMSG, blk);
- that.stopTurtle = true;
- } else if (that.inMatrix) {
- that.pitchTimeMatrix.addRowBlock(blk);
- if (that.pitchBlocks.indexOf(blk) === -1) {
- that.pitchBlocks.push(blk);
- }
- that.pitchTimeMatrix.rowLabels.push(that.blocks.blockList[blk].name);
- that.pitchTimeMatrix.rowArgs.push(args[0]);
- } else {
- that.turtles.turtleList[turtle].doSetHeading(args[0]);
- }
- }
- break;
- case 'show':
- if (args.length === 2) {
- if (typeof(args[1]) === 'string') {
- var len = args[1].length;
- if (len === 14 && args[1].substr(0, 14) === CAMERAVALUE) {
- doUseCamera(args, that.turtles, turtle, false, that.cameraID, that.setCameraID, that.errorMsg);
- } else if (len === 13 && args[1].substr(0, 13) === VIDEOVALUE) {
- doUseCamera(args, that.turtles, turtle, true, that.cameraID, that.setCameraID, that.errorMsg);
- } else if (len > 10 && args[1].substr(0, 10) === 'data:image') {
- that.turtles.turtleList[turtle].doShowImage(args[0], args[1]);
- } else if (len > 8 && args[1].substr(0, 8) === 'https://') {
- that.turtles.turtleList[turtle].doShowURL(args[0], args[1]);
- } else if (len > 7 && args[1].substr(0, 7) === 'http://') {
- that.turtles.turtleList[turtle].doShowURL(args[0], args[1]);
- } else if (len > 7 && args[1].substr(0, 7) === 'file://') {
- that.turtles.turtleList[turtle].doShowURL(args[0], args[1]);
- } else {
- that.turtles.turtleList[turtle].doShowText(args[0], args[1]);
- }
- } else if (typeof(args[1]) === 'object' && that.blocks.blockList[that.blocks.blockList[blk].connections[2]].name === 'loadFile') {
- if (args[1]) {
- that.turtles.turtleList[turtle].doShowText(args[0], args[1][1]);
- } else {
- that.errorMsg(_('You must select a file.'));
- }
- } else {
- that.turtles.turtleList[turtle].doShowText(args[0], args[1]);
- }
- }
- break;
- case 'turtleshell':
- if (args.length === 2) {
- if (typeof(args[0]) === 'string') {
- that.errorMsg(NANERRORMSG, blk);
- that.stopTurtle = true;
- } else {
- that.turtles.turtleList[turtle].doTurtleShell(args[0], args[1]);
- }
- }
- break;
- case 'setturtlename':
- var foundTargetTurtle = false;
- if (args.length === 2) {
- for (var i = 0; i < that.turtles.turtleList.length; i++) {
- if (that.turtles.turtleList[i].name === args[0]) {
- that.turtles.turtleList[i].rename(args[1]);
- foundTargetTurtle = true;
- break;
- }
- }
- }
- if (!foundTargetTurtle) {
- that.errorMsg('Could not find turtle ' + args[0], blk);
- }
- break;
- case 'startTurtle':
- var targetTurtle = that._getTargetTurtle(args);
- if (targetTurtle == null) {
- that.errorMsg('Cannot find turtle: ' + args[0], blk)
- } else {
- if (that.turtles.turtleList[targetTurtle].running) {
- that.errorMsg('Turtle is already running.', blk);
- break;
- }
- that.turtles.turtleList[targetTurtle].queue = [];
- that.turtles.turtleList[targetTurtle].running = true;
- that.parentFlowQueue[targetTurtle] = [];
- that.unhightlightQueue[targetTurtle] = [];
- that.parameterQueue[targetTurtle] = [];
- // Find the start block associated with this turtle.
- var foundStartBlock = false;
- for (var i = 0; i < that.blocks.blockList.length; i++) {
- if (that.blocks.blockList[i] === that.turtles.turtleList[targetTurtle].startBlock) {
- foundStartBlock = true;
- break;
- }
- }
- if (foundStartBlock) {
- that._runFromBlock(that, targetTurtle, i, isflow, receivedArg);
- } else {
- that.errorMsg('Cannot find start block for turtle: ' + args[0], blk)
- }
- }
- break;
- case 'stopTurtle':
- var targetTurtle = that._getTargetTurtle(args);
- if (targetTurtle == null) {
- that.errorMsg('Cannot find turtle: ' + args[0], blk)
- } else {
- that.turtles.turtleList[targetTurtle].queue = [];
- that.parentFlowQueue[targetTurtle] = [];
- that.unhightlightQueue[targetTurtle] = [];
- that.parameterQueue[targetTurtle] = [];
- that._doBreak(targetTurtle);
- }
- break;
- case 'setcolor':
- if (args.length === 1) {
- if (typeof(args[0]) === 'string') {
- that.errorMsg(NANERRORMSG, blk);
- that.stopTurtle = true;
- } else if (that.inMatrix) {
- that.pitchTimeMatrix.addRowBlock(blk);
- if (that.pitchBlocks.indexOf(blk) === -1) {
- that.pitchBlocks.push(blk);
- }
- that.pitchTimeMatrix.rowLabels.push(that.blocks.blockList[blk].name);
- that.pitchTimeMatrix.rowArgs.push(args[0]);
- } else {
- that.turtles.turtleList[turtle].doSetColor(args[0]);
- }
- }
- break;
- case 'setfont':
- if (args.length === 1) {
- if (typeof(args[0]) === 'string') {
- that.turtles.turtleList[turtle].doSetFont(args[0]);
- } else {
- that.errorMsg(NOSTRINGERRORMSG, blk);
- that.stopTurtle = true;
- }
- }
- break;
- case 'sethue':
- if (args.length === 1) {
- if (typeof(args[0]) === 'string') {
- that.errorMsg(NANERRORMSG, blk);
- that.stopTurtle = true;
- } else if (that.inMatrix) {
- that.pitchTimeMatrix.addRowBlock(blk);
- if (that.pitchBlocks.indexOf(blk) === -1) {
- that.pitchBlocks.push(blk);
- }
- that.pitchTimeMatrix.rowLabels.push(that.blocks.blockList[blk].name);
- that.pitchTimeMatrix.rowArgs.push(args[0]);
- } else {
- that.turtles.turtleList[turtle].doSetHue(args[0]);
- }
- }
- break;
- case 'setshade':
- if (args.length === 1) {
- if (typeof(args[0]) === 'string') {
- that.errorMsg(NANERRORMSG, blk);
- that.stopTurtle = true;
- } else if (that.inMatrix) {
- that.pitchTimeMatrix.addRowBlock(blk);
- if (that.pitchBlocks.indexOf(blk) === -1) {
- that.pitchBlocks.push(blk);
- }
- that.pitchTimeMatrix.rowLabels.push(that.blocks.blockList[blk].name);
- that.pitchTimeMatrix.rowArgs.push(args[0]);
- } else {
- that.turtles.turtleList[turtle].doSetValue(args[0]);
- }
- }
- break;
- case 'settranslucency':
- if (args.length === 1) {
- if (typeof(args[0]) === 'string') {
- that.errorMsg(NANERRORMSG, blk);
- that.stopTurtle = true;
- } else if (that.inMatrix) {
- that.pitchTimeMatrix.addRowBlock(blk);
- if (that.pitchBlocks.indexOf(blk) === -1) {
- that.pitchBlocks.push(blk);
- }
- that.pitchTimeMatrix.rowLabels.push(that.blocks.blockList[blk].name);
- that.pitchTimeMatrix.rowArgs.push(args[0]);
- } else {
- args[0] %= 101;
- var alpha = 1.0 - (args[0] / 100);
- that.turtles.turtleList[turtle].doSetPenAlpha(alpha);
- }
- }
- break;
- case 'setgrey':
- if (args.length === 1) {
- if (typeof(args[0]) === 'string') {
- that.errorMsg(NANERRORMSG, blk);
- that.stopTurtle = true;
- } else if (that.inMatrix) {
- that.pitchTimeMatrix.addRowBlock(blk);
- if (that.pitchBlocks.indexOf(blk) === -1) {
- that.pitchBlocks.push(blk);
- }
- that.pitchTimeMatrix.rowLabels.push(that.blocks.blockList[blk].name);
- that.pitchTimeMatrix.rowArgs.push(args[0]);
- } else {
- that.turtles.turtleList[turtle].doSetChroma(args[0]);
- }
- }
- break;
- case 'setpensize':
- if (args.length === 1) {
- if (typeof(args[0]) === 'string') {
- that.errorMsg(NANERRORMSG, blk);
- that.stopTurtle = true;
- } else if (that.inMatrix) {
- that.pitchTimeMatrix.addRowBlock(blk);
- if (that.pitchBlocks.indexOf(blk) === -1) {
- that.pitchBlocks.push(blk);
- }
- that.pitchTimeMatrix.rowLabels.push(that.blocks.blockList[blk].name);
- that.pitchTimeMatrix.rowArgs.push(args[0]);
- } else {
- that.turtles.turtleList[turtle].doSetPensize(args[0]);
- }
- }
- break;
- case 'fill':
- that.turtles.turtleList[turtle].doStartFill();
-
- childFlow = args[0];
- childFlowCount = 1;
-
- var listenerName = '_fill_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.turtles.turtleList[turtle].doEndFill();
- };
-
- that._setListener(turtle, listenerName, __listener);
- break;
- // Deprecated
- case 'beginfill':
- that.turtles.turtleList[turtle].doStartFill();
- break;
- // Deprecated
- case 'endfill':
- that.turtles.turtleList[turtle].doEndFill();
- break;
- case 'hollowline':
- that.turtles.turtleList[turtle].doStartHollowLine();
-
- childFlow = args[0];
- childFlowCount = 1;
-
- var listenerName = '_hollowline_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.turtles.turtleList[turtle].doEndHollowLine();
- };
-
- that._setListener(turtle, listenerName, __listener);
- break;
- // Deprecated
- case 'beginhollowline':
- that.turtles.turtleList[turtle].doStartHollowLine();
- break;
- // Deprecated
- case 'endhollowline':
- that.turtles.turtleList[turtle].doEndHollowLine();
- break;
- case 'fillscreen':
- if (args.length === 3) {
- var hue = that.turtles.turtleList[turtle].color;
- var value = that.turtles.turtleList[turtle].value;
- var chroma = that.turtles.turtleList[turtle].chroma;
- that.turtles.turtleList[turtle].doSetHue(args[0]);
- that.turtles.turtleList[turtle].doSetValue(args[1]);
- that.turtles.turtleList[turtle].doSetChroma(args[2]);
- that.setBackgroundColor(turtle);
- that.turtles.turtleList[turtle].doSetHue(hue);
- that.turtles.turtleList[turtle].doSetValue(value);
- that.turtles.turtleList[turtle].doSetChroma(chroma);
- }
- break;
- case 'nobackground':
- that.svgBackground = false;
- break;
- case 'background':
- that.setBackgroundColor(turtle);
- break;
- case 'penup':
- that.turtles.turtleList[turtle].doPenUp();
- break;
- case 'pendown':
- that.turtles.turtleList[turtle].doPenDown();
- break;
- case 'openProject':
- url = args[0];
-
- function ValidURL(str) {
- var pattern = new RegExp('^(https?:\\/\\/)?'+ // protocol
- '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+ // domain name
- '((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address
- '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path
- '(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string
- '(\\#[-a-z\\d_]*)?$','i'); // fragment locator
- if(!pattern.test(str)) {
- that.errorMsg('Please enter a valid URL.');
- return false;
- } else {
- return true;
- }
- };
-
- if (ValidURL(url)) {
- var win = window.open(url, '_blank')
- if (win) {
- // Browser has allowed it to be opened.
- win.focus();
- } else {
- // Broswer has blocked it.
- alert('Please allow popups for this site');
- }
- }
- break;
- case 'vspace':
- break;
- case 'playback':
- var sound = new Howl({
- urls: [args[0]]
- });
- that.sounds.push(sound);
- sound.play();
- break;
- case 'stopplayback':
- for (var sound in that.sounds) {
- that.sounds[sound].stop();
- }
- that.sounds = [];
- break;
- case 'stopvideocam':
- if (cameraID != null) {
- doStopVideoCam(that.cameraID, that.setCameraID);
- }
- break;
- case 'showblocks':
- that.showBlocks();
- that.setTurtleDelay(DEFAULTDELAY);
- break;
- case 'hideblocks':
- that.hideBlocks();
- that.setTurtleDelay(0);
- break;
- case 'savesvg':
- if (args.length === 1) {
- if (that.svgBackground) {
- that.svgOutput = '<rect x="0" y="0" height="' + this.canvas.height + '" width="' + this.canvas.width + '" fill="' + body.style.background + '"/> ' + that.svgOutput;
- }
- doSaveSVG(that, args[0]);
- }
- break;
- case 'showHeap':
- if (!(turtle in that.turtleHeaps)) {
- that.turtleHeaps[turtle] = [];
- }
- that.textMsg(JSON.stringify(that.turtleHeaps[turtle]));
- break;
- case 'emptyHeap':
- that.turtleHeaps[turtle] = [];
- break;
- case 'push':
- if (args.length === 1) {
- if (!(turtle in that.turtleHeaps)) {
- that.turtleHeaps[turtle] = [];
- }
- that.turtleHeaps[turtle].push(args[0]);
- }
- break;
- case 'saveHeap':
- function downloadFile(filename, mimetype, content) {
- var download = document.createElement('a');
- download.setAttribute('href', 'data:' + mimetype + ';charset-utf-8,' + content);
- download.setAttribute('download', filename);
- document.body.appendChild(download);
- download.click();
- document.body.removeChild(download);
- };
-
- if (args[0] && turtle in that.turtleHeaps) {
- downloadFile(args[0], 'text/json', JSON.stringify(that.turtleHeaps[turtle]));
- }
- break;
- case 'loadHeap':
- var block = that.blocks.blockList[blk];
- if (turtle in that.turtleHeaps) {
- var oldHeap = that.turtleHeaps[turtle];
- } else {
- var oldHeap = [];
- }
- var c = block.connections[1];
- if (c != null && that.blocks.blockList[c].name === 'loadFile') {
- if (args.length !== 1) {
- that.errorMsg(_('You must select a file.'));
- } else {
- try {
- that.turtleHeaps[turtle] = JSON.parse(that.blocks.blockList[c].value[1]);
- if (!Array.isArray(that.turtleHeaps[turtle])) {
- throw 'is not array';
- }
- } catch (e) {
- that.turtleHeaps[turtle] = oldHeap;
- that.errorMsg(_('The file you selected does not contain a valid heap.'));
- }
- }
- } else {
- that.errorMsg(_('The loadHeap block needs a loadFile block.'))
- }
- break;
- case 'loadHeapFromApp':
- var data = [];
- var url = args[1];
- var name = args [0]
- var xmlHttp = new XMLHttpRequest();
- xmlHttp.open('GET', url, false );
- xmlHttp.send();
- if (xmlHttp.readyState === 4 && xmlHttp.status === 200){
- console.log(xmlHttp.responseText);
- try {
- var data = JSON.parse(xmlHttp.responseText);
- } catch (e) {
- console.log(e);
- that.errorMsg(_('Error parsing JSON data:') + e);
- }
- }
- else if (xmlHttp.readyState === 4 && xmlHttp.status !== 200) {
- console.log('fetched the wrong page or network error...');
- that.errorMsg(_('404: Page not found'));
- break;
- }
- else {
- that.errorMsg('xmlHttp.readyState: ' + xmlHttp.readyState);
- break;
- }
- if (name in that.turtleHeaps){
- var oldHeap = turtleHeaps[turtle];
- } else {
- var oldHeap = [];
- }
- that.turtleHeaps[name] = data;
- break;
- case 'saveHeapToApp':
- var name = args[0];
- var url = args[1];
- if (name in that.turtleHeaps) {
- var data = JSON.stringify(that.turtleHeaps[name]);
- var xmlHttp = new XMLHttpRequest();
- xmlHttp.open('POST', url, true);
- xmlHttp.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
- xmlHttp.send(data);
- } else {
- that.errorMsg(_('turtleHeaps does not contain a valid heap for') + ' ' + name);
- }
- break;
- case 'setHeapEntry':
- if (args.length === 2) {
- if (!(turtle in that.turtleHeaps)) {
- that.turtleHeaps[turtle] = [];
- }
- var idx = Math.floor(args[0]);
- if (idx < 1) {
- that.errorMsg(_('Index must be > 0.'))
- }
- // If index > heap length, grow the heap.
- while (that.turtleHeaps[turtle].length < idx) {
- that.turtleHeaps[turtle].push(null);
- }
- that.turtleHeaps[turtle][idx - 1] = args[1];
- }
- break;
-
- // Actions for music-related blocks
- case 'savelilypond':
- if (args.length === 1) {
- saveLilypondOutput(that, args[0]);
- }
- break;
- case 'setmasterbpm':
- if (args.length === 1 && typeof(args[0] === 'number')) {
- if (args[0] < 30) {
- that.errorMsg(_('Beats per minute must be > 30.'))
- that._masterBPM = 30;
- } else if (args[0] > 1000) {
- that.errorMsg(_('Maximum beats per minute is 1000.'))
- that._masterBPM = 1000;
- } else {
- that._masterBPM = args[0];
- }
- that.defaultBPMFactor = TONEBPM / this._masterBPM;
- }
-
- if (this.inTempo) {
- that.tempo.BPMBlocks.push(blk);
- var bpmnumberblock = that.blocks.blockList[blk].connections[1]
- that.tempo.BPMs.push(that.blocks.blockList[bpmnumberblock].text.text);
- }
- break;
- case 'setbpm':
- if (args.length === 2 && typeof(args[0] === 'number')) {
- if (args[0] < 30) {
- that.errorMsg(_('Beats per minute must be > 30.'))
- var bpm = 30;
- } else if (args[0] > 1000) {
- that.errorMsg(_('Maximum beats per minute is 1000.'))
- var bpm = 1000;
- } else {
- var bpm = args[0];
- }
-
- that.bpm[turtle].push(bpm);
-
- childFlow = args[1];
- childFlowCount = 1;
-
- var listenerName = '_bpm_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.bpm[turtle].pop();
- };
-
- that._setListener(turtle, listenerName, __listener);
- }
- break;
- // Deprecated
- case 'setkey':
- if (args.length === 1) {
- that.keySignature[turtle] = args[0];
- }
- break;
- case 'setkey2':
- if (args.length === 2) {
- var modename = 'major';
- for (var i = 0; i < MODENAMES.length; i++) {
- if (MODENAMES[i][0] === args[1]) {
- modename = MODENAMES[i][1];
- that._modeBlock = that.blocks.blockList[blk].connections[2];
- console.log(modename);
- break;
- }
- }
- that.keySignature[turtle] = args[0] + ' ' + modename;
- }
- break;
- case 'rhythmruler':
- console.log("running rhythmruler");
-
- childFlow = args[1];
- childFlowCount = 1;
-
- if (that.rhythmRuler == null) {
- that.rhythmRuler = new RhythmRuler();
- }
-
- // To do: restore previous state
- that.rhythmRuler.Rulers = [];
- that.rhythmRuler.Drums = [];
- that.inRhythmRuler = true;
-
- var listenerName = '_rhythmruler_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.rhythmRuler.init(that);
- };
-
- that._setListener(turtle, listenerName, __listener);
- break;
- case 'pitchstaircase':
- if (that.pitchStaircase == null) {
- that.pitchStaircase = new PitchStaircase();
- }
-
- that.pitchStaircase.Stairs = [];
-
- childFlow = args[0];
- childFlowCount = 1;
- that.inPitchStaircase = true;
-
- var listenerName = '_pitchstaircase_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.pitchStaircase.init(that);
- that.inPitchStaircase = false;
- };
-
- that._setListener(turtle, listenerName, __listener);
- break;
- case 'tempo':
- console.log("running Tempo");
- childFlow = args[0];
- childFlowCount = 1;
-
- if (that.tempo == null) {
- that.tempo = new Tempo();
- }
-
- that.inTempo = true;
- that.tempo.BPMblocks = [];
- that.tempo.BPMs = [];
-
- var listenerName = '_tempo_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.tempo.init(that);
- };
-
- that._setListener(turtle, listenerName, __listener);
- break;
- case 'pitchslider':
- if (that.pitchSlider == null) {
- that.pitchSlider = new PitchSlider();
- }
-
- that.pitchSlider.Sliders = [];
-
- childFlow = args[0];
- childFlowCount = 1;
- that.inPitchSlider = true;
-
- var listenerName = '_pitchslider_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.pitchSlider.init(that);
- that.inPitchSlider = false;
- };
-
- that._setListener(turtle, listenerName, __listener);
- break;
- case 'pitchdrummatrix':
- if (args.length === 1) {
- childFlow = args[0];
- childFlowCount = 1;
- }
-
- if (that.pitchDrumMatrix == null) {
- that.pitchDrumMatrix = new PitchDrumMatrix();
- }
-
- that.inPitchDrumMatrix = true;
- that.pitchDrumMatrix.rowLabels = [];
- that.pitchDrumMatrix.rowArgs = [];
- that.pitchDrumMatrix.drums = [];
- that.pitchDrumMatrix.clearBlocks();
-
- var listenerName = '_pitchdrummatrix_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- if (that.pitchDrumMatrix.drums.length === 0 || that.pitchDrumMatrix.rowLabels.length === 0) {
- that.errorMsg(_('You must have at least one pitch block and one drum block in the matrix.'), blk);
- } else {
- // Process queued up rhythms.
- that.pitchDrumMatrix.init(that);
- that.pitchDrumMatrix.makeClickable();
- }
- };
-
- that._setListener(turtle, listenerName, __listener);
- break;
- case 'modewidget':
- if (args.length === 1) {
- childFlow = args[0];
- childFlowCount = 1;
- }
-
- if (that.modeWidget == null) {
- that.modeWidget = new ModeWidget();
- }
-
- var listenerName = '_modewidget_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- console.log(that.keySignature[turtle]);
- that.modeWidget.init(that, that._modeBlock);
- }
-
- that._setListener(turtle, listenerName, __listener);
- break;
- case 'status':
- if (that.statusMatrix == null) {
- that.statusMatrix = new StatusMatrix();
- }
-
- that.statusMatrix.init(that);
- that.statusFields = [];
- if (args.length === 1) {
- childFlow = args[0];
- childFlowCount = 1;
- }
-
- that.inStatusMatrix = true;
-
- var listenerName = '_status_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.statusMatrix.init(that);
- that.inStatusMatrix = false;
- }
-
- that._setListener(turtle, listenerName, __listener);
- break;
- case 'matrix':
- if (args.length === 1) {
- childFlow = args[0];
- childFlowCount = 1;
- }
-
- that.inMatrix = true;
-
- if (that.pitchTimeMatrix == null) {
- that.pitchTimeMatrix = new PitchTimeMatrix();
- }
-
- that.pitchTimeMatrix.rowLabels = [];
- that.pitchTimeMatrix.rowArgs = [];
- that.pitchTimeMatrix.graphicsBlocks = [];
- that.pitchTimeMatrix.clearBlocks();
-
- that.tupletRhythms = [];
- that.tupletParams = [];
- that.addingNotesToTuplet = false;
-
- var listenerName = '_matrix_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- if (that.tupletRhythms.length === 0 || that.pitchTimeMatrix.rowLabels.length === 0) {
- that.errorMsg(_('You must have at least one pitch block and one rhythm block in the matrix.'), blk);
- } else {
- // Process queued up rhythms.
- that.pitchTimeMatrix.init(that);
-
- for (var i = 0; i < that.tupletRhythms.length; i++) {
- // We have two cases: (1) notes in a tuplet;
- // and (2) rhythm block outside of a
- // tuplet. Rhythm blocks in a tuplet are
- // converted to notes.
- switch (that.tupletRhythms[i][0]) {
- case 'notes':
- case 'simple':
- var tupletParam = [that.tupletParams[that.tupletRhythms[i][1]]];
- tupletParam.push([]);
- for (var j = 2; j < that.tupletRhythms[i].length; j++) {
- tupletParam[1].push(that.tupletRhythms[i][j]);
- }
- that.pitchTimeMatrix.addTuplet(tupletParam);
- break;
- default:
- that.pitchTimeMatrix.addNotes(that.tupletRhythms[i][1], that.tupletRhythms[i][2]);
- break;
- }
- }
-
- that.pitchTimeMatrix.makeClickable();
- }
- };
-
- that._setListener(turtle, listenerName, __listener);
- break;
- case 'invert1':
- if (typeof(args[2]) === 'number') {
- if (args[2] % 2 === 0){
- args[2] = 'even';
- } else {
- args[2] = 'odd';
- }
- }
-
- if (args[2] === _('even')) {
- args2 = 'even';
- }
-
- if (args[2] === _('odd')) {
- args2 = 'odd';
- }
-
- if (args[2] === 'even' || args[2] === 'odd'){
- var octave = calcOctave(that.currentOctaves[turtle], args[1]);
- that.invertList[turtle].push([args[0], octave, args[2]]);
- } else {
- that.errorMsg(NOINPUTERRORMSG, blk);
- that.stopTurtle = true;
- break;
- }
-
- childFlow = args[3];
- childFlowCount = 1;
- var listenerName = '_invert_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.invertList[turtle].pop();
- };
-
- that._setListener(turtle, listenerName, __listener);
- break;
- case 'invert2':
- case 'invert':
- // Deprecated
- if (that.blocks.blockList[blk].name === 'invert') {
- that.invertList[turtle].push([args[0], args[1], 'even']);
- } else {
- that.invertList[turtle].push([args[0], args[1], 'odd']);
- }
- childFlow = args[2];
- childFlowCount = 1;
-
- var listenerName = '_invert_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.invertList[turtle].pop();
- };
-
- that._setListener(turtle, listenerName, __listener);
- break;
- case 'backward':
- that.backward[turtle].push(blk);
- // Set child to bottom block inside clamp
- childFlow = that.blocks.findBottomBlock(args[0]);
- childFlowCount = 1;
-
- var listenerName = '_backward_' + turtle + '_' + blk;
-
- var nextBlock = this.blocks.blockList[blk].connections[1];
- if (nextBlock == null) {
- that.backward[turtle].pop();
- } else {
- that.endOfClampSignals[turtle][nextBlock] = [listenerName];
- }
-
- var __listener = function (event) {
- that.backward[turtle].pop();
- // Since a backward block was requeued each
- // time, we need to flush it from the queue.
- // that.turtles.turtleList[turtle].queue.pop();
- };
-
- that._setListener(turtle, listenerName, __listener);
- break;
- case 'rest2':
- that.notePitches[turtle].push('rest');
- that.noteOctaves[turtle].push(4);
- that.noteCents[turtle].push(0);
- that.noteHertz[turtle].push(0);
- if (turtle in that.beatFactor) {
- that.noteBeatValues[turtle].push(that.beatFactor[turtle]);
- } else {
- that.noteBeatValues[turtle].push(1);
- }
- that.pushedNote[turtle] = true;
- break;
- case 'steppitch':
- // Similar to pitch but calculated from previous note played.
- if (that.inNoteBlock[turtle] === 0) {
- that.errorMsg(_('The Step Pitch Block must be used inside of a Note Block.'), blk);
- that.stopTurtle = true;
- break;
- }
-
- if (typeof(args[0]) !== 'number') {
- that.errorMsg(NANERRORMSG, blk);
- that.stopTurtle = true;
- break;
- }
-
- if (that.lastNotePlayed[turtle] == null) {
- that.errorMsg('The Step Pitch Block must be preceded by a Pitch Block.', blk);
- that.stopTurtle = true;
- break;
- }
-
- function addPitch(note, octave, cents) {
- if (that.drumStyle[turtle].length > 0) {
- var drumname = last(that.drumStyle[turtle]);
- var note2 = that.getNote(note, octave, transposition, that.keySignature[turtle]);
- that.pitchDrumTable[turtle][note2[0] + note2[1]] = drumname;
- }
- that.notePitches[turtle].push(note);
- that.noteOctaves[turtle].push(octave);
- that.noteCents[turtle].push(cents);
- if (cents !== 0) {
- that.noteHertz[turtle].push(pitchToFrequency(note, octave, cents, that.keySignature[turtle]));
- } else {
- that.noteHertz[turtle].push(0);
- }
- }
-
- var len = that.lastNotePlayed[turtle][0].length;
- if (args[0] >= 1) {
- var n = Math.floor(args[0]);
- var value = getStepSizeUp(that.keySignature[turtle], that.lastNotePlayed[turtle][0].slice(0, len - 1));
- var noteObj = that.getNote(that.lastNotePlayed[turtle][0].slice(0, len - 1), parseInt(that.lastNotePlayed[turtle][0].slice(len - 1)), value, that.keySignature[turtle]);
- for (var i = 1; i < n; i++) {
- var value = getStepSizeUp(that.keySignature[turtle], noteObj[0]);
- noteObj = that.getNote(noteObj[0], noteObj[1], value, that.keySignature[turtle]);
- }
- } else if (args[0] <= -1) {
- var n = -Math.ceil(args[0]);
- value = getStepSizeDown(that.keySignature[turtle], that.lastNotePlayed[turtle][0].slice(0, len - 1));
- var noteObj = that.getNote(that.lastNotePlayed[turtle][0].slice(0, len - 1), parseInt(that.lastNotePlayed[turtle][0].slice(len - 1)), value, that.keySignature[turtle]);
- for (var i = 1; i < n; i++) {
- var value = getStepSizeDown(that.keySignature[turtle], noteObj[0]);
- noteObj = that.getNote(noteObj[0], noteObj[1], value, that.keySignature[turtle]);
- }
- } else { // Repeat last pitch played.
- var noteObj = that.getNote(that.lastNotePlayed[turtle][0].slice(0, len - 1), parseInt(that.lastNotePlayed[turtle][0].slice(len - 1)), 0, that.keySignature[turtle]);
- }
-
- var delta = 0;
- if (!(that.invertList[turtle].length === 0)) {
- var len = that.invertList[turtle].length;
- var note1 = that.getNote(noteObj[0], noteObj[1], 0, that.keySignature[turtle]);
- var num1 = getNumber(note1[0], note1[1]);
- for (var i = len - 1; i > -1; i--) {
- var note2 = that.getNote(that.invertList[turtle][i][0], that.invertList[turtle][i][1], 0, that.keySignature[turtle]);
- var num2 = getNumber(note2[0], note2[1]);
- // var a = getNumNote(num1, 0);
- if (that.invertList[turtle][i][2] === 'even') {
- delta += num2 - num1;
- } else { // odd
- delta += num2 - num1 + 0.5;
- }
- num1 += 2 * delta;
- }
- }
-
- addPitch(noteObj[0], noteObj[1], 0);
-
- if (turtle in that.intervals && that.intervals[turtle].length > 0) {
- for (var i = 0; i < that.intervals[turtle].length; i++) {
- var ii = getInterval(that.intervals[turtle][i], that.keySignature[turtle], noteObj[0]);
- var noteObj2 = that.getNote(noteObj[0], noteObj[1], ii, that.keySignature[turtle]);
- addPitch(noteObj2[0], noteObj2[1], 0);
- }
- }
-
- if (turtle in that.perfect && that.perfect[turtle].length > 0) {
- var noteObj2 = that.getNote(noteObj[0], noteObj[1], calcPerfect(last(that.perfect[turtle])), that.keySignature[turtle]);
- addPitch(noteObj2[0], noteObj2[1], 0);
- }
-
- if (turtle in that.diminished && that.diminished[turtle].length > 0) {
- var noteObj2 = that.getNote(noteObj[0], noteObj[1], calcDiminished(last(that.diminished[turtle])), that.keySignature[turtle]);
- addPitch(noteObj2[0], noteObj2[1], 0);
- }
-
- if (turtle in that.augmented && that.augmented[turtle].length > 0) {
- var noteObj2 = that.getNote(noteObj[0], noteObj[1], calcAugmented(last(that.augmented[turtle])), that.keySignature[turtle]);
- addPitch(noteObj2[0], noteObj2[1], 0);
- }
-
- if (turtle in that.major && that.major[turtle].length > 0) {
- var noteObj2 = that.getNote(noteObj[0], noteObj[1], calcMajor(last(that.major[turtle])), that.keySignature[turtle]);
- addPitch(noteObj2[0], noteObj2[1], 0);
- }
-
- if (turtle in that.minor && that.minor[turtle].length > 0) {
- var noteObj2 = that.getNote(noteObj[0], noteObj[1], calcMinor(last(that.minor[turtle])), that.keySignature[turtle]);
- addPitch(noteObj2[0], noteObj2[1], 0);
- }
-
- if (turtle in that.transposition) {
- that.noteTranspositions[turtle].push(that.transposition[turtle] + 2 * delta);
- } else {
- that.noteTranspositions[turtle].push(2 * delta);
- }
-
- if (turtle in that.beatFactor) {
- that.noteBeatValues[turtle].push(that.beatFactor[turtle]);
- } else {
- that.noteBeatValues[turtle].push(1);
- }
-
- that.pushedNote[turtle] = true;
- break;
- case 'playdrum':
- if (args.length !== 1 || args[0] == null) {
- that.errorMsg(NOINPUTERRORMSG, blk);
- that.stopTurtle = true;
- break;
- }
-
- if (typeof(args[0]) !== 'string') {
- that.errorMsg(NANERRORMSG, blk);
- that.stopTurtle = true;
- break;
- }
-
- var drumname = 'kick';
- if (args[0].slice(0, 4) === 'http') {
- drumname = args[0];
- } else {
- for (var drum in DRUMNAMES) {
- if (DRUMNAMES[drum][0] === args[0]) {
- drumname = DRUMNAMES[drum][1];
- break;
- } else if (DRUMNAMES[drum][1] === args[0]) {
- drumname = args[0];
- break;
- }
- }
- }
-
- // If we are in a setdrum clamp, override the drum name.
- if (that.drumStyle[turtle].length > 0) {
- drumname = last(that.drumStyle[turtle]);
- }
-
- if (that.inPitchDrumMatrix) {
- that.pitchDrumMatrix.drums.push(drumname);
- that.pitchDrumMatrix.addColBlock(blk);
- if (that.drumBlocks.indexOf(blk) === -1) {
- that.drumBlocks.push(blk);
- }
- } else if (that.inMatrix) {
- that.pitchTimeMatrix.rowLabels.push(drumname);
- that.pitchTimeMatrix.rowArgs.push(-1);
-
- that.pitchTimeMatrix.addRowBlock(blk);
- if (that.drumBlocks.indexOf(blk) === -1) {
- that.drumBlocks.push(blk);
- }
- } else if (that.inNoteBlock[turtle] > 0) {
- that.noteDrums[turtle].push(drumname);
- } else {
- that.errorMsg(_('Drum Block: Did you mean to use a Note block?'), blk);
- break;
- }
-
- if (turtle in that.beatFactor) {
- that.noteBeatValues[turtle].push(that.beatFactor[turtle]);
- } else {
- that.noteBeatValues[turtle].push(1);
- }
-
- that.pushedNote[turtle] = true;
- break;
- case 'setpitchnumberoffset':
- if (args.length !== 2 || args[0] == null || args[1] == null) {
- that.errorMsg(NOINPUTERRORMSG, blk);
- that.stopTurtle = true;
- break;
- }
-
- var octave = Math.floor(calcOctave(that.currentOctaves[turtle], args[1]));
- that.pitchNumberOffset = pitchToNumber(args[0], octave, that.keySignature[turtle]);
- break;
- case 'pitchnumber':
- case 'scaledegree':
- case 'pitch':
- if (that.blocks.blockList[blk].name == 'pitchnumber') {
- if (args.length !== 1 || args[0] == null) {
- that.errorMsg(NOINPUTERRORMSG, blk);
- that.stopTurtle = true;
- break;
- }
-
- if (typeof(args[0]) !== 'number') {
- that.errorMsg(NANERRORMSG, blk);
- that.stopTurtle = true;
- break;
- }
-
- // In number to pitch we assume A0 == 0. Here we
- // assume that C4 == 0, so we need an offset of 39.
- var obj = numberToPitch(Math.floor(args[0] + that.pitchNumberOffset));
- note = obj[0];
- octave = obj[1];
- cents = 0;
- } else {
- if (args.length !== 2 || args[0] == null || args[1] == null) {
- that.errorMsg(NOINPUTERRORMSG, blk);
- that.stopTurtle = true;
- break;
- }
-
- /*
- if (typeof(args[1]) !== 'number') {
- that.errorMsg(NANERRORMSG, blk);
- that.stopTurtle = true;
- break;
- }
- */
-
- if (typeof(args[0]) === 'number' && that.blocks.blockList[blk].name == 'pitch') {
- // We interpret numbers two different ways:
- // (1) a positive integer between 1 and 12 is taken to be
- // a moveable solfege, e.g., 1 == do; 2 == re...
- // (2) if frequency is input, ignore octave (args[1]).
- // Negative numbers will throw an error.
- if (args[0] < 1) {
- note = '?'; // throws an error
- } else if (args[0] < 13) { // moveable solfege
- note = scaleDegreeToPitch(that.keySignature[turtle], Math.floor(args[0]));
- var octave = Math.floor(calcOctave(that.currentOctaves[turtle], args[1]));
- var cents = 0;
- } else if (args[0] < A0 || args[0] > C8) {
- note = '?'; // throws an error
- } else {
- var obj = frequencyToPitch(args[0]);
- var note = obj[0];
- var octave = obj[1];
- var cents = obj[2];
- }
-
- if (note === '?') {
- that.errorMsg(INVALIDPITCH, blk);
- that.stopTurtle = true;
- break;
- }
- } else if (typeof(args[0]) === 'number' && that.blocks.blockList[blk].name == 'scaledegree') {
- if (args[0] < 0) {
- var neg = true;
- args[0] = -args[0];
- } else {
- var neg = false;
- }
-
- if (args[0] == 0) {
- note = '?'; // throws an error
- } else {
- var obj = keySignatureToMode(that.keySignature[turtle]);
- var modeLength = MUSICALMODES[obj[1]].length;
- var scaleDegree = Math.floor(args[0] - 1) % modeLength;
- scaleDegree += 1;
-
- if (neg) {
- // -1, 4 --> do 4; -2, 4 --> ti 3; -8, 4 --> do 3
- if (scaleDegree > 1) {
- scaleDegree = modeLength - scaleDegree + 2;
- }
- note = scaleDegreeToPitch(that.keySignature[turtle], scaleDegree);
- var deltaOctave = Math.floor((args[0] + modeLength - 2) / modeLength);
- var octave = Math.floor(calcOctave(that.currentOctaves[turtle], args[1])) - deltaOctave;
- } else {
- // 1, 4 --> do 4; 2, 4 --> re 4; 8, 4 --> do 5
- note = scaleDegreeToPitch(that.keySignature[turtle], scaleDegree);
- var deltaOctave = Math.floor((args[0] - 1) / modeLength);
- var octave = Math.floor(calcOctave(that.currentOctaves[turtle], args[1])) + deltaOctave;
- }
- var cents = 0;
- }
-
- if (note === '?') {
- that.errorMsg(INVALIDPITCH, blk);
- that.stopTurtle = true;
- break;
- }
- } else {
- var cents = 0;
- var note = args[0];
- if (calcOctave(that.currentOctaves[turtle], args[1]) < 0) {
- console.log('minimum allowable octave is 0');
- var octave = 0;
- } else if (calcOctave(that.currentOctaves[turtle], args[1]) > 10) {
- // Humans can only hear 10 octaves.
- console.log('clipping octave at 10');
- var octave = 10;
- } else {
- // Octave must be a whole number.
- var octave = Math.floor(calcOctave(that.currentOctaves[turtle], args[1]));
- }
-
- that.getNote(note, octave, 0, that.keySignature[turtle]);
- if (!that.validNote) {
- that.errorMsg(INVALIDPITCH, blk);
- that.stopTurtle = true;
- break;
- }
- }
- }
-
- var delta = 0;
-
- if (that.inPitchDrumMatrix) {
- if (note.toLowerCase() !== 'rest') {
- that.pitchDrumMatrix.addRowBlock(blk);
- if (that.pitchBlocks.indexOf(blk) === -1) {
- that.pitchBlocks.push(blk);
- }
- }
- if (!(that.invertList[turtle].length === 0)) {
- var delta = 0;
- var len = that.invertList[turtle].length;
- // Get an anchor note and its corresponding
- // number, which is used to calculate delta.
- var note1 = that.getNote(note, octave, 0, that.keySignature[turtle]);
- var num1 = that.getNumber(note1[0], note1[1]);
- for (var i = len - 1; i > -1; i--) {
- // Note from which delta is calculated.
- var note2 = that.getNote(that.invertList[turtle][i][0], that.invertList[turtle][i][1], 0, that.keySignature[turtle]);
- var num2 = getNumber(note2[0], note2[1]);
- // var a = getNumNote(num1, 0);
- if (that.invertList[turtle][i][2] === 'even') {
- delta += num2 - num1;
- } else { // odd
- delta += num2 - num1 + 0.5;
- }
- num1 += 2 * delta;
- }
- }
-
- if (that.duplicateFactor[turtle].length > 0) {
- var duplicateFactor = that.duplicateFactor[turtle];
- } else {
- var duplicateFactor = 1;
- }
- for (var i = 0; i < duplicateFactor; i++) {
- // Apply transpositions
- var transposition = 2 * delta;
- if (turtle in that.transposition) {
- transposition += that.transposition[turtle];
- }
-
- var nnote = that.getNote(note, octave, transposition, that.keySignature[turtle]);
- if (noteIsSolfege(note)) {
- nnote[0] = getSolfege(nnote[0]);
- }
-
- if (that.drumStyle[turtle].length > 0) {
- that.pitchDrumMatrix.drums.push(last(that.drumStyle[turtle]));
- } else {
- that.pitchDrumMatrix.rowLabels.push(nnote[0]);
- that.pitchDrumMatrix.rowArgs.push(nnote[1]);
- }
- }
- } else if (that.inMatrix) {
- if (note.toLowerCase() !== 'rest') {
- that.pitchTimeMatrix.addRowBlock(blk);
- if (that.pitchBlocks.indexOf(blk) === -1) {
- that.pitchBlocks.push(blk);
- }
- }
-
- if (!(that.invertList[turtle].length === 0)) {
- var delta = 0;
- var len = that.invertList[turtle].length;
- // Get an anchor note and its corresponding
- // number, which is used to calculate delta.
- var note1 = that.getNote(note, octave, 0, that.keySignature[turtle]);
- var num1 = that.getNumber(note1[0], note1[1]);
- for (var i = len - 1; i > -1; i--) {
- // Note from which delta is calculated.
- var note2 = that.getNote(that.invertList[turtle][i][0], that.invertList[turtle][i][1], 0, that.keySignature[turtle]);
- var num2 = getNumber(note2[0], note2[1]);
- // var a = getNumNote(num1, 0);
- if (that.invertList[turtle][i][2] === 'even') {
- delta += num2 - num1;
- } else { // odd
- delta += num2 - num1 + 0.5;
- }
- num1 += 2 * delta;
- }
- }
-
- if (that.duplicateFactor[turtle].length > 0) {
- var duplicateFactor = that.duplicateFactor[turtle];
- } else {
- var duplicateFactor = 1;
- }
- for (var i = 0; i < duplicateFactor; i++) {
- // Apply transpositions
- var transposition = 2 * delta;
- if (turtle in that.transposition) {
- transposition += that.transposition[turtle];
- }
-
- var nnote = that.getNote(note, octave, transposition, that.keySignature[turtle]);
- if (noteIsSolfege(note)) {
- nnote[0] = getSolfege(nnote[0]);
- }
-
- // If we are in a setdrum clamp, override the pitch.
- if (that.drumStyle[turtle].length > 0) {
- that.pitchTimeMatrix.rowLabels.push(last(that.drumStyle[turtle]));
- that.pitchTimeMatrix.rowArgs.push(-1);
- } else {
- that.pitchTimeMatrix.rowLabels.push(nnote[0]);
- that.pitchTimeMatrix.rowArgs.push(nnote[1]);
- }
- }
- } else if (that.inNoteBlock[turtle] > 0) {
-
- function addPitch(note, octave, cents) {
- if (that.drumStyle[turtle].length > 0) {
- var drumname = last(that.drumStyle[turtle]);
- var note2 = that.getNote(note, octave, transposition, that.keySignature[turtle]);
- that.pitchDrumTable[turtle][note2[0]+note2[1]] = drumname;
- }
- that.notePitches[turtle].push(note);
- that.noteOctaves[turtle].push(octave);
- that.noteCents[turtle].push(cents);
- if (cents !== 0) {
- that.noteHertz[turtle].push(pitchToFrequency(note, octave, cents, that.keySignature[turtle]));
- } else {
- that.noteHertz[turtle].push(0);
- }
- }
-
- if (!(that.invertList[turtle].length === 0)) {
- var len = that.invertList[turtle].length;
- var note1 = that.getNote(note, octave, 0, that.keySignature[turtle]);
- var num1 = getNumber(note1[0], note1[1]);
- for (var i = len - 1; i > -1; i--) {
- var note2 = that.getNote(that.invertList[turtle][i][0], that.invertList[turtle][i][1], 0, that.keySignature[turtle]);
- var num2 = getNumber(note2[0], note2[1]);
- // var a = getNumNote(num1, 0);
- if (that.invertList[turtle][i][2] === 'even') {
- delta += num2 - num1;
- } else { // odd
- delta += num2 - num1 + 0.5;
- }
- num1 += 2 * delta;
- }
- }
-
- addPitch(note, octave, cents);
-
- if (turtle in that.intervals && that.intervals[turtle].length > 0) {
- for (var i = 0; i < that.intervals[turtle].length; i++) {
- var ii = getInterval(that.intervals[turtle][i], that.keySignature[turtle], note);
- var noteObj = that.getNote(note, octave, ii, that.keySignature[turtle]);
- addPitch(noteObj[0], noteObj[1], cents);
- }
- }
-
- if (turtle in that.perfect && that.perfect[turtle].length > 0) {
- var noteObj = that.getNote(note, octave, calcPerfect(last(that.perfect[turtle])), that.keySignature[turtle]);
- addPitch(noteObj[0], noteObj[1], cents);
- }
-
- if (turtle in that.diminished && that.diminished[turtle].length > 0) {
- var noteObj = that.getNote(note, octave, calcDiminished(last(that.diminished[turtle])), that.keySignature[turtle]);
- addPitch(noteObj[0], noteObj[1], cents);
- }
-
- if (turtle in that.augmented && that.augmented[turtle].length > 0) {
- var noteObj = that.getNote(note, octave, calcAugmented(last(that.augmented[turtle])), that.keySignature[turtle]);
- addPitch(noteObj[0], noteObj[1], cents);
- }
-
- if (turtle in that.major && that.major[turtle].length > 0) {
- var noteObj = that.getNote(note, octave, calcMajor(last(that.major[turtle])), that.keySignature[turtle]);
- addPitch(noteObj[0], noteObj[1], cents);
- }
-
- if (turtle in that.minor && that.minor[turtle].length > 0) {
- var noteObj = that.getNote(note, octave, calcMinor(last(that.minor[turtle])), that.keySignature[turtle]);
- addPitch(noteObj[0], noteObj[1], cents);
- }
-
- if (turtle in that.transposition) {
- that.noteTranspositions[turtle].push(that.transposition[turtle] + 2 * delta);
- } else {
- that.noteTranspositions[turtle].push(2 * delta);
- }
-
- if (turtle in that.beatFactor) {
- that.noteBeatValues[turtle].push(that.beatFactor[turtle]);
- } else {
- that.noteBeatValues[turtle].push(1);
- }
-
- that.pushedNote[turtle] = true;
- } else if (that.drumStyle[turtle].length > 0) {
- var drumname = last(that.drumStyle[turtle]);
- var note2 = that.getNote(note, octave, transposition, that.keySignature[turtle]);
- that.pitchDrumTable[turtle][note2[0]+note2[1]] = drumname;
- } else if (that.inPitchStaircase) {
- var frequency = pitchToFrequency(args[0], calcOctave(that.currentOctaves[turtle], args[1]), 0, that.keySignature[turtle]);
- var note = that.getNote(args[0], calcOctave(that.currentOctaves[turtle], args[1]), 0, that.keySignature[turtle]);
- var flag = 0;
-
- for (var i = 0 ; i < that.pitchStaircase.Stairs.length; i++) {
- if (that.pitchStaircase.Stairs[i][2] < parseFloat(frequency)) {
- that.pitchStaircase.Stairs.splice(i, 0, [note[0], note[1], parseFloat(frequency), 1, 1]);
- flag = 1;
- break;
- }
-
- if (that.pitchStaircase.Stairs[i][2] === parseFloat(frequency)) {
- that.pitchStaircase.Stairs.splice(i, 1, [note[0], note[1], parseFloat(frequency), 1, 1]);
- flag = 1;
- break;
- }
- }
-
- if (flag === 0) {
- that.pitchStaircase.Stairs.push([note[0], note[1], parseFloat(frequency), 1, 1]);
- }
- }
- else {
- that.errorMsg(_('Pitch Block: Did you mean to use a Note block?'), blk);
- }
- break;
- case 'rhythm2':
- case 'rhythm':
- if (args.length < 2 || typeof(args[0]) !== 'number' || typeof(args[1]) !== 'number' || args[0] < 1 || args[1] <= 0) {
- that.errorMsg(NOINPUTERRORMSG, blk);
- that.stopTurtle = true;
- break;
- }
-
- if (that.blocks.blockList[blk].name === 'rhythm2') {
- var noteBeatValue = 1 / args[1];
- } else {
- var noteBeatValue = args[1];
- }
-
- if (that.inMatrix) {
- that.pitchTimeMatrix.addColBlock(blk, args[0]);
- for (var i = 0; i < args[0]; i++) {
- that._processNote(noteBeatValue, blk, turtle);
- }
- } else if (that.inRhythmRuler) {
- // Temporary work-around to #272.
- if (that.rhythmRulerMeasure === null) {
- that.rhythmRulerMeasure = args[0] * args[1];
- } else if (that.rhythmRulerMeasure != (args[0] * args[1])) {
- that.errorMsg('Rhythm Ruler imbalance.', blk);
- that.stopTurtle = true;
- }
-
- // Since there maybe more than one instance of the
- // same drum, e.g., if a repeat is used, we look from
- // end of the list instead of the beginning of the
- // list.
-
- var drumIndex = -1;
- for (var i = 0; i < that.rhythmRuler.Drums.length; i++) {
- var j = that.rhythmRuler.Drums.length - i - 1;
- if (that.rhythmRuler.Drums[j] === that._currentDrumBlock) {
- drumIndex = j;
- break;
- }
- }
-
- if (drumIndex !== -1) {
- for (var i = 0; i < args[0]; i++) {
- that.rhythmRuler.Rulers[drumIndex][0].push(noteBeatValue);
- }
- }
- } else {
- that.errorMsg(_('Rhythm Block: Did you mean to use a Matrix block?'), blk);
- }
- break;
-
- // 𝅝 𝅗𝅥 𝅘𝅥 𝅘𝅥𝅮 𝅘𝅥𝅯 𝅘𝅥𝅰 𝅘𝅥𝅱 𝅘𝅥𝅲
- case 'wholeNote':
- that._processNote(1, blk, turtle);
- break;
- case 'halfNote':
- that._processNote(2, blk, turtle);
- break;
- case 'quarterNote':
- that._processNote(4, blk, turtle);
- break;
- case 'eighthNote':
- that._processNote(8, blk, turtle);
- break;
- case 'sixteenthNote':
- that._processNote(16, blk, turtle);
- break;
- case 'thirtysecondNote':
- that._processNote(32, blk, turtle);
- break;
- case 'sixtyfourthNote':
- that._processNote(64, blk, turtle);
- break;
- case 'meter':
- // See Issue #337
- break;
- case 'osctime':
- case 'newnote':
- case 'note':
- // We queue up the child flow of the note clamp and
- // once all of the children are run, we trigger a
- // _playnote_ event, then wait for the note to play.
- // The note can be specified by pitch or synth blocks.
- // The osctime block specifies the duration in
- // milleseconds while the note block specifies
- // duration as a beat value. Note: we should consider
- // the use of the global timer in Tone.js for more
- // accuracy.
-
- // A note can contain multiple pitch blocks to create
- // a chord. The chord is accumuated in these arrays,
- // which are used when we play the note.
- that.oscList[turtle] = [];
- that.noteBeat[turtle] = [];
- that.notePitches[turtle] = [];
- that.noteOctaves[turtle] = [];
- that.noteCents[turtle] = [];
- that.noteHertz[turtle] = [];
- that.noteTranspositions[turtle] = [];
- that.noteBeatValues[turtle] = [];
- that.noteDrums[turtle] = [];
-
- // Ensure that note duration is positive.
- if (args[0] < 0) {
- that.errorMsg(_('Note value must be greater than 0'), blk);
- var noteBeatValue = 0;
- } else {
- if (that.blocks.blockList[blk].name === 'newnote') {
- var noteBeatValue = 1 / args[0];
- } else {
- var noteBeatValue = args[0];
- }
- }
-
- that.inNoteBlock[turtle] += 1;
- that.whichNoteBlock[turtle] = blk;
-
- childFlow = args[1];
- childFlowCount = 1;
-
- var listenerName = '_playnote_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that._processNote(noteBeatValue, blk, turtle);
- that.inNoteBlock[turtle] -= 1;
- that.pitchBlocks = [];
- that.drumBlocks = [];
- };
-
- that._setListener(turtle, listenerName, __listener);
- break;
- case 'rhythmicdot':
- // Dotting a note will increase its play time by
- // a(2 - 1/2^n)
- var currentDotFactor = 2 - (1 / Math.pow(2, that.dotCount[turtle]));
- that.beatFactor[turtle] *= currentDotFactor;
- that.dotCount[turtle] += 1;
- var newDotFactor = 2 - (1 / Math.pow(2, that.dotCount[turtle]));
- that.beatFactor[turtle] /= newDotFactor;
- childFlow = args[0];
- childFlowCount = 1;
-
- var listenerName = '_dot_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- var currentDotFactor = 2 - (1 / Math.pow(2, that.dotCount[turtle]));
- that.beatFactor[turtle] *= currentDotFactor;
- that.dotCount[turtle] -= 1;
- var newDotFactor = 2 - (1 / Math.pow(2, that.dotCount[turtle]));
- that.beatFactor[turtle] /= newDotFactor;
- };
-
- that._setListener(turtle, listenerName, __listener);
- break;
- case 'crescendo':
- if (args.length > 1 && args[0] !== 0) {
- that.crescendoDelta[turtle].push(args[0]);
- that.crescendoVolume[turtle].push(last(that.polyVolume[turtle]));
- that.crescendoInitialVolume[turtle].push(last(that.polyVolume[turtle]));
- that.polyVolume[turtle].push(last(that.crescendoVolume[turtle]));
-
- childFlow = args[1];
- childFlowCount = 1;
-
- var listenerName = '_crescendo_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.crescendoDelta[turtle].pop();
- that.crescendoVolume[turtle].pop();
- that.polyVolume[turtle].pop();
- that.crescendoInitialVolume[turtle].pop();
- if (!that.justCounting[turtle]) {
- lilypondEndCrescendo(that, turtle);
- }
- };
-
- that._setListener(turtle, listenerName, __listener);
- }
- break;
- case 'darbuka':
- case 'clang':
- case 'bottle':
- case 'duck':
- case 'snare':
- case 'hihat':
- case 'tom':
- case 'kick':
- case 'pluck':
- case 'triangle1':
- case 'slap':
- case 'frogs':
- case 'fingercymbals':
- case 'cup':
- case 'cowbell':
- case 'splash':
- case 'ridebell':
- case 'floortom':
- case 'crash':
- case 'chine':
- case 'dog':
- case 'cat':
- case 'clap':
- case 'bubbles':
- case 'cricket':
- that.drumStyle[turtle].push(that.blocks.blockList[blk].name);
- childFlow = args[0];
- childFlowCount = 1;
-
- var listenerName = '_drum_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.drumStyle[turtle].pop();
- };
-
- that._setListener(turtle, listenerName, __listener);
- break;
- case 'setdrum':
- var drumname = 'kick';
- for (var drum in DRUMNAMES) {
- if (DRUMNAMES[drum][0] === args[0]) {
- drumname = DRUMNAMES[drum][1];
- } else if (DRUMNAMES[drum][1] === args[0]) {
- drumname = args[0];
- }
- }
-
- that.drumStyle[turtle].push(drumname);
- childFlow = args[1];
- childFlowCount = 1;
-
- var listenerName = '_setdrum_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.drumStyle[turtle].pop();
- };
-
- that._setListener(turtle, listenerName, __listener);
- if (that.inRhythmRuler) {
- that._currentDrumBlock = blk;
- that.rhythmRuler.Drums.push(blk);
- that.rhythmRuler.Rulers.push([[],[]]);
- }
- break;
- case 'setvoice':
- var voicename = null;
- for (var voice in VOICENAMES) {
- if (VOICENAMES[voice][0] === args[0]) {
- voicename = VOICENAMES[voice][1];
- } else if (VOICENAMES[voice][1] === args[0]) {
- voicename = args[0];
- }
- }
-
- // Maybe it is a drum?
- if (voicename == null) {
- for (var drum in DRUMNAMES) {
- if (DRUMNAMES[drum][0] === args[0]) {
- voicename = DRUMNAMES[drum][1];
- } else if (DRUMNAMES[drum][1] === args[0]) {
- voicename = args[0];
- }
- }
- }
-
- if (voicename == null) {
- that.errorMsg(NOINPUTERRORMSG, blk);
-
- childFlow = args[1];
- childFlowCount = 1;
- } else {
- that.voices[turtle].push(voicename);
- childFlow = args[1];
- childFlowCount = 1;
-
- var listenerName = '_setvoice_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.voices[turtle].pop();
- };
-
- that._setListener(turtle, listenerName, __listener);
- }
- break;
- case 'vibrato':
- var intensity = args[0];
- var rate = args[1];
-
- if (intensity < 1 || intensity > 100) {
- that.errorMsg(_('Vibrato intensity must be between 1 and 100.'), blk);
- that.stopTurtle = true;
- }
-
- if (rate <= 0) {
- that.errorMsg(_('Vibrato rate must be greater than 0.'), blk);
- that.stopTurtle = true;
- }
-
- childFlow = args[2];
- childFlowCount = 1;
-
- that.vibratoIntensity[turtle].push(intensity / 100);
- that.vibratoRate[turtle].push(Math.floor(Math.pow(rate, -1)));
-
- var listenerName = '_vibrato_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
- var __listener = function (event) {
- that.vibratoIntensity[turtle].pop();
- that.vibratoRate[turtle].pop();
- };
- that._setListener(turtle, listenerName, __listener);
- break;
- case 'interval':
- if (typeof(args[0]) !== 'number') {
- that.errorMsg(NOINPUTERRORMSG, blk);
- that.stopTurtle = true;
- break;
- }
-
- if (args[0] > 0) {
- var i = Math.floor(args[0]);
- } else {
- var i = Math.ceil(args[0]);
- }
-
- if (i !== 0) {
- that.intervals[turtle].push(i);
-
- var listenerName = '_interval_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.intervals[turtle].pop();
- };
-
- that._setListener(turtle, listenerName, __listener);
- }
-
- childFlow = args[1];
- childFlowCount = 1;
- break;
- case 'perfectx':
- if (args[0] < 0) {
- var interval = mod12(-args[0]);
- } else {
- var interval = mod12(args[0]);
- }
- var deltaOctave = calcOctaveInterval(args[1]);
- if ([1, 4, 5, 8].indexOf(interval) !== -1) {
- that.perfect[turtle].push([args[0], deltaOctave]);
-
- var listenerName = '_perfect_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.perfect[turtle].pop();
- };
-
- that._setListener(turtle, listenerName, __listener);
- } else {
- that.errorMsg(_('Input to Perfect Block must be 1, 4, 5, or 8'), blk);
- }
-
- childFlow = args[2];
- childFlowCount = 1;
- break;
- case 'perfect':
- // Deprecated
- var mod12Arg = mod12(args[0]);
- if ([1, 4, 5, 8].indexOf(mod12Arg) !== -1) {
- that.perfect[turtle].push([args[0], 0]);
-
- var listenerName = '_perfect_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.perfect[turtle].pop();
- };
-
- that._setListener(turtle, listenerName, __listener);
- } else {
- that.errorMsg(_('Input to Perfect Block must be 1, 4, 5, or 8'), blk);
- }
-
- childFlow = args[1];
- childFlowCount = 1;
- break;
- case 'diminishedx':
- if (args[0] < 0) {
- var interval = mod12(-args[0]);
- } else {
- var interval = mod12(args[0]);
- }
- var deltaOctave = calcOctaveInterval(args[1]);
- if ([1, 2, 3, 4, 5, 6, 7, 8].indexOf(interval) !== -1) {
- that.diminished[turtle].push([args[0], deltaOctave]);
-
- var listenerName = '_diminished_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.diminished[turtle].pop();
- };
-
- that._setListener(turtle, listenerName, __listener);
- } else {
- that.errorMsg(_('Input to Diminished Block must be 1, 2, 3, 4, 5, 6, 7, or 8'), blk);
- }
-
- childFlow = args[2];
- childFlowCount = 1;
- break;
- case 'diminished':
- // Deprecated
- var mod12Arg = mod12(args[0]);
- if ([1, 2, 3, 4, 5, 6, 7, 8].indexOf(mod12Arg) !== -1) {
- that.diminished[turtle].push([args[0], 0]);
-
- var listenerName = '_diminished_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.diminished[turtle].pop();
- };
-
- that._setListener(turtle, listenerName, __listener);
- } else {
- that.errorMsg(_('Input to Diminished Block must be 1, 2, 3, 4, 5, 6, 7, or 8'), blk);
- }
-
- childFlow = args[1];
- childFlowCount = 1;
- break;
- case 'augmentedx':
- if (args[0] < 0) {
- var interval = mod12(-args[0]);
- } else {
- var interval = mod12(args[0]);
- }
- var deltaOctave = calcOctaveInterval(args[1]);
- if ([1, 2, 3, 4, 5, 6, 7, 8].indexOf(interval) !== -1) {
- that.augmented[turtle].push([args[0], deltaOctave]);
-
- var listenerName = '_augmented_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.augmented[turtle].pop();
- };
-
- that._setListener(turtle, listenerName, __listener);
- } else {
- that.errorMsg(_('Input to Augmented Block must be 1, 2, 3, 4, 5, 6, 7, or 8'), blk);
- }
-
- childFlow = args[2];
- childFlowCount = 1;
- break;
- case 'augmented':
- // Deprecated
- var mod12Arg = mod12(args[0]);
- if ([1, 2, 3, 4, 5, 6, 7, 8].indexOf(mod12Arg) !== -1) {
- that.augmented[turtle].push([args[0], 0]);
-
- var listenerName = '_tritone_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.augmented[turtle].pop();
- };
-
- that._setListener(turtle, listenerName, __listener);
- } else {
- that.errorMsg(_('Input to Augmented Block must be 1, 2, 3, 4, 5, 6, 7, or 8'), blk);
- }
-
- childFlow = args[1];
- childFlowCount = 1;
- break;
- case 'majorx':
- if (args[0] < 0) {
- var interval = mod12(-args[0]);
- } else {
- var interval = mod12(args[0]);
- }
- var deltaOctave = calcOctaveInterval(args[1]);
- if ([2, 3, 6, 7].indexOf(interval) !== -1) {
- that.major[turtle].push([args[0], deltaOctave]);
-
- var listenerName = '_major_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.major[turtle].pop();
- };
-
- that._setListener(turtle, listenerName, __listener);
- } else {
- that.errorMsg(_('Input to Major Block must be 2, 3, 6, or 7'), blk);
- }
-
- childFlow = args[2];
- childFlowCount = 1;
- break;
- case 'major':
- // Deprecated
- var mod12Arg = mod12(args[0]);
- var octaveArg = args[1];
- if ([2, 3, 6, 7].indexOf(mod12Arg) !== -1) {
- that.major[turtle].push([args[0], 0]);
-
- var listenerName = '_major_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.major[turtle].pop();
- };
-
- that._setListener(turtle, listenerName, __listener);
- } else {
- that.errorMsg(_('Input to Major Block must be 2, 3, 6, or 7'), blk);
- }
-
- childFlow = args[1];
- childFlowCount = 1;
- break;
- case 'minorx':
- if (args[0] < 0) {
- var interval = mod12(-args[0]);
- } else {
- var interval = mod12(args[0]);
- }
- var deltaOctave = calcOctaveInterval(args[1]);
- if ([2, 3, 6, 7].indexOf(interval) !== -1) {
- that.minor[turtle].push([args[0], deltaOctave]);
-
- var listenerName = '_minor_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.minor[turtle].pop();
- };
-
- that._setListener(turtle, listenerName, __listener);
- } else {
- that.errorMsg(_('Input to Minor Block must be 2, 3, 6, or 7'), blk);
- }
-
- childFlow = args[2];
- childFlowCount = 1;
- break;
- case 'minor':
- // Deprecated
- var mod12Arg = mod12(args[0]);
- if ([2, 3, 6, 7].indexOf(mod12Arg) !== -1) {
- that.minor[turtle].push([args[0], 0]);
-
- var listenerName = '_minor_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.minor[turtle].pop();
- };
-
- that._setListener(turtle, listenerName, __listener);
- } else {
- that.errorMsg(_('Input to Minor Block must be 2, 3, 6, or 7'), blk);
- }
-
- childFlow = args[1];
- childFlowCount = 1;
- break;
- case 'newstaccato':
- case 'staccato':
- if (args.length > 1) {
- if (that.blocks.blockList[blk].name === 'newstaccato') {
- that.staccato[turtle].push(1 / args[0]);
- } else {
- that.staccato[turtle].push(args[0]);
- }
- childFlow = args[1];
- childFlowCount = 1;
-
- var listenerName = '_staccato_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.staccato[turtle].pop();
- };
-
- that._setListener(turtle, listenerName, __listener);
- }
- break;
- case 'newslur':
- case 'slur':
- if (args.length > 1) {
- if (that.blocks.blockList[blk].name === 'newslur') {
- that.staccato[turtle].push(-1 / args[0]);
- } else {
- that.staccato[turtle].push(-args[0]);
- }
-
- if (!that.justCounting[turtle]) {
- lilypondBeginSlur(that, turtle);
- }
-
- childFlow = args[1];
- childFlowCount = 1;
-
- var listenerName = '_staccato_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.staccato[turtle].pop();
- if (!that.justCounting[turtle]) {
- lilypondEndSlur(that, turtle);
- }
- };
-
- that._setListener(turtle, listenerName, __listener);
- }
- break;
- case 'drift':
- that.drift[turtle] += 1;
- childFlow = args[0];
- childFlowCount = 1;
-
- var listenerName = '_drift_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.drift[turtle] -= 1;
- };
-
- that._setListener(turtle, listenerName, __listener);
- break;
- case 'tie':
- // Tie notes together in pairs.
- that.tie[turtle] = true;
- that.tieNote[turtle] = [];
- that.tieCarryOver[turtle] = 0;
- childFlow = args[0];
- childFlowCount = 1;
-
- var listenerName = '_tie_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.tie[turtle] = false;
- // If tieCarryOver > 0, we have one more note to
- // play.
- if (that.tieCarryOver[turtle] > 0) {
- if (!that.justCounting[turtle]) {
- // Remove the note from the Lilypond list.
- for (var i = 0; i < that.notePitches[turtle].length; i++) {
- lilypondRemoveTie(that, turtle);
- }
- }
- var noteValue = that.tieCarryOver[turtle];
- that.tieCarryOver[turtle] = 0;
- that._processNote(noteValue, blk, turtle);
- }
- that.tieNote[turtle] = [];
- };
-
- that._setListener(turtle, listenerName, __listener);
- break;
- case 'newswing':
- case 'newswing2':
- case 'swing':
- // Grab a bit from the next note to give to the current note.
- if (that.blocks.blockList[blk].name === 'newswing2') {
- that.swing[turtle].push(1 / args[0]);
- that.swingTarget[turtle].push(1 / args[1]);
- childFlow = args[2];
- } else if (that.blocks.blockList[blk].name === 'newswing') {
- that.swing[turtle].push(1 / args[0]);
- that.swingTarget[turtle].push(null);
- childFlow = args[1];
- } else {
- that.swing[turtle].push(args[0]);
- that.swingTarget[turtle].push(null);
- childFlow = args[1];
- }
- that.swingCarryOver[turtle] = 0;
-
- childFlowCount = 1;
-
- var listenerName = '_swing_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.swingTarget[turtle].pop();
- that.swing[turtle].pop();
- that.swingCarryOver[turtle] = 0;
- };
-
- that._setListener(turtle, listenerName, __listener);
- break;
- case 'duplicatenotes':
- var factor = args[0];
- if (factor === 0) {
- that.errorMsg(ZERODIVIDEERRORMSG, blk);
- that.stopTurtle = true;
- } else {
- that.duplicateFactor[turtle] *= factor;
- childFlow = args[1];
- childFlowCount = 1;
-
- var listenerName = '_duplicate_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.duplicateFactor[turtle] /= factor;
- };
-
- that._setListener(turtle, listenerName, __listener);
- }
- break;
- case 'skipnotes':
- var factor = args[0];
- if (factor === 0) {
- that.errorMsg(ZERODIVIDEERRORMSG, blk);
- that.stopTurtle = true;
- } else {
- that.skipFactor[turtle] *= factor;
- childFlow = args[1];
- childFlowCount = 1;
-
- var listenerName = '_skip_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.skipFactor[turtle] /= factor;
- if (that.skipFactor[turtle] === 1) {
- that.skipIndex[turtle] = 0;
- }
- };
-
- that._setListener(turtle, listenerName, __listener);
- }
- break;
- case 'multiplybeatfactor':
- var factor = args[0];
- if (factor === 0) {
- that.errorMsg(ZERODIVIDEERRORMSG, blk);
- that.stopTurtle = true;
- } else {
- that.beatFactor[turtle] *= factor;
- childFlow = args[1];
- childFlowCount = 1;
-
- var listenerName = '_multiplybeat_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.beatFactor[turtle] /= factor;
- };
-
- that._setListener(turtle, listenerName, __listener);
- }
- break;
- case 'dividebeatfactor':
- var factor = args[0];
- if (factor === 0) {
- that.errorMsg(ZERODIVIDEERRORMSG, blk);
- that.stopTurtle = true;
- } else {
- that.beatFactor[turtle] /= factor;
- childFlow = args[1];
- childFlowCount = 1;
-
- var listenerName = '_dividebeat_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.beatFactor[turtle] *= factor;
- };
-
- that._setListener(turtle, listenerName, __listener);
- }
- break;
- case 'settransposition':
- var transValue = args[0];
- if (!(that.invertList[turtle].length === 0)) {
- that.transposition[turtle] -= transValue;
- } else {
- that.transposition[turtle] += transValue;
- }
-
- childFlow = args[1];
- childFlowCount = 1;
-
- var listenerName = '_transposition_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- if (!(that.invertList[turtle].length === 0)) {
- that.transposition[turtle] += transValue;
- } else {
- that.transposition[turtle] -= transValue;
- }
- };
-
- that._setListener(turtle, listenerName, __listener);
- break;
- case 'sharp':
- if (!(that.invertList[turtle].length === 0)) {
- that.transposition[turtle] -= 1;
- } else {
- that.transposition[turtle] += 1;
- }
- childFlow = args[0];
- childFlowCount = 1;
-
- var listenerName = '_sharp_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- if (!(that.invertList[turtle].length === 0)) {
- that.transposition[turtle] += 1;
- } else {
- that.transposition[turtle] -= 1;
- }
- };
-
- that._setListener(turtle, listenerName, __listener);
- break;
- case 'flat':
- if (!(that.invertList[turtle].length === 0)) {
- that.transposition[turtle] += 1;
- } else {
- that.transposition[turtle] -= 1;
- }
- childFlow = args[0];
- childFlowCount = 1;
-
- var listenerName = '_flat_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- if (!(that.invertList[turtle].length === 0)) {
- that.transposition[turtle] -= 1;
- } else {
- that.transposition[turtle] += 1;
- }
- };
-
- that._setListener(turtle, listenerName, __listener);
- break;
- case 'articulation':
- if (args.length === 2 && typeof(args[0]) === 'number' && args[0] > 0) {
- var newVolume = last(that.polyVolume[turtle]) * (100 + args[0]) / 100;
- if (newVolume > 100) {
- console.log('articulated volume exceeds 100%. clipping');
- newVolume = 100;
- }
- that.polyVolume[turtle].push(newVolume);
- that._setSynthVolume(newVolume, turtle);
-
- if (!that.justCounting[turtle]) {
- lilypondBeginArticulation(that, turtle);
- }
-
- childFlow = args[1];
- childFlowCount = 1;
-
- var listenerName = '_articulation_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.polyVolume[turtle].pop();
- if (!that.justCounting[turtle]) {
- lilypondEndArticulation(that, turtle);
- }
- };
-
- that._setListener(turtle, listenerName, __listener);
- }
- break;
- case 'setnotevolume2':
- if (args.length === 2 && typeof(args[0]) === 'number') {
- that.polyVolume[turtle].push(args[0]);
- that._setSynthVolume(args[0], turtle);
-
- childFlow = args[1];
- childFlowCount = 1;
-
- var listenerName = '_volume_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- that.polyVolume[turtle].pop();
- };
-
- that._setListener(turtle, listenerName, __listener);
- }
- break;
- // Deprecated
- case 'setnotevolume':
- if (args.length === 1) {
- if (typeof(args[0]) === 'string') {
- that.errorMsg(NANERRORMSG, blk);
- that.stopTurtle = true;
- } else {
- that._setSynthVolume(args[0], turtle);
- }
- }
- break;
- // Deprecated P5 tone generator replaced by macro.
- case 'tone':
- break;
- case 'tone2':
- if (_THIS_IS_TURTLE_BLOCKS_) {
- if (typeof(that.turtleOscs[turtle]) === 'undefined') {
- that.turtleOscs[turtle] = new p5.TriOsc();
- }
-
- osc = that.turtleOscs[turtle];
- osc.stop();
- osc.start();
- osc.amp(0);
-
- osc.freq(args[0]);
- osc.fade(0.5, 0.2);
-
- setTimeout(function(osc) {
- osc.fade(0, 0.2);
- }, args[1], osc);
- }
- break;
- case 'hertz':
- if (args.length !== 1 || args[0] == null) {
- that.errorMsg(NOINPUTERRORMSG, blk);
- that.stopTurtle = true;
- break;
- }
-
- if (typeof(args[0]) !== 'number') {
- that.errorMsg(NANERRORMSG, blk);
- that.stopTurtle = true;
- break;
- }
-
- var obj = frequencyToPitch(args[0]);
- var note = obj[0];
- var octave = obj[1];
- var cents = obj[2];
- var delta = 0;
-
- if (note === '?') {
- that.errorMsg(INVALIDPITCH, blk);
- that.stopTurtle = true;
- } else if (that.inMatrix) {
- that.pitchTimeMatrix.addRowBlock(blk);
- if (that.pitchBlocks.indexOf(blk) === -1) {
- that.pitchBlocks.push(blk);
- }
-
- that.pitchTimeMatrix.rowLabels.push(that.blocks.blockList[blk].name);
- that.pitchTimeMatrix.rowArgs.push(args[0]);
- } else if (that.inNoteBlock[turtle] > 0) {
-
- function addPitch(note, octave, cents, frequency) {
- if (that.drumStyle[turtle].length > 0) {
- var drumname = last(that.drumStyle[turtle]);
- var note2 = that.getNote(note, octave, transposition, that.keySignature[turtle]);
- that.pitchDrumTable[turtle][note2[0] + note2[1]] = drumname;
- }
- that.notePitches[turtle].push(note);
- that.noteOctaves[turtle].push(octave);
- that.noteCents[turtle].push(cents);
- that.noteHertz[turtle].push(frequency);
- }
-
- if (!(that.invertList[turtle].length === 0)) {
- var len = that.invertList[turtle].length;
- var note1 = that.getNote(note, octave, 0, that.keySignature[turtle]);
- var num1 = getNumber(note1[0], note1[1]);
- for (var i = len - 1; i > -1; i--) {
- var note2 = that.getNote(that.invertList[turtle][i][0], that.invertList[turtle][i][1], 0, that.keySignature[turtle]);
- var num2 = getNumber(note2[0], note2[1]);
- // var a = getNumNote(num1, 0);
- if (that.invertList[turtle][i][2] === 'even') {
- delta += num2 - num1;
- } else { // odd
- delta += num2 - num1 + 0.5;
- }
- num1 += 2 * delta;
- }
- }
-
- addPitch(note, octave, cents, args[0]);
-
- if (turtle in that.intervals && that.intervals[turtle].length > 0) {
- for (var i = 0; i < that.intervals[turtle].length; i++) {
- var ii = getInterval(that.intervals[turtle][i], that.keySignature[turtle], note);
- var noteObj = that.getNote(note, octave, ii, that.keySignature[turtle]);
- addPitch(noteObj[0], noteObj[1], cents, 0);
- }
- }
-
- if (turtle in that.perfect && that.perfect[turtle].length > 0) {
- var noteObj = that.getNote(note, octave, calcPerfect(last(that.perfect[turtle])), that.keySignature[turtle]);
- addPitch(noteObj[0], noteObj[1], cents, 0);
- }
-
- if (turtle in that.diminished && that.diminished[turtle].length > 0) {
- var noteObj = that.getNote(note, octave, calcDiminished(last(that.diminished[turtle])), that.keySignature[turtle]);
- addPitch(noteObj[0], noteObj[1], cents, 0);
- }
-
- if (turtle in that.augmented && that.augmented[turtle].length > 0) {
- var noteObj = that.getNote(note, octave, calcAugmented(last(that.augmented[turtle])), that.keySignature[turtle]);
- addPitch(noteObj[0], noteObj[1], cents, 0);
- }
-
- if (turtle in that.major && that.major[turtle].length > 0) {
- var noteObj = that.getNote(note, octave, calcMajor(last(that.major[turtle])), that.keySignature[turtle]);
- addPitch(noteObj[0], noteObj[1], cents, 0);
- }
-
- if (turtle in that.minor && that.minor[turtle].length > 0) {
- var noteObj = that.getNote(note, octave, calcMinor(last(that.minor[turtle])), that.keySignature[turtle]);
- addPitch(noteObj[0], noteObj[1], cents, 0);
- }
-
- if (turtle in that.transposition) {
- that.noteTranspositions[turtle].push(that.transposition[turtle] + 2 * delta);
- } else {
- that.noteTranspositions[turtle].push(2 * delta);
- }
-
- if (turtle in that.beatFactor) {
- that.noteBeatValues[turtle].push(that.beatFactor[turtle]);
- } else {
- that.noteBeatValues[turtle].push(1);
- }
-
- that.pushedNote[turtle] = true;
- } else if (that.inPitchStaircase) {
- var frequency = args[0];
- var note = frequencyToPitch(args[0]);
- var flag = 0;
-
- for (var i = 0 ; i < that.pitchStaircase.Stairs.length; i++) {
- if (that.pitchStaircase.Stairs[i][2] < parseFloat(frequency)) {
- that.pitchStaircase.Stairs.splice(i, 0, [note[0], note[1], parseFloat(frequency)]);
- flag = 1;
- break;
- }
- if (that.pitchStaircase.Stairs[i][2] === parseFloat(frequency)) {
- that.pitchStaircase.Stairs.splice(i, 1, [note[0], note[1], parseFloat(frequency)]);
- flag = 1;
- break;
- }
- }
-
- if (flag === 0) {
- that.pitchStaircase.Stairs.push([note[0], note[1], parseFloat(frequency)]);
- }
- } else if (that.inPitchSlider) {
- that.pitchSlider.Sliders.push([args[0], 0, 0]);
- } else {
- that.errorMsg(_('Hertz Block: Did you mean to use a Note block?'), blk);
- }
- break;
- // deprecated
- case 'triangle':
- case 'sine':
- case 'square':
- case 'sawtooth':
- if (args.length === 1) {
- var obj = frequencyToPitch(args[0]);
- // obj[2] is cents
- if (that.inMatrix) {
- that.pitchTimeMatrix.addRowBlock(blk);
- if (that.pitchBlocks.indexOf(blk) === -1) {
- that.pitchBlocks.push(blk);
- }
- that.pitchTimeMatrix.rowLabels.push(that.blocks.blockList[blk].name);
- that.pitchTimeMatrix.rowArgs.push(args[0]);
- } else if (that.inPitchSlider) {
- that.pitchSlider.Sliders.push([args[0], 0, 0]);
- } else {
- that.oscList[turtle].push(that.blocks.blockList[blk].name);
-
- // We keep track of pitch and octave for notation purposes.
- that.notePitches[turtle].push(obj[0]);
- that.noteOctaves[turtle].push(obj[1]);
- that.noteCents[turtle].push(obj[2]);
- if (obj[2] !== 0) {
- that.noteHertz[turtle].push(pitchToFrequency(obj[0], obj[1], obj[2], that.keySignature[turtle]));
- } else {
- that.noteHertz[turtle].push(0);
- }
-
- if (turtle in that.transposition) {
- that.noteTranspositions[turtle].push(that.transposition[turtle]);
- } else {
- that.noteTranspositions[turtle].push(0);
- }
-
- if (turtle in that.beatFactor) {
- that.noteBeatValues[turtle].push(that.beatFactor[turtle]);
- } else {
- that.noteBeatValues[turtle].push(1);
- }
-
- that.pushedNote[turtle] = true;
- }
- }
- break;
- // Deprecated
- case 'playfwd':
- that.pitchTimeMatrix.playDirection = 1;
- that._runFromBlock(that, turtle, args[0]);
- break;
- // Deprecated
- case 'playbwd':
- that.pitchTimeMatrix.playDirection = -1;
- that._runFromBlock(that, turtle, args[0]);
- break;
- case 'stuplet':
- if (that.inMatrix) {
- that.pitchTimeMatrix.addColBlock(blk, args[0]);
- var noteBeatValue = (1 / args[1]) * that.beatFactor[turtle];
- if (that.tuplet === true) {
- // The simple-tuplet block is inside.
- for (var i = 0; i < args[0]; i++) {
- if (!that.addingNotesToTuplet) {
- that.tupletRhythms.push(['notes', 0]);
- that.addingNotesToTuplet = true;
- }
- that._processNote(noteBeatValue, blk, turtle);
- }
- } else {
- that.tupletParams.push([1, noteBeatValue]);
- var obj = ['simple', 0];
- for (var i = 0; i < args[0]; i++) {
- obj.push((1 / args[1]) * that.beatFactor[turtle]);
- }
- that.tupletRhythms.push(obj);
- }
- }
- break;
- case 'tuplet2':
- case 'tuplet3':
- if (that.inMatrix) {
- if (that.blocks.blockList[blk].name === 'tuplet3') {
- that.tupletParams.push([args[0], (1 / args[1]) * that.beatFactor[turtle]]);
- } else {
- that.tupletParams.push([args[0], args[1] * that.beatFactor[turtle]]);
- }
- that.tuplet = true;
- that.addingNotesToTuplet = false;
- } else {
- that.errorMsg(_('Tuplet Block: Did you mean to use a Matrix block?'), blk);
- }
- childFlow = args[2];
- childFlowCount = 1;
-
- var listenerName = '_tuplet_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- if (that.inMatrix) {
- that.tuplet = false;
- that.addingNotesToTuplet = false;
- } else {
- }
- };
-
- that._setListener(turtle, listenerName, __listener);
- break;
- case 'tuplet4':
- if (that.inMatrix) {
- that.tupletParams.push([1, (1 / args[0]) * that.beatFactor[turtle]]);
- that.tuplet = true;
- that.addingNotesToTuplet = false;
- } else {
- that.errorMsg(_('Tuplet Block: Did you mean to use a Matrix block?'), blk);
- }
- childFlow = args[1];
- childFlowCount = 1;
-
- var listenerName = '_tuplet_' + turtle;
- that._setDispatchBlock(blk, turtle, listenerName);
-
- var __listener = function (event) {
- if (that.inMatrix) {
- that.tuplet = false;
- that.addingNotesToTuplet = false;
- } else {
- }
- };
-
- that._setListener(turtle, listenerName, __listener);
- break;
- default:
- if (that.blocks.blockList[blk].name in that.evalFlowDict) {
- eval(that.evalFlowDict[that.blocks.blockList[blk].name]);
- } else {
- // Could be an arg block, so we need to print its value.
- if (that.blocks.blockList[blk].isArgBlock()) {
- args.push(that.parseArg(that, turtle, blk));
- console.log('block: ' + blk + ' turtle: ' + turtle);
- console.log('block name: ' + that.blocks.blockList[blk].name);
- console.log('block value: ' + that.blocks.blockList[blk].value);
- if (that.blocks.blockList[blk].value == null) {
- that.textMsg('null block value');
- } else {
- that.textMsg(that.blocks.blockList[blk].value.toString());
- }
- } else {
- that.errorMsg('I do not know how to ' + that.blocks.blockList[blk].name + '.', blk);
- }
- that.stopTurtle = true;
- }
- break;
- }
-
- // (3) Queue block below the current block.
-
- // Is the block in a queued clamp?
- if (blk in that.endOfClampSignals[turtle]) {
- for (var i = that.endOfClampSignals[turtle][blk].length - 1; i >= 0; i--) {
- var signal = that.endOfClampSignals[turtle][blk][i];
- if (signal != null) {
- that.stage.dispatchEvent(that.endOfClampSignals[turtle][blk][i]);
- // Mark issued signals as null
- that.endOfClampSignals[turtle][blk][i] = null;
- }
- }
- var cleanSignals = [];
- for (var i = 0; i < that.endOfClampSignals[turtle][blk].length; i++) {
- if (that.endOfClampSignals[turtle][blk][i] != null) {
- cleanSignals.push(that.endOfClampSignals[turtle][blk][i]);
- }
- }
- that.endOfClampSignals[turtle][blk] = cleanSignals;
- }
-
- if (docById('statusDiv').style.visibility === 'visible') {
- that.statusMatrix.updateAll();
- }
-
- // If there is a child flow, queue it.
- if (childFlow != null) {
- if (that.blocks.blockList[blk].name==='doArg' || that.blocks.blockList[blk].name==='nameddoArg') {
- var queueBlock = new Queue(childFlow, childFlowCount, blk, actionArgs);
- } else {
- var queueBlock = new Queue(childFlow, childFlowCount, blk, receivedArg);
- }
- // We need to keep track of the parent block to the child
- // flow so we can unlightlight the parent block after the
- // child flow completes.
- that.parentFlowQueue[turtle].push(blk);
- that.turtles.turtleList[turtle].queue.push(queueBlock);
- }
-
- var nextBlock = null;
- var parentBlk = null;
- // Run the last flow in the queue.
- if (that.turtles.turtleList[turtle].queue.length > queueStart) {
- nextBlock = last(that.turtles.turtleList[turtle].queue).blk;
- parentBlk = last(that.turtles.turtleList[turtle].queue).parentBlk;
- passArg = last(that.turtles.turtleList[turtle].queue).args;
- // Since the forever block starts at -1, it will never === 1.
- if (last(that.turtles.turtleList[turtle].queue).count === 1) {
- // Finished child so pop it off the queue.
- that.turtles.turtleList[turtle].queue.pop();
- } else {
- // Decrement the counter for repeating that flow.
- last(that.turtles.turtleList[turtle].queue).count -= 1;
- }
- }
-
- if (nextBlock != null) {
- if (parentBlk !== blk) {
- // The wait block waits waitTimes longer than other
- // blocks before it is unhighlighted.
- if (that.turtleDelay === TURTLESTEP) {
- that.unhighlightStepQueue[turtle] = blk;
- } else {
- setTimeout(function () {
- if (that.blocks.visible) {
- that.blocks.unhighlight(blk);
- }
- }, that.turtleDelay + that.waitTimes[turtle]);
- }
- }
-
- if ((that.backward[turtle].length > 0 && that.blocks.blockList[blk].connections[0] == null) || (that.backward[turtle].length === 0 && last(that.blocks.blockList[blk].connections) == null)) {
- // If we are at the end of the child flow, queue the
- // unhighlighting of the parent block to the flow.
- if (that.parentFlowQueue[turtle].length > 0 && that.turtles.turtleList[turtle].queue.length > 0 && last(that.turtles.turtleList[turtle].queue).parentBlk !== last(that.parentFlowQueue[turtle])) {
- that.unhightlightQueue[turtle].push(last(that.parentFlowQueue[turtle]));
- // that.unhightlightQueue[turtle].push(that.parentFlowQueue[turtle].pop());
- } else if (that.unhightlightQueue[turtle].length > 0) {
- // The child flow is finally complete, so unhighlight.
- setTimeout(function () {
- if (that.blocks.visible) {
- that.blocks.unhighlight(that.unhightlightQueue[turtle].pop());
- } else {
- that.unhightlightQueue[turtle].pop();
- }
- }, that.turtleDelay);
- }
- }
-
- // We don't update parameter blocks when running full speed.
- if (that.turtleDelay !== 0) {
- for (var pblk in that.parameterQueue[turtle]) {
- that._updateParameterBlock(that, turtle, that.parameterQueue[turtle][pblk]);
- }
- }
-
- if (isflow){
- that._runFromBlockNow(that, turtle, nextBlock, isflow, passArg, queueStart);
- }
- else{
- that._runFromBlock(that, turtle, nextBlock, isflow, passArg);
- }
- } else {
- // Make sure any unissued signals are dispatched.
- for (var b in that.endOfClampSignals[turtle]) {
- for (var i = 0; i < that.endOfClampSignals[turtle][b].length; i++) {
- if (that.endOfClampSignals[turtle][b][i] != null) {
- that.stage.dispatchEvent(that.endOfClampSignals[turtle][b][i]);
- }
- }
- }
-
- if (turtle in that.forwardListener) {
- for (var b in that.forwardListener[turtle]) {
- for (var i = 0; i < this.forwardListener[turtle][b].length; i++) {
- that.stage.removeEventListener('_forward_' + turtle, that.forwardListener[turtle][b][i], false);
- }
- }
- }
-
- if (turtle in that.rightListener) {
- for (var b in that.rightListener[turtle]) {
- for (var i = 0; i < this.rightListener[turtle][b].length; i++) {
- that.stage.removeEventListener('_right_' + turtle, that.rightListener[turtle][b][i], false);
- }
- }
- }
-
- if (turtle in that.arcListener) {
- for (var b in that.arcListener[turtle]) {
- for (var i = 0; i < this.arcListener[turtle][b].length; i++) {
- that.stage.removeEventListener('_arc_' + turtle, that.arcListener[turtle][b][i], false);
- }
- }
- }
-
- // Make sure SVG path is closed.
- that.turtles.turtleList[turtle].closeSVG();
-
- // Mark the turtle as not running.
- that.turtles.turtleList[turtle].running = false;
- if (!that.turtles.running() && queueStart === 0) {
- that.onStopTurtle();
- }
-
- // Because flow can come from calc blocks, we are not
- // ensured that the turtle is really finished running
- // yet. Hence the timeout.
- __checkLilypond = function () {
- if (!that.turtles.running() && queueStart === 0 && that.suppressOutput[turtle] && !that.justCounting[turtle]) {
- console.log('saving lilypond output: ' + that.lilypondStaging);
- saveLilypondOutput(that, _('My Project') + '.ly');
- that.suppressOutput[turtle] = false;
- that.checkingLilypond = false;
- that.runningLilypond = false;
- // Reset cursor.
- document.body.style.cursor = 'default';
- } else if (that.suppressOutput[turtle]) {
- setTimeout(function () {
- __checkLilypond();
- }, 250);
- }
- };
-
- if (!that.turtles.running() && queueStart === 0 && that.suppressOutput[turtle] && !that.justCounting[turtle]) {
- if (!that.checkingLilypond) {
- that.checkingLilypond = true;
- setTimeout(function () {
- __checkLilypond();
- }, 250);
- }
- }
-
- // Nothing else to do... so cleaning up.
- if (that.turtles.turtleList[turtle].queue.length === 0 || blk !== last(that.turtles.turtleList[turtle].queue).parentBlk) {
- setTimeout(function () {
- if (that.blocks.visible) {
- that.blocks.unhighlight(blk);
- }
- }, that.turtleDelay);
- }
-
- // Unhighlight any parent blocks still highlighted.
- for (var b in that.parentFlowQueue[turtle]) {
- if (that.blocks.visible) {
- that.blocks.unhighlight(that.parentFlowQueue[turtle][b]);
- }
- }
-
- // Make sure the turtles are on top.
- var i = that.stage.getNumChildren() - 1;
- that.stage.setChildIndex(that.turtles.turtleList[turtle].container, i);
- that.refreshCanvas();
-
- for (var arg in that.evalOnStopList) {
- eval(that.evalOnStopList[arg]);
- }
-
- }
-
- clearTimeout(this.saveTimeout);
-
- var me = this;
- this.saveTimeout = setTimeout(function () {
- // Save at the end to save an image
- // console.log('in saveTimeout');
- me.saveLocally();
- }, DEFAULTDELAY * 1.5);
- };
-
- this._setSynthVolume = function (vol, turtle) {
- if (vol > 100) {
- vol = 100;
- } else if (vol < 0) {
- vol = 0;
- }
-
- if (_THIS_IS_MUSIC_BLOCKS_) {
- this.synth.setVolume(vol);
- }
- };
-
- this._processNote = function (noteValue, blk, turtle) {
- if (this.bpm[turtle].length > 0) {
- var bpmFactor = TONEBPM / last(this.bpm[turtle]);
- } else {
- var bpmFactor = TONEBPM / this._masterBPM;
- }
-
- if (this.blocks.blockList[blk].name === 'osctime') {
- // Convert msecs to note value.
- if (noteValue == 0) {
- var noteBeatValue = 0;
- } else {
- var noteBeatValue = (bpmFactor * 1000) / noteValue;
- }
- } else {
- var noteBeatValue = noteValue;
- }
-
- // How best to expose this in the UI? What units?
- this.notesPlayed[turtle] += (1 / (noteValue * this.beatFactor[turtle]));
-
- var vibratoRate = 0;
- var vibratoValue = 0;
- var vibratoIntensity = 0;
- var doVibrato = false;
- if (this.vibratoRate[turtle].length > 0) {
- vibratoRate = last(this.vibratoRate[turtle]);
- vibratoIntensity = last(this.vibratoIntensity[turtle]);
- doVibrato = true;
- }
-
- var carry = 0;
-
- if (this.crescendoDelta[turtle].length === 0) {
- this._setSynthVolume(last(this.polyVolume[turtle]), turtle);
- }
-
- if (this.inMatrix) {
- if (this.inNoteBlock[turtle] > 0) {
- this.pitchTimeMatrix.addColBlock(blk, 1);
- for (var i = 0; i < this.pitchBlocks.length; i++) {
- this.pitchTimeMatrix.addNode(this.pitchBlocks[i], blk, 0);
- }
- for (var i = 0; i < this.drumBlocks.length; i++) {
- this.pitchTimeMatrix.addNode(this.drumBlocks[i], blk, 0);
- }
- }
- noteBeatValue *= this.beatFactor[turtle];
- if (this.tuplet === true) {
- if (this.addingNotesToTuplet) {
- var i = this.tupletRhythms.length - 1;
- this.tupletRhythms[i].push(noteBeatValue);
- } else {
- this.tupletRhythms.push(['notes', this.tupletParams.length - 1, noteBeatValue]);
- this.addingNotesToTuplet = true;
- }
- } else {
- this.tupletRhythms.push(['', 1, noteBeatValue]);
- }
- } else {
- // We start the music clock as the first note is being
- // played.
- if (this.firstNoteTime == null && !this.suppressOutput[turtle]) {
- var d = new Date();
- this.firstNoteTime = d.getTime();
- }
-
- // Calculate a lag: In case this turtle has fallen behind,
- // we need to catch up.
- var d = new Date();
- var elapsedTime = (d.getTime() - this.firstNoteTime) / 1000;
- if (this.drift[turtle] === 0) {
- // How far behind is this turtle lagging?
- var turtleLag = elapsedTime - this.turtleTime[turtle];
- } else {
- // When we are "drifting", we don't bother with lag.
- var turtleLag = 0;
- }
- // If we are in a tie, depending upon parity, we either
- // add the duration from the previous note to the current
- // note, or we cache the duration and set the wait to
- // zero. FIXME: Will not work when using dup and skip.
- if (this.tie[turtle]) {
- // We need to check to see if we are tying together
- // similar notes.
- if (this.tieCarryOver[turtle] > 0) {
- var match = true;
- if (this.tieNote[turtle].length !== this.notePitches[turtle].length) {
- match = false;
- } else {
- for (var i = 0; i < this.tieNote[turtle].length; i++) {
- if (this.tieNote[turtle][i][0] != this.notePitches[turtle][i]) {
- match = false;
- break;
- }
-
- if (this.tieNote[turtle][i][1] != this.noteOctaves[turtle][i]) {
- match = false;
- break;
- }
- }
- }
- if (!match) {
- var tmpBeatValue = this.tieCarryOver[turtle];
- this.tieCarryOver[turtle] = 0;
- this.tie[turtle] = false;
-
- // Save the current note.
- var saveNote = [];
- for (var i = 0; i < this.notePitches[turtle].length; i++) {
- saveNote.push([this.notePitches[turtle][i], this.noteOctaves[turtle][i], this.noteCents[turtle][i], this.noteHertz[turtle][i]]);
- }
-
- // Swap in the previous note.
- this.notePitches[turtle] = [];
- this.noteOctaves[turtle] = [];
- this.noteCents[turtle] = [];
- this.noteHertz[turtle] = [];
- for (var i = 0; i < this.tieNote[turtle].length; i++) {
- this.notePitches[turtle].push(this.tieNote[turtle][i][0]);
- this.noteOctaves[turtle].push(this.tieNote[turtle][i][1]);
- this.noteCents[turtle].push(this.tieNote[turtle][i][2]);
- this.noteHertz[turtle].push(this.tieNote[turtle][i][3]);
- }
- this.tieNote[turtle] = [];
-
- if (!this.justCounting[turtle]) {
- // Remove the note from the Lilypond list.
- for (var i = 0; i < this.notePitches[turtle].length; i++) {
- lilypondRemoveTie(this, turtle);
- }
- }
-
- this._processNote(tmpBeatValue, blk, turtle);
-
- // Restore the current note.
- this.tie[turtle] = true;
- this.notePitches[turtle] = [];
- this.noteOctaves[turtle] = [];
- this.noteCents[turtle] = [];
- this.noteHertz[turtle] = [];
- for (var i = 0; i < saveNote.length; i++) {
- this.notePitches[turtle].push(saveNote[i][0]);
- this.noteOctaves[turtle].push(saveNote[i][1]);
- this.noteCents[turtle].push(saveNote[i][2]);
- this.noteHertz[turtle].push(saveNote[i][3]);
- }
- }
- }
-
- if (this.tieCarryOver[turtle] === 0) {
- this.tieNote[turtle] = [];
- this.tieCarryOver[turtle] = noteBeatValue;
- for (var i = 0; i < this.notePitches[turtle].length; i++) {
- this.tieNote[turtle].push([this.notePitches[turtle][i], this.noteOctaves[turtle][i], this.noteCents[turtle][i], this.noteHertz[turtle][i]]);
- }
- noteBeatValue = 0;
- } else {
- carry = this.tieCarryOver[turtle];
- noteBeatValue = 1 / ((1 / noteBeatValue) + (1 / this.tieCarryOver[turtle]));
- this.tieCarryOver[turtle] = 0;
- }
- }
-
- // If we are in a swing, depending upon parity, we either
- // add the duration from the current note or we substract
- // duration from the next note. Swing is triggered by an
- // initial notevalue. When that notevalue is encountered
- // again, the swing terminates, e.g., 8->4->4->4->8
- // 8->4->4->4->8
- // FIXME: Will not work when using dup and skip.
- // FIXME: Could behave weirdly with tie.
- if (this.swing[turtle].length > 0) {
- // Deprecated
- // newswing2 takes the target as an argument
- if (last(this.swingTarget[turtle]) == null) {
- // When we start a swing we need to keep track of
- // the initial beat value.
- this.swingTarget[turtle][this.swingTarget[turtle].length - 1] = noteBeatValue;
- }
-
- var swingValue = last(this.swing[turtle]);
- // If this notevalue matches the target, either we are
- // starting a swing or ending a swing.
- if (noteBeatValue === last(this.swingTarget[turtle])) {
- if (this.swingCarryOver[turtle] === 0) {
- noteBeatValue = 1 / ((1 / noteBeatValue) + (1 / swingValue));
- this.swingCarryOver[turtle] = swingValue;
- } else {
- if (noteBeatValue === swingValue) {
- noteBeatValue = 0;
- } else {
- noteBeatValue = 1 / ((1 / noteBeatValue) - (1 / swingValue));
- }
- this.swingCarryOver[turtle] = 0;
- }
-
- if (noteBeatValue < 0) {
- noteBeatValue = 0;
- }
- }
- }
-
- // Duration is the duration of the note to be
- // played. doWait sets the wait time for the turtle before
- // the next block is executed.
- var duration = noteBeatValue * this.beatFactor[turtle]; // beat value
- if (duration > 0 && !this.suppressOutput[turtle]) {
- this.turtleTime[turtle] += ((bpmFactor / duration) + (this.noteDelay / 1000)) * this.duplicateFactor[turtle];
- }
-
- if (!this.suppressOutput[turtle]) {
- if (duration > 0) {
- this._doWait(turtle, Math.max(((bpmFactor / duration) + (this.noteDelay / 1000)) * this.duplicateFactor[turtle] - turtleLag, 0));
- }
- }
-
- var waitTime = 0;
- for (var j = 0; j < this.duplicateFactor[turtle]; j++) {
- if (this.skipFactor[turtle] > 1 && this.skipIndex[turtle] % this.skipFactor[turtle] > 0) {
- this.skipIndex[turtle] += 1;
- // Lessen delay time by one note since we are
- // skipping a note.
- if (duration > 0) {
- this.waitTimes[turtle] -= ((bpmFactor / duration) + (this.noteDelay / 1000)) * 1000;
- if (this.waitTimes[turtle] < 0) {
- this.waitTimes[turtle] = 0;
- }
- }
- continue;
- }
-
- if (this.skipFactor[turtle] > 1) {
- this.skipIndex[turtle] += 1;
- }
-
- if (!this.suppressOutput[turtle]) {
- if (j > 0) {
- if (duration > 0) {
- waitTime += (bpmFactor * 1000 / duration);
- }
- }
- } else {
- waitTime = 0;
- }
-
- __playnote = function (that) {
- var notes = [];
- var drums = [];
- var insideChord = -1;
- if ((that.notePitches[turtle].length + that.oscList[turtle].length) > 1) {
- if (turtle in that.lilypondStaging && !that.justCounting[turtle]) {
- var insideChord = that.lilypondStaging[turtle].length + 1;
- } else {
- var insideChord = 1;
- }
- }
-
- that.noteBeat[turtle] = noteBeatValue;
-
- // Do not process a note if its duration is equal
- // to infinity or NaN.
- if (!isFinite(duration)) {
- return;
- }
-
- // Use the beatValue of the first note in
- // the group since there can only be one.
- if (that.staccato[turtle].length > 0) {
- var staccatoBeatValue = last(that.staccato[turtle]);
- if (staccatoBeatValue < 0) {
- // slur
- var beatValue = bpmFactor / ((noteBeatValue) * that.noteBeatValues[turtle][0]) + bpmFactor / (-staccatoBeatValue * that.noteBeatValues[turtle][0]);
- } else if (staccatoBeatValue > noteBeatValue) {
- // staccato
- var beatValue = bpmFactor / (staccatoBeatValue * that.noteBeatValues[turtle][0]);
- } else {
- var beatValue = bpmFactor / (noteBeatValue * that.noteBeatValues[turtle][0]);
- }
- } else {
- var beatValue = bpmFactor / (noteBeatValue * that.noteBeatValues[turtle][0]);
- }
-
- if (doVibrato) {
- vibratoValue = beatValue * (duration / vibratoRate);
- }
-
- that._dispatchTurtleSignals(turtle, beatValue, blk, noteBeatValue);
- // Process pitches
- if (that.notePitches[turtle].length > 0) {
- for (var i = 0; i < that.notePitches[turtle].length; i++) {
- if (that.notePitches[turtle][i] === 'rest') {
- note = 'R';
- } else {
- var noteObj = that.getNote(that.notePitches[turtle][i], that.noteOctaves[turtle][i], that.noteTranspositions[turtle][i], that.keySignature[turtle]);
-
- // If the cents for this note != 0, then
- // we need to convert to frequency and add
- // in the cents.
- if (that.noteCents[turtle][i] !== 0) {
- if (that.noteHertz[turtle][i] !== 0 && that.noteTranspositions[turtle][i] === 0) {
- var note = that.noteHertz[turtle][i];
- } else {
- var note = Math.floor(pitchToFrequency(noteObj[0], noteObj[1], that.noteCents[turtle][i], that.keySignature[turtle]));
- }
- } else {
- var note = noteObj[0] + noteObj[1];
- }
- }
-
- if (note !== 'R') {
- notes.push(note);
- }
-
- if (duration > 0) {
- if (carry > 0) {
- if (i === 0 && !that.justCounting[turtle]) {
- lilypondInsertTie(that, turtle);
- }
- originalDuration = 1 / ((1 / duration) - (1 / carry));
- } else {
- originalDuration = duration;
- }
- if (!that.justCounting[turtle]) {
- updateLilypondNotation(that, note, originalDuration, turtle, insideChord);
- }
- } else if (that.tieCarryOver[turtle] > 0) {
- if (!that.justCounting[turtle]) {
- updateLilypondNotation(that, note, that.tieCarryOver[turtle], turtle, insideChord);
- }
- } else {
- // console.log('duration == ' + duration + ' and tieCarryOver === 0 and drift is ' + drift);
- }
- }
-
- if (!that.justCounting[turtle]) {
- console.log("notes to play " + notes + ' ' + noteBeatValue);
- } else {
- console.log("notes to count " + notes + ' ' + noteBeatValue);
- }
-
- if (!that.suppressOutput[turtle]) {
- that.turtles.turtleList[turtle].blink(duration,last(that.polyVolume[turtle]));
- }
-
- if (notes.length > 0) {
- var len = notes[0].length;
-
- // Deprecated
- if (typeof(notes[i]) === 'string') {
- that.currentNotes[turtle] = notes[0].slice(0, len - 1);
- that.currentOctaves[turtle] = parseInt(notes[0].slice(len - 1));
- }
-
- if (that.turtles.turtleList[turtle].drum) {
- for (var i = 0; i < notes.length; i++) {
- notes[i] = notes[i].replace(/♭/g, 'b').replace(/♯/g, '#'); // 'C2'; // Remove pitch
-
- }
- } else {
- for (var i = 0; i < notes.length; i++) {
- if (typeof(notes[i]) === 'string') {
- notes[i] = notes[i].replace(/♭/g, 'b').replace(/♯/g, '#');
- }
- }
- }
-
- if (!that.suppressOutput[turtle] && duration > 0) {
- if (_THIS_IS_MUSIC_BLOCKS_) {
- if (that.oscList[turtle].length > 0) {
- if (notes.length > 1) {
- that.errorMsg(last(that.oscList[turtle]) + ': ' + _('synth cannot play chords.'), blk);
- }
-
- that.synth.trigger(notes, beatValue, last(that.oscList[turtle]), [vibratoIntensity, vibratoValue]);
- } else if (that.drumStyle[turtle].length > 0) {
- that.synth.trigger(notes, beatValue, last(that.drumStyle[turtle]), []);
- } else if (that.turtles.turtleList[turtle].drum) {
- that.synth.trigger(notes, beatValue, 'drum', []);
- } else {
- // Look for any notes in the chord that might be in the pitchDrumTable.
- for (var d = 0; d < notes.length; d++) {
- if (notes[d] in that.pitchDrumTable[turtle]) {
- that.synth.trigger(notes[d], beatValue, that.pitchDrumTable[turtle][notes[d]], []);
- } else if (turtle in that.voices && last(that.voices[turtle])) {
- that.synth.trigger(notes[d], beatValue, last(that.voices[turtle]), [vibratoIntensity, vibratoValue]);
- } else {
- that.synth.trigger(notes[d], beatValue, 'default', [vibratoIntensity, vibratoValue]);
- }
- }
- }
-
- that.synth.start();
- }
- }
-
- that.lastNotePlayed[turtle] = [notes[0], noteBeatValue];
- that.noteStatus[turtle] = [notes, noteBeatValue];
- }
- }
-
- // Process drums
- if (that.noteDrums[turtle].length > 0) {
- for (var i = 0; i < that.noteDrums[turtle].length; i++) {
- drums.push(that.noteDrums[turtle][i]);
- }
-
- // console.log("drums to play " + drums + ' ' + noteBeatValue);
-
- if (!that.suppressOutput[turtle] && duration > 0) {
- if (_THIS_IS_MUSIC_BLOCKS_) {
- for (var i = 0; i < drums.length; i++) {
- if (that.drumStyle[turtle].length > 0) {
- that.synth.trigger(['C2'], beatValue, last(that.drumStyle[turtle]), []);
- } else {
- that.synth.trigger(['C2'], beatValue, drums[i], []);
- }
- }
- }
- }
- }
-
- // Ensure note value block unhighlights after note plays.
- setTimeout(function () {
- if (that.blocks.visible) {
- that.blocks.unhighlight(blk);
- }
- }, beatValue * 1000);
- };
-
- if (waitTime === 0 || this.suppressOutput[turtle]) {
- __playnote(this);
- } else {
- var that = this;
- setTimeout(function () {
- __playnote(that);
- }, waitTime + this.noteDelay);
- }
-
- if (this.crescendoDelta[turtle].length > 0) {
- if (last(this.crescendoVolume[turtle]) === last(this.crescendoInitialVolume[turtle]) && !this.justCounting[turtle]) {
- lilypondBeginCrescendo(this, turtle, last(this.crescendoDelta[turtle]));
- }
-
- var len = this.crescendoVolume[turtle].length
- this.crescendoVolume[turtle][len - 1] += this.crescendoDelta[turtle][len - 1];
- this._setSynthVolume(this.crescendoVolume[turtle][len - 1], turtle);
- var len2 = this.polyVolume[turtle].length;
- this.polyVolume[turtle][len2 - 1] = this.crescendoVolume[turtle][len - 1];
- }
- }
-
- this.pushedNote[turtle] = false;
- }
- };
-
- this._dispatchTurtleSignals = function (turtle, beatValue, blk, noteBeatValue) {
- // When turtle commands (forward, right, arc) are inside of Notes,
- // they are progressive.
- var that = this;
- var stepTime = beatValue * 1000 / (NOTEDIV + 4);
-
- // We want to update the turtle graphics every 50ms with a note.
- // FIXME: Do this more efficiently
- if (stepTime > 200) {
- that.dispatchFactor[turtle] = 0.25;
- } else if (stepTime > 100) {
- that.dispatchFactor[turtle] = 0.5;
- } else if (stepTime > 50) {
- that.dispatchFactor[turtle] = 1;
- } else if (stepTime > 25) {
- that.dispatchFactor[turtle] = 2;
- } else if (stepTime > 12.5) {
- that.dispatchFactor[turtle] = 4;
- } else {
- that.dispatchFactor[turtle] = 8;
- }
-
- for (var t = 0; t < (NOTEDIV / that.dispatchFactor[turtle]); t++) {
- setTimeout(function () {
- if (turtle in that.forwardListener && blk in that.forwardListener[turtle]) {
- that.stage.dispatchEvent('_forward_' + turtle + '_' + blk);
- }
- if (turtle in that.rightListener && blk in that.rightListener[turtle]) {
- that.stage.dispatchEvent('_right_' + turtle + '_' + blk);
- }
- if (turtle in that.arcListener && blk in that.arcListener[turtle]) {
- that.stage.dispatchEvent('_arc_' + turtle + '_' + blk);
- }
- // (NOTEDIV + 4) is a workaround so that the graphics
- // finish a bit ahead of the note in order t minimize the
- // risk that there is overlap with the next note scheduled
- // to trigger.
- }, t * stepTime * that.dispatchFactor[turtle]);
- }
-
- setTimeout(function () {
- if (turtle in that.forwardListener && blk in that.forwardListener[turtle]) {
- for (var i = 0; i < that.forwardListener[turtle][blk].length; i++) {
- that.stage.removeEventListener('_forward_' + turtle + '_' + blk, that.forwardListener[turtle][blk][i], false);
- }
- delete that.forwardListener[turtle][blk];
- }
-
- if (turtle in that.rightListener && blk in that.rightListener[turtle]) {
- for (var i = 0; i < that.rightListener[turtle][blk].length; i++) {
- that.stage.removeEventListener('_right_' + turtle + '_' + blk, that.rightListener[turtle][blk][i], false);
- }
- delete that.rightListener[turtle][blk];
- }
-
- if (turtle in that.arcListener && blk in that.arcListener[turtle]) {
- for (var i = 0; i < that.arcListener[turtle][blk].length; i++) {
- that.stage.removeEventListener('_arc_' + turtle + '_' + blk, that.arcListener[turtle][blk][i], false);
- }
- delete that.arcListener[turtle][blk];
- }
-
- }, beatValue * 1000);
- };
-
- this._setListener = function (turtle, listenerName, listener) {
- if (listenerName in this.turtles.turtleList[turtle].listeners) {
- this.stage.removeEventListener(listenerName, this.turtles.turtleList[turtle].listeners[listenerName], false);
- }
- this.turtles.turtleList[turtle].listeners[listenerName] = listener;
- this.stage.addEventListener(listenerName, listener, false);
- };
-
- this._setDispatchBlock = function (blk, turtle, listenerName) {
- if (this.backward[turtle].length > 0) {
- if (this.blocks.blockList[last(this.backward[turtle])].name === 'backward') {
- var c = 1;
- } else {
- var c = 2;
- }
- if (this.blocks.sameGeneration(this.blocks.blockList[last(this.backward[turtle])].connections[c], blk)) {
- var nextBlock = this.blocks.blockList[blk].connections[0];
- this.endOfClampSignals[turtle][nextBlock] = [listenerName];
- } else {
- var nextBlock = null;
- }
- } else {
- var nextBlock = last(this.blocks.blockList[blk].connections);
- }
-
- if (nextBlock == null) {
- return;
- }
-
- this.endOfClampSignals[turtle][nextBlock] = [listenerName];
- };
-
- this._getTargetTurtle = function (args) {
- // The target turtle name can be a string or an int. Make
- // sure there is a turtle by this name and then find the
- // associated start block.
-
- var targetTurtle = args[0];
-
- // We'll compare the names as strings.
- if (typeof(targetTurtle) === 'number') {
- targetTurtle = targetTurtle.toString();
- }
-
- for (var i = 0; i < this.turtles.turtleList.length; i++) {
- var turtleName = this.turtles.turtleList[i].name;
- if (typeof(turtleName) === 'number') {
- turtleName = turtleName.toString();
- }
- if (turtleName === targetTurtle) {
- return i;
- }
- }
-
- return null;
- };
-
- this._loopBlock = function (name) {
- return ['forever', 'repeat', 'while', 'until'].indexOf(name) !== -1;
- };
-
- this._doBreak = function (turtle) {
- // Look for a parent loopBlock in queue and set its count to 1.
- var parentLoopBlock = null;
- var loopBlkIdx = -1;
- var queueLength = this.turtles.turtleList[turtle].queue.length;
- for (var i = queueLength - 1; i > -1; i--) {
- if (this._loopBlock(this.blocks.blockList[this.turtles.turtleList[turtle].queue[i].blk].name)) {
- // while or until
- loopBlkIdx = this.turtles.turtleList[turtle].queue[i].blk;
- parentLoopBlock = this.blocks.blockList[loopBlkIdx];
- // Flush the parent from the queue.
- this.turtles.turtleList[turtle].queue.pop();
- break;
- } else if (this._loopBlock(this.blocks.blockList[this.turtles.turtleList[turtle].queue[i].parentBlk].name)) {
- // repeat or forever
- loopBlkIdx = this.turtles.turtleList[turtle].queue[i].parentBlk;
- parentLoopBlock = this.blocks.blockList[loopBlkIdx];
- // Flush the parent from the queue.
- this.turtles.turtleList[turtle].queue.pop();
- break;
- }
- }
- if (parentLoopBlock == null) {
- // In this case, we flush the child flow.
- this.turtles.turtleList[turtle].queue.pop();
- return;
- }
-
- // For while and until, we need to add any childflow from the
- // parent to the queue.
- if (parentLoopBlock.name === 'while' || parentLoopBlock.name === 'until') {
- var childFlow = last(parentLoopBlock.connections);
- if (childFlow != null) {
- var queueBlock = new Queue(childFlow, 1, loopBlkIdx);
- // We need to keep track of the parent block to the
- // child flow so we can unlightlight the parent block
- // after the child flow completes.
- this.parentFlowQueue[turtle].push(loopBlkIdx);
- this.turtles.turtleList[turtle].queue.push(queueBlock);
- }
- }
- };
-
- this.parseArg = function (that, turtle, blk, parentBlk, receivedArg) {
- // Retrieve the value of a block.
- if (blk == null) {
- that.errorMsg('Missing argument.', parentBlk);
- that.stopTurtle = true;
- return null
- }
-
- if (that.blocks.blockList[blk].protoblock.parameter) {
- if (turtle in that.parameterQueue) {
- if (that.parameterQueue[turtle].indexOf(blk) === -1) {
- that.parameterQueue[turtle].push(blk);
- }
- } else {
- // console.log('turtle ' + turtle + ' has no parameterQueue');
- }
- }
-
- if (that.blocks.blockList[blk].isValueBlock()) {
- if (that.blocks.blockList[blk].name === 'number' && typeof(that.blocks.blockList[blk].value) === 'string') {
- try {
- that.blocks.blockList[blk].value = Number(that.blocks.blockList[blk].value);
- } catch (e) {
- console.log(e);
- }
- }
- return that.blocks.blockList[blk].value;
- } else if (that.blocks.blockList[blk].isArgBlock() || that.blocks.blockList[blk].isArgClamp() || that.blocks.blockList[blk].isArgFlowClampBlock()) {
- switch (that.blocks.blockList[blk].name) {
- case 'loudness':
- if (_THIS_IS_TURTLE_BLOCKS_) {
- try { // DEBUGGING P5 MIC
- if (!that.mic.enabled) {
- that.mic.start();
- that.blocks.blockList[blk].value = 0;
- } else {
- that.blocks.blockList[blk].value = Math.round(that.mic.getLevel() * 1000);
- }
- } catch (e) { // MORE DEBUGGING
- console.log(e);
- that.mic.start();
- that.blocks.blockList[blk].value = Math.round(that.mic.getLevel() * 1000);
- }
- } else {
- var values = that.analyser.analyse();
- var sum = 0;
- for(var k=0; k<that.limit; k++){
- sum += (values[k] * values[k]);
- }
- var rms = Math.sqrt(sum/that.limit);
- try {
- if (!that.mic.open()) {
- that.mic.open();
- that.blocks.blockList[blk].value = 0;
- } else {
- that.blocks.blockList[blk].value = Math.round(rms);
- }
- } catch (e) { // MORE DEBUGGING
- console.log(e);
- that.mic.open();
- that.blocks.blockList[blk].value = Math.round(rms);
- }
- }
- break;
- case 'eval':
- var cblk1 = that.blocks.blockList[blk].connections[1];
- var cblk2 = that.blocks.blockList[blk].connections[2];
- var a = that.parseArg(that, turtle, cblk1, blk, receivedArg);
- var b = that.parseArg(that, turtle, cblk2, blk, receivedArg);
- // Restricted to math methods
- that.blocks.blockList[blk].value = Number(eval('Math.' + a.replace(/x/g, b.toString())));
- break;
- case 'arg':
- var cblk = that.blocks.blockList[blk].connections[1];
- var name = that.parseArg(that, turtle, cblk, blk, receivedArg);
- var action_args=receivedArg
- if(action_args.length >= Number(name)){
- var value = action_args[Number(name)-1];
- that.blocks.blockList[blk].value = value;
- }else {
- that.errorMsg('Invalid argument',blk);
- that.stopTurtle = true;
- }
- return that.blocks.blockList[blk].value;
- break;
- case 'box':
- var cblk = that.blocks.blockList[blk].connections[1];
- var name = that.parseArg(that, turtle, cblk, blk, receivedArg);
- if (name in that.boxes) {
- that.blocks.blockList[blk].value = that.boxes[name];
- } else {
- that.errorMsg(NOBOXERRORMSG, blk, name);
- that.stopTurtle = true;
- that.blocks.blockList[blk].value = null;
- }
- break;
- case 'turtlename':
- that.blocks.blockList[blk].value = that.turtles.turtleList[turtle].name;
- break;
- case 'namedbox':
- var name = that.blocks.blockList[blk].privateData;
- if (that.inStatusMatrix && that.blocks.blockList[that.blocks.blockList[blk].connections[0]].name === 'print') {
- that.statusFields.push([blk, that.blocks.blockList[blk].name]);
- } else if (!that.updatingStatusMatrix) {
- if (name in that.boxes) {
- that.blocks.blockList[blk].value = that.boxes[name];
- } else {
- that.errorMsg(NOBOXERRORMSG, blk, name);
- that.stopTurtle = true;
- that.blocks.blockList[blk].value = null;
- }
- }
- break;
- case 'namedarg' :
- var name = that.blocks.blockList[blk].privateData;
- var action_args = receivedArg;
-
- // If an action block with an arg is clicked,
- // the arg will have no value.
- if (action_args == null) {
- that.errorMsg('Invalid argument', blk);
- that.stopTurtle = true;
- that.blocks.blockList[blk].value = null;
- return;
- }
-
- if (action_args.length >= Number(name)) {
- var value = action_args[Number(name)-1];
- that.blocks.blockList[blk].value = value;
- } else {
- that.errorMsg('Invalid argument', blk);
- }
-
- return that.blocks.blockList[blk].value;
- break;
- case 'sqrt':
- if (that.inStatusMatrix && that.blocks.blockList[that.blocks.blockList[blk].connections[0]].name === 'print') {
- that.statusFields.push([blk, that.blocks.blockList[blk].name]);
- } else {
- var cblk = that.blocks.blockList[blk].connections[1];
- var a = that.parseArg(that, turtle, cblk, blk, receivedArg);
- if (a < 0) {
- that.errorMsg(NOSQRTERRORMSG, blk);
- that.stopTurtle = true;
- a = -a;
- }
- that.blocks.blockList[blk].value = that._doSqrt(a);
- }
- break;
- case 'int':
- if (that.inStatusMatrix && that.blocks.blockList[that.blocks.blockList[blk].connections[0]].name === 'print') {
- that.statusFields.push([blk, 'int']);
- } else {
- var cblk = that.blocks.blockList[blk].connections[1];
- var a = that.parseArg(that, turtle, cblk, blk, receivedArg);
- that.blocks.blockList[blk].value = Math.floor(a);
- }
- break;
- case 'mod':
- if (that.inStatusMatrix && that.blocks.blockList[that.blocks.blockList[blk].connections[0]].name === 'print') {
- that.statusFields.push([blk, 'mod']);
- } else {
- var cblk1 = that.blocks.blockList[blk].connections[1];
- var cblk2 = that.blocks.blockList[blk].connections[2];
- var a = that.parseArg(that, turtle, cblk1, blk, receivedArg);
- var b = that.parseArg(that, turtle, cblk2, blk, receivedArg);
- that.blocks.blockList[blk].value = that._doMod(a, b);
- }
- break;
- case 'not':
- var cblk = that.blocks.blockList[blk].connections[1];
- var a = that.parseArg(that, turtle, cblk, blk, receivedArg);
- that.blocks.blockList[blk].value = !a;
- break;
- case 'greater':
- var cblk1 = that.blocks.blockList[blk].connections[1];
- var cblk2 = that.blocks.blockList[blk].connections[2];
- var a = that.parseArg(that, turtle, cblk1, blk, receivedArg);
- var b = that.parseArg(that, turtle, cblk2, blk, receivedArg);
- that.blocks.blockList[blk].value = (Number(a) > Number(b));
- break;
- case 'equal':
- var cblk1 = that.blocks.blockList[blk].connections[1];
- var cblk2 = that.blocks.blockList[blk].connections[2];
- var a = that.parseArg(that, turtle, cblk1, blk, receivedArg);
- var b = that.parseArg(that, turtle, cblk2, blk, receivedArg);
- that.blocks.blockList[blk].value = (a === b);
- break;
- case 'less':
- var cblk1 = that.blocks.blockList[blk].connections[1];
- var cblk2 = that.blocks.blockList[blk].connections[2];
- var a = that.parseArg(that, turtle, cblk1, blk, receivedArg);
- var b = that.parseArg(that, turtle, cblk2, blk, receivedArg);
- var result = (Number(a) < Number(b));
- that.blocks.blockList[blk].value = result;
- break;
- case 'random':
- var cblk1 = that.blocks.blockList[blk].connections[1];
- var cblk2 = that.blocks.blockList[blk].connections[2];
- var a = that.parseArg(that, turtle, cblk1, blk, receivedArg);
- var b = that.parseArg(that, turtle, cblk2, blk, receivedArg);
- that.blocks.blockList[blk].value = that._doRandom(a, b);
- break;
- case 'oneOf':
- var cblk1 = that.blocks.blockList[blk].connections[1];
- var cblk2 = that.blocks.blockList[blk].connections[2];
- var a = that.parseArg(that, turtle, cblk1, blk, receivedArg);
- var b = that.parseArg(that, turtle, cblk2, blk, receivedArg);
- that.blocks.blockList[blk].value = that._doOneOf(a, b);
- break;
- case 'plus':
- if (that.inStatusMatrix && that.blocks.blockList[that.blocks.blockList[blk].connections[0]].name === 'print') {
- that.statusFields.push([blk, 'plus']);
- } else {
- var cblk1 = that.blocks.blockList[blk].connections[1];
- var cblk2 = that.blocks.blockList[blk].connections[2];
- var a = that.parseArg(that, turtle, cblk1, blk, receivedArg);
- var b = that.parseArg(that, turtle, cblk2, blk, receivedArg);
- that.blocks.blockList[blk].value = that._doPlus(a, b);
- }
- break;
- case 'multiply':
- if (that.inStatusMatrix && that.blocks.blockList[that.blocks.blockList[blk].connections[0]].name === 'print') {
- that.statusFields.push([blk, 'multiply']);
- } else {
- var cblk1 = that.blocks.blockList[blk].connections[1];
- var cblk2 = that.blocks.blockList[blk].connections[2];
- var a = that.parseArg(that, turtle, cblk1, blk, receivedArg);
- var b = that.parseArg(that, turtle, cblk2, blk, receivedArg);
- that.blocks.blockList[blk].value = that._doMultiply(a, b);
- }
- break;
- case 'power':
- if (that.inStatusMatrix && that.blocks.blockList[that.blocks.blockList[blk].connections[0]].name === 'print') {
- that.statusFields.push([blk, 'power']);
- } else {
- var cblk1 = that.blocks.blockList[blk].connections[1];
- var cblk2 = that.blocks.blockList[blk].connections[2];
- var a = that.parseArg(that, turtle, cblk1, blk, receivedArg);
- var b = that.parseArg(that, turtle, cblk2, blk, receivedArg);
- that.blocks.blockList[blk].value = that._doPower(a, b);
- }
- break;
- case 'divide':
- if (that.inStatusMatrix && that.blocks.blockList[that.blocks.blockList[blk].connections[0]].name === 'print') {
- that.statusFields.push([blk, 'divide']);
- } else {
- var cblk1 = that.blocks.blockList[blk].connections[1];
- var cblk2 = that.blocks.blockList[blk].connections[2];
- var a = that.parseArg(that, turtle, cblk1, blk, receivedArg);
- var b = that.parseArg(that, turtle, cblk2, blk, receivedArg);
- that.blocks.blockList[blk].value = that._doDivide(a, b);
- }
- break;
- case 'minus':
- if (that.inStatusMatrix && that.blocks.blockList[that.blocks.blockList[blk].connections[0]].name === 'print') {
- that.statusFields.push([blk, 'minus']);
- } else {
- var cblk1 = that.blocks.blockList[blk].connections[1];
- var cblk2 = that.blocks.blockList[blk].connections[2];
- var a = that.parseArg(that, turtle, cblk1, blk, receivedArg);
- var b = that.parseArg(that, turtle, cblk2, blk, receivedArg);
- that.blocks.blockList[blk].value = that._doMinus(a, b);
- }
- break;
- case 'neg':
- if (that.inStatusMatrix && that.blocks.blockList[that.blocks.blockList[blk].connections[0]].name === 'print') {
- that.statusFields.push([blk, 'neg']);
- } else {
- var cblk1 = that.blocks.blockList[blk].connections[1];
- var a = that.parseArg(that, turtle, cblk1, blk, receivedArg);
- that.blocks.blockList[blk].value = that._doMinus(0, a);
- }
- break;
- case 'toascii':
- if (that.inStatusMatrix && that.blocks.blockList[that.blocks.blockList[blk].connections[0]].name === 'print') {
- that.statusFields.push([blk, 'toascii']);
- } else {
- var cblk1 = that.blocks.blockList[blk].connections[1];
- var a = that.parseArg(that, turtle, cblk1, blk, receivedArg);
- that.blocks.blockList[blk].value = String.fromCharCode(a);
- }
- break;
- case 'myclick':
- console.log('[click' + that.turtles.turtleList[turtle].name + ']');
- that.blocks.blockList[blk].value = 'click' + that.turtles.turtleList[turtle].name;
- break;
- case 'heading':
- if (that.inStatusMatrix && that.blocks.blockList[that.blocks.blockList[blk].connections[0]].name === 'print') {
- that.statusFields.push([blk, 'heading']);
- } else {
- that.blocks.blockList[blk].value = that.turtles.turtleList[turtle].orientation;
- }
- break;
- case 'x':
- if (that.inStatusMatrix && that.blocks.blockList[that.blocks.blockList[blk].connections[0]].name === 'print') {
- that.statusFields.push([blk, 'x']);
- } else {
- that.blocks.blockList[blk].value = that.turtles.screenX2turtleX(that.turtles.turtleList[turtle].container.x);
- }
- break;
- case 'y':
- if (that.inStatusMatrix && that.blocks.blockList[that.blocks.blockList[blk].connections[0]].name === 'print') {
- that.statusFields.push([blk, 'y']);
- } else {
- that.blocks.blockList[blk].value = that.turtles.screenY2turtleY(that.turtles.turtleList[turtle].container.y);
- }
- break;
- case 'xturtle':
- case 'yturtle':
- var cblk = that.blocks.blockList[blk].connections[1];
- var targetTurtle = that.parseArg(that, turtle, cblk, blk, receivedArg);
- for (var i = 0; i < that.turtles.turtleList.length; i++) {
- var thisTurtle = that.turtles.turtleList[i];
- if (targetTurtle === thisTurtle.name) {
- if (that.blocks.blockList[blk].name === 'yturtle') {
- that.blocks.blockList[blk].value = that.turtles.screenY2turtleY(thisTurtle.container.y);
- } else {
- that.blocks.blockList[blk].value = that.turtles.screenX2turtleX(thisTurtle.container.x);
- }
- break;
- }
- }
- if (i === that.turtles.turtleList.length) {
- that.errorMsg('Could not find turtle ' + targetTurtle, blk);
- that.blocks.blockList[blk].value = 0;
- }
- break;
- case 'bpmfactor':
- if (that.inStatusMatrix && that.blocks.blockList[that.blocks.blockList[blk].connections[0]].name === 'print') {
- that.statusFields.push([blk, 'bpm']);
- } else if (that.bpm[turtle].length > 0) {
- that.blocks.blockList[blk].value = last(that.bpm[turtle]);
- } else {
- that.blocks.blockList[blk].value = that._masterBPM;
- }
- break;
- case 'staccatofactor':
- if (that.inStatusMatrix && that.blocks.blockList[that.blocks.blockList[blk].connections[0]].name === 'print') {
- that.statusFields.push([blk, 'staccato']);
- } else if (that.staccato[turtle].length > 0) {
- that.blocks.blockList[blk].value = last(that.staccato[turtle]);
- } else {
- that.blocks.blockList[blk].value = 0;
- }
- break;
- case 'slurfactor':
- if (that.inStatusMatrix && that.blocks.blockList[that.blocks.blockList[blk].connections[0]].name === 'print') {
- that.statusFields.push([blk, 'slur']);
- } else if (that.staccato[turtle].length > 0) {
- that.blocks.blockList[blk].value = -last(that.staccato[turtle]);
- } else {
- that.blocks.blockList[blk].value = 0;
- }
- break;
- case 'key':
- if (that.inStatusMatrix && that.blocks.blockList[that.blocks.blockList[blk].connections[0]].name === 'print') {
- that.statusFields.push([blk, 'key']);
- } else {
- that.blocks.blockList[blk].value = that.keySignature[turtle];
- }
- break;
- case 'consonantstepsizeup':
- if (that.lastNotePlayed[turtle] !== null) {
- var len = that.lastNotePlayed[turtle][0].length;
- that.blocks.blockList[blk].value = getStepSizeUp(that.keySignature[turtle], that.lastNotePlayed[turtle][0].slice(0, len - 1));
- } else {
- that.blocks.blockList[blk].value = getStepSizeUp(that.keySignature[turtle], 'A');
- }
- break;
- case 'consonantstepsizedown':
- if (that.lastNotePlayed[turtle] !== null) {
- var len = that.lastNotePlayed[turtle][0].length;
- that.blocks.blockList[blk].value = getStepSizeDown(that.keySignature[turtle], that.lastNotePlayed[turtle][0].slice(0, len - 1));
- } else {
- that.blocks.blockList[blk].value = getStepSizeDown(that.keySignature[turtle], 'A');
- }
- break;
- case 'transpositionfactor':
- if (that.inStatusMatrix && that.blocks.blockList[that.blocks.blockList[blk].connections[0]].name === 'print') {
- that.statusFields.push([blk, 'transposition']);
- } else {
- that.blocks.blockList[blk].value = that.transposition[turtle];
- }
- break;
- case 'duplicatefactor':
- if (that.inStatusMatrix && that.blocks.blockList[that.blocks.blockList[blk].connections[0]].name === 'print') {
- that.statusFields.push([blk, 'duplicate']);
- } else {
- that.blocks.blockList[blk].value = that.duplicateFactor[turtle];
- }
- break;
- case 'skipfactor':
- if (that.inStatusMatrix && that.blocks.blockList[that.blocks.blockList[blk].connections[0]].name === 'print') {
- that.statusFields.push([blk, 'skip']);
- } else {
- that.blocks.blockList[blk].value = that.skipFactor[turtle];
- }
- break;
- case 'notevolumefactor':
- if (that.inStatusMatrix && that.blocks.blockList[that.blocks.blockList[blk].connections[0]].name === 'print') {
- that.statusFields.push([blk, 'volume']);
- } else {
- that.blocks.blockList[blk].value = last(that.polyVolume[turtle]);
- }
- break;
- case 'elapsednotes':
- if (that.inStatusMatrix && that.blocks.blockList[that.blocks.blockList[blk].connections[0]].name === 'print') {
- that.statusFields.push([blk, 'elapsednotes']);
- } else {
- that.blocks.blockList[blk].value = that.notesPlayed[turtle];
- }
- break;
- case 'beatfactor':
- if (that.inStatusMatrix && that.blocks.blockList[that.blocks.blockList[blk].connections[0]].name === 'print') {
- that.statusFields.push([blk, 'beatfactor']);
- } else {
- that.blocks.blockList[blk].value = that.beatFactor[turtle];
- }
- break;
- case 'number2pitch':
- case 'number2octave':
- var cblk = that.blocks.blockList[blk].connections[1];
- var num = that.parseArg(that, turtle, cblk, blk, receivedArg);
- if (num != null && typeof(num) === 'number') {
- var obj = numberToPitch(num + that.pitchNumberOffset);
- if (that.blocks.blockList[blk].name === 'number2pitch') {
- that.blocks.blockList[blk].value = obj[0];
- } else {
- that.blocks.blockList[blk].value = obj[1];
- }
- } else {
- that.errorMsg('Invalid argument', blk);
- that.stopTurtle = true;
- }
- break;
- case 'turtlepitch':
- var value = null;
- var cblk = that.blocks.blockList[blk].connections[1];
- var targetTurtle = that.parseArg(that, turtle, cblk, blk, receivedArg);
- for (var i = 0; i < that.turtles.turtleList.length; i++) {
- var thisTurtle = that.turtles.turtleList[i];
- if (targetTurtle === thisTurtle.name) {
- if (that.lastNotePlayed[turtle] !== null) {
- var len = that.lastNotePlayed[turtle][0].length;
- var pitch = that.lastNotePlayed[turtle][0].slice(0, len - 1);
- var octave = parseInt(that.lastNotePlayed[turtle][0].slice(len - 1));
-
- var obj = [pitch, octave];
- } else if(that.notePitches[i].length > 0) {
- var obj = that.getNote(that.notePitches[i][0], that.noteOctaves[i][0], that.noteTranspositions[i][0], that.keySignature[i]);
- } else {
- console.log('Could not find a note for turtle ' + turtle);
- var obj = ['C', 0];
- }
- value = pitchToNumber(obj[0], obj[1], that.keySignature[turtle]) - that.pitchNumberOffset;
- that.blocks.blockList[blk].value = value;
- }
- }
- if (value == null) {
- that.errorMsg('Could not find turtle ' + targetTurtle, blk);
- that.blocks.blockList[blk].value = 0;
- }
- break;
- case 'turtlenote':
- case 'turtlenote2':
- var value = null;
- var cblk = that.blocks.blockList[blk].connections[1];
- var targetTurtle = that.parseArg(that, turtle, cblk, blk, receivedArg);
- for (var i = 0; i < that.turtles.turtleList.length; i++) {
- var thisTurtle = that.turtles.turtleList[i];
- if (targetTurtle === thisTurtle.name) {
- if (that.lastNotePlayed[turtle] !== null) {
- value = that.lastNotePlayed[turtle][1];
- } else if(that.notePitches[i].length > 0) {
- value = that.noteBeat[i];
- } else {
- console.log('Could not find a note for turtle ' + turtle);
- value = -1;
- }
- if (that.blocks.blockList[blk].name === 'turtlenote') {
- that.blocks.blockList[blk].value = value;
- } else if (value !== 0) {
- that.blocks.blockList[blk].value = 1 / value;
- } else {
- that.blocks.blockList[blk].value = 0;
- }
- }
- }
- if (value == null) {
- that.errorMsg('Could not find turtle ' + targetTurtle, blk);
- that.blocks.blockList[blk].value = -1;
- }
- break;
- // Deprecated
- case 'currentnote':
- that.blocks.blockList[blk].value = that.currentNotes[turtle];
- break;
- // Deprecated
- case 'currentoctave':
- that.blocks.blockList[blk].value = that.currentOctaves[turtle];
- break;
- case 'color':
- case 'hue':
- if (that.inStatusMatrix && that.blocks.blockList[that.blocks.blockList[blk].connections[0]].name === 'print') {
- that.statusFields.push([blk, 'color']);
- } else {
- that.blocks.blockList[blk].value = that.turtles.turtleList[turtle].color;
- }
- break;
- case 'shade':
- if (that.inStatusMatrix && that.blocks.blockList[that.blocks.blockList[blk].connections[0]].name === 'print') {
- that.statusFields.push([blk, 'shade']);
- } else {
- that.blocks.blockList[blk].value = that.turtles.turtleList[turtle].value;
- }
- break;
- case 'grey':
- if (that.inStatusMatrix && that.blocks.blockList[that.blocks.blockList[blk].connections[0]].name === 'print') {
- that.statusFields.push([blk, 'grey']);
- } else {
- that.blocks.blockList[blk].value = that.turtles.turtleList[turtle].chroma;
- }
- break;
- case 'pensize':
- if (that.inStatusMatrix && that.blocks.blockList[that.blocks.blockList[blk].connections[0]].name === 'print') {
- that.statusFields.push([blk, 'pensize']);
- } else {
- that.blocks.blockList[blk].value = that.turtles.turtleList[turtle].stroke;
- }
- break;
- case 'and':
- var cblk1 = that.blocks.blockList[blk].connections[1];
- var cblk2 = that.blocks.blockList[blk].connections[2];
- var a = that.parseArg(that, turtle, cblk1, blk, receivedArg);
- var b = that.parseArg(that, turtle, cblk2, blk, receivedArg);
- that.blocks.blockList[blk].value = a && b;
- break;
- case 'or':
- var cblk1 = that.blocks.blockList[blk].connections[1];
- var cblk2 = that.blocks.blockList[blk].connections[2];
- var a = that.parseArg(that, turtle, cblk1, blk, receivedArg);
- var b = that.parseArg(that, turtle, cblk2, blk, receivedArg);
- that.blocks.blockList[blk].value = a || b;
- break;
- case 'time':
- var d = new Date();
- that.blocks.blockList[blk].value = (d.getTime() - that.time) / 1000;
- break;
- case 'hspace':
- var cblk = that.blocks.blockList[blk].connections[1];
- var v = that.parseArg(that, turtle, cblk, blk, receivedArg);
- that.blocks.blockList[blk].value = v;
- break;
- case 'mousex':
- that.blocks.blockList[blk].value = that.getStageX();
- break;
- case 'mousey':
- that.blocks.blockList[blk].value = that.getStageY();
- break;
- case 'mousebutton':
- that.blocks.blockList[blk].value = that.getStageMouseDown();
- break;
- case 'keyboard':
- that.lastKeyCode = that.getCurrentKeyCode();
- that.blocks.blockList[blk].value = that.lastKeyCode;
- that.clearCurrentKeyCode();
- break;
- case 'getred':
- case 'getgreen':
- case 'getblue':
- var colorString = that.turtles.turtleList[turtle].canvasColor;
- // 'rgba(255,0,49,1)' or '#ff0031'
- if (colorString[0] === "#") {
- colorString = hex2rgb(colorString.split("#")[1]);
- }
- var obj = colorString.split('(');
- var obj = obj[1].split(',');
- switch (that.blocks.blockList[blk].name) {
- case 'getred':
- that.blocks.blockList[blk].value = parseInt(Number(obj[0]) / 2.55);
- break;
- case 'getgreen':
- that.blocks.blockList[blk].value = parseInt(Number(obj[1]) / 2.55);
- break;
- case 'getblue':
- that.blocks.blockList[blk].value = parseInt(Number(obj[2]) / 2.55);
- break;
- }
- break;
- case 'getcolorpixel':
- var wasVisible = that.turtles.turtleList[turtle].container.visible;
- that.turtles.turtleList[turtle].container.visible = false;
- var x = that.turtles.turtleList[turtle].container.x;
- var y = that.turtles.turtleList[turtle].container.y;
- that.refreshCanvas();
- var ctx = that.canvas.getContext('2d');
- var imgData = ctx.getImageData(x, y, 1, 1).data;
- var color = searchColors(imgData[0], imgData[1], imgData[2]);
- if (imgData[3] === 0) {
- color = body.style.background.substring(body.style.background.indexOf('(') + 1, body.style.background.lastIndexOf(')')).split(/,\s*/),
- color = searchColors(color[0], color[1], color[2]);
- }
- that.blocks.blockList[blk].value = color;
- if (wasVisible) {
- that.turtles.turtleList[turtle].container.visible = true;
- }
- break;
- case 'loadFile':
- // No need to do anything here.
- break;
- case 'tofrequency':
- if (_THIS_IS_MUSIC_BLOCKS_) {
- var block = that.blocks.blockList[blk];
- var cblk1 = that.blocks.blockList[blk].connections[1];
- var cblk2 = that.blocks.blockList[blk].connections[2];
- var note = that.parseArg(that, turtle, cblk1, blk, receivedArg);
- var octave = Math.floor(calcOctave(that.currentOctaves[turtle], that.parseArg(that, turtle, cblk2, blk, receivedArg)));
- block.value = Math.round(pitchToFrequency(note, octave, 0, that.keySignature[turtle]));
- } else {
- const NOTENAMES = ['A', 'B♭', 'B', 'C', 'D♭', 'D', 'E♭', 'E', 'F', 'G♭', 'G', 'A♭'];
- const NOTECONVERSION = {'A♯': 'B♭', 'C♯': 'D♭', 'D♯': 'E♭', 'F♯': 'G♭', 'G♯': 'A♭'};
- var block = that.blocks.blockList[blk];
- var cblk = block.connections[1];
- var noteName = that.parseArg(that, turtle, cblk, blk, receivedArg);
- if (typeof(noteName) === 'string') {
- noteName = noteName.replace('b', '♭');
- noteName = noteName.replace('#', '♯');
- if (noteName in NOTECONVERSION) {
- noteName = NOTECONVERSION[noteName];
- }
-
- var idx = NOTENAMES.indexOf(noteName);
- if (idx === -1) {
- this.errorMsg(_('Note name must be one of A, A♯, B♭, B, C, C♯, D♭, D, D♯, E♭, E, F, F♯, G♭, G, G♯ or A♭.'));
- block.value = 440;
- } else {
- var cblk = block.connections[2];
- var octave = Math.floor(that.parseArg(that, turtle, cblk, blk, receivedArg));
- if (octave < 1) {
- octave = 1;
- }
-
- if (idx > 2) {
- octave -= 1; // New octave starts on C
- }
-
- var i = octave * 12 + idx;
- block.value = 27.5 * Math.pow(1.05946309435929, i);
- }
- } else {
- block.value = 440 * Math.pow(2, (noteName - 69) / 12);
- }
- }
- break;
- case 'pop':
- var block = that.blocks.blockList[blk];
- if (turtle in that.turtleHeaps && that.turtleHeaps[turtle].length > 0) {
- block.value = that.turtleHeaps[turtle].pop();
- } else {
- that.errorMsg(_('empty heap'));
- block.value = null;
- }
- break;
- case 'indexHeap':
- var block = that.blocks.blockList[blk];
- var cblk = that.blocks.blockList[blk].connections[1];
- var a = that.parseArg(that, turtle, cblk, blk, receivedArg);
- if (!(turtle in that.turtleHeaps)) {
- that.turtleHeaps[turtle] = [];
- }
- // If index > heap length, grow the heap.
- while (that.turtleHeaps[turtle].length < a) {
- that.turtleHeaps[turtle].push(null);
- }
- block.value = that.turtleHeaps[turtle][a - 1];
- break;
- case 'heapLength':
- var block = that.blocks.blockList[blk];
- if (!(turtle in that.turtleHeaps)) {
- that.turtleHeaps[turtle] = [];
- }
- // console.log(that.turtleHeaps[turtle].length);
- block.value = that.turtleHeaps[turtle].length;
- break;
- case 'heapEmpty':
- var block = that.blocks.blockList[blk];
- if (turtle in that.turtleHeaps) {
- block.value = (that.turtleHeaps[turtle].length === 0);
- } else {
- block.value = true;
- }
- break;
- case 'notecounter':
- var saveCountingStatus = that.justCounting[turtle];
- var saveSuppressStatus = that.suppressOutput[turtle];
- that.suppressOutput[turtle] = true;
- that.justCounting[turtle] = true;
- var actionArgs = [];
- var saveNoteCount = that.notesPlayed[turtle];
- var cblk = that.blocks.blockList[blk].connections[1];
- if (cblk == null) {
- that.blocks.blockList[blk].value = 0;
- } else {
- that.turtles.turtleList[turtle].running = true;
- that._runFromBlockNow(that, turtle, cblk, true, actionArgs, that.turtles.turtleList[turtle].queue.length);
- that.blocks.blockList[blk].value = that.notesPlayed[turtle] - saveNoteCount;
- that.notesPlayed[turtle] = saveNoteCount;
- }
- that.justCounting[turtle] = saveCountingStatus;
- that.suppressOutput[turtle] = saveSuppressStatus;
- break;
- case 'calc':
- var actionArgs = [];
- var cblk = that.blocks.blockList[blk].connections[1];
- var name = that.parseArg(that, turtle, cblk, blk, receivedArg);
- actionArgs = receivedArg;
- // that.getBlockAtStartOfArg(blk);
- if (name in that.actions) {
- that.turtles.turtleList[turtle].running = true;
- that._runFromBlockNow(that, turtle, that.actions[name], true, actionArgs, that.turtles.turtleList[turtle].queue.length);
- that.blocks.blockList[blk].value = that.returns.shift();
- } else {
- that.errorMsg(NOACTIONERRORMSG, blk, name);
- that.stopTurtle = true;
- }
- break;
- case 'namedcalc':
- var name = that.blocks.blockList[blk].privateData;
- var actionArgs = [];
-
- actionArgs = receivedArg;
- // that.getBlockAtStartOfArg(blk);
- if (name in that.actions) {
- that.turtles.turtleList[turtle].running = true;
- that._runFromBlockNow(that, turtle, that.actions[name], true, actionArgs, that.turtles.turtleList[turtle].queue.length);
- that.blocks.blockList[blk].value = that.returns.shift();
- } else {
- that.errorMsg(NOACTIONERRORMSG, blk, name);
- that.stopTurtle = true;
- }
- break;
- case 'calcArg':
- var actionArgs = [];
- // that.getBlockAtStartOfArg(blk);
- if (that.blocks.blockList[blk].argClampSlots.length > 0) {
- for (var i = 0; i < that.blocks.blockList[blk].argClampSlots.length; i++){
- var t = (that.parseArg(that, turtle, that.blocks.blockList[blk].connections[i + 2], blk, receivedArg));
- actionArgs.push(t);
- }
- }
- var cblk = that.blocks.blockList[blk].connections[1];
- var name = that.parseArg(that, turtle, cblk, blk, receivedArg);
- if (name in that.actions) {
- that.turtles.turtleList[turtle].running = true;
- that._runFromBlockNow(that, turtle, that.actions[name], true, actionArgs, that.turtles.turtleList[turtle].queue.length);
- that.blocks.blockList[blk].value = that.returns.pop();
- } else {
- that.errorMsg(NOACTIONERRORMSG, blk, name);
- that.stopTurtle = true;
- }
- break;
- case 'namedcalcArg':
- var name = that.blocks.blockList[blk].privateData;
- var actionArgs = [];
- // that.getBlockAtStartOfArg(blk);
- if (that.blocks.blockList[blk].argClampSlots.length > 0) {
- for (var i = 0; i < that.blocks.blockList[blk].argClampSlots.length; i++){
- var t = (that.parseArg(that, turtle, that.blocks.blockList[blk].connections[i + 1], blk, receivedArg));
- actionArgs.push(t);
- }
- }
- if (name in that.actions) {
- // Just run the stack.
- that.turtles.turtleList[turtle].running = true;
- that._runFromBlockNow(that, turtle, that.actions[name], true, actionArgs, that.turtles.turtleList[turtle].queue.length);
- that.blocks.blockList[blk].value = that.returns.pop();
- } else {
- that.errorMsg(NOACTIONERRORMSG, blk, name);
- that.stopTurtle = true;
- }
- break;
- case 'doArg':
- return blk;
- break;
- case 'nameddoArg':
- return blk;
- break;
- case 'returnValue':
- if (that.returns.length > 0) {
- that.blocks.blockList[blk].value = that.returns.pop();
- } else {
- console.log('WARNING: No return value.');
- that.blocks.blockList[blk].value = 0;
- }
- break;
- default:
- if (that.blocks.blockList[blk].name in that.evalArgDict) {
- eval(that.evalArgDict[that.blocks.blockList[blk].name]);
- } else {
- console.log('ERROR: I do not know how to ' + that.blocks.blockList[blk].name);
- }
- break;
- }
- return that.blocks.blockList[blk].value;
- } else {
- return blk;
- }
- };
-
- this._doWait = function (turtle, secs) {
- this.waitTimes[turtle] = Number(secs) * 1000;
- };
-
- // Math functions
- this._doRandom = function (a, b) {
- if (typeof(a) === 'string' || typeof(b) === 'string') {
- this.errorMsg(NANERRORMSG);
- this.stopTurtle = true;
- return 0;
- }
-
- return Math.floor(Math.random() * (Number(b) - Number(a) + 1) + Number(a));
- };
-
- this._doOneOf = function (a, b) {
- if (Math.random() < 0.5) {
- return a;
- } else {
- return b;
- }
- };
-
- this._doMod = function (a, b) {
- if (typeof(a) === 'string' || typeof(b) === 'string') {
- this.errorMsg(NANERRORMSG);
- this.stopTurtle = true;
- return 0;
- }
-
- return Number(a) % Number(b);
- };
-
- this._doSqrt = function (a) {
- if (typeof(a) === 'string') {
- this.errorMsg(NANERRORMSG);
- this.stopTurtle = true;
- return 0;
- }
-
- return Math.sqrt(Number(a));
- };
-
- this._doPlus = function (a, b) {
- if (typeof(a) === 'string' || typeof(b) === 'string') {
- if (typeof(a) === 'string') {
- var aString = a;
- } else {
- var aString = a.toString();
- }
-
- if (typeof(b) === 'string') {
- var bString = b;
- } else {
- var bString = b.toString();
- }
-
- return aString + bString;
- } else {
- return Number(a) + Number(b);
- }
- };
-
- this._doMinus = function (a, b) {
- if (typeof(a) === 'string' || typeof(b) === 'string') {
- this.errorMsg(NANERRORMSG);
- this.stopTurtle = true;
- return 0;
- }
-
- return Number(a) - Number(b);
- };
-
- this._doMultiply = function (a, b) {
- if (typeof(a) === 'string' || typeof(b) === 'string') {
- this.errorMsg(NANERRORMSG);
- this.stopTurtle = true;
- return 0;
- }
-
- return Number(a) * Number(b);
- };
-
- this._doPower = function (a, b) {
- if (typeof(a) === 'string' || typeof(b) === 'string') {
- this.errorMsg(NANERRORMSG);
- this.stopTurtle = true;
- return 0;
- }
-
- return Math.pow(a, b);
- };
-
- this._doDivide = function (a, b) {
- if (typeof(a) === 'string' || typeof(b) === 'string') {
- this.errorMsg(NANERRORMSG);
- this.stopTurtle = true;
- return 0;
- }
-
- if (Number(b) === 0) {
- this.errorMsg(ZERODIVIDEERRORMSG);
- this.stopTurtle = true;
- return 0;
- } else {
- return Number(a) / Number(b);
- }
- };
-
- this.setBackgroundColor = function (turtle) {
- /// Change body background in DOM to current color.
- if (turtle === -1) {
- var c = platformColor.background;
- } else {
- var c = this.turtles.turtleList[turtle].canvasColor;
- }
- docById('myCanvas').style.background = c;
- this.svgOutput = '';
- };
-
- this.setCameraID = function (id) {
- this.cameraID = id;
- };
-
- this.hideBlocks = function () {
- // Hide all the blocks.
- this.blocks.hide();
- this.refreshCanvas();
- };
-
- this.showBlocks = function () {
- // Show all the blocks.
- this.blocks.show();
- this.blocks.bringToTop();
- this.refreshCanvas();
- };
-
- this.getNote = function (solfege, octave, transposition, keySignature) {
- this.validNote = true;
- var sharpFlat = false;
-
- octave = Math.round(octave);
- transposition = Math.round(transposition);
- if (typeof(solfege) === 'number') {
- solfege = solfege.toString();
- }
-
- // Check for double flat or double sharp.
- var len = solfege.length;
- if (len > 2) {
- var lastTwo = solfege.slice(len - 2);
- if (lastTwo === 'bb' || lastTwo === '♭♭') {
- solfege = solfege.slice(0, len - 1);
- transposition -= 1;
- } else if (lastTwo === '##' || lastTwo === '♯♯') {
- solfege = solfege.slice(0, len - 1);
- transposition += 1;
- } else if (lastTwo === '#b' || lastTwo === '♯♭' || lastTwo === 'b#' || lastTwo === '♭♯') {
- // Not sure this could occur... but just in case.
- solfege = solfege.slice(0, len - 2);
- }
- }
-
- // Already a note? No need to convert from solfege.
- if (solfege in BTOFLAT) {
- solfege = BTOFLAT[solfege];
- } else if (solfege in STOSHARP) {
- solfege = STOSHARP[solfege];
- }
-
- if (solfege in EXTRATRANSPOSITIONS) {
- octave += EXTRATRANSPOSITIONS[solfege][1];
- note = EXTRATRANSPOSITIONS[solfege][0];
- } else if (NOTESSHARP.indexOf(solfege.toUpperCase()) !== -1) {
- note = solfege.toUpperCase();
- } else if (NOTESFLAT.indexOf(solfege) !== -1) {
- note = solfege;
- } else if (NOTESFLAT2.indexOf(solfege) !== -1) {
- // Convert to uppercase, e.g., d♭ -> D♭.
- note = NOTESFLAT[notesFlat2.indexOf(solfege)];
- } else {
- // Not a note, so convert from Solfege.
- // Could be mi#<sub>4</sub> (from matrix) or mi# (from note).
- if (solfege.substr(-1) === '>') {
- // Read octave and solfege from HTML
- octave = parseInt(solfege.slice(solfege.indexOf('>') + 1, solfege.indexOf('/') - 1));
- solfege = solfege.substr(0, solfege.indexOf('<'));
- }
-
- if(['#', '♯', '♭', 'b'].indexOf(solfege.substr(-1)) !== -1) {
- sharpFlat = true;
- }
-
- if (!keySignature) {
- keySignature = 'C';
- }
-
- var obj = getScaleAndHalfSteps(keySignature);
- var thisScale = obj[0];
- var halfSteps = obj[1];
- var myKeySignature = obj[2];
- var mode = obj[3];
-
- // Ensure it is a valid key signature.
- offset = thisScale.indexOf(myKeySignature);
- if (offset === -1) {
- console.log('WARNING: Key ' + myKeySignature + ' not found in ' + thisScale + '. Using default of C');
- var offset = 0;
- var thisScale = NOTESSHARP;
- }
-
- if (sharpFlat) {
- if (solfege.substr(-1) === '#') {
- offset += 1;
- } else if (solfege.substr(-1) === '♯') {
- offset += 1;
- } else if (solfege.substr(-1) === '♭') {
- offset -= 1;
- } else if(solfege.substr(-1) === 'b') {
- offset -= 1;
- }
- }
-
- // Reverse any i18n
- // solfnotes_ is used in the interface for i18n
- //.TRANS: the note names must be separated by single spaces
- var solfnotes_ = _('ti la sol fa mi re do').split(' ');
- if (solfnotes_.indexOf(solfege.substr(0, 2).toLowerCase()) !== -1) {
- var solfegePart = SOLFNOTES[solfnotes_.indexOf(solfege.substr(0, 2).toLowerCase())];
- } else if (solfnotes_.indexOf(solfege.substr(0, 3).toLowerCase()) !== -1) {
- var solfegePart = SOLFNOTES[solfnotes_.indexOf(solfege.substr(0, 3).toLowerCase())];
- } else {
- var solfegePart = solfege.substr(0, 2).toLowerCase();
- }
-
- if (solfege.toLowerCase().substr(0, 4) === 'rest') {
- return ['R', ''];
- } else if (halfSteps.indexOf(solfegePart) !== -1) {
- var index = halfSteps.indexOf(solfegePart) + offset;
- if (index > 11) {
- index -= 12;
- octave += 1;
- }
- note = thisScale[index];
- } else {
- console.log('WARNING: Note ' + solfege + ' not found in ' + halfSteps + '. Returning REST');
- // this.validNote = false;
- this.errorMsg(INVALIDPITCH, null);
- return ['R', ''];
- }
-
- if (note in EXTRATRANSPOSITIONS) {
- octave += EXTRATRANSPOSITIONS[note][1];
- note = EXTRATRANSPOSITIONS[note][0];
- }
- }
-
- if (transposition && transposition !== 0) {
- if (transposition < 0) {
- deltaOctave = -Math.floor(-transposition / 12);
- deltaNote = -(-transposition % 12);
- } else {
- deltaOctave = Math.floor(transposition / 12);
- deltaNote = transposition % 12;
- }
-
- octave += deltaOctave;
-
- if (NOTESSHARP.indexOf(note) !== -1) {
- i = NOTESSHARP.indexOf(note);
- i += deltaNote;
- if (i < 0) {
- i += 12;
- octave -= 1;
- } else if (i > 11) {
- i -= 12;
- octave += 1;
- }
- note = NOTESSHARP[i];
- } else if (NOTESFLAT.indexOf(note) !== -1) {
- i = NOTESFLAT.indexOf(note);
- i += deltaNote;
- if (i < 0) {
- i += 12;
- octave -= 1;
- } else if (i > 11) {
- i -= 12;
- octave += 1;
- }
- note = NOTESFLAT[i];
- } else {
- console.log('note not found? ' + note);
- }
- }
-
- if (octave < 0) {
- return [note, 0];
- } else if (octave > 10) {
- return [note, 10];
- } else {
- return [note, octave];
- }
- };
-
- };
|