UNPKG

@soundtouchjs/audio-worklet

Version:

An ES2015+ AudioWorklet implementation of the SoundTouchJS library

1,578 lines (1,523 loc) 60.3 kB
/* * SoundTouch Audio Worklet v0.1.17 AudioWorklet using the * SoundTouch audio processing library * * Copyright (c) Olli Parviainen * Copyright (c) Ryan Berdeen * Copyright (c) Jakub Fiala * Copyright (c) Steve 'Cutter' Blades * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 'use strict'; function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a 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); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); } function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } function _construct(Parent, args, Class) { if (_isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); } function _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; } function _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); } function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; } function _get() { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(arguments.length < 3 ? target : receiver); } return desc.value; }; } return _get.apply(this, arguments); } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var runtime = function (exports) { var Op = Object.prototype; var hasOwn = Op.hasOwnProperty; var undefined$1; var $Symbol = typeof Symbol === "function" ? Symbol : {}; var iteratorSymbol = $Symbol.iterator || "@@iterator"; var asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator"; var toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag"; function define(obj, key, value) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); return obj[key]; } try { define({}, ""); } catch (err) { define = function define(obj, key, value) { return obj[key] = value; }; } function wrap(innerFn, outerFn, self, tryLocsList) { var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator; var generator = Object.create(protoGenerator.prototype); var context = new Context(tryLocsList || []); generator._invoke = makeInvokeMethod(innerFn, self, context); return generator; } exports.wrap = wrap; function tryCatch(fn, obj, arg) { try { return { type: "normal", arg: fn.call(obj, arg) }; } catch (err) { return { type: "throw", arg: err }; } } var GenStateSuspendedStart = "suspendedStart"; var GenStateSuspendedYield = "suspendedYield"; var GenStateExecuting = "executing"; var GenStateCompleted = "completed"; var ContinueSentinel = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var IteratorPrototype = {}; define(IteratorPrototype, iteratorSymbol, function () { return this; }); var getProto = Object.getPrototypeOf; var NativeIteratorPrototype = getProto && getProto(getProto(values([]))); if (NativeIteratorPrototype && NativeIteratorPrototype !== Op && hasOwn.call(NativeIteratorPrototype, iteratorSymbol)) { IteratorPrototype = NativeIteratorPrototype; } var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(IteratorPrototype); GeneratorFunction.prototype = GeneratorFunctionPrototype; define(Gp, "constructor", GeneratorFunctionPrototype); define(GeneratorFunctionPrototype, "constructor", GeneratorFunction); GeneratorFunction.displayName = define(GeneratorFunctionPrototype, toStringTagSymbol, "GeneratorFunction"); function defineIteratorMethods(prototype) { ["next", "throw", "return"].forEach(function (method) { define(prototype, method, function (arg) { return this._invoke(method, arg); }); }); } exports.isGeneratorFunction = function (genFun) { var ctor = typeof genFun === "function" && genFun.constructor; return ctor ? ctor === GeneratorFunction || (ctor.displayName || ctor.name) === "GeneratorFunction" : false; }; exports.mark = function (genFun) { if (Object.setPrototypeOf) { Object.setPrototypeOf(genFun, GeneratorFunctionPrototype); } else { genFun.__proto__ = GeneratorFunctionPrototype; define(genFun, toStringTagSymbol, "GeneratorFunction"); } genFun.prototype = Object.create(Gp); return genFun; }; exports.awrap = function (arg) { return { __await: arg }; }; function AsyncIterator(generator, PromiseImpl) { function invoke(method, arg, resolve, reject) { var record = tryCatch(generator[method], generator, arg); if (record.type === "throw") { reject(record.arg); } else { var result = record.arg; var value = result.value; if (value && _typeof(value) === "object" && hasOwn.call(value, "__await")) { return PromiseImpl.resolve(value.__await).then(function (value) { invoke("next", value, resolve, reject); }, function (err) { invoke("throw", err, resolve, reject); }); } return PromiseImpl.resolve(value).then(function (unwrapped) { result.value = unwrapped; resolve(result); }, function (error) { return invoke("throw", error, resolve, reject); }); } } var previousPromise; function enqueue(method, arg) { function callInvokeWithMethodAndArg() { return new PromiseImpl(function (resolve, reject) { invoke(method, arg, resolve, reject); }); } return previousPromise = previousPromise ? previousPromise.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } this._invoke = enqueue; } defineIteratorMethods(AsyncIterator.prototype); define(AsyncIterator.prototype, asyncIteratorSymbol, function () { return this; }); exports.AsyncIterator = AsyncIterator; exports.async = function (innerFn, outerFn, self, tryLocsList, PromiseImpl) { if (PromiseImpl === void 0) PromiseImpl = Promise; var iter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList), PromiseImpl); return exports.isGeneratorFunction(outerFn) ? iter : iter.next().then(function (result) { return result.done ? result.value : iter.next(); }); }; function makeInvokeMethod(innerFn, self, context) { var state = GenStateSuspendedStart; return function invoke(method, arg) { if (state === GenStateExecuting) { throw new Error("Generator is already running"); } if (state === GenStateCompleted) { if (method === "throw") { throw arg; } return doneResult(); } context.method = method; context.arg = arg; while (true) { var delegate = context.delegate; if (delegate) { var delegateResult = maybeInvokeDelegate(delegate, context); if (delegateResult) { if (delegateResult === ContinueSentinel) continue; return delegateResult; } } if (context.method === "next") { context.sent = context._sent = context.arg; } else if (context.method === "throw") { if (state === GenStateSuspendedStart) { state = GenStateCompleted; throw context.arg; } context.dispatchException(context.arg); } else if (context.method === "return") { context.abrupt("return", context.arg); } state = GenStateExecuting; var record = tryCatch(innerFn, self, context); if (record.type === "normal") { state = context.done ? GenStateCompleted : GenStateSuspendedYield; if (record.arg === ContinueSentinel) { continue; } return { value: record.arg, done: context.done }; } else if (record.type === "throw") { state = GenStateCompleted; context.method = "throw"; context.arg = record.arg; } } }; } function maybeInvokeDelegate(delegate, context) { var method = delegate.iterator[context.method]; if (method === undefined$1) { context.delegate = null; if (context.method === "throw") { if (delegate.iterator["return"]) { context.method = "return"; context.arg = undefined$1; maybeInvokeDelegate(delegate, context); if (context.method === "throw") { return ContinueSentinel; } } context.method = "throw"; context.arg = new TypeError("The iterator does not provide a 'throw' method"); } return ContinueSentinel; } var record = tryCatch(method, delegate.iterator, context.arg); if (record.type === "throw") { context.method = "throw"; context.arg = record.arg; context.delegate = null; return ContinueSentinel; } var info = record.arg; if (!info) { context.method = "throw"; context.arg = new TypeError("iterator result is not an object"); context.delegate = null; return ContinueSentinel; } if (info.done) { context[delegate.resultName] = info.value; context.next = delegate.nextLoc; if (context.method !== "return") { context.method = "next"; context.arg = undefined$1; } } else { return info; } context.delegate = null; return ContinueSentinel; } defineIteratorMethods(Gp); define(Gp, toStringTagSymbol, "Generator"); define(Gp, iteratorSymbol, function () { return this; }); define(Gp, "toString", function () { return "[object Generator]"; }); function pushTryEntry(locs) { var entry = { tryLoc: locs[0] }; if (1 in locs) { entry.catchLoc = locs[1]; } if (2 in locs) { entry.finallyLoc = locs[2]; entry.afterLoc = locs[3]; } this.tryEntries.push(entry); } function resetTryEntry(entry) { var record = entry.completion || {}; record.type = "normal"; delete record.arg; entry.completion = record; } function Context(tryLocsList) { this.tryEntries = [{ tryLoc: "root" }]; tryLocsList.forEach(pushTryEntry, this); this.reset(true); } exports.keys = function (object) { var keys = []; for (var key in object) { keys.push(key); } keys.reverse(); return function next() { while (keys.length) { var key = keys.pop(); if (key in object) { next.value = key; next.done = false; return next; } } next.done = true; return next; }; }; function values(iterable) { if (iterable) { var iteratorMethod = iterable[iteratorSymbol]; if (iteratorMethod) { return iteratorMethod.call(iterable); } if (typeof iterable.next === "function") { return iterable; } if (!isNaN(iterable.length)) { var i = -1, next = function next() { while (++i < iterable.length) { if (hasOwn.call(iterable, i)) { next.value = iterable[i]; next.done = false; return next; } } next.value = undefined$1; next.done = true; return next; }; return next.next = next; } } return { next: doneResult }; } exports.values = values; function doneResult() { return { value: undefined$1, done: true }; } Context.prototype = { constructor: Context, reset: function reset(skipTempReset) { this.prev = 0; this.next = 0; this.sent = this._sent = undefined$1; this.done = false; this.delegate = null; this.method = "next"; this.arg = undefined$1; this.tryEntries.forEach(resetTryEntry); if (!skipTempReset) { for (var name in this) { if (name.charAt(0) === "t" && hasOwn.call(this, name) && !isNaN(+name.slice(1))) { this[name] = undefined$1; } } } }, stop: function stop() { this.done = true; var rootEntry = this.tryEntries[0]; var rootRecord = rootEntry.completion; if (rootRecord.type === "throw") { throw rootRecord.arg; } return this.rval; }, dispatchException: function dispatchException(exception) { if (this.done) { throw exception; } var context = this; function handle(loc, caught) { record.type = "throw"; record.arg = exception; context.next = loc; if (caught) { context.method = "next"; context.arg = undefined$1; } return !!caught; } for (var i = this.tryEntries.length - 1; i >= 0; --i) { var entry = this.tryEntries[i]; var record = entry.completion; if (entry.tryLoc === "root") { return handle("end"); } if (entry.tryLoc <= this.prev) { var hasCatch = hasOwn.call(entry, "catchLoc"); var hasFinally = hasOwn.call(entry, "finallyLoc"); if (hasCatch && hasFinally) { if (this.prev < entry.catchLoc) { return handle(entry.catchLoc, true); } else if (this.prev < entry.finallyLoc) { return handle(entry.finallyLoc); } } else if (hasCatch) { if (this.prev < entry.catchLoc) { return handle(entry.catchLoc, true); } } else if (hasFinally) { if (this.prev < entry.finallyLoc) { return handle(entry.finallyLoc); } } else { throw new Error("try statement without catch or finally"); } } } }, abrupt: function abrupt(type, arg) { for (var i = this.tryEntries.length - 1; i >= 0; --i) { var entry = this.tryEntries[i]; if (entry.tryLoc <= this.prev && hasOwn.call(entry, "finallyLoc") && this.prev < entry.finallyLoc) { var finallyEntry = entry; break; } } if (finallyEntry && (type === "break" || type === "continue") && finallyEntry.tryLoc <= arg && arg <= finallyEntry.finallyLoc) { finallyEntry = null; } var record = finallyEntry ? finallyEntry.completion : {}; record.type = type; record.arg = arg; if (finallyEntry) { this.method = "next"; this.next = finallyEntry.finallyLoc; return ContinueSentinel; } return this.complete(record); }, complete: function complete(record, afterLoc) { if (record.type === "throw") { throw record.arg; } if (record.type === "break" || record.type === "continue") { this.next = record.arg; } else if (record.type === "return") { this.rval = this.arg = record.arg; this.method = "return"; this.next = "end"; } else if (record.type === "normal" && afterLoc) { this.next = afterLoc; } return ContinueSentinel; }, finish: function finish(finallyLoc) { for (var i = this.tryEntries.length - 1; i >= 0; --i) { var entry = this.tryEntries[i]; if (entry.finallyLoc === finallyLoc) { this.complete(entry.completion, entry.afterLoc); resetTryEntry(entry); return ContinueSentinel; } } }, "catch": function _catch(tryLoc) { for (var i = this.tryEntries.length - 1; i >= 0; --i) { var entry = this.tryEntries[i]; if (entry.tryLoc === tryLoc) { var record = entry.completion; if (record.type === "throw") { var thrown = record.arg; resetTryEntry(entry); } return thrown; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(iterable, resultName, nextLoc) { this.delegate = { iterator: values(iterable), resultName: resultName, nextLoc: nextLoc }; if (this.method === "next") { this.arg = undefined$1; } return ContinueSentinel; } }; return exports; }( (typeof module === "undefined" ? "undefined" : _typeof(module)) === "object" ? module.exports : {}); try { regeneratorRuntime = runtime; } catch (accidentalStrictMode) { if ((typeof globalThis === "undefined" ? "undefined" : _typeof(globalThis)) === "object") { globalThis.regeneratorRuntime = runtime; } else { Function("r", "regeneratorRuntime = r")(runtime); } } var FifoSampleBuffer = function () { function FifoSampleBuffer() { _classCallCheck(this, FifoSampleBuffer); this._vector = new Float32Array(); this._position = 0; this._frameCount = 0; } _createClass(FifoSampleBuffer, [{ key: "vector", get: function get() { return this._vector; } }, { key: "position", get: function get() { return this._position; } }, { key: "startIndex", get: function get() { return this._position * 2; } }, { key: "frameCount", get: function get() { return this._frameCount; } }, { key: "endIndex", get: function get() { return (this._position + this._frameCount) * 2; } }, { key: "clear", value: function clear() { this.receive(this._frameCount); this.rewind(); } }, { key: "put", value: function put(numFrames) { this._frameCount += numFrames; } }, { key: "putSamples", value: function putSamples(samples, position) { var numFrames = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; position = position || 0; var sourceOffset = position * 2; if (!(numFrames >= 0)) { numFrames = (samples.length - sourceOffset) / 2; } var numSamples = numFrames * 2; this.ensureCapacity(numFrames + this._frameCount); var destOffset = this.endIndex; this.vector.set(samples.subarray(sourceOffset, sourceOffset + numSamples), destOffset); this._frameCount += numFrames; } }, { key: "putBuffer", value: function putBuffer(buffer, position) { var numFrames = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; position = position || 0; if (!(numFrames >= 0)) { numFrames = buffer.frameCount - position; } this.putSamples(buffer.vector, buffer.position + position, numFrames); } }, { key: "receive", value: function receive(numFrames) { if (!(numFrames >= 0) || numFrames > this._frameCount) { numFrames = this.frameCount; } this._frameCount -= numFrames; this._position += numFrames; } }, { key: "receiveSamples", value: function receiveSamples(output) { var numFrames = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; var numSamples = numFrames * 2; var sourceOffset = this.startIndex; output.set(this._vector.subarray(sourceOffset, sourceOffset + numSamples)); this.receive(numFrames); } }, { key: "extract", value: function extract(output) { var position = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; var numFrames = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; var sourceOffset = this.startIndex + position * 2; var numSamples = numFrames * 2; output.set(this._vector.subarray(sourceOffset, sourceOffset + numSamples)); } }, { key: "ensureCapacity", value: function ensureCapacity() { var numFrames = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; var minLength = parseInt(numFrames * 2); if (this._vector.length < minLength) { var newVector = new Float32Array(minLength); newVector.set(this._vector.subarray(this.startIndex, this.endIndex)); this._vector = newVector; this._position = 0; } else { this.rewind(); } } }, { key: "ensureAdditionalCapacity", value: function ensureAdditionalCapacity() { var numFrames = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; this.ensureCapacity(this._frameCount + numFrames); } }, { key: "rewind", value: function rewind() { if (this._position > 0) { this._vector.set(this._vector.subarray(this.startIndex, this.endIndex)); this._position = 0; } } }]); return FifoSampleBuffer; }(); var AbstractFifoSamplePipe = function () { function AbstractFifoSamplePipe(createBuffers) { _classCallCheck(this, AbstractFifoSamplePipe); if (createBuffers) { this._inputBuffer = new FifoSampleBuffer(); this._outputBuffer = new FifoSampleBuffer(); } else { this._inputBuffer = this._outputBuffer = null; } } _createClass(AbstractFifoSamplePipe, [{ key: "inputBuffer", get: function get() { return this._inputBuffer; }, set: function set(inputBuffer) { this._inputBuffer = inputBuffer; } }, { key: "outputBuffer", get: function get() { return this._outputBuffer; }, set: function set(outputBuffer) { this._outputBuffer = outputBuffer; } }, { key: "clear", value: function clear() { this._inputBuffer.clear(); this._outputBuffer.clear(); } }]); return AbstractFifoSamplePipe; }(); var RateTransposer = function (_AbstractFifoSamplePi) { _inherits(RateTransposer, _AbstractFifoSamplePi); var _super = _createSuper(RateTransposer); function RateTransposer(createBuffers) { var _this; _classCallCheck(this, RateTransposer); _this = _super.call(this, createBuffers); _this.reset(); _this._rate = 1; return _this; } _createClass(RateTransposer, [{ key: "rate", set: function set(rate) { this._rate = rate; } }, { key: "reset", value: function reset() { this.slopeCount = 0; this.prevSampleL = 0; this.prevSampleR = 0; } }, { key: "clone", value: function clone() { var result = new RateTransposer(); result.rate = this._rate; return result; } }, { key: "process", value: function process() { var numFrames = this._inputBuffer.frameCount; this._outputBuffer.ensureAdditionalCapacity(numFrames / this._rate + 1); var numFramesOutput = this.transpose(numFrames); this._inputBuffer.receive(); this._outputBuffer.put(numFramesOutput); } }, { key: "transpose", value: function transpose() { var numFrames = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; if (numFrames === 0) { return 0; } var src = this._inputBuffer.vector; var srcOffset = this._inputBuffer.startIndex; var dest = this._outputBuffer.vector; var destOffset = this._outputBuffer.endIndex; var used = 0; var i = 0; while (this.slopeCount < 1.0) { dest[destOffset + 2 * i] = (1.0 - this.slopeCount) * this.prevSampleL + this.slopeCount * src[srcOffset]; dest[destOffset + 2 * i + 1] = (1.0 - this.slopeCount) * this.prevSampleR + this.slopeCount * src[srcOffset + 1]; i = i + 1; this.slopeCount += this._rate; } this.slopeCount -= 1.0; if (numFrames !== 1) { out: while (true) { while (this.slopeCount > 1.0) { this.slopeCount -= 1.0; used = used + 1; if (used >= numFrames - 1) { break out; } } var srcIndex = srcOffset + 2 * used; dest[destOffset + 2 * i] = (1.0 - this.slopeCount) * src[srcIndex] + this.slopeCount * src[srcIndex + 2]; dest[destOffset + 2 * i + 1] = (1.0 - this.slopeCount) * src[srcIndex + 1] + this.slopeCount * src[srcIndex + 3]; i = i + 1; this.slopeCount += this._rate; } } this.prevSampleL = src[srcOffset + 2 * numFrames - 2]; this.prevSampleR = src[srcOffset + 2 * numFrames - 1]; return i; } }]); return RateTransposer; }(AbstractFifoSamplePipe); var FilterSupport = function () { function FilterSupport(pipe) { _classCallCheck(this, FilterSupport); this._pipe = pipe; } _createClass(FilterSupport, [{ key: "pipe", get: function get() { return this._pipe; } }, { key: "inputBuffer", get: function get() { return this._pipe.inputBuffer; } }, { key: "outputBuffer", get: function get() { return this._pipe.outputBuffer; } }, { key: "fillInputBuffer", value: function fillInputBuffer() { throw new Error('fillInputBuffer() not overridden'); } }, { key: "fillOutputBuffer", value: function fillOutputBuffer() { var numFrames = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; while (this.outputBuffer.frameCount < numFrames) { var numInputFrames = 8192 * 2 - this.inputBuffer.frameCount; this.fillInputBuffer(numInputFrames); if (this.inputBuffer.frameCount < 8192 * 2) { break; } this._pipe.process(); } } }, { key: "clear", value: function clear() { this._pipe.clear(); } }]); return FilterSupport; }(); var noop = function noop() { return; }; var SimpleFilter = function (_FilterSupport) { _inherits(SimpleFilter, _FilterSupport); var _super2 = _createSuper(SimpleFilter); function SimpleFilter(sourceSound, pipe) { var _this2; var callback = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : noop; _classCallCheck(this, SimpleFilter); _this2 = _super2.call(this, pipe); _this2.callback = callback; _this2.sourceSound = sourceSound; _this2.historyBufferSize = 22050; _this2._sourcePosition = 0; _this2.outputBufferPosition = 0; _this2._position = 0; return _this2; } _createClass(SimpleFilter, [{ key: "position", get: function get() { return this._position; }, set: function set(position) { if (position > this._position) { throw new RangeError('New position may not be greater than current position'); } var newOutputBufferPosition = this.outputBufferPosition - (this._position - position); if (newOutputBufferPosition < 0) { throw new RangeError('New position falls outside of history buffer'); } this.outputBufferPosition = newOutputBufferPosition; this._position = position; } }, { key: "sourcePosition", get: function get() { return this._sourcePosition; }, set: function set(sourcePosition) { this.clear(); this._sourcePosition = sourcePosition; } }, { key: "onEnd", value: function onEnd() { this.callback(); } }, { key: "fillInputBuffer", value: function fillInputBuffer() { var numFrames = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; var samples = new Float32Array(numFrames * 2); var numFramesExtracted = this.sourceSound.extract(samples, numFrames, this._sourcePosition); this._sourcePosition += numFramesExtracted; this.inputBuffer.putSamples(samples, 0, numFramesExtracted); } }, { key: "extract", value: function extract(target) { var numFrames = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; this.fillOutputBuffer(this.outputBufferPosition + numFrames); var numFramesExtracted = Math.min(numFrames, this.outputBuffer.frameCount - this.outputBufferPosition); this.outputBuffer.extract(target, this.outputBufferPosition, numFramesExtracted); var currentFrames = this.outputBufferPosition + numFramesExtracted; this.outputBufferPosition = Math.min(this.historyBufferSize, currentFrames); this.outputBuffer.receive(Math.max(currentFrames - this.historyBufferSize, 0)); this._position += numFramesExtracted; return numFramesExtracted; } }, { key: "handleSampleData", value: function handleSampleData(event) { this.extract(event.data, 4096); } }, { key: "clear", value: function clear() { _get(_getPrototypeOf(SimpleFilter.prototype), "clear", this).call(this); this.outputBufferPosition = 0; } }]); return SimpleFilter; }(FilterSupport); var USE_AUTO_SEQUENCE_LEN = 0; var DEFAULT_SEQUENCE_MS = USE_AUTO_SEQUENCE_LEN; var USE_AUTO_SEEKWINDOW_LEN = 0; var DEFAULT_SEEKWINDOW_MS = USE_AUTO_SEEKWINDOW_LEN; var DEFAULT_OVERLAP_MS = 8; var _SCAN_OFFSETS = [[124, 186, 248, 310, 372, 434, 496, 558, 620, 682, 744, 806, 868, 930, 992, 1054, 1116, 1178, 1240, 1302, 1364, 1426, 1488, 0], [-100, -75, -50, -25, 25, 50, 75, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [-20, -15, -10, -5, 5, 10, 15, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [-4, -3, -2, -1, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]; var AUTOSEQ_TEMPO_LOW = 0.5; var AUTOSEQ_TEMPO_TOP = 2.0; var AUTOSEQ_AT_MIN = 125.0; var AUTOSEQ_AT_MAX = 50.0; var AUTOSEQ_K = (AUTOSEQ_AT_MAX - AUTOSEQ_AT_MIN) / (AUTOSEQ_TEMPO_TOP - AUTOSEQ_TEMPO_LOW); var AUTOSEQ_C = AUTOSEQ_AT_MIN - AUTOSEQ_K * AUTOSEQ_TEMPO_LOW; var AUTOSEEK_AT_MIN = 25.0; var AUTOSEEK_AT_MAX = 15.0; var AUTOSEEK_K = (AUTOSEEK_AT_MAX - AUTOSEEK_AT_MIN) / (AUTOSEQ_TEMPO_TOP - AUTOSEQ_TEMPO_LOW); var AUTOSEEK_C = AUTOSEEK_AT_MIN - AUTOSEEK_K * AUTOSEQ_TEMPO_LOW; var Stretch = function (_AbstractFifoSamplePi2) { _inherits(Stretch, _AbstractFifoSamplePi2); var _super3 = _createSuper(Stretch); function Stretch(createBuffers) { var _this3; _classCallCheck(this, Stretch); _this3 = _super3.call(this, createBuffers); _this3._quickSeek = true; _this3.midBufferDirty = false; _this3.midBuffer = null; _this3.overlapLength = 0; _this3.autoSeqSetting = true; _this3.autoSeekSetting = true; _this3._tempo = 1; _this3.setParameters(44100, DEFAULT_SEQUENCE_MS, DEFAULT_SEEKWINDOW_MS, DEFAULT_OVERLAP_MS); return _this3; } _createClass(Stretch, [{ key: "clear", value: function clear() { _get(_getPrototypeOf(Stretch.prototype), "clear", this).call(this); this.clearMidBuffer(); } }, { key: "clearMidBuffer", value: function clearMidBuffer() { if (this.midBufferDirty) { this.midBufferDirty = false; this.midBuffer = null; } } }, { key: "setParameters", value: function setParameters(sampleRate, sequenceMs, seekWindowMs, overlapMs) { if (sampleRate > 0) { this.sampleRate = sampleRate; } if (overlapMs > 0) { this.overlapMs = overlapMs; } if (sequenceMs > 0) { this.sequenceMs = sequenceMs; this.autoSeqSetting = false; } else { this.autoSeqSetting = true; } if (seekWindowMs > 0) { this.seekWindowMs = seekWindowMs; this.autoSeekSetting = false; } else { this.autoSeekSetting = true; } this.calculateSequenceParameters(); this.calculateOverlapLength(this.overlapMs); this.tempo = this._tempo; } }, { key: "tempo", get: function get() { return this._tempo; }, set: function set(newTempo) { var intskip; this._tempo = newTempo; this.calculateSequenceParameters(); this.nominalSkip = this._tempo * (this.seekWindowLength - this.overlapLength); this.skipFract = 0; intskip = Math.floor(this.nominalSkip + 0.5); this.sampleReq = Math.max(intskip + this.overlapLength, this.seekWindowLength) + this.seekLength; } }, { key: "inputChunkSize", get: function get() { return this.sampleReq; } }, { key: "outputChunkSize", get: function get() { return this.overlapLength + Math.max(0, this.seekWindowLength - 2 * this.overlapLength); } }, { key: "calculateOverlapLength", value: function calculateOverlapLength() { var overlapInMsec = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; var newOvl; newOvl = this.sampleRate * overlapInMsec / 1000; newOvl = newOvl < 16 ? 16 : newOvl; newOvl -= newOvl % 8; this.overlapLength = newOvl; this.refMidBuffer = new Float32Array(this.overlapLength * 2); this.midBuffer = new Float32Array(this.overlapLength * 2); } }, { key: "checkLimits", value: function checkLimits(x, mi, ma) { return x < mi ? mi : x > ma ? ma : x; } }, { key: "calculateSequenceParameters", value: function calculateSequenceParameters() { var seq; var seek; if (this.autoSeqSetting) { seq = AUTOSEQ_C + AUTOSEQ_K * this._tempo; seq = this.checkLimits(seq, AUTOSEQ_AT_MAX, AUTOSEQ_AT_MIN); this.sequenceMs = Math.floor(seq + 0.5); } if (this.autoSeekSetting) { seek = AUTOSEEK_C + AUTOSEEK_K * this._tempo; seek = this.checkLimits(seek, AUTOSEEK_AT_MAX, AUTOSEEK_AT_MIN); this.seekWindowMs = Math.floor(seek + 0.5); } this.seekWindowLength = Math.floor(this.sampleRate * this.sequenceMs / 1000); this.seekLength = Math.floor(this.sampleRate * this.seekWindowMs / 1000); } }, { key: "quickSeek", set: function set(enable) { this._quickSeek = enable; } }, { key: "clone", value: function clone() { var result = new Stretch(); result.tempo = this._tempo; result.setParameters(this.sampleRate, this.sequenceMs, this.seekWindowMs, this.overlapMs); return result; } }, { key: "seekBestOverlapPosition", value: function seekBestOverlapPosition() { return this._quickSeek ? this.seekBestOverlapPositionStereoQuick() : this.seekBestOverlapPositionStereo(); } }, { key: "seekBestOverlapPositionStereo", value: function seekBestOverlapPositionStereo() { var bestOffset; var bestCorrelation; var correlation; var i = 0; this.preCalculateCorrelationReferenceStereo(); bestOffset = 0; bestCorrelation = Number.MIN_VALUE; for (; i < this.seekLength; i = i + 1) { correlation = this.calculateCrossCorrelationStereo(2 * i, this.refMidBuffer); if (correlation > bestCorrelation) { bestCorrelation = correlation; bestOffset = i; } } return bestOffset; } }, { key: "seekBestOverlapPositionStereoQuick", value: function seekBestOverlapPositionStereoQuick() { var bestOffset; var bestCorrelation; var correlation; var scanCount = 0; var correlationOffset; var tempOffset; this.preCalculateCorrelationReferenceStereo(); bestCorrelation = Number.MIN_VALUE; bestOffset = 0; correlationOffset = 0; tempOffset = 0; for (; scanCount < 4; scanCount = scanCount + 1) { var j = 0; while (_SCAN_OFFSETS[scanCount][j]) { tempOffset = correlationOffset + _SCAN_OFFSETS[scanCount][j]; if (tempOffset >= this.seekLength) { break; } correlation = this.calculateCrossCorrelationStereo(2 * tempOffset, this.refMidBuffer); if (correlation > bestCorrelation) { bestCorrelation = correlation; bestOffset = tempOffset; } j = j + 1; } correlationOffset = bestOffset; } return bestOffset; } }, { key: "preCalculateCorrelationReferenceStereo", value: function preCalculateCorrelationReferenceStereo() { var i = 0; var context; var temp; for (; i < this.overlapLength; i = i + 1) { temp = i * (this.overlapLength - i); context = i * 2; this.refMidBuffer[context] = this.midBuffer[context] * temp; this.refMidBuffer[context + 1] = this.midBuffer[context + 1] * temp; } } }, { key: "calculateCrossCorrelationStereo", value: function calculateCrossCorrelationStereo(mixingPosition, compare) { var mixing = this._inputBuffer.vector; mixingPosition += this._inputBuffer.startIndex; var correlation = 0; var i = 2; var calcLength = 2 * this.overlapLength; var mixingOffset; for (; i < calcLength; i = i + 2) { mixingOffset = i + mixingPosition; correlation += mixing[mixingOffset] * compare[i] + mixing[mixingOffset + 1] * compare[i + 1]; } return correlation; } }, { key: "overlap", value: function overlap(overlapPosition) { this.overlapStereo(2 * overlapPosition); } }, { key: "overlapStereo", value: function overlapStereo(inputPosition) { var input = this._inputBuffer.vector; inputPosition += this._inputBuffer.startIndex; var output = this._outputBuffer.vector; var outputPosition = this._outputBuffer.endIndex; var i = 0; var context; var tempFrame; var frameScale = 1 / this.overlapLength; var fi; var inputOffset; var outputOffset; for (; i < this.overlapLength; i = i + 1) { tempFrame = (this.overlapLength - i) * frameScale; fi = i * frameScale; context = 2 * i; inputOffset = context + inputPosition; outputOffset = context + outputPosition; output[outputOffset + 0] = input[inputOffset + 0] * fi + this.midBuffer[context + 0] * tempFrame; output[outputOffset + 1] = input[inputOffset + 1] * fi + this.midBuffer[context + 1] * tempFrame; } } }, { key: "process", value: function process() { var offset; var temp; var overlapSkip; if (this.midBuffer === null) { if (this._inputBuffer.frameCount < this.overlapLength) { return; } this.midBuffer = new Float32Array(this.overlapLength * 2); this._inputBuffer.receiveSamples(this.midBuffer, this.overlapLength); } while (this._inputBuffer.frameCount >= this.sampleReq) { offset = this.seekBestOverlapPosition(); this._outputBuffer.ensureAdditionalCapacity(this.overlapLength); this.overlap(Math.floor(offset)); this._outputBuffer.put(this.overlapLength); temp = this.seekWindowLength - 2 * this.overlapLength; if (temp > 0) { this._outputBuffer.putBuffer(this._inputBuffer, offset + this.overlapLength, temp); } var start = this._inputBuffer.startIndex + 2 * (offset + this.seekWindowLength - this.overlapLength); this.midBuffer.set(this._inputBuffer.vector.subarray(start, start + 2 * this.overlapLength)); this.skipFract += this.nominalSkip; overlapSkip = Math.floor(this.skipFract); this.skipFract -= overlapSkip; this._inputBuffer.receive(overlapSkip); } } }]); return Stretch; }(AbstractFifoSamplePipe); var testFloatEqual = function testFloatEqual(a, b) { return (a > b ? a - b : b - a) > 1e-10; }; var SoundTouch = function () { function SoundTouch() { _classCallCheck(this, SoundTouch); this.transposer = new RateTransposer(false); this.stretch = new Stretch(false); this._inputBuffer = new FifoSampleBuffer(); this._intermediateBuffer = new FifoSampleBuffer(); this._outputBuffer = new FifoSampleBuffer(); this._rate = 0; this._tempo = 0; this.virtualPitch = 1.0; this.virtualRate = 1.0; this.virtualTempo = 1.0; this.calculateEffectiveRateAndTempo(); } _createClass(SoundTouch, [{ key: "clear", value: function clear() { this.transposer.clear(); this.stretch.clear(); } }, { key: "clone", value: function clone() { var result = new SoundTouch(); result.rate = this.rate; result.tempo = this.tempo; return result; } }, { key: "rate", get: function get() { return this._rate; }, set: function set(rate) { this.virtualRate = rate; this.calculateEffectiveRateAndTempo(); } }, { key: "rateChange", set: function set(rateChange) { this._rate = 1.0 + 0.01 * rateChange; } }, { key: "tempo", get: function get() { return this._tempo; }, set: function set(tempo) { this.virtualTempo = tempo; this.calculateEffectiveRateAndTempo(); } }, { key: "tempoChange", set: function set(tempoChange) { this.tempo = 1.0 + 0.01 * tempoChange; } }, { key: "pitch", set: function set(pitch) { this.virtualPitch = pitch; this.calculateEffectiveRateAndTempo(); } }, { key: "pitchOctaves", set: function set(pitchOctaves) { this.pitch = Math.exp(0.69314718056 * pitchOctaves); this.calculateEffectiveRateAndTempo(); } }, { key: "pitchSemitones", set: function set(pitchSemitones) { this.pitchOctaves = pitchSemitones / 12.0; } }, { key: "inputBuffer", get: function get() { return this._inputBuffer; } }, { key: "outputBuffer", get: function get() { return this._outputBuffer; } }, { key: "calculateEffectiveRateAndTempo", value: function calculateEffectiveRateAndTempo() { var previousTempo = this._tempo; var previousRate = this._rate; this._tempo = this.virtualTempo / this.virtualPitch; this._rate = this.virtualRate * this.virtualPitch; if (testFloatEqual(this._tempo, previousTempo)) { this.stretch.tempo = this._tempo; } if (testFloatEqual(this._rate, previousRate)) { this.transposer.rate = this._rate; } if (this._rate > 1.0) { if (this._outputBuffer != this.transposer.outputBuffer) { this.stretch.inputBuffer = this._inputBuffer; this.stretch.outputBuffer = this._intermediateBuffer; this.transposer.inputBuffer = this._intermediateBuffer; this.transposer.outputBuffer = this._outputBuffer; } } else { if (this._outputBuffer != this.stretch.outputBuffer) { this.transposer.inputBuffer = this._inputBuffer; this.transposer.outputBuffer = this._intermediateBuffer; this.stretch.inputBuffer = this._intermediateBuffer; this.stretch.outputBuffer = this._outputBuffer; } } } }, { key: "process", value: function process() { if (this._rate > 1.0) { this.stretch.process(); this.transposer.process(); } else { this.transposer.process(); this.stretch.process(); } } }]); return SoundTouch; }(); var WebAudioBufferSource = function () { function WebAudioBufferSource(buffer) { _classCallCheck(this, WebAudioBufferSource); this.buffer = buffer; this._position = 0; } _createCl