Skip to content

Instantly share code, notes, and snippets.

@softpunch
Last active July 7, 2017 01:58
Show Gist options
  • Save softpunch/e008b13b9a8a278666dc6b6efc363b20 to your computer and use it in GitHub Desktop.
Save softpunch/e008b13b9a8a278666dc6b6efc363b20 to your computer and use it in GitHub Desktop.
Ramps/Oscillators
// snippets from @mohayonao's pure js implementation of web audio api
// https://github.com/mohayonao/web-audio-engine/
// https://github.com/mohayonao/web-audio-engine/blob/master/build/web-audio-engine.js
// basic constructors
// audio scheduled source node
},{"../impl":126,"../utils":135}],31:[function(require,module,exports){
"use strict";
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var impl = require("../impl");
var AudioScheduledSourceNode = require("./AudioScheduledSourceNode");
var AudioParam = require("./AudioParam");
var AudioBufferSourceNode = function (_AudioScheduledSource) {
_inherits(AudioBufferSourceNode, _AudioScheduledSource);
function AudioBufferSourceNode(context, opts) {
_classCallCheck(this, AudioBufferSourceNode);
var _this = _possibleConstructorReturn(this, (AudioBufferSourceNode.__proto__ || Object.getPrototypeOf(AudioBufferSourceNode)).call(this, context));
_this._impl = new impl.AudioBufferSourceNode(context._impl, opts);
_this._impl.$playbackRate = new AudioParam(context, _this._impl.getPlaybackRate());
_this._impl.$detune = new AudioParam(context, _this._impl.getDetune());
_this._impl.$buffer = null;
_this._impl.$onended = null;
if (opts && opts.buffer) {
_this.buffer = opts.buffer;
}
return _this;
}
_createClass(AudioBufferSourceNode, [{
key: "start",
value: function start(when, offset, duration) {
this._impl.start(when, offset, duration);
}
}, {
key: "buffer",
get: function get() {
return this._impl.$buffer;
},
set: function set(value) {
this._impl.$buffer = value;
this._impl.setBuffer(value);
}
}, {
key: "playbackRate",
get: function get() {
return this._impl.$playbackRate;
}
}, {
key: "detune",
get: function get() {
return this._impl.$detune;
}
}, {
key: "loop",
get: function get() {
return this._impl.getLoop();
},
set: function set(value) {
this._impl.setLoop(value);
}
}, {
key: "loopStart",
get: function get() {
return this._impl.getLoopStart();
},
set: function set(value) {
this._impl.setLoopStart(value);
}
}, {
key: "loopEnd",
get: function get() {
return this._impl.getLoopEnd();
},
set: function set(value) {
this._impl.setLoopEnd(value);
}
}]);
return AudioBufferSourceNode;
}(AudioScheduledSourceNode);
module.exports = AudioBufferSourceNode;
},{"../impl":126,"./AudioParam":35,"./AudioScheduledSourceNode":36}],32:[function(require,module,exports){
"use strict";
//
//
//
//
// AudioParam
},{"../utils":135,"./EventTarget":45}],35:[function(require,module,exports){
"use strict";
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var _require = require("../utils"),
defineProp = _require.defineProp;
var AudioParam = function () {
function AudioParam(context, impl) {
_classCallCheck(this, AudioParam);
defineProp(this, "_context", context);
defineProp(this, "_impl", impl);
}
_createClass(AudioParam, [{
key: "setValueAtTime",
value: function setValueAtTime(value, startTime) {
this._impl.setValueAtTime(value, startTime);
return this;
}
}, {
key: "linearRampToValueAtTime",
value: function linearRampToValueAtTime(value, endTime) {
this._impl.linearRampToValueAtTime(value, endTime);
return this;
}
}, {
key: "exponentialRampToValueAtTime",
value: function exponentialRampToValueAtTime(value, endTime) {
this._impl.exponentialRampToValueAtTime(value, endTime);
return this;
}
}, {
key: "setTargetAtTime",
value: function setTargetAtTime(target, startTime, timeConstant) {
this._impl.setTargetAtTime(target, startTime, timeConstant);
return this;
}
}, {
key: "setValueCurveAtTime",
value: function setValueCurveAtTime(values, startTime, duration) {
this._impl.setValueCurveAtTime(values, startTime, duration);
return this;
}
}, {
key: "cancelScheduledValues",
value: function cancelScheduledValues(startTime) {
this._impl.cancelScheduledValues(startTime);
return this;
}
}, {
key: "value",
get: function get() {
return this._impl.getValue();
},
set: function set(value) {
this._impl.setValue(value);
}
}, {
key: "defaultValue",
get: function get() {
return this._impl.getDefaultValue();
}
}]);
return AudioParam;
}();
module.exports = AudioParam;
//
//
//
//
// oscillator
},{"../impl":126,"./AudioNode":34}],48:[function(require,module,exports){
"use strict";
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var impl = require("../impl");
var AudioScheduledSourceNode = require("./AudioScheduledSourceNode");
var AudioParam = require("./AudioParam");
var OscillatorNode = function (_AudioScheduledSource) {
_inherits(OscillatorNode, _AudioScheduledSource);
function OscillatorNode(context, opts) {
_classCallCheck(this, OscillatorNode);
var _this = _possibleConstructorReturn(this, (OscillatorNode.__proto__ || Object.getPrototypeOf(OscillatorNode)).call(this, context));
_this._impl = new impl.OscillatorNode(context._impl, opts);
_this._impl.$frequency = new AudioParam(context, _this._impl.getFrequency());
_this._impl.$detune = new AudioParam(context, _this._impl.getDetune());
_this._impl.$onended = null;
if (opts && opts.periodicWave) {
_this.setPeriodicWave(opts.periodicWave);
}
return _this;
}
_createClass(OscillatorNode, [{
key: "setPeriodicWave",
value: function setPeriodicWave(periodicWave) {
this._impl.setPeriodicWave(periodicWave);
}
}, {
key: "type",
get: function get() {
return this._impl.getType();
},
set: function set(value) {
this._impl.setType(value);
}
}, {
key: "frequency",
get: function get() {
return this._impl.$frequency;
}
}, {
key: "detune",
get: function get() {
return this._impl.$detune;
}
}]);
return OscillatorNode;
}(AudioScheduledSourceNode);
module.exports = OscillatorNode;
//
//
//
//
// basic context parameters
module.exports = {
MIN_SAMPLERATE: 3000,
MAX_SAMPLERATE: 192000,
MIN_NUMBER_OF_CHANNELS: 1,
MAX_NUMBER_OF_CHANNELS: 32,
MIN_BLOCK_SIZE: 8,
MAX_BLOCK_SIZE: 1024
};
//
//
//
//
// AudioParam Details
},{"../constants":66,"../constants/ChannelCountMode":62,"../constants/ChannelInterpretation":63,"../utils":135,"./AudioParam":80,"./EventTarget":91,"./core/AudioNodeInput":103,"./core/AudioNodeOutput":104}],80:[function(require,module,exports){
"use strict";
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var AudioNodeInput = require("./core/AudioNodeInput");
var AudioBus = require("./core/AudioBus");
var AudioParamDSP = require("./dsp/AudioParam");
var _require = require("../utils"),
defaults = _require.defaults;
var _require2 = require("../utils"),
toNumber = _require2.toNumber;
var _require3 = require("../constants/ChannelCountMode"),
EXPLICIT = _require3.EXPLICIT;
var _require4 = require("../constants/AudioParamRate"),
CONTROL_RATE = _require4.CONTROL_RATE;
var _require5 = require("../constants/AudioParamEvent"),
SET_VALUE_AT_TIME = _require5.SET_VALUE_AT_TIME;
var _require6 = require("../constants/AudioParamEvent"),
LINEAR_RAMP_TO_VALUE_AT_TIME = _require6.LINEAR_RAMP_TO_VALUE_AT_TIME;
var _require7 = require("../constants/AudioParamEvent"),
EXPONENTIAL_RAMP_TO_VALUE_AT_TIME = _require7.EXPONENTIAL_RAMP_TO_VALUE_AT_TIME;
var _require8 = require("../constants/AudioParamEvent"),
SET_TARGET_AT_TIME = _require8.SET_TARGET_AT_TIME;
var _require9 = require("../constants/AudioParamEvent"),
SET_VALUE_CURVE_AT_TIME = _require9.SET_VALUE_CURVE_AT_TIME;
/**
* @prop {AudioContext} context
* @prop {number} blockSize
* @prop {number} sampleRate
* @prop {AudioNodeInput[]} inputs
* @prop {AudioBus} outputBus
*/
var AudioParam = function () {
/**
* @param {AudioContext} context
* @param {string} opts.rate - [ AUDIO_RATE, CONTROL_RATE ]
* @param {number} opts.defaultValue
*/
function AudioParam(context) {
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
_classCallCheck(this, AudioParam);
var rate = defaults(opts.rate, CONTROL_RATE);
var defaultValue = defaults(opts.defaultValue, 0);
this.context = context;
this.blockSize = context.blockSize;
this.sampleRate = context.sampleRate;
this.inputs = [new AudioNodeInput({
node: this,
index: 0,
numberOfChannels: 1,
channelCount: 1,
channelCountMode: EXPLICIT
})];
this.outputBus = new AudioBus(1, this.blockSize, this.sampleRate);
this._rate = rate;
this._defaultValue = toNumber(defaultValue);
this._value = this._defaultValue;
this._userValue = this._value;
this._timeline = [];
this.dspInit(this._rate);
}
/**
* @return {number}
*/
_createClass(AudioParam, [{
key: "getValue",
value: function getValue() {
return this._value;
}
/**
* @param {number} value
*/
}, {
key: "setValue",
value: function setValue(value) {
this._value = this._userValue = toNumber(value);
}
/**
* @return {number}
*/
}, {
key: "getDefaultValue",
value: function getDefaultValue() {
return this._defaultValue;
}
/**
* @param {number} value
* @param {number} startTime
*/
}, {
key: "setValueAtTime",
value: function setValueAtTime(value, startTime) {
value = toNumber(value);
startTime = Math.max(0, toNumber(startTime));
var eventItem = {
type: SET_VALUE_AT_TIME,
time: startTime,
args: [value, startTime],
startFrame: Math.round(startTime * this.sampleRate),
endFrame: Infinity,
startValue: value,
endValue: value
};
var index = this.insertEvent(eventItem);
var prevEventItem = this._timeline[index - 1];
var nextEventItem = this._timeline[index + 1];
if (prevEventItem) {
switch (prevEventItem.type) {
case SET_VALUE_AT_TIME:
case SET_TARGET_AT_TIME:
prevEventItem.endFrame = eventItem.startFrame;
break;
}
}
if (nextEventItem) {
switch (nextEventItem.type) {
case LINEAR_RAMP_TO_VALUE_AT_TIME:
case EXPONENTIAL_RAMP_TO_VALUE_AT_TIME:
nextEventItem.startFrame = eventItem.startFrame;
nextEventItem.startValue = eventItem.startValue;
break;
}
eventItem.endFrame = nextEventItem.startFrame;
}
if (index <= this._currentEventIndex) {
this._currentEventIndex = index;
this._remainSamples = 0;
}
}
/**
* @param {number} value
* @param {number} endTime
*/
}, {
key: "linearRampToValueAtTime",
value: function linearRampToValueAtTime(value, endTime) {
value = toNumber(value);
endTime = Math.max(0, toNumber(endTime));
var eventItem = {
type: LINEAR_RAMP_TO_VALUE_AT_TIME,
time: endTime,
args: [value, endTime],
startFrame: 0,
endFrame: Math.round(endTime * this.sampleRate),
startValue: this._defaultValue,
endValue: value
};
var index = this.insertEvent(eventItem);
var prevEventItem = this._timeline[index - 1];
var nextEventItem = this._timeline[index + 1];
if (prevEventItem) {
switch (prevEventItem.type) {
case SET_VALUE_AT_TIME:
case SET_TARGET_AT_TIME:
eventItem.startFrame = prevEventItem.startFrame;
eventItem.startValue = prevEventItem.startValue;
prevEventItem.endFrame = eventItem.startFrame;
break;
case LINEAR_RAMP_TO_VALUE_AT_TIME:
case EXPONENTIAL_RAMP_TO_VALUE_AT_TIME:
case SET_VALUE_CURVE_AT_TIME:
eventItem.startFrame = prevEventItem.endFrame;
eventItem.startValue = prevEventItem.endValue;
break;
}
}
if (nextEventItem) {
switch (nextEventItem.type) {
case LINEAR_RAMP_TO_VALUE_AT_TIME:
case EXPONENTIAL_RAMP_TO_VALUE_AT_TIME:
nextEventItem.startFrame = eventItem.endFrame;
nextEventItem.startValue = eventItem.endValue;
break;
}
}
if (index <= this._currentEventIndex) {
this._currentEventIndex = index;
this._remainSamples = 0;
}
}
/**
* @param {number} value
* @param {number} endTime
*/
}, {
key: "exponentialRampToValueAtTime",
value: function exponentialRampToValueAtTime(value, endTime) {
value = Math.max(1e-6, toNumber(value));
endTime = Math.max(0, toNumber(endTime));
var eventItem = {
type: EXPONENTIAL_RAMP_TO_VALUE_AT_TIME,
time: endTime,
args: [value, endTime],
startFrame: 0,
endFrame: Math.round(endTime * this.sampleRate),
startValue: Math.max(1e-6, this._defaultValue),
endValue: value
};
var index = this.insertEvent(eventItem);
var prevEventItem = this._timeline[index - 1];
var nextEventItem = this._timeline[index + 1];
if (prevEventItem) {
switch (prevEventItem.type) {
case SET_VALUE_AT_TIME:
case SET_TARGET_AT_TIME:
eventItem.startFrame = prevEventItem.startFrame;
eventItem.startValue = prevEventItem.startValue;
prevEventItem.endFrame = eventItem.startFrame;
break;
case LINEAR_RAMP_TO_VALUE_AT_TIME:
case EXPONENTIAL_RAMP_TO_VALUE_AT_TIME:
case SET_VALUE_CURVE_AT_TIME:
eventItem.startFrame = prevEventItem.endFrame;
eventItem.startValue = prevEventItem.endValue;
break;
}
}
if (nextEventItem) {
switch (nextEventItem.type) {
case LINEAR_RAMP_TO_VALUE_AT_TIME:
case EXPONENTIAL_RAMP_TO_VALUE_AT_TIME:
nextEventItem.startFrame = eventItem.endFrame;
nextEventItem.startValue = eventItem.endValue;
break;
}
}
if (index <= this._currentEventIndex) {
this._currentEventIndex = index;
this._remainSamples = 0;
}
}
/**
* @param {number} target
* @param {number} startTime
* @param {number} timeConstant
*/
}, {
key: "setTargetAtTime",
value: function setTargetAtTime(target, startTime, timeConstant) {
target = toNumber(target);
startTime = Math.max(0, toNumber(startTime));
timeConstant = Math.max(0, toNumber(timeConstant));
var eventItem = {
type: SET_TARGET_AT_TIME,
time: startTime,
args: [target, startTime, timeConstant],
startFrame: Math.round(startTime * this.sampleRate),
endFrame: Infinity,
startValue: 0,
endValue: target
};
var index = this.insertEvent(eventItem);
var prevEventItem = this._timeline[index - 1];
var nextEventItem = this._timeline[index + 1];
if (prevEventItem) {
switch (prevEventItem.type) {
case SET_VALUE_AT_TIME:
eventItem.startValue = prevEventItem.endValue;
prevEventItem.endFrame = eventItem.startFrame;
break;
case SET_TARGET_AT_TIME:
eventItem.startValue = 0;
prevEventItem.endFrame = eventItem.startFrame;
break;
case LINEAR_RAMP_TO_VALUE_AT_TIME:
case EXPONENTIAL_RAMP_TO_VALUE_AT_TIME:
case SET_VALUE_CURVE_AT_TIME:
eventItem.startValue = prevEventItem.endValue;
break;
}
}
if (nextEventItem) {
switch (nextEventItem.type) {
case LINEAR_RAMP_TO_VALUE_AT_TIME:
case EXPONENTIAL_RAMP_TO_VALUE_AT_TIME:
nextEventItem.startFrame = eventItem.startFrame;
nextEventItem.startValue = eventItem.startValue;
break;
}
eventItem.endFrame = nextEventItem.startFrame;
}
if (index <= this._currentEventIndex) {
this._currentEventIndex = index;
this._remainSamples = 0;
}
}
/**
* @param {Float32Array[]} values
* @param {number} startTime
* @param {number} duration
*/
}, {
key: "setValueCurveAtTime",
value: function setValueCurveAtTime(values, startTime, duration) {
startTime = Math.max(0, toNumber(startTime));
duration = Math.max(0, toNumber(duration));
if (values.length === 0 || duration === 0) {
return;
}
var eventItem = {
type: SET_VALUE_CURVE_AT_TIME,
time: startTime,
args: [values, startTime, duration],
startFrame: Math.round(startTime * this.sampleRate),
endFrame: Math.round((startTime + duration) * this.sampleRate),
startValue: values[0],
endValue: values[values.length - 1]
};
var index = this.insertEvent(eventItem);
var prevEventItem = this._timeline[index - 1];
var nextEventItem = this._timeline[index + 1];
if (prevEventItem) {
switch (prevEventItem.type) {
case SET_VALUE_AT_TIME:
case SET_TARGET_AT_TIME:
prevEventItem.endFrame = eventItem.startFrame;
break;
}
}
if (nextEventItem) {
switch (nextEventItem.type) {
case LINEAR_RAMP_TO_VALUE_AT_TIME:
case EXPONENTIAL_RAMP_TO_VALUE_AT_TIME:
nextEventItem.startFrame = eventItem.startFrame;
nextEventItem.startValue = eventItem.endValue;
break;
}
}
if (index <= this._currentEventIndex) {
this._currentEventIndex = index;
this._remainSamples = 0;
}
}
/**
* @param {number} startTime
*/
}, {
key: "cancelScheduledValues",
value: function cancelScheduledValues(startTime) {
startTime = Math.max(0, toNumber(startTime));
this._timeline = this._timeline.filter(function (eventItem) {
return eventItem.time < startTime;
});
var index = this._timeline.length - 1;
var lastEventItem = this._timeline[index];
if (lastEventItem) {
switch (lastEventItem.type) {
case SET_VALUE_AT_TIME:
case SET_TARGET_AT_TIME:
lastEventItem.endFrame = Infinity;
break;
}
}
if (index <= this._currentEventIndex) {
this._currentEventIndex = index;
this._remainSamples = 0;
}
}
/**
* @return {string}
*/
}, {
key: "getRate",
value: function getRate() {
return this._rate;
}
/**
* @return {boolean}
*/
}, {
key: "hasSampleAccurateValues",
value: function hasSampleAccurateValues() {
return this._hasSampleAccurateValues;
}
/**
* @return {Float32Array}
*/
}, {
key: "getSampleAccurateValues",
value: function getSampleAccurateValues() {
return this.outputBus.getChannelData()[0];
}
/**
*
*/
}, {
key: "enableOutputsIfNecessary",
value: function enableOutputsIfNecessary() {}
/**
*
*/
}, {
key: "disableOutputsIfNecessary",
value: function disableOutputsIfNecessary() {}
/**
* @return {object[]}
*/
}, {
key: "getTimeline",
value: function getTimeline() {
return this._timeline;
}
/**
* @return {object[]}
*/
}, {
key: "getEvents",
value: function getEvents() {
return this._timeline.map(function (event) {
return { type: event.type, time: event.time, args: event.args };
});
}
/**
* @param {object}
* @return {number}
*/
}, {
key: "insertEvent",
value: function insertEvent(eventItem) {
var time = eventItem.time;
var timeline = this._timeline;
if (timeline.length === 0 || timeline[timeline.length - 1].time < time) {
timeline.push(eventItem);
return timeline.length - 1;
}
var pos = 0;
var replace = 0;
while (pos < timeline.length) {
if (timeline[pos].time === time && timeline[pos].type === eventItem.type) {
replace = 1;
break;
}
if (time < timeline[pos].time) {
break;
}
pos += 1;
}
timeline.splice(pos, replace, eventItem);
return pos;
}
}]);
return AudioParam;
}();
Object.assign(AudioParam.prototype, AudioParamDSP);
module.exports = AudioParam;
},{"../constants/AudioParamEvent":59,"../constants/AudioParamRate":60,"../constants/ChannelCountMode":62,"../utils":135,"./core/AudioBus":101,"./core/AudioNodeInput":103,"./dsp/AudioParam":107}],81:[function(require,module,exports){
"use strict";
//
//
//
//
// audio sched source node details
var AudioScheduledSourceNode = function (_AudioSourceNode) {
_inherits(AudioScheduledSourceNode, _AudioSourceNode);
/**
* @param {AudioContext} context
*/
function AudioScheduledSourceNode(context, opts) {
_classCallCheck(this, AudioScheduledSourceNode);
var _this = _possibleConstructorReturn(this, (AudioScheduledSourceNode.__proto__ || Object.getPrototypeOf(AudioScheduledSourceNode)).call(this, context, opts));
_this._startTime = Infinity;
_this._stopTime = Infinity;
_this._startFrame = Infinity;
_this._stopFrame = Infinity;
return _this;
}
/**
* @return {number}
*/
_createClass(AudioScheduledSourceNode, [{
key: "getStartTime",
value: function getStartTime() {
if (this._startTime !== Infinity) {
return this._startTime;
}
}
/**
* @return {number}
*/
}, {
key: "getStopTime",
value: function getStopTime() {
if (this._stopTime !== Infinity) {
return this._stopTime;
}
}
/**
* @return {string}
*/
}, {
key: "getPlaybackState",
value: function getPlaybackState() {
if (this._startTime === Infinity) {
return UNSCHEDULED;
}
if (this.context.currentTime < this._startTime) {
return SCHEDULED;
}
if (this._stopTime <= this.context.currentTime) {
return FINISHED;
}
return PLAYING;
}
/**
* @param {number} when
*/
}, {
key: "start",
value: function start(when) {
var _this2 = this;
/* istanbul ignore next */
if (this._startTime !== Infinity) {
return;
}
when = Math.max(this.context.currentTime, toNumber(when));
this._startTime = when;
this._startFrame = Math.round(when * this.sampleRate);
this.context.sched(when, function () {
_this2.outputs[0].enable();
});
}
/**
* @param {number} when
*/
}, {
key: "stop",
value: function stop(when) {
/* istanbul ignore next */
if (this._stopTime !== Infinity) {
return;
}
when = Math.max(this.context.currentTime, this._startTime, toNumber(when));
this._stopTime = when;
this._stopFrame = Math.round(when * this.sampleRate);
}
}]);
return AudioScheduledSourceNode;
}(AudioSourceNode);
module.exports = AudioScheduledSourceNode;
},{"../constants/PlaybackState":65,"../utils":135,"./AudioSourceNode":82}],82:[function(require,module,exports){
"use strict";
//
//
//
//
// oscillator details
},{"../constants/ChannelCountMode":62,"../utils":135,"./AudioNode":79,"./dsp/IIRFilterNode":118}],94:[function(require,module,exports){
"use strict";
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var AudioScheduledSourceNode = require("./AudioScheduledSourceNode");
var PeriodicWave = require("./PeriodicWave");
var OscillatorNodeDSP = require("./dsp/OscillatorNode");
var _require = require("../utils"),
defaults = _require.defaults;
var _require2 = require("../utils"),
toImpl = _require2.toImpl;
var _require3 = require("../constants/AudioParamRate"),
AUDIO_RATE = _require3.AUDIO_RATE;
var _require4 = require("../constants/OscillatorType"),
SINE = _require4.SINE,
SAWTOOTH = _require4.SAWTOOTH,
TRIANGLE = _require4.TRIANGLE,
SQUARE = _require4.SQUARE,
CUSTOM = _require4.CUSTOM;
var DefaultPeriodicWaves = {};
var allowedOscillatorTypes = [SINE, SAWTOOTH, TRIANGLE, SQUARE];
var DEFAULT_TYPE = SINE;
var DEFAULT_FREQUENCY = 440;
var DEFAULT_DETUNE = 0;
var OscillatorNode = function (_AudioScheduledSource) {
_inherits(OscillatorNode, _AudioScheduledSource);
/**
* @param {AudioContext} context
* @param {object} opts
* @param {string} opts.type
* @param {number} opts.frequency
* @param {number} opts.detune
*/
function OscillatorNode(context) {
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
_classCallCheck(this, OscillatorNode);
var type = defaults(opts.type, DEFAULT_TYPE);
var frequency = defaults(opts.frequency, DEFAULT_FREQUENCY);
var detune = defaults(opts.detune, DEFAULT_DETUNE);
var _this = _possibleConstructorReturn(this, (OscillatorNode.__proto__ || Object.getPrototypeOf(OscillatorNode)).call(this, context, opts));
_this._frequency = _this.addParam(AUDIO_RATE, frequency);
_this._detune = _this.addParam(AUDIO_RATE, detune);
_this._type = type;
_this._periodicWave = _this.buildPeriodicWave(_this._type);
_this._waveTable = null;
_this.dspInit();
return _this;
}
/**
* @return {string}
*/
_createClass(OscillatorNode, [{
key: "getType",
value: function getType() {
return this._type;
}
/**
* @param {string} value
*/
}, {
key: "setType",
value: function setType(value) {
/* istanbul ignore else */
if (allowedOscillatorTypes.indexOf(value) !== -1) {
this._type = value;
this._periodicWave = this.buildPeriodicWave(value);
this._waveTable = this._periodicWave.getWaveTable();
}
}
/**
* @param {AudioParam}
*/
}, {
key: "getFrequency",
value: function getFrequency() {
return this._frequency;
}
/**
* @param {AudioParam}
*/
}, {
key: "getDetune",
value: function getDetune() {
return this._detune;
}
/**
* @param {PeriodicWave} periodicWave
*/
}, {
key: "setPeriodicWave",
value: function setPeriodicWave(periodicWave) {
periodicWave = toImpl(periodicWave);
/* istanbul ignore else */
if (periodicWave instanceof PeriodicWave) {
this._type = CUSTOM;
this._periodicWave = periodicWave;
this._waveTable = this._periodicWave.getWaveTable();
}
}
/**
* @return {PeriodicWave}
*/
}, {
key: "getPeriodicWave",
value: function getPeriodicWave() {
return this._periodicWave;
}
/**
* @param {string} type
* @return {PeriodicWave}
*/
}, {
key: "buildPeriodicWave",
value: function buildPeriodicWave(type) {
var sampleRate = this.context.sampleRate;
var key = type + ":" + sampleRate;
/* istanbul ignore else */
if (!DefaultPeriodicWaves[key]) {
var periodicWave = new PeriodicWave({ sampleRate: sampleRate }, { constraints: false });
periodicWave.generateBasicWaveform(type);
DefaultPeriodicWaves[key] = periodicWave;
}
return DefaultPeriodicWaves[key];
}
}]);
return OscillatorNode;
}(AudioScheduledSourceNode);
Object.assign(OscillatorNode.prototype, OscillatorNodeDSP);
module.exports = OscillatorNode;
},{"../constants/AudioParamRate":60,"../constants/OscillatorType":64,"../utils":135,"./AudioScheduledSourceNode":81,"./PeriodicWave":96,"./dsp/OscillatorNode":119}],95:[function(require,module,exports){
"use strict";
//
//
//
//
// periodic wave details
"use strict";
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var nmap = require("nmap");
var PeriodicWaveDSP = require("./dsp/PeriodicWave");
var _require = require("../constants/OscillatorType"),
SINE = _require.SINE,
SAWTOOTH = _require.SAWTOOTH,
TRIANGLE = _require.TRIANGLE,
SQUARE = _require.SQUARE,
CUSTOM = _require.CUSTOM;
var PeriodicWave = function () {
/**
* @param {AudioContext} context
* @param {object} opts
* @param {Float32Array} opts.real
* @param {Float32Array} opts.imag
* @param {boolean} opts.constraints
*/
function PeriodicWave(context) {
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
_classCallCheck(this, PeriodicWave);
var real = opts.real;
var imag = opts.imag;
var constraints = opts.constraints;
this.context = context;
this._real = real;
this._imag = imag;
this._constants = !!constraints;
this._name = CUSTOM;
this.dspInit();
}
/**
* @return {Float32Array}
*/
_createClass(PeriodicWave, [{
key: "getReal",
value: function getReal() {
return this._real;
}
/**
* @return {Float32Array}
*/
}, {
key: "getImag",
value: function getImag() {
return this._imag;
}
/**
* @return {booleam}
*/
}, {
key: "getConstraints",
value: function getConstraints() {
return this._constants;
}
/**
* @return {string}
*/
}, {
key: "getName",
value: function getName() {
return this._name;
}
/**
* @return {Float32Array}
*/
}, {
key: "getWaveTable",
value: function getWaveTable() {
if (!this._waveTable) {
this._waveTable = this.dspBuildWaveTable();
}
return this._waveTable;
}
}, {
key: "generateBasicWaveform",
value: function generateBasicWaveform(type) {
var length = 512;
switch (type) {
case SINE:
this._real = new Float32Array([0, 0]);
this._imag = new Float32Array([0, 1]);
this._name = SINE;
break;
case SAWTOOTH:
this._real = new Float32Array(length);
this._imag = new Float32Array(nmap(length, function (_, n) {
return n === 0 ? 0 : Math.pow(-1, n + 1) * (2 / (n * Math.PI));
}));
this._name = SAWTOOTH;
this.dspBuildWaveTable();
break;
case TRIANGLE:
this._real = new Float32Array(length);
this._imag = new Float32Array(nmap(length, function (_, n) {
return n === 0 ? 0 : 8 * Math.sin(n * Math.PI / 2) / Math.pow(n * Math.PI, 2);
}));
this._name = TRIANGLE;
this.dspBuildWaveTable();
break;
case SQUARE:
this._real = new Float32Array(length);
this._imag = new Float32Array(nmap(length, function (_, n) {
return n === 0 ? 0 : 2 / (n * Math.PI) * (1 - Math.pow(-1, n));
}));
this._name = SQUARE;
this.dspBuildWaveTable();
break;
default:
this._real = new Float32Array([0]);
this._imag = new Float32Array([0]);
this._name = CUSTOM;
this.dspBuildWaveTable();
break;
}
}
}]);
return PeriodicWave;
}();
Object.assign(PeriodicWave.prototype, PeriodicWaveDSP);
module.exports = PeriodicWave;
},{"../constants/OscillatorType":64,"./dsp/PeriodicWave":121,"nmap":25}],97:[function(require,module,exports){
"use strict";
//
//
//
//
// various DSP algorithm details
DSPAlgorithm[0] = function (source, destination, length) {
var numberOfChannels = Math.min(source.length, destination.length);
for (var ch = 0; ch < numberOfChannels; ch++) {
for (var i = 0; i < length; i++) {
destination[ch][i] += source[ch][i];
}
}
};
DSPAlgorithm[0].set = function (source, destination) {
var numberOfChannels = Math.min(source.length, destination.length);
for (var ch = 0; ch < numberOfChannels; ch++) {
destination[ch].set(source[ch]);
}
};
DSPAlgorithm[1001001] = function (source, destination, length) {
var output = destination[0];
var input = source[0];
for (var i = 0; i < length; i++) {
output[i] += input[i];
}
};
DSPAlgorithm[1001001].set = function (source, destination) {
destination[0].set(source[0]);
};
DSPAlgorithm[2001001] = DSPAlgorithm[1001001];
DSPAlgorithm[2001001].set = DSPAlgorithm[1001001].set;
DSPAlgorithm[1001002] = function (source, destination, length) {
var outputL = destination[0];
var outputR = destination[1];
var input = source[0];
for (var i = 0; i < length; i++) {
outputL[i] += input[i];
outputR[i] += input[i];
}
};
DSPAlgorithm[1001002].set = function (source, destination) {
destination[0].set(source[0]);
destination[1].set(source[0]);
};
DSPAlgorithm[1001004] = DSPAlgorithm[1001002];
DSPAlgorithm[1001004].set = DSPAlgorithm[1001002].set;
DSPAlgorithm[1001006] = function (source, destination, length) {
var outputC = destination[2];
var input = source[0];
for (var i = 0; i < length; i++) {
outputC[i] += input[i];
}
};
DSPAlgorithm[1001006].set = function (source, destination) {
destination[2].set(source[0]);
};
DSPAlgorithm[1002002] = function (source, destination, length) {
var outputL = destination[0];
var outputR = destination[1];
var inputL = source[0];
var inputR = source[1];
for (var i = 0; i < length; i++) {
outputL[i] += inputL[i];
outputR[i] += inputR[i];
}
};
DSPAlgorithm[1002002].set = function (source, destination) {
destination[0].set(source[0]);
destination[1].set(source[1]);
};
DSPAlgorithm[2002002] = DSPAlgorithm[1002002];
DSPAlgorithm[2002002].set = DSPAlgorithm[1002002].set;
DSPAlgorithm[1002004] = DSPAlgorithm[1002002];
DSPAlgorithm[1002004].set = DSPAlgorithm[1002002].set;
DSPAlgorithm[1002006] = DSPAlgorithm[1002004];
DSPAlgorithm[1002006].set = DSPAlgorithm[1002004].set;
DSPAlgorithm[1004006] = function (source, destination, length) {
var outputL = destination[0];
var outputR = destination[1];
var outputSL = destination[4];
var outputSR = destination[5];
var inputL = source[0];
var inputR = source[1];
var inputSL = source[2];
var inputSR = source[3];
for (var i = 0; i < length; i++) {
outputL[i] += inputL[i];
outputR[i] += inputR[i];
outputSL[i] += inputSL[i];
outputSR[i] += inputSR[i];
}
};
DSPAlgorithm[1004006].set = function (source, destination) {
destination[0].set(source[0]);
destination[1].set(source[1]);
destination[4].set(source[2]);
destination[5].set(source[3]);
};
DSPAlgorithm[1002001] = function (source, destination, length) {
var output = destination[0];
var inputL = source[0];
var inputR = source[1];
for (var i = 0; i < length; i++) {
output[i] += 0.5 * (inputL[i] + inputR[i]);
}
};
DSPAlgorithm[1004001] = function (source, destination, length) {
var output = destination[0];
var inputL = source[0];
var inputR = source[1];
var inputSL = source[2];
var inputSR = source[3];
for (var i = 0; i < length; i++) {
output[i] += 0.25 * (inputL[i] + inputR[i] + inputSL[i] + inputSR[i]);
}
};
DSPAlgorithm[1006001] = function (source, destination, length) {
var output = destination[0];
var inputL = source[0];
var inputR = source[1];
var inputC = source[2];
var inputSL = source[4];
var inputSR = source[5];
for (var i = 0; i < length; i++) {
output[i] += 0.7071 * (inputL[i] + inputR[i]) + inputC[i] + 0.5 * (inputSL[i] + inputSR[i]);
}
};
DSPAlgorithm[1004002] = function (source, destination, length) {
var outputL = destination[0];
var outputR = destination[1];
var inputL = source[0];
var inputR = source[1];
var inputSL = source[2];
var inputSR = source[3];
for (var i = 0; i < length; i++) {
outputL[i] += 0.5 * (inputL[i] + inputSL[i]);
outputR[i] += 0.5 * (inputR[i] + inputSR[i]);
}
};
DSPAlgorithm[1006002] = function (source, destination, length) {
var outputL = destination[0];
var outputR = destination[1];
var inputL = source[0];
var inputR = source[1];
var inputC = source[2];
var inputSL = source[4];
var inputSR = source[5];
for (var i = 0; i < length; i++) {
outputL[i] += inputL[i] + 0.7071 * (inputC[i] + inputSL[i]);
outputR[i] += inputR[i] + 0.7071 * (inputC[i] + inputSR[i]);
}
};
DSPAlgorithm[1006004] = function (source, destination, length) {
var outputL = destination[0];
var outputR = destination[1];
var outputSL = destination[2];
var outputSR = destination[3];
var inputL = source[0];
var inputR = source[1];
var inputC = source[2];
var inputSL = source[4];
var inputSR = source[5];
for (var i = 0; i < length; i++) {
outputL[i] += inputL[i] + 0.7071 * inputC[i];
outputR[i] += inputR[i] + 0.7071 * inputC[i];
outputSL[i] += inputSL[i];
outputSR[i] += inputSR[i];
}
};
module.exports = AudioBus;
},{"../../constants/ChannelInterpretation":63,"../../utils":135,"./AudioData":102}],102:[function(require,module,exports){
"use strict";
//
//
//
//
// audio buffer source node dsp details
"use strict";
var AudioBufferSourceNodeDSP = {
dspInit: function dspInit() {
this._phase = 0;
},
dspStart: function dspStart() {
if (this._audioData) {
var bufferSampleRate = this._audioData.sampleRate;
var bufferDuration = this._audioData.length / bufferSampleRate;
this._phase = Math.max(0, Math.min(this._offset, bufferDuration)) * bufferSampleRate;
}
},
dspProcess: function dspProcess() {
if (this._audioData === null) {
return this.dspEmitEnded();
}
var blockSize = this.blockSize;
var quantumStartFrame = this.context.currentSampleFrame;
var quantumEndFrame = quantumStartFrame + blockSize;
var sampleOffset = Math.max(0, this._startFrame - quantumStartFrame);
var fillToSample = Math.min(quantumEndFrame, this._stopFrame) - quantumStartFrame;
var outputs = this.outputs[0].bus.getMutableData();
var writeIndex = 0;
writeIndex = this.dspBufferRendering(outputs, sampleOffset, fillToSample, this.sampleRate);
// timeline
// |----------------|-------*--------|----------------|----------------|
// ^ ^ ^
// |------>| quantumEndFrame
// | wrote |
// | stopFrame
// quantumStartFrame
if (this._stopFrame <= quantumStartFrame + writeIndex) {
// rest samples fill zero
var numberOfChannels = outputs.length;
while (writeIndex < blockSize) {
for (var ch = 0; ch < numberOfChannels; ch++) {
outputs[ch][writeIndex] = 0;
}
writeIndex += 1;
}
this.dspEmitEnded();
}
},
dspBufferRendering: function dspBufferRendering(outputs, writeIndex, inNumSamples, sampleRate) {
var playbackRateValues = this._playbackRate.getSampleAccurateValues();
var detuneValues = this._detune.getSampleAccurateValues();
var numberOfChannels = this._audioData.numberOfChannels;
var bufferLength = this._audioData.length;
var bufferSampleRate = this._audioData.sampleRate;
var bufferChannelData = this._audioData.channelData;
var playbackRateToPhaseIncr = bufferSampleRate / sampleRate;
var phase = this._phase;
while (writeIndex < inNumSamples) {
var playbackRateValue = playbackRateValues[writeIndex];
var detuneValue = detuneValues[writeIndex];
var computedPlaybackRate = playbackRateValue * Math.pow(2, detuneValue / 1200);
for (var ch = 0; ch < numberOfChannels; ch++) {
var v0 = bufferChannelData[ch][phase | 0] || 0;
var v1 = bufferChannelData[ch][(phase | 0) + 1] || 0;
outputs[ch][writeIndex] = v0 + phase % 1 * (v1 - v0);
}
writeIndex += 1;
phase += playbackRateToPhaseIncr * Math.max(0, computedPlaybackRate);
if (this._loop) {
if (0 <= this._loopStart && this._loopStart < this._loopEnd) {
var loopEndSamples = this._loopEnd * bufferSampleRate;
if (loopEndSamples <= phase) {
phase = this._loopStart * bufferSampleRate;
}
} else {
if (bufferLength <= phase) {
phase = 0;
}
}
} else {
if (bufferLength <= phase) {
this.dspEmitEnded();
break;
}
}
}
this._phase = phase;
return writeIndex;
},
dspEmitEnded: function dspEmitEnded() {
var _this = this;
this._done = true;
this.context.addPostProcess(function () {
_this.outputs[0].bus.zeros();
_this.outputs[0].disable();
_this.dispatchEvent({ type: "ended" });
});
}
};
module.exports = AudioBufferSourceNodeDSP;
},{}],107:[function(require,module,exports){
//
//
//
//
// audio param dsp details
"use strict";
var AudioParamUtils = require("../../utils/AudioParamUtils");
var _require = require("../../utils"),
fill = _require.fill;
var _require2 = require("../../constants/AudioParamEvent"),
SET_VALUE_AT_TIME = _require2.SET_VALUE_AT_TIME;
var _require3 = require("../../constants/AudioParamEvent"),
LINEAR_RAMP_TO_VALUE_AT_TIME = _require3.LINEAR_RAMP_TO_VALUE_AT_TIME;
var _require4 = require("../../constants/AudioParamEvent"),
EXPONENTIAL_RAMP_TO_VALUE_AT_TIME = _require4.EXPONENTIAL_RAMP_TO_VALUE_AT_TIME;
var _require5 = require("../../constants/AudioParamEvent"),
SET_TARGET_AT_TIME = _require5.SET_TARGET_AT_TIME;
var _require6 = require("../../constants/AudioParamEvent"),
SET_VALUE_CURVE_AT_TIME = _require6.SET_VALUE_CURVE_AT_TIME;
var AudioParamDSP = {
dspInit: function dspInit() {
this._prevValue = NaN;
this._hasSampleAccurateValues = false;
this._currentEventIndex = -1;
this._quantumStartFrame = -1;
this._remainSamples = 0;
this._schedParams = {};
},
dspProcess: function dspProcess() {
var input = this.inputs[0];
var inputBus = input.bus;
input.pull();
var hasEvents = !!this._timeline.length;
var hasInput = !inputBus.isSilent;
var algorithm = hasEvents * 2 + hasInput;
switch (algorithm) {
case 0:
// events: x / input: x
return this.dspStaticValue();
case 1:
// events: x / input: o
return this.dspInputAndOffset(inputBus);
case 2:
// events: o / input: x
return this.dspEvents();
case 3:
// events: o / input: o
return this.dspEventsAndInput(inputBus);
default:
/* istanbul ignore next */
void 0;
}
},
dspStaticValue: function dspStaticValue() {
var value = this._value;
if (value !== this._prevValue) {
if (value === 0) {
this.outputBus.zeros();
} else {
fill(this.outputBus.getMutableData()[0], value);
}
this._prevValue = value;
}
this._hasSampleAccurateValues = false;
},
dspInputAndOffset: function dspInputAndOffset(inputBus) {
var blockSize = this.blockSize;
var outputBus = this.outputBus;
var output = outputBus.getMutableData()[0];
var input = inputBus.getChannelData()[0];
var value = this._value;
output.set(input);
if (value !== 0) {
for (var i = 0; i < blockSize; i++) {
output[i] += value;
}
}
this._prevValue = NaN;
this._hasSampleAccurateValues = true;
},
dspEvents: function dspEvents() {
var outputBus = this.outputBus;
var output = outputBus.getMutableData()[0];
this.dspValuesForTimeRange(output);
this._prevValue = NaN;
this._hasSampleAccurateValues = true;
},
dspEventsAndInput: function dspEventsAndInput(inputBus) {
var blockSize = this.blockSize;
var outputBus = this.outputBus;
var output = outputBus.getMutableData()[0];
var input = inputBus.getChannelData()[0];
this.dspValuesForTimeRange(output);
for (var i = 0; i < blockSize; i++) {
output[i] += input[i];
}
this._prevValue = NaN;
this._hasSampleAccurateValues = true;
},
dspValuesForTimeRange: function dspValuesForTimeRange(output) {
var blockSize = this.blockSize;
var quantumStartFrame = this.context.currentSampleFrame;
var quantumEndFrame = quantumStartFrame + blockSize;
var sampleRate = this.sampleRate;
var timeline = this._timeline;
var value = this._value;
var writeIndex = 0;
// processing until the first event
if (this._currentEventIndex === -1) {
var firstEventStartFrame = timeline[0].startFrame;
// timeline
// |----------------|----------------|-------*--------|----------------|
// ^ ^ ^
// | quantumEndFrame firstEventStartFrame
// quantumStartFrame
// <---------------> fill value with in range
if (quantumEndFrame <= firstEventStartFrame) {
for (var i = 0; i < blockSize; i++) {
output[i] = value;
}
this._hasSampleAccurateValues = false;
return;
}
// timeline
// |----------------|----------------|-------*--------|----------------|
// ^ ^ ^
// | | quantumEndFrame
// | firstEventStartFrame
// quantumStartFrame
// <------> fill value with in range
for (var _i = 0, imax = firstEventStartFrame - quantumStartFrame; _i < imax; _i++) {
output[writeIndex++] = value;
}
this._currentEventIndex = 0;
}
this._hasSampleAccurateValues = true;
var remainSamples = this._quantumStartFrame === quantumStartFrame ? this._remainSamples : 0;
var schedParams = this._schedParams;
// if new event exists, should recalculate remainSamples
if (remainSamples === Infinity && this._currentEventIndex + 1 !== timeline.length) {
remainSamples = timeline[this._currentEventIndex + 1].startFrame - quantumStartFrame;
}
while (writeIndex < blockSize && this._currentEventIndex < timeline.length) {
var eventItem = timeline[this._currentEventIndex];
var startFrame = eventItem.startFrame;
var endFrame = eventItem.endFrame;
// timeline
// |-------*--------|-------*--------|----------------|----------------|
// ^ ^ ^ ^
// |<-------------->| | quantumEndFrame
// | | quantumStartFrame
// startFrame endFrame
// skip event if
// (endFrame < quantumStartFrame): past event
// or
// (startFrame === endFrame): setValueAtTime before linearRampToValueAtTime or exponentialRampToValueAtTime.
if (endFrame < quantumStartFrame || startFrame === endFrame) {
remainSamples = 0;
this._currentEventIndex += 1;
continue;
}
if (remainSamples <= 0) {
var processedSamples = Math.max(0, quantumStartFrame - startFrame);
switch (eventItem.type) {
case SET_VALUE_AT_TIME:
{
value = eventItem.startValue;
schedParams = { type: SET_VALUE_AT_TIME };
}
break;
case LINEAR_RAMP_TO_VALUE_AT_TIME:
{
var valueRange = eventItem.endValue - eventItem.startValue;
var frameRange = eventItem.endFrame - eventItem.startFrame;
var grow = valueRange / frameRange;
if (grow) {
value = eventItem.startValue + processedSamples * grow;
schedParams = { type: LINEAR_RAMP_TO_VALUE_AT_TIME, grow: grow };
} else {
value = eventItem.startValue;
schedParams = { type: SET_VALUE_AT_TIME };
}
}
break;
case EXPONENTIAL_RAMP_TO_VALUE_AT_TIME:
{
var valueRatio = eventItem.endValue / eventItem.startValue;
var _frameRange = eventItem.endFrame - eventItem.startFrame;
var _grow = Math.pow(valueRatio, 1 / _frameRange);
if (_grow) {
value = eventItem.startValue * Math.pow(_grow, processedSamples);
schedParams = { type: EXPONENTIAL_RAMP_TO_VALUE_AT_TIME, grow: _grow };
} else {
value = eventItem.startValue;
schedParams = { type: SET_VALUE_AT_TIME };
}
}
break;
case SET_TARGET_AT_TIME:
{
var target = Math.fround(eventItem.args[0]);
var timeConstant = eventItem.args[2];
var discreteTimeConstant = 1 - Math.exp(-1 / (sampleRate * timeConstant));
var time = (quantumStartFrame + writeIndex) / sampleRate;
value = AudioParamUtils.computeValueAtTime(timeline, time, this._userValue);
if (discreteTimeConstant !== 1) {
schedParams = { type: SET_TARGET_AT_TIME, target: target, discreteTimeConstant: discreteTimeConstant };
} else {
schedParams = { type: SET_VALUE_AT_TIME };
}
}
break;
case SET_VALUE_CURVE_AT_TIME:
{
var curve = eventItem.args[0];
schedParams = { type: SET_VALUE_CURVE_AT_TIME, curve: curve, startFrame: startFrame, endFrame: endFrame };
}
break;
}
remainSamples = endFrame - startFrame - processedSamples;
} // if (remainSamples === 0)
var fillFrames = Math.min(blockSize - writeIndex, remainSamples);
switch (schedParams.type) {
case SET_VALUE_AT_TIME:
{
for (var _i2 = 0; _i2 < fillFrames; _i2++) {
output[writeIndex++] = value;
}
}
break;
case LINEAR_RAMP_TO_VALUE_AT_TIME:
{
for (var _i3 = 0; _i3 < fillFrames; _i3++) {
output[writeIndex++] = value;
value += schedParams.grow;
}
}
break;
case EXPONENTIAL_RAMP_TO_VALUE_AT_TIME:
{
for (var _i4 = 0; _i4 < fillFrames; _i4++) {
output[writeIndex++] = value;
value *= schedParams.grow;
}
}
break;
case SET_TARGET_AT_TIME:
{
for (var _i5 = 0; _i5 < fillFrames; _i5++) {
output[writeIndex++] = value;
value += (schedParams.target - value) * schedParams.discreteTimeConstant;
}
}
break;
case SET_VALUE_CURVE_AT_TIME:
{
var _curve = schedParams.curve;
var schedRange = schedParams.endFrame - schedParams.startFrame;
var schedStartFrame = schedParams.startFrame;
for (var _i6 = 0; _i6 < fillFrames; _i6++) {
var xx = (quantumStartFrame + writeIndex - schedStartFrame) / schedRange;
var ix = xx * (_curve.length - 1);
var i0 = ix | 0;
var i1 = i0 + 1;
value = _curve[i0] + ix % 1 * (_curve[i1] - _curve[i0]);
output[writeIndex++] = value;
}
if (remainSamples === fillFrames) {
value = _curve[_curve.length - 1];
}
}
break;
}
remainSamples -= fillFrames;
if (remainSamples === 0) {
this._currentEventIndex += 1;
}
} // while (writeIndex < blockSize)
while (writeIndex < blockSize) {
output[writeIndex++] = value;
}
this._value = value;
this._schedParams = schedParams;
this._remainSamples = remainSamples;
this._quantumStartFrame = quantumEndFrame;
}
};
module.exports = AudioParamDSP;
},{"../../constants/AudioParamEvent":59,"../../utils":135,"../../utils/AudioParamUtils":128}],108:[function(require,module,exports){
"use strict";
//
//
//
//
// oscillator and periodic wave dsp details
"use strict";
var _require = require("../../constants/OscillatorType"),
SINE = _require.SINE;
var OscillatorNodeDSP = {
dspInit: function dspInit() {
this._phase = 0;
},
dspProcess: function dspProcess() {
var _this = this;
var blockSize = this.blockSize;
var quantumStartFrame = this.context.currentSampleFrame;
var quantumEndFrame = quantumStartFrame + blockSize;
var sampleOffset = Math.max(0, this._startFrame - quantumStartFrame);
var fillToSample = Math.min(quantumEndFrame, this._stopFrame) - quantumStartFrame;
var output = this.outputs[0].bus.getMutableData()[0];
var writeIndex = 0;
if (this._type === SINE) {
writeIndex = this.dspSine(output, sampleOffset, fillToSample, this.sampleRate);
} else {
writeIndex = this.dspWave(output, sampleOffset, fillToSample, this.sampleRate);
}
// timeline
// |----------------|-------*--------|----------------|----------------|
// ^ ^ ^
// |------>| quantumEndFrame
// | wrote |
// | stopFrame
// quantumStartFrame
if (this._stopFrame <= quantumStartFrame + writeIndex) {
// rest samples fill zero
while (writeIndex < blockSize) {
output[writeIndex++] = 0;
}
this.context.addPostProcess(function () {
_this.outputs[0].bus.zeros();
_this.outputs[0].disable();
_this.dispatchEvent({ type: "ended" });
});
}
},
dspSine: function dspSine(output, writeIndex, blockSize, sampleRate) {
var frequency = this._frequency;
var detune = this._detune;
var algorithm = frequency.hasSampleAccurateValues() * 2 + detune.hasSampleAccurateValues();
var frequencyToPhaseIncr = 2 * Math.PI / sampleRate;
var phase = this._phase;
if (algorithm === 0) {
var frequencyValue = frequency.getValue();
var detuneValue = detune.getValue();
var computedFrequency = frequencyValue * Math.pow(2, detuneValue / 1200);
var phaseIncr = frequencyToPhaseIncr * computedFrequency;
while (writeIndex < blockSize) {
output[writeIndex++] = Math.sin(phase);
phase += phaseIncr;
}
} else {
var frequencyValues = frequency.getSampleAccurateValues();
var detuneValues = detune.getSampleAccurateValues();
while (writeIndex < blockSize) {
var _frequencyValue = frequencyValues[writeIndex];
var _detuneValue = detuneValues[writeIndex];
var _computedFrequency = _frequencyValue * Math.pow(2, _detuneValue / 1200);
output[writeIndex++] = Math.sin(phase);
phase += frequencyToPhaseIncr * _computedFrequency;
}
}
this._phase = phase;
return writeIndex;
},
dspWave: function dspWave(output, writeIndex, blockSize, sampleRate) {
var frequency = this._frequency;
var detune = this._detune;
var algorithm = frequency.hasSampleAccurateValues() * 2 + detune.hasSampleAccurateValues();
var waveTable = this._waveTable;
var waveTableLength = waveTable.length - 1;
var frequencyToPhaseIncr = 1 / sampleRate;
var phase = this._phase;
if (algorithm === 0) {
var frequencyValue = frequency.getValue();
var detuneValue = detune.getValue();
var computedFrequency = frequencyValue * Math.pow(2, detuneValue / 1200);
var phaseIncr = frequencyToPhaseIncr * computedFrequency;
while (writeIndex < blockSize) {
var idx = phase * waveTableLength % waveTableLength;
var v0 = waveTable[idx | 0];
var v1 = waveTable[(idx | 0) + 1];
output[writeIndex++] = v0 + idx % 1 * (v1 - v0);
phase += phaseIncr;
}
} else {
var frequencyValues = frequency.getSampleAccurateValues();
var detuneValues = detune.getSampleAccurateValues();
while (writeIndex < blockSize) {
var _frequencyValue2 = frequencyValues[writeIndex];
var _detuneValue2 = detuneValues[writeIndex];
var _computedFrequency2 = _frequencyValue2 * Math.pow(2, _detuneValue2 / 1200);
var _idx = phase * waveTableLength % waveTableLength;
var _v = waveTable[_idx | 0];
var _v2 = waveTable[(_idx | 0) + 1];
output[writeIndex++] = _v + _idx % 1 * (_v2 - _v);
phase += frequencyToPhaseIncr * _computedFrequency2;
}
}
this._phase = phase;
return writeIndex;
}
};
module.exports = OscillatorNodeDSP;
},{"../../constants/OscillatorType":64}],120:[function(require,module,exports){
"use strict";
var PannerNodeDSP = {
dspProcess: function dspProcess() {
var outputBus = this.outputs[0].bus;
outputBus.zeros();
outputBus.sumFrom(this.inputs[0].bus);
}
};
module.exports = PannerNodeDSP;
},{}],121:[function(require,module,exports){
"use strict";
var WAVE_TABLE_LENGTH = 8192;
var PeriodicWaveDSP = {
dspInit: function dspInit() {
this._waveTable = null;
},
dspBuildWaveTable: function dspBuildWaveTable() {
if (this._waveTable !== null) {
return this._waveTable;
}
var waveTable = new Float32Array(WAVE_TABLE_LENGTH + 1);
var real = this._real;
var imag = this._imag;
var maxAbsValue = 0;
var periodicWaveLength = Math.min(real.length, 16);
for (var i = 0; i < WAVE_TABLE_LENGTH; i++) {
var x = i / WAVE_TABLE_LENGTH * Math.PI * 2;
for (var n = 1; n < periodicWaveLength; n++) {
waveTable[i] += real[n] * Math.cos(n * x) + imag[n] * Math.sin(n * x);
}
maxAbsValue = Math.max(maxAbsValue, Math.abs(waveTable[i]));
}
if (!this._constants && maxAbsValue !== 1) {
for (var _i = 0; _i < WAVE_TABLE_LENGTH; _i++) {
waveTable[_i] *= maxAbsValue;
}
}
waveTable[WAVE_TABLE_LENGTH] = waveTable[0];
this._waveTable = waveTable;
return waveTable;
}
};
module.exports = PeriodicWaveDSP;
},{}],122:[function(require,module,exports){
"use strict";
//
//
//
//
// audio param ramp dsp details
"use strict";
var _require = require("../constants/AudioParamEvent"),
SET_VALUE_AT_TIME = _require.SET_VALUE_AT_TIME;
var _require2 = require("../constants/AudioParamEvent"),
LINEAR_RAMP_TO_VALUE_AT_TIME = _require2.LINEAR_RAMP_TO_VALUE_AT_TIME;
var _require3 = require("../constants/AudioParamEvent"),
EXPONENTIAL_RAMP_TO_VALUE_AT_TIME = _require3.EXPONENTIAL_RAMP_TO_VALUE_AT_TIME;
var _require4 = require("../constants/AudioParamEvent"),
SET_TARGET_AT_TIME = _require4.SET_TARGET_AT_TIME;
var _require5 = require("../constants/AudioParamEvent"),
SET_VALUE_CURVE_AT_TIME = _require5.SET_VALUE_CURVE_AT_TIME;
/**
* @param {object[]} timeline
* @param {number} time
* @param {number} defaultValue
*/
function computeValueAtTime(timeline, time, defaultValue) {
var value = defaultValue;
for (var i = 0, imax = timeline.length; i < imax; i++) {
var e0 = timeline[i];
var e1 = timeline[i + 1];
var t0 = Math.min(time, e1 ? e1.time : time);
if (time < e0.time) {
break;
}
switch (e0.type) {
case SET_VALUE_AT_TIME:
case LINEAR_RAMP_TO_VALUE_AT_TIME:
case EXPONENTIAL_RAMP_TO_VALUE_AT_TIME:
value = e0.args[0];
break;
case SET_TARGET_AT_TIME:
value = getTargetValueAtTime(t0, value, e0.args[0], e0.args[1], e0.args[2]);
break;
case SET_VALUE_CURVE_AT_TIME:
value = getValueCurveAtTime(t0, e0.args[0], e0.args[1], e0.args[2]);
break;
}
if (e1) {
switch (e1.type) {
case LINEAR_RAMP_TO_VALUE_AT_TIME:
value = getLinearRampToValueAtTime(t0, value, e1.args[0], e0.time, e1.args[1]);
break;
case EXPONENTIAL_RAMP_TO_VALUE_AT_TIME:
value = getExponentialRampToValueAtTime(t0, value, e1.args[0], e0.time, e1.args[1]);
break;
}
}
}
return value;
}
function getLinearRampToValueAtTime(t, v0, v1, t0, t1) {
var a;
if (t <= t0) {
return v0;
}
if (t1 <= t) {
return v1;
}
a = (t - t0) / (t1 - t0);
return v0 + a * (v1 - v0);
}
function getExponentialRampToValueAtTime(t, v0, v1, t0, t1) {
var a;
if (t <= t0) {
return v0;
}
if (t1 <= t) {
return v1;
}
a = (t - t0) / (t1 - t0);
return v0 * Math.pow(v1 / v0, a);
}
function getTargetValueAtTime(t, v0, v1, t0, timeConstant) {
if (t <= t0) {
return v0;
}
return v1 + (v0 - v1) * Math.exp((t0 - t) / timeConstant);
}
function getValueCurveAtTime(t, curve, t0, duration) {
var x, ix, i0, i1;
var y0, y1, a;
x = (t - t0) / duration;
ix = x * (curve.length - 1);
i0 = ix | 0;
i1 = i0 + 1;
if (curve.length <= i1) {
return curve[curve.length - 1];
}
y0 = curve[i0];
y1 = curve[i1];
a = ix % 1;
return y0 + a * (y1 - y0);
}
module.exports = { computeValueAtTime: computeValueAtTime, getLinearRampToValueAtTime: getLinearRampToValueAtTime, getExponentialRampToValueAtTime: getExponentialRampToValueAtTime, getTargetValueAtTime: getTargetValueAtTime, getValueCurveAtTime: getValueCurveAtTime };
},{"../constants/AudioParamEvent":59}],129:[function(require,module,exports){
"use strict";
//
//
//
//
// clamp details
"use strict";
/**
* @param {number} value
* @param {number} minValue
* @param {number} maxValue
*/
function clamp(value, minValue, maxValue) {
return Math.max(minValue, Math.min(value, maxValue));
}
module.exports = clamp;
},{}],138:[function(require,module,exports){
//
//
//
//
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment