repo: janusweb action: commit revision: path_from: revision_from: 2402a3be77c8cfc75fe55c5d87296cfc2858ddb9: path_to: revision_to:
commit 2402a3be77c8cfc75fe55c5d87296cfc2858ddb9 Author: James BaicoianuDate: Sun May 1 20:15:42 2016 -0700 Workaround for Resampler.initializeBuffers() being erroneously called during load diff --git a/scripts/external/JanusVOIP.js b/scripts/external/JanusVOIP.js
--- a/scripts/external/JanusVOIP.js
+++ b/scripts/external/JanusVOIP.js
@@ -1,430 +1,434 @@
-// event dispatcher by mrdoob https://github.com/mrdoob/eventdispatcher.js
-var EventDispatcher = function () {}
+(function() {
+ // event dispatcher by mrdoob https://github.com/mrdoob/eventdispatcher.js
+ var EventDispatcher = function () {}
-EventDispatcher.prototype = {
+ EventDispatcher.prototype = {
- constructor: EventDispatcher,
+ constructor: EventDispatcher,
- apply: function ( object ) {
+ apply: function ( object ) {
- object.addEventListener = EventDispatcher.prototype.addEventListener;
- object.hasEventListener = EventDispatcher.prototype.hasEventListener;
- object.removeEventListener = EventDispatcher.prototype.removeEventListener;
- object.dispatchEvent = EventDispatcher.prototype.dispatchEvent;
+ object.addEventListener = EventDispatcher.prototype.addEventListener;
+ object.hasEventListener = EventDispatcher.prototype.hasEventListener;
+ object.removeEventListener = EventDispatcher.prototype.removeEventListener;
+ object.dispatchEvent = EventDispatcher.prototype.dispatchEvent;
- },
+ },
- addEventListener: function ( type, listener ) {
+ addEventListener: function ( type, listener ) {
- if ( this._listeners === undefined ) this._listeners = {};
+ if ( this._listeners === undefined ) this._listeners = {};
- var listeners = this._listeners;
+ var listeners = this._listeners;
- if ( listeners[ type ] === undefined ) {
+ if ( listeners[ type ] === undefined ) {
- listeners[ type ] = [];
+ listeners[ type ] = [];
- }
+ }
- if ( listeners[ type ].indexOf( listener ) === - 1 ) {
+ if ( listeners[ type ].indexOf( listener ) === - 1 ) {
- listeners[ type ].push( listener );
+ listeners[ type ].push( listener );
- }
+ }
- },
+ },
- hasEventListener: function ( type, listener ) {
+ hasEventListener: function ( type, listener ) {
- if ( this._listeners === undefined ) return false;
+ if ( this._listeners === undefined ) return false;
- var listeners = this._listeners;
+ var listeners = this._listeners;
- if ( listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1 ) {
+ if ( listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1 ) {
- return true;
+ return true;
- }
+ }
- return false;
+ return false;
- },
+ },
- removeEventListener: function ( type, listener ) {
+ removeEventListener: function ( type, listener ) {
- if ( this._listeners === undefined ) return;
+ if ( this._listeners === undefined ) return;
- var listeners = this._listeners;
- var listenerArray = listeners[ type ];
+ var listeners = this._listeners;
+ var listenerArray = listeners[ type ];
- if ( listenerArray !== undefined ) {
+ if ( listenerArray !== undefined ) {
- var index = listenerArray.indexOf( listener );
+ var index = listenerArray.indexOf( listener );
- if ( index !== - 1 ) {
+ if ( index !== - 1 ) {
- listenerArray.splice( index, 1 );
+ listenerArray.splice( index, 1 );
+
+ }
}
- }
+ },
- },
+ dispatchEvent: function ( event ) {
+
+ if ( this._listeners === undefined ) return;
- dispatchEvent: function ( event ) {
-
- if ( this._listeners === undefined ) return;
+ var listeners = this._listeners;
+ var listenerArray = listeners[ event.type ];
- var listeners = this._listeners;
- var listenerArray = listeners[ event.type ];
+ if ( listenerArray !== undefined ) {
- if ( listenerArray !== undefined ) {
+ event.target = this;
- event.target = this;
+ var array = [];
+ var length = listenerArray.length;
- var array = [];
- var length = listenerArray.length;
+ for ( var i = 0; i < length; i ++ ) {
- for ( var i = 0; i < length; i ++ ) {
+ array[ i ] = listenerArray[ i ];
- array[ i ] = listenerArray[ i ];
+ }
- }
+ for ( var i = 0; i < length; i ++ ) {
- for ( var i = 0; i < length; i ++ ) {
+ array[ i ].call( this, event );
- array[ i ].call( this, event );
+ }
}
}
+ };
+ JanusVOIPRecorder = function(args) {
+ if (!args) var args = {};
+ this.sampleRate = args.sampleRate || 11000;
}
+ EventDispatcher.prototype.apply(JanusVOIPRecorder.prototype);
-};
-JanusVOIPRecorder = function(args) {
- if (!args) var args = {};
- this.sampleRate = args.sampleRate || 11000;
-}
-EventDispatcher.prototype.apply(JanusVOIPRecorder.prototype);
+ JanusVOIPRecorder.prototype.start = function() {
+ if (!this.context) {
+ this.createContext();
+ }
+ var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
+ if (!navigator.getUserMedia) {
+ navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
+ }
-JanusVOIPRecorder.prototype.start = function() {
- if (!this.context) {
- this.createContext();
+ navigator.getUserMedia({audio: true}, this.attachContext.bind(this), this.handleFailure.bind(this));
+ }
+ JanusVOIPRecorder.prototype.stop = function() {
+ if (this.voipsource) {
+ var tracks = this.voipsource.getAudioTracks();
+ tracks.forEach(function(track) {
+ track.stop();
+ });
+ this.voipsource = false;
+ this.dispatchEvent({type: 'voip_stop'});
+ }
}
- var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
- if (!navigator.getUserMedia) {
- navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
+ JanusVOIPRecorder.prototype.createContext = function() {
+ var audioContext = window.AudioContext || window.webkitAudioContext;
+ if (!this.context) {
+ this.context = new audioContext();
+ }
+ var context = this.context;
+
+ // retrieve the current sample rate to be used for WAV packaging
+ var sampleRate = context.sampleRate;
+
+ // creates a gain node
+ this.volume = context.createGain();
+
+ /* From the spec: This value controls how frequently the audioprocess event is
+ dispatched and how many sample-frames need to be processed each call.
+ Lower values for buffer size will result in a lower (better) latency.
+ Higher values will be necessary to avoid audio breakup and glitches */
+ var bufferSize = 4096;
+ this.recorder = context.createScriptProcessor(bufferSize, 1, 1);
+ var recorder = this.recorder;
+ // we connect the recorder
+ this.volume.connect (recorder);
+ recorder.connect (context.destination);
+
+ this.recorder = recorder;
+ this.dispatchEvent({type: 'voip_init'});
}
+ JanusVOIPRecorder.prototype.attachContext = function(audiostream) {
+ this.voipsource = audiostream;
+
+ // creates an audio node from the microphone incoming stream
+ var audioInput = this.context.createMediaStreamSource(audiostream);
- navigator.getUserMedia({audio: true}, this.attachContext.bind(this), this.handleFailure.bind(this));
-}
-JanusVOIPRecorder.prototype.stop = function() {
- if (this.voipsource) {
- var tracks = this.voipsource.getAudioTracks();
+ // connect the stream to the gain node
+ audioInput.connect(this.volume);
+
+ var recorder = this.recorder,
+ context = this.context;
+ recorder.onaudioprocess = this.processAudio.bind(this, context);
+ var tracks = this.voipsource.getTracks();
tracks.forEach(function(track) {
- track.stop();
- });
- this.voipsource = false;
- this.dispatchEvent({type: 'voip_stop'});
+ track.addEventListener('ended', function() { recorder.onaudioprocess = null; });
+ }.bind(this))
+
+ this.dispatchEvent({type: 'voip_start', element: this});
}
-}
-JanusVOIPRecorder.prototype.createContext = function() {
- var audioContext = window.AudioContext || window.webkitAudioContext;
- if (!this.context) {
- this.context = new audioContext();
+ JanusVOIPRecorder.prototype.processAudio = function(context, e){
+ var left = e.inputBuffer.getChannelData(0);
+ var resampler = new Resampler(context.sampleRate, this.sampleRate, 1, left);
+ var what = resampler.resampler(left.length);
+ var newbuf = new Uint16Array(resampler.outputBuffer.length);
+ for (var i = 0; i < newbuf.length; i++) {
+ newbuf[i] = Math.floor(resampler.outputBuffer[i] * 32767);
+ }
+ this.dispatchEvent({type: 'voip_data', element: this, data: newbuf});
}
- var context = this.context;
-
- // retrieve the current sample rate to be used for WAV packaging
- var sampleRate = context.sampleRate;
-
- // creates a gain node
- this.volume = context.createGain();
-
- /* From the spec: This value controls how frequently the audioprocess event is
- dispatched and how many sample-frames need to be processed each call.
- Lower values for buffer size will result in a lower (better) latency.
- Higher values will be necessary to avoid audio breakup and glitches */
- var bufferSize = 4096;
- this.recorder = context.createScriptProcessor(bufferSize, 1, 1);
- var recorder = this.recorder;
- // we connect the recorder
- this.volume.connect (recorder);
- recorder.connect (context.destination);
-
- this.recorder = recorder;
- this.dispatchEvent({type: 'voip_init'});
-}
-JanusVOIPRecorder.prototype.attachContext = function(audiostream) {
- this.voipsource = audiostream;
-
- // creates an audio node from the microphone incoming stream
- var audioInput = this.context.createMediaStreamSource(audiostream);
-
- // connect the stream to the gain node
- audioInput.connect(this.volume);
-
- var recorder = this.recorder,
- context = this.context;
- recorder.onaudioprocess = this.processAudio.bind(this, context);
- var tracks = this.voipsource.getTracks();
- tracks.forEach(function(track) {
- track.addEventListener('ended', function() { recorder.onaudioprocess = null; });
- }.bind(this))
-
- this.dispatchEvent({type: 'voip_start', element: this});
-}
-JanusVOIPRecorder.prototype.processAudio = function(context, e){
- var left = e.inputBuffer.getChannelData(0);
- var resampler = new Resampler(context.sampleRate, this.sampleRate, 1, left);
- var what = resampler.resampler(left.length);
- var newbuf = new Uint16Array(resampler.outputBuffer.length);
- for (var i = 0; i < newbuf.length; i++) {
- newbuf[i] = Math.floor(resampler.outputBuffer[i] * 32767);
+ JanusVOIPRecorder.prototype.handleFailure = function(err) {
+ this.dispatchEvent({type: 'voip_error', element: this, data: err});
}
- this.dispatchEvent({type: 'voip_data', element: this, data: newbuf});
-}
-JanusVOIPRecorder.prototype.handleFailure = function(err) {
- this.dispatchEvent({type: 'voip_error', element: this, data: err});
-}
-
-
-JanusVOIPPlayer = function(args) {
- if (!args) var args = {};
- this.context = args.context;
- this.sampleRate = args.sampleRate || 11000;
- this.bufferTime = args.bufferTime || 1.0;
- this.audioScale = args.audioScale || 32768;
-
- this.bufferLength = this.sampleRate * this.bufferTime;
-}
-EventDispatcher.prototype.apply(JanusVOIPPlayer.prototype);
-
-JanusVOIPPlayer.prototype.start = function() {
- this.rawbuffer = context.createBuffer(2, this.bufferLength, this.sampleRate);
- this.readoffset = 0;
- this.writeoffset = 0;
-
- this.dispatchEvent({type: 'voip_player_init', element: this});
-}
-JanusVOIPPlayer.prototype.speak = function(noise) {
- var binary_string = window.atob(noise);
- var len = binary_string.length;
-
- // Even though this is a mono source, we treat it as stereo so it can be used as poitional audio
- var bufferLeft = this.rawbuffer.getChannelData(0);
- var bufferRight = this.rawbuffer.getChannelData(1);
-
- // Decode the binary string into an unsigned char array
- var audiodata = new Uint8Array(len);
- for (var i = 0; i < len; i++) {
- audiodata[i] = binary_string.charCodeAt(i);
+
+
+ JanusVOIPPlayer = function(args) {
+ if (!args) var args = {};
+ this.sampleRate = args.sampleRate || 11000;
+ this.bufferTime = args.bufferTime || 1.0;
+ this.audioScale = args.audioScale || 32768;
+
+ this.bufferLength = this.sampleRate * this.bufferTime;
}
+ EventDispatcher.prototype.apply(JanusVOIPPlayer.prototype);
- // Create a new view into the decoded data which gives us the data as int16_t instead of unsigned chars
- var audiodata16 = new Int16Array(audiodata.buffer);
+ JanusVOIPPlayer.prototype.start = function(context) {
+ this.rawbuffer = context.createBuffer(2, this.bufferLength, this.sampleRate);
+ this.readoffset = 0;
+ this.writeoffset = 0;
- var startoffset = this.writeoffset;
- // Write the scaled data into our buffer, treating it as a looping ring buffer
- for (var i = 0; i < audiodata16.length; i++) {
- var idx = (startoffset + i) % this.bufferLength;
- bufferLeft[idx] = bufferRight[idx] = (audiodata16[i] / this.audioScale);
+ this.dispatchEvent({type: 'voip_player_init', element: this});
}
- this.writeoffset += audiodata16.length;
+ JanusVOIPPlayer.prototype.speak = function(noise) {
+ var binary_string = window.atob(noise);
+ var len = binary_string.length;
+
+ // Even though this is a mono source, we treat it as stereo so it can be used as poitional audio
+ var bufferLeft = this.rawbuffer.getChannelData(0);
+ var bufferRight = this.rawbuffer.getChannelData(1);
+
+ // Decode the binary string into an unsigned char array
+ var audiodata = new Uint8Array(len);
+ for (var i = 0; i < len; i++) {
+ audiodata[i] = binary_string.charCodeAt(i);
+ }
+
+ // Create a new view into the decoded data which gives us the data as int16_t instead of unsigned chars
+ var audiodata16 = new Int16Array(audiodata.buffer);
+
+ console.log('decoded', audiodata, audiodata16);
- this.dispatchEvent({type: 'voip_player_data', element: this, data: {buffer: bufferLeft, start: startoffset, end: this.writeoffset}});
- if (this.talktimer) {
- clearTimeout(this.talktimer);
+ var startoffset = this.writeoffset;
+ // Write the scaled data into our buffer, treating it as a looping ring buffer
+ for (var i = 0; i < audiodata16.length; i++) {
+ console.log(audiodata[i] / this.audioScale);
+ var idx = (startoffset + i) % this.bufferLength;
+ bufferLeft[idx] = bufferRight[idx] = (audiodata16[i] / this.audioScale);
+ }
+ this.writeoffset += audiodata16.length;
+
+ this.dispatchEvent({type: 'voip_player_data', element: this, data: {buffer: bufferLeft, start: startoffset, end: this.writeoffset}});
+ if (this.talktimer) {
+ clearTimeout(this.talktimer);
+ }
+ this.talktimer = setTimeout(elation.bind(this, this.stop), this.bufferLength * 500);
}
- this.talktimer = setTimeout(elation.bind(this, this.stop), this.bufferLength * 500);
-}
-JanusVOIPPlayer.prototype.stop = function() {
- this.dispatchEvent({type: 'voip_player_stop', element: this});
-}
-JanusVOIPPlayer.prototype.silence = function() {
- var bufferLeft = this.rawbuffer.getChannelData(0);
- var bufferRight = this.rawbuffer.getChannelData(1);
- for (var i = 0; i < bufferLeft.length; i++) {
- bufferLeft[i] = bufferRight[i] = 0;
+ JanusVOIPPlayer.prototype.stop = function() {
+ this.dispatchEvent({type: 'voip_player_stop', element: this});
+ }
+ JanusVOIPPlayer.prototype.silence = function() {
+ var bufferLeft = this.rawbuffer.getChannelData(0);
+ var bufferRight = this.rawbuffer.getChannelData(1);
+ for (var i = 0; i < bufferLeft.length; i++) {
+ bufferLeft[i] = bufferRight[i] = 0;
+ }
+ this.writeoffset = 0;
}
- this.writeoffset = 0;
-}
-//JavaScript Audio Resampler
-//Copyright (C) 2011-2015 Grant Galitz
-//Released to Public Domain
-function Resampler(fromSampleRate, toSampleRate, channels, inputBuffer) {
- //Input Sample Rate:
- this.fromSampleRate = +fromSampleRate;
- //Output Sample Rate:
- this.toSampleRate = +toSampleRate;
- //Number of channels:
- this.channels = channels | 0;
- //Type checking the input buffer:
- if (typeof inputBuffer != "object") {
- throw(new Error("inputBuffer is not an object."));
- }
- if (!(inputBuffer instanceof Array) && !(inputBuffer instanceof Float32Array) && !(inputBuffer instanceof Float64Array)) {
- throw(new Error("inputBuffer is not an array or a float32 or a float64 array."));
- }
- this.inputBuffer = inputBuffer;
- //Initialize the resampler:
- this.initialize();
-}
-Resampler.prototype.initialize = function () {
- //Perform some checks:
- if (this.fromSampleRate > 0 && this.toSampleRate > 0 && this.channels > 0) {
- if (this.fromSampleRate == this.toSampleRate) {
- //Setup a resampler bypass:
- this.resampler = this.bypassResampler; //Resampler just returns what was passed through.
- this.ratioWeight = 1;
- this.outputBuffer = this.inputBuffer;
- }
- else {
- this.ratioWeight = this.fromSampleRate / this.toSampleRate;
- if (this.fromSampleRate < this.toSampleRate) {
- /*
- Use generic linear interpolation if upsampling,
- as linear interpolation produces a gradient that we want
- and works fine with two input sample points per output in this case.
- */
- this.compileLinearInterpolationFunction();
- this.lastWeight = 1;
- }
- else {
- /*
- Custom resampler I wrote that doesn't skip samples
- like standard linear interpolation in high downsampling.
- This is more accurate than linear interpolation on downsampling.
- */
- this.compileMultiTapFunction();
- this.tailExists = false;
- this.lastWeight = 0;
- }
- this.initializeBuffers();
- }
- }
- else {
- throw(new Error("Invalid settings specified for the resampler."));
- }
-}
-Resampler.prototype.compileLinearInterpolationFunction = function () {
- var toCompile = "var outputOffset = 0;\
- if (bufferLength > 0) {\
- var buffer = this.inputBuffer;\
- var weight = this.lastWeight;\
- var firstWeight = 0;\
- var secondWeight = 0;\
- var sourceOffset = 0;\
- var outputOffset = 0;\
- var outputBuffer = this.outputBuffer;\
- for (; weight < 1; weight += " + this.ratioWeight + ") {\
- secondWeight = weight % 1;\
- firstWeight = 1 - secondWeight;";
- for (var channel = 0; channel < this.channels; ++channel) {
- toCompile += "outputBuffer[outputOffset++] = (this.lastOutput[" + channel + "] * firstWeight) + (buffer[" + channel + "] * secondWeight);";
- }
- toCompile += "}\
- weight -= 1;\
- for (bufferLength -= " + this.channels + ", sourceOffset = Math.floor(weight) * " + this.channels + "; sourceOffset < bufferLength;) {\
- secondWeight = weight % 1;\
- firstWeight = 1 - secondWeight;";
- for (var channel = 0; channel < this.channels; ++channel) {
- toCompile += "outputBuffer[outputOffset++] = (buffer[sourceOffset" + ((channel > 0) ? (" + " + channel) : "") + "] * firstWeight) + (buffer[sourceOffset + " + (this.channels + channel) + "] * secondWeight);";
- }
- toCompile += "weight += " + this.ratioWeight + ";\
- sourceOffset = Math.floor(weight) * " + this.channels + ";\
- }";
- for (var channel = 0; channel < this.channels; ++channel) {
- toCompile += "this.lastOutput[" + channel + "] = buffer[sourceOffset++];";
+ //JavaScript Audio Resampler
+ //Copyright (C) 2011-2015 Grant Galitz
+ //Released to Public Domain
+ function Resampler(fromSampleRate, toSampleRate, channels, inputBuffer) {
+ //Input Sample Rate:
+ this.fromSampleRate = +fromSampleRate;
+ //Output Sample Rate:
+ this.toSampleRate = +toSampleRate;
+ //Number of channels:
+ this.channels = channels | 0;
+ //Type checking the input buffer:
+ if (typeof inputBuffer != "object") {
+ throw(new Error("inputBuffer is not an object."));
+ }
+ if (!(inputBuffer instanceof Array) && !(inputBuffer instanceof Float32Array) && !(inputBuffer instanceof Float64Array)) {
+ throw(new Error("inputBuffer is not an array or a float32 or a float64 array."));
+ }
+ this.inputBuffer = inputBuffer;
+ //Initialize the resampler:
+ this.initialize();
+ }
+ Resampler.prototype.initialize = function () {
+ //Perform some checks:
+ if (this.fromSampleRate > 0 && this.toSampleRate > 0 && this.channels > 0) {
+ if (this.fromSampleRate == this.toSampleRate) {
+ //Setup a resampler bypass:
+ this.resampler = this.bypassResampler; //Resampler just returns what was passed through.
+ this.ratioWeight = 1;
+ this.outputBuffer = this.inputBuffer;
+ }
+ else {
+ this.ratioWeight = this.fromSampleRate / this.toSampleRate;
+ if (this.fromSampleRate < this.toSampleRate) {
+ /*
+ Use generic linear interpolation if upsampling,
+ as linear interpolation produces a gradient that we want
+ and works fine with two input sample points per output in this case.
+ */
+ this.compileLinearInterpolationFunction();
+ this.lastWeight = 1;
}
- toCompile += "this.lastWeight = weight % 1;\
- }\
- return outputOffset;";
- this.resampler = Function("bufferLength", toCompile);
-}
-Resampler.prototype.compileMultiTapFunction = function () {
- var toCompile = "var outputOffset = 0;\
- if (bufferLength > 0) {\
- var buffer = this.inputBuffer;\
- var weight = 0;";
- for (var channel = 0; channel < this.channels; ++channel) {
- toCompile += "var output" + channel + " = 0;"
+ else {
+ /*
+ Custom resampler I wrote that doesn't skip samples
+ like standard linear interpolation in high downsampling.
+ This is more accurate than linear interpolation on downsampling.
+ */
+ this.compileMultiTapFunction();
+ this.tailExists = false;
+ this.lastWeight = 0;
}
- toCompile += "var actualPosition = 0;\
- var amountToNext = 0;\
- var alreadyProcessedTail = !this.tailExists;\
- this.tailExists = false;\
- var outputBuffer = this.outputBuffer;\
- var currentPosition = 0;\
- do {\
- if (alreadyProcessedTail) {\
- weight = " + this.ratioWeight + ";";
- for (channel = 0; channel < this.channels; ++channel) {
- toCompile += "output" + channel + " = 0;"
- }
- toCompile += "}\
- else {\
- weight = this.lastWeight;";
- for (channel = 0; channel < this.channels; ++channel) {
- toCompile += "output" + channel + " = this.lastOutput[" + channel + "];"
- }
- toCompile += "alreadyProcessedTail = true;\
- }\
- while (weight > 0 && actualPosition < bufferLength) {\
- amountToNext = 1 + actualPosition - currentPosition;\
- if (weight >= amountToNext) {";
- for (channel = 0; channel < this.channels; ++channel) {
- toCompile += "output" + channel + " += buffer[actualPosition++] * amountToNext;"
- }
- toCompile += "currentPosition = actualPosition;\
- weight -= amountToNext;\
- }\
- else {";
- for (channel = 0; channel < this.channels; ++channel) {
- toCompile += "output" + channel + " += buffer[actualPosition" + ((channel > 0) ? (" + " + channel) : "") + "] * weight;"
- }
- toCompile += "currentPosition += weight;\
- weight = 0;\
- break;\
- }\
- }\
- if (weight <= 0) {";
- for (channel = 0; channel < this.channels; ++channel) {
- toCompile += "outputBuffer[outputOffset++] = output" + channel + " / " + this.ratioWeight + ";"
- }
- toCompile += "}\
- else {\
- this.lastWeight = weight;";
- for (channel = 0; channel < this.channels; ++channel) {
- toCompile += "this.lastOutput[" + channel + "] = output" + channel + ";"
- }
- toCompile += "this.tailExists = true;\
- break;\
- }\
- } while (actualPosition < bufferLength);\
- }\
- return outputOffset;";
- this.resampler = Function("bufferLength", toCompile);
-}
-Resampler.prototype.bypassResampler = function (upTo) {
- return upTo;
-}
-Resampler.prototype.initializeBuffers = function () {
- //Initialize the internal buffer:
- var outputBufferSize = (Math.ceil(this.inputBuffer.length * this.toSampleRate / this.fromSampleRate / this.channels * 1.000000476837158203125) * this.channels) + this.channels;
- try {
- this.outputBuffer = new Float32Array(outputBufferSize);
- this.lastOutput = new Float32Array(this.channels);
- }
- catch (error) {
- this.outputBuffer = [];
- this.lastOutput = [];
- }
-}
+ this.initializeBuffers();
+ }
+ }
+ else {
+ throw(new Error("Invalid settings specified for the resampler."));
+ }
+ }
+ Resampler.prototype.compileLinearInterpolationFunction = function () {
+ var toCompile = "var outputOffset = 0;\
+ if (bufferLength > 0) {\
+ var buffer = this.inputBuffer;\
+ var weight = this.lastWeight;\
+ var firstWeight = 0;\
+ var secondWeight = 0;\
+ var sourceOffset = 0;\
+ var outputOffset = 0;\
+ var outputBuffer = this.outputBuffer;\
+ for (; weight < 1; weight += " + this.ratioWeight + ") {\
+ secondWeight = weight % 1;\
+ firstWeight = 1 - secondWeight;";
+ for (var channel = 0; channel < this.channels; ++channel) {
+ toCompile += "outputBuffer[outputOffset++] = (this.lastOutput[" + channel + "] * firstWeight) + (buffer[" + channel + "] * secondWeight);";
+ }
+ toCompile += "}\
+ weight -= 1;\
+ for (bufferLength -= " + this.channels + ", sourceOffset = Math.floor(weight) * " + this.channels + "; sourceOffset < bufferLength;) {\
+ secondWeight = weight % 1;\
+ firstWeight = 1 - secondWeight;";
+ for (var channel = 0; channel < this.channels; ++channel) {
+ toCompile += "outputBuffer[outputOffset++] = (buffer[sourceOffset" + ((channel > 0) ? (" + " + channel) : "") + "] * firstWeight) + (buffer[sourceOffset + " + (this.channels + channel) + "] * secondWeight);";
+ }
+ toCompile += "weight += " + this.ratioWeight + ";\
+ sourceOffset = Math.floor(weight) * " + this.channels + ";\
+ }";
+ for (var channel = 0; channel < this.channels; ++channel) {
+ toCompile += "this.lastOutput[" + channel + "] = buffer[sourceOffset++];";
+ }
+ toCompile += "this.lastWeight = weight % 1;\
+ }\
+ return outputOffset;";
+ this.resampler = Function("bufferLength", toCompile);
+ }
+ Resampler.prototype.compileMultiTapFunction = function () {
+ var toCompile = "var outputOffset = 0;\
+ if (bufferLength > 0) {\
+ var buffer = this.inputBuffer;\
+ var weight = 0;";
+ for (var channel = 0; channel < this.channels; ++channel) {
+ toCompile += "var output" + channel + " = 0;"
+ }
+ toCompile += "var actualPosition = 0;\
+ var amountToNext = 0;\
+ var alreadyProcessedTail = !this.tailExists;\
+ this.tailExists = false;\
+ var outputBuffer = this.outputBuffer;\
+ var currentPosition = 0;\
+ do {\
+ if (alreadyProcessedTail) {\
+ weight = " + this.ratioWeight + ";";
+ for (channel = 0; channel < this.channels; ++channel) {
+ toCompile += "output" + channel + " = 0;"
+ }
+ toCompile += "}\
+ else {\
+ weight = this.lastWeight;";
+ for (channel = 0; channel < this.channels; ++channel) {
+ toCompile += "output" + channel + " = this.lastOutput[" + channel + "];"
+ }
+ toCompile += "alreadyProcessedTail = true;\
+ }\
+ while (weight > 0 && actualPosition < bufferLength) {\
+ amountToNext = 1 + actualPosition - currentPosition;\
+ if (weight >= amountToNext) {";
+ for (channel = 0; channel < this.channels; ++channel) {
+ toCompile += "output" + channel + " += buffer[actualPosition++] * amountToNext;"
+ }
+ toCompile += "currentPosition = actualPosition;\
+ weight -= amountToNext;\
+ }\
+ else {";
+ for (channel = 0; channel < this.channels; ++channel) {
+ toCompile += "output" + channel + " += buffer[actualPosition" + ((channel > 0) ? (" + " + channel) : "") + "] * weight;"
+ }
+ toCompile += "currentPosition += weight;\
+ weight = 0;\
+ break;\
+ }\
+ }\
+ if (weight <= 0) {";
+ for (channel = 0; channel < this.channels; ++channel) {
+ toCompile += "outputBuffer[outputOffset++] = output" + channel + " / " + this.ratioWeight + ";"
+ }
+ toCompile += "}\
+ else {\
+ this.lastWeight = weight;";
+ for (channel = 0; channel < this.channels; ++channel) {
+ toCompile += "this.lastOutput[" + channel + "] = output" + channel + ";"
+ }
+ toCompile += "this.tailExists = true;\
+ break;\
+ }\
+ } while (actualPosition < bufferLength);\
+ }\
+ return outputOffset;";
+ this.resampler = Function("bufferLength", toCompile);
+ }
+ Resampler.prototype.bypassResampler = function (upTo) {
+ return upTo;
+ }
+ Resampler.prototype.initializeBuffers = function () {
+ //Initialize the internal buffer:
+ var outputBufferSize = (Math.ceil(this.inputBuffer.length * this.toSampleRate / this.fromSampleRate / this.channels * 1.000000476837158203125) * this.channels) + this.channels;
+ try {
+ this.outputBuffer = new Float32Array(outputBufferSize);
+ this.lastOutput = new Float32Array(this.channels);
+ }
+ catch (error) {
+ this.outputBuffer = [];
+ this.lastOutput = [];
+ }
+ }
+})();
-----END OF PAGE-----