Skip to content
Snippets Groups Projects
maxi_webAudio.js 8.57 KiB
Newer Older
// 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;

Dr-Dan's avatar
Dr-Dan committed
// ------------------------------------------------
// 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];
        }
    }
};
Dr-Dan's avatar
Dr-Dan committed

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;
};
Dr-Dan's avatar
Dr-Dan committed


// tools
maximJs.maxiTools = function(){};
maximJs.maxiTools.prototype.arrayOfObj = function(obj, num){
Dr-Dan's avatar
Dr-Dan committed

    for(var i = 0; i < num; i++){
        array.push(new obj());
    }
    return array;
};
Dr-Dan's avatar
Dr-Dan committed

maximJs.maxiTools.prototype.getArrayAsVectorDbl = function(arrayIn){
    var vecOut = new Module.VectorDouble();
    for(var i = 0; i < arrayIn.length; i++){
        vecOut.push_back(arrayIn[i]);
    }
Dr-Dan's avatar
Dr-Dan committed

Dr-Dan's avatar
Dr-Dan committed




// ------------------------------------------------
maximJs.maxiAudio = function() {
    this.numChannels = 2;

    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) {
        context = this.context;
Dr-Dan's avatar
Dr-Dan committed

Dr-Dan's avatar
Dr-Dan committed

    // 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();
};