diff --git a/src/soundjs/AbstractSoundInstance.js b/src/soundjs/AbstractSoundInstance.js
index b38311d2..b402b2e2 100644
--- a/src/soundjs/AbstractSoundInstance.js
+++ b/src/soundjs/AbstractSoundInstance.js
@@ -152,6 +152,85 @@ this.createjs = this.createjs || {};
set: this.setPan
});
+ /**
+ * The filter frequency of the sound, between 0 and half the sample rate. Note that filter is not supported by HTML Audio.
+ *
+ * @property filterFrequency
+ * @type {Number}
+ * @default 22050
+ */
+ this._filterFrequency = 22050;
+ Object.defineProperty(this, "filterFrequency", {
+ get: this.getFilterFrequency,
+ set: this.setFilterFrequency
+ });
+
+ /**
+ * The filter quality factor of the sound, between 0.0001 and 1000. Note that filter is not supported by HTML Audio.
+ *
+ * @property filterFrequency
+ * @type {Number}
+ * @default 1
+ */
+ this._filterQ = 1;
+ Object.defineProperty(this, "filterQ", {
+ get: this.getFilterQ,
+ set: this.setFilterQ
+ });
+
+ /**
+ * The filter type, one of the following: "lowpass" "highpass" bandpass". Note that filter is not supported by HTML Audio.
+ *
+ * @property filterType
+ * @type {String}
+ * @default "lowpass"
+ */
+ this._filterType = "lowpass";
+ Object.defineProperty(this, "filterType", {
+ get: this.getFilterType,
+ set: this.setFilterType
+ });
+
+ /**
+ * The filter detune value in cents. Note that filter is not supported by HTML Audio.
+ *
+ * @property filterDetune
+ * @type {Number}
+ * @default 0
+ */
+ this._filterDetune = 0;
+ Object.defineProperty(this, "filterDetune", {
+ get: this.getFilterDetune,
+ set: this.setFilterDetune
+ });
+
+ /**
+ * The distortion value in amount. Note that distortion is not supported by HTML Audio.
+ *
+ * @property distortionAmount
+ * @type {Number}
+ * @default 0
+ */
+ this._distortionAmount = 0;
+ Object.defineProperty(this, "distortionAmount", {
+ get: this.getDistortionAmount,
+ set: this.setDistortionAmount
+ });
+
+ /**
+ * The convolver buffer to use on the convolver node. This can be an audioBuffer or a filepath, and will be handled appropriately depending on which.
+ * Note that convolver is not supported by HTML Audio.
+ *
+ * @property convolverBuffer
+ * @type {String} || {AudioBuffer}
+ * @default null
+ */
+ this._convolverBuffer = null;
+ Object.defineProperty(this, "convolverBuffer", {
+ get: this.getConvolverBuffer,
+ set: this.setConvolverBuffer
+ });
+
/**
* Audio sprite property used to determine the starting offset.
* @property startTime
@@ -529,6 +608,185 @@ this.createjs = this.createjs || {};
return this._pan;
};
+ /**
+ * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/filterFrequency:property"}}{{/crossLink}} directly as a property
+ *
+ * @deprecated
+ * @method setFilterFrequency
+ * @param {Number} value The filter frequency value, between 0 and half the sample rate.
+ * @return {AbstractSoundInstance} Returns reference to itself for chaining calls
+ */
+ p.setFilterFrequency = function (value) {
+ if(value == this._filterFrequency) { return this; }
+ this._filterFrequency = value;
+ this._updateFilter();
+ return this;
+ };
+
+ /**
+ * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/filterFrequency:property"}}{{/crossLink}} directly as a property
+ *
+ * @deprecated
+ * @method getFilterFrequency
+ * @return {Number} The value of the filter frequency, between 0 and half the sample rate.
+ */
+ p.getFilterFrequency = function () {
+ return this._filterFrequency;
+ };
+
+ /**
+ * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/filterQ:property"}}{{/crossLink}} directly as a property
+ *
+ * @deprecated
+ * @method setFilterQ
+ * @param {Number} value The filter quality factor, between 0.0001 and 1000.
+ * @return {AbstractSoundInstance} Returns reference to itself for chaining calls
+ */
+ p.setFilterQ = function (value) {
+ if(value == this._filterQ) { return this; }
+ this._filterQ = value;
+ this._updateFilter();
+ return this;
+ };
+
+ /**
+ * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/filterQ:property"}}{{/crossLink}} directly as a property
+ *
+ * @deprecated
+ * @method getFilterQ
+ * @return {Number} The value of the filter frequency, between 0.0001 and 1000.
+ */
+ p.getFilterQ = function () {
+ return this._filterQ;
+ };
+
+ /**
+ * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/filterType:property"}}{{/crossLink}} directly as a property
+ *
+ * @deprecated
+ * @method setFilterType
+ * @param {String} The filter type, one of the following: "lowpass" "highpass" bandpass".
+ * @return {AbstractSoundInstance} Returns reference to itself for chaining calls
+ */
+ p.setFilterType = function (value) {
+ if(value == this._filterType) { return this; }
+
+ var acceptedTypes = {
+ "lowpass" : true,
+ "highpass" : true,
+ "bandpass" : true
+ };
+
+ if (typeof acceptedTypes[value] === 'undefined') { return false; }
+
+ this._filterType = value;
+ this._updateFilter();
+ return this;
+ };
+
+ /**
+ * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/filterType:property"}}{{/crossLink}} directly as a property
+ *
+ * @deprecated
+ * @method getFilterType
+ * @return {String} The filter type, one of the following: "lowpass" "highpass" bandpass".
+ */
+ p.getFilterType = function () {
+ return this._filterType;
+ };
+
+ /**
+ * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/filterDetune:property"}}{{/crossLink}} directly as a property
+ *
+ * @deprecated
+ * @method setFilterDetune
+ * @param {Number} The filter detune value in cents.
+ * @return {AbstractSoundInstance} Returns reference to itself for chaining calls
+ */
+ p.setFilterDetune = function (value) {
+ if(value == this._filterDetune) { return this; }
+
+ this._filterDetune= value;
+ this._updateFilter();
+ return this;
+ };
+
+ /**
+ * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/filterDetune:property"}}{{/crossLink}} directly as a property
+ *
+ * @deprecated
+ * @method getFilterDetune
+ * @return {Number} The filter detune value in cents.
+ */
+ p.getFilterDetune = function () {
+ return this._filterDetune;
+ };
+
+ /**
+ * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/distortionAmount:property"}}{{/crossLink}} directly as a property
+ *
+ * @deprecated
+ * @method setDistortionAmount
+ * @param {Number} The distortion value in amount.
+ * @return {AbstractSoundInstance} Returns reference to itself for chaining calls
+ */
+ p.setDistortionAmount = function (value) {
+ if(value == this._distortionAmount) { return this; }
+
+ this._distortionAmount = value;
+ this._updateDistortion();
+ return this;
+ };
+
+ /**
+ * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/distortionAmount:property"}}{{/crossLink}} directly as a property
+ *
+ * @deprecated
+ * @method getDistortionAmount
+ * @return {Number} The distortion value in amount.
+ */
+ p.getDistortionAmount = function () {
+ return this._distortionAmount;
+ };
+
+ /**
+ * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/convolverBuffer:property"}}{{/crossLink}} directly as a property
+ *
+ * @deprecated
+ * @method setConvolverBuffer
+ * @param {String} The filepath to an impulse response WAV || {AudioBuffer} The audio buffer to use as the convoler's buffer.
+ * @return {AbstractSoundInstance} Returns reference to itself for chaining calls
+ */
+ p.setConvolverBuffer = function (buffer) {
+ if (typeof buffer === 'string') {
+ //if a filepath is passed, must import it as an arraybuffer and decode
+ this._getConvolverBufferFromFilepath(buffer);
+ }
+ else {
+ if (typeof AudioBuffer !== 'undefined' && buffer instanceof AudioBuffer) {
+ //audio buffer is passed, set it directly
+ this._convolverBuffer = buffer;
+ this._updateConvolver();
+ }
+ else {
+ return false;
+ }
+ }
+ return this;
+ };
+
+ /**
+ * DEPRECATED, please use {{#crossLink "AbstractSoundInstance/convolverBuffer:property"}}{{/crossLink}} directly as a property
+ *
+ * @deprecated
+ * @method getConvolverBuffer
+ * @return {AudioBuffer} The audio buffer being used as the convolver's buffer.
+ */
+ p.getConvolverBuffer = function () {
+ return this._convolverBuffer;
+ };
+
+
/**
* DEPRECATED, please use {{#crossLink "AbstractSoundInstance/position:property"}}{{/crossLink}} directly as a property
*
diff --git a/src/soundjs/webaudio/WebAudioSoundInstance.js b/src/soundjs/webaudio/WebAudioSoundInstance.js
index 888564b2..042e6657 100644
--- a/src/soundjs/webaudio/WebAudioSoundInstance.js
+++ b/src/soundjs/webaudio/WebAudioSoundInstance.js
@@ -78,6 +78,37 @@ this.createjs = this.createjs || {};
this.panNode.connect(this.gainNode);
this._updatePan();
+ /**
+ * NOTE this is only intended for use by advanced users.
+ *
A ConvolverNode allowing application of convolver buffers (e.g. reverb) Connected to WebAudioSoundInstance {{#crossLink "WebAudioSoundInstance/panNode:property"}}{{/crossLink}}.
+ * @property convolverNode
+ * @type { ConvolverNode}
+ * @since 0.6.?
+ */
+ this.convolverNode = s.context.createConvolver();
+ this.convolverNode.buffer = this.testBuffer;
+ this.convolverNode.connect(this.panNode); //convolver node => pan node => gain node
+
+ /**
+ * NOTE this is only intended for use by advanced users.
+ *
A filterNode allowing frequency filtering. Connected to WebAudioSoundInstance {{#crossLink "WebAudioSoundInstance/convolverNode:property"}}{{/crossLink}}.
+ * @property filterNode
+ * @type {BiquadFilterNode}
+ * @since 0.6.?
+ */
+ this.filterNode = s.context.createBiquadFilter();
+ this.filterNode.connect(this.convolverNode); //filter node => convolver node => pan node => gain node
+
+ /**
+ * NOTE this is only intended for use by advanced users.
+ *
A waveShaperNode allowing application of disortion curves. Connected to WebAudioSoundInstance {{#crossLink "WebAudioSoundInstance/filterNode:property"}}{{/crossLink}}.
+ * @property distortionNode
+ * @type {WaveShaperNode}
+ * @since 0.6.?
+ */
+ this.distortionNode = s.context.createWaveShaper();
+ this.distortionNode.connect(this.filterNode); //distortion node => filter node => convolver node => pan node => gain node
+
/**
* NOTE this is only intended for use by advanced users.
*
sourceNode is the audio source. Connected to WebAudioSoundInstance {{#crossLink "WebAudioSoundInstance/panNode:property"}}{{/crossLink}}.
@@ -196,6 +227,55 @@ this.createjs = this.createjs || {};
// z need to be -0.5 otherwise the sound only plays in left, right, or center
};
+ p._updateFilter = function() {
+ this.filterNode.frequency.value = this._filterFrequency;
+ this.filterNode.Q.value = this._filterQ;
+ this.filterNode.type = this._filterType;
+ this.filterNode.detune.value = this._filterDetune;
+ };
+
+ // distortion curve for the waveshaper, thanks to Kevin Ennis
+ // http://stackoverflow.com/questions/22312841/waveshaper-node-in-webaudio-how-to-emulate-distortion
+ p._makeDistortionCurve = function(amount) {
+ var k = typeof amount === 'number' ? amount : 50;
+ var n_samples = 44100;
+ var curve = new Float32Array(n_samples);
+ var deg = Math.PI / 180;
+ var i = 0;
+ var x;
+ for ( ; i < n_samples; ++i ) {
+ x = i * 2 / n_samples - 1;
+ curve[i] = ( 3 + k ) * x * 20 * deg / ( Math.PI + k * Math.abs(x) );
+ }
+ return curve;
+ };
+
+ p._updateDistortion = function() {
+ this.distortionNode.oversample = '4x'; //pull this out into a config. Can be 'none', '2x' or '4x'
+ this.distortionNode.curve = this._makeDistortionCurve(this._distortionAmount);
+ };
+
+ p._updateConvolver = function() {
+ this.convolverNode.buffer = this._convolverBuffer;
+ };
+
+ p._getConvolverBufferFromFilepath = function(filepath) {
+ // grab audio track via XHR for convolver node
+ var req = new XMLHttpRequest();
+ req.open('GET', filepath, true);
+ req.responseType = 'arraybuffer';
+
+ var self = this; //save this reference
+ req.onload = function() {
+ var audioData = req.response;
+ s.context.decodeAudioData(audioData, function(buffer) {
+ self._convolverBuffer = buffer;
+ self._updateConvolver();
+ }, function(e){"Error with decoding audio data" + e.err});
+ }
+ req.send();
+ };
+
p._removeLooping = function(value) {
this._sourceNodeNext = this._cleanUpAudioNode(this._sourceNodeNext);
};
@@ -269,9 +349,13 @@ this.createjs = this.createjs || {};
* @since 0.4.1
*/
p._createAndPlayAudioNode = function(startTime, offset) {
+ console.log('createandplayaudionode');
var audioNode = s.context.createBufferSource();
audioNode.buffer = this.playbackResource;
- audioNode.connect(this.panNode);
+ audioNode.connect(this.distortionNode);
+ //audioNode.connect(this.convolverNode);
+ console.log('connected to convolverNode');
+
var dur = this._duration * 0.001;
audioNode.startTime = startTime + dur;
audioNode.start(audioNode.startTime, offset+(this._startTime*0.001), dur - offset);