PageSourceSearch

https://www.arkona-russia.com/wp-content/plugins/wolf-visual-compo…/lib/wavesurfer/wavesurfer.js?ver=3.3.3

js arkona-russia.com collected 2026-10-02 12:48:38 UTC 192,842 bytes, 6,237 lines download raw bytes

vendor: 4,174 bytes, lines 1-103
1/*!
2 * wavesurfer.js 3.3.3 (2020-04-16)
3 * https://github.com/katspaugh/wavesurfer.js
4 * @license BSD-3-Clause
5 */
6(function webpackUniversalModuleDefinition(root, factory) {
7  if(typeof exports === 'object' && typeof module === 'object')
8    module.exports = factory();
9  else if(typeof define === 'function' && define.amd)
10    define("WaveSurfer", [], factory);
11  else if(typeof exports === 'object')
12    exports["WaveSurfer"] = factory();
13  else
14    root["WaveSurfer"] = factory();
15})(window, function() {
16return /******/ (function(modules) { // webpackBootstrap
17/******/  // The module cache
18/******/  var installedModules = {};
19/******/
20/******/  // The require function
21/******/  function __webpack_require__(moduleId) {
22/******/
23/******/    // Check if module is in cache
24/******/    if(installedModules[moduleId]) {
25/******/      return installedModules[moduleId].exports;
26/******/    }
27/******/    // Create a new module (and put it into the cache)
28/******/    var module = installedModules[moduleId] = {
29/******/      i: moduleId,
30/******/      l: false,
31/******/      exports: {}
32/******/    };
33/******/
34/******/    // Execute the module function
35/******/    modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
36/******/
37/******/    // Flag the module as loaded
38/******/    module.l = true;
39/******/
40/******/    // Return the exports of the module
41/******/    return module.exports;
42/******/  }
43/******/
44/******/
45/******/  // expose the modules object (__webpack_modules__)
46/******/  __webpack_require__.m = modules;
47/******/
48/******/  // expose the module cache
49/******/  __webpack_require__.c = installedModules;
50/******/
51/******/  // define getter function for harmony exports
52/******/  __webpack_require__.d = function(exports, name, getter) {
53/******/    if(!__webpack_require__.o(exports, name)) {
54/******/      Object.defineProperty(exports, name, { enumerable: true, get: getter });
55/******/    }
56/******/  };
57/******/
58/******/  // define __esModule on exports
59/******/  __webpack_require__.r = function(exports) {
60/******/    if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
61/******/      Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
62/******/    }
63/******/    Object.defineProperty(exports, '__esModule', { value: true });
64/******/  };
65/******/
66/******/  // create a fake namespace object
67/******/  // mode & 1: value is a module id, require it
68/******/  // mode & 2: merge all properties of value into the ns
69/******/  // mode & 4: return value when already ns object
70/******/  // mode & 8|1: behave like require
71/******/  __webpack_require__.t = function(value, mode) {
72/******/    if(mode & 1) value = __webpack_require__(value);
73/******/    if(mode & 8) return value;
74/******/    if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
75/******/    var ns = Object.create(null);
76/******/    __webpack_require__.r(ns);
77/******/    Object.defineProperty(ns, 'default', { enumerable: true, value: value });
78/******/    if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
79/******/    return ns;
80/******/  };
81/******/
82/******/  // getDefaultExport function for compatibility with non-harmony modules
83/******/  __webpack_require__.n = function(module) {
84/******/    var getter = module && module.__esModule ?
85/******/      function getDefault() { return module['default']; } :
86/******/      function getModuleExports() { return module; };
87/******/    __webpack_require__.d(getter, 'a', getter);
88/******/    return getter;
89/******/  };
90/******/
91/******/  // Object.prototype.hasOwnProperty.call
92/******/  __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
93/******/
94/******/  // __webpack_public_path__
95/******/  __webpack_require__.p = "";
96/******/
97/******/
98/******/  // Load entry module and return exports
99/******/  return __webpack_require__(__webpack_require__.s = "./src/wavesurfer.js");
100/******/ })
101/************************************************************************/
102/******/ ({
103
vendor: 2,102 bytes, lines 104-184
104/***/ "./node_modules/debounce/index.js":
105/*!****************************************!*\
106  !*** ./node_modules/debounce/index.js ***!
107  \****************************************/
108/*! no static exports found */
109/***/ (function(module, exports) {
110
111/**
112 * Returns a function, that, as long as it continues to be invoked, will not
113 * be triggered. The function will be called after it stops being called for
114 * N milliseconds. If `immediate` is passed, trigger the function on the
115 * leading edge, instead of the trailing. The function also has a property 'clear' 
116 * that is a function which will clear the timer to prevent previously scheduled executions. 
117 *
118 * @source underscore.js
119 * @see http://unscriptable.com/2009/03/20/debouncing-javascript-methods/
120 * @param {Function} function to wrap
121 * @param {Number} timeout in ms (`100`)
122 * @param {Boolean} whether to execute at the beginning (`false`)
123 * @api public
124 */
125function debounce(func, wait, immediate){
126  var timeout, args, context, timestamp, result;
127  if (null == wait) wait = 100;
128
129  function later() {
130    var last = Date.now() - timestamp;
131
132    if (last < wait && last >= 0) {
133      timeout = setTimeout(later, wait - last);
134    } else {
135      timeout = null;
136      if (!immediate) {
137        result = func.apply(context, args);
138        context = args = null;
139      }
140    }
141  };
142
143  var debounced = function(){
144    context = this;
145    args = arguments;
146    timestamp = Date.now();
147    var callNow = immediate && !timeout;
148    if (!timeout) timeout = setTimeout(later, wait);
149    if (callNow) {
150      result = func.apply(context, args);
151      context = args = null;
152    }
153
154    return result;
155  };
156
157  debounced.clear = function() {
158    if (timeout) {
159      clearTimeout(timeout);
160      timeout = null;
161    }
162  };
163  
164  debounced.flush = function() {
165    if (timeout) {
166      result = func.apply(context, args);
167      context = args = null;
168      
169      clearTimeout(timeout);
170      timeout = null;
171    }
172  };
173
174  return debounced;
175};
176
177// Adds compatibility for ES modules
178debounce.debounce = debounce;
179
180module.exports = debounce;
181
182
183/***/ }),
184
185/***/ "./src/drawer.canvasentry.js":
186/*!***********************************!*\
187  !*** ./src/drawer.canvasentry.js ***!
188  \***********************************/
189/*! no static exports found */
190/***/ (function(module, exports, __webpack_require__) {
191
192"use strict";
193
194
195Object.defineProperty(exports, "__esModule", {
196  value: true
197});
198exports.default = void 0;
199
200var _style = _interopRequireDefault(__webpack_require__(/*! ./util/style */ "./src/util/style.js"));
201
202var _getId = _interopRequireDefault(__webpack_require__(/*! ./util/get-id */ "./src/util/get-id.js"));
203
204function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
205
206function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
207
208function _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); } }
209
210function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
211
212/**
213 * The `CanvasEntry` class represents an element consisting of a wave `canvas`
214 * and an (optional) progress wave `canvas`.
215 *
216 * The `MultiCanvas` renderer uses one or more `CanvasEntry` instances to
217 * render a waveform, depending on the zoom level.
218 */
219var CanvasEntry =
220/*#__PURE__*/
221function () {
222  function CanvasEntry() {
223    _classCallCheck(this, CanvasEntry);
224
225    /**
226     * The wave node
227     *
228     * @type {HTMLCanvasElement}
229     */
230    this.wave = null;
231    /**
232     * The wave canvas rendering context
233     *
234     * @type {CanvasRenderingContext2D}
235     */
236
237    this.waveCtx = null;
238    /**
239     * The (optional) progress wave node
240     *
241     * @type {HTMLCanvasElement}
242     */
243
244    this.progress = null;
245    /**
246     * The (optional) progress wave canvas rendering context
247     *
248     * @type {CanvasRenderingContext2D}
249     */
250
251    this.progressCtx = null;
252    /**
253     * Start of the area the canvas should render, between 0 and 1
254     *
255     * @type {number}
256     * @private
257     */
258
259    this.start = 0;
260    /**
261     * End of the area the canvas should render, between 0 and 1
262     *
263     * @type {number}
264     * @private
265     */
266
267    this.end = 1;
268    /**
269     * Unique identifier for this entry
270     *
271     * @type {string}
272     */
273
274    this.id = (0, _getId.default)(typeof this.constructor.name !== 'undefined' ? this.constructor.name.toLowerCase() + '_' : 'canvasentry_');
275    /**
276     * Canvas 2d context attributes
277     *
278     * @type {object}
279     */
280
281    this.canvasContextAttributes = {};
282  }
283  /**
284   * Store the wave canvas element and create the 2D rendering context
285   *
286   * @param {HTMLCanvasElement} element The wave `canvas` element.
287   */
288
289
290  _createClass(CanvasEntry, [{
291    key: "initWave",
292    value: function initWave(element) {
293      this.wave = element;
294      this.waveCtx = this.wave.getContext('2d', this.canvasContextAttributes);
295    }
296    /**
297     * Store the progress wave canvas element and create the 2D rendering
298     * context
299     *
300     * @param {HTMLCanvasElement} element The progress wave `canvas` element.
301     */
302
303  }, {
304    key: "initProgress",
305    value: function initProgress(element) {
306      this.progress = element;
307      this.progressCtx = this.progress.getContext('2d', this.canvasContextAttributes);
308    }
309    /**
310     * Update the dimensions
311     *
312     * @param {number} elementWidth Width of the entry
313     * @param {number} totalWidth Total width of the multi canvas renderer
314     * @param {number} width The new width of the element
315     * @param {number} height The new height of the element
316     */
317
318  }, {
319    key: "updateDimensions",
320    value: function updateDimensions(elementWidth, totalWidth, width, height) {
321      // where the canvas starts and ends in the waveform, represented as a
322      // decimal between 0 and 1
323      this.start = this.wave.offsetLeft / totalWidth || 0;
324      this.end = this.start + elementWidth / totalWidth; // set wave canvas dimensions
325
326      this.wave.width = width;
327      this.wave.height = height;
328      var elementSize = {
329        width: elementWidth + 'px'
330      };
331      (0, _style.default)(this.wave, elementSize);
332
333      if (this.hasProgressCanvas) {
334        // set progress canvas dimensions
335        this.progress.width = width;
336        this.progress.height = height;
337        (0, _style.default)(this.progress, elementSize);
338      }
339    }
340    /**
341     * Clear the wave and progress rendering contexts
342     */
343
344  }, {
345    key: "clearWave",
346    value: function clearWave() {
347      // wave
348      this.waveCtx.clearRect(0, 0, this.waveCtx.canvas.width, this.waveCtx.canvas.height); // progress
349
350      if (this.hasProgressCanvas) {
351        this.progressCtx.clearRect(0, 0, this.progressCtx.canvas.width, this.progressCtx.canvas.height);
352      }
353    }
354    /**
355     * Set the fill styles for wave and progress
356     *
357     * @param {string} waveColor Fill color for the wave canvas
358     * @param {?string} progressColor Fill color for the progress canvas
359     */
360
361  }, {
362    key: "setFillStyles",
363    value: function setFillStyles(waveColor, progressColor) {
364      this.waveCtx.fillStyle = waveColor;
365
366      if (this.hasProgressCanvas) {
367        this.progressCtx.fillStyle = progressColor;
368      }
369    }
370    /**
371     * Draw a rectangle for wave and progress
372     *
373     * @param {number} x X start position
374     * @param {number} y Y start position
375     * @param {number} width Width of the rectangle
376     * @param {number} height Height of the rectangle
377     * @param {number} radius Radius of the rectangle
378     */
379
380  }, {
381    key: "fillRects",
382    value: function fillRects(x, y, width, height, radius) {
383      this.fillRectToContext(this.waveCtx, x, y, width, height, radius);
384
385      if (this.hasProgressCanvas) {
386        this.fillRectToContext(this.progressCtx, x, y, width, height, radius);
387      }
388    }
389    /**
390     * Draw the actual rectangle on a `canvas` element
391     *
392     * @private
393     * @param {CanvasRenderingContext2D} ctx Rendering context of target canvas
394     * @param {number} x X start position
395     * @param {number} y Y start position
396     * @param {number} width Width of the rectangle
397     * @param {number} height Height of the rectangle
398     * @param {number} radius Radius of the rectangle
399     */
400
401  }, {
402    key: "fillRectToContext",
403    value: function fillRectToContext(ctx, x, y, width, height, radius) {
404      if (!ctx) {
405        return;
406      }
407
408      if (radius) {
409        this.drawRoundedRect(ctx, x, y, width, height, radius);
410      } else {
411        ctx.fillRect(x, y, width, height);
412      }
413    }
414    /**
415     * Draw a rounded rectangle on Canvas
416     *
417     * @private
418     * @param {CanvasRenderingContext2D} ctx Canvas context
419     * @param {number} x X-position of the rectangle
420     * @param {number} y Y-position of the rectangle
421     * @param {number} width Width of the rectangle
422     * @param {number} height Height of the rectangle
423     * @param {number} radius Radius of the rectangle
424     *
425     * @return {void}
426     * @example drawRoundedRect(ctx, 50, 50, 5, 10, 3)
427     */
428
429  }, {
430    key: "drawRoundedRect",
431    value: function drawRoundedRect(ctx, x, y, width, height, radius) {
432      if (height === 0) {
433        return;
434      } // peaks are float values from -1 to 1. Use absolute height values in
435      // order to correctly calculate rounded rectangle coordinates
436
437
438      if (height < 0) {
439        height *= -1;
440        y -= height;
441      }
442
443      ctx.beginPath();
444      ctx.moveTo(x + radius, y);
445      ctx.lineTo(x + width - radius, y);
446      ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
447      ctx.lineTo(x + width, y + height - radius);
448      ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
449      ctx.lineTo(x + radius, y + height);
450      ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
451      ctx.lineTo(x, y + radius);
452      ctx.quadraticCurveTo(x, y, x + radius, y);
453      ctx.closePath();
454      ctx.fill();
455    }
456    /**
457     * Render the actual wave and progress lines
458     *
459     * @param {number[]} peaks Array with peaks data
460     * @param {number} absmax Maximum peak value (absolute)
461     * @param {number} halfH Half the height of the waveform
462     * @param {number} offsetY Offset to the top
463     * @param {number} start The x-offset of the beginning of the area that
464     * should be rendered
465     * @param {number} end The x-offset of the end of the area that
466     * should be rendered
467     */
468
469  }, {
470    key: "drawLines",
471    value: function drawLines(peaks, absmax, halfH, offsetY, start, end) {
472      this.drawLineToContext(this.waveCtx, peaks, absmax, halfH, offsetY, start, end);
473
474      if (this.hasProgressCanvas) {
475        this.drawLineToContext(this.progressCtx, peaks, absmax, halfH, offsetY, start, end);
476      }
477    }
478    /**
479     * Render the actual waveform line on a `canvas` element
480     *
481     * @private
482     * @param {CanvasRenderingContext2D} ctx Rendering context of target canvas
483     * @param {number[]} peaks Array with peaks data
484     * @param {number} absmax Maximum peak value (absolute)
485     * @param {number} halfH Half the height of the waveform
486     * @param {number} offsetY Offset to the top
487     * @param {number} start The x-offset of the beginning of the area that
488     * should be rendered
489     * @param {number} end The x-offset of the end of the area that
490     * should be rendered
491     */
492
493  }, {
494    key: "drawLineToContext",
495    value: function drawLineToContext(ctx, peaks, absmax, halfH, offsetY, start, end) {
496      if (!ctx) {
497        return;
498      }
499
500      var length = peaks.length / 2;
501      var first = Math.round(length * this.start); // use one more peak value to make sure we join peaks at ends -- unless,
502      // of course, this is the last canvas
503
504      var last = Math.round(length * this.end) + 1;
505      var canvasStart = first;
506      var canvasEnd = last;
507      var scale = this.wave.width / (canvasEnd - canvasStart - 1); // optimization
508
509      var halfOffset = halfH + offsetY;
510      var absmaxHalf = absmax / halfH;
511      ctx.beginPath();
512      ctx.moveTo((canvasStart - first) * scale, halfOffset);
513      ctx.lineTo((canvasStart - first) * scale, halfOffset - Math.round((peaks[2 * canvasStart] || 0) / absmaxHalf));
514      var i, peak, h;
515
516      for (i = canvasStart; i < canvasEnd; i++) {
517        peak = peaks[2 * i] || 0;
518        h = Math.round(peak / absmaxHalf);
519        ctx.lineTo((i - first) * scale + this.halfPixel, halfOffset - h);
520      } // draw the bottom edge going backwards, to make a single
521      // closed hull to fill
522
523
524      var j = canvasEnd - 1;
525
526      for (j; j >= canvasStart; j--) {
527        peak = peaks[2 * j + 1] || 0;
528        h = Math.round(peak / absmaxHalf);
529        ctx.lineTo((j - first) * scale + this.halfPixel, halfOffset - h);
530      }
531
532      ctx.lineTo((canvasStart - first) * scale, halfOffset - Math.round((peaks[2 * canvasStart + 1] || 0) / absmaxHalf));
533      ctx.closePath();
534      ctx.fill();
535    }
536    /**
537     * Destroys this entry
538     */
539
540  }, {
541    key: "destroy",
542    value: function destroy() {
543      this.waveCtx = null;
544      this.wave = null;
545      this.progressCtx = null;
546      this.progress = null;
547    }
548    /**
549     * Return image data of the wave `canvas` element
550     *
551     * When using a `type` of `'blob'`, this will return a `Promise` that
552     * resolves with a `Blob` instance.
553     *
554     * @param {string} format='image/png' An optional value of a format type.
555     * @param {number} quality=0.92 An optional value between 0 and 1.
556     * @param {string} type='dataURL' Either 'dataURL' or 'blob'.
557     * @return {string|Promise} When using the default `'dataURL'` `type` this
558     * returns a data URL. When using the `'blob'` `type` this returns a
559     * `Promise` that resolves with a `Blob` instance.
560     */
561
562  }, {
563    key: "getImage",
564    value: function getImage(format, quality, type) {
565      var _this = this;
566
567      if (type === 'blob') {
568        return new Promise(function (resolve) {
569          _this.wave.toBlob(resolve, format, quality);
570        });
571      } else if (type === 'dataURL') {
572        return this.wave.toDataURL(format, quality);
573      }
574    }
575  }]);
576
577  return CanvasEntry;
578}();
579
580exports.default = CanvasEntry;
581module.exports = exports.default;
582
583/***/ }),
584
vendor: 4,411 bytes, lines 585-666
585/***/ "./src/drawer.js":
586/*!***********************!*\
587  !*** ./src/drawer.js ***!
588  \***********************/
589/*! no static exports found */
590/***/ (function(module, exports, __webpack_require__) {
591
592"use strict";
593
594
595Object.defineProperty(exports, "__esModule", {
596  value: true
597});
598exports.default = void 0;
599
600var util = _interopRequireWildcard(__webpack_require__(/*! ./util */ "./src/util/index.js"));
601
602function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }
603
604function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (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; }
605
606function _typeof(obj) { 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); }
607
608function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
609
610function _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); } }
611
612function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
613
614function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
615
616function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
617
618function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
619
620function _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); }
621
622function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
623
624/**
625 * Parent class for renderers
626 *
627 * @extends {Observer}
628 */
629var Drawer =
630/*#__PURE__*/
631function (_util$Observer) {
632  _inherits(Drawer, _util$Observer);
633
634  /**
635   * @param {HTMLElement} container The container node of the wavesurfer instance
636   * @param {WavesurferParams} params The wavesurfer initialisation options
637   */
638  function Drawer(container, params) {
639    var _this;
640
641    _classCallCheck(this, Drawer);
642
643    _this = _possibleConstructorReturn(this, _getPrototypeOf(Drawer).call(this));
644    /** @private */
645
646    _this.container = container;
647    /**
648     * @type {WavesurferParams}
649     * @private
650     */
651
652    _this.params = params;
653    /**
654     * The width of the renderer
655     * @type {number}
656     */
657
658    _this.width = 0;
659    /**
660     * The height of the renderer
661     * @type {number}
662     */
663
664    _this.height = params.height * _this.params.pixelRatio;
665    /** @private */
666
667    _this.lastPos = 0;
668    /**
669     * The `<wave>` element which is added to the container
670     * @type {HTMLElement}
671     */
672
673    _this.wrapper = null;
674    return _this;
675  }
676  /**
677   * Alias of `util.style`
678   *
679   * @param {HTMLElement} el The element that the styles will be applied to
680   * @param {Object} styles The map of propName: attribute, both are used as-is
681   * @return {HTMLElement} el
682   */
683
684
685  _createClass(Drawer, [{
686    key: "style",
687    value: function style(el, styles) {
688      return util.style(el, styles);
689    }
690    /**
691     * Create the wrapper `<wave>` element, style it and set up the events for
692     * interaction
693     */
694
695  }, {
696    key: "createWrapper",
697    value: function createWrapper() {
698      this.wrapper = this.container.appendChild(document.createElement('wave'));
699      this.style(this.wrapper, {
700        display: 'block',
701        position: 'relative',
702        userSelect: 'none',
703        webkitUserSelect: 'none',
704        height: this.params.height + 'px'
705      });
706
707      if (this.params.fillParent || this.params.scrollParent) {
708        this.style(this.wrapper, {
709          width: '100%',
710          overflowX: this.params.hideScrollbar ? 'hidden' : 'auto',
711          overflowY: 'hidden'
712        });
713      }
714
715      this.setupWrapperEvents();
716    }
717    /**
718     * Handle click event
719     *
720     * @param {Event} e Click event
721     * @param {?boolean} noPrevent Set to true to not call `e.preventDefault()`
722     * @return {number} Playback position from 0 to 1
723     */
724
725  }, {
726    key: "handleEvent",
727    value: function handleEvent(e, noPrevent) {
728      !noPrevent && e.preventDefault();
729      var clientX = e.targetTouches ? e.targetTouches[0].clientX : e.clientX;
730      var bbox = this.wrapper.getBoundingClientRect();
731      var nominalWidth = this.width;
732      var parentWidth = this.getWidth();
733      var progress;
734
735      if (!this.params.fillParent && nominalWidth < parentWidth) {
736        progress = (this.params.rtl ? bbox.right - clientX : clientX - bbox.left) * (this.params.pixelRatio / nominalWidth) || 0;
737
738        if (progress > 1) {
739          progress = 1;
740        }
741      } else {
742        progress = ((this.params.rtl ? bbox.right - clientX : clientX - bbox.left) + this.wrapper.scrollLeft) / this.wrapper.scrollWidth || 0;
743      }
744
745      return progress;
746    }
747    /**
748     * @private
749     */
750
751  }, {
752    key: "setupWrapperEvents",
753    value: function setupWrapperEvents() {
754      var _this2 = this;
755
756      this.wrapper.addEventListener('click', function (e) {
757        var scrollbarHeight = _this2.wrapper.offsetHeight - _this2.wrapper.clientHeight;
758
759        if (scrollbarHeight !== 0) {
760          // scrollbar is visible.  Check if click was on it
761          var bbox = _this2.wrapper.getBoundingClientRect();
762
763          if (e.clientY >= bbox.bottom - scrollbarHeight) {
764            // ignore mousedown as it was on the scrollbar
765            return;
766          }
767        }
768
769        if (_this2.params.interact) {
770          _this2.fireEvent('click', e, _this2.handleEvent(e));
771        }
772      });
773      this.wrapper.addEventListener('dblclick', function (e) {
774        if (_this2.params.interact) {
775          _this2.fireEvent('dblclick', e, _this2.handleEvent(e));
776        }
777      });
778      this.wrapper.addEventListener('scroll', function (e) {
779        return _this2.fireEvent('scroll', e);
780      });
781    }
782    /**
783     * Draw peaks on the canvas
784     *
785     * @param {number[]|Number.<Array[]>} peaks Can also be an array of arrays
786     * for split channel rendering
787     * @param {number} length The width of the area that should be drawn
788     * @param {number} start The x-offset of the beginning of the area that
789     * should be rendered
790     * @param {number} end The x-offset of the end of the area that should be
791     * rendered
792     */
793
794  }, {
795    key: "drawPeaks",
796    value: function drawPeaks(peaks, length, start, end) {
797      if (!this.setWidth(length)) {
798        this.clearWave();
799      }
800
801      this.params.barWidth ? this.drawBars(peaks, 0, start, end) : this.drawWave(peaks, 0, start, end);
802    }
803    /**
804     * Scroll to the beginning
805     */
806
807  }, {
808    key: "resetScroll",
809    value: function resetScroll() {
810      if (this.wrapper !== null) {
811        this.wrapper.scrollLeft = 0;
812      }
813    }
814    /**
815     * Recenter the view-port at a certain percent of the waveform
816     *
817     * @param {number} percent Value from 0 to 1 on the waveform
818     */
819
820  }, {
821    key: "recenter",
822    value: function recenter(percent) {
823      var position = this.wrapper.scrollWidth * percent;
824      this.recenterOnPosition(position, true);
825    }
826    /**
827     * Recenter the view-port on a position, either scroll there immediately or
828     * in steps of 5 pixels
829     *
830     * @param {number} position X-offset in pixels
831     * @param {boolean} immediate Set to true to immediately scroll somewhere
832     */
833
834  }, {
835    key: "recenterOnPosition",
836    value: function recenterOnPosition(position, immediate) {
837      var scrollLeft = this.wrapper.scrollLeft;
838      var half = ~~(this.wrapper.clientWidth / 2);
839      var maxScroll = this.wrapper.scrollWidth - this.wrapper.clientWidth;
840      var target = position - half;
841      var offset = target - scrollLeft;
842
843      if (maxScroll == 0) {
844        // no need to continue if scrollbar is not there
845        return;
846      } // if the cursor is currently visible...
847
848
849      if (!immediate && -half <= offset && offset < half) {
850        // set rate at which waveform is centered
851        var rate = this.params.autoCenterRate; // make rate depend on width of view and length of waveform
852
853        rate /= half;
854        rate *= maxScroll;
855        offset = Math.max(-rate, Math.min(rate, offset));
856        target = scrollLeft + offset;
857      } // limit target to valid range (0 to maxScroll)
858
859
860      target = Math.max(0, Math.min(maxScroll, target)); // no use attempting to scroll if we're not moving
861
862      if (target != scrollLeft) {
863        this.wrapper.scrollLeft = target;
864      }
865    }
866    /**
867     * Get the current scroll position in pixels
868     *
869     * @return {number} Horizontal scroll position in pixels
870     */
871
872  }, {
873    key: "getScrollX",
874    value: function getScrollX() {
875      var x = 0;
876
877      if (this.wrapper) {
878        var pixelRatio = this.params.pixelRatio;
879        x = Math.round(this.wrapper.scrollLeft * pixelRatio); // In cases of elastic scroll (safari with mouse wheel) you can
880        // scroll beyond the limits of the container
881        // Calculate and floor the scrollable extent to make sure an out
882        // of bounds value is not returned
883        // Ticket #1312
884
885        if (this.params.scrollParent) {
886          var maxScroll = ~~(this.wrapper.scrollWidth * pixelRatio - this.getWidth());
887          x = Math.min(maxScroll, Math.max(0, x));
888        }
889      }
890
891      return x;
892    }
893    /**
894     * Get the width of the container
895     *
896     * @return {number} The width of the container
897     */
898
899  }, {
900    key: "getWidth",
901    value: function getWidth() {
902      return Math.round(this.container.clientWidth * this.params.pixelRatio);
903    }
904    /**
905     * Set the width of the container
906     *
907     * @param {number} width The new width of the container
908     * @return {boolean} Whether the width of the container was updated or not
909     */
910
911  }, {
912    key: "setWidth",
913    value: function setWidth(width) {
914      if (this.width == width) {
915        return false;
916      }
917
918      this.width = width;
919
920      if (this.params.fillParent || this.params.scrollParent) {
921        this.style(this.wrapper, {
922          width: ''
923        });
924      } else {
925        this.style(this.wrapper, {
926          width: ~~(this.width / this.params.pixelRatio) + 'px'
927        });
928      }
929
930      this.updateSize();
931      return true;
932    }
933    /**
934     * Set the height of the container
935     *
936     * @param {number} height The new height of the container.
937     * @return {boolean} Whether the height of the container was updated or not
938     */
939
940  }, {
941    key: "setHeight",
942    value: function setHeight(height) {
943      if (height == this.height) {
944        return false;
945      }
946
947      this.height = height;
948      this.style(this.wrapper, {
949        height: ~~(this.height / this.params.pixelRatio) + 'px'
950      });
951      this.updateSize();
952      return true;
953    }
954    /**
955     * Called by wavesurfer when progress should be rendered
956     *
957     * @param {number} progress From 0 to 1
958     */
959
960  }, {
961    key: "progress",
962    value: function progress(_progress) {
963      var minPxDelta = 1 / this.params.pixelRatio;
964      var pos = Math.round(_progress * this.width) * minPxDelta;
965
966      if (pos < this.lastPos || pos - this.lastPos >= minPxDelta) {
967        this.lastPos = pos;
968
969        if (this.params.scrollParent && this.params.autoCenter) {
970          var newPos = ~~(this.wrapper.scrollWidth * _progress);
971          this.recenterOnPosition(newPos, this.params.autoCenterImmediately);
972        }
973
974        this.updateProgress(pos);
975      }
976    }
977    /**
978     * This is called when wavesurfer is destroyed
979     */
980
981  }, {
982    key: "destroy",
983    value: function destroy() {
984      this.unAll();
985
986      if (this.wrapper) {
987        if (this.wrapper.parentNode == this.container) {
988          this.container.removeChild(this.wrapper);
989        }
990
991        this.wrapper = null;
992      }
993    }
994    /* Renderer-specific methods */
995
996    /**
997     * Called after cursor related params have changed.
998     *
999     * @abstract
1000     */
1001
1002  }, {
1003    key: "updateCursor",
1004    value: function updateCursor() {}
1005    /**
1006     * Called when the size of the container changes so the renderer can adjust
1007     *
1008     * @abstract
1009     */
1010
1011  }, {
1012    key: "updateSize",
1013    value: function updateSize() {}
1014    /**
1015     * Draw a waveform with bars
1016     *
1017     * @abstract
1018     * @param {number[]|Number.<Array[]>} peaks Can also be an array of arrays for split channel
1019     * rendering
1020     * @param {number} channelIndex The index of the current channel. Normally
1021     * should be 0
1022     * @param {number} start The x-offset of the beginning of the area that
1023     * should be rendered
1024     * @param {number} end The x-offset of the end of the area that should be
1025     * rendered
1026     */
1027
1028  }, {
1029    key: "drawBars",
1030    value: function drawBars(peaks, channelIndex, start, end) {}
1031    /**
1032     * Draw a waveform
1033     *
1034     * @abstract
1035     * @param {number[]|Number.<Array[]>} peaks Can also be an array of arrays for split channel
1036     * rendering
1037     * @param {number} channelIndex The index of the current channel. Normally
1038     * should be 0
1039     * @param {number} start The x-offset of the beginning of the area that
1040     * should be rendered
1041     * @param {number} end The x-offset of the end of the area that should be
1042     * rendered
1043     */
1044
1045  }, {
1046    key: "drawWave",
1047    value: function drawWave(peaks, channelIndex, start, end) {}
1048    /**
1049     * Clear the waveform
1050     *
1051     * @abstract
1052     */
1053
1054  }, {
1055    key: "clearWave",
1056    value: function clearWave() {}
1057    /**
1058     * Render the new progress
1059     *
1060     * @abstract
1061     * @param {number} position X-Offset of progress position in pixels
1062     */
1063
1064  }, {
1065    key: "updateProgress",
1066    value: function updateProgress(position) {}
1067  }]);
1068
1069  return Drawer;
1070}(util.Observer);
1071
1072exports.default = Drawer;
1073module.exports = exports.default;
1074
1075/***/ }),
1076
1077/***/ "./src/drawer.multicanvas.js":
1078/*!***********************************!*\
1079  !*** ./src/drawer.multicanvas.js ***!
1080  \***********************************/
1081/*! no static exports found */
1082/***/ (function(module, exports, __webpack_require__) {
1083
1084"use strict";
1085
1086
1087Object.defineProperty(exports, "__esModule", {
1088  value: true
1089});
1090exports.default = void 0;
1091
1092var _drawer = _interopRequireDefault(__webpack_require__(/*! ./drawer */ "./src/drawer.js"));
1093
1094var util = _interopRequireWildcard(__webpack_require__(/*! ./util */ "./src/util/index.js"));
1095
1096var _drawer2 = _interopRequireDefault(__webpack_require__(/*! ./drawer.canvasentry */ "./src/drawer.canvasentry.js"));
1097
1098function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }
1099
1100function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (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; }
1101
1102function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
1103
1104function _typeof(obj) { 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); }
1105
1106function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
1107
1108function _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); } }
1109
1110function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
1111
1112function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
1113
1114function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
1115
1116function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
1117
1118function _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); }
1119
1120function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
1121
1122/**
1123 * MultiCanvas renderer for wavesurfer. Is currently the default and sole
1124 * builtin renderer.
1125 *
1126 * A `MultiCanvas` consists of one or more `CanvasEntry` instances, depending
1127 * on the zoom level.
1128 */
1129var MultiCanvas =
1130/*#__PURE__*/
1131function (_Drawer) {
1132  _inherits(MultiCanvas, _Drawer);
1133
1134  /**
1135   * @param {HTMLElement} container The container node of the wavesurfer instance
1136   * @param {WavesurferParams} params The wavesurfer initialisation options
1137   */
1138  function MultiCanvas(container, params) {
1139    var _this;
1140
1141    _classCallCheck(this, MultiCanvas);
1142
1143    _this = _possibleConstructorReturn(this, _getPrototypeOf(MultiCanvas).call(this, container, params));
1144    /**
1145     * @type {number}
1146     * @private
1147     */
1148
1149    _this.maxCanvasWidth = params.maxCanvasWidth;
1150    /**
1151     * @private
1152     * @type {number}
1153     */
1154
1155    _this.maxCanvasElementWidth = Math.round(params.maxCanvasWidth / params.pixelRatio);
1156    /**
1157     * Whether or not the progress wave is rendered. If the `waveColor`
1158     * and `progressColor` are the same color it is not.
1159     *
1160     * @type {boolean}
1161     */
1162
1163    _this.hasProgressCanvas = params.waveColor != params.progressColor;
1164    /**
1165     * @private
1166     * @type {number}
1167     */
1168
1169    _this.halfPixel = 0.5 / params.pixelRatio;
1170    /**
1171     * List of `CanvasEntry` instances.
1172     *
1173     * @private
1174     * @type {Array}
1175     */
1176
1177    _this.canvases = [];
1178    /**
1179     * @private
1180     * @type {HTMLElement}
1181     */
1182
1183    _this.progressWave = null;
1184    /**
1185     * Class used to generate entries.
1186     *
1187     * @private
1188     * @type {function}
1189     */
1190
1191    _this.EntryClass = _drawer2.default;
1192    /**
1193     * Canvas 2d context attributes.
1194     *
1195     * @private
1196     * @type {object}
1197     */
1198
1199    _this.canvasContextAttributes = params.drawingContextAttributes;
1200    /**
1201     * Overlap added between entries to prevent vertical white stripes
1202     * between `canvas` elements.
1203     *
1204     * @type {number}
1205     */
1206
1207    _this.overlap = 2 * Math.ceil(params.pixelRatio / 2);
1208    /**
1209     * The radius of the wave bars. Makes bars rounded
1210     *
1211     * @private
1212     * @type {number}
1213     */
1214
1215    _this.barRadius = params.barRadius || 0;
1216    return _this;
1217  }
1218  /**
1219   * Initialize the drawer
1220   */
1221
1222
1223  _createClass(MultiCanvas, [{
1224    key: "init",
1225    value: function init() {
1226      this.createWrapper();
1227      this.createElements();
1228    }
1229    /**
1230     * Create the canvas elements and style them
1231     *
1232     * @private
1233     */
1234
1235  }, {
1236    key: "createElements",
1237    value: function createElements() {
1238      this.progressWave = this.wrapper.appendChild(this.style(document.createElement('wave'), {
1239        position: 'absolute',
1240        zIndex: 3,
1241        left: 0,
1242        top: 0,
1243        bottom: 0,
1244        overflow: 'hidden',
1245        width: '0',
1246        display: 'none',
1247        boxSizing: 'border-box',
1248        borderRightStyle: 'solid',
1249        pointerEvents: 'none'
1250      }));
1251      this.addCanvas();
1252      this.updateCursor();
1253    }
1254    /**
1255     * Update cursor style
1256     */
1257
1258  }, {
1259    key: "updateCursor",
1260    value: function updateCursor() {
1261      this.style(this.progressWave, {
1262        borderRightWidth: this.params.cursorWidth + 'px',
1263        borderRightColor: this.params.cursorColor
1264      });
1265    }
1266    /**
1267     * Adjust to the updated size by adding or removing canvases
1268     */
1269
1270  }, {
1271    key: "updateSize",
1272    value: function updateSize() {
1273      var _this2 = this;
1274
1275      var totalWidth = Math.round(this.width / this.params.pixelRatio);
1276      var requiredCanvases = Math.ceil(totalWidth / (this.maxCanvasElementWidth + this.overlap)); // add required canvases
1277
1278      while (this.canvases.length < requiredCanvases) {
1279        this.addCanvas();
1280      } // remove older existing canvases, if any
1281
1282
1283      while (this.canvases.length > requiredCanvases) {
1284        this.removeCanvas();
1285      }
1286
1287      var canvasWidth = this.maxCanvasWidth + this.overlap;
1288      var lastCanvas = this.canvases.length - 1;
1289      this.canvases.forEach(function (entry, i) {
1290        if (i == lastCanvas) {
1291          canvasWidth = _this2.width - _this2.maxCanvasWidth * lastCanvas;
1292        }
1293
1294        _this2.updateDimensions(entry, canvasWidth, _this2.height);
1295
1296        entry.clearWave();
1297      });
1298    }
1299    /**
1300     * Add a canvas to the canvas list
1301     *
1302     * @private
1303     */
1304
1305  }, {
1306    key: "addCanvas",
1307    value: function addCanvas() {
1308      var entry = new this.EntryClass();
1309      entry.canvasContextAttributes = this.canvasContextAttributes;
1310      entry.hasProgressCanvas = this.hasProgressCanvas;
1311      entry.halfPixel = this.halfPixel;
1312      var leftOffset = this.maxCanvasElementWidth * this.canvases.length; // wave
1313
1314      entry.initWave(this.wrapper.appendChild(this.style(document.createElement('canvas'), {
1315        position: 'absolute',
1316        zIndex: 2,
1317        left: leftOffset + 'px',
1318        top: 0,
1319        bottom: 0,
1320        height: '100%',
1321        pointerEvents: 'none'
1322      }))); // progress
1323
1324      if (this.hasProgressCanvas) {
1325        entry.initProgress(this.progressWave.appendChild(this.style(document.createElement('canvas'), {
1326          position: 'absolute',
1327          left: leftOffset + 'px',
1328          top: 0,
1329          bottom: 0,
1330          height: '100%'
1331        })));
1332      }
1333
1334      this.canvases.push(entry);
1335    }
1336    /**
1337     * Pop single canvas from the list
1338     *
1339     * @private
1340     */
1341
1342  }, {
1343    key: "removeCanvas",
1344    value: function removeCanvas() {
1345      var lastEntry = this.canvases[this.canvases.length - 1]; // wave
1346
1347      lastEntry.wave.parentElement.removeChild(lastEntry.wave); // progress
1348
1349      if (this.hasProgressCanvas) {
1350        lastEntry.progress.parentElement.removeChild(lastEntry.progress);
1351      } // cleanup
1352
1353
1354      if (lastEntry) {
1355        lastEntry.destroy();
1356        lastEntry = null;
1357      }
1358
1359      this.canvases.pop();
1360    }
1361    /**
1362     * Update the dimensions of a canvas element
1363     *
1364     * @private
1365     * @param {CanvasEntry} entry Target entry
1366     * @param {number} width The new width of the element
1367     * @param {number} height The new height of the element
1368     */
1369
1370  }, {
1371    key: "updateDimensions",
1372    value: function updateDimensions(entry, width, height) {
1373      var elementWidth = Math.round(width / this.params.pixelRatio);
1374      var totalWidth = Math.round(this.width / this.params.pixelRatio); // update canvas dimensions
1375
1376      entry.updateDimensions(elementWidth, totalWidth, width, height); // style element
1377
1378      this.style(this.progressWave, {
1379        display: 'block'
1380      });
1381    }
1382    /**
1383     * Clear the whole multi-canvas
1384     */
1385
1386  }, {
1387    key: "clearWave",
1388    value: function clearWave() {
1389      var _this3 = this;
1390
1391      util.frame(function () {
1392        _this3.canvases.forEach(function (entry) {
1393          return entry.clearWave();
1394        });
1395      })();
1396    }
1397    /**
1398     * Draw a waveform with bars
1399     *
1400     * @param {number[]|Number.<Array[]>} peaks Can also be an array of arrays
1401     * for split channel rendering
1402     * @param {number} channelIndex The index of the current channel. Normally
1403     * should be 0. Must be an integer.
1404     * @param {number} start The x-offset of the beginning of the area that
1405     * should be rendered
1406     * @param {number} end The x-offset of the end of the area that should be
1407     * rendered
1408     * @returns {void}
1409     */
1410
1411  }, {
1412    key: "drawBars",
1413    value: function drawBars(peaks, channelIndex, start, end) {
1414      var _this4 = this;
1415
1416      return this.prepareDraw(peaks, channelIndex, start, end, function (_ref) {
1417        var absmax = _ref.absmax,
1418            hasMinVals = _ref.hasMinVals,
1419            height = _ref.height,
1420            offsetY = _ref.offsetY,
1421            halfH = _ref.halfH,
1422            peaks = _ref.peaks;
1423
1424        // if drawBars was called within ws.empty we don't pass a start and
1425        // don't want anything to happen
1426        if (start === undefined) {
1427          return;
1428        } // Skip every other value if there are negatives.
1429
1430
1431        var peakIndexScale = hasMinVals ? 2 : 1;
1432        var length = peaks.length / peakIndexScale;
1433        var bar = _this4.params.barWidth * _this4.params.pixelRatio;
1434        var gap = _this4.params.barGap === null ? Math.max(_this4.params.pixelRatio, ~~(bar / 2)) : Math.max(_this4.params.pixelRatio, _this4.params.barGap * _this4.params.pixelRatio);
1435        var step = bar + gap;
1436        var scale = length / _this4.width;
1437        var first = start;
1438        var last = end;
1439        var i = first;
1440
1441        for (i; i < last; i += step) {
1442          var peak = peaks[Math.floor(i * scale * peakIndexScale)] || 0;
1443          var h = Math.round(peak / absmax * halfH);
1444          /* in case of silences, allow the user to specify that we
1445           * always draw *something* (normally a 1px high bar) */
1446
1447          if (h == 0 && _this4.params.barMinHeight) h = _this4.params.barMinHeight;
1448
1449          _this4.fillRect(i + _this4.halfPixel, halfH - h + offsetY, bar + _this4.halfPixel, h * 2, _this4.barRadius);
1450        }
1451      });
1452    }
1453    /**
1454     * Draw a waveform
1455     *
1456     * @param {number[]|Number.<Array[]>} peaks Can also be an array of arrays
1457     * for split channel rendering
1458     * @param {number} channelIndex The index of the current channel. Normally
1459     * should be 0
1460     * @param {number?} start The x-offset of the beginning of the area that
1461     * should be rendered (If this isn't set only a flat line is rendered)
1462     * @param {number?} end The x-offset of the end of the area that should be
1463     * rendered
1464     * @returns {void}
1465     */
1466
1467  }, {
1468    key: "drawWave",
1469    value: function drawWave(peaks, channelIndex, start, end) {
1470      var _this5 = this;
1471
1472      return this.prepareDraw(peaks, channelIndex, start, end, function (_ref2) {
1473        var absmax = _ref2.absmax,
1474            hasMinVals = _ref2.hasMinVals,
1475            height = _ref2.height,
1476            offsetY = _ref2.offsetY,
1477            halfH = _ref2.halfH,
1478            peaks = _ref2.peaks;
1479
1480        if (!hasMinVals) {
1481          var reflectedPeaks = [];
1482          var len = peaks.length;
1483          var i = 0;
1484
1485          for (i; i < len; i++) {
1486            reflectedPeaks[2 * i] = peaks[i];
1487            reflectedPeaks[2 * i + 1] = -peaks[i];
1488          }
1489
1490          peaks = reflectedPeaks;
1491        } // if drawWave was called within ws.empty we don't pass a start and
1492        // end and simply want a flat line
1493
1494
1495        if (start !== undefined) {
1496          _this5.drawLine(peaks, absmax, halfH, offsetY, start, end);
1497        } // always draw a median line
1498
1499
1500        _this5.fillRect(0, halfH + offsetY - _this5.halfPixel, _this5.width, _this5.halfPixel, _this5.barRadius);
1501      });
1502    }
1503    /**
1504     * Tell the canvas entries to render their portion of the waveform
1505     *
1506     * @private
1507     * @param {number[]} peaks Peaks data
1508     * @param {number} absmax Maximum peak value (absolute)
1509     * @param {number} halfH Half the height of the waveform
1510     * @param {number} offsetY Offset to the top
1511     * @param {number} start The x-offset of the beginning of the area that
1512     * should be rendered
1513     * @param {number} end The x-offset of the end of the area that
1514     * should be rendered
1515     */
1516
1517  }, {
1518    key: "drawLine",
1519    value: function drawLine(peaks, absmax, halfH, offsetY, start, end) {
1520      var _this6 = this;
1521
1522      this.canvases.forEach(function (entry) {
1523        _this6.setFillStyles(entry);
1524
1525        entry.drawLines(peaks, absmax, halfH, offsetY, start, end);
1526      });
1527    }
1528    /**
1529     * Draw a rectangle on the multi-canvas
1530     *
1531     * @param {number} x X-position of the rectangle
1532     * @param {number} y Y-position of the rectangle
1533     * @param {number} width Width of the rectangle
1534     * @param {number} height Height of the rectangle
1535     * @param {number} radius Radius of the rectangle
1536     */
1537
1538  }, {
1539    key: "fillRect",
1540    value: function fillRect(x, y, width, height, radius) {
1541      var startCanvas = Math.floor(x / this.maxCanvasWidth);
1542      var endCanvas = Math.min(Math.ceil((x + width) / this.maxCanvasWidth) + 1, this.canvases.length);
1543      var i = startCanvas;
1544
1545      for (i; i < endCanvas; i++) {
1546        var entry = this.canvases[i];
1547        var leftOffset = i * this.maxCanvasWidth;
1548        var intersection = {
1549          x1: Math.max(x, i * this.maxCanvasWidth),
1550          y1: y,
1551          x2: Math.min(x + width, i * this.maxCanvasWidth + entry.wave.width),
1552          y2: y + height
1553        };
1554
1555        if (intersection.x1 < intersection.x2) {
1556          this.setFillStyles(entry);
1557          entry.fillRects(intersection.x1 - leftOffset, intersection.y1, intersection.x2 - intersection.x1, intersection.y2 - intersection.y1, radius);
1558        }
1559      }
1560    }
1561    /**
1562     * Performs preparation tasks and calculations which are shared by `drawBars`
1563     * and `drawWave`
1564     *
1565     * @private
1566     * @param {number[]|Number.<Array[]>} peaks Can also be an array of arrays for
1567     * split channel rendering
1568     * @param {number} channelIndex The index of the current channel. Normally
1569     * should be 0
1570     * @param {number?} start The x-offset of the beginning of the area that
1571     * should be rendered. If this isn't set only a flat line is rendered
1572     * @param {number?} end The x-offset of the end of the area that should be
1573     * rendered
1574     * @param {function} fn The render function to call, e.g. `drawWave`
1575     * @returns {void}
1576     */
1577
1578  }, {
1579    key: "prepareDraw",
1580    value: function prepareDraw(peaks, channelIndex, start, end, fn) {
1581      var _this7 = this;
1582
1583      return util.frame(function () {
1584        // Split channels and call this function with the channelIndex set
1585        if (peaks[0] instanceof Array) {
1586          var channels = peaks;
1587
1588          if (_this7.params.splitChannels) {
1589            _this7.setHeight(channels.length * _this7.params.height * _this7.params.pixelRatio);
1590
1591            return channels.forEach(function (channelPeaks, i) {
1592              return _this7.prepareDraw(channelPeaks, i, start, end, fn);
1593            });
1594          }
1595
1596          peaks = channels[0];
1597        } // calculate maximum modulation value, either from the barHeight
1598        // parameter or if normalize=true from the largest value in the peak
1599        // set
1600
1601
1602        var absmax = 1 / _this7.params.barHeight;
1603
1604        if (_this7.params.normalize) {
1605          var max = util.max(peaks);
1606          var min = util.min(peaks);
1607          absmax = -min > max ? -min : max;
1608        } // Bar wave draws the bottom only as a reflection of the top,
1609        // so we don't need negative values
1610
1611
1612        var hasMinVals = [].some.call(peaks, function (val) {
1613          return val < 0;
1614        });
1615        var height = _this7.params.height * _this7.params.pixelRatio;
1616        var offsetY = height * channelIndex || 0;
1617        var halfH = height / 2;
1618        return fn({
1619          absmax: absmax,
1620          hasMinVals: hasMinVals,
1621          height: height,
1622          offsetY: offsetY,
1623          halfH: halfH,
1624          peaks: peaks
1625        });
1626      })();
1627    }
1628    /**
1629     * Set the fill styles for a certain entry (wave and progress)
1630     *
1631     * @private
1632     * @param {CanvasEntry} entry Target entry
1633     */
1634
1635  }, {
1636    key: "setFillStyles",
1637    value: function setFillStyles(entry) {
1638      entry.setFillStyles(this.params.waveColor, this.params.progressColor);
1639    }
1640    /**
1641     * Return image data of the multi-canvas
1642     *
1643     * When using a `type` of `'blob'`, this will return a `Promise`.
1644     *
1645     * @param {string} format='image/png' An optional value of a format type.
1646     * @param {number} quality=0.92 An optional value between 0 and 1.
1647     * @param {string} type='dataURL' Either 'dataURL' or 'blob'.
1648     * @return {string|string[]|Promise} When using the default `'dataURL'`
1649     * `type` this returns a single data URL or an array of data URLs,
1650     * one for each canvas. When using the `'blob'` `type` this returns a
1651     * `Promise` that resolves with an array of `Blob` instances, one for each
1652     * canvas.
1653     */
1654
1655  }, {
1656    key: "getImage",
1657    value: function getImage(format, quality, type) {
1658      if (type === 'blob') {
1659        return Promise.all(this.canvases.map(function (entry) {
1660          return entry.getImage(format, quality, type);
1661        }));
1662      } else if (type === 'dataURL') {
1663        var images = this.canvases.map(function (entry) {
1664          return entry.getImage(format, quality, type);
1665        });
1666        return images.length > 1 ? images : images[0];
1667      }
1668    }
1669    /**
1670     * Render the new progress
1671     *
1672     * @param {number} position X-offset of progress position in pixels
1673     */
1674
1675  }, {
1676    key: "updateProgress",
1677    value: function updateProgress(position) {
1678      this.style(this.progressWave, {
1679        width: position + 'px'
1680      });
1681    }
1682  }]);
1683
1684  return MultiCanvas;
1685}(_drawer.default);
1686
1687exports.default = MultiCanvas;
1688module.exports = exports.default;
1689
1690/***/ }),
1691
vendor: 4,817 bytes, lines 1692-1773
1692/***/ "./src/mediaelement-webaudio.js":
1693/*!**************************************!*\
1694  !*** ./src/mediaelement-webaudio.js ***!
1695  \**************************************/
1696/*! no static exports found */
1697/***/ (function(module, exports, __webpack_require__) {
1698
1699"use strict";
1700
1701
1702Object.defineProperty(exports, "__esModule", {
1703  value: true
1704});
1705exports.default = void 0;
1706
1707var _mediaelement = _interopRequireDefault(__webpack_require__(/*! ./mediaelement */ "./src/mediaelement.js"));
1708
1709function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
1710
1711function _typeof(obj) { 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); }
1712
1713function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
1714
1715function _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); } }
1716
1717function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
1718
1719function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
1720
1721function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
1722
1723function _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); }
1724
1725function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }
1726
1727function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
1728
1729function _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); }
1730
1731function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
1732
1733/**
1734 * MediaElementWebAudio backend: allows to load audio as HTML5 audio tag and use it with WebAudio API.
1735 * Setting the MediaElementWebAudio backend, there is the possibility to load audio of big dimensions, using the WebAudio API features.
1736 * The audio to load is an HTML5 audio tag, so you have to use the same methods of MediaElement backend for loading and playback.
1737 * In this way, the audio resource is not loaded entirely from server, but in ranges, since you load an HTML5 audio tag.
1738 * In this way, filters and other functionalities can be performed like with WebAudio backend, but without decoding
1739 * internally audio data, that caused crashing of the browser. You have to give also peaks, so the audio data are not decoded.
1740 *
1741 * @since 3.2.0
1742 */
1743var MediaElementWebAudio =
1744/*#__PURE__*/
1745function (_MediaElement) {
1746  _inherits(MediaElementWebAudio, _MediaElement);
1747
1748  /**
1749   * Construct the backend
1750   *
1751   * @param {WavesurferParams} params Wavesurfer parameters
1752   */
1753  function MediaElementWebAudio(params) {
1754    var _this;
1755
1756    _classCallCheck(this, MediaElementWebAudio);
1757
1758    _this = _possibleConstructorReturn(this, _getPrototypeOf(MediaElementWebAudio).call(this, params));
1759    /** @private */
1760
1761    _this.params = params;
1762    /** @private */
1763
1764    _this.sourceMediaElement = null;
1765    return _this;
1766  }
1767  /**
1768   * Initialise the backend, called in `wavesurfer.createBackend()`
1769   */
1770
1771
1772  _createClass(MediaElementWebAudio, [{
1773    key: "init",
1774    value: function init() {
1775      this.setPlaybackRate(this.params.audioRate);
1776      this.createTimer();
1777      this.createVolumeNode();
1778      this.createScriptNode();
1779      this.createAnalyserNode();
1780    }
1781    /**
1782     * Private method called by both `load` (from url)
1783     * and `loadElt` (existing media element) methods.
1784     *
1785     * @param {HTMLMediaElement} media HTML5 Audio or Video element
1786     * @param {number[]|Number.<Array[]>} peaks Array of peak data
1787     * @private
1788     */
1789
1790  }, {
1791    key: "_load",
1792    value: function _load(media, peaks) {
1793      _get(_getPrototypeOf(MediaElementWebAudio.prototype), "_load", this).call(this, media, peaks);
1794
1795      this.createMediaElementSource(media);
1796    }
1797    /**
1798     * Create MediaElementSource node
1799     *
1800     * @since 3.2.0
1801     * @param {HTMLMediaElement} mediaElement HTML5 Audio to load
1802     */
1803
1804  }, {
1805    key: "createMediaElementSource",
1806    value: function createMediaElementSource(mediaElement) {
1807      this.sourceMediaElement = this.ac.createMediaElementSource(mediaElement);
1808      this.sourceMediaElement.connect(this.analyser);
1809    }
1810  }]);
1811
1812  return MediaElementWebAudio;
1813}(_mediaelement.default);
1814
1815exports.default = MediaElementWebAudio;
1816module.exports = exports.default;
1817
1818/***/ }),
1819
1820/***/ "./src/mediaelement.js":
1821/*!*****************************!*\
1822  !*** ./src/mediaelement.js ***!
1823  \*****************************/
1824/*! no static exports found */
1825/***/ (function(module, exports, __webpack_require__) {
1826
1827"use strict";
1828
1829
1830Object.defineProperty(exports, "__esModule", {
1831  value: true
1832});
1833exports.default = void 0;
1834
1835var _webaudio = _interopRequireDefault(__webpack_require__(/*! ./webaudio */ "./src/webaudio.js"));
1836
1837var util = _interopRequireWildcard(__webpack_require__(/*! ./util */ "./src/util/index.js"));
1838
1839function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }
1840
1841function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (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; }
1842
1843function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
1844
1845function _typeof(obj) { 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); }
1846
1847function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
1848
1849function _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); } }
1850
1851function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
1852
1853function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
1854
1855function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
1856
1857function _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); }
1858
1859function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }
1860
1861function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
1862
1863function _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); }
1864
1865function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
1866
1867/**
1868 * MediaElement backend
1869 */
1870var MediaElement =
1871/*#__PURE__*/
1872function (_WebAudio) {
1873  _inherits(MediaElement, _WebAudio);
1874
1875  /**
1876   * Construct the backend
1877   *
1878   * @param {WavesurferParams} params Wavesurfer parameters
1879   */
1880  function MediaElement(params) {
1881    var _this;
1882
1883    _classCallCheck(this, MediaElement);
1884
1885    _this = _possibleConstructorReturn(this, _getPrototypeOf(MediaElement).call(this, params));
1886    /** @private */
1887
1888    _this.params = params;
1889    /**
1890     * Initially a dummy media element to catch errors. Once `_load` is
1891     * called, this will contain the actual `HTMLMediaElement`.
1892     * @private
1893     */
1894
1895    _this.media = {
1896      currentTime: 0,
1897      duration: 0,
1898      paused: true,
1899      playbackRate: 1,
1900      play: function play() {},
1901      pause: function pause() {},
1902      volume: 0
1903    };
1904    /** @private */
1905
1906    _this.mediaType = params.mediaType.toLowerCase();
1907    /** @private */
1908
1909    _this.elementPosition = params.elementPosition;
1910    /** @private */
1911
1912    _this.peaks = null;
1913    /** @private */
1914
1915    _this.playbackRate = 1;
1916    /** @private */
1917
1918    _this.volume = 1;
1919    /** @private */
1920
1921    _this.isMuted = false;
1922    /** @private */
1923
1924    _this.buffer = null;
1925    /** @private */
1926
1927    _this.onPlayEnd = null;
1928    /** @private */
1929
1930    _this.mediaListeners = {};
1931    return _this;
1932  }
1933  /**
1934   * Initialise the backend, called in `wavesurfer.createBackend()`
1935   */
1936
1937
1938  _createClass(MediaElement, [{
1939    key: "init",
1940    value: function init() {
1941      this.setPlaybackRate(this.params.audioRate);
1942      this.createTimer();
1943    }
1944    /**
1945     * Attach event listeners to media element.
1946     */
1947
1948  }, {
1949    key: "_setupMediaListeners",
1950    value: function _setupMediaListeners() {
1951      var _this2 = this;
1952
1953      this.mediaListeners.error = function () {
1954        _this2.fireEvent('error', 'Error loading media element');
1955      };
1956
1957      this.mediaListeners.canplay = function () {
1958        _this2.fireEvent('canplay');
1959      };
1960
1961      this.mediaListeners.ended = function () {
1962        _this2.fireEvent('finish');
1963      }; // listen to and relay play, pause and seeked events to enable
1964      // playback control from the external media element
1965
1966
1967      this.mediaListeners.play = function () {
1968        _this2.fireEvent('play');
1969      };
1970
1971      this.mediaListeners.pause = function () {
1972        _this2.fireEvent('pause');
1973      };
1974
1975      this.mediaListeners.seeked = function (event) {
1976        _this2.fireEvent('seek');
1977      };
1978
1979      this.mediaListeners.volumechange = function (event) {
1980        _this2.isMuted = _this2.media.muted;
1981
1982        if (_this2.isMuted) {
1983          _this2.volume = 0;
1984        } else {
1985          _this2.volume = _this2.media.volume;
1986        }
1987
1988        _this2.fireEvent('volume');
1989      }; // reset event listeners
1990
1991
1992      Object.keys(this.mediaListeners).forEach(function (id) {
1993        _this2.media.removeEventListener(id, _this2.mediaListeners[id]);
1994
1995        _this2.media.addEventListener(id, _this2.mediaListeners[id]);
1996      });
1997    }
1998    /**
1999     * Create a timer to provide a more precise `audioprocess` event.
2000     */
2001
2002  }, {
2003    key: "createTimer",
2004    value: function createTimer() {
2005      var _this3 = this;
2006
2007      var onAudioProcess = function onAudioProcess() {
2008        if (_this3.isPaused()) {
2009          return;
2010        }
2011
2012        _this3.fireEvent('audioprocess', _this3.getCurrentTime()); // Call again in the next frame
2013
2014
2015        util.frame(onAudioProcess)();
2016      };
2017
2018      this.on('play', onAudioProcess); // Update the progress one more time to prevent it from being stuck in
2019      // case of lower framerates
2020
2021      this.on('pause', function () {
2022        _this3.fireEvent('audioprocess', _this3.getCurrentTime());
2023      });
2024    }
2025    /**
2026     * Create media element with url as its source,
2027     * and append to container element.
2028     *
2029     * @param {string} url Path to media file
2030     * @param {HTMLElement} container HTML element
2031     * @param {number[]|Number.<Array[]>} peaks Array of peak data
2032     * @param {string} preload HTML 5 preload attribute value
2033     * @throws Will throw an error if the `url` argument is not a valid media
2034     * element.
2035     */
2036
2037  }, {
2038    key: "load",
2039    value: function load(url, container, peaks, preload) {
2040      var media = document.createElement(this.mediaType);
2041      media.controls = this.params.mediaControls;
2042      media.autoplay = this.params.autoplay || false;
2043      media.preload = preload == null ? 'auto' : preload;
2044      media.src = url;
2045      media.style.width = '100%';
2046      var prevMedia = container.querySelector(this.mediaType);
2047
2048      if (prevMedia) {
2049        container.removeChild(prevMedia);
2050      }
2051
2052      container.appendChild(media);
2053
2054      this._load(media, peaks);
2055    }
2056    /**
2057     * Load existing media element.
2058     *
2059     * @param {HTMLMediaElement} elt HTML5 Audio or Video element
2060     * @param {number[]|Number.<Array[]>} peaks Array of peak data
2061     */
2062
2063  }, {
2064    key: "loadElt",
2065    value: function loadElt(elt, peaks) {
2066      elt.controls = this.params.mediaControls;
2067      elt.autoplay = this.params.autoplay || false;
2068
2069      this._load(elt, peaks);
2070    }
2071    /**
2072     * Method called by both `load` (from url)
2073     * and `loadElt` (existing media element) methods.
2074     *
2075     * @param {HTMLMediaElement} media HTML5 Audio or Video element
2076     * @param {number[]|Number.<Array[]>} peaks Array of peak data
2077     * @throws Will throw an error if the `media` argument is not a valid media
2078     * element.
2079     * @private
2080     */
2081
2082  }, {
2083    key: "_load",
2084    value: function _load(media, peaks) {
2085      // verify media element is valid
2086      if (!(media instanceof HTMLMediaElement) || typeof media.addEventListener === 'undefined') {
2087        throw new Error('media parameter is not a valid media element');
2088      } // load must be called manually on iOS, otherwise peaks won't draw
2089      // until a user interaction triggers load --> 'ready' event
2090
2091
2092      if (typeof media.load == 'function') {
2093        // Resets the media element and restarts the media resource. Any
2094        // pending events are discarded. How much media data is fetched is
2095        // still affected by the preload attribute.
2096        media.load();
2097      }
2098
2099      this.media = media;
2100
2101      this._setupMediaListeners();
2102
2103      this.peaks = peaks;
2104      this.onPlayEnd = null;
2105      this.buffer = null;
2106      this.isMuted = media.muted;
2107      this.setPlaybackRate(this.playbackRate);
2108      this.setVolume(this.volume);
2109    }
2110    /**
2111     * Used by `wavesurfer.isPlaying()` and `wavesurfer.playPause()`
2112     *
2113     * @return {boolean} Media paused or not
2114     */
2115
2116  }, {
2117    key: "isPaused",
2118    value: function isPaused() {
2119      return !this.media || this.media.paused;
2120    }
2121    /**
2122     * Used by `wavesurfer.getDuration()`
2123     *
2124     * @return {number} Duration
2125     */
2126
2127  }, {
2128    key: "getDuration",
2129    value: function getDuration() {
2130      if (this.explicitDuration) {
2131        return this.explicitDuration;
2132      }
2133
2134      var duration = (this.buffer || this.media).duration;
2135
2136      if (duration >= Infinity) {
2137        // streaming audio
2138        duration = this.media.seekable.end(0);
2139      }
2140
2141      return duration;
2142    }
2143    /**
2144     * Returns the current time in seconds relative to the audio-clip's
2145     * duration.
2146     *
2147     * @return {number} Current time
2148     */
2149
2150  }, {
2151    key: "getCurrentTime",
2152    value: function getCurrentTime() {
2153      return this.media && this.media.currentTime;
2154    }
2155    /**
2156     * Get the position from 0 to 1
2157     *
2158     * @return {number} Current position
2159     */
2160
2161  }, {
2162    key: "getPlayedPercents",
2163    value: function getPlayedPercents() {
2164      return this.getCurrentTime() / this.getDuration() || 0;
2165    }
2166    /**
2167     * Get the audio source playback rate.
2168     *
2169     * @return {number} Playback rate
2170     */
2171
2172  }, {
2173    key: "getPlaybackRate",
2174    value: function getPlaybackRate() {
2175      return this.playbackRate || this.media.playbackRate;
2176    }
2177    /**
2178     * Set the audio source playback rate.
2179     *
2180     * @param {number} value Playback rate
2181     */
2182
2183  }, {
2184    key: "setPlaybackRate",
2185    value: function setPlaybackRate(value) {
2186      this.playbackRate = value || 1;
2187      this.media.playbackRate = this.playbackRate;
2188    }
2189    /**
2190     * Used by `wavesurfer.seekTo()`
2191     *
2192     * @param {number} start Position to start at in seconds
2193     */
2194
2195  }, {
2196    key: "seekTo",
2197    value: function seekTo(start) {
2198      if (start != null) {
2199        this.media.currentTime = start;
2200      }
2201
2202      this.clearPlayEnd();
2203    }
2204    /**
2205     * Plays the loaded audio region.
2206     *
2207     * @param {number} start Start offset in seconds, relative to the beginning
2208     * of a clip.
2209     * @param {number} end When to stop, relative to the beginning of a clip.
2210     * @emits MediaElement#play
2211     * @return {Promise} Result
2212     */
2213
2214  }, {
2215    key: "play",
2216    value: function play(start, end) {
2217      this.seekTo(start);
2218      var promise = this.media.play();
2219      end && this.setPlayEnd(end);
2220      return promise;
2221    }
2222    /**
2223     * Pauses the loaded audio.
2224     *
2225     * @emits MediaElement#pause
2226     * @return {Promise} Result
2227     */
2228
2229  }, {
2230    key: "pause",
2231    value: function pause() {
2232      var promise;
2233
2234      if (this.media) {
2235        promise = this.media.pause();
2236      }
2237
2238      this.clearPlayEnd();
2239      return promise;
2240    }
2241    /**
2242     * Set the play end
2243     *
2244     * @param {number} end Where to end
2245     */
2246
2247  }, {
2248    key: "setPlayEnd",
2249    value: function setPlayEnd(end) {
2250      var _this4 = this;
2251
2252      this.clearPlayEnd();
2253
2254      this._onPlayEnd = function (time) {
2255        if (time >= end) {
2256          _this4.pause();
2257
2258          _this4.seekTo(end);
2259        }
2260      };
2261
2262      this.on('audioprocess', this._onPlayEnd);
2263    }
2264    /** @private */
2265
2266  }, {
2267    key: "clearPlayEnd",
2268    value: function clearPlayEnd() {
2269      if (this._onPlayEnd) {
2270        this.un('audioprocess', this._onPlayEnd);
2271        this._onPlayEnd = null;
2272      }
2273    }
2274    /**
2275     * Compute the max and min value of the waveform when broken into
2276     * <length> subranges.
2277     *
2278     * @param {number} length How many subranges to break the waveform into.
2279     * @param {number} first First sample in the required range.
2280     * @param {number} last Last sample in the required range.
2281     * @return {number[]|Number.<Array[]>} Array of 2*<length> peaks or array of
2282     * arrays of peaks consisting of (max, min) values for each subrange.
2283     */
2284
2285  }, {
2286    key: "getPeaks",
2287    value: function getPeaks(length, first, last) {
2288      if (this.buffer) {
2289        return _get(_getPrototypeOf(MediaElement.prototype), "getPeaks", this).call(this, length, first, last);
2290      }
2291
2292      return this.peaks || [];
2293    }
2294    /**
2295     * Set the sink id for the media player
2296     *
2297     * @param {string} deviceId String value representing audio device id.
2298     * @returns {Promise} A Promise that resolves to `undefined` when there
2299     * are no errors.
2300     */
2301
2302  }, {
2303    key: "setSinkId",
2304    value: function setSinkId(deviceId) {
2305      if (deviceId) {
2306        if (!this.media.setSinkId) {
2307          return Promise.reject(new Error('setSinkId is not supported in your browser'));
2308        }
2309
2310        return this.media.setSinkId(deviceId);
2311      }
2312
2313      return Promise.reject(new Error('Invalid deviceId: ' + deviceId));
2314    }
2315    /**
2316     * Get the current volume
2317     *
2318     * @return {number} value A floating point value between 0 and 1.
2319     */
2320
2321  }, {
2322    key: "getVolume",
2323    value: function getVolume() {
2324      return this.volume;
2325    }
2326    /**
2327     * Set the audio volume
2328     *
2329     * @param {number} value A floating point value between 0 and 1.
2330     */
2331
2332  }, {
2333    key: "setVolume",
2334    value: function setVolume(value) {
2335      this.volume = value; // no need to change when it's already at that volume
2336
2337      if (this.media.volume !== this.volume) {
2338        this.media.volume = this.volume;
2339      }
2340    }
2341    /**
2342     * This is called when wavesurfer is destroyed
2343     *
2344     */
2345
2346  }, {
2347    key: "destroy",
2348    value: function destroy() {
2349      var _this5 = this;
2350
2351      this.pause();
2352      this.unAll();
2353      this.destroyed = true; // cleanup media event listeners
2354
2355      Object.keys(this.mediaListeners).forEach(function (id) {
2356        if (_this5.media) {
2357          _this5.media.removeEventListener(id, _this5.mediaListeners[id]);
2358        }
2359      });
2360
2361      if (this.params.removeMediaElementOnDestroy && this.media && this.media.parentNode) {
2362        this.media.parentNode.removeChild(this.media);
2363      }
2364
2365      this.media = null;
2366    }
2367  }]);
2368
2369  return MediaElement;
2370}(_webaudio.default);
2371
2372exports.default = MediaElement;
2373module.exports = exports.default;
2374
2375/***/ }),
2376
2377/***/ "./src/peakcache.js":
2378/*!**************************!*\
2379  !*** ./src/peakcache.js ***!
2380  \**************************/
2381/*! no static exports found */
2382/***/ (function(module, exports, __webpack_require__) {
2383
2384"use strict";
2385
2386
2387Object.defineProperty(exports, "__esModule", {
2388  value: true
2389});
2390exports.default = void 0;
2391
2392function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
2393
2394function _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); } }
2395
2396function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
2397
2398/**
2399 * Caches the decoded peaks data to improve rendering speed for large audio
2400 *
2401 * Is used if the option parameter `partialRender` is set to `true`
2402 */
2403var PeakCache =
2404/*#__PURE__*/
2405function () {
2406  /**
2407   * Instantiate cache
2408   */
2409  function PeakCache() {
2410    _classCallCheck(this, PeakCache);
2411
2412    this.clearPeakCache();
2413  }
2414  /**
2415   * Empty the cache
2416   */
2417
2418
2419  _createClass(PeakCache, [{
2420    key: "clearPeakCache",
2421    value: function clearPeakCache() {
2422      /**
2423       * Flat array with entries that are always in pairs to mark the
2424       * beginning and end of each subrange.  This is a convenience so we can
2425       * iterate over the pairs for easy set difference operations.
2426       * @private
2427       */
2428      this.peakCacheRanges = [];
2429      /**
2430       * Length of the entire cachable region, used for resetting the cache
2431       * when this changes (zoom events, for instance).
2432       * @private
2433       */
2434
2435      this.peakCacheLength = -1;
2436    }
2437    /**
2438     * Add a range of peaks to the cache
2439     *
2440     * @param {number} length The length of the range
2441     * @param {number} start The x offset of the start of the range
2442     * @param {number} end The x offset of the end of the range
2443     * @return {Number.<Array[]>} Array with arrays of numbers
2444     */
2445
2446  }, {
2447    key: "addRangeToPeakCache",
2448    value: function addRangeToPeakCache(length, start, end) {
2449      if (length != this.peakCacheLength) {
2450        this.clearPeakCache();
2451        this.peakCacheLength = length;
2452      } // Return ranges that weren't in the cache before the call.
2453
2454
2455      var uncachedRanges = [];
2456      var i = 0; // Skip ranges before the current start.
2457
2458      while (i < this.peakCacheRanges.length && this.peakCacheRanges[i] < start) {
2459        i++;
2460      } // If |i| is even, |start| falls after an existing range.  Otherwise,
2461      // |start| falls between an existing range, and the uncached region
2462      // starts when we encounter the next node in |peakCacheRanges| or
2463      // |end|, whichever comes first.
2464
2465
2466      if (i % 2 == 0) {
2467        uncachedRanges.push(start);
2468      }
2469
2470      while (i < this.peakCacheRanges.length && this.peakCacheRanges[i] <= end) {
2471        uncachedRanges.push(this.peakCacheRanges[i]);
2472        i++;
2473      } // If |i| is even, |end| is after all existing ranges.
2474
2475
2476      if (i % 2 == 0) {
2477        uncachedRanges.push(end);
2478      } // Filter out the 0-length ranges.
2479
2480
2481      uncachedRanges = uncachedRanges.filter(function (item, pos, arr) {
2482        if (pos == 0) {
2483          return item != arr[pos + 1];
2484        } else if (pos == arr.length - 1) {
2485          return item != arr[pos - 1];
2486        }
2487
2488        return item != arr[pos - 1] && item != arr[pos + 1];
2489      }); // Merge the two ranges together, uncachedRanges will either contain
2490      // wholly new points, or duplicates of points in peakCacheRanges.  If
2491      // duplicates are detected, remove both and extend the range.
2492
2493      this.peakCacheRanges = this.peakCacheRanges.concat(uncachedRanges);
2494      this.peakCacheRanges = this.peakCacheRanges.sort(function (a, b) {
2495        return a - b;
2496      }).filter(function (item, pos, arr) {
2497        if (pos == 0) {
2498          return item != arr[pos + 1];
2499        } else if (pos == arr.length - 1) {
2500          return item != arr[pos - 1];
2501        }
2502
2503        return item != arr[pos - 1] && item != arr[pos + 1];
2504      }); // Push the uncached ranges into an array of arrays for ease of
2505      // iteration in the functions that call this.
2506
2507      var uncachedRangePairs = [];
2508
2509      for (i = 0; i < uncachedRanges.length; i += 2) {
2510        uncachedRangePairs.push([uncachedRanges[i], uncachedRanges[i + 1]]);
2511      }
2512
2513      return uncachedRangePairs;
2514    }
2515    /**
2516     * For testing
2517     *
2518     * @return {Number.<Array[]>} Array with arrays of numbers
2519     */
2520
2521  }, {
2522    key: "getCacheRanges",
2523    value: function getCacheRanges() {
2524      var peakCacheRangePairs = [];
2525      var i;
2526
2527      for (i = 0; i < this.peakCacheRanges.length; i += 2) {
2528        peakCacheRangePairs.push([this.peakCacheRanges[i], this.peakCacheRanges[i + 1]]);
2529      }
2530
2531      return peakCacheRangePairs;
2532    }
2533  }]);
2534
2535  return PeakCache;
2536}();
2537
2538exports.default = PeakCache;
2539module.exports = exports.default;
2540
2541/***/ }),
2542
2543/***/ "./src/util/ajax.js":
2544/*!**************************!*\
2545  !*** ./src/util/ajax.js ***!
2546  \**************************/
2547/*! no static exports found */
2548/***/ (function(module, exports, __webpack_require__) {
2549
2550"use strict";
2551
2552
2553Object.defineProperty(exports, "__esModule", {
2554  value: true
2555});
2556exports.default = ajax;
2557
2558var _observer = _interopRequireDefault(__webpack_require__(/*! ./observer */ "./src/util/observer.js"));
2559
2560function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
2561
2562/**
2563 * Perform an ajax request using `XMLHttpRequest`.
2564 *
2565 * @deprecated Use `util.fetchFile` instead.
2566 *
2567 * @param {Object} options AJAX options to use. See example below for options.
2568 * @returns {Observer} Observer instance
2569 * @example
2570 * // default options
2571 * let options = {
2572 *     method: 'GET',
2573 *     url: undefined,
2574 *     responseType: 'json',
2575 *     xhr: {}
2576 * };
2577 *
2578 * // override default options
2579 * options.url = '../media/demo.wav';
2580 * options.responseType = 'arraybuffer';
2581 * options.xhr = {
2582 *     requestHeaders: [
2583 *         {
2584 *             key: 'Authorization',
2585 *             value: 'my-token'
2586 *         }
2587 *     ],
2588 *     withCredentials: true
2589 * };
2590 *
2591 * // make ajax call
2592 * let ajaxCall = util.ajax(options);
2593 * ajaxCall.on('progress', e => {
2594 *     console.log('progress', e);
2595 * });
2596 * ajaxCall.on('success', (data, e) => {
2597 *     console.log('success!', data);
2598 * });
2599 * ajaxCall.on('error', e => {
2600 *     console.warn('ajax error: ' + e.target.statusText);
2601 * });
2602 */
2603function ajax(options) {
2604  var instance = new _observer.default();
2605  var xhr = new XMLHttpRequest();
2606  var fired100 = false;
2607  xhr.open(options.method || 'GET', options.url, true);
2608  xhr.responseType = options.responseType || 'json';
2609
2610  if (options.xhr) {
2611    if (options.xhr.requestHeaders) {
2612      // add custom request headers
2613      options.xhr.requestHeaders.forEach(function (header) {
2614        xhr.setRequestHeader(header.key, header.value);
2615      });
2616    }
2617
2618    if (options.xhr.withCredentials) {
2619      // use credentials
2620      xhr.withCredentials = true;
2621    }
2622  }
2623
2624  xhr.addEventListener('progress', function (e) {
2625    instance.fireEvent('progress', e);
2626
2627    if (e.lengthComputable && e.loaded == e.total) {
2628      fired100 = true;
2629    }
2630  });
2631  xhr.addEventListener('load', function (e) {
2632    if (!fired100) {
2633      instance.fireEvent('progress', e);
2634    }
2635
2636    instance.fireEvent('load', e);
2637
2638    if (200 == xhr.status || 206 == xhr.status) {
2639      instance.fireEvent('success', xhr.response, e);
2640    } else {
2641      instance.fireEvent('error', e);
2642    }
2643  });
2644  xhr.addEventListener('error', function (e) {
2645    return instance.fireEvent('error', e);
2646  });
2647  xhr.send();
2648  instance.xhr = xhr;
2649  return instance;
2650}
2651
2652module.exports = exports.default;
2653
2654/***/ }),
2655
2656/***/ "./src/util/extend.js":
2657/*!****************************!*\
2658  !*** ./src/util/extend.js ***!
2659  \****************************/
2660/*! no static exports found */
2661/***/ (function(module, exports, __webpack_require__) {
2662
2663"use strict";
2664
2665
2666Object.defineProperty(exports, "__esModule", {
2667  value: true
2668});
2669exports.default = extend;
2670
2671/* eslint no-console: ["error", { allow: ["warn"] }] */
2672
2673/**
2674 * Extend an object shallowly with others
2675 *
2676 * @param {Object} dest The target object
2677 * @param {Object[]} sources The objects to use for extending
2678 *
2679 * @return {Object} Merged object
2680 * @deprecated since version 3.3.0
2681 */
2682function extend(dest) {
2683  console.warn('util.extend is deprecated; use Object.assign instead');
2684
2685  for (var _len = arguments.length, sources = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
2686    sources[_key - 1] = arguments[_key];
2687  }
2688
2689  sources.forEach(function (source) {
2690    Object.keys(source).forEach(function (key) {
2691      dest[key] = source[key];
2692    });
2693  });
2694  return dest;
2695}
2696
2697module.exports = exports.default;
2698
2699/***/ }),
2700
2701/***/ "./src/util/fetch.js":
2702/*!***************************!*\
2703  !*** ./src/util/fetch.js ***!
2704  \***************************/
2705/*! no static exports found */
2706/***/ (function(module, exports, __webpack_require__) {
2707
2708"use strict";
2709
2710
2711Object.defineProperty(exports, "__esModule", {
2712  value: true
2713});
2714exports.default = fetchFile;
2715
2716var _observer = _interopRequireDefault(__webpack_require__(/*! ./observer */ "./src/util/observer.js"));
2717
2718function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
2719
2720function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
2721
2722function _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); } }
2723
2724function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
2725
2726var ProgressHandler =
2727/*#__PURE__*/
2728function () {
2729  /**
2730   * Instantiate ProgressHandler
2731   *
2732   * @param {Observer} instance The `fetchFile` observer instance.
2733   * @param {Number} contentLength Content length.
2734   * @param {Response} response Response object.
2735   */
2736  function ProgressHandler(instance, contentLength, response) {
2737    _classCallCheck(this, ProgressHandler);
2738
2739    this.instance = instance;
2740    this.instance._reader = response.body.getReader();
2741    this.total = parseInt(contentLength, 10);
2742    this.loaded = 0;
2743  }
2744  /**
2745   * A method that is called once, immediately after the `ReadableStream``
2746   * is constructed.
2747   *
2748   * @param {ReadableStreamDefaultController} controller Controller instance
2749   *     used to control the stream.
2750   */
2751
2752
2753  _createClass(ProgressHandler, [{
2754    key: "start",
2755    value: function start(controller) {
2756      var _this = this;
2757
2758      var read = function read() {
2759        // instance._reader.read() returns a promise that resolves
2760        // when a value has been received
2761        _this.instance._reader.read().then(function (_ref) {
2762          var done = _ref.done,
2763              value = _ref.value;
2764
2765          // result objects contain two properties:
2766          // done  - true if the stream has already given you all its data.
2767          // value - some data. Always undefined when done is true.
2768          if (done) {
2769            // ensure onProgress called when content-length=0
2770            if (_this.total === 0) {
2771              _this.instance.onProgress.call(_this.instance, {
2772                loaded: _this.loaded,
2773                total: _this.total,
2774                lengthComputable: false
2775              });
2776            } // no more data needs to be consumed, close the stream
2777
2778
2779            controller.close();
2780            return;
2781          }
2782
2783          _this.loaded += value.byteLength;
2784
2785          _this.instance.onProgress.call(_this.instance, {
2786            loaded: _this.loaded,
2787            total: _this.total,
2788            lengthComputable: !(_this.total === 0)
2789          }); // enqueue the next data chunk into our target stream
2790
2791
2792          controller.enqueue(value);
2793          read();
2794        }).catch(function (error) {
2795          controller.error(error);
2796        });
2797      };
2798
2799      read();
2800    }
2801  }]);
2802
2803  return ProgressHandler;
2804}();
2805/**
2806 * Load a file using `fetch`.
2807 *
2808 * @param {object} options Request options to use. See example below.
2809 * @returns {Observer} Observer instance
2810 * @example
2811 * // default options
2812 * let options = {
2813 *     url: undefined,
2814 *     method: 'GET',
2815 *     mode: 'cors',
2816 *     credentials: 'same-origin',
2817 *     cache: 'default',
2818 *     responseType: 'json',
2819 *     requestHeaders: [],
2820 *     redirect: 'follow',
2821 *     referrer: 'client'
2822 * };
2823 *
2824 * // override some options
2825 * options.url = '../media/demo.wav';
2826
2827 * // available types: 'arraybuffer', 'blob', 'json' or 'text'
2828 * options.responseType = 'arraybuffer';
2829 *
2830 * // make fetch call
2831 * let request = util.fetchFile(options);
2832 *
2833 * // listen for events
2834 * request.on('progress', e => {
2835 *     console.log('progress', e);
2836 * });
2837 *
2838 * request.on('success', data => {
2839 *     console.log('success!', data);
2840 * });
2841 *
2842 * request.on('error', e => {
2843 *     console.warn('fetchFile error: ', e);
2844 * });
2845 */
2846
2847
2848function fetchFile(options) {
2849  if (!options) {
2850    throw new Error('fetch options missing');
2851  } else if (!options.url) {
2852    throw new Error('fetch url missing');
2853  }
2854
2855  var instance = new _observer.default();
2856  var fetchHeaders = new Headers();
2857  var fetchRequest = new Request(options.url); // add ability to abort
2858
2859  instance.controller = new AbortController(); // check if headers have to be added
2860
2861  if (options && options.requestHeaders) {
2862    // add custom request headers
2863    options.requestHeaders.forEach(function (header) {
2864      fetchHeaders.append(header.key, header.value);
2865    });
2866  } // parse fetch options
2867
2868
2869  var responseType = options.responseType || 'json';
2870  var fetchOptions = {
2871    method: options.method || 'GET',
2872    headers: fetchHeaders,
2873    mode: options.mode || 'cors',
2874    credentials: options.credentials || 'same-origin',
2875    cache: options.cache || 'default',
2876    redirect: options.redirect || 'follow',
2877    referrer: options.referrer || 'client',
2878    signal: instance.controller.signal
2879  };
2880  fetch(fetchRequest, fetchOptions).then(function (response) {
2881    // store response reference
2882    instance.response = response;
2883    var progressAvailable = true;
2884
2885    if (!response.body) {
2886      // ReadableStream is not yet supported in this browser
2887      // see https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream
2888      progressAvailable = false;
2889    } // Server must send CORS header "Access-Control-Expose-Headers: content-length"
2890
2891
2892    var contentLength = response.headers.get('content-length');
2893
2894    if (contentLength === null) {
2895      // Content-Length server response header missing.
2896      // Don't evaluate download progress if we can't compare against a total size
2897      // see https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Access-Control-Expose-Headers
2898      progressAvailable = false;
2899    }
2900
2901    if (!progressAvailable) {
2902      // not able to check download progress so skip it
2903      return response;
2904    } // fire progress event when during load
2905
2906
2907    instance.onProgress = function (e) {
2908      instance.fireEvent('progress', e);
2909    };
2910
2911    return new Response(new ReadableStream(new ProgressHandler(instance, contentLength, response)), fetchOptions);
2912  }).then(function (response) {
2913    var errMsg;
2914
2915    if (response.ok) {
2916      switch (responseType) {
2917        case 'arraybuffer':
2918          return response.arrayBuffer();
2919
2920        case 'json':
2921          return response.json();
2922
2923        case 'blob':
2924          return response.blob();
2925
2926        case 'text':
2927          return response.text();
2928
2929        default:
2930          errMsg = 'Unknown responseType: ' + responseType;
2931          break;
2932      }
2933    }
2934
2935    if (!errMsg) {
2936      errMsg = 'HTTP error status: ' + response.status;
2937    }
2938
2939    throw new Error(errMsg);
2940  }).then(function (response) {
2941    instance.fireEvent('success', response);
2942  }).catch(function (error) {
2943    instance.fireEvent('error', error);
2944  }); // return the fetch request
2945
2946  instance.fetchRequest = fetchRequest;
2947  return instance;
2948}
2949
2950module.exports = exports.default;
2951
2952/***/ }),
2953
2954/***/ "./src/util/frame.js":
2955/*!***************************!*\
2956  !*** ./src/util/frame.js ***!
2957  \***************************/
2958/*! no static exports found */
2959/***/ (function(module, exports, __webpack_require__) {
2960
2961"use strict";
2962
2963
2964Object.defineProperty(exports, "__esModule", {
2965  value: true
2966});
2967exports.default = frame;
2968
2969var _requestAnimationFrame = _interopRequireDefault(__webpack_require__(/*! ./request-animation-frame */ "./src/util/request-animation-frame.js"));
2970
2971function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
2972
2973/**
2974 * Create a function which will be called at the next requestAnimationFrame
2975 * cycle
2976 *
2977 * @param {function} func The function to call
2978 *
2979 * @return {func} The function wrapped within a requestAnimationFrame
2980 */
2981function frame(func) {
2982  return function () {
2983    for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
2984      args[_key] = arguments[_key];
2985    }
2986
2987    return (0, _requestAnimationFrame.default)(function () {
2988      return func.apply(void 0, args);
2989    });
2990  };
2991}
2992
2993module.exports = exports.default;
2994
2995/***/ }),
2996
2997/***/ "./src/util/get-id.js":
2998/*!****************************!*\
2999  !*** ./src/util/get-id.js ***!
3000  \****************************/
3001/*! no static exports found */
3002/***/ (function(module, exports, __webpack_require__) {
3003
3004"use strict";
3005
3006
3007Object.defineProperty(exports, "__esModule", {
3008  value: true
3009});
3010exports.default = getId;
3011
3012/**
3013 * Get a random prefixed ID
3014 *
3015 * @param {String} prefix Prefix to use. Default is `'wavesurfer_'`.
3016 * @returns {String} Random prefixed ID
3017 * @example
3018 * console.log(getId()); // logs 'wavesurfer_b5pors4ru6g'
3019 *
3020 * let prefix = 'foo-';
3021 * console.log(getId(prefix)); // logs 'foo-b5pors4ru6g'
3022 */
3023function getId(prefix) {
3024  if (prefix === undefined) {
3025    prefix = 'wavesurfer_';
3026  }
3027
3028  return prefix + Math.random().toString(32).substring(2);
3029}
3030
3031module.exports = exports.default;
3032
3033/***/ }),
3034
3035/***/ "./src/util/index.js":
3036/*!***************************!*\
3037  !*** ./src/util/index.js ***!
3038  \***************************/
3039/*! no static exports found */
3040/***/ (function(module, exports, __webpack_require__) {
3041
3042"use strict";
3043
3044
3045Object.defineProperty(exports, "__esModule", {
3046  value: true
3047});
3048Object.defineProperty(exports, "ajax", {
3049  enumerable: true,
3050  get: function get() {
3051    return _ajax.default;
3052  }
3053});
3054Object.defineProperty(exports, "getId", {
3055  enumerable: true,
3056  get: function get() {
3057    return _getId.default;
3058  }
3059});
3060Object.defineProperty(exports, "max", {
3061  enumerable: true,
3062  get: function get() {
3063    return _max.default;
3064  }
3065});
3066Object.defineProperty(exports, "min", {
3067  enumerable: true,
3068  get: function get() {
3069    return _min.default;
3070  }
3071});
3072Object.defineProperty(exports, "Observer", {
3073  enumerable: true,
3074  get: function get() {
3075    return _observer.default;
3076  }
3077});
3078Object.defineProperty(exports, "extend", {
3079  enumerable: true,
3080  get: function get() {
3081    return _extend.default;
3082  }
3083});
3084Object.defineProperty(exports, "style", {
3085  enumerable: true,
3086  get: function get() {
3087    return _style.default;
3088  }
3089});
3090Object.defineProperty(exports, "requestAnimationFrame", {
3091  enumerable: true,
3092  get: function get() {
3093    return _requestAnimationFrame.default;
3094  }
3095});
3096Object.defineProperty(exports, "frame", {
3097  enumerable: true,
3098  get: function get() {
3099    return _frame.default;
3100  }
3101});
3102Object.defineProperty(exports, "debounce", {
3103  enumerable: true,
3104  get: function get() {
3105    return _debounce.default;
3106  }
3107});
3108Object.defineProperty(exports, "preventClick", {
3109  enumerable: true,
3110  get: function get() {
3111    return _preventClick.default;
3112  }
3113});
3114Object.defineProperty(exports, "fetchFile", {
3115  enumerable: true,
3116  get: function get() {
3117    return _fetch.default;
3118  }
3119});
3120
3121var _ajax = _interopRequireDefault(__webpack_require__(/*! ./ajax */ "./src/util/ajax.js"));
3122
3123var _getId = _interopRequireDefault(__webpack_require__(/*! ./get-id */ "./src/util/get-id.js"));
3124
3125var _max = _interopRequireDefault(__webpack_require__(/*! ./max */ "./src/util/max.js"));
3126
3127var _min = _interopRequireDefault(__webpack_require__(/*! ./min */ "./src/util/min.js"));
3128
3129var _observer = _interopRequireDefault(__webpack_require__(/*! ./observer */ "./src/util/observer.js"));
3130
3131var _extend = _interopRequireDefault(__webpack_require__(/*! ./extend */ "./src/util/extend.js"));
3132
3133var _style = _interopRequireDefault(__webpack_require__(/*! ./style */ "./src/util/style.js"));
3134
3135var _requestAnimationFrame = _interopRequireDefault(__webpack_require__(/*! ./request-animation-frame */ "./src/util/request-animation-frame.js"));
3136
3137var _frame = _interopRequireDefault(__webpack_require__(/*! ./frame */ "./src/util/frame.js"));
3138
3139var _debounce = _interopRequireDefault(__webpack_require__(/*! debounce */ "./node_modules/debounce/index.js"));
3140
3141var _preventClick = _interopRequireDefault(__webpack_require__(/*! ./prevent-click */ "./src/util/prevent-click.js"));
3142
3143var _fetch = _interopRequireDefault(__webpack_require__(/*! ./fetch */ "./src/util/fetch.js"));
3144
3145function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
3146
3147/***/ }),
3148
3149/***/ "./src/util/max.js":
3150/*!*************************!*\
3151  !*** ./src/util/max.js ***!
3152  \*************************/
3153/*! no static exports found */
3154/***/ (function(module, exports, __webpack_require__) {
3155
3156"use strict";
3157
3158
3159Object.defineProperty(exports, "__esModule", {
3160  value: true
3161});
3162exports.default = max;
3163
3164/**
3165 * Get the largest value
3166 *
3167 * @param   {Array} values Array of numbers
3168 * @returns {Number} Largest number found
3169 * @example console.log(max([1, 2, 3])); // logs 3
3170 */
3171function max(values) {
3172  var largest = -Infinity;
3173  Object.keys(values).forEach(function (i) {
3174    if (values[i] > largest) {
3175      largest = values[i];
3176    }
3177  });
3178  return largest;
3179}
3180
3181module.exports = exports.default;
3182
3183/***/ }),
3184
3185/***/ "./src/util/min.js":
3186/*!*************************!*\
3187  !*** ./src/util/min.js ***!
3188  \*************************/
3189/*! no static exports found */
3190/***/ (function(module, exports, __webpack_require__) {
3191
3192"use strict";
3193
3194
3195Object.defineProperty(exports, "__esModule", {
3196  value: true
3197});
3198exports.default = min;
3199
3200/**
3201 * Get the smallest value
3202 *
3203 * @param   {Array} values Array of numbers
3204 * @returns {Number} Smallest number found
3205 * @example console.log(min([1, 2, 3])); // logs 1
3206 */
3207function min(values) {
3208  var smallest = Number(Infinity);
3209  Object.keys(values).forEach(function (i) {
3210    if (values[i] < smallest) {
3211      smallest = values[i];
3212    }
3213  });
3214  return smallest;
3215}
3216
3217module.exports = exports.default;
3218
3219/***/ }),
3220
3221/***/ "./src/util/observer.js":
3222/*!******************************!*\
3223  !*** ./src/util/observer.js ***!
3224  \******************************/
3225/*! no static exports found */
3226/***/ (function(module, exports, __webpack_require__) {
3227
3228"use strict";
3229
3230
3231Object.defineProperty(exports, "__esModule", {
3232  value: true
3233});
3234exports.default = void 0;
3235
3236function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
3237
3238function _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); } }
3239
3240function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
3241
3242/**
3243 * @typedef {Object} ListenerDescriptor
3244 * @property {string} name The name of the event
3245 * @property {function} callback The callback
3246 * @property {function} un The function to call to remove the listener
3247 */
3248
3249/**
3250 * Observer class
3251 */
3252var Observer =
3253/*#__PURE__*/
3254function () {
3255  /**
3256   * Instantiate Observer
3257   */
3258  function Observer() {
3259    _classCallCheck(this, Observer);
3260
3261    /**
3262     * @private
3263     * @todo Initialise the handlers here already and remove the conditional
3264     * assignment in `on()`
3265     */
3266    this.handlers = null;
3267  }
3268  /**
3269   * Attach a handler function for an event.
3270   *
3271   * @param {string} event Name of the event to listen to
3272   * @param {function} fn The callback to trigger when the event is fired
3273   * @return {ListenerDescriptor} The event descriptor
3274   */
3275
3276
3277  _createClass(Observer, [{
3278    key: "on",
3279    value: function on(event, fn) {
3280      var _this = this;
3281
3282      if (!this.handlers) {
3283        this.handlers = {};
3284      }
3285
3286      var handlers = this.handlers[event];
3287
3288      if (!handlers) {
3289        handlers = this.handlers[event] = [];
3290      }
3291
3292      handlers.push(fn); // Return an event descriptor
3293
3294      return {
3295        name: event,
3296        callback: fn,
3297        un: function un(e, fn) {
3298          return _this.un(e, fn);
3299        }
3300      };
3301    }
3302    /**
3303     * Remove an event handler.
3304     *
3305     * @param {string} event Name of the event the listener that should be
3306     * removed listens to
3307     * @param {function} fn The callback that should be removed
3308     */
3309
3310  }, {
3311    key: "un",
3312    value: function un(event, fn) {
3313      if (!this.handlers) {
3314        return;
3315      }
3316
3317      var handlers = this.handlers[event];
3318      var i;
3319
3320      if (handlers) {
3321        if (fn) {
3322          for (i = handlers.length - 1; i >= 0; i--) {
3323            if (handlers[i] == fn) {
3324              handlers.splice(i, 1);
3325            }
3326          }
3327        } else {
3328          handlers.length = 0;
3329        }
3330      }
3331    }
3332    /**
3333     * Remove all event handlers.
3334     */
3335
3336  }, {
3337    key: "unAll",
3338    value: function unAll() {
3339      this.handlers = null;
3340    }
3341    /**
3342     * Attach a handler to an event. The handler is executed at most once per
3343     * event type.
3344     *
3345     * @param {string} event The event to listen to
3346     * @param {function} handler The callback that is only to be called once
3347     * @return {ListenerDescriptor} The event descriptor
3348     */
3349
3350  }, {
3351    key: "once",
3352    value: function once(event, handler) {
3353      var _this2 = this;
3354
3355      var fn = function fn() {
3356        for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
3357          args[_key] = arguments[_key];
3358        }
3359
3360        /*  eslint-disable no-invalid-this */
3361        handler.apply(_this2, args);
3362        /*  eslint-enable no-invalid-this */
3363
3364        setTimeout(function () {
3365          _this2.un(event, fn);
3366        }, 0);
3367      };
3368
3369      return this.on(event, fn);
3370    }
3371    /**
3372     * Manually fire an event
3373     *
3374     * @param {string} event The event to fire manually
3375     * @param {...any} args The arguments with which to call the listeners
3376     */
3377
3378  }, {
3379    key: "fireEvent",
3380    value: function fireEvent(event) {
3381      for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
3382        args[_key2 - 1] = arguments[_key2];
3383      }
3384
3385      if (!this.handlers) {
3386        return;
3387      }
3388
3389      var handlers = this.handlers[event];
3390      handlers && handlers.forEach(function (fn) {
3391        fn.apply(void 0, args);
3392      });
3393    }
3394  }]);
3395
3396  return Observer;
3397}();
3398
3399exports.default = Observer;
3400module.exports = exports.default;
3401
3402/***/ }),
3403
3404/***/ "./src/util/prevent-click.js":
3405/*!***********************************!*\
3406  !*** ./src/util/prevent-click.js ***!
3407  \***********************************/
3408/*! no static exports found */
3409/***/ (function(module, exports, __webpack_require__) {
3410
3411"use strict";
3412
3413
3414Object.defineProperty(exports, "__esModule", {
3415  value: true
3416});
3417exports.default = preventClick;
3418
3419/**
3420 * Stops propagation of click event and removes event listener
3421 *
3422 * @private
3423 * @param {object} event The click event
3424 */
3425function preventClickHandler(event) {
3426  event.stopPropagation();
3427  document.body.removeEventListener('click', preventClickHandler, true);
3428}
3429/**
3430 * Starts listening for click event and prevent propagation
3431 *
3432 * @param {object} values Values
3433 */
3434
3435
3436function preventClick(values) {
3437  document.body.addEventListener('click', preventClickHandler, true);
3438}
3439
3440module.exports = exports.default;
3441
3442/***/ }),
3443
3444/***/ "./src/util/request-animation-frame.js":
3445/*!*********************************************!*\
3446  !*** ./src/util/request-animation-frame.js ***!
3447  \*********************************************/
3448/*! no static exports found */
3449/***/ (function(module, exports, __webpack_require__) {
3450
3451"use strict";
3452
3453
3454Object.defineProperty(exports, "__esModule", {
3455  value: true
3456});
3457exports.default = void 0;
3458
3459/* eslint-disable valid-jsdoc */
3460
3461/**
3462 * Returns the `requestAnimationFrame` function for the browser, or a shim with
3463 * `setTimeout` if the function is not found
3464 *
3465 * @return {function} Available `requestAnimationFrame` function for the browser
3466 */
3467var _default = (window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback, element) {
3468  return setTimeout(callback, 1000 / 60);
3469}).bind(window);
3470
3471exports.default = _default;
3472module.exports = exports.default;
3473
3474/***/ }),
3475
3476/***/ "./src/util/style.js":
3477/*!***************************!*\
3478  !*** ./src/util/style.js ***!
3479  \***************************/
3480/*! no static exports found */
3481/***/ (function(module, exports, __webpack_require__) {
3482
3483"use strict";
3484
3485
3486Object.defineProperty(exports, "__esModule", {
3487  value: true
3488});
3489exports.default = style;
3490
3491/**
3492 * Apply a map of styles to an element
3493 *
3494 * @param {HTMLElement} el The element that the styles will be applied to
3495 * @param {Object} styles The map of propName: attribute, both are used as-is
3496 *
3497 * @return {HTMLElement} el
3498 */
3499function style(el, styles) {
3500  Object.keys(styles).forEach(function (prop) {
3501    if (el.style[prop] !== styles[prop]) {
3502      el.style[prop] = styles[prop];
3503    }
3504  });
3505  return el;
3506}
3507
3508module.exports = exports.default;
3509
3510/***/ }),
3511
vendor: 4,746 bytes, lines 3512-3576
3512/***/ "./src/wavesurfer.js":
3513/*!***************************!*\
3514  !*** ./src/wavesurfer.js ***!
3515  \***************************/
3516/*! no static exports found */
3517/***/ (function(module, exports, __webpack_require__) {
3518
3519"use strict";
3520
3521
3522Object.defineProperty(exports, "__esModule", {
3523  value: true
3524});
3525exports.default = void 0;
3526
3527var util = _interopRequireWildcard(__webpack_require__(/*! ./util */ "./src/util/index.js"));
3528
3529var _drawer = _interopRequireDefault(__webpack_require__(/*! ./drawer.multicanvas */ "./src/drawer.multicanvas.js"));
3530
3531var _webaudio = _interopRequireDefault(__webpack_require__(/*! ./webaudio */ "./src/webaudio.js"));
3532
3533var _mediaelement = _interopRequireDefault(__webpack_require__(/*! ./mediaelement */ "./src/mediaelement.js"));
3534
3535var _peakcache = _interopRequireDefault(__webpack_require__(/*! ./peakcache */ "./src/peakcache.js"));
3536
3537var _mediaelementWebaudio = _interopRequireDefault(__webpack_require__(/*! ./mediaelement-webaudio */ "./src/mediaelement-webaudio.js"));
3538
3539function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
3540
3541function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }
3542
3543function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (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; }
3544
3545function _typeof(obj) { 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); }
3546
3547function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
3548
3549function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
3550
3551function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
3552
3553function _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); }
3554
3555function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
3556
3557function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
3558
3559function _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); } }
3560
3561function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
3562
3563/*
3564 * This work is licensed under a BSD-3-Clause License.
3565 */
3566
3567/** @external {HTMLElement} https://developer.mozilla.org/en/docs/Web/API/HTMLElement */
3568
3569/** @external {OfflineAudioContext} https://developer.mozilla.org/en-US/docs/Web/API/OfflineAudioContext */
3570
3571/** @external {File} https://developer.mozilla.org/en-US/docs/Web/API/File */
3572
3573/** @external {Blob} https://developer.mozilla.org/en-US/docs/Web/API/Blob */
3574
3575/** @external {CanvasRenderingContext2D} https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D */
3576
3577/** @external {MediaStreamConstraints} https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamConstraints */
3578
3579/** @external {AudioNode} https://developer.mozilla.org/de/docs/Web/API/AudioNode */
3580
3581/**
3582 * @typedef {Object} WavesurferParams
3583 * @property {AudioContext} audioContext=null Use your own previously
3584 * initialized AudioContext or leave blank.
3585 * @property {number} audioRate=1 Speed at which to play audio. Lower number is
3586 * slower.
3587 * @property {ScriptProcessorNode} audioScriptProcessor=null Use your own previously
3588 * initialized ScriptProcessorNode or leave blank.
3589 * @property {boolean} autoCenter=true If a scrollbar is present, center the
3590 * waveform on current progress
3591 * @property {number} autoCenterRate=5 If autoCenter is active, rate at which the
3592 * waveform is centered
3593 * @property {boolean} autoCenterImmediately=false If autoCenter is active, immediately
3594 * center waveform on current progress
3595 * @property {string} backend='WebAudio' `'WebAudio'|'MediaElement'|'MediaElementWebAudio'` In most cases
3596 * you don't have to set this manually. MediaElement is a fallback for unsupported browsers.
3597 * MediaElementWebAudio allows to use WebAudio API also with big audio files, loading audio like with
3598 * MediaElement backend (HTML5 audio tag). You have to use the same methods of MediaElement backend for loading and
3599 * playback, giving also peaks, so the audio data are not decoded. In this way you can use WebAudio features, like filters,
3600 * also with audio with big duration. For example:
3601 * ` wavesurfer.load(url | HTMLMediaElement, peaks, preload, duration);
3602 *   wavesurfer.play();
3603 *   wavesurfer.setFilter(customFilter);
3604 * `
3605 * @property {string} backgroundColor=null Change background color of the
3606 * waveform container.
3607 * @property {number} barHeight=1 The height of the wave bars.
3608 * @property {number} barRadius=0 The radius of the wave bars. Makes bars rounded
3609 * @property {number} barGap=null The optional spacing between bars of the wave,
3610 * if not provided will be calculated in legacy format.
3611 * @property {number} barWidth=null Draw the waveform using bars.
3612 * @property {number} barMinHeight=null If specified, draw at least a bar of this height,
3613 * eliminating waveform gaps
3614 * @property {boolean} closeAudioContext=false Close and nullify all audio
3615 * contexts when the destroy method is called.
3616 * @property {!string|HTMLElement} container CSS selector or HTML element where
3617 * the waveform should be drawn. This is the only required parameter.
3618 * @property {string} cursorColor='#333' The fill color of the cursor indicating
3619 * the playhead position.
3620 * @property {number} cursorWidth=1 Measured in pixels.
3621 * @property {object} drawingContextAttributes={desynchronized: false} Drawing context
3622 * attributes.
3623 * @property {number} duration=null Optional audio length so pre-rendered peaks
3624 * can be display immediately for example.
3625 * @property {boolean} fillParent=true Whether to fill the entire container or
3626 * draw only according to `minPxPerSec`.
3627 * @property {boolean} forceDecode=false Force decoding of audio using web audio
3628 * when zooming to get a more detailed waveform.
3629 * @property {number} height=128 The height of the waveform. Measured in
3630 * pixels.
3631 * @property {boolean} hideScrollbar=false Whether to hide the horizontal
3632 * scrollbar when one would normally be shown.
3633 * @property {boolean} interact=true Whether the mouse interaction will be
3634 * enabled at initialization. You can switch this parameter at any time later
3635 * on.
3636 * @property {boolean} loopSelection=true (Use with regions plugin) Enable
3637 * looping of selected regions
3638 * @property {number} maxCanvasWidth=4000 Maximum width of a single canvas in
3639 * pixels, excluding a small overlap (2 * `pixelRatio`, rounded up to the next
3640 * even integer). If the waveform is longer than this value, additional canvases
3641 * will be used to render the waveform, which is useful for very large waveforms
3642 * that may be too wide for browsers to draw on a single canvas.
3643 * @property {boolean} mediaControls=false (Use with backend `MediaElement` or `MediaElementWebAudio`)
3644 * this enables the native controls for the media element
3645 * @property {string} mediaType='audio' (Use with backend `MediaElement` or `MediaElementWebAudio`)
3646 * `'audio'|'video'` ('video' only for `MediaElement`)
3647 * @property {number} minPxPerSec=20 Minimum number of pixels per second of
3648 * audio.
3649 * @property {boolean} normalize=false If true, normalize by the maximum peak
3650 * instead of 1.0.
3651 * @property {boolean} partialRender=false Use the PeakCache to improve
3652 * rendering speed of large waveforms
3653 * @property {number} pixelRatio=window.devicePixelRatio The pixel ratio used to
3654 * calculate display
3655 * @property {PluginDefinition[]} plugins=[] An array of plugin definitions to
3656 * register during instantiation, they will be directly initialised unless they
3657 * are added with the `deferInit` property set to true.
3658 * @property {string} progressColor='#555' The fill color of the part of the
3659 * waveform behind the cursor. When `progressColor` and `waveColor` are the same
3660 * the progress wave is not rendered at all.
3661 * @property {boolean} removeMediaElementOnDestroy=true Set to false to keep the
3662 * media element in the DOM when the player is destroyed. This is useful when
3663 * reusing an existing media element via the `loadMediaElement` method.
3664 * @property {Object} renderer=MultiCanvas Can be used to inject a custom
3665 * renderer.
3666 * @property {boolean|number} responsive=false If set to `true` resize the
3667 * waveform, when the window is resized. This is debounced with a `100ms`
3668 * timeout by default. If this parameter is a number it represents that timeout.
3669 * @property {boolean} rtl=false If set to `true`, renders waveform from
3670 * right-to-left.
3671 * @property {boolean} scrollParent=false Whether to scroll the container with a
3672 * lengthy waveform. Otherwise the waveform is shrunk to the container width
3673 * (see fillParent).
3674 * @property {number} skipLength=2 Number of seconds to skip with the
3675 * skipForward() and skipBackward() methods.
3676 * @property {boolean} splitChannels=false Render with separate waveforms for
3677 * the channels of the audio
3678 * @property {string} waveColor='#999' The fill color of the waveform after the
3679 * cursor.
3680 * @property {object} xhr={} XHR options. For example:
3681 * `let xhr = {
3682 *     cache: 'default',
3683 *     mode: 'cors',
3684 *     method: 'GET',
3685 *     credentials: 'same-origin',
3686 *     redirect: 'follow',
3687 *     referrer: 'client',
3688 *     headers: [
3689 *         {
3690 *             key: 'Authorization',
3691 *             value: 'my-token'
3692 *         }
3693 *     ]
3694 * };`
3695 */
3696
3697/**
3698 * @typedef {Object} PluginDefinition
3699 * @desc The Object used to describe a plugin
3700 * @example wavesurfer.addPlugin(pluginDefinition);
3701 * @property {string} name The name of the plugin, the plugin instance will be
3702 * added as a property to the wavesurfer instance under this name
3703 * @property {?Object} staticProps The properties that should be added to the
3704 * wavesurfer instance as static properties
3705 * @property {?boolean} deferInit Don't initialise plugin
3706 * automatically
3707 * @property {Object} params={} The plugin parameters, they are the first parameter
3708 * passed to the plugin class constructor function
3709 * @property {PluginClass} instance The plugin instance factory, is called with
3710 * the dependency specified in extends. Returns the plugin class.
3711 */
3712
3713/**
3714 * @interface PluginClass
3715 *
3716 * @desc This is the interface which is implemented by all plugin classes. Note
3717 * that this only turns into an observer after being passed through
3718 * `wavesurfer.addPlugin`.
3719 *
3720 * @extends {Observer}
3721 */
3722var PluginClass =
3723/*#__PURE__*/
3724function () {
3725  _createClass(PluginClass, [{
3726    key: "create",
3727
3728    /**
3729     * Plugin definition factory
3730     *
3731     * This function must be used to create a plugin definition which can be
3732     * used by wavesurfer to correctly instantiate the plugin.
3733     *
3734     * It returns a `PluginDefinition` object representing the plugin.
3735     *
3736     * @param {Object} params={} The plugin params (specific to the plugin)
3737     */
3738    value: function create(params) {}
3739    /**
3740     * Construct the plugin
3741     *
3742     * @param {Object} params={} The plugin params (specific to the plugin)
3743     * @param {Object} ws The wavesurfer instance
3744     */
3745
3746  }]);
3747
3748  function PluginClass(params, ws) {
3749    _classCallCheck(this, PluginClass);
3750  }
3751  /**
3752   * Initialise the plugin
3753   *
3754   * Start doing something. This is called by
3755   * `wavesurfer.initPlugin(pluginName)`
3756   */
3757
3758
3759  _createClass(PluginClass, [{
3760    key: "init",
3761    value: function init() {}
3762    /**
3763     * Destroy the plugin instance
3764     *
3765     * Stop doing something. This is called by
3766     * `wavesurfer.destroyPlugin(pluginName)`
3767     */
3768
3769  }, {
3770    key: "destroy",
3771    value: function destroy() {}
3772  }]);
3773
3774  return PluginClass;
3775}();
3776/**
3777 * WaveSurfer core library class
3778 *
3779 * @extends {Observer}
3780 * @example
3781 * const params = {
3782 *   container: '#waveform',
3783 *   waveColor: 'violet',
3784 *   progressColor: 'purple'
3785 * };
3786 *
3787 * // initialise like this
3788 * const wavesurfer = WaveSurfer.create(params);
3789 *
3790 * // or like this ...
3791 * const wavesurfer = new WaveSurfer(params);
3792 * wavesurfer.init();
3793 *
3794 * // load audio file
3795 * wavesurfer.load('example/media/demo.wav');
3796 */
3797
3798
3799var WaveSurfer =
3800/*#__PURE__*/
3801function (_util$Observer) {
3802  _inherits(WaveSurfer, _util$Observer);
3803
3804  _createClass(WaveSurfer, null, [{
3805    key: "create",
3806
3807    /** @private */
3808
3809    /** @private */
3810
3811    /**
3812     * Instantiate this class, call its `init` function and returns it
3813     *
3814     * @param {WavesurferParams} params The wavesurfer parameters
3815     * @return {Object} WaveSurfer instance
3816     * @example const wavesurfer = WaveSurfer.create(params);
3817     */
3818    value: function create(params) {
3819      var wavesurfer = new WaveSurfer(params);
3820      return wavesurfer.init();
3821    }
3822    /**
3823     * The library version number is available as a static property of the
3824     * WaveSurfer class
3825     *
3826     * @type {String}
3827     * @example
3828     * console.log('Using wavesurfer.js ' + WaveSurfer.VERSION);
3829     */
3830
3831  }]);
3832
3833  /**
3834   * Initialise wavesurfer instance
3835   *
3836   * @param {WavesurferParams} params Instantiation options for wavesurfer
3837   * @example
3838   * const wavesurfer = new WaveSurfer(params);
3839   * @returns {this} Wavesurfer instance
3840   */
3841  function WaveSurfer(params) {
3842    var _this;
3843
3844    _classCallCheck(this, WaveSurfer);
3845
3846    _this = _possibleConstructorReturn(this, _getPrototypeOf(WaveSurfer).call(this));
3847    /**
3848     * Extract relevant parameters (or defaults)
3849     * @private
3850     */
3851
3852    _this.defaultParams = {
3853      audioContext: null,
3854      audioScriptProcessor: null,
3855      audioRate: 1,
3856      autoCenter: true,
3857      autoCenterRate: 5,
3858      autoCenterImmediately: false,
3859      backend: 'WebAudio',
3860      backgroundColor: null,
3861      barHeight: 1,
3862      barRadius: 0,
3863      barGap: null,
3864      barMinHeight: null,
3865      container: null,
3866      cursorColor: '#333',
3867      cursorWidth: 1,
3868      dragSelection: true,
3869      drawingContextAttributes: {
3870        // Boolean that hints the user agent to reduce the latency
3871        // by desynchronizing the canvas paint cycle from the event
3872        // loop
3873        desynchronized: false
3874      },
3875      duration: null,
3876      fillParent: true,
3877      forceDecode: false,
3878      height: 128,
3879      hideScrollbar: false,
3880      interact: true,
3881      loopSelection: true,
3882      maxCanvasWidth: 4000,
3883      mediaContainer: null,
3884      mediaControls: false,
3885      mediaType: 'audio',
3886      minPxPerSec: 20,
3887      normalize: false,
3888      partialRender: false,
3889      pixelRatio: window.devicePixelRatio || screen.deviceXDPI / screen.logicalXDPI,
3890      plugins: [],
3891      progressColor: '#555',
3892      removeMediaElementOnDestroy: true,
3893      renderer: _drawer.default,
3894      responsive: false,
3895      rtl: false,
3896      scrollParent: false,
3897      skipLength: 2,
3898      splitChannels: false,
3899      waveColor: '#999',
3900      xhr: {}
3901    };
3902    _this.backends = {
3903      MediaElement: _mediaelement.default,
3904      WebAudio: _webaudio.default,
3905      MediaElementWebAudio: _mediaelementWebaudio.default
3906    };
3907    _this.util = util;
3908    _this.params = Object.assign({}, _this.defaultParams, params);
3909    /** @private */
3910
3911    _this.container = 'string' == typeof params.container ? document.querySelector(_this.params.container) : _this.params.container;
3912
3913    if (!_this.container) {
3914      throw new Error('Container element not found');
3915    }
3916
3917    if (_this.params.mediaContainer == null) {
3918      /** @private */
3919      _this.mediaContainer = _this.container;
3920    } else if (typeof _this.params.mediaContainer == 'string') {
3921      /** @private */
3922      _this.mediaContainer = document.querySelector(_this.params.mediaContainer);
3923    } else {
3924      /** @private */
3925      _this.mediaContainer = _this.params.mediaContainer;
3926    }
3927
3928    if (!_this.mediaContainer) {
3929      throw new Error('Media Container element not found');
3930    }
3931
3932    if (_this.params.maxCanvasWidth <= 1) {
3933      throw new Error('maxCanvasWidth must be greater than 1');
3934    } else if (_this.params.maxCanvasWidth % 2 == 1) {
3935      throw new Error('maxCanvasWidth must be an even number');
3936    }
3937
3938    if (_this.params.rtl === true) {
3939      util.style(_this.container, {
3940        transform: 'rotateY(180deg)'
3941      });
3942    }
3943
3944    if (_this.params.backgroundColor) {
3945      _this.setBackgroundColor(_this.params.backgroundColor);
3946    }
3947    /**
3948     * @private Used to save the current volume when muting so we can
3949     * restore once unmuted
3950     * @type {number}
3951     */
3952
3953
3954    _this.savedVolume = 0;
3955    /**
3956     * @private The current muted state
3957     * @type {boolean}
3958     */
3959
3960    _this.isMuted = false;
3961    /**
3962     * @private Will hold a list of event descriptors that need to be
3963     * canceled on subsequent loads of audio
3964     * @type {Object[]}
3965     */
3966
3967    _this.tmpEvents = [];
3968    /**
3969     * @private Holds any running audio downloads
3970     * @type {Observer}
3971     */
3972
3973    _this.currentRequest = null;
3974    /** @private */
3975
3976    _this.arraybuffer = null;
3977    /** @private */
3978
3979    _this.drawer = null;
3980    /** @private */
3981
3982    _this.backend = null;
3983    /** @private */
3984
3985    _this.peakCache = null;
3985 // cache constructor objects
3986
3987    if (typeof _this.params.renderer !== 'function') {
3988      throw new Error('Renderer parameter is invalid');
3989    }
3990    /**
3991     * @private The uninitialised Drawer class
3992     */
3993
3994
3995    _this.Drawer = _this.params.renderer;
3996    /**
3997     * @private The uninitialised Backend class
3998     */
3999    // Back compat
4000
4001    if (_this.params.backend == 'AudioElement') {
4002      _this.params.backend = 'MediaElement';
4003    }
4004
4005    if ((_this.params.backend == 'WebAudio' || _this.params.backend === 'MediaElementWebAudio') && !_webaudio.default.prototype.supportsWebAudio.call(null)) {
4006      _this.params.backend = 'MediaElement';
4007    }
4008
4009    _this.Backend = _this.backends[_this.params.backend];
4010    /**
4011     * @private map of plugin names that are currently initialised
4012     */
4013
4014    _this.initialisedPluginList = {};
4015    /** @private */
4016
4017    _this.isDestroyed = false;
4018    /**
4019     * Get the current ready status.
4020     *
4021     * @example const isReady = wavesurfer.isReady;
4022     * @return {boolean}
4023     */
4024
4025    _this.isReady = false; // responsive debounced event listener. If this.params.responsive is not
4026    // set, this is never called. Use 100ms or this.params.responsive as
4027    // timeout for the debounce function.
4028
4029    var prevWidth = 0;
4030    _this._onResize = util.debounce(function () {
4031      if (prevWidth != _this.drawer.wrapper.clientWidth && !_this.params.scrollParent) {
4032        prevWidth = _this.drawer.wrapper.clientWidth;
4033
4034        _this.drawer.fireEvent('redraw');
4035      }
4036    }, typeof _this.params.responsive === 'number' ? _this.params.responsive : 100);
4037    return _possibleConstructorReturn(_this, _assertThisInitialized(_this));
4038  }
4039  /**
4040   * Initialise the wave
4041   *
4042   * @example
4043   * var wavesurfer = new WaveSurfer(params);
4044   * wavesurfer.init();
4045   * @return {this} The wavesurfer instance
4046   */
4047
4048
4049  _createClass(WaveSurfer, [{
4050    key: "init",
4051    value: function init() {
4052      this.registerPlugins(this.params.plugins);
4053      this.createDrawer();
4054      this.createBackend();
4055      this.createPeakCache();
4056      return this;
4057    }
4058    /**
4059     * Add and initialise array of plugins (if `plugin.deferInit` is falsey),
4060     * this function is called in the init function of wavesurfer
4061     *
4062     * @param {PluginDefinition[]} plugins An array of plugin definitions
4063     * @emits {WaveSurfer#plugins-registered} Called with the array of plugin definitions
4064     * @return {this} The wavesurfer instance
4065     */
4066
4067  }, {
4068    key: "registerPlugins",
4069    value: function registerPlugins(plugins) {
4070      var _this2 = this;
4071
4072      // first instantiate all the plugins
4073      plugins.forEach(function (plugin) {
4074        return _this2.addPlugin(plugin);
4075      }); // now run the init functions
4076
4077      plugins.forEach(function (plugin) {
4078        // call init function of the plugin if deferInit is falsey
4079        // in that case you would manually use initPlugins()
4080        if (!plugin.deferInit) {
4081          _this2.initPlugin(plugin.name);
4082        }
4083      });
4084      this.fireEvent('plugins-registered', plugins);
4085      return this;
4086    }
4087    /**
4088     * Get a map of plugin names that are currently initialised
4089     *
4090     * @example wavesurfer.getPlugins();
4091     * @return {Object} Object with plugin names
4092     */
4093
4094  }, {
4095    key: "getActivePlugins",
4096    value: function getActivePlugins() {
4097      return this.initialisedPluginList;
4098    }
4099    /**
4100     * Add a plugin object to wavesurfer
4101     *
4102     * @param {PluginDefinition} plugin A plugin definition
4103     * @emits {WaveSurfer#plugin-added} Called with the name of the plugin that was added
4104     * @example wavesurfer.addPlugin(WaveSurfer.minimap());
4105     * @return {this} The wavesurfer instance
4106     */
4107
4108  }, {
4109    key: "addPlugin",
4110    value: function addPlugin(plugin) {
4111      var _this3 = this;
4112
4113      if (!plugin.name) {
4114        throw new Error('Plugin does not have a name!');
4115      }
4116
4117      if (!plugin.instance) {
4118        throw new Error("Plugin ".concat(plugin.name, " does not have an instance property!"));
4119      } // staticProps properties are applied to wavesurfer instance
4120
4121
4122      if (plugin.staticProps) {
4123        Object.keys(plugin.staticProps).forEach(function (pluginStaticProp) {
4124          /**
4125           * Properties defined in a plugin definition's `staticProps` property are added as
4126           * staticProps properties of the WaveSurfer instance
4127           */
4128          _this3[pluginStaticProp] = plugin.staticProps[pluginStaticProp];
4129        });
4130      }
4131
4132      var Instance = plugin.instance; // turn the plugin instance into an observer
4133
4134      var observerPrototypeKeys = Object.getOwnPropertyNames(util.Observer.prototype);
4135      observerPrototypeKeys.forEach(function (key) {
4136        Instance.prototype[key] = util.Observer.prototype[key];
4137      });
4138      /**
4139       * Instantiated plugin classes are added as a property of the wavesurfer
4140       * instance
4141       * @type {Object}
4142       */
4143
4144      this[plugin.name] = new Instance(plugin.params || {}, this);
4145      this.fireEvent('plugin-added', plugin.name);
4146      return this;
4147    }
4148    /**
4149     * Initialise a plugin
4150     *
4151     * @param {string} name A plugin name
4152     * @emits WaveSurfer#plugin-initialised
4153     * @example wavesurfer.initPlugin('minimap');
4154     * @return {this} The wavesurfer instance
4155     */
4156
4157  }, {
4158    key: "initPlugin",
4159    value: function initPlugin(name) {
4160      if (!this[name]) {
4161        throw new Error("Plugin ".concat(name, " has not been added yet!"));
4162      }
4163
4164      if (this.initialisedPluginList[name]) {
4165        // destroy any already initialised plugins
4166        this.destroyPlugin(name);
4167      }
4168
4169      this[name].init();
4170      this.initialisedPluginList[name] = true;
4171      this.fireEvent('plugin-initialised', name);
4172      return this;
4173    }
4174    /**
4175     * Destroy a plugin
4176     *
4177     * @param {string} name A plugin name
4178     * @emits WaveSurfer#plugin-destroyed
4179     * @example wavesurfer.destroyPlugin('minimap');
4180     * @returns {this} The wavesurfer instance
4181     */
4182
4183  }, {
4184    key: "destroyPlugin",
4185    value: function destroyPlugin(name) {
4186      if (!this[name]) {
4187        throw new Error("Plugin ".concat(name, " has not been added yet and cannot be destroyed!"));
4188      }
4189
4190      if (!this.initialisedPluginList[name]) {
4191        throw new Error("Plugin ".concat(name, " is not active and cannot be destroyed!"));
4192      }
4193
4194      if (typeof this[name].destroy !== 'function') {
4195        throw new Error("Plugin ".concat(name, " does not have a destroy function!"));
4196      }
4197
4198      this[name].destroy();
4199      delete this.initialisedPluginList[name];
4200      this.fireEvent('plugin-destroyed', name);
4201      return this;
4202    }
4203    /**
4204     * Destroy all initialised plugins. Convenience function to use when
4205     * wavesurfer is removed
4206     *
4207     * @private
4208     */
4209
4210  }, {
4211    key: "destroyAllPlugins",
4212    value: function destroyAllPlugins() {
4213      var _this4 = this;
4214
4215      Object.keys(this.initialisedPluginList).forEach(function (name) {
4216        return _this4.destroyPlugin(name);
4217      });
4218    }
4219    /**
4220     * Create the drawer and draw the waveform
4221     *
4222     * @private
4223     * @emits WaveSurfer#drawer-created
4224     */
4225
4226  }, {
4227    key: "createDrawer",
4228    value: function createDrawer() {
4229      var _this5 = this;
4230
4231      this.drawer = new this.Drawer(this.container, this.params);
4232      this.drawer.init();
4233      this.fireEvent('drawer-created', this.drawer);
4234
4235      if (this.params.responsive !== false) {
4236        window.addEventListener('resize', this._onResize, true);
4237        window.addEventListener('orientationchange', this._onResize, true);
4238      }
4239
4240      this.drawer.on('redraw', function () {
4241        _this5.drawBuffer();
4242
4243        _this5.drawer.progress(_this5.backend.getPlayedPercents());
4244      }); // Click-to-seek
4245
4246      this.drawer.on('click', function (e, progress) {
4247        setTimeout(function () {
4248          return _this5.seekTo(progress);
4249        }, 0);
4250      }); // Relay the scroll event from the drawer
4251
4252      this.drawer.on('scroll', function (e) {
4253        if (_this5.params.partialRender) {
4254          _this5.drawBuffer();
4255        }
4256
4257        _this5.fireEvent('scroll', e);
4258      });
4259    }
4260    /**
4261     * Create the backend
4262     *
4263     * @private
4264     * @emits WaveSurfer#backend-created
4265     */
4266
4267  }, {
4268    key: "createBackend",
4269    value: function createBackend() {
4270      var _this6 = this;
4271
4272      if (this.backend) {
4273        this.backend.destroy();
4274      }
4275
4276      this.backend = new this.Backend(this.params);
4277      this.backend.init();
4278      this.fireEvent('backend-created', this.backend);
4279      this.backend.on('finish', function () {
4280        _this6.drawer.progress(_this6.backend.getPlayedPercents());
4281
4282        _this6.fireEvent('finish');
4283      });
4284      this.backend.on('play', function () {
4285        return _this6.fireEvent('play');
4286      });
4287      this.backend.on('pause', function () {
4288        return _this6.fireEvent('pause');
4289      });
4290      this.backend.on('audioprocess', function (time) {
4291        _this6.drawer.progress(_this6.backend.getPlayedPercents());
4292
4293        _this6.fireEvent('audioprocess', time);
4294      }); // only needed for MediaElement and MediaElementWebAudio backend
4295
4296      if (this.params.backend === 'MediaElement' || this.params.backend === 'MediaElementWebAudio') {
4297        this.backend.on('seek', function () {
4298          _this6.drawer.progress(_this6.backend.getPlayedPercents());
4299        });
4300        this.backend.on('volume', function () {
4301          var newVolume = _this6.getVolume();
4302
4303          _this6.fireEvent('volume', newVolume);
4304
4305          if (_this6.backend.isMuted !== _this6.isMuted) {
4306            _this6.isMuted = _this6.backend.isMuted;
4307
4308            _this6.fireEvent('mute', _this6.isMuted);
4309          }
4310        });
4311      }
4312    }
4313    /**
4314     * Create the peak cache
4315     *
4316     * @private
4317     */
4318
4319  }, {
4320    key: "createPeakCache",
4321    value: function createPeakCache() {
4322      if (this.params.partialRender) {
4323        this.peakCache = new _peakcache.default();
4324      }
4325    }
4326    /**
4327     * Get the duration of the audio clip
4328     *
4329     * @example const duration = wavesurfer.getDuration();
4330     * @return {number} Duration in seconds
4331     */
4332
4333  }, {
4334    key: "getDuration",
4335    value: function getDuration() {
4336      return this.backend.getDuration();
4337    }
4338    /**
4339     * Get the current playback position
4340     *
4341     * @example const currentTime = wavesurfer.getCurrentTime();
4342     * @return {number} Playback position in seconds
4343     */
4344
4345  }, {
4346    key: "getCurrentTime",
4347    value: function getCurrentTime() {
4348      return this.backend.getCurrentTime();
4349    }
4350    /**
4351     * Set the current play time in seconds.
4352     *
4353     * @param {number}
4353 seconds A positive number in seconds. E.g. 10 means 10
4354     * seconds, 60 means 1 minute
4355     */
4356
4357  }, {
4358    key: "setCurrentTime",
4359    value: function setCurrentTime(seconds) {
4360      if (seconds >= this.getDuration()) {
4361        this.seekTo(1);
4362      } else {
4363        this.seekTo(seconds / this.getDuration());
4364      }
4365    }
4366    /**
4367     * Starts playback from the current position. Optional start and end
4368     * measured in seconds can be used to set the range of audio to play.
4369     *
4370     * @param {?number} start Position to start at
4371     * @param {?number} end Position to end at
4372     * @emits WaveSurfer#interaction
4373     * @return {Promise} Result of the backend play method
4374     * @example
4375     * // play from second 1 to 5
4376     * wavesurfer.play(1, 5);
4377     */
4378
4379  }, {
4380    key: "play",
4381    value: function play(start, end) {
4382      var _this7 = this;
4383
4384      this.fireEvent('interaction', function () {
4385        return _this7.play(start, end);
4386      });
4387      return this.backend.play(start, end);
4388    }
4389    /**
4390     * Set a point in seconds for playback to stop at.
4391     *
4392     * @param {number} position Position (in seconds) to stop at
4393     * @version 3.3.0
4394     */
4395
4396  }, {
4397    key: "setPlayEnd",
4398    value: function setPlayEnd(position) {
4399      this.backend.setPlayEnd(position);
4400    }
4401    /**
4402     * Stops and pauses playback
4403     *
4404     * @example wavesurfer.pause();
4405     * @return {Promise} Result of the backend pause method
4406     */
4407
4408  }, {
4409    key: "pause",
4410    value: function pause() {
4411      if (!this.backend.isPaused()) {
4412        return this.backend.pause();
4413      }
4414    }
4415    /**
4416     * Toggle playback
4417     *
4418     * @example wavesurfer.playPause();
4419     * @return {Promise} Result of the backend play or pause method
4420     */
4421
4422  }, {
4423    key: "playPause",
4424    value: function playPause() {
4425      return this.backend.isPaused() ? this.play() : this.pause();
4426    }
4427    /**
4428     * Get the current playback state
4429     *
4430     * @example const isPlaying = wavesurfer.isPlaying();
4431     * @return {boolean} False if paused, true if playing
4432     */
4433
4434  }, {
4435    key: "isPlaying",
4436    value: function isPlaying() {
4437      return !this.backend.isPaused();
4438    }
4439    /**
4440     * Skip backward
4441     *
4442     * @param {?number} seconds Amount to skip back, if not specified `skipLength`
4443     * is used
4444     * @example wavesurfer.skipBackward();
4445     */
4446
4447  }, {
4448    key: "skipBackward",
4449    value: function skipBackward(seconds) {
4450      this.skip(-seconds || -this.params.skipLength);
4451    }
4452    /**
4453     * Skip forward
4454     *
4455     * @param {?number} seconds Amount to skip back, if not specified `skipLength`
4456     * is used
4457     * @example wavesurfer.skipForward();
4458     */
4459
4460  }, {
4461    key: "skipForward",
4462    value: function skipForward(seconds) {
4463      this.skip(seconds || this.params.skipLength);
4464    }
4465    /**
4466     * Skip a number of seconds from the current position (use a negative value
4467     * to go backwards).
4468     *
4469     * @param {number} offset Amount to skip back or forwards
4470     * @example
4471     * // go back 2 seconds
4472     * wavesurfer.skip(-2);
4473     */
4474
4475  }, {
4476    key: "skip",
4477    value: function skip(offset) {
4478      var duration = this.getDuration() || 1;
4479      var position = this.getCurrentTime() || 0;
4480      position = Math.max(0, Math.min(duration, position + (offset || 0)));
4481      this.seekAndCenter(position / duration);
4482    }
4483    /**
4484     * Seeks to a position and centers the view
4485     *
4486     * @param {number} progress Between 0 (=beginning) and 1 (=end)
4487     * @example
4488     * // seek and go to the middle of the audio
4489     * wavesurfer.seekTo(0.5);
4490     */
4491
4492  }, {
4493    key: "seekAndCenter",
4494    value: function seekAndCenter(progress) {
4495      this.seekTo(progress);
4496      this.drawer.recenter(progress);
4497    }
4498    /**
4499     * Seeks to a position
4500     *
4501     * @param {number} progress Between 0 (=beginning) and 1 (=end)
4502     * @emits WaveSurfer#interaction
4503     * @emits WaveSurfer#seek
4504     * @example
4505     * // seek to the middle of the audio
4506     * wavesurfer.seekTo(0.5);
4507     */
4508
4509  }, {
4510    key: "seekTo",
4511    value: function seekTo(progress) {
4512      var _this8 = this;
4513
4514      // return an error if progress is not a number between 0 and 1
4515      if (typeof progress !== 'number' || !isFinite(progress) || progress < 0 || progress > 1) {
4516        throw new Error('Error calling wavesurfer.seekTo, parameter must be a number between 0 and 1!');
4517      }
4518
4519      this.fireEvent('interaction', function () {
4520        return _this8.seekTo(progress);
4521      });
4522      var paused = this.backend.isPaused(); // avoid draw wrong position while playing backward seeking
4523
4524      if (!paused) {
4525        this.backend.pause();
4526      } // avoid small scrolls while paused seeking
4527
4528
4529      var oldScrollParent = this.params.scrollParent;
4530      this.params.scrollParent = false;
4531      this.backend.seekTo(progress * this.getDuration());
4532      this.drawer.progress(progress);
4533
4534      if (!paused) {
4535        this.backend.play();
4536      }
4537
4538      this.params.scrollParent = oldScrollParent;
4539      this.fireEvent('seek', progress);
4540    }
4541    /**
4542     * Stops and goes to the beginning.
4543     *
4544     * @example wavesurfer.stop();
4545     */
4546
4547  }, {
4548    key: "stop",
4549    value: function stop() {
4550      this.pause();
4551      this.seekTo(0);
4552      this.drawer.progress(0);
4553    }
4554    /**
4555     * Sets the ID of the audio device to use for output and returns a Promise.
4556     *
4557     * @param {string} deviceId String value representing underlying output
4558     * device
4559     * @returns {Promise} `Promise` that resolves to `undefined` when there are
4560     * no errors detected.
4561     */
4562
4563  }, {
4564    key: "setSinkId",
4565    value: function setSinkId(deviceId) {
4566      return this.backend.setSinkId(deviceId);
4567    }
4568    /**
4569     * Set the playback volume.
4570     *
4571     * @param {number} newVolume A value between 0 and 1, 0 being no
4572     * volume and 1 being full volume.
4573     * @emits WaveSurfer#volume
4574     */
4575
4576  }, {
4577    key: "setVolume",
4578    value: function setVolume(newVolume) {
4579      this.backend.setVolume(newVolume);
4580      this.fireEvent('volume', newVolume);
4581    }
4582    /**
4583     * Get the playback volume.
4584     *
4585     * @return {number} A value between 0 and 1, 0 being no
4586     * volume and 1 being full volume.
4587     */
4588
4589  }, {
4590    key: "getVolume",
4591    value: function getVolume() {
4592      return this.backend.getVolume();
4593    }
4594    /**
4595     * Set the playback rate.
4596     *
4597     * @param {number} rate A positive number. E.g. 0.5 means half the normal
4598     * speed, 2 means double speed and so on.
4599     * @example wavesurfer.setPlaybackRate(2);
4600     */
4601
4602  }, {
4603    key: "setPlaybackRate",
4604    value: function setPlaybackRate(rate) {
4605      this.backend.setPlaybackRate(rate);
4606    }
4607    /**
4608     * Get the playback rate.
4609     *
4610     * @return {number} The current playback rate.
4611     */
4612
4613  }, {
4614    key: "getPlaybackRate",
4615    value: function getPlaybackRate() {
4616      return this.backend.getPlaybackRate();
4617    }
4618    /**
4619     * Toggle the volume on and off. If not currently muted it will save the
4620     * current volume value and turn the volume off. If currently muted then it
4621     * will restore the volume to the saved value, and then rest the saved
4622     * value.
4623     *
4624     * @example wavesurfer.toggleMute();
4625     */
4626
4627  }, {
4628    key: "toggleMute",
4629    value: function toggleMute() {
4630      this.setMute(!this.isMuted);
4631    }
4632    /**
4633     * Enable or disable muted audio
4634     *
4635     * @param {boolean} mute Specify `true` to mute audio.
4636     * @emits WaveSurfer#volume
4637     * @emits WaveSurfer#mute
4638     * @example
4639     * // unmute
4640     * wavesurfer.setMute(false);
4641     * console.log(wavesurfer.getMute()) // logs false
4642     */
4643
4644  }, {
4645    key: "setMute",
4646    value: function setMute(mute) {
4647      // ignore all muting requests if the audio is already in that state
4648      if (mute === this.isMuted) {
4649        this.fireEvent('mute', this.isMuted);
4650        return;
4651      }
4652
4653      if (mute) {
4654        // If currently not muted then save current volume,
4655        // turn off the volume and update the mute properties
4656        this.savedVolume = this.backend.getVolume();
4657        this.backend.setVolume(0);
4658        this.isMuted = true;
4659        this.fireEvent('volume', 0);
4660      } else {
4661        // If currently muted then restore to the saved volume
4662        // and update the mute properties
4663        this.backend.setVolume(this.savedVolume);
4664        this.isMuted = false;
4665        this.fireEvent('volume', this.savedVolume);
4666      }
4667
4668      this.fireEvent('mute', this.isMuted);
4669    }
4670    /**
4671     * Get the current mute status.
4672     *
4673     * @example const isMuted = wavesurfer.getMute();
4674     * @return {boolean} Current mute status
4675     */
4676
4677  }, {
4678    key: "getMute",
4679    value: function getMute() {
4680      return this.isMuted;
4681    }
4682    /**
4683     * Get the list of current set filters as an array.
4684     *
4685     * Filters must be set with setFilters method first
4686     *
4687     * @return {array} List of enabled filters
4688     */
4689
4690  }, {
4691    key: "getFilters",
4692    value: function getFilters() {
4693      return this.backend.filters || [];
4694    }
4695    /**
4696     * Toggles `scrollParent` and redraws
4697     *
4698     * @example wavesurfer.toggleScroll();
4699     */
4700
4701  }, {
4702    key: "toggleScroll",
4703    value: function toggleScroll() {
4704      this.params.scrollParent = !this.params.scrollParent;
4705      this.drawBuffer();
4706    }
4707    /**
4708     * Toggle mouse interaction
4709     *
4710     * @example wavesurfer.toggleInteraction();
4711     */
4712
4713  }, {
4714    key: "toggleInteraction",
4715    value: function toggleInteraction() {
4716      this.params.interact = !this.params.interact;
4717    }
4718    /**
4719     * Get the fill color of the waveform after the cursor.
4720     *
4721     * @return {string} A CSS color string.
4722     */
4723
4724  }, {
4725    key: "getWaveColor",
4726    value: function getWaveColor() {
4727      return this.params.waveColor;
4728    }
4729    /**
4730     * Set the fill color of the waveform after the cursor.
4731     *
4732     * @param {string} color A CSS color string.
4733     * @example wavesurfer.setWaveColor('#ddd');
4734     */
4735
4736  }, {
4737    key: "setWaveColor",
4738    value: function setWaveColor(color) {
4739      this.params.waveColor = color;
4740      this.drawBuffer();
4741    }
4742    /**
4743     * Get the fill color of the waveform behind the cursor.
4744     *
4745     * @return {string} A CSS color string.
4746     */
4747
4748  }, {
4749    key: "getProgressColor",
4750    value: function getProgressColor() {
4751      return this.params.progressColor;
4752    }
4753    /**
4754     * Set the fill color of the waveform behind the cursor.
4755     *
4756     * @param {string} color A CSS color string.
4757     * @example wavesurfer.setProgressColor('#400');
4758     */
4759
4760  }, {
4761    key: "setProgressColor",
4762    value: function setProgressColor(color) {
4763      this.params.progressColor = color;
4764      this.drawBuffer();
4765    }
4766    /**
4767     * Get the background color of the waveform container.
4768     *
4769     * @return {string} A CSS color string.
4770     */
4771
4772  }, {
4773    key: "getBackgroundColor",
4774    value: function getBackgroundColor() {
4775      return this.params.backgroundColor;
4776    }
4777    /**
4778     * Set the background color of the waveform container.
4779     *
4780     * @param {string} color A CSS color string.
4781     * @example wavesurfer.setBackgroundColor('#FF00FF');
4782     */
4783
4784  }, {
4785    key: "setBackgroundColor",
4786    value: function setBackgroundColor(color) {
4787      this.params.backgroundColor = color;
4788      util.style(this.container, {
4789        background: this.params.backgroundColor
4790      });
4791    }
4792    /**
4793     * Get the fill color of the cursor indicating the playhead
4794     * position.
4795     *
4796     * @return {string} A CSS color string.
4797     */
4798
4799  }, {
4800    key: "getCursorColor",
4801    value: function getCursorColor() {
4802      return this.params.cursorColor;
4803    }
4804    /**
4805     * Set the fill color of the cursor indicating the playhead
4806     * position.
4807     *
4808     * @param {string} color A CSS color string.
4809     * @example wavesurfer.setCursorColor('#222');
4810     */
4811
4812  }, {
4813    key: "setCursorColor",
4814    value: function setCursorColor(color) {
4815      this.params.cursorColor = color;
4816      this.drawer.updateCursor();
4817    }
4818    /**
4819     * Get the height of the waveform.
4820     *
4821     * @return {number} Height measured in pixels.
4822     */
4823
4824  }, {
4825    key: "getHeight",
4826    value: function getHeight() {
4827      return this.params.height;
4828    }
4829    /**
4830     * Set the height of the waveform.
4831     *
4832     * @param {number} height Height measured in pixels.
4833     * @example wavesurfer.setHeight(200);
4834     */
4835
4836  }, {
4837    key: "setHeight",
4838    value: function setHeight(height) {
4839      this.params.height = height;
4840      this.drawer.setHeight(height * this.params.pixelRatio);
4841      this.drawBuffer();
4842    }
4843    /**
4844     * Get the correct peaks for current wave view-port and render wave
4845     *
4846     * @private
4847     * @emits WaveSurfer#redraw
4848     */
4849
4850  }, {
4851    key: "drawBuffer",
4852    value: function drawBuffer() {
4853      var nominalWidth = Math.round(this.getDuration() * this.params.minPxPerSec * this.params.pixelRatio);
4854      var parentWidth = this.drawer.getWidth();
4855      var width = nominalWidth; // always start at 0 after zooming for scrolling : issue redraw left part
4856
4857      var start = 0;
4858      var end = Math.max(start + parentWidth, width); // Fill container
4859
4860      if (this.params.fillParent && (!this.params.scrollParent || nominalWidth < parentWidth)) {
4861        width = parentWidth;
4862        start = 0;
4863        end = width;
4864      }
4865
4866      var peaks;
4867
4868      if (this.params.partialRender) {
4869        var newRanges = this.peakCache.addRangeToPeakCache(width, start, end);
4870        var i;
4871
4872        for (i = 0; i < newRanges.length; i++) {
4873          peaks = this.backend.getPeaks(width, newRanges[i][0], newRanges[i][1]);
4874          this.drawer.drawPeaks(peaks, width, newRanges[i][0], newRanges[i][1]);
4875        }
4876      } else {
4877        peaks = this.backend.getPeaks(width, start, end);
4878        this.drawer.drawPeaks(peaks, width, start, end);
4879      }
4880
4881      this.fireEvent('redraw', peaks, width);
4882    }
4883    /**
4884     * Horizontally zooms the waveform in and out. It also changes the parameter
4885     * `minPxPerSec` and enables the `scrollParent` option. Calling the function
4886     * with a falsey parameter will reset the zoom state.
4887     *
4888     * @param {?number} pxPerSec Number of horizontal pixels per second of
4889     * audio, if none is set the waveform returns to unzoomed state
4890     * @emits WaveSurfer#zoom
4891     * @example wavesurfer.zoom(20);
4892     */
4893
4894  }, {
4895    key: "zoom",
4896    value: function zoom(pxPerSec) {
4897      if (!pxPerSec) {
4898        this.params.minPxPerSec = this.defaultParams.minPxPerSec;
4899        this.params.scrollParent = false;
4900      } else {
4901        this.params.minPxPerSec = pxPerSec;
4902        this.params.scrollParent = true;
4903      }
4904
4905      this.drawBuffer();
4906      this.drawer.progress(this.backend.getPlayedPercents());
4907      this.drawer.recenter(this.getCurrentTime() / this.getDuration());
4908      this.fireEvent('zoom', pxPerSec);
4909    }
4910    /**
4911     * Decode buffer and load
4912     *
4913     * @private
4914     * @param {ArrayBuffer} arraybuffer Buffer to process
4915     */
4916
4917  }, {
4918    key: "loadArrayBuffer",
4919    value: function loadArrayBuffer(arraybuffer) {
4920      var _this9 = this;
4921
4922      this.decodeArrayBuffer(arraybuffer, function (data) {
4923        if (!_this9.isDestroyed) {
4924          _this9.loadDecodedBuffer(data);
4925        }
4926      });
4927    }
4928    /**
4929     * Directly load an externally decoded AudioBuffer
4930     *
4931     * @private
4932     * @param {AudioBuffer} buffer Buffer to process
4933     * @emits WaveSurfer#ready
4934     */
4935
4936  }, {
4937    key: "loadDecodedBuffer",
4938    value: function loadDecodedBuffer(buffer) {
4939      this.backend.load(buffer);
4940      this.drawBuffer();
4941      this.isReady = true;
4942      this.fireEvent('ready');
4943    }
4944    /**
4945     * Loads audio data from a Blob or File object
4946     *
4947     * @param {Blob|File} blob Audio data
4948     * @example
4949     */
4950
4951  }, {
4952    key: "loadBlob",
4953    value: function loadBlob(blob) {
4954      var _this10 = this;
4955
4956      // Create file reader
4957      var reader = new FileReader();
4958      reader.addEventListener('progress', function (e) {
4959        return _this10.onProgress(e);
4960      });
4961      reader.addEventListener('load', function (e) {
4962        return _this10.loadArrayBuffer(e.target.result);
4963      });
4964      reader.addEventListener('error', function () {
4965        return _this10.fireEvent('error', 'Error reading file');
4966      });
4967      reader.readAsArrayBuffer(blob);
4968      this.empty();
4969    }
4970    /**
4971     * Loads audio and re-renders the waveform.
4972     *
4973     * @param {string|HTMLMediaElement} url The url of the audio file or the
4974     * audio element with the audio
4975     * @param {number[]|Number.<Array[]>} peaks Wavesurfer does not have to decode
4976     * the audio to render the waveform if this is specified
4977     * @param {?string} preload (Use with backend `MediaElement` and `MediaElementWebAudio`)
4978     * `'none'|'metadata'|'auto'` Preload attribute for the media element
4979     * @param {?number} duration The duration of the audio. This is used to
4980     * render the peaks data in the correct size for the audio duration (as
4981     * befits the current `minPxPerSec` and zoom value) without having to decode
4982     * the audio.
4983     * @returns {void}
4984     * @throws Will throw an error if the `url` argument is empty.
4985     * @example
4986     * // uses fetch or media element to load file (depending on backend)
4987     * wavesurfer.load('http://example.com/demo.wav');
4988     *
4989     * // setting preload attribute with media element backend and supplying
4990     * // peaks
4991     * wavesurfer.load(
4992     *   'http://example.com/demo.wav',
4993     *   [0.0218, 0.0183, 0.0165, 0.0198, 0.2137, 0.2888],
4994     *   true
4995     * );
4996     */
4997
4998  }, {
4999    key: "load",
5000    value: function load(url, peaks, preload, duration) {
5001      if (!url) {
5002        throw new Error('url parameter cannot be empty');
5003      }
5004
5005      this.empty();
5006
5007      if (preload) {
5008        // check whether the preload attribute will be usable and if not log
5009        // a warning listing the reasons why not and nullify the variable
5010        var preloadIgnoreReasons = {
5011          "Preload is not 'auto', 'none' or 'metadata'": ['auto', 'metadata', 'none'].indexOf(preload) === -1,
5012          'Peaks are not provided': !peaks,
5013          "Backend is not of type 'MediaElement' or 'MediaElementWebAudio'": ['MediaElement', 'MediaElementWebAudio'].indexOf(this.params.backend) === -1,
5014          'Url is not of type string': typeof url !== 'string'
5015        };
5016        var activeReasons = Object.keys(preloadIgnoreReasons).filter(function (reason) {
5017          return preloadIgnoreReasons[reason];
5018        });
5019
5020        if (activeReasons.length) {
5021          // eslint-disable-next-line no-console
5022          console.warn('Preload parameter of wavesurfer.load will be ignored because:\n\t- ' + activeReasons.join('\n\t- ')); // stop invalid values from being used
5023
5024          preload = null;
5025        }
5026      }
5027
5028      switch (this.params.backend) {
5029        case 'WebAudio':
5030          return this.loadBuffer(url, peaks, duration);
5031
5032        case 'MediaElement':
5033        case 'MediaElementWebAudio':
5034          return this.loadMediaElement(url, peaks, preload, duration);
5035      }
5036    }
5037    /**
5038     * Loads audio using Web Audio buffer backend.
5039     *
5040     * @private
5041     * @param {string} url URL of audio file
5042     * @param {number[]|Number.<Array[]>} peaks Peaks data
5043     * @param {?number} duration Optional duration of audio file
5044     * @returns {void}
5045     */
5046
5047  }, {
5048    key: "loadBuffer",
5049    value: function loadBuffer(url, peaks, duration) {
5050      var _this11 = this;
5051
5052      var load = function load(action) {
5053        if (action) {
5054          _this11.tmpEvents.push(_this11.once('ready', action));
5055        }
5056
5057        return _this11.getArrayBuffer(url, function (data) {
5058          return _this11.loadArrayBuffer(data);
5059        });
5060      };
5061
5062      if (peaks) {
5063        this.backend.setPeaks(peaks, duration);
5064        this.drawBuffer();
5065        this.tmpEvents.push(this.once('interaction', load));
5066      } else {
5067        return load();
5068      }
5069    }
5070    /**
5071     * Either create a media element, or load an existing media element.
5072     *
5073     * @private
5074     * @param {string|HTMLMediaElement} urlOrElt Either a path to a media file, or an
5075     * existing HTML5 Audio/Video Element
5076     * @param {number[]|Number.<Array[]>} peaks Array of peaks. Required to bypass web audio
5077     * dependency
5078     * @param {?boolean} preload Set to true if the preload attribute of the
5079     * audio element should be enabled
5080     * @param {?number} duration Optional duration of audio file
5081     */
5082
5083  }, {
5084    key: "loadMediaElement",
5085    value: function loadMediaElement(urlOrElt, peaks, preload, duration) {
5086      var _this12 = this;
5087
5088      var url = urlOrElt;
5089
5090      if (typeof urlOrElt === 'string') {
5091        this.backend.load(url, this.mediaContainer, peaks, preload);
5092      } else {
5093        var elt = urlOrElt;
5094        this.backend.loadElt(elt, peaks); // If peaks are not provided,
5095        // url = element.src so we can get peaks with web audio
5096
5097        url = elt.src;
5098      }
5099
5100      this.tmpEvents.push(this.backend.once('canplay', function () {
5101        // ignore when backend was already destroyed
5102        if (!_this12.backend.destroyed) {
5103          _this12.drawBuffer();
5104
5105          _this12.isReady = true;
5106
5107          _this12.fireEvent('ready');
5108        }
5109      }), this.backend.once('error', function (err) {
5110        return _this12.fireEvent('error', err);
5111      })); // If no pre-decoded peaks provided or pre-decoded peaks are
5112      // provided with forceDecode flag, attempt to download the
5113      // audio file and decode it with Web Audio.
5114
5115      if (peaks) {
5116        this.backend.setPeaks(peaks, duration);
5117      }
5118
5119      if ((!peaks || this.params.forceDecode) && this.backend.supportsWebAudio()) {
5120        this.getArrayBuffer(url, function (arraybuffer) {
5121          _this12.decodeArrayBuffer(arraybuffer, function (buffer) {
5122            _this12.backend.buffer = buffer;
5123
5124            _this12.backend.setPeaks(null);
5125
5126            _this12.drawBuffer();
5127
5128            _this12.fireEvent('waveform-ready');
5129          });
5130        });
5131      }
5132    }
5133    /**
5134     * Decode an array buffer and pass data to a callback
5135     *
5136     * @private
5137     * @param {Object} arraybuffer The array buffer to decode
5138     * @param {function} callback The function to call on complete
5139     */
5140
5141  }, {
5142    key: "decodeArrayBuffer",
5143    value: function decodeArrayBuffer(arraybuffer, callback) {
5144      var _this13 = this;
5145
5146      this.arraybuffer = arraybuffer;
5147      this.backend.decodeArrayBuffer(arraybuffer, function (data) {
5148        // Only use the decoded data if we haven't been destroyed or
5149        // another decode started in the meantime
5150        if (!_this13.isDestroyed && _this13.arraybuffer == arraybuffer) {
5151          callback(data);
5152          _this13.arraybuffer = null;
5153        }
5154      }, function () {
5155        return _this13.fireEvent('error', 'Error decoding audiobuffer');
5156      });
5157    }
5158    /**
5159     * Load an array buffer using fetch and pass the result to a callback
5160     *
5161     * @param {string} url The URL of the file object
5162     * @param {function} callback The function to call on complete
5163     * @returns {util.fetchFile} fetch call
5164     * @private
5165     */
5166
5167  }, {
5168    key: "getArrayBuffer",
5169    value: function getArrayBuffer(url, callback) {
5170      var _this14 = this;
5171
5172      var options = Object.assign({
5173        url: url,
5174        responseType: 'arraybuffer'
5175      }, this.params.xhr);
5176      var request = util.fetchFile(options);
5177      this.currentRequest = request;
5178      this.tmpEvents.push(request.on('progress', function (e) {
5179        _this14.onProgress(e);
5180      }), request.on('success', function (data) {
5181        callback(data);
5182        _this14.currentRequest = null;
5183      }), request.on('error', function (e) {
5184        _this14.fireEvent('error', e);
5185
5186        _this14.currentRequest = null;
5187      }));
5188      return request;
5189    }
5190    /**
5191     * Called while the audio file is loading
5192     *
5193     * @private
5194     * @param {Event} e Progress event
5195     * @emits WaveSurfer#loading
5196     */
5197
5198  }, {
5199    key: "onProgress",
5200    value: function onProgress(e) {
5201      var percentComplete;
5202
5203      if (e.lengthComputable) {
5204        percentComplete = e.loaded / e.total;
5205      } else {
5206        // Approximate progress with an asymptotic
5207        // function, and assume downloads in the 1-3 MB range.
5208        percentComplete = e.loaded / (e.loaded + 1000000);
5209      }
5210
5211      this.fireEvent('loading', Math.round(percentComplete * 100), e.target);
5212    }
5213    /**
5214     * Exports PCM data into a JSON array and opens in a new window.
5215     *
5216     * @param {number} length=1024 The scale in which to export the peaks
5217     * @param {number} accuracy=10000
5218     * @param {?boolean} noWindow Set to true to disable opening a new
5219     * window with the JSON
5220     * @param {number} start Start index
5221     * @param {number} end End index
5222     * @return {Promise} Promise that resolves with array of peaks
5223     */
5224
5225  }, {
5226    key: "exportPCM",
5227    value: function exportPCM(length, accuracy, noWindow, start, end) {
5228      length = length || 1024;
5229      start = start || 0;
5230      accuracy = accuracy || 10000;
5231      noWindow = noWindow || false;
5232      var peaks = this.backend.getPeaks(length, start, end);
5233      var arr = [].map.call(peaks, function (val) {
5234        return Math.round(val * accuracy) / accuracy;
5235      });
5236      return new Promise(function (resolve, reject) {
5237        var json = JSON.stringify(arr);
5238
5239        if (!noWindow) {
5240          window.open('data:application/json;charset=utf-8,' + encodeURIComponent(json));
5241        }
5242
5243        resolve(json);
5244      });
5245    }
5246    /**
5247     * Save waveform image as data URI.
5248     *
5249     * The default format is `'image/png'`. Other supported types are
5250     * `'image/jpeg'` and `'image/webp'`.
5251     *
5252     * @param {string} format='image/png' A string indicating the image format.
5253     * The default format type is `'image/png'`.
5254     * @param {number} quality=1 A number between 0 and 1 indicating the image
5255     * quality to use for image formats that use lossy compression such as
5256     * `'image/jpeg'`` and `'image/webp'`.
5257     * @param {string} type Image data type to return. Either 'dataURL' (default)
5258     * or 'blob'.
5259     * @return {string|string[]|Promise} When using `'dataURL'` type this returns
5260     * a single data URL or an array of data URLs, one for each canvas. When using
5261     * `'blob'` type this returns a `Promise` resolving with an array of `Blob`
5262     * instances, one for each canvas.
5263     */
5264
5265  }, {
5266    key: "exportImage",
5267    value: function exportImage(format, quality, type) {
5268      if (!format) {
5269        format = 'image/png';
5270      }
5271
5272      if (!quality) {
5273        quality = 1;
5274      }
5275
5276      if (!type) {
5277        type = 'dataURL';
5278      }
5279
5280      return this.drawer.getImage(format, quality, type);
5281    }
5282    /**
5283     * Cancel any fetch request currently in progress
5284     */
5285
5286  }, {
5287    key: "cancelAjax",
5288    value: function cancelAjax() {
5289      if (this.currentRequest && this.currentRequest.controller) {
5290        this.currentRequest.controller.abort();
5291        this.currentRequest = null;
5292      }
5293    }
5294    /**
5295     * @private
5296     */
5297
5298  }, {
5299    key: "clearTmpEvents",
5300    value: function clearTmpEvents() {
5301      this.tmpEvents.forEach(function (e) {
5302        return e.un();
5303      });
5304    }
5305    /**
5306     * Display empty waveform.
5307     */
5308
5309  }, {
5310    key: "empty",
5311    value: function empty() {
5312      if (!this.backend.isPaused()) {
5313        this.stop();
5314        this.backend.disconnectSource();
5315      }
5316
5317      this.isReady = false;
5318      this.cancelAjax();
5319      this.clearTmpEvents(); // empty drawer
5320
5321      this.drawer.progress(0);
5322      this.drawer.setWidth(0);
5323      this.drawer.drawPeaks({
5324        length: this.drawer.getWidth()
5325      }, 0);
5326    }
5327    /**
5328     * Remove events, elements and disconnect WebAudio nodes.
5329     *
5330     * @emits WaveSurfer#destroy
5331     */
5332
5333  }, {
5334    key: "destroy",
5335    value: function destroy() {
5336      this.destroyAllPlugins();
5337      this.fireEvent('destroy');
5338      this.cancelAjax();
5339      this.clearTmpEvents();
5340      this.unAll();
5341
5342      if (this.params.responsive !== false) {
5343        window.removeEventListener('resize', this._onResize, true);
5344        window.removeEventListener('orientationchange', this._onResize, true);
5345      }
5346
5347      if (this.backend) {
5348        this.backend.destroy();
5349      }
5350
5351      if (this.drawer) {
5352        this.drawer.destroy();
5353      }
5354
5355      this.isDestroyed = true;
5356      this.isReady = false;
5357      this.arraybuffer = null;
5358    }
5359  }]);
5360
5361  return WaveSurfer;
5362}(util.Observer);
5363
5364exports.default = WaveSurfer;
5365WaveSurfer.VERSION = "3.3.3";
5366WaveSurfer.util = util;
5367module.exports = exports.default;
5368
5369/***/ }),
5370
5371/***/ "./src/webaudio.js":
5372/*!*************************!*\
5373  !*** ./src/webaudio.js ***!
5374  \*************************/
5375/*! no static exports found */
5376/***/ (function(module, exports, __webpack_require__) {
5377
5378"use strict";
5379
5380
5381Object.defineProperty(exports, "__esModule", {
5382  value: true
5383});
5384exports.default = void 0;
5385
5386var util = _interopRequireWildcard(__webpack_require__(/*! ./util */ "./src/util/index.js"));
5387
5388function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }
5389
5390function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (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; }
5391
5392function _typeof(obj) { 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); }
5393
5394function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
5395
5396function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
5397
5398function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
5399
5400function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
5401
5402function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
5403
5404function _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); } }
5405
5406function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
5407
5408function _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); }
5409
5410function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
5411
5412// using constants to prevent someone writing the string wrong
5413var PLAYING = 'playing';
5414var PAUSED = 'paused';
5415var FINISHED = 'finished';
5416/**
5417 * WebAudio backend
5418 *
5419 * @extends {Observer}
5420 */
5421
5422var WebAudio =
5423/*#__PURE__*/
5424function (_util$Observer) {
5425  _inherits(WebAudio, _util$Observer);
5426
5427  _createClass(WebAudio, [{
5428    key: "supportsWebAudio",
5429
5430    /** scriptBufferSize: size of the processing buffer */
5431
5432    /** audioContext: allows to process audio with WebAudio API */
5433
5434    /** @private */
5435
5436    /** @private */
5437
5438    /**
5439     * Does the browser support this backend
5440     *
5441     * @return {boolean} Whether or not this browser supports this backend
5442     */
5443    value: function supportsWebAudio() {
5444      return !!(window.AudioContext || window.webkitAudioContext);
5445    }
5446    /**
5447     * Get the audio context used by this backend or create one
5448     *
5449     * @return {AudioContext} Existing audio context, or creates a new one
5450     */
5451
5452  }, {
5453    key: "getAudioContext",
5454    value: function getAudioContext() {
5455      if (!window.WaveSurferAudioContext) {
5456        window.WaveSurferAudioContext = new (window.AudioContext || window.webkitAudioContext)();
5457      }
5458
5459      return window.WaveSurferAudioContext;
5460    }
5461    /**
5462     * Get the offline audio context used by this backend or create one
5463     *
5464     * @param {number} sampleRate The sample rate to use
5465     * @return {OfflineAudioContext} Existing offline audio context, or creates
5466     * a new one
5467     */
5468
5469  }, {
5470    key: "getOfflineAudioContext",
5471    value: function getOfflineAudioContext(sampleRate) {
5472      if (!window.WaveSurferOfflineAudioContext) {
5473        window.WaveSurferOfflineAudioContext = new (window.OfflineAudioContext || window.webkitOfflineAudioContext)(1, 2, sampleRate);
5474      }
5475
5476      return window.WaveSurferOfflineAudioContext;
5477    }
5478    /**
5479     * Construct the backend
5480     *
5481     * @param {WavesurferParams} params Wavesurfer parameters
5482     */
5483
5484  }]);
5485
5486  function WebAudio(params) {
5487    var _this$stateBehaviors, _this$states;
5488
5489    var _this;
5490
5491    _classCallCheck(this, WebAudio);
5492
5493    _this = _possibleConstructorReturn(this, _getPrototypeOf(WebAudio).call(this));
5494    /** @private */
5495
5496    _this.audioContext = null;
5497    _this.offlineAudioContext = null;
5498    _this.stateBehaviors = (_this$stateBehaviors = {}, _defineProperty(_this$stateBehaviors, PLAYING, {
5499      init: function init() {
5500        this.addOnAudioProcess();
5501      },
5502      getPlayedPercents: function getPlayedPercents() {
5503        var duration = this.getDuration();
5504        return this.getCurrentTime() / duration || 0;
5505      },
5506      getCurrentTime: function getCurrentTime() {
5507        return this.startPosition + this.getPlayedTime();
5508      }
5509    }), _defineProperty(_this$stateBehaviors, PAUSED, {
5510      init: function init() {
5511        this.removeOnAudioProcess();
5512      },
5513      getPlayedPercents: function getPlayedPercents() {
5514        var duration = this.getDuration();
5515        return this.getCurrentTime() / duration || 0;
5516      },
5517      getCurrentTime: function getCurrentTime() {
5518        return this.startPosition;
5519      }
5520    }), _defineProperty(_this$stateBehaviors, FINISHED, {
5521      init: function init() {
5522        this.removeOnAudioProcess();
5523        this.fireEvent('finish');
5524      },
5525      getPlayedPercents: function getPlayedPercents() {
5526        return 1;
5527      },
5528      getCurrentTime: function getCurrentTime() {
5529        return this.getDuration();
5530      }
5531    }), _this$stateBehaviors);
5532    _this.params = params;
5533    /** ac: Audio Context instance */
5534
5535    _this.ac = params.audioContext || (_this.supportsWebAudio() ? _this.getAudioContext() : {});
5536    /**@private */
5537
5538    _this.lastPlay = _this.ac.currentTime;
5539    /** @private */
5540
5541    _this.startPosition = 0;
5542    /** @private */
5543
5544    _this.scheduledPause = null;
5545    /** @private */
5546
5547    _this.states = (_this$states = {}, _defineProperty(_this$states, PLAYING, Object.create(_this.stateBehaviors[PLAYING])), _defineProperty(_this$states, PAUSED, Object.create(_this.stateBehaviors[PAUSED])), _defineProperty(_this$states, FINISHED, Object.create(_this.stateBehaviors[FINISHED])), _this$states);
5548    /** @private */
5549
5550    _this.buffer = null;
5551    /** @private */
5552
5553    _this.filters = [];
5554    /** gainNode: allows to control audio volume */
5555
5556    _this.gainNode = null;
5557    /** @private */
5558
5559    _this.mergedPeaks = null;
5560    /** @private */
5561
5562    _this.offlineAc = null;
5563    /** @private */
5564
5565    _this.peaks = null;
5566    /** @private */
5567
5568    _this.playbackRate = 1;
5569    /** analyser: provides audio analysis information */
5570
5571    _this.analyser = null;
5572    /** scriptNode: allows processing audio */
5573
5574    _this.scriptNode = null;
5575    /** @private */
5576
5577    _this.source = null;
5578    /** @private */
5579
5580    _this.splitPeaks = [];
5581    /** @private */
5582
5583    _this.state = null;
5584    /** @private */
5585
5586    _this.explicitDuration = params.duration;
5587    /**
5588     * Boolean indicating if the backend was destroyed.
5589     */
5590
5591    _this.destroyed = false;
5592    return _this;
5593  }
5594  /**
5595   * Initialise the backend, called in `wavesurfer.createBackend()`
5596   */
5597
5598
5599  _createClass(WebAudio, [{
5600    key: "init",
5601    value: function init() {
5602      this.createVolumeNode();
5603      this.createScriptNode();
5604      this.createAnalyserNode();
5605      this.setState(PAUSED);
5606      this.setPlaybackRate(this.params.audioRate);
5607      this.setLength(0);
5608    }
5609    /** @private */
5610
5611  }, {
5612    key: "disconnectFilters",
5613    value: function disconnectFilters() {
5614      if (this.filters) {
5615        this.filters.forEach(function (filter) {
5616          filter && filter.disconnect();
5617        });
5618        this.filters = null; // Reconnect direct path
5619
5620        this.analyser.connect(this.gainNode);
5621      }
5622    }
5623    /**
5624     * @private
5625     *
5626     * @param {string} state The new state
5627     */
5628
5629  }, {
5630    key: "setState",
5631    value: function setState(state) {
5632      if (this.state !== this.states[state]) {
5633        this.state = this.states[state];
5634        this.state.init.call(this);
5635      }
5636    }
5637    /**
5638     * Unpacked `setFilters()`
5639     *
5640     * @param {...AudioNode} filters One or more filters to set
5641     */
5642
5643  }, {
5644    key: "setFilter",
5645    value: function setFilter() {
5646      for (var _len = arguments.length, filters = new Array(_len), _key = 0; _key < _len; _key++) {
5647        filters[_key] = arguments[_key];
5648      }
5649
5650      this.setFilters(filters);
5651    }
5652    /**
5653     * Insert custom Web Audio nodes into the graph
5654     *
5655     * @param {AudioNode[]} filters Packed filters array
5656     * @example
5657     * const lowpass = wavesurfer.backend.ac.createBiquadFilter();
5658     * wavesurfer.backend.setFilter(lowpass);
5659     */
5660
5661  }, {
5662    key: "setFilters",
5663    value: function setFilters(filters) {
5664      // Remove existing filters
5665      this.disconnectFilters(); // Insert filters if filter array not empty
5666
5667      if (filters && filters.length) {
5668        this.filters = filters; // Disconnect direct path before inserting filters
5669
5670        this.analyser.disconnect(); // Connect each filter in turn
5671
5672        filters.reduce(function (prev, curr) {
5673          prev.connect(curr);
5674          return curr;
5675        }, this.analyser).connect(this.gainNode);
5676      }
5677    }
5678    /** Create ScriptProcessorNode to process audio */
5679
5680  }, {
5681    key: "createScriptNode",
5682    value: function createScriptNode() {
5683      if (this.params.audioScriptProcessor) {
5684        this.scriptNode = this.params.audioScriptProcessor;
5685      } else {
5686        if (this.ac.createScriptProcessor) {
5687          this.scriptNode = this.ac.createScriptProcessor(WebAudio.scriptBufferSize);
5688        } else {
5689          this.scriptNode = this.ac.createJavaScriptNode(WebAudio.scriptBufferSize);
5690        }
5691      }
5692
5693      this.scriptNode.connect(this.ac.destination);
5694    }
5695    /** @private */
5696
5697  }, {
5698    key: "addOnAudioProcess",
5699    value: function addOnAudioProcess() {
5700      var _this2 = this;
5701
5702      this.scriptNode.onaudioprocess = function () {
5703        var time = _this2.getCurrentTime();
5704
5705        if (time >= _this2.getDuration()) {
5706          _this2.setState(FINISHED);
5707
5708          _this2.fireEvent('pause');
5709        } else if (time >= _this2.scheduledPause) {
5710          _this2.pause();
5711        } else if (_this2.state === _this2.states[PLAYING]) {
5712          _this2.fireEvent('audioprocess', time);
5713        }
5714      };
5715    }
5716    /** @private */
5717
5718  }, {
5719    key: "removeOnAudioProcess",
5720    value: function removeOnAudioProcess() {
5721      this.scriptNode.onaudioprocess = function () {};
5722    }
5723    /** Create analyser node to perform audio analysis */
5724
5725  }, {
5726    key: "createAnalyserNode",
5727    value: function createAnalyserNode() {
5728      this.analyser = this.ac.createAnalyser();
5729      this.analyser.connect(this.gainNode);
5730    }
5731    /**
5732     * Create the gain node needed to control the playback volume.
5733     *
5734     */
5735
5736  }, {
5737    key: "createVolumeNode",
5738    value: function createVolumeNode() {
5739      // Create gain node using the AudioContext
5740      if (this.ac.createGain) {
5741        this.gainNode = this.ac.createGain();
5742      } else {
5743        this.gainNode = this.ac.createGainNode();
5744      } // Add the gain node to the graph
5745
5746
5747      this.gainNode.connect(this.ac.destination);
5748    }
5749    /**
5750     * Set the sink id for the media player
5751     *
5752     * @param {string} deviceId String value representing audio device id.
5753     * @returns {Promise} A Promise that resolves to `undefined` when there
5754     * are no errors.
5755     */
5756
5757  }, {
5758    key: "setSinkId",
5759    value: function setSinkId(deviceId) {
5760      if (deviceId) {
5761        /**
5762         * The webaudio API doesn't currently support setting the device
5763         * output. Here we create an HTMLAudioElement, connect the
5764         * webaudio stream to that element and setSinkId there.
5765         */
5766        var audio = new window.Audio();
5767
5768        if (!audio.setSinkId) {
5769          return Promise.reject(new Error('setSinkId is not supported in your browser'));
5770        }
5771
5772        audio.autoplay = true;
5773        var dest = this.ac.createMediaStreamDestination();
5774        this.gainNode.disconnect();
5775        this.gainNode.connect(dest);
5776        audio.srcObject = dest.stream;
5777        return audio.setSinkId(deviceId);
5778      } else {
5779        return Promise.reject(new Error('Invalid deviceId: ' + deviceId));
5780      }
5781    }
5782    /**
5783     * Set the audio volume
5784     *
5785     * @param {number} value A floating point value between 0 and 1.
5786     */
5787
5788  }, {
5789    key: "setVolume",
5790    value: function setVolume(value) {
5791      this.gainNode.gain.setValueAtTime(value, this.ac.currentTime);
5792    }
5793    /**
5794     * Get the current volume
5795     *
5796     * @return {number} value A floating point value between 0 and 1.
5797     */
5798
5799  }, {
5800    key: "getVolume",
5801    value: function getVolume() {
5802      return this.gainNode.gain.value;
5803    }
5804    /**
5805     * Decode an array buffer and pass data to a callback
5806     *
5807     * @private
5808     * @param {ArrayBuffer} arraybuffer The array buffer to decode
5809     * @param {function} callback The function to call on complete.
5810     * @param {function} errback The function to call on error.
5811     */
5812
5813  }, {
5814    key: "decodeArrayBuffer",
5815    value: function decodeArrayBuffer(arraybuffer, callback, errback) {
5816      if (!this.offlineAc) {
5817        this.offlineAc = this.getOfflineAudioContext(this.ac && this.ac.sampleRate ? this.ac.sampleRate : 44100);
5818      }
5819
5820      this.offlineAc.decodeAudioData(arraybuffer, function (data) {
5821        return callback(data);
5822      }, errback);
5823    }
5824    /**
5825     * Set pre-decoded peaks
5826     *
5827     * @param {number[]|Number.<Array[]>} peaks Peaks data
5828     * @param {?number} duration Explicit duration
5829     */
5830
5831  }, {
5832    key: "setPeaks",
5833    value: function setPeaks(peaks, duration) {
5834      if (duration != null) {
5835        this.explicitDuration = duration;
5836      }
5837
5838      this.peaks = peaks;
5839    }
5840    /**
5841     * Set the rendered length (different from the length of the audio)
5842     *
5843     * @param {number} length The rendered length
5844     */
5845
5846  }, {
5847    key: "setLength",
5848    value: function setLength(length) {
5849      // No resize, we can preserve the cached peaks.
5850      if (this.mergedPeaks && length == 2 * this.mergedPeaks.length - 1 + 2) {
5851        return;
5852      }
5853
5854      this.splitPeaks = [];
5855      this.mergedPeaks = []; // Set the last element of the sparse array so the peak arrays are
5856      // appropriately sized for other calculations.
5857
5858      var channels = this.buffer ? this.buffer.numberOfChannels : 1;
5859      var c;
5860
5861      for (c = 0; c < channels; c++) {
5862        this.splitPeaks[c] = [];
5863        this.splitPeaks[c][2 * (length - 1)] = 0;
5864        this.splitPeaks[c][2 * (length - 1) + 1] = 0;
5865      }
5866
5867      this.mergedPeaks[2 * (length - 1)] = 0;
5868      this.mergedPeaks[2 * (length - 1) + 1] = 0;
5869    }
5870    /**
5871     * Compute the max and min value of the waveform when broken into <length> subranges.
5872     *
5873     * @param {number} length How many subranges to break the waveform into.
5874     * @param {number} first First sample in the required range.
5875     * @param {number} last Last sample in the required range.
5876     * @return {number[]|Number.<Array[]>} Array of 2*<length> peaks or array of arrays of
5877     * peaks consisting of (max, min) values for each subrange.
5878     */
5879
5880  }, {
5881    key: "getPeaks",
5882    value: function getPeaks(length, first, last) {
5883      if (this.peaks) {
5884        return this.peaks;
5885      }
5886
5887      if (!this.buffer) {
5888        return [];
5889      }
5890
5891      first = first || 0;
5892      last = last || length - 1;
5893      this.setLength(length);
5894
5895      if (!this.buffer) {
5896        return this.params.splitChannels ? this.splitPeaks : this.mergedPeaks;
5897      }
5898      /**
5899       * The following snippet fixes a buffering data issue on the Safari
5900       * browser which returned undefined It creates the missing buffer based
5901       * on 1 channel, 4096 samples and the sampleRate from the current
5902       * webaudio context 4096 samples seemed to be the best fit for rendering
5903       * will review this code once a stable version of Safari TP is out
5904       */
5905
5906
5907      if (!this.buffer.length) {
5908        var newBuffer = this.createBuffer(1, 4096, this.sampleRate);
5909        this.buffer = newBuffer.buffer;
5910      }
5911
5912      var sampleSize = this.buffer.length / length;
5913      var sampleStep = ~~(sampleSize / 10) || 1;
5914      var channels = this.buffer.numberOfChannels;
5915      var c;
5916
5917      for (c = 0; c < channels; c++) {
5918        var peaks = this.splitPeaks[c];
5919        var chan = this.buffer.getChannelData(c);
5920        var i = void 0;
5921
5922        for (i = first; i <= last; i++) {
5923          var start = ~~(i * sampleSize);
5924          var end = ~~(start + sampleSize);
5925          var min = 0;
5926          var max = 0;
5927          var j = void 0;
5928
5929          for (j = start; j < end; j += sampleStep) {
5930            var value = chan[j];
5931
5932            if (value > max) {
5933              max = value;
5934            }
5935
5936            if (value < min) {
5937              min = value;
5938            }
5939          }
5940
5941          peaks[2 * i] = max;
5942          peaks[2 * i + 1] = min;
5943
5944          if (c == 0 || max > this.mergedPeaks[2 * i]) {
5945            this.mergedPeaks[2 * i] = max;
5946          }
5947
5948          if (c == 0 || min < this.mergedPeaks[2 * i + 1]) {
5949            this.mergedPeaks[2 * i + 1] = min;
5950          }
5951        }
5952      }
5953
5954      return this.params.splitChannels ? this.splitPeaks : this.mergedPeaks;
5955    }
5956    /**
5957     * Get the position from 0 to 1
5958     *
5959     * @return {number} Position
5960     */
5961
5962  }, {
5963    key: "getPlayedPercents",
5964    value: function getPlayedPercents() {
5965      return this.state.getPlayedPercents.call(this);
5966    }
5967    /** @private */
5968
5969  }, {
5970    key: "disconnectSource",
5971    value: function disconnectSource() {
5972      if (this.source) {
5973        this.source.disconnect();
5974      }
5975    }
5976    /**
5977     * This is called when wavesurfer is destroyed
5978     */
5979
5980  }, {
5981    key: "destroy",
5982    value: function destroy() {
5983      if (!this.isPaused()) {
5984        this.pause();
5985      }
5986
5987      this.unAll();
5988      this.buffer = null;
5989      this.destroyed = true;
5990      this.disconnectFilters();
5991      this.disconnectSource();
5992      this.gainNode.disconnect();
5993      this.scriptNode.disconnect();
5994      this.analyser.disconnect(); // close the audioContext if closeAudioContext option is set to true
5995
5996      if (this.params.closeAudioContext) {
5997        // check if browser supports AudioContext.close()
5998        if (typeof this.ac.close === 'function' && this.ac.state != 'closed') {
5999          this.ac.close();
6000        } // clear the reference to the audiocontext
6001
6002
6003        this.ac = null; // clear the actual audiocontext, either passed as param or the
6004        // global singleton
6005
6006        if (!this.params.audioContext) {
6007          window.WaveSurferAudioContext = null;
6008        } else {
6009          this.params.audioContext = null;
6010        } // clear the offlineAudioContext
6011
6012
6013        window.WaveSurferOfflineAudioContext = null;
6014      }
6015    }
6016    /**
6017     * Loaded a decoded audio buffer
6018     *
6019     * @param {Object} buffer Decoded audio buffer to load
6020     */
6021
6022  }, {
6023    key: "load",
6024    value: function load(buffer) {
6025      this.startPosition = 0;
6026      this.lastPlay = this.ac.currentTime;
6027      this.buffer = buffer;
6028      this.createSource();
6029    }
6030    /** @private */
6031
6032  }, {
6033    key: "createSource",
6034    value: function createSource() {
6035      this.disconnectSource();
6036      this.source = this.ac.createBufferSource(); // adjust for old browsers
6037
6038      this.source.start = this.source.start || this.source.noteGrainOn;
6039      this.source.stop = this.source.stop || this.source.noteOff;
6040      this.source.playbackRate.setValueAtTime(this.playbackRate, this.ac.currentTime);
6041      this.source.buffer = this.buffer;
6042      this.source.connect(this.analyser);
6043    }
6044    /**
6045     * Used by `wavesurfer.isPlaying()` and `wavesurfer.playPause()`
6046     *
6047     * @return {boolean} Whether or not this backend is currently paused
6048     */
6049
6050  }, {
6051    key: "isPaused",
6052    value: function isPaused() {
6053      return this.state !== this.states[PLAYING];
6054    }
6055    /**
6056     * Used by `wavesurfer.getDuration()`
6057     *
6058     * @return {number} Duration of loaded buffer
6059     */
6060
6061  }, {
6062    key: "getDuration",
6063    value: function getDuration() {
6064      if (this.explicitDuration) {
6065        return this.explicitDuration;
6066      }
6067
6068      if (!this.buffer) {
6069        return 0;
6070      }
6071
6072      return this.buffer.duration;
6073    }
6074    /**
6075     * Used by `wavesurfer.seekTo()`
6076     *
6077     * @param {number} start Position to start at in seconds
6078     * @param {number} end Position to end at in seconds
6079     * @return {{start: number, end: number}} Object containing start and end
6080     * positions
6081     */
6082
6083  }, {
6084    key: "seekTo",
6085    value: function seekTo(start, end) {
6086      if (!this.buffer) {
6087        return;
6088      }
6089
6090      this.scheduledPause = null;
6091
6092      if (start == null) {
6093        start = this.getCurrentTime();
6094
6095        if (start >= this.getDuration()) {
6096          start = 0;
6097        }
6098      }
6099
6100      if (end == null) {
6101        end = this.getDuration();
6102      }
6103
6104      this.startPosition = start;
6105      this.lastPlay = this.ac.currentTime;
6106
6107      if (this.state === this.states[FINISHED]) {
6108        this.setState(PAUSED);
6109      }
6110
6111      return {
6112        start: start,
6113        end: end
6114      };
6115    }
6116    /**
6117     * Get the playback position in seconds
6118     *
6119     * @return {number} The playback position in seconds
6120     */
6121
6122  }, {
6123    key: "getPlayedTime",
6124    value: function getPlayedTime() {
6125      return (this.ac.currentTime - this.lastPlay) * this.playbackRate;
6126    }
6127    /**
6128     * Plays the loaded audio region.
6129     *
6130     * @param {number} start Start offset in seconds, relative to the beginning
6131     * of a clip.
6132     * @param {number} end When to stop relative to the beginning of a clip.
6133     */
6134
6135  }, {
6136    key: "play",
6137    value: function play(start, end) {
6138      if (!this.buffer) {
6139        return;
6140      } // need to re-create source on each playback
6141
6142
6143      this.createSource();
6144      var adjustedTime = this.seekTo(start, end);
6145      start = adjustedTime.start;
6146      end = adjustedTime.end;
6147      this.scheduledPause = end;
6148      this.source.start(0, start);
6149
6150      if (this.ac.state == 'suspended') {
6151        this.ac.resume && this.ac.resume();
6152      }
6153
6154      this.setState(PLAYING);
6155      this.fireEvent('play');
6156    }
6157    /**
6158     * Pauses the loaded audio.
6159     */
6160
6161  }, {
6162    key: "pause",
6163    value: function pause() {
6164      this.scheduledPause = null;
6165      this.startPosition += this.getPlayedTime();
6166      this.source && this.source.stop(0);
6167      this.setState(PAUSED);
6168      this.fireEvent('pause');
6169    }
6170    /**
6171     * Returns the current time in seconds relative to the audio-clip's
6172     * duration.
6173     *
6174     * @return {number} The current time in seconds
6175     */
6176
6177  }, {
6178    key: "getCurrentTime",
6179    value: function getCurrentTime() {
6180      return this.state.getCurrentTime.call(this);
6181    }
6182    /**
6183     * Returns the current playback rate. (0=no playback, 1=normal playback)
6184     *
6185     * @return {number} The current playback rate
6186     */
6187
6188  }, {
6189    key: "getPlaybackRate",
6190    value: function getPlaybackRate() {
6191      return this.playbackRate;
6192    }
6193    /**
6194     * Set the audio source playback rate.
6195     *
6196     * @param {number} value The playback rate to use
6197     */
6198
6199  }, {
6200    key: "setPlaybackRate",
6201    value: function setPlaybackRate(value) {
6202      value = value || 1;
6203
6204      if (this.isPaused()) {
6205        this.playbackRate = value;
6206      } else {
6207        this.pause();
6208        this.playbackRate = value;
6209        this.play();
6210      }
6211    }
6212    /**
6213     * Set a point in seconds for playback to stop at.
6214     *
6215     * @param {number} end Position to end at
6216     * @version 3.3.0
6217     */
6218
6219  }, {
6220    key: "setPlayEnd",
6221    value: function setPlayEnd(end) {
6222      this.scheduledPause = end;
6223    }
6224  }]);
6225
6226  return WebAudio;
6227}(util.Observer);
6228
6229exports.default = WebAudio;
6230WebAudio.scriptBufferSize = 256;
6231module.exports = exports.default;
6232
6233/***/ })
6233
6234
6235/******/ });
6236});
6237//# sourceMappingURL=wavesurfer.js.map

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.