// might adopt some strange functions from Module? // var maximJs = Module; // alternatively... // probably better this way // no inheritance of Module stuff... var maximJs = {}; maximJs.maxiSettings = Module.maxiSettings; maximJs.maxiOsc = Module.maxiOsc; maximJs.maxiEnvelope = Module.maxiEnvelope; maximJs.maxiDelayline = Module.maxiDelayline; maximJs.maxiFilter = Module.maxiFilter; maximJs.maxiMix = Module.maxiMix; maximJs.maxiLagExp = Module.maxiLagExp; maximJs.maxiSample = Module.maxiSample; maximJs.maxiMap = Module.maxiMap; maximJs.maxiDyn = Module.maxiDyn; maximJs.maxiEnv = Module.maxiEnv; maximJs.convert = Module.convert; maximJs.maxiDistortion = Module.maxiDistortion; maximJs.maxiFlanger = Module.maxiFlanger; maximJs.maxiChorus = Module.maxiChorus; maximJs.maxiDCBlocker = Module.maxiDCBlocker; maximJs.maxiSVF = Module.maxiSVF; maximJs.maxiEnvelopeFollower = Module.maxiEnvelopeFollower; maximJs.maxiKick = Module.maxiKick; maximJs.maxiSnare = Module.maxiSnare; maximJs.maxiHats = Module.maxiHats; maximJs.maxiClock = Module.maxiClock; // LIBS // FFT-ish maximJs.maxiFFT = Module.maxiFFT; maximJs.maxiIFFT = Module.maxiIFFT; maximJs.maxiMFCC = Module.maxiMFCC; maximJs.maxiFFTOctaveAnalyzer = Module.maxiFFTOctaveAnalyzer; // Grains maximJs.maxiTimestretch = Module.maxiTimestretch; maximJs.maxiPitchShift = Module.maxiPitchShift; maximJs.maxiPitchStretch = Module.maxiPitchStretch; // ------------------------------------------------ // maxiArray - could extend Array object? // cheaty array method to avoid mixing vector terminology with arrays // but have to copy everything?! // better to use GetArrayAsVectorDbl function ??? maximJs.maxiArray = function maxiArray(){ this.length = 0; var vec = new Module.VectorDouble(); // this.update = function(){ // var lengthsMatch = this.length !== this.vec.size(); // if(!lengthsMatch){ // if(this.length < this.vec.size()){ // for(var i = this.length; i < this.vec.size(); i++){ // this[i] = this.vec.get(i); // } // } else{ // for(var i = this.length; i < this.vec.size(); i++){ // delete this[i]; // } // } // // reset length var // this.length = this.vec.size(); // } // }; }; maximJs.maxiArray.prototype.asVector = function(arrayIn){ return this.vec; }; maximJs.maxiArray.prototype.asJsArray = function(arrayIn){ var arrayOut = []; for(var i = 0; i < this.length; i++){ array.push(this.vec.get(i)); } return arrayOut; }; maximJs.maxiArray.prototype.set = function(arrayIn){ this.clear(); this.vec = GetArrayAsVectorDbl(arrayIn); this.length = this.vec.size(); this.SetSqBrackets(true); }; maximJs.maxiArray.prototype.push = function(num){ this.vec.push_back(num); this[this.length] = num; this.length++; }; // set object properties to mimic array // this doesn't seem particularly efficient or smart maximJs.maxiArray.prototype.SetSqBrackets = function(useSq){ for(var i = 0; i < this.length; i++){ if(useSq){ this[i] = this.vec.get(i); } else{ delete this[i]; } } }; maximJs.maxiArray.prototype.clear = function(useSq){ for(var i = 0; i < this.length; i++){ delete this[i]; } Module.vectorTools.clearVectorDbl(this.vec); this.length = 0; }; // tools maximJs.maxiTools = function(){}; maximJs.maxiTools.prototype.arrayOfObj = function(obj, num){ var array = []; for(var i = 0; i < num; i++){ array.push(new obj()); } return array; }; maximJs.maxiTools.prototype.getArrayAsVectorDbl = function(arrayIn){ var vecOut = new Module.VectorDouble(); for(var i = 0; i < arrayIn.length; i++){ vecOut.push_back(arrayIn[i]); } return vecOut; }; // ------------------------------------------------ maximJs.maxiAudio = function() { this.numChannels = 2; this.output = 0; this.context = null; this.source = null; this.analyser = null; this.jsProcessor = null; this.initDone = false; }; maximJs.maxiAudio.play = function(){}; // don't really need setup?? maximJs.maxiAudio.prototype.setup = function(){ console.log("non-overrided setup"); }; maximJs.maxiAudio.prototype.getNumChannels = function(){ return this.numChannels; }; // isArray should be second param really // set num channels and set output as an array // use this if you want to change number of channels maximJs.maxiAudio.prototype.setNumChannels = function(isArray, numChannels_){ this.numChannels = numChannels_; this.outputIsArray(isArray, numChannels_); this.resetAudio(); }; // use this if you want to keep num of outputs but change // method e.g. array or not maximJs.maxiAudio.prototype.outputIsArray = function(isArray){ if(isArray){ this.output = new Array(this.numChannels); for(var i = 0; i < this.numChannels; i++){ this.output[i] = 0; } } else { this.output = 0; } }; // function handling audio processing // called byjsProcessor maximJs.maxiAudio.prototype.process = function(event) { var numChannels = event.outputBuffer.numberOfChannels; var outputLength = event.outputBuffer.getChannelData(0).length; // console.log("n"); for (var i = 0; i < outputLength; ++i) { this.play(); if(self.output instanceof Array){ for (var channel = 0; channel < numChannels; channel++) { event.outputBuffer.getChannelData(channel)[i] = this.output[channel]; } } else { for (var channel = 0; channel < numChannels; channel++) { event.outputBuffer.getChannelData(channel)[i] = this.output; } } } } .bind(this) ; maximJs.maxiAudio.prototype.init = function() { // Temporary patch until all browsers support unprefixed context. this.context = new (window.AudioContext || window.webkitAudioContext)(); this.source = this.context.createBufferSource(); this.jsProcessor = this.context.createScriptProcessor(4096, this.numChannels, this.numChannels); // var process = this.process; this.jsProcessor.onaudioprocess = function(event) { var numChannels = event.outputBuffer.numberOfChannels; var outputLength = event.outputBuffer.getChannelData(0).length; // console.log("n"); for (var i = 0; i < outputLength; ++i) { this.play(); if(self.output instanceof Array){ for (var channel = 0; channel < numChannels; channel++) { event.outputBuffer.getChannelData(channel)[i] = this.output[channel]; } } else { for (var channel = 0; channel < numChannels; channel++) { event.outputBuffer.getChannelData(channel)[i] = this.output; } } } } .bind(this) ; this.analyser = this.context.createAnalyser(); this.analyser.fftSize = 2048; // Connect the processing graph: source -> jsProcessor -> analyser -> destination this.source.connect(this.jsProcessor); this.jsProcessor.connect(this.analyser); this.analyser.connect(this.context.destination); this.initDone = true; }; maximJs.maxiAudio.prototype.resetAudio = function(){ if(this.initDone){ this.source.disconnect(); this.jsProcessor.disconnect(); this.analyser.disconnect(); } this.init(); }; // option to load sample if a different context is used maximJs.maxiAudio.prototype.loadSample = function(url, samplePlayer, contextIn) { var data = []; var context; if(!contextIn){ context = this.context; } else { context = contextIn; } samplePlayer.clear(); // Load asynchronously var request = new XMLHttpRequest(); request.addEventListener("load", function (evt) { console.log("The transfer is complete."); }); request.open("GET", url, true); request.responseType = "arraybuffer"; request.onload = function() { context.decodeAudioData( request.response, function(buffer) { // source.buffer = buffer; // source.loop = true; // source.start(0); data = buffer.getChannelData(0); if(data){ var myBufferData = new Module.VectorDouble(); // Module.vectorTools.clearVectorDbl(myBufferData); for(var n = 0; n < data.length; n++){ myBufferData.push_back(data[n]); } samplePlayer.setSample(myBufferData/*, context.sampleRate*/); } }, function(buffer) { console.log("Error decoding source!"); } ); }; request.send(); };