// Jazz 081417 -- An experiment in JavaScript jazz improvisation. // I cleaned up a few things from an eailer version. // John Clavin -- August 14, 2017 var noteArray = [52,53,54,55,56,57,58,59,60,61,62,63,64, 65,66,67,68,69,70,71,72,73,74,75,76,77]; var dorianTemplate = [2,0,1,2,0,1,0,2,0,1,2,0, 2,0,1,2,0,1,0,2,0,1,2,0, 2,0,1,2,0,1,0,2,0,1,2,0,2,0]; var tempKeyArray = [2,0,1,2,0,1,0,2,0,1,2,0, 2,0,1,2,0,1,0,2,0,1,2,0,2,0]; var parserDirFlag; var parserIndex; var voiceArray = []; var music; var goMusic = true; var xPos = 0; function setup() { createCanvas(960, 400); frameRate(60); rectMode(CENTER); noStroke(); background(238); masterVolume(0.30); parserDirFlag = true; parserIndex = 4; for (var v = 0; v < 4; v++) { voice = new jcOsc(); voiceArray.push(voice); } music = new MusicManagement(); music.composeSpaces(); } function draw() { if (goMusic) { music.manage(); } } function MusicManagement() { this.timeSpaces = []; this.tsCounter = 0; this.composeSpaces = function() { for (var i = 0; i < 248; i++) { var s = new TimeSpace(); this.timeSpaces.push(s); } for (var j = 0; j < this.timeSpaces.length; j++) { this.timeSpaces[j].compose(); } } this.manage = function() { this.timeSpaces[this.tsCounter].musicGraphics(); if ((this.tsCounter + 1) < this.timeSpaces.length) { if (this.timeSpaces[this.tsCounter].timeFinishedFlag === false) { this.timeSpaces[this.tsCounter].play(); } else { this.timeSpaces[this.tsCounter].timeFinishedFlag = false; this.tsCounter++; this.timeSpaces[this.tsCounter].play(); } } else { goMusic = false; } } } function TimeSpace() { this.restFlag = false; this.noteStartedFlag = false; this.timeFinishedFlag = false; this.noteFoundFlag = false; this.hiNotesFlag = false; this.musicKey = 0; this.notes2Play = []; this.musicTime = 0; this.numberOfNotes = 0; this.compose = function() { if (random(100) < 7) { this.musicKey = int(random(12)); for ( var i = 0; i < noteArray.length; i++) { tempKeyArray[i] = dorianTemplate[i + this.musicKey]; } } if (random(100) < 80) { this.numberOfNotes = 1; } else { this.numberOfNotes = int(random(2, 5)); } if (this.numberOfNotes == 1) { this.musicTime = 9; noteFoundFlag = false; while(noteFoundFlag === false) { if(tempKeyArray[parserIndex] > 0) { var note = noteArray[parserIndex]; this.notes2Play[0] = note; noteFoundFlag = true; } this.parserMove(); } if (random(100) < 40) { if (this.hiNotesFlag === true) { parserIndex = int(random(4, 11)); } else { parserIndex = int(random(13, 20)); } parserDirFlag = !parserDirFlag; noteFoundFlag = false; while(noteFoundFlag === false) { if(tempKeyArray[parserIndex] == 2) { note = noteArray[parserIndex]; this.notes2Play[0] = note; noteFoundFlag = true; } this.parserMove(); } } } else { this.musicTime = 36; for (var j = 0; j < 4; j++) { noteFoundFlag = false; while(noteFoundFlag === false) { if(tempKeyArray[parserIndex] == 2) { note = noteArray[parserIndex]; this.notes2Play[j] = note; noteFoundFlag = true; } this.parserMove(); } } } } this.parserMove = function() { if (parserIndex >= 24) { parserDirFlag = false; } if (parserIndex <= 1) { parserDirFlag = true; } if (parserDirFlag === true) { parserIndex++; } else { parserIndex--; } if (parserIndex > 12) { this.hiNotesFlag = true; } else { this.hiNotesFlag = false; } } this.play = function() { if (this.restFlag === true) { if (this.musicTime > 0) { this.musicTime--; } else { this.timeFinishedFlag = true; } } else { if (this.noteStartedFlag === false) { for (var n = 0; n < this.numberOfNotes; n++) { voiceArray[n].jamOn(this.notes2Play[n]); } this.noteStartedFlag = true; } if (this.musicTime > 0) { this.musicTime--; } else { this.timeFinishedFlag = true; this.noteStartedFlag = false; } } } this.musicGraphics = function() { xPos = xPos + 0.25; for (var n = 0; n < this.numberOfNotes; n++) { var yPos = map(this.notes2Play[n], 77, 52, 0, height); noStroke(); if (this.numberOfNotes > 1) { fill(0); } else { fill(200, 0, 0); } rect(xPos, yPos, 6, 12); } } } function jcOsc() { this.osc1 = new p5.SawOsc(); this.osc2 = new p5.SawOsc(); this.osc1Env = new p5.Env(); this.osc2Env = new p5.Env(); this.osc1Env.setADSR(0.004, 0.25, 0.2, 0.8); this.osc2Env.setADSR(0.004, 0.15, 0.2, 0.8); this.osc1Env.setRange(0.60, 0); this.osc2Env.setRange(0.60, 0); this.osc1.amp(this.osc1Env); this.osc2.amp(this.osc2Env); this.osc1.start(); this.osc2.start(); this.jamOn = function(xnote) { this.note = xnote; this.osc1Freq = midiToFreq(this.note); this.osc2Freq = midiToFreq(this.note); this.osc1.freq(this.osc1Freq); this.osc2.freq(this.osc2Freq * 1.004); this.osc1Env.play(); this.osc2Env.play(); } }