diff --git "a/src/app/static/assets/js/wavesurfer.js" "b/src/app/static/assets/js/wavesurfer.js" new file mode 100644--- /dev/null +++ "b/src/app/static/assets/js/wavesurfer.js" @@ -0,0 +1,9401 @@ +/*! + * wavesurfer.js 5.1.0 (2021-06-20) + * https://wavesurfer-js.org + * @license BSD-3-Clause + */ +(function webpackUniversalModuleDefinition(root, factory) { + if (typeof exports === "object" && typeof module === "object") + module.exports = factory(); + else if (typeof define === "function" && define.amd) + define("WaveSurfer", [], factory); + else if (typeof exports === "object") exports["WaveSurfer"] = factory(); + else root["WaveSurfer"] = factory(); +})(this, function () { + return /******/ (() => { + // webpackBootstrap + /******/ var __webpack_modules__ = { + /***/ "./src/drawer.canvasentry.js": + /*!***********************************!*\ + !*** ./src/drawer.canvasentry.js ***! + \***********************************/ + /***/ (module, exports, __webpack_require__) => { + "use strict"; + + Object.defineProperty(exports, "__esModule", { + value: true, + }); + exports.default = void 0; + + var _style = _interopRequireDefault( + __webpack_require__( + /*! ./util/style */ "./src/util/style.js" + ) + ); + + var _getId = _interopRequireDefault( + __webpack_require__( + /*! ./util/get-id */ "./src/util/get-id.js" + ) + ); + + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { default: 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); + return Constructor; + } + + /** + * The `CanvasEntry` class represents an element consisting of a wave `canvas` + * and an (optional) progress wave `canvas`. + * + * The `MultiCanvas` renderer uses one or more `CanvasEntry` instances to + * render a waveform, depending on the zoom level. + */ + var CanvasEntry = /*#__PURE__*/ (function () { + function CanvasEntry() { + _classCallCheck(this, CanvasEntry); + + /** + * The wave node + * + * @type {HTMLCanvasElement} + */ + this.wave = null; + /** + * The wave canvas rendering context + * + * @type {CanvasRenderingContext2D} + */ + + this.waveCtx = null; + /** + * The (optional) progress wave node + * + * @type {HTMLCanvasElement} + */ + + this.progress = null; + /** + * The (optional) progress wave canvas rendering context + * + * @type {CanvasRenderingContext2D} + */ + + this.progressCtx = null; + /** + * Start of the area the canvas should render, between 0 and 1 + * + * @type {number} + */ + + this.start = 0; + /** + * End of the area the canvas should render, between 0 and 1 + * + * @type {number} + */ + + this.end = 1; + /** + * Unique identifier for this entry + * + * @type {string} + */ + + this.id = (0, _getId.default)( + typeof this.constructor.name !== "undefined" + ? this.constructor.name.toLowerCase() + "_" + : "canvasentry_" + ); + /** + * Canvas 2d context attributes + * + * @type {object} + */ + + this.canvasContextAttributes = {}; + } + /** + * Store the wave canvas element and create the 2D rendering context + * + * @param {HTMLCanvasElement} element The wave `canvas` element. + */ + + _createClass(CanvasEntry, [ + { + key: "initWave", + value: function initWave(element) { + this.wave = element; + this.waveCtx = this.wave.getContext( + "2d", + this.canvasContextAttributes + ); + }, + /** + * Store the progress wave canvas element and create the 2D rendering + * context + * + * @param {HTMLCanvasElement} element The progress wave `canvas` element. + */ + }, + { + key: "initProgress", + value: function initProgress(element) { + this.progress = element; + this.progressCtx = this.progress.getContext( + "2d", + this.canvasContextAttributes + ); + }, + /** + * Update the dimensions + * + * @param {number} elementWidth Width of the entry + * @param {number} totalWidth Total width of the multi canvas renderer + * @param {number} width The new width of the element + * @param {number} height The new height of the element + */ + }, + { + key: "updateDimensions", + value: function updateDimensions( + elementWidth, + totalWidth, + width, + height + ) { + // where the canvas starts and ends in the waveform, represented as a + // decimal between 0 and 1 + this.start = + this.wave.offsetLeft / totalWidth || 0; + this.end = + this.start + elementWidth / totalWidth; // set wave canvas dimensions + + this.wave.width = width; + this.wave.height = height; + var elementSize = { + width: elementWidth + "px", + }; + (0, _style.default)(this.wave, elementSize); + + if (this.hasProgressCanvas) { + // set progress canvas dimensions + this.progress.width = width; + this.progress.height = height; + (0, _style.default)( + this.progress, + elementSize + ); + } + }, + /** + * Clear the wave and progress rendering contexts + */ + }, + { + key: "clearWave", + value: function clearWave() { + // wave + this.waveCtx.clearRect( + 0, + 0, + this.waveCtx.canvas.width, + this.waveCtx.canvas.height + ); // progress + + if (this.hasProgressCanvas) { + this.progressCtx.clearRect( + 0, + 0, + this.progressCtx.canvas.width, + this.progressCtx.canvas.height + ); + } + }, + /** + * Set the fill styles for wave and progress + * + * @param {string} waveColor Fill color for the wave canvas + * @param {?string} progressColor Fill color for the progress canvas + */ + }, + { + key: "setFillStyles", + value: function setFillStyles( + waveColor, + progressColor + ) { + this.waveCtx.fillStyle = waveColor; + + if (this.hasProgressCanvas) { + this.progressCtx.fillStyle = + progressColor; + } + }, + /** + * Set the canvas transforms for wave and progress + * + * @param {boolean} vertical Whether to render vertically + */ + }, + { + key: "applyCanvasTransforms", + value: function applyCanvasTransforms( + vertical + ) { + if (vertical) { + // Reflect the waveform across the line y = -x + this.waveCtx.setTransform( + 0, + 1, + 1, + 0, + 0, + 0 + ); + + if (this.hasProgressCanvas) { + this.progressCtx.setTransform( + 0, + 1, + 1, + 0, + 0, + 0 + ); + } + } + }, + /** + * Draw a rectangle for wave and progress + * + * @param {number} x X start position + * @param {number} y Y start position + * @param {number} width Width of the rectangle + * @param {number} height Height of the rectangle + * @param {number} radius Radius of the rectangle + */ + }, + { + key: "fillRects", + value: function fillRects( + x, + y, + width, + height, + radius + ) { + this.fillRectToContext( + this.waveCtx, + x, + y, + width, + height, + radius + ); + + if (this.hasProgressCanvas) { + this.fillRectToContext( + this.progressCtx, + x, + y, + width, + height, + radius + ); + } + }, + /** + * Draw the actual rectangle on a `canvas` element + * + * @param {CanvasRenderingContext2D} ctx Rendering context of target canvas + * @param {number} x X start position + * @param {number} y Y start position + * @param {number} width Width of the rectangle + * @param {number} height Height of the rectangle + * @param {number} radius Radius of the rectangle + */ + }, + { + key: "fillRectToContext", + value: function fillRectToContext( + ctx, + x, + y, + width, + height, + radius + ) { + if (!ctx) { + return; + } + + if (radius) { + this.drawRoundedRect( + ctx, + x, + y, + width, + height, + radius + ); + } else { + ctx.fillRect(x, y, width, height); + } + }, + /** + * Draw a rounded rectangle on Canvas + * + * @param {CanvasRenderingContext2D} ctx Canvas context + * @param {number} x X-position of the rectangle + * @param {number} y Y-position of the rectangle + * @param {number} width Width of the rectangle + * @param {number} height Height of the rectangle + * @param {number} radius Radius of the rectangle + * + * @return {void} + * @example drawRoundedRect(ctx, 50, 50, 5, 10, 3) + */ + }, + { + key: "drawRoundedRect", + value: function drawRoundedRect( + ctx, + x, + y, + width, + height, + radius + ) { + if (height === 0) { + return; + } // peaks are float values from -1 to 1. Use absolute height values in + // order to correctly calculate rounded rectangle coordinates + + if (height < 0) { + height *= -1; + y -= height; + } + + ctx.beginPath(); + ctx.moveTo(x + radius, y); + ctx.lineTo(x + width - radius, y); + ctx.quadraticCurveTo( + x + width, + y, + x + width, + y + radius + ); + ctx.lineTo(x + width, y + height - radius); + ctx.quadraticCurveTo( + x + width, + y + height, + x + width - radius, + y + height + ); + ctx.lineTo(x + radius, y + height); + ctx.quadraticCurveTo( + x, + y + height, + x, + y + height - radius + ); + ctx.lineTo(x, y + radius); + ctx.quadraticCurveTo(x, y, x + radius, y); + ctx.closePath(); + ctx.fill(); + }, + /** + * Render the actual wave and progress lines + * + * @param {number[]} peaks Array with peaks data + * @param {number} absmax Maximum peak value (absolute) + * @param {number} halfH Half the height of the waveform + * @param {number} offsetY Offset to the top + * @param {number} start The x-offset of the beginning of the area that + * should be rendered + * @param {number} end The x-offset of the end of the area that + * should be rendered + */ + }, + { + key: "drawLines", + value: function drawLines( + peaks, + absmax, + halfH, + offsetY, + start, + end + ) { + this.drawLineToContext( + this.waveCtx, + peaks, + absmax, + halfH, + offsetY, + start, + end + ); + + if (this.hasProgressCanvas) { + this.drawLineToContext( + this.progressCtx, + peaks, + absmax, + halfH, + offsetY, + start, + end + ); + } + }, + /** + * Render the actual waveform line on a `canvas` element + * + * @param {CanvasRenderingContext2D} ctx Rendering context of target canvas + * @param {number[]} peaks Array with peaks data + * @param {number} absmax Maximum peak value (absolute) + * @param {number} halfH Half the height of the waveform + * @param {number} offsetY Offset to the top + * @param {number} start The x-offset of the beginning of the area that + * should be rendered + * @param {number} end The x-offset of the end of the area that + * should be rendered + */ + }, + { + key: "drawLineToContext", + value: function drawLineToContext( + ctx, + peaks, + absmax, + halfH, + offsetY, + start, + end + ) { + if (!ctx) { + return; + } + + var length = peaks.length / 2; + var first = Math.round(length * this.start); // use one more peak value to make sure we join peaks at ends -- unless, + // of course, this is the last canvas + + var last = + Math.round(length * this.end) + 1; + var canvasStart = first; + var canvasEnd = last; + var scale = + this.wave.width / + (canvasEnd - canvasStart - 1); // optimization + + var halfOffset = halfH + offsetY; + var absmaxHalf = absmax / halfH; + ctx.beginPath(); + ctx.moveTo( + (canvasStart - first) * scale, + halfOffset + ); + ctx.lineTo( + (canvasStart - first) * scale, + halfOffset - + Math.round( + (peaks[2 * canvasStart] || 0) / + absmaxHalf + ) + ); + var i, peak, h; + + for (i = canvasStart; i < canvasEnd; i++) { + peak = peaks[2 * i] || 0; + h = Math.round(peak / absmaxHalf); + ctx.lineTo( + (i - first) * scale + + this.halfPixel, + halfOffset - h + ); + } // draw the bottom edge going backwards, to make a single + // closed hull to fill + + var j = canvasEnd - 1; + + for (j; j >= canvasStart; j--) { + peak = peaks[2 * j + 1] || 0; + h = Math.round(peak / absmaxHalf); + ctx.lineTo( + (j - first) * scale + + this.halfPixel, + halfOffset - h + ); + } + + ctx.lineTo( + (canvasStart - first) * scale, + halfOffset - + Math.round( + (peaks[2 * canvasStart + 1] || + 0) / absmaxHalf + ) + ); + ctx.closePath(); + ctx.fill(); + }, + /** + * Destroys this entry + */ + }, + { + key: "destroy", + value: function destroy() { + this.waveCtx = null; + this.wave = null; + this.progressCtx = null; + this.progress = null; + }, + /** + * Return image data of the wave `canvas` element + * + * When using a `type` of `'blob'`, this will return a `Promise` that + * resolves with a `Blob` instance. + * + * @param {string} format='image/png' An optional value of a format type. + * @param {number} quality=0.92 An optional value between 0 and 1. + * @param {string} type='dataURL' Either 'dataURL' or 'blob'. + * @return {string|Promise} When using the default `'dataURL'` `type` this + * returns a data URL. When using the `'blob'` `type` this returns a + * `Promise` that resolves with a `Blob` instance. + */ + }, + { + key: "getImage", + value: function getImage( + format, + quality, + type + ) { + var _this = this; + + if (type === "blob") { + return new Promise(function (resolve) { + _this.wave.toBlob( + resolve, + format, + quality + ); + }); + } else if (type === "dataURL") { + return this.wave.toDataURL( + format, + quality + ); + } + }, + }, + ]); + + return CanvasEntry; + })(); + + exports.default = CanvasEntry; + module.exports = exports.default; + + /***/ + }, + + /***/ "./src/drawer.js": + /*!***********************!*\ + !*** ./src/drawer.js ***! + \***********************/ + /***/ (module, exports, __webpack_require__) => { + "use strict"; + + function _typeof(obj) { + "@babel/helpers - typeof"; + if ( + typeof Symbol === "function" && + typeof Symbol.iterator === "symbol" + ) { + _typeof = function _typeof(obj) { + return typeof obj; + }; + } else { + _typeof = function _typeof(obj) { + return obj && + typeof Symbol === "function" && + obj.constructor === Symbol && + obj !== Symbol.prototype + ? "symbol" + : typeof obj; + }; + } + return _typeof(obj); + } + + Object.defineProperty(exports, "__esModule", { + value: true, + }); + exports.default = void 0; + + var util = _interopRequireWildcard( + __webpack_require__(/*! ./util */ "./src/util/index.js") + ); + + function _getRequireWildcardCache(nodeInterop) { + if (typeof WeakMap !== "function") return null; + var cacheBabelInterop = new WeakMap(); + var cacheNodeInterop = new WeakMap(); + return (_getRequireWildcardCache = + function _getRequireWildcardCache(nodeInterop) { + return nodeInterop + ? cacheNodeInterop + : cacheBabelInterop; + })(nodeInterop); + } + + function _interopRequireWildcard(obj, nodeInterop) { + if (!nodeInterop && obj && obj.__esModule) { + return obj; + } + if ( + obj === null || + (_typeof(obj) !== "object" && + typeof obj !== "function") + ) { + return { default: obj }; + } + var cache = _getRequireWildcardCache(nodeInterop); + if (cache && cache.has(obj)) { + return cache.get(obj); + } + var newObj = {}; + var hasPropertyDescriptor = + Object.defineProperty && + Object.getOwnPropertyDescriptor; + for (var key in obj) { + if ( + key !== "default" && + Object.prototype.hasOwnProperty.call(obj, key) + ) { + var desc = hasPropertyDescriptor + ? Object.getOwnPropertyDescriptor(obj, key) + : null; + if (desc && (desc.get || desc.set)) { + Object.defineProperty(newObj, key, desc); + } else { + newObj[key] = obj[key]; + } + } + } + newObj.default = obj; + if (cache) { + cache.set(obj, newObj); + } + return newObj; + } + + 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); + 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, + }, + } + ); + if (superClass) _setPrototypeOf(subClass, superClass); + } + + function _setPrototypeOf(o, p) { + _setPrototypeOf = + Object.setPrototypeOf || + function _setPrototypeOf(o, p) { + o.__proto__ = p; + return o; + }; + return _setPrototypeOf(o, p); + } + + 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 _possibleConstructorReturn(self, call) { + if ( + call && + (_typeof(call) === "object" || + typeof call === "function") + ) { + return call; + } + return _assertThisInitialized(self); + } + + function _assertThisInitialized(self) { + if (self === void 0) { + throw new ReferenceError( + "this hasn't been initialised - super() hasn't been called" + ); + } + return self; + } + + 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 _getPrototypeOf(o) { + _getPrototypeOf = Object.setPrototypeOf + ? Object.getPrototypeOf + : function _getPrototypeOf(o) { + return ( + o.__proto__ || Object.getPrototypeOf(o) + ); + }; + return _getPrototypeOf(o); + } + + /** + * Parent class for renderers + * + * @extends {Observer} + */ + var Drawer = /*#__PURE__*/ (function (_util$Observer) { + _inherits(Drawer, _util$Observer); + + var _super = _createSuper(Drawer); + + /** + * @param {HTMLElement} container The container node of the wavesurfer instance + * @param {WavesurferParams} params The wavesurfer initialisation options + */ + function Drawer(container, params) { + var _this; + + _classCallCheck(this, Drawer); + + _this = _super.call(this); + _this.container = util.withOrientation( + container, + params.vertical + ); + /** + * @type {WavesurferParams} + */ + + _this.params = params; + /** + * The width of the renderer + * @type {number} + */ + + _this.width = 0; + /** + * The height of the renderer + * @type {number} + */ + + _this.height = + params.height * _this.params.pixelRatio; + _this.lastPos = 0; + /** + * The `` element which is added to the container + * @type {HTMLElement} + */ + + _this.wrapper = null; + return _this; + } + /** + * Alias of `util.style` + * + * @param {HTMLElement} el The element that the styles will be applied to + * @param {Object} styles The map of propName: attribute, both are used as-is + * @return {HTMLElement} el + */ + + _createClass(Drawer, [ + { + key: "style", + value: function style(el, styles) { + return util.style(el, styles); + }, + /** + * Create the wrapper `` element, style it and set up the events for + * interaction + */ + }, + { + key: "createWrapper", + value: function createWrapper() { + this.wrapper = util.withOrientation( + this.container.appendChild( + document.createElement("wave") + ), + this.params.vertical + ); + this.style(this.wrapper, { + display: "block", + position: "relative", + userSelect: "none", + webkitUserSelect: "none", + height: this.params.height + "px", + }); + + if ( + this.params.fillParent || + this.params.scrollParent + ) { + this.style(this.wrapper, { + width: "100%", + overflowX: this.params.hideScrollbar + ? "hidden" + : "auto", + overflowY: "hidden", + }); + } + + this.setupWrapperEvents(); + }, + /** + * Handle click event + * + * @param {Event} e Click event + * @param {?boolean} noPrevent Set to true to not call `e.preventDefault()` + * @return {number} Playback position from 0 to 1 + */ + }, + { + key: "handleEvent", + value: function handleEvent(e, noPrevent) { + !noPrevent && e.preventDefault(); + var clientX = util.withOrientation( + e.targetTouches + ? e.targetTouches[0] + : e, + this.params.vertical + ).clientX; + var bbox = + this.wrapper.getBoundingClientRect(); + var nominalWidth = this.width; + var parentWidth = this.getWidth(); + var progressPixels = this.getProgressPixels( + bbox, + clientX + ); + var progress; + + if ( + !this.params.fillParent && + nominalWidth < parentWidth + ) { + progress = + progressPixels * + (this.params.pixelRatio / + nominalWidth) || 0; + } else { + progress = + (progressPixels + + this.wrapper.scrollLeft) / + this.wrapper.scrollWidth || 0; + } + + return util.clamp(progress, 0, 1); + }, + }, + { + key: "getProgressPixels", + value: function getProgressPixels( + wrapperBbox, + clientX + ) { + if (this.params.rtl) { + return wrapperBbox.right - clientX; + } else { + return clientX - wrapperBbox.left; + } + }, + }, + { + key: "setupWrapperEvents", + value: function setupWrapperEvents() { + var _this2 = this; + + this.wrapper.addEventListener( + "click", + function (e) { + var orientedEvent = + util.withOrientation( + e, + _this2.params.vertical + ); + var scrollbarHeight = + _this2.wrapper.offsetHeight - + _this2.wrapper.clientHeight; + + if (scrollbarHeight !== 0) { + // scrollbar is visible. Check if click was on it + var bbox = + _this2.wrapper.getBoundingClientRect(); + + if ( + orientedEvent.clientY >= + bbox.bottom - + scrollbarHeight + ) { + // ignore mousedown as it was on the scrollbar + return; + } + } + + if (_this2.params.interact) { + _this2.fireEvent( + "click", + e, + _this2.handleEvent(e) + ); + } + } + ); + this.wrapper.addEventListener( + "dblclick", + function (e) { + if (_this2.params.interact) { + _this2.fireEvent( + "dblclick", + e, + _this2.handleEvent(e) + ); + } + } + ); + this.wrapper.addEventListener( + "scroll", + function (e) { + return _this2.fireEvent( + "scroll", + e + ); + } + ); + }, + /** + * Draw peaks on the canvas + * + * @param {number[]|Number.} peaks Can also be an array of arrays + * for split channel rendering + * @param {number} length The width of the area that should be drawn + * @param {number} start The x-offset of the beginning of the area that + * should be rendered + * @param {number} end The x-offset of the end of the area that should be + * rendered + */ + }, + { + key: "drawPeaks", + value: function drawPeaks( + peaks, + length, + start, + end + ) { + if (!this.setWidth(length)) { + this.clearWave(); + } + + this.params.barWidth + ? this.drawBars(peaks, 0, start, end) + : this.drawWave(peaks, 0, start, end); + }, + /** + * Scroll to the beginning + */ + }, + { + key: "resetScroll", + value: function resetScroll() { + if (this.wrapper !== null) { + this.wrapper.scrollLeft = 0; + } + }, + /** + * Recenter the view-port at a certain percent of the waveform + * + * @param {number} percent Value from 0 to 1 on the waveform + */ + }, + { + key: "recenter", + value: function recenter(percent) { + var position = + this.wrapper.scrollWidth * percent; + this.recenterOnPosition(position, true); + }, + /** + * Recenter the view-port on a position, either scroll there immediately or + * in steps of 5 pixels + * + * @param {number} position X-offset in pixels + * @param {boolean} immediate Set to true to immediately scroll somewhere + */ + }, + { + key: "recenterOnPosition", + value: function recenterOnPosition( + position, + immediate + ) { + var scrollLeft = this.wrapper.scrollLeft; + var half = ~~(this.wrapper.clientWidth / 2); + var maxScroll = + this.wrapper.scrollWidth - + this.wrapper.clientWidth; + var target = position - half; + var offset = target - scrollLeft; + + if (maxScroll == 0) { + // no need to continue if scrollbar is not there + return; + } // if the cursor is currently visible... + + if ( + !immediate && + -half <= offset && + offset < half + ) { + // set rate at which waveform is centered + var rate = this.params.autoCenterRate; // make rate depend on width of view and length of waveform + + rate /= half; + rate *= maxScroll; + offset = Math.max( + -rate, + Math.min(rate, offset) + ); + target = scrollLeft + offset; + } // limit target to valid range (0 to maxScroll) + + target = Math.max( + 0, + Math.min(maxScroll, target) + ); // no use attempting to scroll if we're not moving + + if (target != scrollLeft) { + this.wrapper.scrollLeft = target; + } + }, + /** + * Get the current scroll position in pixels + * + * @return {number} Horizontal scroll position in pixels + */ + }, + { + key: "getScrollX", + value: function getScrollX() { + var x = 0; + + if (this.wrapper) { + var pixelRatio = this.params.pixelRatio; + x = Math.round( + this.wrapper.scrollLeft * pixelRatio + ); // In cases of elastic scroll (safari with mouse wheel) you can + // scroll beyond the limits of the container + // Calculate and floor the scrollable extent to make sure an out + // of bounds value is not returned + // Ticket #1312 + + if (this.params.scrollParent) { + var maxScroll = ~~( + this.wrapper.scrollWidth * + pixelRatio - + this.getWidth() + ); + x = Math.min( + maxScroll, + Math.max(0, x) + ); + } + } + + return x; + }, + /** + * Get the width of the container + * + * @return {number} The width of the container + */ + }, + { + key: "getWidth", + value: function getWidth() { + return Math.round( + this.container.clientWidth * + this.params.pixelRatio + ); + }, + /** + * Set the width of the container + * + * @param {number} width The new width of the container + * @return {boolean} Whether the width of the container was updated or not + */ + }, + { + key: "setWidth", + value: function setWidth(width) { + if (this.width == width) { + return false; + } + + this.width = width; + + if ( + this.params.fillParent || + this.params.scrollParent + ) { + this.style(this.wrapper, { + width: "", + }); + } else { + var newWidth = + ~~( + this.width / + this.params.pixelRatio + ) + "px"; + this.style(this.wrapper, { + width: newWidth, + }); + } + + this.updateSize(); + return true; + }, + /** + * Set the height of the container + * + * @param {number} height The new height of the container. + * @return {boolean} Whether the height of the container was updated or not + */ + }, + { + key: "setHeight", + value: function setHeight(height) { + if (height == this.height) { + return false; + } + + this.height = height; + this.style(this.wrapper, { + height: + ~~( + this.height / + this.params.pixelRatio + ) + "px", + }); + this.updateSize(); + return true; + }, + /** + * Called by wavesurfer when progress should be rendered + * + * @param {number} progress From 0 to 1 + */ + }, + { + key: "progress", + value: function progress(_progress) { + var minPxDelta = 1 / this.params.pixelRatio; + var pos = + Math.round(_progress * this.width) * + minPxDelta; + + if ( + pos < this.lastPos || + pos - this.lastPos >= minPxDelta + ) { + this.lastPos = pos; + + if ( + this.params.scrollParent && + this.params.autoCenter + ) { + var newPos = ~~( + this.wrapper.scrollWidth * + _progress + ); + this.recenterOnPosition( + newPos, + this.params + .autoCenterImmediately + ); + } + + this.updateProgress(pos); + } + }, + /** + * This is called when wavesurfer is destroyed + */ + }, + { + key: "destroy", + value: function destroy() { + this.unAll(); + + if (this.wrapper) { + if ( + this.wrapper.parentNode == + this.container.domElement + ) { + this.container.removeChild( + this.wrapper.domElement + ); + } + + this.wrapper = null; + } + }, + /* Renderer-specific methods */ + + /** + * Called after cursor related params have changed. + * + * @abstract + */ + }, + { + key: "updateCursor", + value: function updateCursor() {}, + /** + * Called when the size of the container changes so the renderer can adjust + * + * @abstract + */ + }, + { + key: "updateSize", + value: function updateSize() {}, + /** + * Draw a waveform with bars + * + * @abstract + * @param {number[]|Number.} peaks Can also be an array of arrays for split channel + * rendering + * @param {number} channelIndex The index of the current channel. Normally + * should be 0 + * @param {number} start The x-offset of the beginning of the area that + * should be rendered + * @param {number} end The x-offset of the end of the area that should be + * rendered + */ + }, + { + key: "drawBars", + value: function drawBars( + peaks, + channelIndex, + start, + end + ) {}, + /** + * Draw a waveform + * + * @abstract + * @param {number[]|Number.} peaks Can also be an array of arrays for split channel + * rendering + * @param {number} channelIndex The index of the current channel. Normally + * should be 0 + * @param {number} start The x-offset of the beginning of the area that + * should be rendered + * @param {number} end The x-offset of the end of the area that should be + * rendered + */ + }, + { + key: "drawWave", + value: function drawWave( + peaks, + channelIndex, + start, + end + ) {}, + /** + * Clear the waveform + * + * @abstract + */ + }, + { + key: "clearWave", + value: function clearWave() {}, + /** + * Render the new progress + * + * @abstract + * @param {number} position X-Offset of progress position in pixels + */ + }, + { + key: "updateProgress", + value: function updateProgress(position) {}, + }, + ]); + + return Drawer; + })(util.Observer); + + exports.default = Drawer; + module.exports = exports.default; + + /***/ + }, + + /***/ "./src/drawer.multicanvas.js": + /*!***********************************!*\ + !*** ./src/drawer.multicanvas.js ***! + \***********************************/ + /***/ (module, exports, __webpack_require__) => { + "use strict"; + + function _typeof(obj) { + "@babel/helpers - typeof"; + if ( + typeof Symbol === "function" && + typeof Symbol.iterator === "symbol" + ) { + _typeof = function _typeof(obj) { + return typeof obj; + }; + } else { + _typeof = function _typeof(obj) { + return obj && + typeof Symbol === "function" && + obj.constructor === Symbol && + obj !== Symbol.prototype + ? "symbol" + : typeof obj; + }; + } + return _typeof(obj); + } + + Object.defineProperty(exports, "__esModule", { + value: true, + }); + exports.default = void 0; + + var _drawer = _interopRequireDefault( + __webpack_require__(/*! ./drawer */ "./src/drawer.js") + ); + + var util = _interopRequireWildcard( + __webpack_require__(/*! ./util */ "./src/util/index.js") + ); + + var _drawer2 = _interopRequireDefault( + __webpack_require__( + /*! ./drawer.canvasentry */ "./src/drawer.canvasentry.js" + ) + ); + + function _getRequireWildcardCache(nodeInterop) { + if (typeof WeakMap !== "function") return null; + var cacheBabelInterop = new WeakMap(); + var cacheNodeInterop = new WeakMap(); + return (_getRequireWildcardCache = + function _getRequireWildcardCache(nodeInterop) { + return nodeInterop + ? cacheNodeInterop + : cacheBabelInterop; + })(nodeInterop); + } + + function _interopRequireWildcard(obj, nodeInterop) { + if (!nodeInterop && obj && obj.__esModule) { + return obj; + } + if ( + obj === null || + (_typeof(obj) !== "object" && + typeof obj !== "function") + ) { + return { default: obj }; + } + var cache = _getRequireWildcardCache(nodeInterop); + if (cache && cache.has(obj)) { + return cache.get(obj); + } + var newObj = {}; + var hasPropertyDescriptor = + Object.defineProperty && + Object.getOwnPropertyDescriptor; + for (var key in obj) { + if ( + key !== "default" && + Object.prototype.hasOwnProperty.call(obj, key) + ) { + var desc = hasPropertyDescriptor + ? Object.getOwnPropertyDescriptor(obj, key) + : null; + if (desc && (desc.get || desc.set)) { + Object.defineProperty(newObj, key, desc); + } else { + newObj[key] = obj[key]; + } + } + } + newObj.default = obj; + if (cache) { + cache.set(obj, newObj); + } + return newObj; + } + + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { default: 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); + 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, + }, + } + ); + if (superClass) _setPrototypeOf(subClass, superClass); + } + + function _setPrototypeOf(o, p) { + _setPrototypeOf = + Object.setPrototypeOf || + function _setPrototypeOf(o, p) { + o.__proto__ = p; + return o; + }; + return _setPrototypeOf(o, p); + } + + 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 _possibleConstructorReturn(self, call) { + if ( + call && + (_typeof(call) === "object" || + typeof call === "function") + ) { + return call; + } + return _assertThisInitialized(self); + } + + function _assertThisInitialized(self) { + if (self === void 0) { + throw new ReferenceError( + "this hasn't been initialised - super() hasn't been called" + ); + } + return self; + } + + 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 _getPrototypeOf(o) { + _getPrototypeOf = Object.setPrototypeOf + ? Object.getPrototypeOf + : function _getPrototypeOf(o) { + return ( + o.__proto__ || Object.getPrototypeOf(o) + ); + }; + return _getPrototypeOf(o); + } + + /** + * MultiCanvas renderer for wavesurfer. Is currently the default and sole + * builtin renderer. + * + * A `MultiCanvas` consists of one or more `CanvasEntry` instances, depending + * on the zoom level. + */ + var MultiCanvas = /*#__PURE__*/ (function (_Drawer) { + _inherits(MultiCanvas, _Drawer); + + var _super = _createSuper(MultiCanvas); + + /** + * @param {HTMLElement} container The container node of the wavesurfer instance + * @param {WavesurferParams} params The wavesurfer initialisation options + */ + function MultiCanvas(container, params) { + var _this; + + _classCallCheck(this, MultiCanvas); + + _this = _super.call(this, container, params); + /** + * @type {number} + */ + + _this.maxCanvasWidth = params.maxCanvasWidth; + /** + * @type {number} + */ + + _this.maxCanvasElementWidth = Math.round( + params.maxCanvasWidth / params.pixelRatio + ); + /** + * Whether or not the progress wave is rendered. If the `waveColor` + * and `progressColor` are the same color it is not. + * + * @type {boolean} + */ + + _this.hasProgressCanvas = + params.waveColor != params.progressColor; + /** + * @type {number} + */ + + _this.halfPixel = 0.5 / params.pixelRatio; + /** + * List of `CanvasEntry` instances. + * + * @type {Array} + */ + + _this.canvases = []; + /** + * @type {HTMLElement} + */ + + _this.progressWave = null; + /** + * Class used to generate entries. + * + * @type {function} + */ + + _this.EntryClass = _drawer2.default; + /** + * Canvas 2d context attributes. + * + * @type {object} + */ + + _this.canvasContextAttributes = + params.drawingContextAttributes; + /** + * Overlap added between entries to prevent vertical white stripes + * between `canvas` elements. + * + * @type {number} + */ + + _this.overlap = + 2 * Math.ceil(params.pixelRatio / 2); + /** + * The radius of the wave bars. Makes bars rounded + * + * @type {number} + */ + + _this.barRadius = params.barRadius || 0; + /** + * Whether to render the waveform vertically. Defaults to false. + * + * @type {boolean} + */ + + _this.vertical = params.vertical; + return _this; + } + /** + * Initialize the drawer + */ + + _createClass(MultiCanvas, [ + { + key: "init", + value: function init() { + this.createWrapper(); + this.createElements(); + }, + /** + * Create the canvas elements and style them + * + */ + }, + { + key: "createElements", + value: function createElements() { + this.progressWave = util.withOrientation( + this.wrapper.appendChild( + document.createElement("wave") + ), + this.params.vertical + ); + this.style(this.progressWave, { + position: "absolute", + zIndex: 3, + left: 0, + top: 0, + bottom: 0, + overflow: "hidden", + width: "0", + display: "none", + boxSizing: "border-box", + borderRightStyle: "solid", + pointerEvents: "none", + }); + this.addCanvas(); + this.updateCursor(); + }, + /** + * Update cursor style + */ + }, + { + key: "updateCursor", + value: function updateCursor() { + this.style(this.progressWave, { + borderRightWidth: + this.params.cursorWidth + "px", + borderRightColor: + this.params.cursorColor, + }); + }, + /** + * Adjust to the updated size by adding or removing canvases + */ + }, + { + key: "updateSize", + value: function updateSize() { + var _this2 = this; + + var totalWidth = Math.round( + this.width / this.params.pixelRatio + ); + var requiredCanvases = Math.ceil( + totalWidth / + (this.maxCanvasElementWidth + + this.overlap) + ); // add required canvases + + while ( + this.canvases.length < requiredCanvases + ) { + this.addCanvas(); + } // remove older existing canvases, if any + + while ( + this.canvases.length > requiredCanvases + ) { + this.removeCanvas(); + } + + var canvasWidth = + this.maxCanvasWidth + this.overlap; + var lastCanvas = this.canvases.length - 1; + this.canvases.forEach(function (entry, i) { + if (i == lastCanvas) { + canvasWidth = + _this2.width - + _this2.maxCanvasWidth * + lastCanvas; + } + + _this2.updateDimensions( + entry, + canvasWidth, + _this2.height + ); + + entry.clearWave(); + }); + }, + /** + * Add a canvas to the canvas list + * + */ + }, + { + key: "addCanvas", + value: function addCanvas() { + var entry = new this.EntryClass(); + entry.canvasContextAttributes = + this.canvasContextAttributes; + entry.hasProgressCanvas = + this.hasProgressCanvas; + entry.halfPixel = this.halfPixel; + var leftOffset = + this.maxCanvasElementWidth * + this.canvases.length; // wave + + var wave = util.withOrientation( + this.wrapper.appendChild( + document.createElement("canvas") + ), + this.params.vertical + ); + this.style(wave, { + position: "absolute", + zIndex: 2, + left: leftOffset + "px", + top: 0, + bottom: 0, + height: "100%", + pointerEvents: "none", + }); + entry.initWave(wave); // progress + + if (this.hasProgressCanvas) { + var progress = util.withOrientation( + this.progressWave.appendChild( + document.createElement("canvas") + ), + this.params.vertical + ); + this.style(progress, { + position: "absolute", + left: leftOffset + "px", + top: 0, + bottom: 0, + height: "100%", + }); + entry.initProgress(progress); + } + + this.canvases.push(entry); + }, + /** + * Pop single canvas from the list + * + */ + }, + { + key: "removeCanvas", + value: function removeCanvas() { + var lastEntry = + this.canvases[this.canvases.length - 1]; // wave + + lastEntry.wave.parentElement.removeChild( + lastEntry.wave.domElement + ); // progress + + if (this.hasProgressCanvas) { + lastEntry.progress.parentElement.removeChild( + lastEntry.progress.domElement + ); + } // cleanup + + if (lastEntry) { + lastEntry.destroy(); + lastEntry = null; + } + + this.canvases.pop(); + }, + /** + * Update the dimensions of a canvas element + * + * @param {CanvasEntry} entry Target entry + * @param {number} width The new width of the element + * @param {number} height The new height of the element + */ + }, + { + key: "updateDimensions", + value: function updateDimensions( + entry, + width, + height + ) { + var elementWidth = Math.round( + width / this.params.pixelRatio + ); + var totalWidth = Math.round( + this.width / this.params.pixelRatio + ); // update canvas dimensions + + entry.updateDimensions( + elementWidth, + totalWidth, + width, + height + ); // style element + + this.style(this.progressWave, { + display: "block", + }); + }, + /** + * Clear the whole multi-canvas + */ + }, + { + key: "clearWave", + value: function clearWave() { + var _this3 = this; + + util.frame(function () { + _this3.canvases.forEach(function ( + entry + ) { + return entry.clearWave(); + }); + })(); + }, + /** + * Draw a waveform with bars + * + * @param {number[]|Number.} peaks Can also be an array of arrays + * for split channel rendering + * @param {number} channelIndex The index of the current channel. Normally + * should be 0. Must be an integer. + * @param {number} start The x-offset of the beginning of the area that + * should be rendered + * @param {number} end The x-offset of the end of the area that should be + * rendered + * @returns {void} + */ + }, + { + key: "drawBars", + value: function drawBars( + peaks, + channelIndex, + start, + end + ) { + var _this4 = this; + + return this.prepareDraw( + peaks, + channelIndex, + start, + end, + function (_ref) { + var absmax = _ref.absmax, + hasMinVals = _ref.hasMinVals, + height = _ref.height, + offsetY = _ref.offsetY, + halfH = _ref.halfH, + peaks = _ref.peaks, + ch = _ref.channelIndex; + + // if drawBars was called within ws.empty we don't pass a start and + // don't want anything to happen + if (start === undefined) { + return; + } // Skip every other value if there are negatives. + + var peakIndexScale = hasMinVals + ? 2 + : 1; + var length = + peaks.length / peakIndexScale; + var bar = + _this4.params.barWidth * + _this4.params.pixelRatio; + var gap = + _this4.params.barGap === null + ? Math.max( + _this4.params + .pixelRatio, + ~~(bar / 2) + ) + : Math.max( + _this4.params + .pixelRatio, + _this4.params.barGap * + _this4.params + .pixelRatio + ); + var step = bar + gap; + var scale = length / _this4.width; + var first = start; + var last = end; + var i = first; + + for (i; i < last; i += step) { + var peak = + peaks[ + Math.floor( + i * + scale * + peakIndexScale + ) + ] || 0; + var h = Math.round( + (peak / absmax) * halfH + ); + /* in case of silences, allow the user to specify that we + * always draw *something* (normally a 1px high bar) */ + + if ( + h == 0 && + _this4.params.barMinHeight + ) { + h = + _this4.params + .barMinHeight; + } + + _this4.fillRect( + i + _this4.halfPixel, + halfH - h + offsetY, + bar + _this4.halfPixel, + h * 2, + _this4.barRadius, + ch + ); + } + } + ); + }, + /** + * Draw a waveform + * + * @param {number[]|Number.} peaks Can also be an array of arrays + * for split channel rendering + * @param {number} channelIndex The index of the current channel. Normally + * should be 0 + * @param {number?} start The x-offset of the beginning of the area that + * should be rendered (If this isn't set only a flat line is rendered) + * @param {number?} end The x-offset of the end of the area that should be + * rendered + * @returns {void} + */ + }, + { + key: "drawWave", + value: function drawWave( + peaks, + channelIndex, + start, + end + ) { + var _this5 = this; + + return this.prepareDraw( + peaks, + channelIndex, + start, + end, + function (_ref2) { + var absmax = _ref2.absmax, + hasMinVals = _ref2.hasMinVals, + height = _ref2.height, + offsetY = _ref2.offsetY, + halfH = _ref2.halfH, + peaks = _ref2.peaks, + channelIndex = + _ref2.channelIndex; + + if (!hasMinVals) { + var reflectedPeaks = []; + var len = peaks.length; + var i = 0; + + for (i; i < len; i++) { + reflectedPeaks[2 * i] = + peaks[i]; + reflectedPeaks[2 * i + 1] = + -peaks[i]; + } + + peaks = reflectedPeaks; + } // if drawWave was called within ws.empty we don't pass a start and + // end and simply want a flat line + + if (start !== undefined) { + _this5.drawLine( + peaks, + absmax, + halfH, + offsetY, + start, + end, + channelIndex + ); + } // always draw a median line + + _this5.fillRect( + 0, + halfH + + offsetY - + _this5.halfPixel, + _this5.width, + _this5.halfPixel, + _this5.barRadius, + channelIndex + ); + } + ); + }, + /** + * Tell the canvas entries to render their portion of the waveform + * + * @param {number[]} peaks Peaks data + * @param {number} absmax Maximum peak value (absolute) + * @param {number} halfH Half the height of the waveform + * @param {number} offsetY Offset to the top + * @param {number} start The x-offset of the beginning of the area that + * should be rendered + * @param {number} end The x-offset of the end of the area that + * should be rendered + * @param {channelIndex} channelIndex The channel index of the line drawn + */ + }, + { + key: "drawLine", + value: function drawLine( + peaks, + absmax, + halfH, + offsetY, + start, + end, + channelIndex + ) { + var _this6 = this; + + var _ref3 = + this.params.splitChannelsOptions + .channelColors[channelIndex] || + {}, + waveColor = _ref3.waveColor, + progressColor = _ref3.progressColor; + + this.canvases.forEach(function (entry, i) { + _this6.setFillStyles( + entry, + waveColor, + progressColor + ); + + _this6.applyCanvasTransforms( + entry, + _this6.params.vertical + ); + + entry.drawLines( + peaks, + absmax, + halfH, + offsetY, + start, + end + ); + }); + }, + /** + * Draw a rectangle on the multi-canvas + * + * @param {number} x X-position of the rectangle + * @param {number} y Y-position of the rectangle + * @param {number} width Width of the rectangle + * @param {number} height Height of the rectangle + * @param {number} radius Radius of the rectangle + * @param {channelIndex} channelIndex The channel index of the bar drawn + */ + }, + { + key: "fillRect", + value: function fillRect( + x, + y, + width, + height, + radius, + channelIndex + ) { + var startCanvas = Math.floor( + x / this.maxCanvasWidth + ); + var endCanvas = Math.min( + Math.ceil( + (x + width) / this.maxCanvasWidth + ) + 1, + this.canvases.length + ); + var i = startCanvas; + + for (i; i < endCanvas; i++) { + var entry = this.canvases[i]; + var leftOffset = + i * this.maxCanvasWidth; + var intersection = { + x1: Math.max( + x, + i * this.maxCanvasWidth + ), + y1: y, + x2: Math.min( + x + width, + i * this.maxCanvasWidth + + entry.wave.width + ), + y2: y + height, + }; + + if (intersection.x1 < intersection.x2) { + var _ref4 = + this.params + .splitChannelsOptions + .channelColors[ + channelIndex + ] || {}, + waveColor = _ref4.waveColor, + progressColor = + _ref4.progressColor; + + this.setFillStyles( + entry, + waveColor, + progressColor + ); + this.applyCanvasTransforms( + entry, + this.params.vertical + ); + entry.fillRects( + intersection.x1 - leftOffset, + intersection.y1, + intersection.x2 - + intersection.x1, + intersection.y2 - + intersection.y1, + radius + ); + } + } + }, + /** + * Returns whether to hide the channel from being drawn based on params. + * + * @param {number} channelIndex The index of the current channel. + * @returns {bool} True to hide the channel, false to draw. + */ + }, + { + key: "hideChannel", + value: function hideChannel(channelIndex) { + return ( + this.params.splitChannels && + this.params.splitChannelsOptions.filterChannels.includes( + channelIndex + ) + ); + }, + /** + * Performs preparation tasks and calculations which are shared by `drawBars` + * and `drawWave` + * + * @param {number[]|Number.} peaks Can also be an array of arrays for + * split channel rendering + * @param {number} channelIndex The index of the current channel. Normally + * should be 0 + * @param {number?} start The x-offset of the beginning of the area that + * should be rendered. If this isn't set only a flat line is rendered + * @param {number?} end The x-offset of the end of the area that should be + * rendered + * @param {function} fn The render function to call, e.g. `drawWave` + * @param {number} drawIndex The index of the current channel after filtering. + * @param {number?} normalizedMax Maximum modulation value across channels for use with relativeNormalization. Ignored when undefined + * @returns {void} + */ + }, + { + key: "prepareDraw", + value: function prepareDraw( + peaks, + channelIndex, + start, + end, + fn, + drawIndex, + normalizedMax + ) { + var _this7 = this; + + return util.frame(function () { + // Split channels and call this function with the channelIndex set + if (peaks[0] instanceof Array) { + var channels = peaks; + + if (_this7.params.splitChannels) { + var filteredChannels = + channels.filter(function ( + c, + i + ) { + return !_this7.hideChannel( + i + ); + }); + + if ( + !_this7.params + .splitChannelsOptions + .overlay + ) { + _this7.setHeight( + Math.max( + filteredChannels.length, + 1 + ) * + _this7.params + .height * + _this7.params + .pixelRatio + ); + } + + var overallAbsMax; + + if ( + _this7.params + .splitChannelsOptions && + _this7.params + .splitChannelsOptions + .relativeNormalization + ) { + // calculate maximum peak across channels to use for normalization + overallAbsMax = util.max( + channels.map(function ( + channelPeaks + ) { + return util.absMax( + channelPeaks + ); + }) + ); + } + + return channels.forEach( + function (channelPeaks, i) { + return _this7.prepareDraw( + channelPeaks, + i, + start, + end, + fn, + filteredChannels.indexOf( + channelPeaks + ), + overallAbsMax + ); + } + ); + } + + peaks = channels[0]; + } // Return and do not draw channel peaks if hidden. + + if (_this7.hideChannel(channelIndex)) { + return; + } // calculate maximum modulation value, either from the barHeight + // parameter or if normalize=true from the largest value in the peak + // set + + var absmax = + 1 / _this7.params.barHeight; + + if (_this7.params.normalize) { + absmax = + normalizedMax === undefined + ? util.absMax(peaks) + : normalizedMax; + } // Bar wave draws the bottom only as a reflection of the top, + // so we don't need negative values + + var hasMinVals = [].some.call( + peaks, + function (val) { + return val < 0; + } + ); + var height = + _this7.params.height * + _this7.params.pixelRatio; + var halfH = height / 2; + var offsetY = height * drawIndex || 0; // Override offsetY if overlay is true + + if ( + _this7.params + .splitChannelsOptions && + _this7.params.splitChannelsOptions + .overlay + ) { + offsetY = 0; + } + + return fn({ + absmax: absmax, + hasMinVals: hasMinVals, + height: height, + offsetY: offsetY, + halfH: halfH, + peaks: peaks, + channelIndex: channelIndex, + }); + })(); + }, + /** + * Set the fill styles for a certain entry (wave and progress) + * + * @param {CanvasEntry} entry Target entry + * @param {string} waveColor Wave color to draw this entry + * @param {string} progressColor Progress color to draw this entry + */ + }, + { + key: "setFillStyles", + value: function setFillStyles(entry) { + var waveColor = + arguments.length > 1 && + arguments[1] !== undefined + ? arguments[1] + : this.params.waveColor; + var progressColor = + arguments.length > 2 && + arguments[2] !== undefined + ? arguments[2] + : this.params.progressColor; + entry.setFillStyles( + waveColor, + progressColor + ); + }, + /** + * Set the canvas transforms for a certain entry (wave and progress) + * + * @param {CanvasEntry} entry Target entry + * @param {boolean} vertical Whether to render the waveform vertically + */ + }, + { + key: "applyCanvasTransforms", + value: function applyCanvasTransforms(entry) { + var vertical = + arguments.length > 1 && + arguments[1] !== undefined + ? arguments[1] + : false; + entry.applyCanvasTransforms(vertical); + }, + /** + * Return image data of the multi-canvas + * + * When using a `type` of `'blob'`, this will return a `Promise`. + * + * @param {string} format='image/png' An optional value of a format type. + * @param {number} quality=0.92 An optional value between 0 and 1. + * @param {string} type='dataURL' Either 'dataURL' or 'blob'. + * @return {string|string[]|Promise} When using the default `'dataURL'` + * `type` this returns a single data URL or an array of data URLs, + * one for each canvas. When using the `'blob'` `type` this returns a + * `Promise` that resolves with an array of `Blob` instances, one for each + * canvas. + */ + }, + { + key: "getImage", + value: function getImage( + format, + quality, + type + ) { + if (type === "blob") { + return Promise.all( + this.canvases.map(function (entry) { + return entry.getImage( + format, + quality, + type + ); + }) + ); + } else if (type === "dataURL") { + var images = this.canvases.map( + function (entry) { + return entry.getImage( + format, + quality, + type + ); + } + ); + return images.length > 1 + ? images + : images[0]; + } + }, + /** + * Render the new progress + * + * @param {number} position X-offset of progress position in pixels + */ + }, + { + key: "updateProgress", + value: function updateProgress(position) { + this.style(this.progressWave, { + width: position + "px", + }); + }, + }, + ]); + + return MultiCanvas; + })(_drawer.default); + + exports.default = MultiCanvas; + module.exports = exports.default; + + /***/ + }, + + /***/ "./src/mediaelement-webaudio.js": + /*!**************************************!*\ + !*** ./src/mediaelement-webaudio.js ***! + \**************************************/ + /***/ (module, exports, __webpack_require__) => { + "use strict"; + + function _typeof(obj) { + "@babel/helpers - typeof"; + if ( + typeof Symbol === "function" && + typeof Symbol.iterator === "symbol" + ) { + _typeof = function _typeof(obj) { + return typeof obj; + }; + } else { + _typeof = function _typeof(obj) { + return obj && + typeof Symbol === "function" && + obj.constructor === Symbol && + obj !== Symbol.prototype + ? "symbol" + : typeof obj; + }; + } + return _typeof(obj); + } + + Object.defineProperty(exports, "__esModule", { + value: true, + }); + exports.default = void 0; + + var _mediaelement = _interopRequireDefault( + __webpack_require__( + /*! ./mediaelement */ "./src/mediaelement.js" + ) + ); + + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { default: 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); + return Constructor; + } + + function _get(target, property, receiver) { + 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(receiver); + } + return desc.value; + }; + } + return _get(target, property, receiver || target); + } + + function _superPropBase(object, property) { + while ( + !Object.prototype.hasOwnProperty.call( + object, + property + ) + ) { + object = _getPrototypeOf(object); + if (object === null) break; + } + return object; + } + + 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, + }, + } + ); + if (superClass) _setPrototypeOf(subClass, superClass); + } + + function _setPrototypeOf(o, p) { + _setPrototypeOf = + Object.setPrototypeOf || + function _setPrototypeOf(o, p) { + o.__proto__ = p; + return o; + }; + return _setPrototypeOf(o, p); + } + + 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 _possibleConstructorReturn(self, call) { + if ( + call && + (_typeof(call) === "object" || + typeof call === "function") + ) { + return call; + } + return _assertThisInitialized(self); + } + + function _assertThisInitialized(self) { + if (self === void 0) { + throw new ReferenceError( + "this hasn't been initialised - super() hasn't been called" + ); + } + return self; + } + + 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 _getPrototypeOf(o) { + _getPrototypeOf = Object.setPrototypeOf + ? Object.getPrototypeOf + : function _getPrototypeOf(o) { + return ( + o.__proto__ || Object.getPrototypeOf(o) + ); + }; + return _getPrototypeOf(o); + } + + /** + * MediaElementWebAudio backend: load audio via an HTML5 audio tag, but playback with the WebAudio API. + * The advantage here is that the html5