Index: /gs3-extensions/web-audio/trunk/wavesurfer/INSTALL.sh
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/INSTALL.sh	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/INSTALL.sh	(revision 33546)
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+
+if [ ! -d ../../../web/ext ] ; then
+  echo "  Making directory: ../../../web/ext"
+  mkdir ../../../web/ext
+fi
+
+if [ ! -d ../../../web/ext/audio ] ; then
+  echo "  Making directory: ../../../web/ext/audio"
+  mkdir ../../../web/ext/audio
+fi
+
+echo "  Installing 'wavesurfer' into ../../../web/ext/audio"
+
+/bin/cp -r ws css wavesurfer-player.js ../../../web/ext/audio/.
+
Index: /gs3-extensions/web-audio/trunk/wavesurfer/css/ribbon.css
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/css/ribbon.css	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/css/ribbon.css	(revision 33546)
@@ -0,0 +1,140 @@
+/*!
+ * "Fork me on GitHub" CSS ribbon v0.1.1 | MIT License
+ * https://github.com/simonwhitaker/github-fork-ribbon-css
+*/
+
+/* Left will inherit from right (so we don't need to duplicate code) */
+.github-fork-ribbon {
+  /* The right and left classes determine the side we attach our banner to */
+  position: absolute;
+
+  /* Add a bit of padding to give some substance outside the "stitching" */
+  padding: 2px 0;
+
+  /* Set the base colour */
+  background-color: #a00;
+
+  /* Set a gradient: transparent black at the top to almost-transparent black at the bottom */
+  background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 0)), to(rgba(0, 0, 0, 0.15)));
+  background-image: -webkit-linear-gradient(top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15));
+  background-image: -moz-linear-gradient(top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15));
+  background-image: -ms-linear-gradient(top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15));
+  background-image: -o-linear-gradient(top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15));
+  background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15));
+
+  /* Add a drop shadow */
+  -webkit-box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.5);
+  -moz-box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.5);
+  box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.5);
+
+  /* Set the font */
+  font: 700 13px "Helvetica Neue", Helvetica, Arial, sans-serif;
+
+  z-index: 9999;
+  pointer-events: auto;
+}
+
+.github-fork-ribbon a,
+.github-fork-ribbon a:hover {
+  /* Set the text properties */
+  color: #fff;
+  text-decoration: none;
+  text-shadow: 0 -1px rgba(0, 0, 0, 0.5);
+  text-align: center;
+
+  /* Set the geometry. If you fiddle with these you'll also need
+     to tweak the top and right values in .github-fork-ribbon. */
+  width: 200px;
+  line-height: 20px;
+
+  /* Set the layout properties */
+  display: inline-block;
+  padding: 2px 0;
+
+  /* Add "stitching" effect */
+  border-width: 1px 0;
+  border-style: dotted;
+  border-color: #fff;
+  border-color: rgba(255, 255, 255, 0.7);
+}
+
+.github-fork-ribbon-wrapper {
+  width: 150px;
+  height: 150px;
+  position: absolute;
+  overflow: hidden;
+  top: 0;
+  z-index: 9999;
+  pointer-events: none;
+}
+
+.github-fork-ribbon-wrapper.fixed {
+  position: fixed;
+}
+
+.github-fork-ribbon-wrapper.left {
+  left: 0;
+}
+
+.github-fork-ribbon-wrapper.right {
+  right: 0;
+}
+
+.github-fork-ribbon-wrapper.left-bottom {
+  position: fixed;
+  top: inherit;
+  bottom: 0;
+  left: 0;
+}
+
+.github-fork-ribbon-wrapper.right-bottom {
+  position: fixed;
+  top: inherit;
+  bottom: 0;
+  right: 0;
+}
+
+.github-fork-ribbon-wrapper.right .github-fork-ribbon {
+  top: 42px;
+  right: -43px;
+
+  -webkit-transform: rotate(45deg);
+  -moz-transform: rotate(45deg);
+  -ms-transform: rotate(45deg);
+  -o-transform: rotate(45deg);
+  transform: rotate(45deg);
+}
+
+.github-fork-ribbon-wrapper.left .github-fork-ribbon {
+  top: 42px;
+  left: -43px;
+
+  -webkit-transform: rotate(-45deg);
+  -moz-transform: rotate(-45deg);
+  -ms-transform: rotate(-45deg);
+  -o-transform: rotate(-45deg);
+  transform: rotate(-45deg);
+}
+
+
+.github-fork-ribbon-wrapper.left-bottom .github-fork-ribbon {
+  top: 80px;
+  left: -43px;
+
+  -webkit-transform: rotate(45deg);
+  -moz-transform: rotate(45deg);
+  -ms-transform: rotate(45deg);
+  -o-transform: rotate(45deg);
+  transform: rotate(45deg);
+}
+
+.github-fork-ribbon-wrapper.right-bottom .github-fork-ribbon {
+  top: 80px;
+  right: -43px;
+
+  -webkit-transform: rotate(-45deg);
+  -moz-transform: rotate(-45deg);
+  -ms-transform: rotate(-45deg);
+  -o-transform: rotate(-45deg);
+  transform: rotate(-45deg);
+}
Index: /gs3-extensions/web-audio/trunk/wavesurfer/css/style.css
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/css/style.css	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/css/style.css	(revision 33546)
@@ -0,0 +1,110 @@
+/* Space out content a bit */
+body {
+    padding-top: 20px;
+    padding-bottom: 20px;
+}
+
+/* Everything but the jumbotron gets side spacing for mobile first views */
+.header,
+.marketing,
+.footer {
+    padding-left: 15px;
+    padding-right: 15px;
+}
+
+/* Custom page header */
+.header {
+    border-bottom: 1px solid #e5e5e5;
+}
+
+/* Make the masthead heading the same height as the navigation */
+.header h3 {
+    margin-top: 0;
+    margin-bottom: 0;
+    line-height: 40px;
+    padding-bottom: 19px;
+}
+
+/* Custom page footer */
+.footer {
+    padding-top: 19px;
+    color: #777;
+    border-top: 1px solid #e5e5e5;
+}
+
+/* Customize container */
+@media (min-width: 1024px) {
+    .container {
+        max-width: 900px;
+    }
+}
+
+.container-narrow > hr {
+    margin: 30px 0;
+}
+
+/* Supporting marketing content */
+.marketing {
+    margin: 40px 0;
+}
+
+.marketing p + h4 {
+    margin-top: 28px;
+}
+
+/* Responsive: Portrait tablets and up */
+@media screen and (min-width: 768px) {
+    /* Remove the padding we set earlier */
+    .header,
+    .marketing,
+    .footer {
+        padding-left: 0;
+        padding-right: 0;
+    }
+    /* Space out the masthead */
+    .header {
+        margin-bottom: 30px;
+    }
+}
+
+.controls {
+    padding: 30px 0 15px;
+    text-align: center;
+}
+
+.controls .btn {
+    margin-bottom: 15px;
+}
+
+@media screen and (min-width: 990px) {
+    .controls .mark-controls {
+        display: inline;
+    }
+}
+
+.lead {
+    text-align: center;
+    padding: 20px;
+}
+
+#waveform {
+    position: relative;
+}
+
+#progress-bar {
+    position: absolute;
+    z-index: 10;
+    top: 50%;
+    margin-top: -10px;
+    left: 5%;
+    width: 90%;
+}
+
+#drop {
+    border: 3px dashed #ddd;
+    padding: 30px;
+}
+
+#drop.wavesurfer-dragover {
+    border-color: #333;
+}
Index: /gs3-extensions/web-audio/trunk/wavesurfer/wavesurfer-player.js
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/wavesurfer-player.js	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/wavesurfer-player.js	(revision 33546)
@@ -0,0 +1,41 @@
+'use strict';
+
+// Create an instance
+var wavesurfer = {};
+
+// Init & load audio file
+document.addEventListener('DOMContentLoaded', function() {
+    wavesurfer = WaveSurfer.create({
+        container: document.querySelector('#waveform'),
+	minPxPerSec: 2,
+	//normalize: true,
+	barWidth: 2,
+	barHeight: 3, // the height of the wave
+	barGap: 1, // the optional spacing between bars of the wave, if not provided will be calculated in legacy format
+        plugins: [
+            WaveSurfer.cursor.create({
+                showTime: true,
+                opacity: 1,
+                customShowTimeStyle: {
+                    'background-color': '#000',
+                    color: '#fff',
+                    padding: '2px',
+                    'font-size': '10px'
+                }
+		}),
+	    WaveSurfer.timeline.create({
+		    container: "#wave-timeline"
+		})
+        ]
+    });
+
+    wavesurfer.on('error', function(e) {
+        console.warn(e);
+    });
+
+
+    // Play button
+    var button = document.querySelector('[data-action="play"]');
+
+    button.addEventListener('click', wavesurfer.playPause.bind(wavesurfer));
+});
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.cursor.js
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.cursor.js	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.cursor.js	(revision 33546)
@@ -0,0 +1,425 @@
+/*!
+ * wavesurfer.js cursor plugin 2.2.1 (2019-09-30)
+ * https://github.com/katspaugh/wavesurfer.js
+ * @license BSD-3-Clause
+ */
+(function webpackUniversalModuleDefinition(root, factory) {
+	if(typeof exports === 'object' && typeof module === 'object')
+		module.exports = factory();
+	else if(typeof define === 'function' && define.amd)
+		define("cursor", [], factory);
+	else if(typeof exports === 'object')
+		exports["cursor"] = factory();
+	else
+		root["WaveSurfer"] = root["WaveSurfer"] || {}, root["WaveSurfer"]["cursor"] = factory();
+})(window, function() {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+/******/
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId]) {
+/******/ 			return installedModules[moduleId].exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			i: moduleId,
+/******/ 			l: false,
+/******/ 			exports: {}
+/******/ 		};
+/******/
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ 		// Flag the module as loaded
+/******/ 		module.l = true;
+/******/
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/
+/******/
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+/******/
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+/******/
+/******/ 	// define getter function for harmony exports
+/******/ 	__webpack_require__.d = function(exports, name, getter) {
+/******/ 		if(!__webpack_require__.o(exports, name)) {
+/******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
+/******/ 		}
+/******/ 	};
+/******/
+/******/ 	// define __esModule on exports
+/******/ 	__webpack_require__.r = function(exports) {
+/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ 		}
+/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
+/******/ 	};
+/******/
+/******/ 	// create a fake namespace object
+/******/ 	// mode & 1: value is a module id, require it
+/******/ 	// mode & 2: merge all properties of value into the ns
+/******/ 	// mode & 4: return value when already ns object
+/******/ 	// mode & 8|1: behave like require
+/******/ 	__webpack_require__.t = function(value, mode) {
+/******/ 		if(mode & 1) value = __webpack_require__(value);
+/******/ 		if(mode & 8) return value;
+/******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
+/******/ 		var ns = Object.create(null);
+/******/ 		__webpack_require__.r(ns);
+/******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
+/******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
+/******/ 		return ns;
+/******/ 	};
+/******/
+/******/ 	// getDefaultExport function for compatibility with non-harmony modules
+/******/ 	__webpack_require__.n = function(module) {
+/******/ 		var getter = module && module.__esModule ?
+/******/ 			function getDefault() { return module['default']; } :
+/******/ 			function getModuleExports() { return module; };
+/******/ 		__webpack_require__.d(getter, 'a', getter);
+/******/ 		return getter;
+/******/ 	};
+/******/
+/******/ 	// Object.prototype.hasOwnProperty.call
+/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "localhost:8080/dist/plugin/";
+/******/
+/******/
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(__webpack_require__.s = "./src/plugin/cursor.js");
+/******/ })
+/************************************************************************/
+/******/ ({
+
+/***/ "./src/plugin/cursor.js":
+/*!******************************!*\
+  !*** ./src/plugin/cursor.js ***!
+  \******************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+/**
+ * @typedef {Object} CursorPluginParams
+ * @property {?boolean} deferInit Set to true to stop auto init in `addPlugin()`
+ * @property {boolean} hideOnBlur=true Hide the cursor when the mouse leaves the
+ * waveform
+ * @property {string} width='1px' The width of the cursor
+ * @property {string} color='black' The color of the cursor
+ * @property {string} opacity='0.25' The opacity of the cursor
+ * @property {string} style='solid' The border style of the cursor
+ * @property {number} zIndex=3 The z-index of the cursor element
+ * @property {object} customStyle An object with custom styles which are applied
+ * to the cursor element
+ * @property {boolean} showTime=false Show the time on the cursor.
+ * @property {object} customShowTimeStyle An object with custom styles which are
+ * applied to the cursor time element.
+ */
+
+/**
+ * Displays a thin line at the position of the cursor on the waveform.
+ *
+ * @implements {PluginClass}
+ * @extends {Observer}
+ * @example
+ * // es6
+ * import CursorPlugin from 'wavesurfer.cursor.js';
+ *
+ * // commonjs
+ * var CursorPlugin = require('wavesurfer.cursor.js');
+ *
+ * // if you are using <script> tags
+ * var CursorPlugin = window.WaveSurfer.cursor;
+ *
+ * // ... initialising wavesurfer with the plugin
+ * var wavesurfer = WaveSurfer.create({
+ *   // wavesurfer options ...
+ *   plugins: [
+ *     CursorPlugin.create({
+ *       // plugin options ...
+ *     })
+ *   ]
+ * });
+ */
+var CursorPlugin =
+/*#__PURE__*/
+function () {
+  _createClass(CursorPlugin, null, [{
+    key: "create",
+
+    /**
+     * Cursor plugin definition factory
+     *
+     * This function must be used to create a plugin definition which can be
+     * used by wavesurfer to correctly instantiate the plugin.
+     *
+     * @param  {CursorPluginParams} params parameters use to initialise the
+     * plugin
+     * @return {PluginDefinition} an object representing the plugin
+     */
+    value: function create(params) {
+      return {
+        name: 'cursor',
+        deferInit: params && params.deferInit ? params.deferInit : false,
+        params: params,
+        staticProps: {
+          enableCursor: function enableCursor() {
+            console.warn('Deprecated enableCursor!');
+            this.initPlugins('cursor');
+          }
+        },
+        instance: CursorPlugin
+      };
+    }
+    /**
+     * @type {CursorPluginParams}
+     */
+
+  }]);
+
+  /**
+   * Construct the plugin class. You probably want to use CursorPlugin.create
+   * instead.
+   *
+   * @param {CursorPluginParams} params
+   * @param {object} ws
+   */
+  function CursorPlugin(params, ws) {
+    var _this = this;
+
+    _classCallCheck(this, CursorPlugin);
+
+    this.defaultParams = {
+      hideOnBlur: true,
+      width: '1px',
+      color: 'black',
+      opacity: '0.25',
+      style: 'solid',
+      zIndex: 4,
+      customStyle: {},
+      customShowTimeStyle: {},
+      showTime: false
+    };
+
+    this._onMousemove = function (e) {
+      var bbox = _this.wavesurfer.container.getBoundingClientRect();
+
+      _this.updateCursorPosition(e.clientX - bbox.left);
+    };
+
+    this._onMouseenter = function () {
+      return _this.showCursor();
+    };
+
+    this._onMouseleave = function () {
+      return _this.hideCursor();
+    };
+
+    /** @private */
+    this.wavesurfer = ws;
+    /** @private */
+
+    this.style = ws.util.style;
+    /**
+     * The cursor HTML element
+     *
+     * @type {?HTMLElement}
+     */
+
+    this.cursor = null;
+    /**
+     * displays the time next to the cursor
+     *
+     * @type {Boolean}
+     */
+
+    this.showTime = null;
+    /**
+     * The html container that will display the time
+     *
+     * @type {?HTMLElement}
+     */
+
+    this.displayTime = null;
+    /** @private */
+
+    this.params = ws.util.extend({}, this.defaultParams, params);
+  }
+  /**
+   * Initialise the plugin (used by the Plugin API)
+   */
+
+
+  _createClass(CursorPlugin, [{
+    key: "init",
+    value: function init() {
+      this.wrapper = this.wavesurfer.container;
+      this.cursor = this.wrapper.appendChild(this.style(document.createElement('cursor'), this.wavesurfer.util.extend({
+        position: 'absolute',
+        zIndex: this.params.zIndex,
+        left: 0,
+        top: 0,
+        bottom: 0,
+        width: '0',
+        display: 'flex',
+        borderRightStyle: this.params.style,
+        borderRightWidth: this.params.width,
+        borderRightColor: this.params.color,
+        opacity: this.params.opacity,
+        pointerEvents: 'none'
+      }, this.params.customStyle)));
+
+      if (this.params.showTime) {
+        this.showTime = this.wrapper.appendChild(this.style(document.createElement('showTitle'), this.wavesurfer.util.extend({
+          position: 'absolute',
+          zIndex: this.params.zIndex,
+          left: 0,
+          top: 0,
+          bottom: 0,
+          width: 'auto',
+          display: 'flex',
+          opacity: this.params.opacity,
+          pointerEvents: 'none',
+          height: '100%'
+        }, this.params.customStyle)));
+        this.displayTime = this.showTime.appendChild(this.style(document.createElement('div'), this.wavesurfer.util.extend({
+          display: 'inline',
+          pointerEvents: 'none',
+          margin: 'auto'
+        }, this.params.customShowTimeStyle)));
+      }
+
+      this.wrapper.addEventListener('mousemove', this._onMousemove);
+
+      if (this.params.hideOnBlur) {
+        this.wrapper.addEventListener('mouseenter', this._onMouseenter);
+        this.wrapper.addEventListener('mouseleave', this._onMouseleave);
+      }
+    }
+    /**
+     * Destroy the plugin (used by the Plugin API)
+     */
+
+  }, {
+    key: "destroy",
+    value: function destroy() {
+      if (this.params.showTime) {
+        this.cursor.parentNode.removeChild(this.showTime);
+      }
+
+      this.cursor.parentNode.removeChild(this.cursor);
+      this.wrapper.removeEventListener('mousemove', this._onMousemove);
+
+      if (this.params.hideOnBlur) {
+        this.wrapper.removeEventListener('mouseenter', this._onMouseenter);
+        this.wrapper.removeEventListener('mouseleave', this._onMouseleave);
+      }
+    }
+    /**
+     * Update the cursor position
+     *
+     * @param {number} pos The x offset of the cursor in pixels
+     */
+
+  }, {
+    key: "updateCursorPosition",
+    value: function updateCursorPosition(pos) {
+      this.style(this.cursor, {
+        left: "".concat(pos, "px")
+      });
+
+      if (this.params.showTime) {
+        var duration = this.wavesurfer.getDuration();
+        var elementWidth = this.wavesurfer.drawer.width / this.wavesurfer.params.pixelRatio;
+        var scrollWidth = this.wavesurfer.drawer.getScrollX();
+        var scrollTime = duration / this.wavesurfer.drawer.width * scrollWidth;
+        var timeValue = Math.max(0, pos / elementWidth * duration) + scrollTime;
+        var formatValue = this.formatTime(timeValue);
+        this.style(this.showTime, {
+          left: "".concat(pos, "px")
+        });
+        this.displayTime.innerHTML = "".concat(formatValue);
+      }
+    }
+    /**
+     * Show the cursor
+     */
+
+  }, {
+    key: "showCursor",
+    value: function showCursor() {
+      this.style(this.cursor, {
+        display: 'flex'
+      });
+
+      if (this.params.showTime) {
+        this.style(this.showTime, {
+          display: 'flex'
+        });
+      }
+    }
+    /**
+     * Hide the cursor
+     */
+
+  }, {
+    key: "hideCursor",
+    value: function hideCursor() {
+      this.style(this.cursor, {
+        display: 'none'
+      });
+
+      if (this.params.showTime) {
+        this.style(this.showTime, {
+          display: 'none'
+        });
+      }
+    }
+    /** timestamp time calculation */
+
+  }, {
+    key: "formatTime",
+    value: function formatTime(cursorTime) {
+      return [cursorTime].map(function (time) {
+        return [Math.floor(time % 3600 / 60), // minutes
+        ('00' + Math.floor(time % 60)).slice(-2), // seconds
+        ('000' + Math.floor(time % 1 * 1000)).slice(-3) // miliseconds
+        ].join(':');
+      });
+    }
+  }]);
+
+  return CursorPlugin;
+}();
+
+exports.default = CursorPlugin;
+module.exports = exports.default;
+
+/***/ })
+
+/******/ });
+});
+//# sourceMappingURL=wavesurfer.cursor.js.map
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.cursor.js.map
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.cursor.js.map	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.cursor.js.map	(revision 33546)
@@ -0,0 +1,1 @@
+{"version":3,"sources":["webpack://WaveSurfer.[name]/webpack/universalModuleDefinition","webpack://WaveSurfer.[name]/webpack/bootstrap","webpack://WaveSurfer.[name]/./src/plugin/cursor.js"],"names":["CursorPlugin","params","name","deferInit","staticProps","enableCursor","console","warn","initPlugins","instance","ws","defaultParams","hideOnBlur","width","color","opacity","style","zIndex","customStyle","customShowTimeStyle","showTime","_onMousemove","e","bbox","wavesurfer","container","getBoundingClientRect","updateCursorPosition","clientX","left","_onMouseenter","showCursor","_onMouseleave","hideCursor","util","cursor","displayTime","extend","wrapper","appendChild","document","createElement","position","top","bottom","display","borderRightStyle","borderRightWidth","borderRightColor","pointerEvents","height","margin","addEventListener","parentNode","removeChild","removeEventListener","pos","duration","getDuration","elementWidth","drawer","pixelRatio","scrollWidth","getScrollX","scrollTime","timeValue","Math","max","formatValue","formatTime","innerHTML","cursorTime","map","time","floor","slice","join"],"mappings":"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","file":"wavesurfer.cursor.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"cursor\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"cursor\"] = factory();\n\telse\n\t\troot[\"WaveSurfer\"] = root[\"WaveSurfer\"] || {}, root[\"WaveSurfer\"][\"cursor\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"localhost:8080/dist/plugin/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/plugin/cursor.js\");\n","/**\n * @typedef {Object} CursorPluginParams\n * @property {?boolean} deferInit Set to true to stop auto init in `addPlugin()`\n * @property {boolean} hideOnBlur=true Hide the cursor when the mouse leaves the\n * waveform\n * @property {string} width='1px' The width of the cursor\n * @property {string} color='black' The color of the cursor\n * @property {string} opacity='0.25' The opacity of the cursor\n * @property {string} style='solid' The border style of the cursor\n * @property {number} zIndex=3 The z-index of the cursor element\n * @property {object} customStyle An object with custom styles which are applied\n * to the cursor element\n * @property {boolean} showTime=false Show the time on the cursor.\n * @property {object} customShowTimeStyle An object with custom styles which are\n * applied to the cursor time element.\n */\n\n/**\n * Displays a thin line at the position of the cursor on the waveform.\n *\n * @implements {PluginClass}\n * @extends {Observer}\n * @example\n * // es6\n * import CursorPlugin from 'wavesurfer.cursor.js';\n *\n * // commonjs\n * var CursorPlugin = require('wavesurfer.cursor.js');\n *\n * // if you are using <script> tags\n * var CursorPlugin = window.WaveSurfer.cursor;\n *\n * // ... initialising wavesurfer with the plugin\n * var wavesurfer = WaveSurfer.create({\n *   // wavesurfer options ...\n *   plugins: [\n *     CursorPlugin.create({\n *       // plugin options ...\n *     })\n *   ]\n * });\n */\nexport default class CursorPlugin {\n    /**\n     * Cursor plugin definition factory\n     *\n     * This function must be used to create a plugin definition which can be\n     * used by wavesurfer to correctly instantiate the plugin.\n     *\n     * @param  {CursorPluginParams} params parameters use to initialise the\n     * plugin\n     * @return {PluginDefinition} an object representing the plugin\n     */\n    static create(params) {\n        return {\n            name: 'cursor',\n            deferInit: params && params.deferInit ? params.deferInit : false,\n            params: params,\n            staticProps: {\n                enableCursor() {\n                    console.warn('Deprecated enableCursor!');\n                    this.initPlugins('cursor');\n                }\n            },\n            instance: CursorPlugin\n        };\n    }\n\n    /**\n     * @type {CursorPluginParams}\n     */\n    defaultParams = {\n        hideOnBlur: true,\n        width: '1px',\n        color: 'black',\n        opacity: '0.25',\n        style: 'solid',\n        zIndex: 4,\n        customStyle: {},\n        customShowTimeStyle: {},\n        showTime: false\n    };\n\n    /** @private */\n    _onMousemove = e => {\n        const bbox = this.wavesurfer.container.getBoundingClientRect();\n        this.updateCursorPosition(e.clientX - bbox.left);\n    };\n    /** @private */\n    _onMouseenter = () => this.showCursor();\n    /** @private */\n    _onMouseleave = () => this.hideCursor();\n\n    /**\n     * Construct the plugin class. You probably want to use CursorPlugin.create\n     * instead.\n     *\n     * @param {CursorPluginParams} params\n     * @param {object} ws\n     */\n    constructor(params, ws) {\n        /** @private */\n        this.wavesurfer = ws;\n        /** @private */\n        this.style = ws.util.style;\n        /**\n         * The cursor HTML element\n         *\n         * @type {?HTMLElement}\n         */\n        this.cursor = null;\n        /**\n         * displays the time next to the cursor\n         *\n         * @type {Boolean}\n         */\n        this.showTime = null;\n        /**\n         * The html container that will display the time\n         *\n         * @type {?HTMLElement}\n         */\n        this.displayTime = null;\n        /** @private */\n        this.params = ws.util.extend({}, this.defaultParams, params);\n    }\n\n    /**\n     * Initialise the plugin (used by the Plugin API)\n     */\n    init() {\n        this.wrapper = this.wavesurfer.container;\n        this.cursor = this.wrapper.appendChild(\n            this.style(\n                document.createElement('cursor'),\n                this.wavesurfer.util.extend(\n                    {\n                        position: 'absolute',\n                        zIndex: this.params.zIndex,\n                        left: 0,\n                        top: 0,\n                        bottom: 0,\n                        width: '0',\n                        display: 'flex',\n                        borderRightStyle: this.params.style,\n                        borderRightWidth: this.params.width,\n                        borderRightColor: this.params.color,\n                        opacity: this.params.opacity,\n                        pointerEvents: 'none'\n                    },\n                    this.params.customStyle\n                )\n            )\n        );\n        if (this.params.showTime) {\n            this.showTime = this.wrapper.appendChild(\n                this.style(\n                    document.createElement('showTitle'),\n                    this.wavesurfer.util.extend(\n                        {\n                            position: 'absolute',\n                            zIndex: this.params.zIndex,\n                            left: 0,\n                            top: 0,\n                            bottom: 0,\n                            width: 'auto',\n                            display: 'flex',\n                            opacity: this.params.opacity,\n                            pointerEvents: 'none',\n                            height: '100%'\n                        },\n                        this.params.customStyle\n                    )\n                )\n            );\n            this.displayTime = this.showTime.appendChild(\n                this.style(\n                    document.createElement('div'),\n                    this.wavesurfer.util.extend(\n                        {\n                            display: 'inline',\n                            pointerEvents: 'none',\n                            margin: 'auto'\n                        },\n                        this.params.customShowTimeStyle\n                    )\n                )\n            );\n        }\n\n        this.wrapper.addEventListener('mousemove', this._onMousemove);\n        if (this.params.hideOnBlur) {\n            this.wrapper.addEventListener('mouseenter', this._onMouseenter);\n            this.wrapper.addEventListener('mouseleave', this._onMouseleave);\n        }\n    }\n\n    /**\n     * Destroy the plugin (used by the Plugin API)\n     */\n    destroy() {\n        if (this.params.showTime) {\n            this.cursor.parentNode.removeChild(this.showTime);\n        }\n        this.cursor.parentNode.removeChild(this.cursor);\n        this.wrapper.removeEventListener('mousemove', this._onMousemove);\n        if (this.params.hideOnBlur) {\n            this.wrapper.removeEventListener('mouseenter', this._onMouseenter);\n            this.wrapper.removeEventListener('mouseleave', this._onMouseleave);\n        }\n    }\n\n    /**\n     * Update the cursor position\n     *\n     * @param {number} pos The x offset of the cursor in pixels\n     */\n    updateCursorPosition(pos) {\n        this.style(this.cursor, {\n            left: `${pos}px`\n        });\n        if (this.params.showTime) {\n            const duration = this.wavesurfer.getDuration();\n            const elementWidth =\n                this.wavesurfer.drawer.width /\n                this.wavesurfer.params.pixelRatio;\n            const scrollWidth = this.wavesurfer.drawer.getScrollX();\n\n            const scrollTime =\n                (duration / this.wavesurfer.drawer.width) * scrollWidth;\n\n            const timeValue =\n                Math.max(0, (pos / elementWidth) * duration) + scrollTime;\n            const formatValue = this.formatTime(timeValue);\n            this.style(this.showTime, {\n                left: `${pos}px`\n            });\n            this.displayTime.innerHTML = `${formatValue}`;\n        }\n    }\n\n    /**\n     * Show the cursor\n     */\n    showCursor() {\n        this.style(this.cursor, {\n            display: 'flex'\n        });\n        if (this.params.showTime) {\n            this.style(this.showTime, {\n                display: 'flex'\n            });\n        }\n    }\n\n    /**\n     * Hide the cursor\n     */\n    hideCursor() {\n        this.style(this.cursor, {\n            display: 'none'\n        });\n        if (this.params.showTime) {\n            this.style(this.showTime, {\n                display: 'none'\n            });\n        }\n    }\n\n    /** timestamp time calculation */\n    formatTime(cursorTime) {\n        return [cursorTime].map(time =>\n            [\n                Math.floor((time % 3600) / 60), // minutes\n                ('00' + Math.floor(time % 60)).slice(-2), // seconds\n                ('000' + Math.floor((time % 1) * 1000)).slice(-3) // miliseconds\n            ].join(':')\n        );\n    }\n}\n"],"sourceRoot":""}
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.cursor.min.js
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.cursor.min.js	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.cursor.min.js	(revision 33546)
@@ -0,0 +1,2 @@
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("cursor",[],t):"object"==typeof exports?exports.cursor=t():(e.WaveSurfer=e.WaveSurfer||{},e.WaveSurfer.cursor=t())}(window,(function(){return function(e){var t={};function r(i){if(t[i])return t[i].exports;var s=t[i]={i:i,l:!1,exports:{}};return e[i].call(s.exports,s,s.exports,r),s.l=!0,s.exports}return r.m=e,r.c=t,r.d=function(e,t,i){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(r.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var s in e)r.d(i,s,function(t){return e[t]}.bind(null,s));return i},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="localhost:8080/dist/plugin/",r(r.s=4)}({4:function(e,t,r){"use strict";function i(e,t){for(var r=0;r<t.length;r++){var i=t[r];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}function s(e,t,r){return t&&i(e.prototype,t),r&&i(e,r),e}Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o=function(){function e(t,r){var i=this;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.defaultParams={hideOnBlur:!0,width:"1px",color:"black",opacity:"0.25",style:"solid",zIndex:4,customStyle:{},customShowTimeStyle:{},showTime:!1},this._onMousemove=function(e){var t=i.wavesurfer.container.getBoundingClientRect();i.updateCursorPosition(e.clientX-t.left)},this._onMouseenter=function(){return i.showCursor()},this._onMouseleave=function(){return i.hideCursor()},this.wavesurfer=r,this.style=r.util.style,this.cursor=null,this.showTime=null,this.displayTime=null,this.params=r.util.extend({},this.defaultParams,t)}return s(e,null,[{key:"create",value:function(t){return{name:"cursor",deferInit:!(!t||!t.deferInit)&&t.deferInit,params:t,staticProps:{enableCursor:function(){console.warn("Deprecated enableCursor!"),this.initPlugins("cursor")}},instance:e}}}]),s(e,[{key:"init",value:function(){this.wrapper=this.wavesurfer.container,this.cursor=this.wrapper.appendChild(this.style(document.createElement("cursor"),this.wavesurfer.util.extend({position:"absolute",zIndex:this.params.zIndex,left:0,top:0,bottom:0,width:"0",display:"flex",borderRightStyle:this.params.style,borderRightWidth:this.params.width,borderRightColor:this.params.color,opacity:this.params.opacity,pointerEvents:"none"},this.params.customStyle))),this.params.showTime&&(this.showTime=this.wrapper.appendChild(this.style(document.createElement("showTitle"),this.wavesurfer.util.extend({position:"absolute",zIndex:this.params.zIndex,left:0,top:0,bottom:0,width:"auto",display:"flex",opacity:this.params.opacity,pointerEvents:"none",height:"100%"},this.params.customStyle))),this.displayTime=this.showTime.appendChild(this.style(document.createElement("div"),this.wavesurfer.util.extend({display:"inline",pointerEvents:"none",margin:"auto"},this.params.customShowTimeStyle)))),this.wrapper.addEventListener("mousemove",this._onMousemove),this.params.hideOnBlur&&(this.wrapper.addEventListener("mouseenter",this._onMouseenter),this.wrapper.addEventListener("mouseleave",this._onMouseleave))}},{key:"destroy",value:function(){this.params.showTime&&this.cursor.parentNode.removeChild(this.showTime),this.cursor.parentNode.removeChild(this.cursor),this.wrapper.removeEventListener("mousemove",this._onMousemove),this.params.hideOnBlur&&(this.wrapper.removeEventListener("mouseenter",this._onMouseenter),this.wrapper.removeEventListener("mouseleave",this._onMouseleave))}},{key:"updateCursorPosition",value:function(e){if(this.style(this.cursor,{left:"".concat(e,"px")}),this.params.showTime){var t=this.wavesurfer.getDuration(),r=this.wavesurfer.drawer.width/this.wavesurfer.params.pixelRatio,i=this.wavesurfer.drawer.getScrollX(),s=t/this.wavesurfer.drawer.width*i,o=Math.max(0,e/r*t)+s,n=this.formatTime(o);this.style(this.showTime,{left:"".concat(e,"px")}),this.displayTime.innerHTML="".concat(n)}}},{key:"showCursor",value:function(){this.style(this.cursor,{display:"flex"}),this.params.showTime&&this.style(this.showTime,{display:"flex"})}},{key:"hideCursor",value:function(){this.style(this.cursor,{display:"none"}),this.params.showTime&&this.style(this.showTime,{display:"none"})}},{key:"formatTime",value:function(e){return[e].map((function(e){return[Math.floor(e%3600/60),("00"+Math.floor(e%60)).slice(-2),("000"+Math.floor(e%1*1e3)).slice(-3)].join(":")}))}}]),e}();t.default=o,e.exports=t.default}})}));
+//# sourceMappingURL=wavesurfer.cursor.min.js.map
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.cursor.min.js.map
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.cursor.min.js.map	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.cursor.min.js.map	(revision 33546)
@@ -0,0 +1,1 @@
+{"version":3,"sources":["webpack://WaveSurfer.[name]/webpack/universalModuleDefinition","webpack://WaveSurfer.[name]/webpack/bootstrap","webpack://WaveSurfer.[name]/./src/plugin/cursor.js"],"names":["root","factory","exports","module","define","amd","window","installedModules","__webpack_require__","moduleId","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","CursorPlugin","params","ws","defaultParams","hideOnBlur","width","color","opacity","style","zIndex","customStyle","customShowTimeStyle","showTime","_onMousemove","e","bbox","wavesurfer","container","getBoundingClientRect","updateCursorPosition","clientX","left","_onMouseenter","showCursor","_onMouseleave","hideCursor","this","util","cursor","displayTime","extend","deferInit","staticProps","enableCursor","console","warn","initPlugins","instance","wrapper","appendChild","document","createElement","position","top","bottom","display","borderRightStyle","borderRightWidth","borderRightColor","pointerEvents","height","margin","addEventListener","parentNode","removeChild","removeEventListener","pos","duration","getDuration","elementWidth","drawer","pixelRatio","scrollWidth","getScrollX","scrollTime","timeValue","Math","max","formatValue","formatTime","innerHTML","cursorTime","map","time","floor","slice","join"],"mappings":"CAAA,SAA2CA,EAAMC,GAC1B,iBAAZC,SAA0C,iBAAXC,OACxCA,OAAOD,QAAUD,IACQ,mBAAXG,QAAyBA,OAAOC,IAC9CD,OAAO,SAAU,GAAIH,GACK,iBAAZC,QACdA,QAAgB,OAAID,KAEpBD,EAAiB,WAAIA,EAAiB,YAAK,GAAIA,EAAiB,WAAU,OAAIC,KARhF,CASGK,QAAQ,WACX,O,YCTE,IAAIC,EAAmB,GAGvB,SAASC,EAAoBC,GAG5B,GAAGF,EAAiBE,GACnB,OAAOF,EAAiBE,GAAUP,QAGnC,IAAIC,EAASI,EAAiBE,GAAY,CACzCC,EAAGD,EACHE,GAAG,EACHT,QAAS,IAUV,OANAU,EAAQH,GAAUI,KAAKV,EAAOD,QAASC,EAAQA,EAAOD,QAASM,GAG/DL,EAAOQ,GAAI,EAGJR,EAAOD,QA0Df,OArDAM,EAAoBM,EAAIF,EAGxBJ,EAAoBO,EAAIR,EAGxBC,EAAoBQ,EAAI,SAASd,EAASe,EAAMC,GAC3CV,EAAoBW,EAAEjB,EAASe,IAClCG,OAAOC,eAAenB,EAASe,EAAM,CAAEK,YAAY,EAAMC,IAAKL,KAKhEV,EAAoBgB,EAAI,SAAStB,GACX,oBAAXuB,QAA0BA,OAAOC,aAC1CN,OAAOC,eAAenB,EAASuB,OAAOC,YAAa,CAAEC,MAAO,WAE7DP,OAAOC,eAAenB,EAAS,aAAc,CAAEyB,OAAO,KAQvDnB,EAAoBoB,EAAI,SAASD,EAAOE,GAEvC,GADU,EAAPA,IAAUF,EAAQnB,EAAoBmB,IAC/B,EAAPE,EAAU,OAAOF,EACpB,GAAW,EAAPE,GAA8B,iBAAVF,GAAsBA,GAASA,EAAMG,WAAY,OAAOH,EAChF,IAAII,EAAKX,OAAOY,OAAO,MAGvB,GAFAxB,EAAoBgB,EAAEO,GACtBX,OAAOC,eAAeU,EAAI,UAAW,CAAET,YAAY,EAAMK,MAAOA,IACtD,EAAPE,GAA4B,iBAATF,EAAmB,IAAI,IAAIM,KAAON,EAAOnB,EAAoBQ,EAAEe,EAAIE,EAAK,SAASA,GAAO,OAAON,EAAMM,IAAQC,KAAK,KAAMD,IAC9I,OAAOF,GAIRvB,EAAoB2B,EAAI,SAAShC,GAChC,IAAIe,EAASf,GAAUA,EAAO2B,WAC7B,WAAwB,OAAO3B,EAAgB,SAC/C,WAA8B,OAAOA,GAEtC,OADAK,EAAoBQ,EAAEE,EAAQ,IAAKA,GAC5BA,GAIRV,EAAoBW,EAAI,SAASiB,EAAQC,GAAY,OAAOjB,OAAOkB,UAAUC,eAAe1B,KAAKuB,EAAQC,IAGzG7B,EAAoBgC,EAAI,8BAIjBhC,EAAoBA,EAAoBiC,EAAI,G,sUCxChCC,E,WA0DjB,WAAYC,EAAQC,GAAI,Y,4FAAA,cA7BxBC,cAAgB,CACZC,YAAY,EACZC,MAAO,MACPC,MAAO,QACPC,QAAS,OACTC,MAAO,QACPC,OAAQ,EACRC,YAAa,GACbC,oBAAqB,GACrBC,UAAU,GAoBU,KAhBxBC,aAAe,SAAAC,GACX,IAAMC,EAAO,EAAKC,WAAWC,UAAUC,wBACvC,EAAKC,qBAAqBL,EAAEM,QAAUL,EAAKM,OAcvB,KAXxBC,cAAgB,kBAAM,EAAKC,cAWH,KATxBC,cAAgB,kBAAM,EAAKC,cAWvBC,KAAKV,WAAad,EAElBwB,KAAKlB,MAAQN,EAAGyB,KAAKnB,MAMrBkB,KAAKE,OAAS,KAMdF,KAAKd,SAAW,KAMhBc,KAAKG,YAAc,KAEnBH,KAAKzB,OAASC,EAAGyB,KAAKG,OAAO,GAAIJ,KAAKvB,cAAeF,G,8CAvE3CA,GACV,MAAO,CACH1B,KAAM,SACNwD,aAAW9B,IAAUA,EAAO8B,YAAY9B,EAAO8B,UAC/C9B,OAAQA,EACR+B,YAAa,CACTC,aADS,WAELC,QAAQC,KAAK,4BACbT,KAAKU,YAAY,YAGzBC,SAAUrC,O,kCAmEd0B,KAAKY,QAAUZ,KAAKV,WAAWC,UAC/BS,KAAKE,OAASF,KAAKY,QAAQC,YACvBb,KAAKlB,MACDgC,SAASC,cAAc,UACvBf,KAAKV,WAAWW,KAAKG,OACjB,CACIY,SAAU,WACVjC,OAAQiB,KAAKzB,OAAOQ,OACpBY,KAAM,EACNsB,IAAK,EACLC,OAAQ,EACRvC,MAAO,IACPwC,QAAS,OACTC,iBAAkBpB,KAAKzB,OAAOO,MAC9BuC,iBAAkBrB,KAAKzB,OAAOI,MAC9B2C,iBAAkBtB,KAAKzB,OAAOK,MAC9BC,QAASmB,KAAKzB,OAAOM,QACrB0C,cAAe,QAEnBvB,KAAKzB,OAAOS,eAIpBgB,KAAKzB,OAAOW,WACZc,KAAKd,SAAWc,KAAKY,QAAQC,YACzBb,KAAKlB,MACDgC,SAASC,cAAc,aACvBf,KAAKV,WAAWW,KAAKG,OACjB,CACIY,SAAU,WACVjC,OAAQiB,KAAKzB,OAAOQ,OACpBY,KAAM,EACNsB,IAAK,EACLC,OAAQ,EACRvC,MAAO,OACPwC,QAAS,OACTtC,QAASmB,KAAKzB,OAAOM,QACrB0C,cAAe,OACfC,OAAQ,QAEZxB,KAAKzB,OAAOS,eAIxBgB,KAAKG,YAAcH,KAAKd,SAAS2B,YAC7Bb,KAAKlB,MACDgC,SAASC,cAAc,OACvBf,KAAKV,WAAWW,KAAKG,OACjB,CACIe,QAAS,SACTI,cAAe,OACfE,OAAQ,QAEZzB,KAAKzB,OAAOU,wBAM5Be,KAAKY,QAAQc,iBAAiB,YAAa1B,KAAKb,cAC5Ca,KAAKzB,OAAOG,aACZsB,KAAKY,QAAQc,iBAAiB,aAAc1B,KAAKJ,eACjDI,KAAKY,QAAQc,iBAAiB,aAAc1B,KAAKF,kB,gCAQjDE,KAAKzB,OAAOW,UACZc,KAAKE,OAAOyB,WAAWC,YAAY5B,KAAKd,UAE5Cc,KAAKE,OAAOyB,WAAWC,YAAY5B,KAAKE,QACxCF,KAAKY,QAAQiB,oBAAoB,YAAa7B,KAAKb,cAC/Ca,KAAKzB,OAAOG,aACZsB,KAAKY,QAAQiB,oBAAoB,aAAc7B,KAAKJ,eACpDI,KAAKY,QAAQiB,oBAAoB,aAAc7B,KAAKF,kB,2CASvCgC,GAIjB,GAHA9B,KAAKlB,MAAMkB,KAAKE,OAAQ,CACpBP,KAAM,GAAF,OAAKmC,EAAL,QAEJ9B,KAAKzB,OAAOW,SAAU,CACtB,IAAM6C,EAAW/B,KAAKV,WAAW0C,cAC3BC,EACFjC,KAAKV,WAAW4C,OAAOvD,MACvBqB,KAAKV,WAAWf,OAAO4D,WACrBC,EAAcpC,KAAKV,WAAW4C,OAAOG,aAErCC,EACDP,EAAW/B,KAAKV,WAAW4C,OAAOvD,MAASyD,EAE1CG,EACFC,KAAKC,IAAI,EAAIX,EAAMG,EAAgBF,GAAYO,EAC7CI,EAAc1C,KAAK2C,WAAWJ,GACpCvC,KAAKlB,MAAMkB,KAAKd,SAAU,CACtBS,KAAM,GAAF,OAAKmC,EAAL,QAER9B,KAAKG,YAAYyC,UAAjB,UAAgCF,M,mCAQpC1C,KAAKlB,MAAMkB,KAAKE,OAAQ,CACpBiB,QAAS,SAETnB,KAAKzB,OAAOW,UACZc,KAAKlB,MAAMkB,KAAKd,SAAU,CACtBiC,QAAS,W,mCASjBnB,KAAKlB,MAAMkB,KAAKE,OAAQ,CACpBiB,QAAS,SAETnB,KAAKzB,OAAOW,UACZc,KAAKlB,MAAMkB,KAAKd,SAAU,CACtBiC,QAAS,W,iCAMV0B,GACP,MAAO,CAACA,GAAYC,KAAI,SAAAC,GAAI,MACxB,CACIP,KAAKQ,MAAOD,EAAO,KAAQ,KAC1B,KAAOP,KAAKQ,MAAMD,EAAO,KAAKE,OAAO,IACrC,MAAQT,KAAKQ,MAAOD,EAAO,EAAK,MAAOE,OAAO,IACjDC,KAAK,Y","file":"wavesurfer.cursor.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"cursor\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"cursor\"] = factory();\n\telse\n\t\troot[\"WaveSurfer\"] = root[\"WaveSurfer\"] || {}, root[\"WaveSurfer\"][\"cursor\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"localhost:8080/dist/plugin/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 4);\n","/**\n * @typedef {Object} CursorPluginParams\n * @property {?boolean} deferInit Set to true to stop auto init in `addPlugin()`\n * @property {boolean} hideOnBlur=true Hide the cursor when the mouse leaves the\n * waveform\n * @property {string} width='1px' The width of the cursor\n * @property {string} color='black' The color of the cursor\n * @property {string} opacity='0.25' The opacity of the cursor\n * @property {string} style='solid' The border style of the cursor\n * @property {number} zIndex=3 The z-index of the cursor element\n * @property {object} customStyle An object with custom styles which are applied\n * to the cursor element\n * @property {boolean} showTime=false Show the time on the cursor.\n * @property {object} customShowTimeStyle An object with custom styles which are\n * applied to the cursor time element.\n */\n\n/**\n * Displays a thin line at the position of the cursor on the waveform.\n *\n * @implements {PluginClass}\n * @extends {Observer}\n * @example\n * // es6\n * import CursorPlugin from 'wavesurfer.cursor.js';\n *\n * // commonjs\n * var CursorPlugin = require('wavesurfer.cursor.js');\n *\n * // if you are using <script> tags\n * var CursorPlugin = window.WaveSurfer.cursor;\n *\n * // ... initialising wavesurfer with the plugin\n * var wavesurfer = WaveSurfer.create({\n *   // wavesurfer options ...\n *   plugins: [\n *     CursorPlugin.create({\n *       // plugin options ...\n *     })\n *   ]\n * });\n */\nexport default class CursorPlugin {\n    /**\n     * Cursor plugin definition factory\n     *\n     * This function must be used to create a plugin definition which can be\n     * used by wavesurfer to correctly instantiate the plugin.\n     *\n     * @param  {CursorPluginParams} params parameters use to initialise the\n     * plugin\n     * @return {PluginDefinition} an object representing the plugin\n     */\n    static create(params) {\n        return {\n            name: 'cursor',\n            deferInit: params && params.deferInit ? params.deferInit : false,\n            params: params,\n            staticProps: {\n                enableCursor() {\n                    console.warn('Deprecated enableCursor!');\n                    this.initPlugins('cursor');\n                }\n            },\n            instance: CursorPlugin\n        };\n    }\n\n    /**\n     * @type {CursorPluginParams}\n     */\n    defaultParams = {\n        hideOnBlur: true,\n        width: '1px',\n        color: 'black',\n        opacity: '0.25',\n        style: 'solid',\n        zIndex: 4,\n        customStyle: {},\n        customShowTimeStyle: {},\n        showTime: false\n    };\n\n    /** @private */\n    _onMousemove = e => {\n        const bbox = this.wavesurfer.container.getBoundingClientRect();\n        this.updateCursorPosition(e.clientX - bbox.left);\n    };\n    /** @private */\n    _onMouseenter = () => this.showCursor();\n    /** @private */\n    _onMouseleave = () => this.hideCursor();\n\n    /**\n     * Construct the plugin class. You probably want to use CursorPlugin.create\n     * instead.\n     *\n     * @param {CursorPluginParams} params\n     * @param {object} ws\n     */\n    constructor(params, ws) {\n        /** @private */\n        this.wavesurfer = ws;\n        /** @private */\n        this.style = ws.util.style;\n        /**\n         * The cursor HTML element\n         *\n         * @type {?HTMLElement}\n         */\n        this.cursor = null;\n        /**\n         * displays the time next to the cursor\n         *\n         * @type {Boolean}\n         */\n        this.showTime = null;\n        /**\n         * The html container that will display the time\n         *\n         * @type {?HTMLElement}\n         */\n        this.displayTime = null;\n        /** @private */\n        this.params = ws.util.extend({}, this.defaultParams, params);\n    }\n\n    /**\n     * Initialise the plugin (used by the Plugin API)\n     */\n    init() {\n        this.wrapper = this.wavesurfer.container;\n        this.cursor = this.wrapper.appendChild(\n            this.style(\n                document.createElement('cursor'),\n                this.wavesurfer.util.extend(\n                    {\n                        position: 'absolute',\n                        zIndex: this.params.zIndex,\n                        left: 0,\n                        top: 0,\n                        bottom: 0,\n                        width: '0',\n                        display: 'flex',\n                        borderRightStyle: this.params.style,\n                        borderRightWidth: this.params.width,\n                        borderRightColor: this.params.color,\n                        opacity: this.params.opacity,\n                        pointerEvents: 'none'\n                    },\n                    this.params.customStyle\n                )\n            )\n        );\n        if (this.params.showTime) {\n            this.showTime = this.wrapper.appendChild(\n                this.style(\n                    document.createElement('showTitle'),\n                    this.wavesurfer.util.extend(\n                        {\n                            position: 'absolute',\n                            zIndex: this.params.zIndex,\n                            left: 0,\n                            top: 0,\n                            bottom: 0,\n                            width: 'auto',\n                            display: 'flex',\n                            opacity: this.params.opacity,\n                            pointerEvents: 'none',\n                            height: '100%'\n                        },\n                        this.params.customStyle\n                    )\n                )\n            );\n            this.displayTime = this.showTime.appendChild(\n                this.style(\n                    document.createElement('div'),\n                    this.wavesurfer.util.extend(\n                        {\n                            display: 'inline',\n                            pointerEvents: 'none',\n                            margin: 'auto'\n                        },\n                        this.params.customShowTimeStyle\n                    )\n                )\n            );\n        }\n\n        this.wrapper.addEventListener('mousemove', this._onMousemove);\n        if (this.params.hideOnBlur) {\n            this.wrapper.addEventListener('mouseenter', this._onMouseenter);\n            this.wrapper.addEventListener('mouseleave', this._onMouseleave);\n        }\n    }\n\n    /**\n     * Destroy the plugin (used by the Plugin API)\n     */\n    destroy() {\n        if (this.params.showTime) {\n            this.cursor.parentNode.removeChild(this.showTime);\n        }\n        this.cursor.parentNode.removeChild(this.cursor);\n        this.wrapper.removeEventListener('mousemove', this._onMousemove);\n        if (this.params.hideOnBlur) {\n            this.wrapper.removeEventListener('mouseenter', this._onMouseenter);\n            this.wrapper.removeEventListener('mouseleave', this._onMouseleave);\n        }\n    }\n\n    /**\n     * Update the cursor position\n     *\n     * @param {number} pos The x offset of the cursor in pixels\n     */\n    updateCursorPosition(pos) {\n        this.style(this.cursor, {\n            left: `${pos}px`\n        });\n        if (this.params.showTime) {\n            const duration = this.wavesurfer.getDuration();\n            const elementWidth =\n                this.wavesurfer.drawer.width /\n                this.wavesurfer.params.pixelRatio;\n            const scrollWidth = this.wavesurfer.drawer.getScrollX();\n\n            const scrollTime =\n                (duration / this.wavesurfer.drawer.width) * scrollWidth;\n\n            const timeValue =\n                Math.max(0, (pos / elementWidth) * duration) + scrollTime;\n            const formatValue = this.formatTime(timeValue);\n            this.style(this.showTime, {\n                left: `${pos}px`\n            });\n            this.displayTime.innerHTML = `${formatValue}`;\n        }\n    }\n\n    /**\n     * Show the cursor\n     */\n    showCursor() {\n        this.style(this.cursor, {\n            display: 'flex'\n        });\n        if (this.params.showTime) {\n            this.style(this.showTime, {\n                display: 'flex'\n            });\n        }\n    }\n\n    /**\n     * Hide the cursor\n     */\n    hideCursor() {\n        this.style(this.cursor, {\n            display: 'none'\n        });\n        if (this.params.showTime) {\n            this.style(this.showTime, {\n                display: 'none'\n            });\n        }\n    }\n\n    /** timestamp time calculation */\n    formatTime(cursorTime) {\n        return [cursorTime].map(time =>\n            [\n                Math.floor((time % 3600) / 60), // minutes\n                ('00' + Math.floor(time % 60)).slice(-2), // seconds\n                ('000' + Math.floor((time % 1) * 1000)).slice(-3) // miliseconds\n            ].join(':')\n        );\n    }\n}\n"],"sourceRoot":""}
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.elan.js
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.elan.js	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.elan.js	(revision 33546)
@@ -0,0 +1,456 @@
+/*!
+ * wavesurfer.js elan plugin 2.2.1 (2019-09-30)
+ * https://github.com/katspaugh/wavesurfer.js
+ * @license BSD-3-Clause
+ */
+(function webpackUniversalModuleDefinition(root, factory) {
+	if(typeof exports === 'object' && typeof module === 'object')
+		module.exports = factory();
+	else if(typeof define === 'function' && define.amd)
+		define("elan", [], factory);
+	else if(typeof exports === 'object')
+		exports["elan"] = factory();
+	else
+		root["WaveSurfer"] = root["WaveSurfer"] || {}, root["WaveSurfer"]["elan"] = factory();
+})(window, function() {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+/******/
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId]) {
+/******/ 			return installedModules[moduleId].exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			i: moduleId,
+/******/ 			l: false,
+/******/ 			exports: {}
+/******/ 		};
+/******/
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ 		// Flag the module as loaded
+/******/ 		module.l = true;
+/******/
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/
+/******/
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+/******/
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+/******/
+/******/ 	// define getter function for harmony exports
+/******/ 	__webpack_require__.d = function(exports, name, getter) {
+/******/ 		if(!__webpack_require__.o(exports, name)) {
+/******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
+/******/ 		}
+/******/ 	};
+/******/
+/******/ 	// define __esModule on exports
+/******/ 	__webpack_require__.r = function(exports) {
+/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ 		}
+/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
+/******/ 	};
+/******/
+/******/ 	// create a fake namespace object
+/******/ 	// mode & 1: value is a module id, require it
+/******/ 	// mode & 2: merge all properties of value into the ns
+/******/ 	// mode & 4: return value when already ns object
+/******/ 	// mode & 8|1: behave like require
+/******/ 	__webpack_require__.t = function(value, mode) {
+/******/ 		if(mode & 1) value = __webpack_require__(value);
+/******/ 		if(mode & 8) return value;
+/******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
+/******/ 		var ns = Object.create(null);
+/******/ 		__webpack_require__.r(ns);
+/******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
+/******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
+/******/ 		return ns;
+/******/ 	};
+/******/
+/******/ 	// getDefaultExport function for compatibility with non-harmony modules
+/******/ 	__webpack_require__.n = function(module) {
+/******/ 		var getter = module && module.__esModule ?
+/******/ 			function getDefault() { return module['default']; } :
+/******/ 			function getModuleExports() { return module; };
+/******/ 		__webpack_require__.d(getter, 'a', getter);
+/******/ 		return getter;
+/******/ 	};
+/******/
+/******/ 	// Object.prototype.hasOwnProperty.call
+/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "localhost:8080/dist/plugin/";
+/******/
+/******/
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(__webpack_require__.s = "./src/plugin/elan.js");
+/******/ })
+/************************************************************************/
+/******/ ({
+
+/***/ "./src/plugin/elan.js":
+/*!****************************!*\
+  !*** ./src/plugin/elan.js ***!
+  \****************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+/**
+ * @typedef {Object} ElanPluginParams
+ * @property {string|HTMLElement} container CSS selector or HTML element where
+ * the ELAN information should be rendered.
+ * @property {string} url The location of ELAN XML data
+ * @property {?boolean} deferInit Set to true to manually call
+ * @property {?Object} tiers If set only shows the data tiers with the `TIER_ID`
+ * in this map.
+ */
+
+/**
+ * Downloads and renders ELAN audio transcription documents alongside the
+ * waveform.
+ *
+ * @implements {PluginClass}
+ * @extends {Observer}
+ * @example
+ * // es6
+ * import ElanPlugin from 'wavesurfer.elan.js';
+ *
+ * // commonjs
+ * var ElanPlugin = require('wavesurfer.elan.js');
+ *
+ * // if you are using <script> tags
+ * var ElanPlugin = window.WaveSurfer.elan;
+ *
+ * // ... initialising wavesurfer with the plugin
+ * var wavesurfer = WaveSurfer.create({
+ *   // wavesurfer options ...
+ *   plugins: [
+ *     ElanPlugin.create({
+ *       // plugin options ...
+ *     })
+ *   ]
+ * });
+ */
+var ElanPlugin =
+/*#__PURE__*/
+function () {
+  _createClass(ElanPlugin, null, [{
+    key: "create",
+
+    /**
+     * Elan plugin definition factory
+     *
+     * This function must be used to create a plugin definition which can be
+     * used by wavesurfer to correctly instantiate the plugin.
+     *
+     * @param  {ElanPluginParams} params parameters use to initialise the plugin
+     * @return {PluginDefinition} an object representing the plugin
+     */
+    value: function create(params) {
+      return {
+        name: 'elan',
+        deferInit: params && params.deferInit ? params.deferInit : false,
+        params: params,
+        instance: ElanPlugin
+      };
+    }
+  }]);
+
+  function ElanPlugin(params, ws) {
+    _classCallCheck(this, ElanPlugin);
+
+    this.Types = {
+      ALIGNABLE_ANNOTATION: 'ALIGNABLE_ANNOTATION',
+      REF_ANNOTATION: 'REF_ANNOTATION'
+    };
+    this.data = null;
+    this.params = params;
+    this.container = 'string' == typeof params.container ? document.querySelector(params.container) : params.container;
+
+    if (!this.container) {
+      throw Error('No container for ELAN');
+    }
+  }
+
+  _createClass(ElanPlugin, [{
+    key: "init",
+    value: function init() {
+      this.bindClick();
+
+      if (this.params.url) {
+        this.load(this.params.url);
+      }
+    }
+  }, {
+    key: "destroy",
+    value: function destroy() {
+      this.container.removeEventListener('click', this._onClick);
+      this.container.removeChild(this.table);
+    }
+  }, {
+    key: "load",
+    value: function load(url) {
+      var _this = this;
+
+      this.loadXML(url, function (xml) {
+        _this.data = _this.parseElan(xml);
+
+        _this.render();
+
+        _this.fireEvent('ready', _this.data);
+      });
+    }
+  }, {
+    key: "loadXML",
+    value: function loadXML(url, callback) {
+      var xhr = new XMLHttpRequest();
+      xhr.open('GET', url, true);
+      xhr.responseType = 'document';
+      xhr.send();
+      xhr.addEventListener('load', function (e) {
+        callback && callback(e.target.responseXML);
+      });
+    }
+  }, {
+    key: "parseElan",
+    value: function parseElan(xml) {
+      var _this2 = this;
+
+      var _forEach = Array.prototype.forEach;
+      var _map = Array.prototype.map;
+      var data = {
+        media: {},
+        timeOrder: {},
+        tiers: [],
+        annotations: {},
+        alignableAnnotations: []
+      };
+      var header = xml.querySelector('HEADER');
+      var inMilliseconds = header.getAttribute('TIME_UNITS') == 'milliseconds';
+      var media = header.querySelector('MEDIA_DESCRIPTOR');
+      data.media.url = media.getAttribute('MEDIA_URL');
+      data.media.type = media.getAttribute('MIME_TYPE');
+      var timeSlots = xml.querySelectorAll('TIME_ORDER TIME_SLOT');
+      var timeOrder = {};
+
+      _forEach.call(timeSlots, function (slot) {
+        var value = parseFloat(slot.getAttribute('TIME_VALUE')); // If in milliseconds, convert to seconds with rounding
+
+        if (inMilliseconds) {
+          value = Math.round(value * 1e2) / 1e5;
+        }
+
+        timeOrder[slot.getAttribute('TIME_SLOT_ID')] = value;
+      });
+
+      data.tiers = _map.call(xml.querySelectorAll('TIER'), function (tier) {
+        return {
+          id: tier.getAttribute('TIER_ID'),
+          linguisticTypeRef: tier.getAttribute('LINGUISTIC_TYPE_REF'),
+          defaultLocale: tier.getAttribute('DEFAULT_LOCALE'),
+          annotations: _map.call(tier.querySelectorAll('REF_ANNOTATION, ALIGNABLE_ANNOTATION'), function (node) {
+            var annot = {
+              type: node.nodeName,
+              id: node.getAttribute('ANNOTATION_ID'),
+              ref: node.getAttribute('ANNOTATION_REF'),
+              value: node.querySelector('ANNOTATION_VALUE').textContent.trim()
+            };
+
+            if (_this2.Types.ALIGNABLE_ANNOTATION == annot.type) {
+              // Add start & end to alignable annotation
+              annot.start = timeOrder[node.getAttribute('TIME_SLOT_REF1')];
+              annot.end = timeOrder[node.getAttribute('TIME_SLOT_REF2')]; // Add to the list of alignable annotations
+
+              data.alignableAnnotations.push(annot);
+            } // Additionally, put into the flat map of all annotations
+
+
+            data.annotations[annot.id] = annot;
+            return annot;
+          })
+        };
+      }); // Create JavaScript references between annotations
+
+      data.tiers.forEach(function (tier) {
+        tier.annotations.forEach(function (annot) {
+          if (null != annot.ref) {
+            annot.reference = data.annotations[annot.ref];
+          }
+        });
+      }); // Sort alignable annotations by start & end
+
+      data.alignableAnnotations.sort(function (a, b) {
+        var d = a.start - b.start;
+
+        if (d == 0) {
+          d = b.end - a.end;
+        }
+
+        return d;
+      });
+      data.length = data.alignableAnnotations.length;
+      return data;
+    }
+  }, {
+    key: "render",
+    value: function render() {
+      var _this3 = this;
+
+      // apply tiers filter
+      var tiers = this.data.tiers;
+
+      if (this.params.tiers) {
+        tiers = tiers.filter(function (tier) {
+          return tier.id in _this3.params.tiers;
+        });
+      } // denormalize references to alignable annotations
+
+
+      var backRefs = {};
+      var indeces = {};
+      tiers.forEach(function (tier, index) {
+        tier.annotations.forEach(function (annot) {
+          if (annot.reference && annot.reference.type == _this3.Types.ALIGNABLE_ANNOTATION) {
+            if (!(annot.reference.id in backRefs)) {
+              backRefs[annot.ref] = {};
+            }
+
+            backRefs[annot.ref][index] = annot;
+            indeces[index] = true;
+          }
+        });
+      });
+      indeces = Object.keys(indeces).sort();
+      this.renderedAlignable = this.data.alignableAnnotations.filter(function (alignable) {
+        return backRefs[alignable.id];
+      }); // table
+
+      var table = this.table = document.createElement('table');
+      table.className = 'wavesurfer-annotations'; // head
+
+      var thead = document.createElement('thead');
+      var headRow = document.createElement('tr');
+      thead.appendChild(headRow);
+      table.appendChild(thead);
+      var th = document.createElement('th');
+      th.textContent = 'Time';
+      th.className = 'wavesurfer-time';
+      headRow.appendChild(th);
+      indeces.forEach(function (index) {
+        var tier = tiers[index];
+        var th = document.createElement('th');
+        th.className = 'wavesurfer-tier-' + tier.id;
+        th.textContent = tier.id;
+        th.style.width = _this3.params.tiers[tier.id];
+        headRow.appendChild(th);
+      }); // body
+
+      var tbody = document.createElement('tbody');
+      table.appendChild(tbody);
+      this.renderedAlignable.forEach(function (alignable) {
+        var row = document.createElement('tr');
+        row.id = 'wavesurfer-alignable-' + alignable.id;
+        tbody.appendChild(row);
+        var td = document.createElement('td');
+        td.className = 'wavesurfer-time';
+        td.textContent = alignable.start.toFixed(1) + 'â' + alignable.end.toFixed(1);
+        row.appendChild(td);
+        var backRef = backRefs[alignable.id];
+        indeces.forEach(function (index) {
+          var tier = tiers[index];
+          var td = document.createElement('td');
+          var annotation = backRef[index];
+
+          if (annotation) {
+            td.id = 'wavesurfer-annotation-' + annotation.id;
+            td.dataset.ref = alignable.id;
+            td.dataset.start = alignable.start;
+            td.dataset.end = alignable.end;
+            td.textContent = annotation.value;
+          }
+
+          td.className = 'wavesurfer-tier-' + tier.id;
+          row.appendChild(td);
+        });
+      });
+      this.container.innerHTML = '';
+      this.container.appendChild(table);
+    }
+  }, {
+    key: "bindClick",
+    value: function bindClick() {
+      var _this4 = this;
+
+      this._onClick = function (e) {
+        var ref = e.target.dataset.ref;
+
+        if (null != ref) {
+          var annot = _this4.data.annotations[ref];
+
+          if (annot) {
+            _this4.fireEvent('select', annot.start, annot.end);
+          }
+        }
+      };
+
+      this.container.addEventListener('click', this._onClick);
+    }
+  }, {
+    key: "getRenderedAnnotation",
+    value: function getRenderedAnnotation(time) {
+      var result;
+      this.renderedAlignable.some(function (annotation) {
+        if (annotation.start <= time && annotation.end >= time) {
+          result = annotation;
+          return true;
+        }
+
+        return false;
+      });
+      return result;
+    }
+  }, {
+    key: "getAnnotationNode",
+    value: function getAnnotationNode(annotation) {
+      return document.getElementById('wavesurfer-alignable-' + annotation.id);
+    }
+  }]);
+
+  return ElanPlugin;
+}();
+
+exports.default = ElanPlugin;
+module.exports = exports.default;
+
+/***/ })
+
+/******/ });
+});
+//# sourceMappingURL=wavesurfer.elan.js.map
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.elan.js.map
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.elan.js.map	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.elan.js.map	(revision 33546)
@@ -0,0 +1,1 @@
+{"version":3,"sources":["webpack://WaveSurfer.[name]/webpack/universalModuleDefinition","webpack://WaveSurfer.[name]/webpack/bootstrap","webpack://WaveSurfer.[name]/./src/plugin/elan.js"],"names":["ElanPlugin","params","name","deferInit","instance","ws","Types","ALIGNABLE_ANNOTATION","REF_ANNOTATION","data","container","document","querySelector","Error","bindClick","url","load","removeEventListener","_onClick","removeChild","table","loadXML","xml","parseElan","render","fireEvent","callback","xhr","XMLHttpRequest","open","responseType","send","addEventListener","e","target","responseXML","_forEach","Array","prototype","forEach","_map","map","media","timeOrder","tiers","annotations","alignableAnnotations","header","inMilliseconds","getAttribute","type","timeSlots","querySelectorAll","call","slot","value","parseFloat","Math","round","tier","id","linguisticTypeRef","defaultLocale","node","annot","nodeName","ref","textContent","trim","start","end","push","reference","sort","a","b","d","length","filter","backRefs","indeces","index","Object","keys","renderedAlignable","alignable","createElement","className","thead","headRow","appendChild","th","style","width","tbody","row","td","toFixed","backRef","annotation","dataset","innerHTML","time","result","some","getElementById"],"mappings":"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","file":"wavesurfer.elan.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"elan\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"elan\"] = factory();\n\telse\n\t\troot[\"WaveSurfer\"] = root[\"WaveSurfer\"] || {}, root[\"WaveSurfer\"][\"elan\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"localhost:8080/dist/plugin/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/plugin/elan.js\");\n","/**\n * @typedef {Object} ElanPluginParams\n * @property {string|HTMLElement} container CSS selector or HTML element where\n * the ELAN information should be rendered.\n * @property {string} url The location of ELAN XML data\n * @property {?boolean} deferInit Set to true to manually call\n * @property {?Object} tiers If set only shows the data tiers with the `TIER_ID`\n * in this map.\n */\n\n/**\n * Downloads and renders ELAN audio transcription documents alongside the\n * waveform.\n *\n * @implements {PluginClass}\n * @extends {Observer}\n * @example\n * // es6\n * import ElanPlugin from 'wavesurfer.elan.js';\n *\n * // commonjs\n * var ElanPlugin = require('wavesurfer.elan.js');\n *\n * // if you are using <script> tags\n * var ElanPlugin = window.WaveSurfer.elan;\n *\n * // ... initialising wavesurfer with the plugin\n * var wavesurfer = WaveSurfer.create({\n *   // wavesurfer options ...\n *   plugins: [\n *     ElanPlugin.create({\n *       // plugin options ...\n *     })\n *   ]\n * });\n */\nexport default class ElanPlugin {\n    /**\n     * Elan plugin definition factory\n     *\n     * This function must be used to create a plugin definition which can be\n     * used by wavesurfer to correctly instantiate the plugin.\n     *\n     * @param  {ElanPluginParams} params parameters use to initialise the plugin\n     * @return {PluginDefinition} an object representing the plugin\n     */\n    static create(params) {\n        return {\n            name: 'elan',\n            deferInit: params && params.deferInit ? params.deferInit : false,\n            params: params,\n            instance: ElanPlugin\n        };\n    }\n\n    Types = {\n        ALIGNABLE_ANNOTATION: 'ALIGNABLE_ANNOTATION',\n        REF_ANNOTATION: 'REF_ANNOTATION'\n    };\n\n    constructor(params, ws) {\n        this.data = null;\n        this.params = params;\n        this.container =\n            'string' == typeof params.container\n                ? document.querySelector(params.container)\n                : params.container;\n\n        if (!this.container) {\n            throw Error('No container for ELAN');\n        }\n    }\n\n    init() {\n        this.bindClick();\n\n        if (this.params.url) {\n            this.load(this.params.url);\n        }\n    }\n\n    destroy() {\n        this.container.removeEventListener('click', this._onClick);\n        this.container.removeChild(this.table);\n    }\n\n    load(url) {\n        this.loadXML(url, xml => {\n            this.data = this.parseElan(xml);\n            this.render();\n            this.fireEvent('ready', this.data);\n        });\n    }\n\n    loadXML(url, callback) {\n        const xhr = new XMLHttpRequest();\n        xhr.open('GET', url, true);\n        xhr.responseType = 'document';\n        xhr.send();\n        xhr.addEventListener('load', e => {\n            callback && callback(e.target.responseXML);\n        });\n    }\n\n    parseElan(xml) {\n        const _forEach = Array.prototype.forEach;\n        const _map = Array.prototype.map;\n\n        const data = {\n            media: {},\n            timeOrder: {},\n            tiers: [],\n            annotations: {},\n            alignableAnnotations: []\n        };\n\n        const header = xml.querySelector('HEADER');\n        const inMilliseconds =\n            header.getAttribute('TIME_UNITS') == 'milliseconds';\n        const media = header.querySelector('MEDIA_DESCRIPTOR');\n        data.media.url = media.getAttribute('MEDIA_URL');\n        data.media.type = media.getAttribute('MIME_TYPE');\n\n        const timeSlots = xml.querySelectorAll('TIME_ORDER TIME_SLOT');\n        const timeOrder = {};\n        _forEach.call(timeSlots, slot => {\n            let value = parseFloat(slot.getAttribute('TIME_VALUE'));\n            // If in milliseconds, convert to seconds with rounding\n            if (inMilliseconds) {\n                value = Math.round(value * 1e2) / 1e5;\n            }\n            timeOrder[slot.getAttribute('TIME_SLOT_ID')] = value;\n        });\n\n        data.tiers = _map.call(xml.querySelectorAll('TIER'), tier => ({\n            id: tier.getAttribute('TIER_ID'),\n            linguisticTypeRef: tier.getAttribute('LINGUISTIC_TYPE_REF'),\n            defaultLocale: tier.getAttribute('DEFAULT_LOCALE'),\n            annotations: _map.call(\n                tier.querySelectorAll('REF_ANNOTATION, ALIGNABLE_ANNOTATION'),\n                node => {\n                    const annot = {\n                        type: node.nodeName,\n                        id: node.getAttribute('ANNOTATION_ID'),\n                        ref: node.getAttribute('ANNOTATION_REF'),\n                        value: node\n                            .querySelector('ANNOTATION_VALUE')\n                            .textContent.trim()\n                    };\n\n                    if (this.Types.ALIGNABLE_ANNOTATION == annot.type) {\n                        // Add start & end to alignable annotation\n                        annot.start =\n                            timeOrder[node.getAttribute('TIME_SLOT_REF1')];\n                        annot.end =\n                            timeOrder[node.getAttribute('TIME_SLOT_REF2')];\n                        // Add to the list of alignable annotations\n                        data.alignableAnnotations.push(annot);\n                    }\n\n                    // Additionally, put into the flat map of all annotations\n                    data.annotations[annot.id] = annot;\n\n                    return annot;\n                }\n            )\n        }));\n\n        // Create JavaScript references between annotations\n        data.tiers.forEach(tier => {\n            tier.annotations.forEach(annot => {\n                if (null != annot.ref) {\n                    annot.reference = data.annotations[annot.ref];\n                }\n            });\n        });\n\n        // Sort alignable annotations by start & end\n        data.alignableAnnotations.sort((a, b) => {\n            let d = a.start - b.start;\n            if (d == 0) {\n                d = b.end - a.end;\n            }\n            return d;\n        });\n\n        data.length = data.alignableAnnotations.length;\n\n        return data;\n    }\n\n    render() {\n        // apply tiers filter\n        let tiers = this.data.tiers;\n        if (this.params.tiers) {\n            tiers = tiers.filter(tier => tier.id in this.params.tiers);\n        }\n\n        // denormalize references to alignable annotations\n        const backRefs = {};\n        let indeces = {};\n        tiers.forEach((tier, index) => {\n            tier.annotations.forEach(annot => {\n                if (\n                    annot.reference &&\n                    annot.reference.type == this.Types.ALIGNABLE_ANNOTATION\n                ) {\n                    if (!(annot.reference.id in backRefs)) {\n                        backRefs[annot.ref] = {};\n                    }\n                    backRefs[annot.ref][index] = annot;\n                    indeces[index] = true;\n                }\n            });\n        });\n        indeces = Object.keys(indeces).sort();\n\n        this.renderedAlignable = this.data.alignableAnnotations.filter(\n            alignable => backRefs[alignable.id]\n        );\n\n        // table\n        const table = (this.table = document.createElement('table'));\n        table.className = 'wavesurfer-annotations';\n\n        // head\n        const thead = document.createElement('thead');\n        const headRow = document.createElement('tr');\n        thead.appendChild(headRow);\n        table.appendChild(thead);\n        const th = document.createElement('th');\n        th.textContent = 'Time';\n        th.className = 'wavesurfer-time';\n        headRow.appendChild(th);\n        indeces.forEach(index => {\n            const tier = tiers[index];\n            const th = document.createElement('th');\n            th.className = 'wavesurfer-tier-' + tier.id;\n            th.textContent = tier.id;\n            th.style.width = this.params.tiers[tier.id];\n            headRow.appendChild(th);\n        });\n\n        // body\n        const tbody = document.createElement('tbody');\n        table.appendChild(tbody);\n        this.renderedAlignable.forEach(alignable => {\n            const row = document.createElement('tr');\n            row.id = 'wavesurfer-alignable-' + alignable.id;\n            tbody.appendChild(row);\n\n            const td = document.createElement('td');\n            td.className = 'wavesurfer-time';\n            td.textContent =\n                alignable.start.toFixed(1) + 'â' + alignable.end.toFixed(1);\n            row.appendChild(td);\n\n            const backRef = backRefs[alignable.id];\n            indeces.forEach(index => {\n                const tier = tiers[index];\n                const td = document.createElement('td');\n                const annotation = backRef[index];\n                if (annotation) {\n                    td.id = 'wavesurfer-annotation-' + annotation.id;\n                    td.dataset.ref = alignable.id;\n                    td.dataset.start = alignable.start;\n                    td.dataset.end = alignable.end;\n                    td.textContent = annotation.value;\n                }\n                td.className = 'wavesurfer-tier-' + tier.id;\n                row.appendChild(td);\n            });\n        });\n\n        this.container.innerHTML = '';\n        this.container.appendChild(table);\n    }\n\n    bindClick() {\n        this._onClick = e => {\n            const ref = e.target.dataset.ref;\n            if (null != ref) {\n                const annot = this.data.annotations[ref];\n                if (annot) {\n                    this.fireEvent('select', annot.start, annot.end);\n                }\n            }\n        };\n        this.container.addEventListener('click', this._onClick);\n    }\n\n    getRenderedAnnotation(time) {\n        let result;\n        this.renderedAlignable.some(annotation => {\n            if (annotation.start <= time && annotation.end >= time) {\n                result = annotation;\n                return true;\n            }\n            return false;\n        });\n        return result;\n    }\n\n    getAnnotationNode(annotation) {\n        return document.getElementById('wavesurfer-alignable-' + annotation.id);\n    }\n}\n"],"sourceRoot":""}
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.elan.min.js
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.elan.min.js	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.elan.min.js	(revision 33546)
@@ -0,0 +1,2 @@
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("elan",[],t):"object"==typeof exports?exports.elan=t():(e.WaveSurfer=e.WaveSurfer||{},e.WaveSurfer.elan=t())}(window,(function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var a=t[r]={i:r,l:!1,exports:{}};return e[r].call(a.exports,a,a.exports,n),a.l=!0,a.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var a in e)n.d(r,a,function(t){return e[t]}.bind(null,a));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="localhost:8080/dist/plugin/",n(n.s=7)}({7:function(e,t,n){"use strict";function r(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function a(e,t,n){return t&&r(e.prototype,t),n&&r(e,n),e}Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var i=function(){function e(t,n){if(function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.Types={ALIGNABLE_ANNOTATION:"ALIGNABLE_ANNOTATION",REF_ANNOTATION:"REF_ANNOTATION"},this.data=null,this.params=t,this.container="string"==typeof t.container?document.querySelector(t.container):t.container,!this.container)throw Error("No container for ELAN")}return a(e,null,[{key:"create",value:function(t){return{name:"elan",deferInit:!(!t||!t.deferInit)&&t.deferInit,params:t,instance:e}}}]),a(e,[{key:"init",value:function(){this.bindClick(),this.params.url&&this.load(this.params.url)}},{key:"destroy",value:function(){this.container.removeEventListener("click",this._onClick),this.container.removeChild(this.table)}},{key:"load",value:function(e){var t=this;this.loadXML(e,(function(e){t.data=t.parseElan(e),t.render(),t.fireEvent("ready",t.data)}))}},{key:"loadXML",value:function(e,t){var n=new XMLHttpRequest;n.open("GET",e,!0),n.responseType="document",n.send(),n.addEventListener("load",(function(e){t&&t(e.target.responseXML)}))}},{key:"parseElan",value:function(e){var t=this,n=Array.prototype.forEach,r=Array.prototype.map,a={media:{},timeOrder:{},tiers:[],annotations:{},alignableAnnotations:[]},i=e.querySelector("HEADER"),o="milliseconds"==i.getAttribute("TIME_UNITS"),u=i.querySelector("MEDIA_DESCRIPTOR");a.media.url=u.getAttribute("MEDIA_URL"),a.media.type=u.getAttribute("MIME_TYPE");var l=e.querySelectorAll("TIME_ORDER TIME_SLOT"),c={};return n.call(l,(function(e){var t=parseFloat(e.getAttribute("TIME_VALUE"));o&&(t=Math.round(100*t)/1e5),c[e.getAttribute("TIME_SLOT_ID")]=t})),a.tiers=r.call(e.querySelectorAll("TIER"),(function(e){return{id:e.getAttribute("TIER_ID"),linguisticTypeRef:e.getAttribute("LINGUISTIC_TYPE_REF"),defaultLocale:e.getAttribute("DEFAULT_LOCALE"),annotations:r.call(e.querySelectorAll("REF_ANNOTATION, ALIGNABLE_ANNOTATION"),(function(e){var n={type:e.nodeName,id:e.getAttribute("ANNOTATION_ID"),ref:e.getAttribute("ANNOTATION_REF"),value:e.querySelector("ANNOTATION_VALUE").textContent.trim()};return t.Types.ALIGNABLE_ANNOTATION==n.type&&(n.start=c[e.getAttribute("TIME_SLOT_REF1")],n.end=c[e.getAttribute("TIME_SLOT_REF2")],a.alignableAnnotations.push(n)),a.annotations[n.id]=n,n}))}})),a.tiers.forEach((function(e){e.annotations.forEach((function(e){null!=e.ref&&(e.reference=a.annotations[e.ref])}))})),a.alignableAnnotations.sort((function(e,t){var n=e.start-t.start;return 0==n&&(n=t.end-e.end),n})),a.length=a.alignableAnnotations.length,a}},{key:"render",value:function(){var e=this,t=this.data.tiers;this.params.tiers&&(t=t.filter((function(t){return t.id in e.params.tiers})));var n={},r={};t.forEach((function(t,a){t.annotations.forEach((function(t){t.reference&&t.reference.type==e.Types.ALIGNABLE_ANNOTATION&&(t.reference.id in n||(n[t.ref]={}),n[t.ref][a]=t,r[a]=!0)}))})),r=Object.keys(r).sort(),this.renderedAlignable=this.data.alignableAnnotations.filter((function(e){return n[e.id]}));var a=this.table=document.createElement("table");a.className="wavesurfer-annotations";var i=document.createElement("thead"),o=document.createElement("tr");i.appendChild(o),a.appendChild(i);var u=document.createElement("th");u.textContent="Time",u.className="wavesurfer-time",o.appendChild(u),r.forEach((function(n){var r=t[n],a=document.createElement("th");a.className="wavesurfer-tier-"+r.id,a.textContent=r.id,a.style.width=e.params.tiers[r.id],o.appendChild(a)}));var l=document.createElement("tbody");a.appendChild(l),this.renderedAlignable.forEach((function(e){var a=document.createElement("tr");a.id="wavesurfer-alignable-"+e.id,l.appendChild(a);var i=document.createElement("td");i.className="wavesurfer-time",i.textContent=e.start.toFixed(1)+"â"+e.end.toFixed(1),a.appendChild(i);var o=n[e.id];r.forEach((function(n){var r=t[n],i=document.createElement("td"),u=o[n];u&&(i.id="wavesurfer-annotation-"+u.id,i.dataset.ref=e.id,i.dataset.start=e.start,i.dataset.end=e.end,i.textContent=u.value),i.className="wavesurfer-tier-"+r.id,a.appendChild(i)}))})),this.container.innerHTML="",this.container.appendChild(a)}},{key:"bindClick",value:function(){var e=this;this._onClick=function(t){var n=t.target.dataset.ref;if(null!=n){var r=e.data.annotations[n];r&&e.fireEvent("select",r.start,r.end)}},this.container.addEventListener("click",this._onClick)}},{key:"getRenderedAnnotation",value:function(e){var t;return this.renderedAlignable.some((function(n){return n.start<=e&&n.end>=e&&(t=n,!0)})),t}},{key:"getAnnotationNode",value:function(e){return document.getElementById("wavesurfer-alignable-"+e.id)}}]),e}();t.default=i,e.exports=t.default}})}));
+//# sourceMappingURL=wavesurfer.elan.min.js.map
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.elan.min.js.map
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.elan.min.js.map	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.elan.min.js.map	(revision 33546)
@@ -0,0 +1,1 @@
+{"version":3,"sources":["webpack://WaveSurfer.[name]/webpack/universalModuleDefinition","webpack://WaveSurfer.[name]/webpack/bootstrap","webpack://WaveSurfer.[name]/./src/plugin/elan.js"],"names":["root","factory","exports","module","define","amd","window","installedModules","__webpack_require__","moduleId","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","ElanPlugin","params","ws","Types","ALIGNABLE_ANNOTATION","REF_ANNOTATION","this","data","container","document","querySelector","Error","deferInit","instance","bindClick","url","load","removeEventListener","_onClick","removeChild","table","loadXML","xml","parseElan","render","fireEvent","callback","xhr","XMLHttpRequest","open","responseType","send","addEventListener","e","target","responseXML","_forEach","Array","forEach","_map","map","media","timeOrder","tiers","annotations","alignableAnnotations","header","inMilliseconds","getAttribute","type","timeSlots","querySelectorAll","slot","parseFloat","Math","round","tier","id","linguisticTypeRef","defaultLocale","node","annot","nodeName","ref","textContent","trim","start","end","push","reference","sort","a","b","length","filter","backRefs","indeces","index","keys","renderedAlignable","alignable","createElement","className","thead","headRow","appendChild","th","style","width","tbody","row","td","toFixed","backRef","annotation","dataset","innerHTML","time","result","some","getElementById"],"mappings":"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","file":"wavesurfer.elan.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"elan\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"elan\"] = factory();\n\telse\n\t\troot[\"WaveSurfer\"] = root[\"WaveSurfer\"] || {}, root[\"WaveSurfer\"][\"elan\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"localhost:8080/dist/plugin/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 7);\n","/**\n * @typedef {Object} ElanPluginParams\n * @property {string|HTMLElement} container CSS selector or HTML element where\n * the ELAN information should be rendered.\n * @property {string} url The location of ELAN XML data\n * @property {?boolean} deferInit Set to true to manually call\n * @property {?Object} tiers If set only shows the data tiers with the `TIER_ID`\n * in this map.\n */\n\n/**\n * Downloads and renders ELAN audio transcription documents alongside the\n * waveform.\n *\n * @implements {PluginClass}\n * @extends {Observer}\n * @example\n * // es6\n * import ElanPlugin from 'wavesurfer.elan.js';\n *\n * // commonjs\n * var ElanPlugin = require('wavesurfer.elan.js');\n *\n * // if you are using <script> tags\n * var ElanPlugin = window.WaveSurfer.elan;\n *\n * // ... initialising wavesurfer with the plugin\n * var wavesurfer = WaveSurfer.create({\n *   // wavesurfer options ...\n *   plugins: [\n *     ElanPlugin.create({\n *       // plugin options ...\n *     })\n *   ]\n * });\n */\nexport default class ElanPlugin {\n    /**\n     * Elan plugin definition factory\n     *\n     * This function must be used to create a plugin definition which can be\n     * used by wavesurfer to correctly instantiate the plugin.\n     *\n     * @param  {ElanPluginParams} params parameters use to initialise the plugin\n     * @return {PluginDefinition} an object representing the plugin\n     */\n    static create(params) {\n        return {\n            name: 'elan',\n            deferInit: params && params.deferInit ? params.deferInit : false,\n            params: params,\n            instance: ElanPlugin\n        };\n    }\n\n    Types = {\n        ALIGNABLE_ANNOTATION: 'ALIGNABLE_ANNOTATION',\n        REF_ANNOTATION: 'REF_ANNOTATION'\n    };\n\n    constructor(params, ws) {\n        this.data = null;\n        this.params = params;\n        this.container =\n            'string' == typeof params.container\n                ? document.querySelector(params.container)\n                : params.container;\n\n        if (!this.container) {\n            throw Error('No container for ELAN');\n        }\n    }\n\n    init() {\n        this.bindClick();\n\n        if (this.params.url) {\n            this.load(this.params.url);\n        }\n    }\n\n    destroy() {\n        this.container.removeEventListener('click', this._onClick);\n        this.container.removeChild(this.table);\n    }\n\n    load(url) {\n        this.loadXML(url, xml => {\n            this.data = this.parseElan(xml);\n            this.render();\n            this.fireEvent('ready', this.data);\n        });\n    }\n\n    loadXML(url, callback) {\n        const xhr = new XMLHttpRequest();\n        xhr.open('GET', url, true);\n        xhr.responseType = 'document';\n        xhr.send();\n        xhr.addEventListener('load', e => {\n            callback && callback(e.target.responseXML);\n        });\n    }\n\n    parseElan(xml) {\n        const _forEach = Array.prototype.forEach;\n        const _map = Array.prototype.map;\n\n        const data = {\n            media: {},\n            timeOrder: {},\n            tiers: [],\n            annotations: {},\n            alignableAnnotations: []\n        };\n\n        const header = xml.querySelector('HEADER');\n        const inMilliseconds =\n            header.getAttribute('TIME_UNITS') == 'milliseconds';\n        const media = header.querySelector('MEDIA_DESCRIPTOR');\n        data.media.url = media.getAttribute('MEDIA_URL');\n        data.media.type = media.getAttribute('MIME_TYPE');\n\n        const timeSlots = xml.querySelectorAll('TIME_ORDER TIME_SLOT');\n        const timeOrder = {};\n        _forEach.call(timeSlots, slot => {\n            let value = parseFloat(slot.getAttribute('TIME_VALUE'));\n            // If in milliseconds, convert to seconds with rounding\n            if (inMilliseconds) {\n                value = Math.round(value * 1e2) / 1e5;\n            }\n            timeOrder[slot.getAttribute('TIME_SLOT_ID')] = value;\n        });\n\n        data.tiers = _map.call(xml.querySelectorAll('TIER'), tier => ({\n            id: tier.getAttribute('TIER_ID'),\n            linguisticTypeRef: tier.getAttribute('LINGUISTIC_TYPE_REF'),\n            defaultLocale: tier.getAttribute('DEFAULT_LOCALE'),\n            annotations: _map.call(\n                tier.querySelectorAll('REF_ANNOTATION, ALIGNABLE_ANNOTATION'),\n                node => {\n                    const annot = {\n                        type: node.nodeName,\n                        id: node.getAttribute('ANNOTATION_ID'),\n                        ref: node.getAttribute('ANNOTATION_REF'),\n                        value: node\n                            .querySelector('ANNOTATION_VALUE')\n                            .textContent.trim()\n                    };\n\n                    if (this.Types.ALIGNABLE_ANNOTATION == annot.type) {\n                        // Add start & end to alignable annotation\n                        annot.start =\n                            timeOrder[node.getAttribute('TIME_SLOT_REF1')];\n                        annot.end =\n                            timeOrder[node.getAttribute('TIME_SLOT_REF2')];\n                        // Add to the list of alignable annotations\n                        data.alignableAnnotations.push(annot);\n                    }\n\n                    // Additionally, put into the flat map of all annotations\n                    data.annotations[annot.id] = annot;\n\n                    return annot;\n                }\n            )\n        }));\n\n        // Create JavaScript references between annotations\n        data.tiers.forEach(tier => {\n            tier.annotations.forEach(annot => {\n                if (null != annot.ref) {\n                    annot.reference = data.annotations[annot.ref];\n                }\n            });\n        });\n\n        // Sort alignable annotations by start & end\n        data.alignableAnnotations.sort((a, b) => {\n            let d = a.start - b.start;\n            if (d == 0) {\n                d = b.end - a.end;\n            }\n            return d;\n        });\n\n        data.length = data.alignableAnnotations.length;\n\n        return data;\n    }\n\n    render() {\n        // apply tiers filter\n        let tiers = this.data.tiers;\n        if (this.params.tiers) {\n            tiers = tiers.filter(tier => tier.id in this.params.tiers);\n        }\n\n        // denormalize references to alignable annotations\n        const backRefs = {};\n        let indeces = {};\n        tiers.forEach((tier, index) => {\n            tier.annotations.forEach(annot => {\n                if (\n                    annot.reference &&\n                    annot.reference.type == this.Types.ALIGNABLE_ANNOTATION\n                ) {\n                    if (!(annot.reference.id in backRefs)) {\n                        backRefs[annot.ref] = {};\n                    }\n                    backRefs[annot.ref][index] = annot;\n                    indeces[index] = true;\n                }\n            });\n        });\n        indeces = Object.keys(indeces).sort();\n\n        this.renderedAlignable = this.data.alignableAnnotations.filter(\n            alignable => backRefs[alignable.id]\n        );\n\n        // table\n        const table = (this.table = document.createElement('table'));\n        table.className = 'wavesurfer-annotations';\n\n        // head\n        const thead = document.createElement('thead');\n        const headRow = document.createElement('tr');\n        thead.appendChild(headRow);\n        table.appendChild(thead);\n        const th = document.createElement('th');\n        th.textContent = 'Time';\n        th.className = 'wavesurfer-time';\n        headRow.appendChild(th);\n        indeces.forEach(index => {\n            const tier = tiers[index];\n            const th = document.createElement('th');\n            th.className = 'wavesurfer-tier-' + tier.id;\n            th.textContent = tier.id;\n            th.style.width = this.params.tiers[tier.id];\n            headRow.appendChild(th);\n        });\n\n        // body\n        const tbody = document.createElement('tbody');\n        table.appendChild(tbody);\n        this.renderedAlignable.forEach(alignable => {\n            const row = document.createElement('tr');\n            row.id = 'wavesurfer-alignable-' + alignable.id;\n            tbody.appendChild(row);\n\n            const td = document.createElement('td');\n            td.className = 'wavesurfer-time';\n            td.textContent =\n                alignable.start.toFixed(1) + 'â' + alignable.end.toFixed(1);\n            row.appendChild(td);\n\n            const backRef = backRefs[alignable.id];\n            indeces.forEach(index => {\n                const tier = tiers[index];\n                const td = document.createElement('td');\n                const annotation = backRef[index];\n                if (annotation) {\n                    td.id = 'wavesurfer-annotation-' + annotation.id;\n                    td.dataset.ref = alignable.id;\n                    td.dataset.start = alignable.start;\n                    td.dataset.end = alignable.end;\n                    td.textContent = annotation.value;\n                }\n                td.className = 'wavesurfer-tier-' + tier.id;\n                row.appendChild(td);\n            });\n        });\n\n        this.container.innerHTML = '';\n        this.container.appendChild(table);\n    }\n\n    bindClick() {\n        this._onClick = e => {\n            const ref = e.target.dataset.ref;\n            if (null != ref) {\n                const annot = this.data.annotations[ref];\n                if (annot) {\n                    this.fireEvent('select', annot.start, annot.end);\n                }\n            }\n        };\n        this.container.addEventListener('click', this._onClick);\n    }\n\n    getRenderedAnnotation(time) {\n        let result;\n        this.renderedAlignable.some(annotation => {\n            if (annotation.start <= time && annotation.end >= time) {\n                result = annotation;\n                return true;\n            }\n            return false;\n        });\n        return result;\n    }\n\n    getAnnotationNode(annotation) {\n        return document.getElementById('wavesurfer-alignable-' + annotation.id);\n    }\n}\n"],"sourceRoot":""}
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.mediasession.js
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.mediasession.js	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.mediasession.js	(revision 33546)
@@ -0,0 +1,246 @@
+/*!
+ * wavesurfer.js mediasession plugin 2.2.1 (2019-09-30)
+ * https://github.com/katspaugh/wavesurfer.js
+ * @license BSD-3-Clause
+ */
+(function webpackUniversalModuleDefinition(root, factory) {
+	if(typeof exports === 'object' && typeof module === 'object')
+		module.exports = factory();
+	else if(typeof define === 'function' && define.amd)
+		define("mediasession", [], factory);
+	else if(typeof exports === 'object')
+		exports["mediasession"] = factory();
+	else
+		root["WaveSurfer"] = root["WaveSurfer"] || {}, root["WaveSurfer"]["mediasession"] = factory();
+})(window, function() {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+/******/
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId]) {
+/******/ 			return installedModules[moduleId].exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			i: moduleId,
+/******/ 			l: false,
+/******/ 			exports: {}
+/******/ 		};
+/******/
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ 		// Flag the module as loaded
+/******/ 		module.l = true;
+/******/
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/
+/******/
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+/******/
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+/******/
+/******/ 	// define getter function for harmony exports
+/******/ 	__webpack_require__.d = function(exports, name, getter) {
+/******/ 		if(!__webpack_require__.o(exports, name)) {
+/******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
+/******/ 		}
+/******/ 	};
+/******/
+/******/ 	// define __esModule on exports
+/******/ 	__webpack_require__.r = function(exports) {
+/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ 		}
+/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
+/******/ 	};
+/******/
+/******/ 	// create a fake namespace object
+/******/ 	// mode & 1: value is a module id, require it
+/******/ 	// mode & 2: merge all properties of value into the ns
+/******/ 	// mode & 4: return value when already ns object
+/******/ 	// mode & 8|1: behave like require
+/******/ 	__webpack_require__.t = function(value, mode) {
+/******/ 		if(mode & 1) value = __webpack_require__(value);
+/******/ 		if(mode & 8) return value;
+/******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
+/******/ 		var ns = Object.create(null);
+/******/ 		__webpack_require__.r(ns);
+/******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
+/******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
+/******/ 		return ns;
+/******/ 	};
+/******/
+/******/ 	// getDefaultExport function for compatibility with non-harmony modules
+/******/ 	__webpack_require__.n = function(module) {
+/******/ 		var getter = module && module.__esModule ?
+/******/ 			function getDefault() { return module['default']; } :
+/******/ 			function getModuleExports() { return module; };
+/******/ 		__webpack_require__.d(getter, 'a', getter);
+/******/ 		return getter;
+/******/ 	};
+/******/
+/******/ 	// Object.prototype.hasOwnProperty.call
+/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "localhost:8080/dist/plugin/";
+/******/
+/******/
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(__webpack_require__.s = "./src/plugin/mediasession.js");
+/******/ })
+/************************************************************************/
+/******/ ({
+
+/***/ "./src/plugin/mediasession.js":
+/*!************************************!*\
+  !*** ./src/plugin/mediasession.js ***!
+  \************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+function _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); }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+/*global MediaMetadata*/
+
+/**
+ * @typedef {Object} MediaSessionPluginParams
+ * @property {MediaMetadata} metadata A MediaMetadata object: a representation
+ * of the metadata associated with a MediaSession that can be used by user agents
+ * to provide a customized user interface.
+ * @property {?boolean} deferInit Set to true to manually call
+ * `initPlugin('mediasession')`
+ */
+
+/**
+ * Visualize MediaSession information for a wavesurfer instance.
+ *
+ * @implements {PluginClass}
+ * @extends {Observer}
+ * @example
+ * // es6
+ * import MediaSessionPlugin from 'wavesurfer.mediasession.js';
+ *
+ * // commonjs
+ * var MediaSessionPlugin = require('wavesurfer.mediasession.js');
+ *
+ * // if you are using <script> tags
+ * var MediaSessionPlugin = window.WaveSurfer.mediasession;
+ *
+ * // ... initialising wavesurfer with the plugin
+ * var wavesurfer = WaveSurfer.create({
+ *   // wavesurfer options ...
+ *   plugins: [
+ *     MediaSessionPlugin.create({
+ *       // plugin options ...
+ *     })
+ *   ]
+ * });
+ */
+var MediaSessionPlugin =
+/*#__PURE__*/
+function () {
+  _createClass(MediaSessionPlugin, null, [{
+    key: "create",
+
+    /**
+     * MediaSession plugin definition factory
+     *
+     * This function must be used to create a plugin definition which can be
+     * used by wavesurfer to correctly instantiate the plugin.
+     *
+     * @param  {MediaSessionPluginParams} params parameters use to initialise the plugin
+     * @return {PluginDefinition} an object representing the plugin
+     */
+    value: function create(params) {
+      return {
+        name: 'mediasession',
+        deferInit: params && params.deferInit ? params.deferInit : false,
+        params: params,
+        instance: MediaSessionPlugin
+      };
+    }
+  }]);
+
+  function MediaSessionPlugin(params, ws) {
+    var _this = this;
+
+    _classCallCheck(this, MediaSessionPlugin);
+
+    this.params = params;
+    this.wavesurfer = ws;
+
+    if ('mediaSession' in navigator) {
+      // update metadata
+      this.metadata = this.params.metadata;
+      this.update(); // update metadata when playback starts
+
+      this.wavesurfer.on('play', function () {
+        _this.update();
+      }); // set playback action handlers
+
+      navigator.mediaSession.setActionHandler('play', function () {
+        _this.wavesurfer.play();
+      });
+      navigator.mediaSession.setActionHandler('pause', function () {
+        _this.wavesurfer.playPause();
+      });
+      navigator.mediaSession.setActionHandler('seekbackward', function () {
+        _this.wavesurfer.skipBackward();
+      });
+      navigator.mediaSession.setActionHandler('seekforward', function () {
+        _this.wavesurfer.skipForward();
+      });
+    }
+  }
+
+  _createClass(MediaSessionPlugin, [{
+    key: "init",
+    value: function init() {}
+  }, {
+    key: "destroy",
+    value: function destroy() {}
+  }, {
+    key: "update",
+    value: function update() {
+      if ((typeof MediaMetadata === "undefined" ? "undefined" : _typeof(MediaMetadata)) === (typeof Function === "undefined" ? "undefined" : _typeof(Function))) {
+        // set metadata
+        navigator.mediaSession.metadata = new MediaMetadata(this.metadata);
+      }
+    }
+  }]);
+
+  return MediaSessionPlugin;
+}();
+
+exports.default = MediaSessionPlugin;
+module.exports = exports.default;
+
+/***/ })
+
+/******/ });
+});
+//# sourceMappingURL=wavesurfer.mediasession.js.map
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.mediasession.js.map
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.mediasession.js.map	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.mediasession.js.map	(revision 33546)
@@ -0,0 +1,1 @@
+{"version":3,"sources":["webpack://WaveSurfer.[name]/webpack/universalModuleDefinition","webpack://WaveSurfer.[name]/webpack/bootstrap","webpack://WaveSurfer.[name]/./src/plugin/mediasession.js"],"names":["MediaSessionPlugin","params","name","deferInit","instance","ws","wavesurfer","navigator","metadata","update","on","mediaSession","setActionHandler","play","playPause","skipBackward","skipForward","MediaMetadata","Function"],"mappings":";;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+CAA+C;AAC/C,CAAC;AACD,O;QCVA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;;QAEA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;;;QAGA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA,0CAA0C,gCAAgC;QAC1E;QACA;;QAEA;QACA;QACA;QACA,wDAAwD,kBAAkB;QAC1E;QACA,iDAAiD,cAAc;QAC/D;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA,yCAAyC,iCAAiC;QAC1E,gHAAgH,mBAAmB,EAAE;QACrI;QACA;;QAEA;QACA;QACA;QACA,2BAA2B,0BAA0B,EAAE;QACvD,iCAAiC,eAAe;QAChD;QACA;QACA;;QAEA;QACA,sDAAsD,+DAA+D;;QAErH;QACA;;;QAGA;QACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;AClFA;;AAEA;;;;;;;;;AASA;;;;;;;;;;;;;;;;;;;;;;;;;IAyBqBA,kB;;;;;;AACjB;;;;;;;;;2BAScC,M,EAAQ;AAClB,aAAO;AACHC,YAAI,EAAE,cADH;AAEHC,iBAAS,EAAEF,MAAM,IAAIA,MAAM,CAACE,SAAjB,GAA6BF,MAAM,CAACE,SAApC,GAAgD,KAFxD;AAGHF,cAAM,EAAEA,MAHL;AAIHG,gBAAQ,EAAEJ;AAJP,OAAP;AAMH;;;AAED,8BAAYC,MAAZ,EAAoBI,EAApB,EAAwB;AAAA;;AAAA;;AACpB,SAAKJ,MAAL,GAAcA,MAAd;AACA,SAAKK,UAAL,GAAkBD,EAAlB;;AAEA,QAAI,kBAAkBE,SAAtB,EAAiC;AAC7B;AACA,WAAKC,QAAL,GAAgB,KAAKP,MAAL,CAAYO,QAA5B;AACA,WAAKC,MAAL,GAH6B,CAK7B;;AACA,WAAKH,UAAL,CAAgBI,EAAhB,CAAmB,MAAnB,EAA2B,YAAM;AAC7B,aAAI,CAACD,MAAL;AACH,OAFD,EAN6B,CAU7B;;AACAF,eAAS,CAACI,YAAV,CAAuBC,gBAAvB,CAAwC,MAAxC,EAAgD,YAAM;AAClD,aAAI,CAACN,UAAL,CAAgBO,IAAhB;AACH,OAFD;AAGAN,eAAS,CAACI,YAAV,CAAuBC,gBAAvB,CAAwC,OAAxC,EAAiD,YAAM;AACnD,aAAI,CAACN,UAAL,CAAgBQ,SAAhB;AACH,OAFD;AAGAP,eAAS,CAACI,YAAV,CAAuBC,gBAAvB,CAAwC,cAAxC,EAAwD,YAAM;AAC1D,aAAI,CAACN,UAAL,CAAgBS,YAAhB;AACH,OAFD;AAGAR,eAAS,CAACI,YAAV,CAAuBC,gBAAvB,CAAwC,aAAxC,EAAuD,YAAM;AACzD,aAAI,CAACN,UAAL,CAAgBU,WAAhB;AACH,OAFD;AAGH;AACJ;;;;2BAEM,CAAE;;;8BAEC,CAAE;;;6BAEH;AACL,UAAI,QAAOC,aAAP,yCAAOA,aAAP,eAAgCC,QAAhC,yCAAgCA,QAAhC,EAAJ,EAA8C;AAC1C;AACAX,iBAAS,CAACI,YAAV,CAAuBH,QAAvB,GAAkC,IAAIS,aAAJ,CAAkB,KAAKT,QAAvB,CAAlC;AACH;AACJ","file":"wavesurfer.mediasession.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"mediasession\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"mediasession\"] = factory();\n\telse\n\t\troot[\"WaveSurfer\"] = root[\"WaveSurfer\"] || {}, root[\"WaveSurfer\"][\"mediasession\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"localhost:8080/dist/plugin/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/plugin/mediasession.js\");\n","/*global MediaMetadata*/\n\n/**\n * @typedef {Object} MediaSessionPluginParams\n * @property {MediaMetadata} metadata A MediaMetadata object: a representation\n * of the metadata associated with a MediaSession that can be used by user agents\n * to provide a customized user interface.\n * @property {?boolean} deferInit Set to true to manually call\n * `initPlugin('mediasession')`\n */\n\n/**\n * Visualize MediaSession information for a wavesurfer instance.\n *\n * @implements {PluginClass}\n * @extends {Observer}\n * @example\n * // es6\n * import MediaSessionPlugin from 'wavesurfer.mediasession.js';\n *\n * // commonjs\n * var MediaSessionPlugin = require('wavesurfer.mediasession.js');\n *\n * // if you are using <script> tags\n * var MediaSessionPlugin = window.WaveSurfer.mediasession;\n *\n * // ... initialising wavesurfer with the plugin\n * var wavesurfer = WaveSurfer.create({\n *   // wavesurfer options ...\n *   plugins: [\n *     MediaSessionPlugin.create({\n *       // plugin options ...\n *     })\n *   ]\n * });\n */\nexport default class MediaSessionPlugin {\n    /**\n     * MediaSession plugin definition factory\n     *\n     * This function must be used to create a plugin definition which can be\n     * used by wavesurfer to correctly instantiate the plugin.\n     *\n     * @param  {MediaSessionPluginParams} params parameters use to initialise the plugin\n     * @return {PluginDefinition} an object representing the plugin\n     */\n    static create(params) {\n        return {\n            name: 'mediasession',\n            deferInit: params && params.deferInit ? params.deferInit : false,\n            params: params,\n            instance: MediaSessionPlugin\n        };\n    }\n\n    constructor(params, ws) {\n        this.params = params;\n        this.wavesurfer = ws;\n\n        if ('mediaSession' in navigator) {\n            // update metadata\n            this.metadata = this.params.metadata;\n            this.update();\n\n            // update metadata when playback starts\n            this.wavesurfer.on('play', () => {\n                this.update();\n            });\n\n            // set playback action handlers\n            navigator.mediaSession.setActionHandler('play', () => {\n                this.wavesurfer.play();\n            });\n            navigator.mediaSession.setActionHandler('pause', () => {\n                this.wavesurfer.playPause();\n            });\n            navigator.mediaSession.setActionHandler('seekbackward', () => {\n                this.wavesurfer.skipBackward();\n            });\n            navigator.mediaSession.setActionHandler('seekforward', () => {\n                this.wavesurfer.skipForward();\n            });\n        }\n    }\n\n    init() {}\n\n    destroy() {}\n\n    update() {\n        if (typeof MediaMetadata === typeof Function) {\n            // set metadata\n            navigator.mediaSession.metadata = new MediaMetadata(this.metadata);\n        }\n    }\n}\n"],"sourceRoot":""}
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.mediasession.min.js
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.mediasession.min.js	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.mediasession.min.js	(revision 33546)
@@ -0,0 +1,2 @@
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("mediasession",[],t):"object"==typeof exports?exports.mediasession=t():(e.WaveSurfer=e.WaveSurfer||{},e.WaveSurfer.mediasession=t())}(window,(function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="localhost:8080/dist/plugin/",n(n.s=6)}({6:function(e,t,n){"use strict";function r(e){return(r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function o(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function a(e,t,n){return t&&o(e.prototype,t),n&&o(e,n),e}Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var i=function(){function e(t,n){var r=this;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.params=t,this.wavesurfer=n,"mediaSession"in navigator&&(this.metadata=this.params.metadata,this.update(),this.wavesurfer.on("play",(function(){r.update()})),navigator.mediaSession.setActionHandler("play",(function(){r.wavesurfer.play()})),navigator.mediaSession.setActionHandler("pause",(function(){r.wavesurfer.playPause()})),navigator.mediaSession.setActionHandler("seekbackward",(function(){r.wavesurfer.skipBackward()})),navigator.mediaSession.setActionHandler("seekforward",(function(){r.wavesurfer.skipForward()})))}return a(e,null,[{key:"create",value:function(t){return{name:"mediasession",deferInit:!(!t||!t.deferInit)&&t.deferInit,params:t,instance:e}}}]),a(e,[{key:"init",value:function(){}},{key:"destroy",value:function(){}},{key:"update",value:function(){("undefined"==typeof MediaMetadata?"undefined":r(MediaMetadata))===("undefined"==typeof Function?"undefined":r(Function))&&(navigator.mediaSession.metadata=new MediaMetadata(this.metadata))}}]),e}();t.default=i,e.exports=t.default}})}));
+//# sourceMappingURL=wavesurfer.mediasession.min.js.map
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.mediasession.min.js.map
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.mediasession.min.js.map	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.mediasession.min.js.map	(revision 33546)
@@ -0,0 +1,1 @@
+{"version":3,"sources":["webpack://WaveSurfer.[name]/webpack/universalModuleDefinition","webpack://WaveSurfer.[name]/webpack/bootstrap","webpack://WaveSurfer.[name]/./src/plugin/mediasession.js"],"names":["root","factory","exports","module","define","amd","window","installedModules","__webpack_require__","moduleId","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","MediaSessionPlugin","params","ws","this","wavesurfer","navigator","metadata","update","on","mediaSession","setActionHandler","play","playPause","skipBackward","skipForward","deferInit","instance","MediaMetadata","Function"],"mappings":"CAAA,SAA2CA,EAAMC,GAC1B,iBAAZC,SAA0C,iBAAXC,OACxCA,OAAOD,QAAUD,IACQ,mBAAXG,QAAyBA,OAAOC,IAC9CD,OAAO,eAAgB,GAAIH,GACD,iBAAZC,QACdA,QAAsB,aAAID,KAE1BD,EAAiB,WAAIA,EAAiB,YAAK,GAAIA,EAAiB,WAAgB,aAAIC,KARtF,CASGK,QAAQ,WACX,O,YCTE,IAAIC,EAAmB,GAGvB,SAASC,EAAoBC,GAG5B,GAAGF,EAAiBE,GACnB,OAAOF,EAAiBE,GAAUP,QAGnC,IAAIC,EAASI,EAAiBE,GAAY,CACzCC,EAAGD,EACHE,GAAG,EACHT,QAAS,IAUV,OANAU,EAAQH,GAAUI,KAAKV,EAAOD,QAASC,EAAQA,EAAOD,QAASM,GAG/DL,EAAOQ,GAAI,EAGJR,EAAOD,QA0Df,OArDAM,EAAoBM,EAAIF,EAGxBJ,EAAoBO,EAAIR,EAGxBC,EAAoBQ,EAAI,SAASd,EAASe,EAAMC,GAC3CV,EAAoBW,EAAEjB,EAASe,IAClCG,OAAOC,eAAenB,EAASe,EAAM,CAAEK,YAAY,EAAMC,IAAKL,KAKhEV,EAAoBgB,EAAI,SAAStB,GACX,oBAAXuB,QAA0BA,OAAOC,aAC1CN,OAAOC,eAAenB,EAASuB,OAAOC,YAAa,CAAEC,MAAO,WAE7DP,OAAOC,eAAenB,EAAS,aAAc,CAAEyB,OAAO,KAQvDnB,EAAoBoB,EAAI,SAASD,EAAOE,GAEvC,GADU,EAAPA,IAAUF,EAAQnB,EAAoBmB,IAC/B,EAAPE,EAAU,OAAOF,EACpB,GAAW,EAAPE,GAA8B,iBAAVF,GAAsBA,GAASA,EAAMG,WAAY,OAAOH,EAChF,IAAII,EAAKX,OAAOY,OAAO,MAGvB,GAFAxB,EAAoBgB,EAAEO,GACtBX,OAAOC,eAAeU,EAAI,UAAW,CAAET,YAAY,EAAMK,MAAOA,IACtD,EAAPE,GAA4B,iBAATF,EAAmB,IAAI,IAAIM,KAAON,EAAOnB,EAAoBQ,EAAEe,EAAIE,EAAK,SAASA,GAAO,OAAON,EAAMM,IAAQC,KAAK,KAAMD,IAC9I,OAAOF,GAIRvB,EAAoB2B,EAAI,SAAShC,GAChC,IAAIe,EAASf,GAAUA,EAAO2B,WAC7B,WAAwB,OAAO3B,EAAgB,SAC/C,WAA8B,OAAOA,GAEtC,OADAK,EAAoBQ,EAAEE,EAAQ,IAAKA,GAC5BA,GAIRV,EAAoBW,EAAI,SAASiB,EAAQC,GAAY,OAAOjB,OAAOkB,UAAUC,eAAe1B,KAAKuB,EAAQC,IAGzG7B,EAAoBgC,EAAI,8BAIjBhC,EAAoBA,EAAoBiC,EAAI,G,2iBC9ChCC,E,WAmBjB,WAAYC,EAAQC,GAAI,Y,4FAAA,SACpBC,KAAKF,OAASA,EACdE,KAAKC,WAAaF,EAEd,iBAAkBG,YAElBF,KAAKG,SAAWH,KAAKF,OAAOK,SAC5BH,KAAKI,SAGLJ,KAAKC,WAAWI,GAAG,QAAQ,WACvB,EAAKD,YAITF,UAAUI,aAAaC,iBAAiB,QAAQ,WAC5C,EAAKN,WAAWO,UAEpBN,UAAUI,aAAaC,iBAAiB,SAAS,WAC7C,EAAKN,WAAWQ,eAEpBP,UAAUI,aAAaC,iBAAiB,gBAAgB,WACpD,EAAKN,WAAWS,kBAEpBR,UAAUI,aAAaC,iBAAiB,eAAe,WACnD,EAAKN,WAAWU,kB,8CAlCdb,GACV,MAAO,CACH1B,KAAM,eACNwC,aAAWd,IAAUA,EAAOc,YAAYd,EAAOc,UAC/Cd,OAAQA,EACRe,SAAUhB,O,wGAuCV,oBAAOiB,cAAP,cAAOA,mBAAP,oBAAgCC,SAAhC,cAAgCA,aAEhCb,UAAUI,aAAaH,SAAW,IAAIW,cAAcd,KAAKG,e","file":"wavesurfer.mediasession.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"mediasession\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"mediasession\"] = factory();\n\telse\n\t\troot[\"WaveSurfer\"] = root[\"WaveSurfer\"] || {}, root[\"WaveSurfer\"][\"mediasession\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"localhost:8080/dist/plugin/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 6);\n","/*global MediaMetadata*/\n\n/**\n * @typedef {Object} MediaSessionPluginParams\n * @property {MediaMetadata} metadata A MediaMetadata object: a representation\n * of the metadata associated with a MediaSession that can be used by user agents\n * to provide a customized user interface.\n * @property {?boolean} deferInit Set to true to manually call\n * `initPlugin('mediasession')`\n */\n\n/**\n * Visualize MediaSession information for a wavesurfer instance.\n *\n * @implements {PluginClass}\n * @extends {Observer}\n * @example\n * // es6\n * import MediaSessionPlugin from 'wavesurfer.mediasession.js';\n *\n * // commonjs\n * var MediaSessionPlugin = require('wavesurfer.mediasession.js');\n *\n * // if you are using <script> tags\n * var MediaSessionPlugin = window.WaveSurfer.mediasession;\n *\n * // ... initialising wavesurfer with the plugin\n * var wavesurfer = WaveSurfer.create({\n *   // wavesurfer options ...\n *   plugins: [\n *     MediaSessionPlugin.create({\n *       // plugin options ...\n *     })\n *   ]\n * });\n */\nexport default class MediaSessionPlugin {\n    /**\n     * MediaSession plugin definition factory\n     *\n     * This function must be used to create a plugin definition which can be\n     * used by wavesurfer to correctly instantiate the plugin.\n     *\n     * @param  {MediaSessionPluginParams} params parameters use to initialise the plugin\n     * @return {PluginDefinition} an object representing the plugin\n     */\n    static create(params) {\n        return {\n            name: 'mediasession',\n            deferInit: params && params.deferInit ? params.deferInit : false,\n            params: params,\n            instance: MediaSessionPlugin\n        };\n    }\n\n    constructor(params, ws) {\n        this.params = params;\n        this.wavesurfer = ws;\n\n        if ('mediaSession' in navigator) {\n            // update metadata\n            this.metadata = this.params.metadata;\n            this.update();\n\n            // update metadata when playback starts\n            this.wavesurfer.on('play', () => {\n                this.update();\n            });\n\n            // set playback action handlers\n            navigator.mediaSession.setActionHandler('play', () => {\n                this.wavesurfer.play();\n            });\n            navigator.mediaSession.setActionHandler('pause', () => {\n                this.wavesurfer.playPause();\n            });\n            navigator.mediaSession.setActionHandler('seekbackward', () => {\n                this.wavesurfer.skipBackward();\n            });\n            navigator.mediaSession.setActionHandler('seekforward', () => {\n                this.wavesurfer.skipForward();\n            });\n        }\n    }\n\n    init() {}\n\n    destroy() {}\n\n    update() {\n        if (typeof MediaMetadata === typeof Function) {\n            // set metadata\n            navigator.mediaSession.metadata = new MediaMetadata(this.metadata);\n        }\n    }\n}\n"],"sourceRoot":""}
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.microphone.js
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.microphone.js	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.microphone.js	(revision 33546)
@@ -0,0 +1,541 @@
+/*!
+ * wavesurfer.js microphone plugin 2.2.1 (2019-09-30)
+ * https://github.com/katspaugh/wavesurfer.js
+ * @license BSD-3-Clause
+ */
+(function webpackUniversalModuleDefinition(root, factory) {
+	if(typeof exports === 'object' && typeof module === 'object')
+		module.exports = factory();
+	else if(typeof define === 'function' && define.amd)
+		define("microphone", [], factory);
+	else if(typeof exports === 'object')
+		exports["microphone"] = factory();
+	else
+		root["WaveSurfer"] = root["WaveSurfer"] || {}, root["WaveSurfer"]["microphone"] = factory();
+})(window, function() {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+/******/
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId]) {
+/******/ 			return installedModules[moduleId].exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			i: moduleId,
+/******/ 			l: false,
+/******/ 			exports: {}
+/******/ 		};
+/******/
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ 		// Flag the module as loaded
+/******/ 		module.l = true;
+/******/
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/
+/******/
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+/******/
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+/******/
+/******/ 	// define getter function for harmony exports
+/******/ 	__webpack_require__.d = function(exports, name, getter) {
+/******/ 		if(!__webpack_require__.o(exports, name)) {
+/******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
+/******/ 		}
+/******/ 	};
+/******/
+/******/ 	// define __esModule on exports
+/******/ 	__webpack_require__.r = function(exports) {
+/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ 		}
+/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
+/******/ 	};
+/******/
+/******/ 	// create a fake namespace object
+/******/ 	// mode & 1: value is a module id, require it
+/******/ 	// mode & 2: merge all properties of value into the ns
+/******/ 	// mode & 4: return value when already ns object
+/******/ 	// mode & 8|1: behave like require
+/******/ 	__webpack_require__.t = function(value, mode) {
+/******/ 		if(mode & 1) value = __webpack_require__(value);
+/******/ 		if(mode & 8) return value;
+/******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
+/******/ 		var ns = Object.create(null);
+/******/ 		__webpack_require__.r(ns);
+/******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
+/******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
+/******/ 		return ns;
+/******/ 	};
+/******/
+/******/ 	// getDefaultExport function for compatibility with non-harmony modules
+/******/ 	__webpack_require__.n = function(module) {
+/******/ 		var getter = module && module.__esModule ?
+/******/ 			function getDefault() { return module['default']; } :
+/******/ 			function getModuleExports() { return module; };
+/******/ 		__webpack_require__.d(getter, 'a', getter);
+/******/ 		return getter;
+/******/ 	};
+/******/
+/******/ 	// Object.prototype.hasOwnProperty.call
+/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "localhost:8080/dist/plugin/";
+/******/
+/******/
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(__webpack_require__.s = "./src/plugin/microphone.js");
+/******/ })
+/************************************************************************/
+/******/ ({
+
+/***/ "./src/plugin/microphone.js":
+/*!**********************************!*\
+  !*** ./src/plugin/microphone.js ***!
+  \**********************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+/**
+ * @typedef {Object} MicrophonePluginParams
+ * @property {MediaStreamConstraints} constraints The constraints parameter is a
+ * MediaStreamConstaints object with two members: video and audio, describing
+ * the media types requested. Either or both must be specified.
+ * @property {number} bufferSize=4096 The buffer size in units of sample-frames.
+ * If specified, the bufferSize must be one of the following values: `256`,
+ * `512`, `1024`, `2048`, `4096`, `8192`, `16384`
+ * @property {number} numberOfInputChannels=1 Integer specifying the number of
+ * channels for this node's input. Values of up to 32 are supported.
+ * @property {?boolean} deferInit Set to true to manually call
+ * `initPlugin('microphone')`
+ */
+
+/**
+ * Visualize microphone input in a wavesurfer instance.
+ *
+ * @implements {PluginClass}
+ * @extends {Observer}
+ * @example
+ * // es6
+ * import MicrophonePlugin from 'wavesurfer.microphone.js';
+ *
+ * // commonjs
+ * var MicrophonePlugin = require('wavesurfer.microphone.js');
+ *
+ * // if you are using <script> tags
+ * var MicrophonePlugin = window.WaveSurfer.microphone;
+ *
+ * // ... initialising wavesurfer with the plugin
+ * var wavesurfer = WaveSurfer.create({
+ *   // wavesurfer options ...
+ *   plugins: [
+ *     MicrophonePlugin.create({
+ *       // plugin options ...
+ *     })
+ *   ]
+ * });
+ */
+var MicrophonePlugin =
+/*#__PURE__*/
+function () {
+  _createClass(MicrophonePlugin, null, [{
+    key: "create",
+
+    /**
+     * Microphone plugin definition factory
+     *
+     * This function must be used to create a plugin definition which can be
+     * used by wavesurfer to correctly instantiate the plugin.
+     *
+     * @param  {MicrophonePluginParams} params parameters use to initialise the plugin
+     * @return {PluginDefinition} an object representing the plugin
+     */
+    value: function create(params) {
+      return {
+        name: 'microphone',
+        deferInit: params && params.deferInit ? params.deferInit : false,
+        params: params,
+        instance: MicrophonePlugin
+      };
+    }
+  }]);
+
+  function MicrophonePlugin(params, ws) {
+    var _this = this;
+
+    _classCallCheck(this, MicrophonePlugin);
+
+    this.params = params;
+    this.wavesurfer = ws;
+    this.active = false;
+    this.paused = false;
+    this.browser = this.detectBrowser();
+
+    this.reloadBufferFunction = function (e) {
+      return _this.reloadBuffer(e);
+    }; // cross-browser getUserMedia
+
+
+    var promisifiedOldGUM = function promisifiedOldGUM(constraints, successCallback, errorCallback) {
+      // get a hold of getUserMedia, if present
+      var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; // Some browsers just don't implement it - return a rejected
+      // promise with an error to keep a consistent interface
+
+      if (!getUserMedia) {
+        return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
+      } // otherwise, wrap the call to the old navigator.getUserMedia with
+      // a Promise
+
+
+      return new Promise(function (successCallback, errorCallback) {
+        getUserMedia.call(navigator, constraints, successCallback, errorCallback);
+      });
+    }; // Older browsers might not implement mediaDevices at all, so we set an
+    // empty object first
+
+
+    if (navigator.mediaDevices === undefined) {
+      navigator.mediaDevices = {};
+    } // Some browsers partially implement mediaDevices. We can't just assign
+    // an object with getUserMedia as it would overwrite existing
+    // properties. Here, we will just add the getUserMedia property if it's
+    // missing.
+
+
+    if (navigator.mediaDevices.getUserMedia === undefined) {
+      navigator.mediaDevices.getUserMedia = promisifiedOldGUM;
+    }
+
+    this.constraints = this.params.constraints || {
+      video: false,
+      audio: true
+    };
+    this.bufferSize = this.params.bufferSize || 4096;
+    this.numberOfInputChannels = this.params.numberOfInputChannels || 1;
+    this.numberOfOutputChannels = this.params.numberOfOutputChannels || 1;
+
+    this._onBackendCreated = function () {
+      // wavesurfer's AudioContext where we'll route the mic signal to
+      _this.micContext = _this.wavesurfer.backend.getAudioContext();
+    };
+  }
+
+  _createClass(MicrophonePlugin, [{
+    key: "init",
+    value: function init() {
+      this.wavesurfer.on('backend-created', this._onBackendCreated);
+
+      if (this.wavesurfer.backend) {
+        this._onBackendCreated();
+      }
+    }
+    /**
+     * Destroy the microphone plugin.
+     */
+
+  }, {
+    key: "destroy",
+    value: function destroy() {
+      // make sure the buffer is not redrawn during
+      // cleanup and demolition of this plugin.
+      this.paused = true;
+      this.wavesurfer.un('backend-created', this._onBackendCreated);
+      this.stop();
+    }
+    /**
+     * Allow user to select audio input device, e.g. microphone, and
+     * start the visualization.
+     */
+
+  }, {
+    key: "start",
+    value: function start() {
+      var _this2 = this;
+
+      navigator.mediaDevices.getUserMedia(this.constraints).then(function (data) {
+        return _this2.gotStream(data);
+      }).catch(function (data) {
+        return _this2.deviceError(data);
+      });
+    }
+    /**
+     * Pause/resume visualization.
+     */
+
+  }, {
+    key: "togglePlay",
+    value: function togglePlay() {
+      if (!this.active) {
+        // start it first
+        this.start();
+      } else {
+        // toggle paused
+        this.paused = !this.paused;
+
+        if (this.paused) {
+          this.pause();
+        } else {
+          this.play();
+        }
+      }
+    }
+    /**
+     * Play visualization.
+     */
+
+  }, {
+    key: "play",
+    value: function play() {
+      this.paused = false;
+      this.connect();
+    }
+    /**
+     * Pause visualization.
+     */
+
+  }, {
+    key: "pause",
+    value: function pause() {
+      this.paused = true; // disconnect sources so they can be used elsewhere
+      // (eg. during audio playback)
+
+      this.disconnect();
+    }
+    /**
+     * Stop the device stream and remove any remaining waveform drawing from
+     * the wavesurfer canvas.
+     */
+
+  }, {
+    key: "stop",
+    value: function stop() {
+      if (this.active) {
+        // stop visualization and device
+        this.stopDevice(); // empty last frame
+
+        this.wavesurfer.empty();
+      }
+    }
+    /**
+     * Stop the device and the visualization.
+     */
+
+  }, {
+    key: "stopDevice",
+    value: function stopDevice() {
+      this.active = false; // stop visualization
+
+      this.disconnect(); // stop stream from device
+
+      if (this.stream) {
+        // MediaStream.stop is deprecated since:
+        // - Firefox 44 (https://www.fxsitecompat.com/en-US/docs/2015/mediastream-stop-has-been-deprecated/)
+        // - Chrome 45 (https://developers.google.com/web/updates/2015/07/mediastream-deprecations)
+        if (this.browser.browser === 'chrome' && this.browser.version >= 45 || this.browser.browser === 'firefox' && this.browser.version >= 44 || this.browser.browser === 'edge' || this.browser.browser === 'safari') {
+          if (this.stream.getTracks) {
+            // note that this should not be a call
+            this.stream.getTracks().forEach(function (stream) {
+              return stream.stop();
+            });
+            return;
+          }
+        }
+
+        this.stream.stop();
+      }
+    }
+    /**
+     * Connect the media sources that feed the visualization.
+     */
+
+  }, {
+    key: "connect",
+    value: function connect() {
+      if (this.stream !== undefined) {
+        // Create a local buffer for data to be copied to the Wavesurfer buffer for Edge
+        if (this.browser.browser === 'edge') {
+          this.localAudioBuffer = this.micContext.createBuffer(this.numberOfInputChannels, this.bufferSize, this.micContext.sampleRate);
+        } // Create an AudioNode from the stream.
+
+
+        this.mediaStreamSource = this.micContext.createMediaStreamSource(this.stream);
+        this.levelChecker = this.micContext.createScriptProcessor(this.bufferSize, this.numberOfInputChannels, this.numberOfOutputChannels);
+        this.mediaStreamSource.connect(this.levelChecker);
+        this.levelChecker.connect(this.micContext.destination);
+        this.levelChecker.onaudioprocess = this.reloadBufferFunction;
+      }
+    }
+    /**
+     * Disconnect the media sources that feed the visualization.
+     */
+
+  }, {
+    key: "disconnect",
+    value: function disconnect() {
+      if (this.mediaStreamSource !== undefined) {
+        this.mediaStreamSource.disconnect();
+      }
+
+      if (this.levelChecker !== undefined) {
+        this.levelChecker.disconnect();
+        this.levelChecker.onaudioprocess = undefined;
+      }
+
+      if (this.localAudioBuffer !== undefined) {
+        this.localAudioBuffer = undefined;
+      }
+    }
+    /**
+     * Redraw the waveform.
+     */
+
+  }, {
+    key: "reloadBuffer",
+    value: function reloadBuffer(event) {
+      if (!this.paused) {
+        this.wavesurfer.empty();
+
+        if (this.browser.browser === 'edge') {
+          // copy audio data to a local audio buffer,
+          // from https://github.com/audiojs/audio-buffer-utils
+          var channel, l;
+
+          for (channel = 0, l = Math.min(this.localAudioBuffer.numberOfChannels, event.inputBuffer.numberOfChannels); channel < l; channel++) {
+            this.localAudioBuffer.getChannelData(channel).set(event.inputBuffer.getChannelData(channel));
+          }
+
+          this.wavesurfer.loadDecodedBuffer(this.localAudioBuffer);
+        } else {
+          this.wavesurfer.loadDecodedBuffer(event.inputBuffer);
+        }
+      }
+    }
+    /**
+     * Audio input device is ready.
+     *
+     * @param {LocalMediaStream} stream The microphone's media stream.
+     */
+
+  }, {
+    key: "gotStream",
+    value: function gotStream(stream) {
+      this.stream = stream;
+      this.active = true; // start visualization
+
+      this.play(); // notify listeners
+
+      this.fireEvent('deviceReady', stream);
+    }
+    /**
+     * Device error callback.
+     */
+
+  }, {
+    key: "deviceError",
+    value: function deviceError(code) {
+      // notify listeners
+      this.fireEvent('deviceError', code);
+    }
+    /**
+     * Extract browser version out of the provided user agent string.
+     * @param {!string} uastring userAgent string.
+     * @param {!string} expr Regular expression used as match criteria.
+     * @param {!number} pos position in the version string to be returned.
+     * @return {!number} browser version.
+     */
+
+  }, {
+    key: "extractVersion",
+    value: function extractVersion(uastring, expr, pos) {
+      var match = uastring.match(expr);
+      return match && match.length >= pos && parseInt(match[pos], 10);
+    }
+    /**
+     * Browser detector.
+     * @return {object} result containing browser, version and minVersion
+     *     properties.
+     */
+
+  }, {
+    key: "detectBrowser",
+    value: function detectBrowser() {
+      // Returned result object.
+      var result = {};
+      result.browser = null;
+      result.version = null;
+      result.minVersion = null; // Non supported browser.
+
+      if (typeof window === 'undefined' || !window.navigator) {
+        result.browser = 'Not a supported browser.';
+        return result;
+      }
+
+      if (navigator.mozGetUserMedia) {
+        // Firefox
+        result.browser = 'firefox';
+        result.version = this.extractVersion(navigator.userAgent, /Firefox\/(\d+)\./, 1);
+        result.minVersion = 31;
+        return result;
+      } else if (navigator.webkitGetUserMedia) {
+        // Chrome/Chromium/Webview/Opera
+        result.browser = 'chrome';
+        result.version = this.extractVersion(navigator.userAgent, /Chrom(e|ium)\/(\d+)\./, 2);
+        result.minVersion = 38;
+        return result;
+      } else if (navigator.mediaDevices && navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)) {
+        // Edge
+        result.browser = 'edge';
+        result.version = this.extractVersion(navigator.userAgent, /Edge\/(\d+).(\d+)$/, 2);
+        result.minVersion = 10547;
+        return result;
+      } else if (window.RTCPeerConnection && navigator.userAgent.match(/AppleWebKit\/(\d+)\./)) {
+        // Safari
+        result.browser = 'safari';
+        result.minVersion = 11;
+        result.version = this.extractVersion(navigator.userAgent, /AppleWebKit\/(\d+)\./, 1);
+        return result;
+      } // Non supported browser default.
+
+
+      result.browser = 'Not a supported browser.';
+      return result;
+    }
+  }]);
+
+  return MicrophonePlugin;
+}();
+
+exports.default = MicrophonePlugin;
+module.exports = exports.default;
+
+/***/ })
+
+/******/ });
+});
+//# sourceMappingURL=wavesurfer.microphone.js.map
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.microphone.js.map
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.microphone.js.map	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.microphone.js.map	(revision 33546)
@@ -0,0 +1,1 @@
+{"version":3,"sources":["webpack://WaveSurfer.[name]/webpack/universalModuleDefinition","webpack://WaveSurfer.[name]/webpack/bootstrap","webpack://WaveSurfer.[name]/./src/plugin/microphone.js"],"names":["MicrophonePlugin","params","name","deferInit","instance","ws","wavesurfer","active","paused","browser","detectBrowser","reloadBufferFunction","e","reloadBuffer","promisifiedOldGUM","constraints","successCallback","errorCallback","getUserMedia","navigator","webkitGetUserMedia","mozGetUserMedia","msGetUserMedia","Promise","reject","Error","call","mediaDevices","undefined","video","audio","bufferSize","numberOfInputChannels","numberOfOutputChannels","_onBackendCreated","micContext","backend","getAudioContext","on","un","stop","then","data","gotStream","catch","deviceError","start","pause","play","connect","disconnect","stopDevice","empty","stream","version","getTracks","forEach","localAudioBuffer","createBuffer","sampleRate","mediaStreamSource","createMediaStreamSource","levelChecker","createScriptProcessor","destination","onaudioprocess","event","channel","l","Math","min","numberOfChannels","inputBuffer","getChannelData","set","loadDecodedBuffer","fireEvent","code","uastring","expr","pos","match","length","parseInt","result","minVersion","window","extractVersion","userAgent","RTCPeerConnection"],"mappings":"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","file":"wavesurfer.microphone.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"microphone\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"microphone\"] = factory();\n\telse\n\t\troot[\"WaveSurfer\"] = root[\"WaveSurfer\"] || {}, root[\"WaveSurfer\"][\"microphone\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"localhost:8080/dist/plugin/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/plugin/microphone.js\");\n","/**\n * @typedef {Object} MicrophonePluginParams\n * @property {MediaStreamConstraints} constraints The constraints parameter is a\n * MediaStreamConstaints object with two members: video and audio, describing\n * the media types requested. Either or both must be specified.\n * @property {number} bufferSize=4096 The buffer size in units of sample-frames.\n * If specified, the bufferSize must be one of the following values: `256`,\n * `512`, `1024`, `2048`, `4096`, `8192`, `16384`\n * @property {number} numberOfInputChannels=1 Integer specifying the number of\n * channels for this node's input. Values of up to 32 are supported.\n * @property {?boolean} deferInit Set to true to manually call\n * `initPlugin('microphone')`\n */\n\n/**\n * Visualize microphone input in a wavesurfer instance.\n *\n * @implements {PluginClass}\n * @extends {Observer}\n * @example\n * // es6\n * import MicrophonePlugin from 'wavesurfer.microphone.js';\n *\n * // commonjs\n * var MicrophonePlugin = require('wavesurfer.microphone.js');\n *\n * // if you are using <script> tags\n * var MicrophonePlugin = window.WaveSurfer.microphone;\n *\n * // ... initialising wavesurfer with the plugin\n * var wavesurfer = WaveSurfer.create({\n *   // wavesurfer options ...\n *   plugins: [\n *     MicrophonePlugin.create({\n *       // plugin options ...\n *     })\n *   ]\n * });\n */\nexport default class MicrophonePlugin {\n    /**\n     * Microphone plugin definition factory\n     *\n     * This function must be used to create a plugin definition which can be\n     * used by wavesurfer to correctly instantiate the plugin.\n     *\n     * @param  {MicrophonePluginParams} params parameters use to initialise the plugin\n     * @return {PluginDefinition} an object representing the plugin\n     */\n    static create(params) {\n        return {\n            name: 'microphone',\n            deferInit: params && params.deferInit ? params.deferInit : false,\n            params: params,\n            instance: MicrophonePlugin\n        };\n    }\n\n    constructor(params, ws) {\n        this.params = params;\n        this.wavesurfer = ws;\n\n        this.active = false;\n        this.paused = false;\n        this.browser = this.detectBrowser();\n        this.reloadBufferFunction = e => this.reloadBuffer(e);\n\n        // cross-browser getUserMedia\n        const promisifiedOldGUM = (\n            constraints,\n            successCallback,\n            errorCallback\n        ) => {\n            // get a hold of getUserMedia, if present\n            const getUserMedia =\n                navigator.getUserMedia ||\n                navigator.webkitGetUserMedia ||\n                navigator.mozGetUserMedia ||\n                navigator.msGetUserMedia;\n            // Some browsers just don't implement it - return a rejected\n            // promise with an error to keep a consistent interface\n            if (!getUserMedia) {\n                return Promise.reject(\n                    new Error('getUserMedia is not implemented in this browser')\n                );\n            }\n            // otherwise, wrap the call to the old navigator.getUserMedia with\n            // a Promise\n            return new Promise((successCallback, errorCallback) => {\n                getUserMedia.call(\n                    navigator,\n                    constraints,\n                    successCallback,\n                    errorCallback\n                );\n            });\n        };\n        // Older browsers might not implement mediaDevices at all, so we set an\n        // empty object first\n        if (navigator.mediaDevices === undefined) {\n            navigator.mediaDevices = {};\n        }\n        // Some browsers partially implement mediaDevices. We can't just assign\n        // an object with getUserMedia as it would overwrite existing\n        // properties. Here, we will just add the getUserMedia property if it's\n        // missing.\n        if (navigator.mediaDevices.getUserMedia === undefined) {\n            navigator.mediaDevices.getUserMedia = promisifiedOldGUM;\n        }\n        this.constraints = this.params.constraints || {\n            video: false,\n            audio: true\n        };\n        this.bufferSize = this.params.bufferSize || 4096;\n        this.numberOfInputChannels = this.params.numberOfInputChannels || 1;\n        this.numberOfOutputChannels = this.params.numberOfOutputChannels || 1;\n\n        this._onBackendCreated = () => {\n            // wavesurfer's AudioContext where we'll route the mic signal to\n            this.micContext = this.wavesurfer.backend.getAudioContext();\n        };\n    }\n\n    init() {\n        this.wavesurfer.on('backend-created', this._onBackendCreated);\n        if (this.wavesurfer.backend) {\n            this._onBackendCreated();\n        }\n    }\n\n    /**\n     * Destroy the microphone plugin.\n     */\n    destroy() {\n        // make sure the buffer is not redrawn during\n        // cleanup and demolition of this plugin.\n        this.paused = true;\n\n        this.wavesurfer.un('backend-created', this._onBackendCreated);\n        this.stop();\n    }\n\n    /**\n     * Allow user to select audio input device, e.g. microphone, and\n     * start the visualization.\n     */\n    start() {\n        navigator.mediaDevices\n            .getUserMedia(this.constraints)\n            .then(data => this.gotStream(data))\n            .catch(data => this.deviceError(data));\n    }\n\n    /**\n     * Pause/resume visualization.\n     */\n    togglePlay() {\n        if (!this.active) {\n            // start it first\n            this.start();\n        } else {\n            // toggle paused\n            this.paused = !this.paused;\n\n            if (this.paused) {\n                this.pause();\n            } else {\n                this.play();\n            }\n        }\n    }\n\n    /**\n     * Play visualization.\n     */\n    play() {\n        this.paused = false;\n\n        this.connect();\n    }\n\n    /**\n     * Pause visualization.\n     */\n    pause() {\n        this.paused = true;\n\n        // disconnect sources so they can be used elsewhere\n        // (eg. during audio playback)\n        this.disconnect();\n    }\n\n    /**\n     * Stop the device stream and remove any remaining waveform drawing from\n     * the wavesurfer canvas.\n     */\n    stop() {\n        if (this.active) {\n            // stop visualization and device\n            this.stopDevice();\n\n            // empty last frame\n            this.wavesurfer.empty();\n        }\n    }\n\n    /**\n     * Stop the device and the visualization.\n     */\n    stopDevice() {\n        this.active = false;\n\n        // stop visualization\n        this.disconnect();\n\n        // stop stream from device\n        if (this.stream) {\n            // MediaStream.stop is deprecated since:\n            // - Firefox 44 (https://www.fxsitecompat.com/en-US/docs/2015/mediastream-stop-has-been-deprecated/)\n            // - Chrome 45 (https://developers.google.com/web/updates/2015/07/mediastream-deprecations)\n            if (\n                (this.browser.browser === 'chrome' &&\n                    this.browser.version >= 45) ||\n                (this.browser.browser === 'firefox' &&\n                    this.browser.version >= 44) ||\n                this.browser.browser === 'edge' ||\n                this.browser.browser === 'safari'\n            ) {\n                if (this.stream.getTracks) {\n                    // note that this should not be a call\n                    this.stream.getTracks().forEach(stream => stream.stop());\n                    return;\n                }\n            }\n\n            this.stream.stop();\n        }\n    }\n\n    /**\n     * Connect the media sources that feed the visualization.\n     */\n    connect() {\n        if (this.stream !== undefined) {\n            // Create a local buffer for data to be copied to the Wavesurfer buffer for Edge\n            if (this.browser.browser === 'edge') {\n                this.localAudioBuffer = this.micContext.createBuffer(\n                    this.numberOfInputChannels,\n                    this.bufferSize,\n                    this.micContext.sampleRate\n                );\n            }\n\n            // Create an AudioNode from the stream.\n            this.mediaStreamSource = this.micContext.createMediaStreamSource(\n                this.stream\n            );\n\n            this.levelChecker = this.micContext.createScriptProcessor(\n                this.bufferSize,\n                this.numberOfInputChannels,\n                this.numberOfOutputChannels\n            );\n            this.mediaStreamSource.connect(this.levelChecker);\n\n            this.levelChecker.connect(this.micContext.destination);\n            this.levelChecker.onaudioprocess = this.reloadBufferFunction;\n        }\n    }\n\n    /**\n     * Disconnect the media sources that feed the visualization.\n     */\n    disconnect() {\n        if (this.mediaStreamSource !== undefined) {\n            this.mediaStreamSource.disconnect();\n        }\n\n        if (this.levelChecker !== undefined) {\n            this.levelChecker.disconnect();\n            this.levelChecker.onaudioprocess = undefined;\n        }\n\n        if (this.localAudioBuffer !== undefined) {\n            this.localAudioBuffer = undefined;\n        }\n    }\n\n    /**\n     * Redraw the waveform.\n     */\n    reloadBuffer(event) {\n        if (!this.paused) {\n            this.wavesurfer.empty();\n\n            if (this.browser.browser === 'edge') {\n                // copy audio data to a local audio buffer,\n                // from https://github.com/audiojs/audio-buffer-utils\n                let channel, l;\n                for (\n                    channel = 0,\n                        l = Math.min(\n                            this.localAudioBuffer.numberOfChannels,\n                            event.inputBuffer.numberOfChannels\n                        );\n                    channel < l;\n                    channel++\n                ) {\n                    this.localAudioBuffer\n                        .getChannelData(channel)\n                        .set(event.inputBuffer.getChannelData(channel));\n                }\n\n                this.wavesurfer.loadDecodedBuffer(this.localAudioBuffer);\n            } else {\n                this.wavesurfer.loadDecodedBuffer(event.inputBuffer);\n            }\n        }\n    }\n\n    /**\n     * Audio input device is ready.\n     *\n     * @param {LocalMediaStream} stream The microphone's media stream.\n     */\n    gotStream(stream) {\n        this.stream = stream;\n        this.active = true;\n\n        // start visualization\n        this.play();\n\n        // notify listeners\n        this.fireEvent('deviceReady', stream);\n    }\n\n    /**\n     * Device error callback.\n     */\n    deviceError(code) {\n        // notify listeners\n        this.fireEvent('deviceError', code);\n    }\n\n    /**\n     * Extract browser version out of the provided user agent string.\n     * @param {!string} uastring userAgent string.\n     * @param {!string} expr Regular expression used as match criteria.\n     * @param {!number} pos position in the version string to be returned.\n     * @return {!number} browser version.\n     */\n    extractVersion(uastring, expr, pos) {\n        const match = uastring.match(expr);\n        return match && match.length >= pos && parseInt(match[pos], 10);\n    }\n\n    /**\n     * Browser detector.\n     * @return {object} result containing browser, version and minVersion\n     *     properties.\n     */\n    detectBrowser() {\n        // Returned result object.\n        const result = {};\n        result.browser = null;\n        result.version = null;\n        result.minVersion = null;\n\n        // Non supported browser.\n        if (typeof window === 'undefined' || !window.navigator) {\n            result.browser = 'Not a supported browser.';\n            return result;\n        }\n\n        if (navigator.mozGetUserMedia) {\n            // Firefox\n            result.browser = 'firefox';\n            result.version = this.extractVersion(\n                navigator.userAgent,\n                /Firefox\\/(\\d+)\\./,\n                1\n            );\n            result.minVersion = 31;\n            return result;\n        } else if (navigator.webkitGetUserMedia) {\n            // Chrome/Chromium/Webview/Opera\n            result.browser = 'chrome';\n            result.version = this.extractVersion(\n                navigator.userAgent,\n                /Chrom(e|ium)\\/(\\d+)\\./,\n                2\n            );\n            result.minVersion = 38;\n            return result;\n        } else if (\n            navigator.mediaDevices &&\n            navigator.userAgent.match(/Edge\\/(\\d+).(\\d+)$/)\n        ) {\n            // Edge\n            result.browser = 'edge';\n            result.version = this.extractVersion(\n                navigator.userAgent,\n                /Edge\\/(\\d+).(\\d+)$/,\n                2\n            );\n            result.minVersion = 10547;\n            return result;\n        } else if (\n            window.RTCPeerConnection &&\n            navigator.userAgent.match(/AppleWebKit\\/(\\d+)\\./)\n        ) {\n            // Safari\n            result.browser = 'safari';\n            result.minVersion = 11;\n            result.version = this.extractVersion(\n                navigator.userAgent,\n                /AppleWebKit\\/(\\d+)\\./,\n                1\n            );\n            return result;\n        }\n\n        // Non supported browser default.\n        result.browser = 'Not a supported browser.';\n        return result;\n    }\n}\n"],"sourceRoot":""}
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.microphone.min.js
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.microphone.min.js	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.microphone.min.js	(revision 33546)
@@ -0,0 +1,2 @@
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("microphone",[],t):"object"==typeof exports?exports.microphone=t():(e.WaveSurfer=e.WaveSurfer||{},e.WaveSurfer.microphone=t())}(window,(function(){return function(e){var t={};function r(i){if(t[i])return t[i].exports;var n=t[i]={i:i,l:!1,exports:{}};return e[i].call(n.exports,n,n.exports,r),n.l=!0,n.exports}return r.m=e,r.c=t,r.d=function(e,t,i){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(r.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)r.d(i,n,function(t){return e[t]}.bind(null,n));return i},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="localhost:8080/dist/plugin/",r(r.s=5)}({5:function(e,t,r){"use strict";function i(e,t){for(var r=0;r<t.length;r++){var i=t[r];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}function n(e,t,r){return t&&i(e.prototype,t),r&&i(e,r),e}Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o=function(){function e(t,r){var i=this;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.params=t,this.wavesurfer=r,this.active=!1,this.paused=!1,this.browser=this.detectBrowser(),this.reloadBufferFunction=function(e){return i.reloadBuffer(e)};void 0===navigator.mediaDevices&&(navigator.mediaDevices={}),void 0===navigator.mediaDevices.getUserMedia&&(navigator.mediaDevices.getUserMedia=function(e,t,r){var i=navigator.getUserMedia||navigator.webkitGetUserMedia||navigator.mozGetUserMedia||navigator.msGetUserMedia;return i?new Promise((function(t,r){i.call(navigator,e,t,r)})):Promise.reject(new Error("getUserMedia is not implemented in this browser"))}),this.constraints=this.params.constraints||{video:!1,audio:!0},this.bufferSize=this.params.bufferSize||4096,this.numberOfInputChannels=this.params.numberOfInputChannels||1,this.numberOfOutputChannels=this.params.numberOfOutputChannels||1,this._onBackendCreated=function(){i.micContext=i.wavesurfer.backend.getAudioContext()}}return n(e,null,[{key:"create",value:function(t){return{name:"microphone",deferInit:!(!t||!t.deferInit)&&t.deferInit,params:t,instance:e}}}]),n(e,[{key:"init",value:function(){this.wavesurfer.on("backend-created",this._onBackendCreated),this.wavesurfer.backend&&this._onBackendCreated()}},{key:"destroy",value:function(){this.paused=!0,this.wavesurfer.un("backend-created",this._onBackendCreated),this.stop()}},{key:"start",value:function(){var e=this;navigator.mediaDevices.getUserMedia(this.constraints).then((function(t){return e.gotStream(t)})).catch((function(t){return e.deviceError(t)}))}},{key:"togglePlay",value:function(){this.active?(this.paused=!this.paused,this.paused?this.pause():this.play()):this.start()}},{key:"play",value:function(){this.paused=!1,this.connect()}},{key:"pause",value:function(){this.paused=!0,this.disconnect()}},{key:"stop",value:function(){this.active&&(this.stopDevice(),this.wavesurfer.empty())}},{key:"stopDevice",value:function(){if(this.active=!1,this.disconnect(),this.stream){if(("chrome"===this.browser.browser&&this.browser.version>=45||"firefox"===this.browser.browser&&this.browser.version>=44||"edge"===this.browser.browser||"safari"===this.browser.browser)&&this.stream.getTracks)return void this.stream.getTracks().forEach((function(e){return e.stop()}));this.stream.stop()}}},{key:"connect",value:function(){void 0!==this.stream&&("edge"===this.browser.browser&&(this.localAudioBuffer=this.micContext.createBuffer(this.numberOfInputChannels,this.bufferSize,this.micContext.sampleRate)),this.mediaStreamSource=this.micContext.createMediaStreamSource(this.stream),this.levelChecker=this.micContext.createScriptProcessor(this.bufferSize,this.numberOfInputChannels,this.numberOfOutputChannels),this.mediaStreamSource.connect(this.levelChecker),this.levelChecker.connect(this.micContext.destination),this.levelChecker.onaudioprocess=this.reloadBufferFunction)}},{key:"disconnect",value:function(){void 0!==this.mediaStreamSource&&this.mediaStreamSource.disconnect(),void 0!==this.levelChecker&&(this.levelChecker.disconnect(),this.levelChecker.onaudioprocess=void 0),void 0!==this.localAudioBuffer&&(this.localAudioBuffer=void 0)}},{key:"reloadBuffer",value:function(e){if(!this.paused)if(this.wavesurfer.empty(),"edge"===this.browser.browser){var t,r;for(t=0,r=Math.min(this.localAudioBuffer.numberOfChannels,e.inputBuffer.numberOfChannels);t<r;t++)this.localAudioBuffer.getChannelData(t).set(e.inputBuffer.getChannelData(t));this.wavesurfer.loadDecodedBuffer(this.localAudioBuffer)}else this.wavesurfer.loadDecodedBuffer(e.inputBuffer)}},{key:"gotStream",value:function(e){this.stream=e,this.active=!0,this.play(),this.fireEvent("deviceReady",e)}},{key:"deviceError",value:function(e){this.fireEvent("deviceError",e)}},{key:"extractVersion",value:function(e,t,r){var i=e.match(t);return i&&i.length>=r&&parseInt(i[r],10)}},{key:"detectBrowser",value:function(){var e={browser:null,version:null,minVersion:null};return"undefined"!=typeof window&&window.navigator?navigator.mozGetUserMedia?(e.browser="firefox",e.version=this.extractVersion(navigator.userAgent,/Firefox\/(\d+)\./,1),e.minVersion=31,e):navigator.webkitGetUserMedia?(e.browser="chrome",e.version=this.extractVersion(navigator.userAgent,/Chrom(e|ium)\/(\d+)\./,2),e.minVersion=38,e):navigator.mediaDevices&&navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)?(e.browser="edge",e.version=this.extractVersion(navigator.userAgent,/Edge\/(\d+).(\d+)$/,2),e.minVersion=10547,e):window.RTCPeerConnection&&navigator.userAgent.match(/AppleWebKit\/(\d+)\./)?(e.browser="safari",e.minVersion=11,e.version=this.extractVersion(navigator.userAgent,/AppleWebKit\/(\d+)\./,1),e):(e.browser="Not a supported browser.",e):(e.browser="Not a supported browser.",e)}}]),e}();t.default=o,e.exports=t.default}})}));
+//# sourceMappingURL=wavesurfer.microphone.min.js.map
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.microphone.min.js.map
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.microphone.min.js.map	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.microphone.min.js.map	(revision 33546)
@@ -0,0 +1,1 @@
+{"version":3,"sources":["webpack://WaveSurfer.[name]/webpack/universalModuleDefinition","webpack://WaveSurfer.[name]/webpack/bootstrap","webpack://WaveSurfer.[name]/./src/plugin/microphone.js"],"names":["root","factory","exports","module","define","amd","window","installedModules","__webpack_require__","moduleId","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","MicrophonePlugin","params","ws","this","wavesurfer","active","paused","browser","detectBrowser","reloadBufferFunction","e","reloadBuffer","undefined","navigator","mediaDevices","getUserMedia","constraints","successCallback","errorCallback","webkitGetUserMedia","mozGetUserMedia","msGetUserMedia","Promise","reject","Error","video","audio","bufferSize","numberOfInputChannels","numberOfOutputChannels","_onBackendCreated","micContext","backend","getAudioContext","deferInit","instance","on","un","stop","then","data","gotStream","catch","deviceError","pause","play","start","connect","disconnect","stopDevice","empty","stream","version","getTracks","forEach","localAudioBuffer","createBuffer","sampleRate","mediaStreamSource","createMediaStreamSource","levelChecker","createScriptProcessor","destination","onaudioprocess","event","channel","Math","min","numberOfChannels","inputBuffer","getChannelData","set","loadDecodedBuffer","fireEvent","code","uastring","expr","pos","match","length","parseInt","result","extractVersion","userAgent","minVersion","RTCPeerConnection"],"mappings":"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","file":"wavesurfer.microphone.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"microphone\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"microphone\"] = factory();\n\telse\n\t\troot[\"WaveSurfer\"] = root[\"WaveSurfer\"] || {}, root[\"WaveSurfer\"][\"microphone\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"localhost:8080/dist/plugin/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 5);\n","/**\n * @typedef {Object} MicrophonePluginParams\n * @property {MediaStreamConstraints} constraints The constraints parameter is a\n * MediaStreamConstaints object with two members: video and audio, describing\n * the media types requested. Either or both must be specified.\n * @property {number} bufferSize=4096 The buffer size in units of sample-frames.\n * If specified, the bufferSize must be one of the following values: `256`,\n * `512`, `1024`, `2048`, `4096`, `8192`, `16384`\n * @property {number} numberOfInputChannels=1 Integer specifying the number of\n * channels for this node's input. Values of up to 32 are supported.\n * @property {?boolean} deferInit Set to true to manually call\n * `initPlugin('microphone')`\n */\n\n/**\n * Visualize microphone input in a wavesurfer instance.\n *\n * @implements {PluginClass}\n * @extends {Observer}\n * @example\n * // es6\n * import MicrophonePlugin from 'wavesurfer.microphone.js';\n *\n * // commonjs\n * var MicrophonePlugin = require('wavesurfer.microphone.js');\n *\n * // if you are using <script> tags\n * var MicrophonePlugin = window.WaveSurfer.microphone;\n *\n * // ... initialising wavesurfer with the plugin\n * var wavesurfer = WaveSurfer.create({\n *   // wavesurfer options ...\n *   plugins: [\n *     MicrophonePlugin.create({\n *       // plugin options ...\n *     })\n *   ]\n * });\n */\nexport default class MicrophonePlugin {\n    /**\n     * Microphone plugin definition factory\n     *\n     * This function must be used to create a plugin definition which can be\n     * used by wavesurfer to correctly instantiate the plugin.\n     *\n     * @param  {MicrophonePluginParams} params parameters use to initialise the plugin\n     * @return {PluginDefinition} an object representing the plugin\n     */\n    static create(params) {\n        return {\n            name: 'microphone',\n            deferInit: params && params.deferInit ? params.deferInit : false,\n            params: params,\n            instance: MicrophonePlugin\n        };\n    }\n\n    constructor(params, ws) {\n        this.params = params;\n        this.wavesurfer = ws;\n\n        this.active = false;\n        this.paused = false;\n        this.browser = this.detectBrowser();\n        this.reloadBufferFunction = e => this.reloadBuffer(e);\n\n        // cross-browser getUserMedia\n        const promisifiedOldGUM = (\n            constraints,\n            successCallback,\n            errorCallback\n        ) => {\n            // get a hold of getUserMedia, if present\n            const getUserMedia =\n                navigator.getUserMedia ||\n                navigator.webkitGetUserMedia ||\n                navigator.mozGetUserMedia ||\n                navigator.msGetUserMedia;\n            // Some browsers just don't implement it - return a rejected\n            // promise with an error to keep a consistent interface\n            if (!getUserMedia) {\n                return Promise.reject(\n                    new Error('getUserMedia is not implemented in this browser')\n                );\n            }\n            // otherwise, wrap the call to the old navigator.getUserMedia with\n            // a Promise\n            return new Promise((successCallback, errorCallback) => {\n                getUserMedia.call(\n                    navigator,\n                    constraints,\n                    successCallback,\n                    errorCallback\n                );\n            });\n        };\n        // Older browsers might not implement mediaDevices at all, so we set an\n        // empty object first\n        if (navigator.mediaDevices === undefined) {\n            navigator.mediaDevices = {};\n        }\n        // Some browsers partially implement mediaDevices. We can't just assign\n        // an object with getUserMedia as it would overwrite existing\n        // properties. Here, we will just add the getUserMedia property if it's\n        // missing.\n        if (navigator.mediaDevices.getUserMedia === undefined) {\n            navigator.mediaDevices.getUserMedia = promisifiedOldGUM;\n        }\n        this.constraints = this.params.constraints || {\n            video: false,\n            audio: true\n        };\n        this.bufferSize = this.params.bufferSize || 4096;\n        this.numberOfInputChannels = this.params.numberOfInputChannels || 1;\n        this.numberOfOutputChannels = this.params.numberOfOutputChannels || 1;\n\n        this._onBackendCreated = () => {\n            // wavesurfer's AudioContext where we'll route the mic signal to\n            this.micContext = this.wavesurfer.backend.getAudioContext();\n        };\n    }\n\n    init() {\n        this.wavesurfer.on('backend-created', this._onBackendCreated);\n        if (this.wavesurfer.backend) {\n            this._onBackendCreated();\n        }\n    }\n\n    /**\n     * Destroy the microphone plugin.\n     */\n    destroy() {\n        // make sure the buffer is not redrawn during\n        // cleanup and demolition of this plugin.\n        this.paused = true;\n\n        this.wavesurfer.un('backend-created', this._onBackendCreated);\n        this.stop();\n    }\n\n    /**\n     * Allow user to select audio input device, e.g. microphone, and\n     * start the visualization.\n     */\n    start() {\n        navigator.mediaDevices\n            .getUserMedia(this.constraints)\n            .then(data => this.gotStream(data))\n            .catch(data => this.deviceError(data));\n    }\n\n    /**\n     * Pause/resume visualization.\n     */\n    togglePlay() {\n        if (!this.active) {\n            // start it first\n            this.start();\n        } else {\n            // toggle paused\n            this.paused = !this.paused;\n\n            if (this.paused) {\n                this.pause();\n            } else {\n                this.play();\n            }\n        }\n    }\n\n    /**\n     * Play visualization.\n     */\n    play() {\n        this.paused = false;\n\n        this.connect();\n    }\n\n    /**\n     * Pause visualization.\n     */\n    pause() {\n        this.paused = true;\n\n        // disconnect sources so they can be used elsewhere\n        // (eg. during audio playback)\n        this.disconnect();\n    }\n\n    /**\n     * Stop the device stream and remove any remaining waveform drawing from\n     * the wavesurfer canvas.\n     */\n    stop() {\n        if (this.active) {\n            // stop visualization and device\n            this.stopDevice();\n\n            // empty last frame\n            this.wavesurfer.empty();\n        }\n    }\n\n    /**\n     * Stop the device and the visualization.\n     */\n    stopDevice() {\n        this.active = false;\n\n        // stop visualization\n        this.disconnect();\n\n        // stop stream from device\n        if (this.stream) {\n            // MediaStream.stop is deprecated since:\n            // - Firefox 44 (https://www.fxsitecompat.com/en-US/docs/2015/mediastream-stop-has-been-deprecated/)\n            // - Chrome 45 (https://developers.google.com/web/updates/2015/07/mediastream-deprecations)\n            if (\n                (this.browser.browser === 'chrome' &&\n                    this.browser.version >= 45) ||\n                (this.browser.browser === 'firefox' &&\n                    this.browser.version >= 44) ||\n                this.browser.browser === 'edge' ||\n                this.browser.browser === 'safari'\n            ) {\n                if (this.stream.getTracks) {\n                    // note that this should not be a call\n                    this.stream.getTracks().forEach(stream => stream.stop());\n                    return;\n                }\n            }\n\n            this.stream.stop();\n        }\n    }\n\n    /**\n     * Connect the media sources that feed the visualization.\n     */\n    connect() {\n        if (this.stream !== undefined) {\n            // Create a local buffer for data to be copied to the Wavesurfer buffer for Edge\n            if (this.browser.browser === 'edge') {\n                this.localAudioBuffer = this.micContext.createBuffer(\n                    this.numberOfInputChannels,\n                    this.bufferSize,\n                    this.micContext.sampleRate\n                );\n            }\n\n            // Create an AudioNode from the stream.\n            this.mediaStreamSource = this.micContext.createMediaStreamSource(\n                this.stream\n            );\n\n            this.levelChecker = this.micContext.createScriptProcessor(\n                this.bufferSize,\n                this.numberOfInputChannels,\n                this.numberOfOutputChannels\n            );\n            this.mediaStreamSource.connect(this.levelChecker);\n\n            this.levelChecker.connect(this.micContext.destination);\n            this.levelChecker.onaudioprocess = this.reloadBufferFunction;\n        }\n    }\n\n    /**\n     * Disconnect the media sources that feed the visualization.\n     */\n    disconnect() {\n        if (this.mediaStreamSource !== undefined) {\n            this.mediaStreamSource.disconnect();\n        }\n\n        if (this.levelChecker !== undefined) {\n            this.levelChecker.disconnect();\n            this.levelChecker.onaudioprocess = undefined;\n        }\n\n        if (this.localAudioBuffer !== undefined) {\n            this.localAudioBuffer = undefined;\n        }\n    }\n\n    /**\n     * Redraw the waveform.\n     */\n    reloadBuffer(event) {\n        if (!this.paused) {\n            this.wavesurfer.empty();\n\n            if (this.browser.browser === 'edge') {\n                // copy audio data to a local audio buffer,\n                // from https://github.com/audiojs/audio-buffer-utils\n                let channel, l;\n                for (\n                    channel = 0,\n                        l = Math.min(\n                            this.localAudioBuffer.numberOfChannels,\n                            event.inputBuffer.numberOfChannels\n                        );\n                    channel < l;\n                    channel++\n                ) {\n                    this.localAudioBuffer\n                        .getChannelData(channel)\n                        .set(event.inputBuffer.getChannelData(channel));\n                }\n\n                this.wavesurfer.loadDecodedBuffer(this.localAudioBuffer);\n            } else {\n                this.wavesurfer.loadDecodedBuffer(event.inputBuffer);\n            }\n        }\n    }\n\n    /**\n     * Audio input device is ready.\n     *\n     * @param {LocalMediaStream} stream The microphone's media stream.\n     */\n    gotStream(stream) {\n        this.stream = stream;\n        this.active = true;\n\n        // start visualization\n        this.play();\n\n        // notify listeners\n        this.fireEvent('deviceReady', stream);\n    }\n\n    /**\n     * Device error callback.\n     */\n    deviceError(code) {\n        // notify listeners\n        this.fireEvent('deviceError', code);\n    }\n\n    /**\n     * Extract browser version out of the provided user agent string.\n     * @param {!string} uastring userAgent string.\n     * @param {!string} expr Regular expression used as match criteria.\n     * @param {!number} pos position in the version string to be returned.\n     * @return {!number} browser version.\n     */\n    extractVersion(uastring, expr, pos) {\n        const match = uastring.match(expr);\n        return match && match.length >= pos && parseInt(match[pos], 10);\n    }\n\n    /**\n     * Browser detector.\n     * @return {object} result containing browser, version and minVersion\n     *     properties.\n     */\n    detectBrowser() {\n        // Returned result object.\n        const result = {};\n        result.browser = null;\n        result.version = null;\n        result.minVersion = null;\n\n        // Non supported browser.\n        if (typeof window === 'undefined' || !window.navigator) {\n            result.browser = 'Not a supported browser.';\n            return result;\n        }\n\n        if (navigator.mozGetUserMedia) {\n            // Firefox\n            result.browser = 'firefox';\n            result.version = this.extractVersion(\n                navigator.userAgent,\n                /Firefox\\/(\\d+)\\./,\n                1\n            );\n            result.minVersion = 31;\n            return result;\n        } else if (navigator.webkitGetUserMedia) {\n            // Chrome/Chromium/Webview/Opera\n            result.browser = 'chrome';\n            result.version = this.extractVersion(\n                navigator.userAgent,\n                /Chrom(e|ium)\\/(\\d+)\\./,\n                2\n            );\n            result.minVersion = 38;\n            return result;\n        } else if (\n            navigator.mediaDevices &&\n            navigator.userAgent.match(/Edge\\/(\\d+).(\\d+)$/)\n        ) {\n            // Edge\n            result.browser = 'edge';\n            result.version = this.extractVersion(\n                navigator.userAgent,\n                /Edge\\/(\\d+).(\\d+)$/,\n                2\n            );\n            result.minVersion = 10547;\n            return result;\n        } else if (\n            window.RTCPeerConnection &&\n            navigator.userAgent.match(/AppleWebKit\\/(\\d+)\\./)\n        ) {\n            // Safari\n            result.browser = 'safari';\n            result.minVersion = 11;\n            result.version = this.extractVersion(\n                navigator.userAgent,\n                /AppleWebKit\\/(\\d+)\\./,\n                1\n            );\n            return result;\n        }\n\n        // Non supported browser default.\n        result.browser = 'Not a supported browser.';\n        return result;\n    }\n}\n"],"sourceRoot":""}
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.minimap.js
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.minimap.js	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.minimap.js	(revision 33546)
@@ -0,0 +1,521 @@
+/*!
+ * wavesurfer.js minimap plugin 2.2.1 (2019-09-30)
+ * https://github.com/katspaugh/wavesurfer.js
+ * @license BSD-3-Clause
+ */
+(function webpackUniversalModuleDefinition(root, factory) {
+	if(typeof exports === 'object' && typeof module === 'object')
+		module.exports = factory();
+	else if(typeof define === 'function' && define.amd)
+		define("minimap", [], factory);
+	else if(typeof exports === 'object')
+		exports["minimap"] = factory();
+	else
+		root["WaveSurfer"] = root["WaveSurfer"] || {}, root["WaveSurfer"]["minimap"] = factory();
+})(window, function() {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+/******/
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId]) {
+/******/ 			return installedModules[moduleId].exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			i: moduleId,
+/******/ 			l: false,
+/******/ 			exports: {}
+/******/ 		};
+/******/
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ 		// Flag the module as loaded
+/******/ 		module.l = true;
+/******/
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/
+/******/
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+/******/
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+/******/
+/******/ 	// define getter function for harmony exports
+/******/ 	__webpack_require__.d = function(exports, name, getter) {
+/******/ 		if(!__webpack_require__.o(exports, name)) {
+/******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
+/******/ 		}
+/******/ 	};
+/******/
+/******/ 	// define __esModule on exports
+/******/ 	__webpack_require__.r = function(exports) {
+/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ 		}
+/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
+/******/ 	};
+/******/
+/******/ 	// create a fake namespace object
+/******/ 	// mode & 1: value is a module id, require it
+/******/ 	// mode & 2: merge all properties of value into the ns
+/******/ 	// mode & 4: return value when already ns object
+/******/ 	// mode & 8|1: behave like require
+/******/ 	__webpack_require__.t = function(value, mode) {
+/******/ 		if(mode & 1) value = __webpack_require__(value);
+/******/ 		if(mode & 8) return value;
+/******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
+/******/ 		var ns = Object.create(null);
+/******/ 		__webpack_require__.r(ns);
+/******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
+/******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
+/******/ 		return ns;
+/******/ 	};
+/******/
+/******/ 	// getDefaultExport function for compatibility with non-harmony modules
+/******/ 	__webpack_require__.n = function(module) {
+/******/ 		var getter = module && module.__esModule ?
+/******/ 			function getDefault() { return module['default']; } :
+/******/ 			function getModuleExports() { return module; };
+/******/ 		__webpack_require__.d(getter, 'a', getter);
+/******/ 		return getter;
+/******/ 	};
+/******/
+/******/ 	// Object.prototype.hasOwnProperty.call
+/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "localhost:8080/dist/plugin/";
+/******/
+/******/
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(__webpack_require__.s = "./src/plugin/minimap.js");
+/******/ })
+/************************************************************************/
+/******/ ({
+
+/***/ "./src/plugin/minimap.js":
+/*!*******************************!*\
+  !*** ./src/plugin/minimap.js ***!
+  \*******************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+/**
+ * @typedef {Object} MinimapPluginParams
+ * @desc Extends the `WavesurferParams` wavesurfer was initialised with
+ * @property {?string|HTMLElement} container CSS selector or HTML element where
+ * the map should be rendered. By default it is simply appended
+ * after the waveform.
+ * @property {?boolean} deferInit Set to true to manually call
+ * `initPlugin('minimap')`
+ */
+
+/**
+ * Renders a smaller version waveform as a minimap of the main waveform.
+ *
+ * @implements {PluginClass}
+ * @extends {Observer}
+ * @example
+ * // es6
+ * import MinimapPlugin from 'wavesurfer.minimap.js';
+ *
+ * // commonjs
+ * var MinimapPlugin = require('wavesurfer.minimap.js');
+ *
+ * // if you are using <script> tags
+ * var MinimapPlugin = window.WaveSurfer.minimap;
+ *
+ * // ... initialising wavesurfer with the plugin
+ * var wavesurfer = WaveSurfer.create({
+ *   // wavesurfer options ...
+ *   plugins: [
+ *     MinimapPlugin.create({
+ *       // plugin options ...
+ *     })
+ *   ]
+ * });
+ */
+var MinimapPlugin =
+/*#__PURE__*/
+function () {
+  _createClass(MinimapPlugin, null, [{
+    key: "create",
+
+    /**
+     * Minimap plugin definition factory
+     *
+     * This function must be used to create a plugin definition which can be
+     * used by wavesurfer to correctly instantiate the plugin.
+     *
+     * @param  {MinimapPluginParams} params parameters use to initialise the plugin
+     * @return {PluginDefinition} an object representing the plugin
+     */
+    value: function create(params) {
+      return {
+        name: 'minimap',
+        deferInit: params && params.deferInit ? params.deferInit : false,
+        params: params,
+        staticProps: {
+          initMinimap: function initMinimap(customConfig) {
+            console.warn('Deprecated initMinimap!');
+            params = customConfig;
+            this.initPlugins('minimap');
+          }
+        },
+        instance: MinimapPlugin
+      };
+    }
+  }]);
+
+  function MinimapPlugin(params, ws) {
+    var _this = this;
+
+    _classCallCheck(this, MinimapPlugin);
+
+    this.params = ws.util.extend({}, ws.params, {
+      showRegions: false,
+      showOverview: false,
+      overviewBorderColor: 'green',
+      overviewBorderSize: 2,
+      // the container should be different
+      container: false,
+      height: Math.max(Math.round(ws.params.height / 4), 20)
+    }, params, {
+      scrollParent: false,
+      fillParent: true
+    }); // if container is a selector, get the element
+
+    if (typeof params.container === 'string') {
+      var el = document.querySelector(params.container);
+
+      if (!el) {
+        console.warn("Wavesurfer minimap container ".concat(params.container, " was not found! The minimap will be automatically appended below the waveform."));
+      }
+
+      this.params.container = el;
+    } // if no container is specified add a new element and insert it
+
+
+    if (!params.container) {
+      this.params.container = ws.util.style(document.createElement('minimap'), {
+        display: 'block'
+      });
+    }
+
+    this.drawer = new ws.Drawer(this.params.container, this.params);
+    this.wavesurfer = ws;
+    this.util = ws.util;
+    /**
+     * Minimap needs to register to ready and waveform-ready events to
+     * work with MediaElement, the time when ready is called is different
+     * (peaks can not be got)
+     *
+     * @type {string}
+     * @see https://github.com/katspaugh/wavesurfer.js/issues/736
+     */
+
+    this.renderEvent = ws.params.backend === 'MediaElement' ? 'waveform-ready' : 'ready';
+    this.overviewRegion = null;
+    this.drawer.createWrapper();
+    this.createElements();
+    var isInitialised = false; // ws ready event listener
+
+    this._onShouldRender = function () {
+      // only bind the events in the first run
+      if (!isInitialised) {
+        _this.bindWavesurferEvents();
+
+        _this.bindMinimapEvents();
+
+        isInitialised = true;
+      } // if there is no such element, append it to the container (below
+      // the waveform)
+
+
+      if (!document.body.contains(_this.params.container)) {
+        ws.container.insertBefore(_this.params.container, null);
+      }
+
+      if (_this.wavesurfer.regions && _this.params.showRegions) {
+        _this.regions();
+      }
+
+      _this.render();
+    };
+
+    this._onAudioprocess = function (currentTime) {
+      _this.drawer.progress(_this.wavesurfer.backend.getPlayedPercents());
+    }; // ws seek event listener
+
+
+    this._onSeek = function () {
+      return _this.drawer.progress(ws.backend.getPlayedPercents());
+    }; // event listeners for the overview region
+
+
+    this._onScroll = function (e) {
+      if (!_this.draggingOverview) {
+        _this.moveOverviewRegion(e.target.scrollLeft / _this.ratio);
+      }
+    };
+
+    this._onMouseover = function (e) {
+      if (_this.draggingOverview) {
+        _this.draggingOverview = false;
+      }
+    };
+
+    var prevWidth = 0;
+    this._onResize = ws.util.debounce(function () {
+      if (prevWidth != _this.drawer.wrapper.clientWidth) {
+        prevWidth = _this.drawer.wrapper.clientWidth;
+
+        _this.render();
+
+        _this.drawer.progress(_this.wavesurfer.backend.getPlayedPercents());
+      }
+    });
+
+    this._onZoom = function (e) {
+      _this.render();
+    };
+
+    this.wavesurfer.on('zoom', this._onZoom);
+  }
+
+  _createClass(MinimapPlugin, [{
+    key: "init",
+    value: function init() {
+      if (this.wavesurfer.isReady) {
+        this._onShouldRender();
+      }
+
+      this.wavesurfer.on(this.renderEvent, this._onShouldRender);
+    }
+  }, {
+    key: "destroy",
+    value: function destroy() {
+      window.removeEventListener('resize', this._onResize, true);
+      window.removeEventListener('orientationchange', this._onResize, true);
+      this.wavesurfer.drawer.wrapper.removeEventListener('mouseover', this._onMouseover);
+      this.wavesurfer.un(this.renderEvent, this._onShouldRender);
+      this.wavesurfer.un('seek', this._onSeek);
+      this.wavesurfer.un('scroll', this._onScroll);
+      this.wavesurfer.un('audioprocess', this._onAudioprocess);
+      this.wavesurfer.un('zoom', this._onZoom);
+      this.drawer.destroy();
+      this.overviewRegion = null;
+      this.unAll();
+    }
+  }, {
+    key: "regions",
+    value: function regions() {
+      var _this2 = this;
+
+      this.regions = {};
+      this.wavesurfer.on('region-created', function (region) {
+        _this2.regions[region.id] = region;
+
+        _this2.renderRegions();
+      });
+      this.wavesurfer.on('region-updated', function (region) {
+        _this2.regions[region.id] = region;
+
+        _this2.renderRegions();
+      });
+      this.wavesurfer.on('region-removed', function (region) {
+        delete _this2.regions[region.id];
+
+        _this2.renderRegions();
+      });
+    }
+  }, {
+    key: "renderRegions",
+    value: function renderRegions() {
+      var _this3 = this;
+
+      var regionElements = this.drawer.wrapper.querySelectorAll('region');
+      var i;
+
+      for (i = 0; i < regionElements.length; ++i) {
+        this.drawer.wrapper.removeChild(regionElements[i]);
+      }
+
+      Object.keys(this.regions).forEach(function (id) {
+        var region = _this3.regions[id];
+
+        var width = _this3.drawer.width * ((region.end - region.start) / _this3.wavesurfer.getDuration());
+
+        var left = _this3.drawer.width * (region.start / _this3.wavesurfer.getDuration());
+
+        var regionElement = _this3.util.style(document.createElement('region'), {
+          height: 'inherit',
+          backgroundColor: region.color,
+          width: width + 'px',
+          left: left + 'px',
+          display: 'block',
+          position: 'absolute'
+        });
+
+        regionElement.classList.add(id);
+
+        _this3.drawer.wrapper.appendChild(regionElement);
+      });
+    }
+  }, {
+    key: "createElements",
+    value: function createElements() {
+      this.drawer.createElements();
+
+      if (this.params.showOverview) {
+        this.overviewRegion = this.util.style(document.createElement('overview'), {
+          top: 0,
+          bottom: 0,
+          width: '0px',
+          display: 'block',
+          position: 'absolute',
+          cursor: 'move',
+          border: this.params.overviewBorderSize + 'px solid ' + this.params.overviewBorderColor,
+          zIndex: 2,
+          opacity: this.params.overviewOpacity
+        });
+        this.drawer.wrapper.appendChild(this.overviewRegion);
+      }
+    }
+  }, {
+    key: "bindWavesurferEvents",
+    value: function bindWavesurferEvents() {
+      window.addEventListener('resize', this._onResize, true);
+      window.addEventListener('orientationchange', this._onResize, true);
+      this.wavesurfer.on('audioprocess', this._onAudioprocess);
+      this.wavesurfer.on('seek', this._onSeek);
+
+      if (this.params.showOverview) {
+        this.wavesurfer.on('scroll', this._onScroll);
+        this.wavesurfer.drawer.wrapper.addEventListener('mouseover', this._onMouseover);
+      }
+    }
+  }, {
+    key: "bindMinimapEvents",
+    value: function bindMinimapEvents() {
+      var _this4 = this;
+
+      var positionMouseDown = {
+        clientX: 0,
+        clientY: 0
+      };
+      var relativePositionX = 0;
+      var seek = true; // the following event listeners will be destroyed by using
+      // this.unAll() and nullifying the DOM node references after
+      // removing them
+
+      if (this.params.interact) {
+        this.drawer.wrapper.addEventListener('click', function (event) {
+          _this4.fireEvent('click', event, _this4.drawer.handleEvent(event));
+        });
+        this.on('click', function (event, position) {
+          if (seek) {
+            _this4.drawer.progress(position);
+
+            _this4.wavesurfer.seekAndCenter(position);
+          } else {
+            seek = true;
+          }
+        });
+      }
+
+      if (this.params.showOverview) {
+        this.overviewRegion.addEventListener('mousedown', function (event) {
+          _this4.draggingOverview = true;
+          relativePositionX = event.layerX;
+          positionMouseDown.clientX = event.clientX;
+          positionMouseDown.clientY = event.clientY;
+        });
+        this.drawer.wrapper.addEventListener('mousemove', function (event) {
+          if (_this4.draggingOverview) {
+            _this4.moveOverviewRegion(event.clientX - _this4.drawer.container.getBoundingClientRect().left - relativePositionX);
+          }
+        });
+        this.drawer.wrapper.addEventListener('mouseup', function (event) {
+          if (positionMouseDown.clientX - event.clientX === 0 && positionMouseDown.clientX - event.clientX === 0) {
+            seek = true;
+            _this4.draggingOverview = false;
+          } else if (_this4.draggingOverview) {
+            seek = false;
+            _this4.draggingOverview = false;
+          }
+        });
+      }
+    }
+  }, {
+    key: "render",
+    value: function render() {
+      var len = this.drawer.getWidth();
+      var peaks = this.wavesurfer.backend.getPeaks(len, 0, len);
+      this.drawer.drawPeaks(peaks, len, 0, len);
+      this.drawer.progress(this.wavesurfer.backend.getPlayedPercents());
+
+      if (this.params.showOverview) {
+        //get proportional width of overview region considering the respective
+        //width of the drawers
+        this.ratio = this.wavesurfer.drawer.width / this.drawer.width;
+        this.waveShowedWidth = this.wavesurfer.drawer.width / this.ratio;
+        this.waveWidth = this.wavesurfer.drawer.width;
+        this.overviewWidth = this.drawer.container.offsetWidth / this.ratio;
+        this.overviewPosition = 0;
+        this.moveOverviewRegion(this.wavesurfer.drawer.wrapper.scrollLeft / this.ratio);
+        this.overviewRegion.style.width = this.overviewWidth + 'px';
+      }
+    }
+  }, {
+    key: "moveOverviewRegion",
+    value: function moveOverviewRegion(pixels) {
+      if (pixels < 0) {
+        this.overviewPosition = 0;
+      } else if (pixels + this.overviewWidth < this.drawer.container.offsetWidth) {
+        this.overviewPosition = pixels;
+      } else {
+        this.overviewPosition = this.drawer.container.offsetWidth - this.overviewWidth;
+      }
+
+      this.overviewRegion.style.left = this.overviewPosition + 'px';
+
+      if (this.draggingOverview) {
+        this.wavesurfer.drawer.wrapper.scrollLeft = this.overviewPosition * this.ratio;
+      }
+    }
+  }]);
+
+  return MinimapPlugin;
+}();
+
+exports.default = MinimapPlugin;
+module.exports = exports.default;
+
+/***/ })
+
+/******/ });
+});
+//# sourceMappingURL=wavesurfer.minimap.js.map
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.minimap.js.map
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.minimap.js.map	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.minimap.js.map	(revision 33546)
@@ -0,0 +1,1 @@
+{"version":3,"sources":["webpack://WaveSurfer.[name]/webpack/universalModuleDefinition","webpack://WaveSurfer.[name]/webpack/bootstrap","webpack://WaveSurfer.[name]/./src/plugin/minimap.js"],"names":["MinimapPlugin","params","name","deferInit","staticProps","initMinimap","customConfig","console","warn","initPlugins","instance","ws","util","extend","showRegions","showOverview","overviewBorderColor","overviewBorderSize","container","height","Math","max","round","scrollParent","fillParent","el","document","querySelector","style","createElement","display","drawer","Drawer","wavesurfer","renderEvent","backend","overviewRegion","createWrapper","createElements","isInitialised","_onShouldRender","bindWavesurferEvents","bindMinimapEvents","body","contains","insertBefore","regions","render","_onAudioprocess","currentTime","progress","getPlayedPercents","_onSeek","_onScroll","e","draggingOverview","moveOverviewRegion","target","scrollLeft","ratio","_onMouseover","prevWidth","_onResize","debounce","wrapper","clientWidth","_onZoom","on","isReady","window","removeEventListener","un","destroy","unAll","region","id","renderRegions","regionElements","querySelectorAll","i","length","removeChild","Object","keys","forEach","width","end","start","getDuration","left","regionElement","backgroundColor","color","position","classList","add","appendChild","top","bottom","cursor","border","zIndex","opacity","overviewOpacity","addEventListener","positionMouseDown","clientX","clientY","relativePositionX","seek","interact","event","fireEvent","handleEvent","seekAndCenter","layerX","getBoundingClientRect","len","getWidth","peaks","getPeaks","drawPeaks","waveShowedWidth","waveWidth","overviewWidth","offsetWidth","overviewPosition","pixels"],"mappings":"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","file":"wavesurfer.minimap.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"minimap\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"minimap\"] = factory();\n\telse\n\t\troot[\"WaveSurfer\"] = root[\"WaveSurfer\"] || {}, root[\"WaveSurfer\"][\"minimap\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"localhost:8080/dist/plugin/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/plugin/minimap.js\");\n","/**\n * @typedef {Object} MinimapPluginParams\n * @desc Extends the `WavesurferParams` wavesurfer was initialised with\n * @property {?string|HTMLElement} container CSS selector or HTML element where\n * the map should be rendered. By default it is simply appended\n * after the waveform.\n * @property {?boolean} deferInit Set to true to manually call\n * `initPlugin('minimap')`\n */\n\n/**\n * Renders a smaller version waveform as a minimap of the main waveform.\n *\n * @implements {PluginClass}\n * @extends {Observer}\n * @example\n * // es6\n * import MinimapPlugin from 'wavesurfer.minimap.js';\n *\n * // commonjs\n * var MinimapPlugin = require('wavesurfer.minimap.js');\n *\n * // if you are using <script> tags\n * var MinimapPlugin = window.WaveSurfer.minimap;\n *\n * // ... initialising wavesurfer with the plugin\n * var wavesurfer = WaveSurfer.create({\n *   // wavesurfer options ...\n *   plugins: [\n *     MinimapPlugin.create({\n *       // plugin options ...\n *     })\n *   ]\n * });\n */\nexport default class MinimapPlugin {\n    /**\n     * Minimap plugin definition factory\n     *\n     * This function must be used to create a plugin definition which can be\n     * used by wavesurfer to correctly instantiate the plugin.\n     *\n     * @param  {MinimapPluginParams} params parameters use to initialise the plugin\n     * @return {PluginDefinition} an object representing the plugin\n     */\n    static create(params) {\n        return {\n            name: 'minimap',\n            deferInit: params && params.deferInit ? params.deferInit : false,\n            params: params,\n            staticProps: {\n                initMinimap(customConfig) {\n                    console.warn('Deprecated initMinimap!');\n                    params = customConfig;\n                    this.initPlugins('minimap');\n                }\n            },\n            instance: MinimapPlugin\n        };\n    }\n\n    constructor(params, ws) {\n        this.params = ws.util.extend(\n            {},\n            ws.params,\n            {\n                showRegions: false,\n                showOverview: false,\n                overviewBorderColor: 'green',\n                overviewBorderSize: 2,\n                // the container should be different\n                container: false,\n                height: Math.max(Math.round(ws.params.height / 4), 20)\n            },\n            params,\n            {\n                scrollParent: false,\n                fillParent: true\n            }\n        );\n        // if container is a selector, get the element\n        if (typeof params.container === 'string') {\n            const el = document.querySelector(params.container);\n            if (!el) {\n                console.warn(\n                    `Wavesurfer minimap container ${params.container} was not found! The minimap will be automatically appended below the waveform.`\n                );\n            }\n            this.params.container = el;\n        }\n        // if no container is specified add a new element and insert it\n        if (!params.container) {\n            this.params.container = ws.util.style(\n                document.createElement('minimap'),\n                {\n                    display: 'block'\n                }\n            );\n        }\n        this.drawer = new ws.Drawer(this.params.container, this.params);\n        this.wavesurfer = ws;\n        this.util = ws.util;\n        /**\n         * Minimap needs to register to ready and waveform-ready events to\n         * work with MediaElement, the time when ready is called is different\n         * (peaks can not be got)\n         *\n         * @type {string}\n         * @see https://github.com/katspaugh/wavesurfer.js/issues/736\n         */\n        this.renderEvent =\n            ws.params.backend === 'MediaElement' ? 'waveform-ready' : 'ready';\n        this.overviewRegion = null;\n\n        this.drawer.createWrapper();\n        this.createElements();\n        let isInitialised = false;\n\n        // ws ready event listener\n        this._onShouldRender = () => {\n            // only bind the events in the first run\n            if (!isInitialised) {\n                this.bindWavesurferEvents();\n                this.bindMinimapEvents();\n                isInitialised = true;\n            }\n            // if there is no such element, append it to the container (below\n            // the waveform)\n            if (!document.body.contains(this.params.container)) {\n                ws.container.insertBefore(this.params.container, null);\n            }\n\n            if (this.wavesurfer.regions && this.params.showRegions) {\n                this.regions();\n            }\n            this.render();\n        };\n\n        this._onAudioprocess = currentTime => {\n            this.drawer.progress(this.wavesurfer.backend.getPlayedPercents());\n        };\n\n        // ws seek event listener\n        this._onSeek = () =>\n            this.drawer.progress(ws.backend.getPlayedPercents());\n\n        // event listeners for the overview region\n        this._onScroll = e => {\n            if (!this.draggingOverview) {\n                this.moveOverviewRegion(e.target.scrollLeft / this.ratio);\n            }\n        };\n        this._onMouseover = e => {\n            if (this.draggingOverview) {\n                this.draggingOverview = false;\n            }\n        };\n        let prevWidth = 0;\n        this._onResize = ws.util.debounce(() => {\n            if (prevWidth != this.drawer.wrapper.clientWidth) {\n                prevWidth = this.drawer.wrapper.clientWidth;\n                this.render();\n                this.drawer.progress(\n                    this.wavesurfer.backend.getPlayedPercents()\n                );\n            }\n        });\n        this._onZoom = e => {\n            this.render();\n        };\n        this.wavesurfer.on('zoom', this._onZoom);\n    }\n\n    init() {\n        if (this.wavesurfer.isReady) {\n            this._onShouldRender();\n        }\n        this.wavesurfer.on(this.renderEvent, this._onShouldRender);\n    }\n\n    destroy() {\n        window.removeEventListener('resize', this._onResize, true);\n        window.removeEventListener('orientationchange', this._onResize, true);\n        this.wavesurfer.drawer.wrapper.removeEventListener(\n            'mouseover',\n            this._onMouseover\n        );\n        this.wavesurfer.un(this.renderEvent, this._onShouldRender);\n        this.wavesurfer.un('seek', this._onSeek);\n        this.wavesurfer.un('scroll', this._onScroll);\n        this.wavesurfer.un('audioprocess', this._onAudioprocess);\n        this.wavesurfer.un('zoom', this._onZoom);\n        this.drawer.destroy();\n        this.overviewRegion = null;\n        this.unAll();\n    }\n\n    regions() {\n        this.regions = {};\n\n        this.wavesurfer.on('region-created', region => {\n            this.regions[region.id] = region;\n            this.renderRegions();\n        });\n\n        this.wavesurfer.on('region-updated', region => {\n            this.regions[region.id] = region;\n            this.renderRegions();\n        });\n\n        this.wavesurfer.on('region-removed', region => {\n            delete this.regions[region.id];\n            this.renderRegions();\n        });\n    }\n\n    renderRegions() {\n        const regionElements = this.drawer.wrapper.querySelectorAll('region');\n        let i;\n        for (i = 0; i < regionElements.length; ++i) {\n            this.drawer.wrapper.removeChild(regionElements[i]);\n        }\n\n        Object.keys(this.regions).forEach(id => {\n            const region = this.regions[id];\n            const width =\n                this.drawer.width *\n                ((region.end - region.start) / this.wavesurfer.getDuration());\n            const left =\n                this.drawer.width *\n                (region.start / this.wavesurfer.getDuration());\n            const regionElement = this.util.style(\n                document.createElement('region'),\n                {\n                    height: 'inherit',\n                    backgroundColor: region.color,\n                    width: width + 'px',\n                    left: left + 'px',\n                    display: 'block',\n                    position: 'absolute'\n                }\n            );\n            regionElement.classList.add(id);\n            this.drawer.wrapper.appendChild(regionElement);\n        });\n    }\n\n    createElements() {\n        this.drawer.createElements();\n        if (this.params.showOverview) {\n            this.overviewRegion = this.util.style(\n                document.createElement('overview'),\n                {\n                    top: 0,\n                    bottom: 0,\n                    width: '0px',\n                    display: 'block',\n                    position: 'absolute',\n                    cursor: 'move',\n                    border:\n                        this.params.overviewBorderSize +\n                        'px solid ' +\n                        this.params.overviewBorderColor,\n                    zIndex: 2,\n                    opacity: this.params.overviewOpacity\n                }\n            );\n            this.drawer.wrapper.appendChild(this.overviewRegion);\n        }\n    }\n\n    bindWavesurferEvents() {\n        window.addEventListener('resize', this._onResize, true);\n        window.addEventListener('orientationchange', this._onResize, true);\n        this.wavesurfer.on('audioprocess', this._onAudioprocess);\n        this.wavesurfer.on('seek', this._onSeek);\n        if (this.params.showOverview) {\n            this.wavesurfer.on('scroll', this._onScroll);\n            this.wavesurfer.drawer.wrapper.addEventListener(\n                'mouseover',\n                this._onMouseover\n            );\n        }\n    }\n\n    bindMinimapEvents() {\n        const positionMouseDown = {\n            clientX: 0,\n            clientY: 0\n        };\n        let relativePositionX = 0;\n        let seek = true;\n\n        // the following event listeners will be destroyed by using\n        // this.unAll() and nullifying the DOM node references after\n        // removing them\n        if (this.params.interact) {\n            this.drawer.wrapper.addEventListener('click', event => {\n                this.fireEvent('click', event, this.drawer.handleEvent(event));\n            });\n\n            this.on('click', (event, position) => {\n                if (seek) {\n                    this.drawer.progress(position);\n                    this.wavesurfer.seekAndCenter(position);\n                } else {\n                    seek = true;\n                }\n            });\n        }\n\n        if (this.params.showOverview) {\n            this.overviewRegion.addEventListener('mousedown', event => {\n                this.draggingOverview = true;\n                relativePositionX = event.layerX;\n                positionMouseDown.clientX = event.clientX;\n                positionMouseDown.clientY = event.clientY;\n            });\n\n            this.drawer.wrapper.addEventListener('mousemove', event => {\n                if (this.draggingOverview) {\n                    this.moveOverviewRegion(\n                        event.clientX -\n                            this.drawer.container.getBoundingClientRect().left -\n                            relativePositionX\n                    );\n                }\n            });\n\n            this.drawer.wrapper.addEventListener('mouseup', event => {\n                if (\n                    positionMouseDown.clientX - event.clientX === 0 &&\n                    positionMouseDown.clientX - event.clientX === 0\n                ) {\n                    seek = true;\n                    this.draggingOverview = false;\n                } else if (this.draggingOverview) {\n                    seek = false;\n                    this.draggingOverview = false;\n                }\n            });\n        }\n    }\n\n    render() {\n        const len = this.drawer.getWidth();\n        const peaks = this.wavesurfer.backend.getPeaks(len, 0, len);\n        this.drawer.drawPeaks(peaks, len, 0, len);\n        this.drawer.progress(this.wavesurfer.backend.getPlayedPercents());\n\n        if (this.params.showOverview) {\n            //get proportional width of overview region considering the respective\n            //width of the drawers\n            this.ratio = this.wavesurfer.drawer.width / this.drawer.width;\n            this.waveShowedWidth = this.wavesurfer.drawer.width / this.ratio;\n            this.waveWidth = this.wavesurfer.drawer.width;\n            this.overviewWidth = this.drawer.container.offsetWidth / this.ratio;\n            this.overviewPosition = 0;\n            this.moveOverviewRegion(\n                this.wavesurfer.drawer.wrapper.scrollLeft / this.ratio\n            );\n            this.overviewRegion.style.width = this.overviewWidth + 'px';\n        }\n    }\n\n    moveOverviewRegion(pixels) {\n        if (pixels < 0) {\n            this.overviewPosition = 0;\n        } else if (\n            pixels + this.overviewWidth <\n            this.drawer.container.offsetWidth\n        ) {\n            this.overviewPosition = pixels;\n        } else {\n            this.overviewPosition =\n                this.drawer.container.offsetWidth - this.overviewWidth;\n        }\n        this.overviewRegion.style.left = this.overviewPosition + 'px';\n        if (this.draggingOverview) {\n            this.wavesurfer.drawer.wrapper.scrollLeft =\n                this.overviewPosition * this.ratio;\n        }\n    }\n}\n"],"sourceRoot":""}
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.minimap.min.js
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.minimap.min.js	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.minimap.min.js	(revision 33546)
@@ -0,0 +1,2 @@
+!function(e,r){"object"==typeof exports&&"object"==typeof module?module.exports=r():"function"==typeof define&&define.amd?define("minimap",[],r):"object"==typeof exports?exports.minimap=r():(e.WaveSurfer=e.WaveSurfer||{},e.WaveSurfer.minimap=r())}(window,(function(){return function(e){var r={};function i(t){if(r[t])return r[t].exports;var n=r[t]={i:t,l:!1,exports:{}};return e[t].call(n.exports,n,n.exports,i),n.l=!0,n.exports}return i.m=e,i.c=r,i.d=function(e,r,t){i.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,r){if(1&r&&(e=i(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(i.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)i.d(t,n,function(r){return e[r]}.bind(null,n));return t},i.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(r,"a",r),r},i.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},i.p="localhost:8080/dist/plugin/",i(i.s=1)}([,function(e,r,i){"use strict";function t(e,r){for(var i=0;i<r.length;i++){var t=r[i];t.enumerable=t.enumerable||!1,t.configurable=!0,"value"in t&&(t.writable=!0),Object.defineProperty(e,t.key,t)}}function n(e,r,i){return r&&t(e.prototype,r),i&&t(e,i),e}Object.defineProperty(r,"__esModule",{value:!0}),r.default=void 0;var o=function(){function e(r,i){var t=this;if(function(e,r){if(!(e instanceof r))throw new TypeError("Cannot call a class as a function")}(this,e),this.params=i.util.extend({},i.params,{showRegions:!1,showOverview:!1,overviewBorderColor:"green",overviewBorderSize:2,container:!1,height:Math.max(Math.round(i.params.height/4),20)},r,{scrollParent:!1,fillParent:!0}),"string"==typeof r.container){var n=document.querySelector(r.container);n||console.warn("Wavesurfer minimap container ".concat(r.container," was not found! The minimap will be automatically appended below the waveform.")),this.params.container=n}r.container||(this.params.container=i.util.style(document.createElement("minimap"),{display:"block"})),this.drawer=new i.Drawer(this.params.container,this.params),this.wavesurfer=i,this.util=i.util,this.renderEvent="MediaElement"===i.params.backend?"waveform-ready":"ready",this.overviewRegion=null,this.drawer.createWrapper(),this.createElements();var o=!1;this._onShouldRender=function(){o||(t.bindWavesurferEvents(),t.bindMinimapEvents(),o=!0),document.body.contains(t.params.container)||i.container.insertBefore(t.params.container,null),t.wavesurfer.regions&&t.params.showRegions&&t.regions(),t.render()},this._onAudioprocess=function(e){t.drawer.progress(t.wavesurfer.backend.getPlayedPercents())},this._onSeek=function(){return t.drawer.progress(i.backend.getPlayedPercents())},this._onScroll=function(e){t.draggingOverview||t.moveOverviewRegion(e.target.scrollLeft/t.ratio)},this._onMouseover=function(e){t.draggingOverview&&(t.draggingOverview=!1)};var s=0;this._onResize=i.util.debounce((function(){s!=t.drawer.wrapper.clientWidth&&(s=t.drawer.wrapper.clientWidth,t.render(),t.drawer.progress(t.wavesurfer.backend.getPlayedPercents()))})),this._onZoom=function(e){t.render()},this.wavesurfer.on("zoom",this._onZoom)}return n(e,null,[{key:"create",value:function(r){return{name:"minimap",deferInit:!(!r||!r.deferInit)&&r.deferInit,params:r,staticProps:{initMinimap:function(e){console.warn("Deprecated initMinimap!"),r=e,this.initPlugins("minimap")}},instance:e}}}]),n(e,[{key:"init",value:function(){this.wavesurfer.isReady&&this._onShouldRender(),this.wavesurfer.on(this.renderEvent,this._onShouldRender)}},{key:"destroy",value:function(){window.removeEventListener("resize",this._onResize,!0),window.removeEventListener("orientationchange",this._onResize,!0),this.wavesurfer.drawer.wrapper.removeEventListener("mouseover",this._onMouseover),this.wavesurfer.un(this.renderEvent,this._onShouldRender),this.wavesurfer.un("seek",this._onSeek),this.wavesurfer.un("scroll",this._onScroll),this.wavesurfer.un("audioprocess",this._onAudioprocess),this.wavesurfer.un("zoom",this._onZoom),this.drawer.destroy(),this.overviewRegion=null,this.unAll()}},{key:"regions",value:function(){var e=this;this.regions={},this.wavesurfer.on("region-created",(function(r){e.regions[r.id]=r,e.renderRegions()})),this.wavesurfer.on("region-updated",(function(r){e.regions[r.id]=r,e.renderRegions()})),this.wavesurfer.on("region-removed",(function(r){delete e.regions[r.id],e.renderRegions()}))}},{key:"renderRegions",value:function(){var e,r=this,i=this.drawer.wrapper.querySelectorAll("region");for(e=0;e<i.length;++e)this.drawer.wrapper.removeChild(i[e]);Object.keys(this.regions).forEach((function(e){var i=r.regions[e],t=r.drawer.width*((i.end-i.start)/r.wavesurfer.getDuration()),n=r.drawer.width*(i.start/r.wavesurfer.getDuration()),o=r.util.style(document.createElement("region"),{height:"inherit",backgroundColor:i.color,width:t+"px",left:n+"px",display:"block",position:"absolute"});o.classList.add(e),r.drawer.wrapper.appendChild(o)}))}},{key:"createElements",value:function(){this.drawer.createElements(),this.params.showOverview&&(this.overviewRegion=this.util.style(document.createElement("overview"),{top:0,bottom:0,width:"0px",display:"block",position:"absolute",cursor:"move",border:this.params.overviewBorderSize+"px solid "+this.params.overviewBorderColor,zIndex:2,opacity:this.params.overviewOpacity}),this.drawer.wrapper.appendChild(this.overviewRegion))}},{key:"bindWavesurferEvents",value:function(){window.addEventListener("resize",this._onResize,!0),window.addEventListener("orientationchange",this._onResize,!0),this.wavesurfer.on("audioprocess",this._onAudioprocess),this.wavesurfer.on("seek",this._onSeek),this.params.showOverview&&(this.wavesurfer.on("scroll",this._onScroll),this.wavesurfer.drawer.wrapper.addEventListener("mouseover",this._onMouseover))}},{key:"bindMinimapEvents",value:function(){var e=this,r={clientX:0,clientY:0},i=0,t=!0;this.params.interact&&(this.drawer.wrapper.addEventListener("click",(function(r){e.fireEvent("click",r,e.drawer.handleEvent(r))})),this.on("click",(function(r,i){t?(e.drawer.progress(i),e.wavesurfer.seekAndCenter(i)):t=!0}))),this.params.showOverview&&(this.overviewRegion.addEventListener("mousedown",(function(t){e.draggingOverview=!0,i=t.layerX,r.clientX=t.clientX,r.clientY=t.clientY})),this.drawer.wrapper.addEventListener("mousemove",(function(r){e.draggingOverview&&e.moveOverviewRegion(r.clientX-e.drawer.container.getBoundingClientRect().left-i)})),this.drawer.wrapper.addEventListener("mouseup",(function(i){r.clientX-i.clientX==0&&r.clientX-i.clientX==0?(t=!0,e.draggingOverview=!1):e.draggingOverview&&(t=!1,e.draggingOverview=!1)})))}},{key:"render",value:function(){var e=this.drawer.getWidth(),r=this.wavesurfer.backend.getPeaks(e,0,e);this.drawer.drawPeaks(r,e,0,e),this.drawer.progress(this.wavesurfer.backend.getPlayedPercents()),this.params.showOverview&&(this.ratio=this.wavesurfer.drawer.width/this.drawer.width,this.waveShowedWidth=this.wavesurfer.drawer.width/this.ratio,this.waveWidth=this.wavesurfer.drawer.width,this.overviewWidth=this.drawer.container.offsetWidth/this.ratio,this.overviewPosition=0,this.moveOverviewRegion(this.wavesurfer.drawer.wrapper.scrollLeft/this.ratio),this.overviewRegion.style.width=this.overviewWidth+"px")}},{key:"moveOverviewRegion",value:function(e){e<0?this.overviewPosition=0:e+this.overviewWidth<this.drawer.container.offsetWidth?this.overviewPosition=e:this.overviewPosition=this.drawer.container.offsetWidth-this.overviewWidth,this.overviewRegion.style.left=this.overviewPosition+"px",this.draggingOverview&&(this.wavesurfer.drawer.wrapper.scrollLeft=this.overviewPosition*this.ratio)}}]),e}();r.default=o,e.exports=r.default}])}));
+//# sourceMappingURL=wavesurfer.minimap.min.js.map
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.minimap.min.js.map
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.minimap.min.js.map	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.minimap.min.js.map	(revision 33546)
@@ -0,0 +1,1 @@
+{"version":3,"sources":["webpack://WaveSurfer.[name]/webpack/universalModuleDefinition","webpack://WaveSurfer.[name]/webpack/bootstrap","webpack://WaveSurfer.[name]/./src/plugin/minimap.js"],"names":["root","factory","exports","module","define","amd","window","installedModules","__webpack_require__","moduleId","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","MinimapPlugin","params","ws","this","util","extend","showRegions","showOverview","overviewBorderColor","overviewBorderSize","container","height","Math","max","round","scrollParent","fillParent","el","document","querySelector","console","warn","style","createElement","display","drawer","Drawer","wavesurfer","renderEvent","backend","overviewRegion","createWrapper","createElements","isInitialised","_onShouldRender","bindWavesurferEvents","bindMinimapEvents","body","contains","insertBefore","regions","render","_onAudioprocess","currentTime","progress","getPlayedPercents","_onSeek","_onScroll","e","draggingOverview","moveOverviewRegion","target","scrollLeft","ratio","_onMouseover","prevWidth","_onResize","debounce","wrapper","clientWidth","_onZoom","on","deferInit","staticProps","initMinimap","customConfig","initPlugins","instance","isReady","removeEventListener","un","destroy","unAll","region","id","renderRegions","regionElements","querySelectorAll","length","removeChild","keys","forEach","width","end","start","getDuration","left","regionElement","backgroundColor","color","position","classList","add","appendChild","top","bottom","cursor","border","zIndex","opacity","overviewOpacity","addEventListener","positionMouseDown","clientX","clientY","relativePositionX","seek","interact","event","fireEvent","handleEvent","seekAndCenter","layerX","getBoundingClientRect","len","getWidth","peaks","getPeaks","drawPeaks","waveShowedWidth","waveWidth","overviewWidth","offsetWidth","overviewPosition","pixels"],"mappings":"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","file":"wavesurfer.minimap.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"minimap\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"minimap\"] = factory();\n\telse\n\t\troot[\"WaveSurfer\"] = root[\"WaveSurfer\"] || {}, root[\"WaveSurfer\"][\"minimap\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"localhost:8080/dist/plugin/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 1);\n","/**\n * @typedef {Object} MinimapPluginParams\n * @desc Extends the `WavesurferParams` wavesurfer was initialised with\n * @property {?string|HTMLElement} container CSS selector or HTML element where\n * the map should be rendered. By default it is simply appended\n * after the waveform.\n * @property {?boolean} deferInit Set to true to manually call\n * `initPlugin('minimap')`\n */\n\n/**\n * Renders a smaller version waveform as a minimap of the main waveform.\n *\n * @implements {PluginClass}\n * @extends {Observer}\n * @example\n * // es6\n * import MinimapPlugin from 'wavesurfer.minimap.js';\n *\n * // commonjs\n * var MinimapPlugin = require('wavesurfer.minimap.js');\n *\n * // if you are using <script> tags\n * var MinimapPlugin = window.WaveSurfer.minimap;\n *\n * // ... initialising wavesurfer with the plugin\n * var wavesurfer = WaveSurfer.create({\n *   // wavesurfer options ...\n *   plugins: [\n *     MinimapPlugin.create({\n *       // plugin options ...\n *     })\n *   ]\n * });\n */\nexport default class MinimapPlugin {\n    /**\n     * Minimap plugin definition factory\n     *\n     * This function must be used to create a plugin definition which can be\n     * used by wavesurfer to correctly instantiate the plugin.\n     *\n     * @param  {MinimapPluginParams} params parameters use to initialise the plugin\n     * @return {PluginDefinition} an object representing the plugin\n     */\n    static create(params) {\n        return {\n            name: 'minimap',\n            deferInit: params && params.deferInit ? params.deferInit : false,\n            params: params,\n            staticProps: {\n                initMinimap(customConfig) {\n                    console.warn('Deprecated initMinimap!');\n                    params = customConfig;\n                    this.initPlugins('minimap');\n                }\n            },\n            instance: MinimapPlugin\n        };\n    }\n\n    constructor(params, ws) {\n        this.params = ws.util.extend(\n            {},\n            ws.params,\n            {\n                showRegions: false,\n                showOverview: false,\n                overviewBorderColor: 'green',\n                overviewBorderSize: 2,\n                // the container should be different\n                container: false,\n                height: Math.max(Math.round(ws.params.height / 4), 20)\n            },\n            params,\n            {\n                scrollParent: false,\n                fillParent: true\n            }\n        );\n        // if container is a selector, get the element\n        if (typeof params.container === 'string') {\n            const el = document.querySelector(params.container);\n            if (!el) {\n                console.warn(\n                    `Wavesurfer minimap container ${params.container} was not found! The minimap will be automatically appended below the waveform.`\n                );\n            }\n            this.params.container = el;\n        }\n        // if no container is specified add a new element and insert it\n        if (!params.container) {\n            this.params.container = ws.util.style(\n                document.createElement('minimap'),\n                {\n                    display: 'block'\n                }\n            );\n        }\n        this.drawer = new ws.Drawer(this.params.container, this.params);\n        this.wavesurfer = ws;\n        this.util = ws.util;\n        /**\n         * Minimap needs to register to ready and waveform-ready events to\n         * work with MediaElement, the time when ready is called is different\n         * (peaks can not be got)\n         *\n         * @type {string}\n         * @see https://github.com/katspaugh/wavesurfer.js/issues/736\n         */\n        this.renderEvent =\n            ws.params.backend === 'MediaElement' ? 'waveform-ready' : 'ready';\n        this.overviewRegion = null;\n\n        this.drawer.createWrapper();\n        this.createElements();\n        let isInitialised = false;\n\n        // ws ready event listener\n        this._onShouldRender = () => {\n            // only bind the events in the first run\n            if (!isInitialised) {\n                this.bindWavesurferEvents();\n                this.bindMinimapEvents();\n                isInitialised = true;\n            }\n            // if there is no such element, append it to the container (below\n            // the waveform)\n            if (!document.body.contains(this.params.container)) {\n                ws.container.insertBefore(this.params.container, null);\n            }\n\n            if (this.wavesurfer.regions && this.params.showRegions) {\n                this.regions();\n            }\n            this.render();\n        };\n\n        this._onAudioprocess = currentTime => {\n            this.drawer.progress(this.wavesurfer.backend.getPlayedPercents());\n        };\n\n        // ws seek event listener\n        this._onSeek = () =>\n            this.drawer.progress(ws.backend.getPlayedPercents());\n\n        // event listeners for the overview region\n        this._onScroll = e => {\n            if (!this.draggingOverview) {\n                this.moveOverviewRegion(e.target.scrollLeft / this.ratio);\n            }\n        };\n        this._onMouseover = e => {\n            if (this.draggingOverview) {\n                this.draggingOverview = false;\n            }\n        };\n        let prevWidth = 0;\n        this._onResize = ws.util.debounce(() => {\n            if (prevWidth != this.drawer.wrapper.clientWidth) {\n                prevWidth = this.drawer.wrapper.clientWidth;\n                this.render();\n                this.drawer.progress(\n                    this.wavesurfer.backend.getPlayedPercents()\n                );\n            }\n        });\n        this._onZoom = e => {\n            this.render();\n        };\n        this.wavesurfer.on('zoom', this._onZoom);\n    }\n\n    init() {\n        if (this.wavesurfer.isReady) {\n            this._onShouldRender();\n        }\n        this.wavesurfer.on(this.renderEvent, this._onShouldRender);\n    }\n\n    destroy() {\n        window.removeEventListener('resize', this._onResize, true);\n        window.removeEventListener('orientationchange', this._onResize, true);\n        this.wavesurfer.drawer.wrapper.removeEventListener(\n            'mouseover',\n            this._onMouseover\n        );\n        this.wavesurfer.un(this.renderEvent, this._onShouldRender);\n        this.wavesurfer.un('seek', this._onSeek);\n        this.wavesurfer.un('scroll', this._onScroll);\n        this.wavesurfer.un('audioprocess', this._onAudioprocess);\n        this.wavesurfer.un('zoom', this._onZoom);\n        this.drawer.destroy();\n        this.overviewRegion = null;\n        this.unAll();\n    }\n\n    regions() {\n        this.regions = {};\n\n        this.wavesurfer.on('region-created', region => {\n            this.regions[region.id] = region;\n            this.renderRegions();\n        });\n\n        this.wavesurfer.on('region-updated', region => {\n            this.regions[region.id] = region;\n            this.renderRegions();\n        });\n\n        this.wavesurfer.on('region-removed', region => {\n            delete this.regions[region.id];\n            this.renderRegions();\n        });\n    }\n\n    renderRegions() {\n        const regionElements = this.drawer.wrapper.querySelectorAll('region');\n        let i;\n        for (i = 0; i < regionElements.length; ++i) {\n            this.drawer.wrapper.removeChild(regionElements[i]);\n        }\n\n        Object.keys(this.regions).forEach(id => {\n            const region = this.regions[id];\n            const width =\n                this.drawer.width *\n                ((region.end - region.start) / this.wavesurfer.getDuration());\n            const left =\n                this.drawer.width *\n                (region.start / this.wavesurfer.getDuration());\n            const regionElement = this.util.style(\n                document.createElement('region'),\n                {\n                    height: 'inherit',\n                    backgroundColor: region.color,\n                    width: width + 'px',\n                    left: left + 'px',\n                    display: 'block',\n                    position: 'absolute'\n                }\n            );\n            regionElement.classList.add(id);\n            this.drawer.wrapper.appendChild(regionElement);\n        });\n    }\n\n    createElements() {\n        this.drawer.createElements();\n        if (this.params.showOverview) {\n            this.overviewRegion = this.util.style(\n                document.createElement('overview'),\n                {\n                    top: 0,\n                    bottom: 0,\n                    width: '0px',\n                    display: 'block',\n                    position: 'absolute',\n                    cursor: 'move',\n                    border:\n                        this.params.overviewBorderSize +\n                        'px solid ' +\n                        this.params.overviewBorderColor,\n                    zIndex: 2,\n                    opacity: this.params.overviewOpacity\n                }\n            );\n            this.drawer.wrapper.appendChild(this.overviewRegion);\n        }\n    }\n\n    bindWavesurferEvents() {\n        window.addEventListener('resize', this._onResize, true);\n        window.addEventListener('orientationchange', this._onResize, true);\n        this.wavesurfer.on('audioprocess', this._onAudioprocess);\n        this.wavesurfer.on('seek', this._onSeek);\n        if (this.params.showOverview) {\n            this.wavesurfer.on('scroll', this._onScroll);\n            this.wavesurfer.drawer.wrapper.addEventListener(\n                'mouseover',\n                this._onMouseover\n            );\n        }\n    }\n\n    bindMinimapEvents() {\n        const positionMouseDown = {\n            clientX: 0,\n            clientY: 0\n        };\n        let relativePositionX = 0;\n        let seek = true;\n\n        // the following event listeners will be destroyed by using\n        // this.unAll() and nullifying the DOM node references after\n        // removing them\n        if (this.params.interact) {\n            this.drawer.wrapper.addEventListener('click', event => {\n                this.fireEvent('click', event, this.drawer.handleEvent(event));\n            });\n\n            this.on('click', (event, position) => {\n                if (seek) {\n                    this.drawer.progress(position);\n                    this.wavesurfer.seekAndCenter(position);\n                } else {\n                    seek = true;\n                }\n            });\n        }\n\n        if (this.params.showOverview) {\n            this.overviewRegion.addEventListener('mousedown', event => {\n                this.draggingOverview = true;\n                relativePositionX = event.layerX;\n                positionMouseDown.clientX = event.clientX;\n                positionMouseDown.clientY = event.clientY;\n            });\n\n            this.drawer.wrapper.addEventListener('mousemove', event => {\n                if (this.draggingOverview) {\n                    this.moveOverviewRegion(\n                        event.clientX -\n                            this.drawer.container.getBoundingClientRect().left -\n                            relativePositionX\n                    );\n                }\n            });\n\n            this.drawer.wrapper.addEventListener('mouseup', event => {\n                if (\n                    positionMouseDown.clientX - event.clientX === 0 &&\n                    positionMouseDown.clientX - event.clientX === 0\n                ) {\n                    seek = true;\n                    this.draggingOverview = false;\n                } else if (this.draggingOverview) {\n                    seek = false;\n                    this.draggingOverview = false;\n                }\n            });\n        }\n    }\n\n    render() {\n        const len = this.drawer.getWidth();\n        const peaks = this.wavesurfer.backend.getPeaks(len, 0, len);\n        this.drawer.drawPeaks(peaks, len, 0, len);\n        this.drawer.progress(this.wavesurfer.backend.getPlayedPercents());\n\n        if (this.params.showOverview) {\n            //get proportional width of overview region considering the respective\n            //width of the drawers\n            this.ratio = this.wavesurfer.drawer.width / this.drawer.width;\n            this.waveShowedWidth = this.wavesurfer.drawer.width / this.ratio;\n            this.waveWidth = this.wavesurfer.drawer.width;\n            this.overviewWidth = this.drawer.container.offsetWidth / this.ratio;\n            this.overviewPosition = 0;\n            this.moveOverviewRegion(\n                this.wavesurfer.drawer.wrapper.scrollLeft / this.ratio\n            );\n            this.overviewRegion.style.width = this.overviewWidth + 'px';\n        }\n    }\n\n    moveOverviewRegion(pixels) {\n        if (pixels < 0) {\n            this.overviewPosition = 0;\n        } else if (\n            pixels + this.overviewWidth <\n            this.drawer.container.offsetWidth\n        ) {\n            this.overviewPosition = pixels;\n        } else {\n            this.overviewPosition =\n                this.drawer.container.offsetWidth - this.overviewWidth;\n        }\n        this.overviewRegion.style.left = this.overviewPosition + 'px';\n        if (this.draggingOverview) {\n            this.wavesurfer.drawer.wrapper.scrollLeft =\n                this.overviewPosition * this.ratio;\n        }\n    }\n}\n"],"sourceRoot":""}
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.regions.js
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.regions.js	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.regions.js	(revision 33546)
@@ -0,0 +1,1032 @@
+/*!
+ * wavesurfer.js regions plugin 2.2.1 (2019-09-30)
+ * https://github.com/katspaugh/wavesurfer.js
+ * @license BSD-3-Clause
+ */
+(function webpackUniversalModuleDefinition(root, factory) {
+	if(typeof exports === 'object' && typeof module === 'object')
+		module.exports = factory();
+	else if(typeof define === 'function' && define.amd)
+		define("regions", [], factory);
+	else if(typeof exports === 'object')
+		exports["regions"] = factory();
+	else
+		root["WaveSurfer"] = root["WaveSurfer"] || {}, root["WaveSurfer"]["regions"] = factory();
+})(window, function() {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+/******/
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId]) {
+/******/ 			return installedModules[moduleId].exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			i: moduleId,
+/******/ 			l: false,
+/******/ 			exports: {}
+/******/ 		};
+/******/
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ 		// Flag the module as loaded
+/******/ 		module.l = true;
+/******/
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/
+/******/
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+/******/
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+/******/
+/******/ 	// define getter function for harmony exports
+/******/ 	__webpack_require__.d = function(exports, name, getter) {
+/******/ 		if(!__webpack_require__.o(exports, name)) {
+/******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
+/******/ 		}
+/******/ 	};
+/******/
+/******/ 	// define __esModule on exports
+/******/ 	__webpack_require__.r = function(exports) {
+/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ 		}
+/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
+/******/ 	};
+/******/
+/******/ 	// create a fake namespace object
+/******/ 	// mode & 1: value is a module id, require it
+/******/ 	// mode & 2: merge all properties of value into the ns
+/******/ 	// mode & 4: return value when already ns object
+/******/ 	// mode & 8|1: behave like require
+/******/ 	__webpack_require__.t = function(value, mode) {
+/******/ 		if(mode & 1) value = __webpack_require__(value);
+/******/ 		if(mode & 8) return value;
+/******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
+/******/ 		var ns = Object.create(null);
+/******/ 		__webpack_require__.r(ns);
+/******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
+/******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
+/******/ 		return ns;
+/******/ 	};
+/******/
+/******/ 	// getDefaultExport function for compatibility with non-harmony modules
+/******/ 	__webpack_require__.n = function(module) {
+/******/ 		var getter = module && module.__esModule ?
+/******/ 			function getDefault() { return module['default']; } :
+/******/ 			function getModuleExports() { return module; };
+/******/ 		__webpack_require__.d(getter, 'a', getter);
+/******/ 		return getter;
+/******/ 	};
+/******/
+/******/ 	// Object.prototype.hasOwnProperty.call
+/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "localhost:8080/dist/plugin/";
+/******/
+/******/
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(__webpack_require__.s = "./src/plugin/regions.js");
+/******/ })
+/************************************************************************/
+/******/ ({
+
+/***/ "./src/plugin/regions.js":
+/*!*******************************!*\
+  !*** ./src/plugin/regions.js ***!
+  \*******************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+/**
+ * (Single) Region plugin class
+ *
+ * Must be turned into an observer before instantiating. This is done in
+ * RegionsPlugin (main plugin class)
+ *
+ * @extends {Observer}
+ */
+var Region =
+/*#__PURE__*/
+function () {
+  function Region(params, ws) {
+    var _this = this;
+
+    _classCallCheck(this, Region);
+
+    this.wavesurfer = ws;
+    this.wrapper = ws.drawer.wrapper;
+    this.util = ws.util;
+    this.style = this.util.style;
+    this.id = params.id == null ? ws.util.getId() : params.id;
+    this.start = Number(params.start) || 0;
+    this.end = params.end == null ? // small marker-like region
+    this.start + 4 / this.wrapper.scrollWidth * this.wavesurfer.getDuration() : Number(params.end);
+    this.resize = params.resize === undefined ? true : Boolean(params.resize);
+    this.drag = params.drag === undefined ? true : Boolean(params.drag);
+    this.loop = Boolean(params.loop);
+    this.color = params.color || 'rgba(0, 0, 0, 0.1)';
+    this.data = params.data || {};
+    this.attributes = params.attributes || {};
+    this.maxLength = params.maxLength;
+    this.minLength = params.minLength;
+
+    this._onRedraw = function () {
+      return _this.updateRender();
+    };
+
+    this.scroll = params.scroll !== false && ws.params.scrollParent;
+    this.scrollSpeed = params.scrollSpeed || 1;
+    this.scrollThreshold = params.scrollThreshold || 10;
+    this.bindInOut();
+    this.render();
+    this.wavesurfer.on('zoom', this._onRedraw);
+    this.wavesurfer.on('redraw', this._onRedraw);
+    this.wavesurfer.fireEvent('region-created', this);
+  }
+  /* Update region params. */
+
+
+  _createClass(Region, [{
+    key: "update",
+    value: function update(params) {
+      if (null != params.start) {
+        this.start = Number(params.start);
+      }
+
+      if (null != params.end) {
+        this.end = Number(params.end);
+      }
+
+      if (null != params.loop) {
+        this.loop = Boolean(params.loop);
+      }
+
+      if (null != params.color) {
+        this.color = params.color;
+      }
+
+      if (null != params.data) {
+        this.data = params.data;
+      }
+
+      if (null != params.resize) {
+        this.resize = Boolean(params.resize);
+      }
+
+      if (null != params.drag) {
+        this.drag = Boolean(params.drag);
+      }
+
+      if (null != params.maxLength) {
+        this.maxLength = Number(params.maxLength);
+      }
+
+      if (null != params.minLength) {
+        this.minLength = Number(params.minLength);
+      }
+
+      if (null != params.attributes) {
+        this.attributes = params.attributes;
+      }
+
+      this.updateRender();
+      this.fireEvent('update');
+      this.wavesurfer.fireEvent('region-updated', this);
+    }
+    /* Remove a single region. */
+
+  }, {
+    key: "remove",
+    value: function remove() {
+      if (this.element) {
+        this.wrapper.removeChild(this.element);
+        this.element = null;
+        this.fireEvent('remove');
+        this.wavesurfer.un('zoom', this._onRedraw);
+        this.wavesurfer.un('redraw', this._onRedraw);
+        this.wavesurfer.fireEvent('region-removed', this);
+      }
+    }
+    /* Play the audio region. */
+
+  }, {
+    key: "play",
+    value: function play() {
+      this.wavesurfer.play(this.start, this.end);
+      this.fireEvent('play');
+      this.wavesurfer.fireEvent('region-play', this);
+    }
+    /* Play the region in loop. */
+
+  }, {
+    key: "playLoop",
+    value: function playLoop() {
+      var _this2 = this;
+
+      this.play();
+      this.once('out', function () {
+        return _this2.playLoop();
+      });
+    }
+    /* Render a region as a DOM element. */
+
+  }, {
+    key: "render",
+    value: function render() {
+      var regionEl = document.createElement('region');
+      regionEl.className = 'wavesurfer-region';
+      regionEl.title = this.formatTime(this.start, this.end);
+      regionEl.setAttribute('data-id', this.id);
+
+      for (var attrname in this.attributes) {
+        regionEl.setAttribute('data-region-' + attrname, this.attributes[attrname]);
+      }
+
+      var width = this.wrapper.scrollWidth;
+      this.style(regionEl, {
+        position: 'absolute',
+        zIndex: 2,
+        height: '100%',
+        top: '0px'
+      });
+      /* Resize handles */
+
+      if (this.resize) {
+        var handleLeft = regionEl.appendChild(document.createElement('handle'));
+        var handleRight = regionEl.appendChild(document.createElement('handle'));
+        handleLeft.className = 'wavesurfer-handle wavesurfer-handle-start';
+        handleRight.className = 'wavesurfer-handle wavesurfer-handle-end';
+        var css = {
+          cursor: 'col-resize',
+          position: 'absolute',
+          left: '0px',
+          top: '0px',
+          width: '1%',
+          maxWidth: '4px',
+          height: '100%'
+        };
+        this.style(handleLeft, css);
+        this.style(handleRight, css);
+        this.style(handleRight, {
+          left: '100%'
+        });
+      }
+
+      this.element = this.wrapper.appendChild(regionEl);
+      this.updateRender();
+      this.bindEvents(regionEl);
+    }
+  }, {
+    key: "formatTime",
+    value: function formatTime(start, end) {
+      return (start == end ? [start] : [start, end]).map(function (time) {
+        return [Math.floor(time % 3600 / 60), // minutes
+        ('00' + Math.floor(time % 60)).slice(-2) // seconds
+        ].join(':');
+      }).join('-');
+    }
+  }, {
+    key: "getWidth",
+    value: function getWidth() {
+      return this.wavesurfer.drawer.width / this.wavesurfer.params.pixelRatio;
+    }
+    /* Update element's position, width, color. */
+
+  }, {
+    key: "updateRender",
+    value: function updateRender() {
+      // duration varies during loading process, so don't overwrite important data
+      var dur = this.wavesurfer.getDuration();
+      var width = this.getWidth();
+      var startLimited = this.start;
+      var endLimited = this.end;
+
+      if (startLimited < 0) {
+        startLimited = 0;
+        endLimited = endLimited - startLimited;
+      }
+
+      if (endLimited > dur) {
+        endLimited = dur;
+        startLimited = dur - (endLimited - startLimited);
+      }
+
+      if (this.minLength != null) {
+        endLimited = Math.max(startLimited + this.minLength, endLimited);
+      }
+
+      if (this.maxLength != null) {
+        endLimited = Math.min(startLimited + this.maxLength, endLimited);
+      }
+
+      if (this.element != null) {
+        // Calculate the left and width values of the region such that
+        // no gaps appear between regions.
+        var left = Math.round(startLimited / dur * width);
+        var regionWidth = Math.round(endLimited / dur * width) - left;
+        this.style(this.element, {
+          left: left + 'px',
+          width: regionWidth + 'px',
+          backgroundColor: this.color,
+          cursor: this.drag ? 'move' : 'default'
+        });
+
+        for (var attrname in this.attributes) {
+          this.element.setAttribute('data-region-' + attrname, this.attributes[attrname]);
+        }
+
+        this.element.title = this.formatTime(this.start, this.end);
+      }
+    }
+    /* Bind audio events. */
+
+  }, {
+    key: "bindInOut",
+    value: function bindInOut() {
+      var _this3 = this;
+
+      this.firedIn = false;
+      this.firedOut = false;
+
+      var onProcess = function onProcess(time) {
+        if (!_this3.firedOut && _this3.firedIn && (_this3.start >= Math.round(time * 100) / 100 || _this3.end <= Math.round(time * 100) / 100)) {
+          _this3.firedOut = true;
+          _this3.firedIn = false;
+
+          _this3.fireEvent('out');
+
+          _this3.wavesurfer.fireEvent('region-out', _this3);
+        }
+
+        if (!_this3.firedIn && _this3.start <= time && _this3.end > time) {
+          _this3.firedIn = true;
+          _this3.firedOut = false;
+
+          _this3.fireEvent('in');
+
+          _this3.wavesurfer.fireEvent('region-in', _this3);
+        }
+      };
+
+      this.wavesurfer.backend.on('audioprocess', onProcess);
+      this.on('remove', function () {
+        _this3.wavesurfer.backend.un('audioprocess', onProcess);
+      });
+      /* Loop playback. */
+
+      this.on('out', function () {
+        if (_this3.loop) {
+          _this3.wavesurfer.play(_this3.start);
+        }
+      });
+    }
+    /* Bind DOM events. */
+
+  }, {
+    key: "bindEvents",
+    value: function bindEvents() {
+      var _this4 = this;
+
+      this.element.addEventListener('mouseenter', function (e) {
+        _this4.fireEvent('mouseenter', e);
+
+        _this4.wavesurfer.fireEvent('region-mouseenter', _this4, e);
+      });
+      this.element.addEventListener('mouseleave', function (e) {
+        _this4.fireEvent('mouseleave', e);
+
+        _this4.wavesurfer.fireEvent('region-mouseleave', _this4, e);
+      });
+      this.element.addEventListener('click', function (e) {
+        e.preventDefault();
+
+        _this4.fireEvent('click', e);
+
+        _this4.wavesurfer.fireEvent('region-click', _this4, e);
+      });
+      this.element.addEventListener('dblclick', function (e) {
+        e.stopPropagation();
+        e.preventDefault();
+
+        _this4.fireEvent('dblclick', e);
+
+        _this4.wavesurfer.fireEvent('region-dblclick', _this4, e);
+      });
+      /* Drag or resize on mousemove. */
+
+      (this.drag || this.resize) && function () {
+        var container = _this4.wavesurfer.drawer.container;
+
+        var duration = _this4.wavesurfer.getDuration();
+
+        var scrollSpeed = _this4.scrollSpeed;
+        var scrollThreshold = _this4.scrollThreshold;
+        var startTime;
+        var touchId;
+        var drag;
+        var maxScroll;
+        var resize;
+        var updated = false;
+        var scrollDirection;
+        var wrapperRect; // Scroll when the user is dragging within the threshold
+
+        var edgeScroll = function edgeScroll(e) {
+          if (!scrollDirection || !drag && !resize) {
+            return;
+          } // Update scroll position
+
+
+          var scrollLeft = _this4.wrapper.scrollLeft + scrollSpeed * scrollDirection;
+          _this4.wrapper.scrollLeft = scrollLeft = Math.min(maxScroll, Math.max(0, scrollLeft)); // Update time
+
+          var time = _this4.wavesurfer.drawer.handleEvent(e) * duration;
+          var delta = time - startTime;
+          startTime = time; // Continue dragging or resizing
+
+          drag ? _this4.onDrag(delta) : _this4.onResize(delta, resize); // Repeat
+
+          window.requestAnimationFrame(function () {
+            edgeScroll(e);
+          });
+        };
+
+        var onDown = function onDown(e) {
+          if (e.touches && e.touches.length > 1) {
+            return;
+          }
+
+          touchId = e.targetTouches ? e.targetTouches[0].identifier : null;
+          e.stopPropagation();
+          startTime = _this4.wavesurfer.drawer.handleEvent(e, true) * duration; // Store for scroll calculations
+
+          maxScroll = _this4.wrapper.scrollWidth - _this4.wrapper.clientWidth;
+          wrapperRect = _this4.wrapper.getBoundingClientRect();
+
+          if (e.target.tagName.toLowerCase() == 'handle') {
+            if (e.target.classList.contains('wavesurfer-handle-start')) {
+              resize = 'start';
+            } else {
+              resize = 'end';
+            }
+          } else {
+            drag = true;
+            resize = false;
+          }
+        };
+
+        var onUp = function onUp(e) {
+          if (e.touches && e.touches.length > 1) {
+            return;
+          }
+
+          if (drag || resize) {
+            drag = false;
+            scrollDirection = null;
+            resize = false;
+          }
+
+          if (updated) {
+            updated = false;
+
+            _this4.util.preventClick();
+
+            _this4.fireEvent('update-end', e);
+
+            _this4.wavesurfer.fireEvent('region-update-end', _this4, e);
+          }
+        };
+
+        var onMove = function onMove(e) {
+          if (e.touches && e.touches.length > 1) {
+            return;
+          }
+
+          if (e.targetTouches && e.targetTouches[0].identifier != touchId) {
+            return;
+          }
+
+          if (drag || resize) {
+            var oldTime = startTime;
+            var time = _this4.wavesurfer.drawer.handleEvent(e) * duration;
+            var delta = time - startTime;
+            startTime = time; // Drag
+
+            if (_this4.drag && drag) {
+              updated = updated || !!delta;
+
+              _this4.onDrag(delta);
+            } // Resize
+
+
+            if (_this4.resize && resize) {
+              updated = updated || !!delta;
+
+              _this4.onResize(delta, resize);
+            }
+
+            if (_this4.scroll && container.clientWidth < _this4.wrapper.scrollWidth) {
+              if (drag) {
+                // The threshold is not between the mouse and the container edge
+                // but is between the region and the container edge
+                var regionRect = _this4.element.getBoundingClientRect();
+
+                var x = regionRect.left - wrapperRect.left; // Check direction
+
+                if (time < oldTime && x >= 0) {
+                  scrollDirection = -1;
+                } else if (time > oldTime && x + regionRect.width <= wrapperRect.right) {
+                  scrollDirection = 1;
+                } // Check that we are still beyond the threshold
+
+
+                if (scrollDirection === -1 && x > scrollThreshold || scrollDirection === 1 && x + regionRect.width < wrapperRect.right - scrollThreshold) {
+                  scrollDirection = null;
+                }
+              } else {
+                // Mouse based threshold
+                var _x = e.clientX - wrapperRect.left; // Check direction
+
+
+                if (_x <= scrollThreshold) {
+                  scrollDirection = -1;
+                } else if (_x >= wrapperRect.right - scrollThreshold) {
+                  scrollDirection = 1;
+                } else {
+                  scrollDirection = null;
+                }
+              }
+
+              scrollDirection && edgeScroll(e);
+            }
+          }
+        };
+
+        _this4.element.addEventListener('mousedown', onDown);
+
+        _this4.element.addEventListener('touchstart', onDown);
+
+        _this4.wrapper.addEventListener('mousemove', onMove);
+
+        _this4.wrapper.addEventListener('touchmove', onMove);
+
+        document.body.addEventListener('mouseup', onUp);
+        document.body.addEventListener('touchend', onUp);
+
+        _this4.on('remove', function () {
+          document.body.removeEventListener('mouseup', onUp);
+          document.body.removeEventListener('touchend', onUp);
+
+          _this4.wrapper.removeEventListener('mousemove', onMove);
+
+          _this4.wrapper.removeEventListener('touchmove', onMove);
+        });
+
+        _this4.wavesurfer.on('destroy', function () {
+          document.body.removeEventListener('mouseup', onUp);
+          document.body.removeEventListener('touchend', onUp);
+        });
+      }();
+    }
+  }, {
+    key: "onDrag",
+    value: function onDrag(delta) {
+      var maxEnd = this.wavesurfer.getDuration();
+
+      if (this.end + delta > maxEnd || this.start + delta < 0) {
+        return;
+      }
+
+      this.update({
+        start: this.start + delta,
+        end: this.end + delta
+      });
+    }
+  }, {
+    key: "onResize",
+    value: function onResize(delta, direction) {
+      if (direction == 'start') {
+        this.update({
+          start: Math.min(this.start + delta, this.end),
+          end: Math.max(this.start + delta, this.end)
+        });
+      } else {
+        this.update({
+          start: Math.min(this.end + delta, this.start),
+          end: Math.max(this.end + delta, this.start)
+        });
+      }
+    }
+  }]);
+
+  return Region;
+}();
+/**
+ * @typedef {Object} RegionsPluginParams
+ * @property {?boolean} dragSelection Enable creating regions by dragging with
+ * the mouse
+ * @property {?RegionParams[]} regions Regions that should be added upon
+ * initialisation
+ * @property {number} slop=2 The sensitivity of the mouse dragging
+ * @property {?boolean} deferInit Set to true to manually call
+ * `initPlugin('regions')`
+ */
+
+/**
+ * @typedef {Object} RegionParams
+ * @desc The parameters used to describe a region.
+ * @example wavesurfer.addRegion(regionParams);
+ * @property {string} id=ârandom The id of the region
+ * @property {number} start=0 The start position of the region (in seconds).
+ * @property {number} end=0 The end position of the region (in seconds).
+ * @property {?boolean} loop Whether to loop the region when played back.
+ * @property {boolean} drag=true Allow/disallow dragging the region.
+ * @property {boolean} resize=true Allow/disallow resizing the region.
+ * @property {string} [color='rgba(0, 0, 0, 0.1)'] HTML color code.
+ */
+
+/**
+ * Regions are visual overlays on waveform that can be used to play and loop
+ * portions of audio. Regions can be dragged and resized.
+ *
+ * Visual customization is possible via CSS (using the selectors
+ * `.wavesurfer-region` and `.wavesurfer-handle`).
+ *
+ * @implements {PluginClass}
+ * @extends {Observer}
+ *
+ * @example
+ * // es6
+ * import RegionsPlugin from 'wavesurfer.regions.js';
+ *
+ * // commonjs
+ * var RegionsPlugin = require('wavesurfer.regions.js');
+ *
+ * // if you are using <script> tags
+ * var RegionsPlugin = window.WaveSurfer.regions;
+ *
+ * // ... initialising wavesurfer with the plugin
+ * var wavesurfer = WaveSurfer.create({
+ *   // wavesurfer options ...
+ *   plugins: [
+ *     RegionsPlugin.create({
+ *       // plugin options ...
+ *     })
+ *   ]
+ * });
+ */
+
+
+var RegionsPlugin =
+/*#__PURE__*/
+function () {
+  _createClass(RegionsPlugin, null, [{
+    key: "create",
+
+    /**
+     * Regions plugin definition factory
+     *
+     * This function must be used to create a plugin definition which can be
+     * used by wavesurfer to correctly instantiate the plugin.
+     *
+     * @param {RegionsPluginParams} params parameters use to initialise the plugin
+     * @return {PluginDefinition} an object representing the plugin
+     */
+    value: function create(params) {
+      return {
+        name: 'regions',
+        deferInit: params && params.deferInit ? params.deferInit : false,
+        params: params,
+        staticProps: {
+          initRegions: function initRegions() {
+            console.warn('Deprecated initRegions! Use wavesurfer.initPlugins("regions") instead!');
+            this.initPlugin('regions');
+          },
+          addRegion: function addRegion(options) {
+            if (!this.initialisedPluginList.regions) {
+              this.initPlugin('regions');
+            }
+
+            return this.regions.add(options);
+          },
+          clearRegions: function clearRegions() {
+            this.regions && this.regions.clear();
+          },
+          enableDragSelection: function enableDragSelection(options) {
+            if (!this.initialisedPluginList.regions) {
+              this.initPlugin('regions');
+            }
+
+            this.regions.enableDragSelection(options);
+          },
+          disableDragSelection: function disableDragSelection() {
+            this.regions.disableDragSelection();
+          }
+        },
+        instance: RegionsPlugin
+      };
+    }
+  }]);
+
+  function RegionsPlugin(params, ws) {
+    var _this5 = this;
+
+    _classCallCheck(this, RegionsPlugin);
+
+    this.params = params;
+    this.wavesurfer = ws;
+    this.util = ws.util; // turn the plugin instance into an observer
+
+    var observerPrototypeKeys = Object.getOwnPropertyNames(this.util.Observer.prototype);
+    observerPrototypeKeys.forEach(function (key) {
+      Region.prototype[key] = _this5.util.Observer.prototype[key];
+    });
+    this.wavesurfer.Region = Region;
+
+    this._onBackendCreated = function () {
+      _this5.wrapper = _this5.wavesurfer.drawer.wrapper;
+
+      if (_this5.params.regions) {
+        _this5.params.regions.forEach(function (region) {
+          _this5.add(region);
+        });
+      }
+    }; // Id-based hash of regions.
+
+
+    this.list = {};
+
+    this._onReady = function () {
+      if (_this5.params.dragSelection) {
+        _this5.enableDragSelection(_this5.params);
+      }
+
+      Object.keys(_this5.list).forEach(function (id) {
+        _this5.list[id].updateRender();
+      });
+    };
+  }
+
+  _createClass(RegionsPlugin, [{
+    key: "init",
+    value: function init() {
+      // Check if ws is ready
+      if (this.wavesurfer.isReady) {
+        this._onBackendCreated();
+
+        this._onReady();
+      }
+
+      this.wavesurfer.on('ready', this._onReady);
+      this.wavesurfer.on('backend-created', this._onBackendCreated);
+    }
+  }, {
+    key: "destroy",
+    value: function destroy() {
+      this.wavesurfer.un('ready', this._onReady);
+      this.wavesurfer.un('backend-created', this._onBackendCreated);
+      this.disableDragSelection();
+      this.clear();
+    }
+    /* Add a region. */
+
+  }, {
+    key: "add",
+    value: function add(params) {
+      var _this6 = this;
+
+      var region = new this.wavesurfer.Region(params, this.wavesurfer);
+      this.list[region.id] = region;
+      region.on('remove', function () {
+        delete _this6.list[region.id];
+      });
+      return region;
+    }
+    /* Remove all regions. */
+
+  }, {
+    key: "clear",
+    value: function clear() {
+      var _this7 = this;
+
+      Object.keys(this.list).forEach(function (id) {
+        _this7.list[id].remove();
+      });
+    }
+  }, {
+    key: "enableDragSelection",
+    value: function enableDragSelection(params) {
+      var _this8 = this;
+
+      var slop = params.slop || 2;
+      var container = this.wavesurfer.drawer.container;
+      var scroll = params.scroll !== false && this.wavesurfer.params.scrollParent;
+      var scrollSpeed = params.scrollSpeed || 1;
+      var scrollThreshold = params.scrollThreshold || 10;
+      var drag;
+      var duration = this.wavesurfer.getDuration();
+      var maxScroll;
+      var start;
+      var region;
+      var touchId;
+      var pxMove = 0;
+      var scrollDirection;
+      var wrapperRect; // Scroll when the user is dragging within the threshold
+
+      var edgeScroll = function edgeScroll(e) {
+        if (!region || !scrollDirection) {
+          return;
+        } // Update scroll position
+
+
+        var scrollLeft = _this8.wrapper.scrollLeft + scrollSpeed * scrollDirection;
+        _this8.wrapper.scrollLeft = scrollLeft = Math.min(maxScroll, Math.max(0, scrollLeft)); // Update range
+
+        var end = _this8.wavesurfer.drawer.handleEvent(e);
+
+        region.update({
+          start: Math.min(end * duration, start * duration),
+          end: Math.max(end * duration, start * duration)
+        }); // Check that there is more to scroll and repeat
+
+        if (scrollLeft < maxScroll && scrollLeft > 0) {
+          window.requestAnimationFrame(function () {
+            edgeScroll(e);
+          });
+        }
+      };
+
+      var eventDown = function eventDown(e) {
+        if (e.touches && e.touches.length > 1) {
+          return;
+        }
+
+        duration = _this8.wavesurfer.getDuration();
+        touchId = e.targetTouches ? e.targetTouches[0].identifier : null; // Store for scroll calculations
+
+        maxScroll = _this8.wrapper.scrollWidth - _this8.wrapper.clientWidth;
+        wrapperRect = _this8.wrapper.getBoundingClientRect();
+        drag = true;
+        start = _this8.wavesurfer.drawer.handleEvent(e, true);
+        region = null;
+        scrollDirection = null;
+      };
+
+      this.wrapper.addEventListener('mousedown', eventDown);
+      this.wrapper.addEventListener('touchstart', eventDown);
+      this.on('disable-drag-selection', function () {
+        _this8.wrapper.removeEventListener('touchstart', eventDown);
+
+        _this8.wrapper.removeEventListener('mousedown', eventDown);
+      });
+
+      var eventUp = function eventUp(e) {
+        if (e.touches && e.touches.length > 1) {
+          return;
+        }
+
+        drag = false;
+        pxMove = 0;
+        scrollDirection = null;
+
+        if (region) {
+          _this8.util.preventClick();
+
+          region.fireEvent('update-end', e);
+
+          _this8.wavesurfer.fireEvent('region-update-end', region, e);
+        }
+
+        region = null;
+      };
+
+      this.wrapper.addEventListener('mouseup', eventUp);
+      this.wrapper.addEventListener('touchend', eventUp);
+      document.body.addEventListener('mouseup', eventUp);
+      document.body.addEventListener('touchend', eventUp);
+      this.on('disable-drag-selection', function () {
+        document.body.removeEventListener('mouseup', eventUp);
+        document.body.removeEventListener('touchend', eventUp);
+
+        _this8.wrapper.removeEventListener('touchend', eventUp);
+
+        _this8.wrapper.removeEventListener('mouseup', eventUp);
+      });
+
+      var eventMove = function eventMove(e) {
+        if (!drag) {
+          return;
+        }
+
+        if (++pxMove <= slop) {
+          return;
+        }
+
+        if (e.touches && e.touches.length > 1) {
+          return;
+        }
+
+        if (e.targetTouches && e.targetTouches[0].identifier != touchId) {
+          return;
+        }
+
+        if (!region) {
+          region = _this8.add(params || {});
+        }
+
+        var end = _this8.wavesurfer.drawer.handleEvent(e);
+
+        region.update({
+          start: Math.min(end * duration, start * duration),
+          end: Math.max(end * duration, start * duration)
+        }); // If scrolling is enabled
+
+        if (scroll && container.clientWidth < _this8.wrapper.scrollWidth) {
+          // Check threshold based on mouse
+          var x = e.clientX - wrapperRect.left;
+
+          if (x <= scrollThreshold) {
+            scrollDirection = -1;
+          } else if (x >= wrapperRect.right - scrollThreshold) {
+            scrollDirection = 1;
+          } else {
+            scrollDirection = null;
+          }
+
+          scrollDirection && edgeScroll(e);
+        }
+      };
+
+      this.wrapper.addEventListener('mousemove', eventMove);
+      this.wrapper.addEventListener('touchmove', eventMove);
+      this.on('disable-drag-selection', function () {
+        _this8.wrapper.removeEventListener('touchmove', eventMove);
+
+        _this8.wrapper.removeEventListener('mousemove', eventMove);
+      });
+    }
+  }, {
+    key: "disableDragSelection",
+    value: function disableDragSelection() {
+      this.fireEvent('disable-drag-selection');
+    }
+    /* Get current region
+     *  The smallest region that contains the current time.
+     *  If several such regions exist, we take the first.
+     *  Return null if none exist. */
+
+  }, {
+    key: "getCurrentRegion",
+    value: function getCurrentRegion() {
+      var _this9 = this;
+
+      var time = this.wavesurfer.getCurrentTime();
+      var min = null;
+      Object.keys(this.list).forEach(function (id) {
+        var cur = _this9.list[id];
+
+        if (cur.start <= time && cur.end >= time) {
+          if (!min || cur.end - cur.start < min.end - min.start) {
+            min = cur;
+          }
+        }
+      });
+      return min;
+    }
+  }]);
+
+  return RegionsPlugin;
+}();
+
+exports.default = RegionsPlugin;
+module.exports = exports.default;
+
+/***/ })
+
+/******/ });
+});
+//# sourceMappingURL=wavesurfer.regions.js.map
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.regions.js.map
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.regions.js.map	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.regions.js.map	(revision 33546)
@@ -0,0 +1,1 @@
+{"version":3,"sources":["webpack://WaveSurfer.[name]/webpack/universalModuleDefinition","webpack://WaveSurfer.[name]/webpack/bootstrap","webpack://WaveSurfer.[name]/./src/plugin/regions.js"],"names":["Region","params","ws","wavesurfer","wrapper","drawer","util","style","id","getId","start","Number","end","scrollWidth","getDuration","resize","undefined","Boolean","drag","loop","color","data","attributes","maxLength","minLength","_onRedraw","updateRender","scroll","scrollParent","scrollSpeed","scrollThreshold","bindInOut","render","on","fireEvent","element","removeChild","un","play","once","playLoop","regionEl","document","createElement","className","title","formatTime","setAttribute","attrname","width","position","zIndex","height","top","handleLeft","appendChild","handleRight","css","cursor","left","maxWidth","bindEvents","map","time","Math","floor","slice","join","pixelRatio","dur","getWidth","startLimited","endLimited","max","min","round","regionWidth","backgroundColor","firedIn","firedOut","onProcess","backend","addEventListener","e","preventDefault","stopPropagation","container","duration","startTime","touchId","maxScroll","updated","scrollDirection","wrapperRect","edgeScroll","scrollLeft","handleEvent","delta","onDrag","onResize","window","requestAnimationFrame","onDown","touches","length","targetTouches","identifier","clientWidth","getBoundingClientRect","target","tagName","toLowerCase","classList","contains","onUp","preventClick","onMove","oldTime","regionRect","x","right","clientX","body","removeEventListener","maxEnd","update","direction","RegionsPlugin","name","deferInit","staticProps","initRegions","console","warn","initPlugin","addRegion","options","initialisedPluginList","regions","add","clearRegions","clear","enableDragSelection","disableDragSelection","instance","observerPrototypeKeys","Object","getOwnPropertyNames","Observer","prototype","forEach","key","_onBackendCreated","region","list","_onReady","dragSelection","keys","isReady","remove","slop","pxMove","eventDown","eventUp","eventMove","getCurrentTime","cur"],"mappings":";;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+CAA+C;AAC/C,CAAC;AACD,O;QCVA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;;QAEA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;;;QAGA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA,0CAA0C,gCAAgC;QAC1E;QACA;;QAEA;QACA;QACA;QACA,wDAAwD,kBAAkB;QAC1E;QACA,iDAAiD,cAAc;QAC/D;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA,yCAAyC,iCAAiC;QAC1E,gHAAgH,mBAAmB,EAAE;QACrI;QACA;;QAEA;QACA;QACA;QACA,2BAA2B,0BAA0B,EAAE;QACvD,iCAAiC,eAAe;QAChD;QACA;QACA;;QAEA;QACA,sDAAsD,+DAA+D;;QAErH;QACA;;;QAGA;QACA;;;;;;;;;;;;;;;;;;;;;;;;;;AClFA;;;;;;;;IAQMA,M;;;AACF,kBAAYC,MAAZ,EAAoBC,EAApB,EAAwB;AAAA;;AAAA;;AACpB,SAAKC,UAAL,GAAkBD,EAAlB;AACA,SAAKE,OAAL,GAAeF,EAAE,CAACG,MAAH,CAAUD,OAAzB;AACA,SAAKE,IAAL,GAAYJ,EAAE,CAACI,IAAf;AACA,SAAKC,KAAL,GAAa,KAAKD,IAAL,CAAUC,KAAvB;AAEA,SAAKC,EAAL,GAAUP,MAAM,CAACO,EAAP,IAAa,IAAb,GAAoBN,EAAE,CAACI,IAAH,CAAQG,KAAR,EAApB,GAAsCR,MAAM,CAACO,EAAvD;AACA,SAAKE,KAAL,GAAaC,MAAM,CAACV,MAAM,CAACS,KAAR,CAAN,IAAwB,CAArC;AACA,SAAKE,GAAL,GACIX,MAAM,CAACW,GAAP,IAAc,IAAd,GACM;AACA,SAAKF,KAAL,GACC,IAAI,KAAKN,OAAL,CAAaS,WAAlB,GAAiC,KAAKV,UAAL,CAAgBW,WAAhB,EAHvC,GAIMH,MAAM,CAACV,MAAM,CAACW,GAAR,CALhB;AAMA,SAAKG,MAAL,GACId,MAAM,CAACc,MAAP,KAAkBC,SAAlB,GAA8B,IAA9B,GAAqCC,OAAO,CAAChB,MAAM,CAACc,MAAR,CADhD;AAEA,SAAKG,IAAL,GAAYjB,MAAM,CAACiB,IAAP,KAAgBF,SAAhB,GAA4B,IAA5B,GAAmCC,OAAO,CAAChB,MAAM,CAACiB,IAAR,CAAtD;AACA,SAAKC,IAAL,GAAYF,OAAO,CAAChB,MAAM,CAACkB,IAAR,CAAnB;AACA,SAAKC,KAAL,GAAanB,MAAM,CAACmB,KAAP,IAAgB,oBAA7B;AACA,SAAKC,IAAL,GAAYpB,MAAM,CAACoB,IAAP,IAAe,EAA3B;AACA,SAAKC,UAAL,GAAkBrB,MAAM,CAACqB,UAAP,IAAqB,EAAvC;AAEA,SAAKC,SAAL,GAAiBtB,MAAM,CAACsB,SAAxB;AACA,SAAKC,SAAL,GAAiBvB,MAAM,CAACuB,SAAxB;;AACA,SAAKC,SAAL,GAAiB;AAAA,aAAM,KAAI,CAACC,YAAL,EAAN;AAAA,KAAjB;;AAEA,SAAKC,MAAL,GAAc1B,MAAM,CAAC0B,MAAP,KAAkB,KAAlB,IAA2BzB,EAAE,CAACD,MAAH,CAAU2B,YAAnD;AACA,SAAKC,WAAL,GAAmB5B,MAAM,CAAC4B,WAAP,IAAsB,CAAzC;AACA,SAAKC,eAAL,GAAuB7B,MAAM,CAAC6B,eAAP,IAA0B,EAAjD;AAEA,SAAKC,SAAL;AACA,SAAKC,MAAL;AACA,SAAK7B,UAAL,CAAgB8B,EAAhB,CAAmB,MAAnB,EAA2B,KAAKR,SAAhC;AACA,SAAKtB,UAAL,CAAgB8B,EAAhB,CAAmB,QAAnB,EAA6B,KAAKR,SAAlC;AACA,SAAKtB,UAAL,CAAgB+B,SAAhB,CAA0B,gBAA1B,EAA4C,IAA5C;AACH;AAED;;;;;2BACOjC,M,EAAQ;AACX,UAAI,QAAQA,MAAM,CAACS,KAAnB,EAA0B;AACtB,aAAKA,KAAL,GAAaC,MAAM,CAACV,MAAM,CAACS,KAAR,CAAnB;AACH;;AACD,UAAI,QAAQT,MAAM,CAACW,GAAnB,EAAwB;AACpB,aAAKA,GAAL,GAAWD,MAAM,CAACV,MAAM,CAACW,GAAR,CAAjB;AACH;;AACD,UAAI,QAAQX,MAAM,CAACkB,IAAnB,EAAyB;AACrB,aAAKA,IAAL,GAAYF,OAAO,CAAChB,MAAM,CAACkB,IAAR,CAAnB;AACH;;AACD,UAAI,QAAQlB,MAAM,CAACmB,KAAnB,EAA0B;AACtB,aAAKA,KAAL,GAAanB,MAAM,CAACmB,KAApB;AACH;;AACD,UAAI,QAAQnB,MAAM,CAACoB,IAAnB,EAAyB;AACrB,aAAKA,IAAL,GAAYpB,MAAM,CAACoB,IAAnB;AACH;;AACD,UAAI,QAAQpB,MAAM,CAACc,MAAnB,EAA2B;AACvB,aAAKA,MAAL,GAAcE,OAAO,CAAChB,MAAM,CAACc,MAAR,CAArB;AACH;;AACD,UAAI,QAAQd,MAAM,CAACiB,IAAnB,EAAyB;AACrB,aAAKA,IAAL,GAAYD,OAAO,CAAChB,MAAM,CAACiB,IAAR,CAAnB;AACH;;AACD,UAAI,QAAQjB,MAAM,CAACsB,SAAnB,EAA8B;AAC1B,aAAKA,SAAL,GAAiBZ,MAAM,CAACV,MAAM,CAACsB,SAAR,CAAvB;AACH;;AACD,UAAI,QAAQtB,MAAM,CAACuB,SAAnB,EAA8B;AAC1B,aAAKA,SAAL,GAAiBb,MAAM,CAACV,MAAM,CAACuB,SAAR,CAAvB;AACH;;AACD,UAAI,QAAQvB,MAAM,CAACqB,UAAnB,EAA+B;AAC3B,aAAKA,UAAL,GAAkBrB,MAAM,CAACqB,UAAzB;AACH;;AAED,WAAKI,YAAL;AACA,WAAKQ,SAAL,CAAe,QAAf;AACA,WAAK/B,UAAL,CAAgB+B,SAAhB,CAA0B,gBAA1B,EAA4C,IAA5C;AACH;AAED;;;;6BACS;AACL,UAAI,KAAKC,OAAT,EAAkB;AACd,aAAK/B,OAAL,CAAagC,WAAb,CAAyB,KAAKD,OAA9B;AACA,aAAKA,OAAL,GAAe,IAAf;AACA,aAAKD,SAAL,CAAe,QAAf;AACA,aAAK/B,UAAL,CAAgBkC,EAAhB,CAAmB,MAAnB,EAA2B,KAAKZ,SAAhC;AACA,aAAKtB,UAAL,CAAgBkC,EAAhB,CAAmB,QAAnB,EAA6B,KAAKZ,SAAlC;AACA,aAAKtB,UAAL,CAAgB+B,SAAhB,CAA0B,gBAA1B,EAA4C,IAA5C;AACH;AACJ;AAED;;;;2BACO;AACH,WAAK/B,UAAL,CAAgBmC,IAAhB,CAAqB,KAAK5B,KAA1B,EAAiC,KAAKE,GAAtC;AACA,WAAKsB,SAAL,CAAe,MAAf;AACA,WAAK/B,UAAL,CAAgB+B,SAAhB,CAA0B,aAA1B,EAAyC,IAAzC;AACH;AAED;;;;+BACW;AAAA;;AACP,WAAKI,IAAL;AACA,WAAKC,IAAL,CAAU,KAAV,EAAiB;AAAA,eAAM,MAAI,CAACC,QAAL,EAAN;AAAA,OAAjB;AACH;AAED;;;;6BACS;AACL,UAAMC,QAAQ,GAAGC,QAAQ,CAACC,aAAT,CAAuB,QAAvB,CAAjB;AACAF,cAAQ,CAACG,SAAT,GAAqB,mBAArB;AACAH,cAAQ,CAACI,KAAT,GAAiB,KAAKC,UAAL,CAAgB,KAAKpC,KAArB,EAA4B,KAAKE,GAAjC,CAAjB;AACA6B,cAAQ,CAACM,YAAT,CAAsB,SAAtB,EAAiC,KAAKvC,EAAtC;;AAEA,WAAK,IAAMwC,QAAX,IAAuB,KAAK1B,UAA5B,EAAwC;AACpCmB,gBAAQ,CAACM,YAAT,CACI,iBAAiBC,QADrB,EAEI,KAAK1B,UAAL,CAAgB0B,QAAhB,CAFJ;AAIH;;AAED,UAAMC,KAAK,GAAG,KAAK7C,OAAL,CAAaS,WAA3B;AACA,WAAKN,KAAL,CAAWkC,QAAX,EAAqB;AACjBS,gBAAQ,EAAE,UADO;AAEjBC,cAAM,EAAE,CAFS;AAGjBC,cAAM,EAAE,MAHS;AAIjBC,WAAG,EAAE;AAJY,OAArB;AAOA;;AACA,UAAI,KAAKtC,MAAT,EAAiB;AACb,YAAMuC,UAAU,GAAGb,QAAQ,CAACc,WAAT,CACfb,QAAQ,CAACC,aAAT,CAAuB,QAAvB,CADe,CAAnB;AAGA,YAAMa,WAAW,GAAGf,QAAQ,CAACc,WAAT,CAChBb,QAAQ,CAACC,aAAT,CAAuB,QAAvB,CADgB,CAApB;AAGAW,kBAAU,CAACV,SAAX,GAAuB,2CAAvB;AACAY,mBAAW,CAACZ,SAAZ,GAAwB,yCAAxB;AACA,YAAMa,GAAG,GAAG;AACRC,gBAAM,EAAE,YADA;AAERR,kBAAQ,EAAE,UAFF;AAGRS,cAAI,EAAE,KAHE;AAIRN,aAAG,EAAE,KAJG;AAKRJ,eAAK,EAAE,IALC;AAMRW,kBAAQ,EAAE,KANF;AAORR,gBAAM,EAAE;AAPA,SAAZ;AASA,aAAK7C,KAAL,CAAW+C,UAAX,EAAuBG,GAAvB;AACA,aAAKlD,KAAL,CAAWiD,WAAX,EAAwBC,GAAxB;AACA,aAAKlD,KAAL,CAAWiD,WAAX,EAAwB;AACpBG,cAAI,EAAE;AADc,SAAxB;AAGH;;AAED,WAAKxB,OAAL,GAAe,KAAK/B,OAAL,CAAamD,WAAb,CAAyBd,QAAzB,CAAf;AACA,WAAKf,YAAL;AACA,WAAKmC,UAAL,CAAgBpB,QAAhB;AACH;;;+BAEU/B,K,EAAOE,G,EAAK;AACnB,aAAO,CAACF,KAAK,IAAIE,GAAT,GAAe,CAACF,KAAD,CAAf,GAAyB,CAACA,KAAD,EAAQE,GAAR,CAA1B,EACFkD,GADE,CACE,UAAAC,IAAI;AAAA,eACL,CACIC,IAAI,CAACC,KAAL,CAAYF,IAAI,GAAG,IAAR,GAAgB,EAA3B,CADJ,EACoC;AAChC,SAAC,OAAOC,IAAI,CAACC,KAAL,CAAWF,IAAI,GAAG,EAAlB,CAAR,EAA+BG,KAA/B,CAAqC,CAAC,CAAtC,CAFJ,CAE6C;AAF7C,UAGEC,IAHF,CAGO,GAHP,CADK;AAAA,OADN,EAOFA,IAPE,CAOG,GAPH,CAAP;AAQH;;;+BAEU;AACP,aAAO,KAAKhE,UAAL,CAAgBE,MAAhB,CAAuB4C,KAAvB,GAA+B,KAAK9C,UAAL,CAAgBF,MAAhB,CAAuBmE,UAA7D;AACH;AAED;;;;mCACe;AACX;AACA,UAAMC,GAAG,GAAG,KAAKlE,UAAL,CAAgBW,WAAhB,EAAZ;AACA,UAAMmC,KAAK,GAAG,KAAKqB,QAAL,EAAd;AAEA,UAAIC,YAAY,GAAG,KAAK7D,KAAxB;AACA,UAAI8D,UAAU,GAAG,KAAK5D,GAAtB;;AACA,UAAI2D,YAAY,GAAG,CAAnB,EAAsB;AAClBA,oBAAY,GAAG,CAAf;AACAC,kBAAU,GAAGA,UAAU,GAAGD,YAA1B;AACH;;AACD,UAAIC,UAAU,GAAGH,GAAjB,EAAsB;AAClBG,kBAAU,GAAGH,GAAb;AACAE,oBAAY,GAAGF,GAAG,IAAIG,UAAU,GAAGD,YAAjB,CAAlB;AACH;;AAED,UAAI,KAAK/C,SAAL,IAAkB,IAAtB,EAA4B;AACxBgD,kBAAU,GAAGR,IAAI,CAACS,GAAL,CAASF,YAAY,GAAG,KAAK/C,SAA7B,EAAwCgD,UAAxC,CAAb;AACH;;AAED,UAAI,KAAKjD,SAAL,IAAkB,IAAtB,EAA4B;AACxBiD,kBAAU,GAAGR,IAAI,CAACU,GAAL,CAASH,YAAY,GAAG,KAAKhD,SAA7B,EAAwCiD,UAAxC,CAAb;AACH;;AAED,UAAI,KAAKrC,OAAL,IAAgB,IAApB,EAA0B;AACtB;AACA;AACA,YAAMwB,IAAI,GAAGK,IAAI,CAACW,KAAL,CAAYJ,YAAY,GAAGF,GAAhB,GAAuBpB,KAAlC,CAAb;AACA,YAAM2B,WAAW,GAAGZ,IAAI,CAACW,KAAL,CAAYH,UAAU,GAAGH,GAAd,GAAqBpB,KAAhC,IAAyCU,IAA7D;AAEA,aAAKpD,KAAL,CAAW,KAAK4B,OAAhB,EAAyB;AACrBwB,cAAI,EAAEA,IAAI,GAAG,IADQ;AAErBV,eAAK,EAAE2B,WAAW,GAAG,IAFA;AAGrBC,yBAAe,EAAE,KAAKzD,KAHD;AAIrBsC,gBAAM,EAAE,KAAKxC,IAAL,GAAY,MAAZ,GAAqB;AAJR,SAAzB;;AAOA,aAAK,IAAM8B,QAAX,IAAuB,KAAK1B,UAA5B,EAAwC;AACpC,eAAKa,OAAL,CAAaY,YAAb,CACI,iBAAiBC,QADrB,EAEI,KAAK1B,UAAL,CAAgB0B,QAAhB,CAFJ;AAIH;;AAED,aAAKb,OAAL,CAAaU,KAAb,GAAqB,KAAKC,UAAL,CAAgB,KAAKpC,KAArB,EAA4B,KAAKE,GAAjC,CAArB;AACH;AACJ;AAED;;;;gCACY;AAAA;;AACR,WAAKkE,OAAL,GAAe,KAAf;AACA,WAAKC,QAAL,GAAgB,KAAhB;;AAEA,UAAMC,SAAS,GAAG,SAAZA,SAAY,CAAAjB,IAAI,EAAI;AACtB,YACI,CAAC,MAAI,CAACgB,QAAN,IACA,MAAI,CAACD,OADL,KAEC,MAAI,CAACpE,KAAL,IAAcsD,IAAI,CAACW,KAAL,CAAWZ,IAAI,GAAG,GAAlB,IAAyB,GAAvC,IACG,MAAI,CAACnD,GAAL,IAAYoD,IAAI,CAACW,KAAL,CAAWZ,IAAI,GAAG,GAAlB,IAAyB,GAHzC,CADJ,EAKE;AACE,gBAAI,CAACgB,QAAL,GAAgB,IAAhB;AACA,gBAAI,CAACD,OAAL,GAAe,KAAf;;AACA,gBAAI,CAAC5C,SAAL,CAAe,KAAf;;AACA,gBAAI,CAAC/B,UAAL,CAAgB+B,SAAhB,CAA0B,YAA1B,EAAwC,MAAxC;AACH;;AACD,YAAI,CAAC,MAAI,CAAC4C,OAAN,IAAiB,MAAI,CAACpE,KAAL,IAAcqD,IAA/B,IAAuC,MAAI,CAACnD,GAAL,GAAWmD,IAAtD,EAA4D;AACxD,gBAAI,CAACe,OAAL,GAAe,IAAf;AACA,gBAAI,CAACC,QAAL,GAAgB,KAAhB;;AACA,gBAAI,CAAC7C,SAAL,CAAe,IAAf;;AACA,gBAAI,CAAC/B,UAAL,CAAgB+B,SAAhB,CAA0B,WAA1B,EAAuC,MAAvC;AACH;AACJ,OAlBD;;AAoBA,WAAK/B,UAAL,CAAgB8E,OAAhB,CAAwBhD,EAAxB,CAA2B,cAA3B,EAA2C+C,SAA3C;AAEA,WAAK/C,EAAL,CAAQ,QAAR,EAAkB,YAAM;AACpB,cAAI,CAAC9B,UAAL,CAAgB8E,OAAhB,CAAwB5C,EAAxB,CAA2B,cAA3B,EAA2C2C,SAA3C;AACH,OAFD;AAIA;;AACA,WAAK/C,EAAL,CAAQ,KAAR,EAAe,YAAM;AACjB,YAAI,MAAI,CAACd,IAAT,EAAe;AACX,gBAAI,CAAChB,UAAL,CAAgBmC,IAAhB,CAAqB,MAAI,CAAC5B,KAA1B;AACH;AACJ,OAJD;AAKH;AAED;;;;iCACa;AAAA;;AACT,WAAKyB,OAAL,CAAa+C,gBAAb,CAA8B,YAA9B,EAA4C,UAAAC,CAAC,EAAI;AAC7C,cAAI,CAACjD,SAAL,CAAe,YAAf,EAA6BiD,CAA7B;;AACA,cAAI,CAAChF,UAAL,CAAgB+B,SAAhB,CAA0B,mBAA1B,EAA+C,MAA/C,EAAqDiD,CAArD;AACH,OAHD;AAKA,WAAKhD,OAAL,CAAa+C,gBAAb,CAA8B,YAA9B,EAA4C,UAAAC,CAAC,EAAI;AAC7C,cAAI,CAACjD,SAAL,CAAe,YAAf,EAA6BiD,CAA7B;;AACA,cAAI,CAAChF,UAAL,CAAgB+B,SAAhB,CAA0B,mBAA1B,EAA+C,MAA/C,EAAqDiD,CAArD;AACH,OAHD;AAKA,WAAKhD,OAAL,CAAa+C,gBAAb,CAA8B,OAA9B,EAAuC,UAAAC,CAAC,EAAI;AACxCA,SAAC,CAACC,cAAF;;AACA,cAAI,CAAClD,SAAL,CAAe,OAAf,EAAwBiD,CAAxB;;AACA,cAAI,CAAChF,UAAL,CAAgB+B,SAAhB,CAA0B,cAA1B,EAA0C,MAA1C,EAAgDiD,CAAhD;AACH,OAJD;AAMA,WAAKhD,OAAL,CAAa+C,gBAAb,CAA8B,UAA9B,EAA0C,UAAAC,CAAC,EAAI;AAC3CA,SAAC,CAACE,eAAF;AACAF,SAAC,CAACC,cAAF;;AACA,cAAI,CAAClD,SAAL,CAAe,UAAf,EAA2BiD,CAA3B;;AACA,cAAI,CAAChF,UAAL,CAAgB+B,SAAhB,CAA0B,iBAA1B,EAA6C,MAA7C,EAAmDiD,CAAnD;AACH,OALD;AAOA;;AACA,OAAC,KAAKjE,IAAL,IAAa,KAAKH,MAAnB,KACK,YAAM;AACH,YAAMuE,SAAS,GAAG,MAAI,CAACnF,UAAL,CAAgBE,MAAhB,CAAuBiF,SAAzC;;AACA,YAAMC,QAAQ,GAAG,MAAI,CAACpF,UAAL,CAAgBW,WAAhB,EAAjB;;AACA,YAAMe,WAAW,GAAG,MAAI,CAACA,WAAzB;AACA,YAAMC,eAAe,GAAG,MAAI,CAACA,eAA7B;AACA,YAAI0D,SAAJ;AACA,YAAIC,OAAJ;AACA,YAAIvE,IAAJ;AACA,YAAIwE,SAAJ;AACA,YAAI3E,MAAJ;AACA,YAAI4E,OAAO,GAAG,KAAd;AACA,YAAIC,eAAJ;AACA,YAAIC,WAAJ,CAZG,CAcH;;AACA,YAAMC,UAAU,GAAG,SAAbA,UAAa,CAAAX,CAAC,EAAI;AACpB,cAAI,CAACS,eAAD,IAAqB,CAAC1E,IAAD,IAAS,CAACH,MAAnC,EAA4C;AACxC;AACH,WAHmB,CAKpB;;;AACA,cAAIgF,UAAU,GACV,MAAI,CAAC3F,OAAL,CAAa2F,UAAb,GAA0BlE,WAAW,GAAG+D,eAD5C;AAEA,gBAAI,CAACxF,OAAL,CAAa2F,UAAb,GAA0BA,UAAU,GAAG/B,IAAI,CAACU,GAAL,CACnCgB,SADmC,EAEnC1B,IAAI,CAACS,GAAL,CAAS,CAAT,EAAYsB,UAAZ,CAFmC,CAAvC,CARoB,CAapB;;AACA,cAAMhC,IAAI,GACN,MAAI,CAAC5D,UAAL,CAAgBE,MAAhB,CAAuB2F,WAAvB,CAAmCb,CAAnC,IAAwCI,QAD5C;AAEA,cAAMU,KAAK,GAAGlC,IAAI,GAAGyB,SAArB;AACAA,mBAAS,GAAGzB,IAAZ,CAjBoB,CAmBpB;;AACA7C,cAAI,GAAG,MAAI,CAACgF,MAAL,CAAYD,KAAZ,CAAH,GAAwB,MAAI,CAACE,QAAL,CAAcF,KAAd,EAAqBlF,MAArB,CAA5B,CApBoB,CAsBpB;;AACAqF,gBAAM,CAACC,qBAAP,CAA6B,YAAM;AAC/BP,sBAAU,CAACX,CAAD,CAAV;AACH,WAFD;AAGH,SA1BD;;AA4BA,YAAMmB,MAAM,GAAG,SAATA,MAAS,CAAAnB,CAAC,EAAI;AAChB,cAAIA,CAAC,CAACoB,OAAF,IAAapB,CAAC,CAACoB,OAAF,CAAUC,MAAV,GAAmB,CAApC,EAAuC;AACnC;AACH;;AACDf,iBAAO,GAAGN,CAAC,CAACsB,aAAF,GACJtB,CAAC,CAACsB,aAAF,CAAgB,CAAhB,EAAmBC,UADf,GAEJ,IAFN;AAIAvB,WAAC,CAACE,eAAF;AACAG,mBAAS,GACL,MAAI,CAACrF,UAAL,CAAgBE,MAAhB,CAAuB2F,WAAvB,CAAmCb,CAAnC,EAAsC,IAAtC,IAA8CI,QADlD,CATgB,CAYhB;;AACAG,mBAAS,GACL,MAAI,CAACtF,OAAL,CAAaS,WAAb,GAA2B,MAAI,CAACT,OAAL,CAAauG,WAD5C;AAEAd,qBAAW,GAAG,MAAI,CAACzF,OAAL,CAAawG,qBAAb,EAAd;;AAEA,cAAIzB,CAAC,CAAC0B,MAAF,CAASC,OAAT,CAAiBC,WAAjB,MAAkC,QAAtC,EAAgD;AAC5C,gBACI5B,CAAC,CAAC0B,MAAF,CAASG,SAAT,CAAmBC,QAAnB,CACI,yBADJ,CADJ,EAIE;AACElG,oBAAM,GAAG,OAAT;AACH,aAND,MAMO;AACHA,oBAAM,GAAG,KAAT;AACH;AACJ,WAVD,MAUO;AACHG,gBAAI,GAAG,IAAP;AACAH,kBAAM,GAAG,KAAT;AACH;AACJ,SA/BD;;AAgCA,YAAMmG,IAAI,GAAG,SAAPA,IAAO,CAAA/B,CAAC,EAAI;AACd,cAAIA,CAAC,CAACoB,OAAF,IAAapB,CAAC,CAACoB,OAAF,CAAUC,MAAV,GAAmB,CAApC,EAAuC;AACnC;AACH;;AAED,cAAItF,IAAI,IAAIH,MAAZ,EAAoB;AAChBG,gBAAI,GAAG,KAAP;AACA0E,2BAAe,GAAG,IAAlB;AACA7E,kBAAM,GAAG,KAAT;AACH;;AAED,cAAI4E,OAAJ,EAAa;AACTA,mBAAO,GAAG,KAAV;;AACA,kBAAI,CAACrF,IAAL,CAAU6G,YAAV;;AACA,kBAAI,CAACjF,SAAL,CAAe,YAAf,EAA6BiD,CAA7B;;AACA,kBAAI,CAAChF,UAAL,CAAgB+B,SAAhB,CAA0B,mBAA1B,EAA+C,MAA/C,EAAqDiD,CAArD;AACH;AACJ,SAjBD;;AAkBA,YAAMiC,MAAM,GAAG,SAATA,MAAS,CAAAjC,CAAC,EAAI;AAChB,cAAIA,CAAC,CAACoB,OAAF,IAAapB,CAAC,CAACoB,OAAF,CAAUC,MAAV,GAAmB,CAApC,EAAuC;AACnC;AACH;;AACD,cACIrB,CAAC,CAACsB,aAAF,IACAtB,CAAC,CAACsB,aAAF,CAAgB,CAAhB,EAAmBC,UAAnB,IAAiCjB,OAFrC,EAGE;AACE;AACH;;AAED,cAAIvE,IAAI,IAAIH,MAAZ,EAAoB;AAChB,gBAAMsG,OAAO,GAAG7B,SAAhB;AACA,gBAAMzB,IAAI,GACN,MAAI,CAAC5D,UAAL,CAAgBE,MAAhB,CAAuB2F,WAAvB,CAAmCb,CAAnC,IAAwCI,QAD5C;AAEA,gBAAMU,KAAK,GAAGlC,IAAI,GAAGyB,SAArB;AACAA,qBAAS,GAAGzB,IAAZ,CALgB,CAOhB;;AACA,gBAAI,MAAI,CAAC7C,IAAL,IAAaA,IAAjB,EAAuB;AACnByE,qBAAO,GAAGA,OAAO,IAAI,CAAC,CAACM,KAAvB;;AACA,oBAAI,CAACC,MAAL,CAAYD,KAAZ;AACH,aAXe,CAahB;;;AACA,gBAAI,MAAI,CAAClF,MAAL,IAAeA,MAAnB,EAA2B;AACvB4E,qBAAO,GAAGA,OAAO,IAAI,CAAC,CAACM,KAAvB;;AACA,oBAAI,CAACE,QAAL,CAAcF,KAAd,EAAqBlF,MAArB;AACH;;AAED,gBACI,MAAI,CAACY,MAAL,IACA2D,SAAS,CAACqB,WAAV,GAAwB,MAAI,CAACvG,OAAL,CAAaS,WAFzC,EAGE;AACE,kBAAIK,IAAJ,EAAU;AACN;AACA;AACA,oBAAMoG,UAAU,GAAG,MAAI,CAACnF,OAAL,CAAayE,qBAAb,EAAnB;;AACA,oBAAIW,CAAC,GAAGD,UAAU,CAAC3D,IAAX,GAAkBkC,WAAW,CAAClC,IAAtC,CAJM,CAMN;;AACA,oBAAII,IAAI,GAAGsD,OAAP,IAAkBE,CAAC,IAAI,CAA3B,EAA8B;AAC1B3B,iCAAe,GAAG,CAAC,CAAnB;AACH,iBAFD,MAEO,IACH7B,IAAI,GAAGsD,OAAP,IACAE,CAAC,GAAGD,UAAU,CAACrE,KAAf,IAAwB4C,WAAW,CAAC2B,KAFjC,EAGL;AACE5B,iCAAe,GAAG,CAAlB;AACH,iBAdK,CAgBN;;;AACA,oBACKA,eAAe,KAAK,CAAC,CAArB,IACG2B,CAAC,GAAGzF,eADR,IAEC8D,eAAe,KAAK,CAApB,IACG2B,CAAC,GAAGD,UAAU,CAACrE,KAAf,GACI4C,WAAW,CAAC2B,KAAZ,GAAoB1F,eALhC,EAME;AACE8D,iCAAe,GAAG,IAAlB;AACH;AACJ,eA1BD,MA0BO;AACH;AACA,oBAAI2B,EAAC,GAAGpC,CAAC,CAACsC,OAAF,GAAY5B,WAAW,CAAClC,IAAhC,CAFG,CAIH;;;AACA,oBAAI4D,EAAC,IAAIzF,eAAT,EAA0B;AACtB8D,iCAAe,GAAG,CAAC,CAAnB;AACH,iBAFD,MAEO,IACH2B,EAAC,IACD1B,WAAW,CAAC2B,KAAZ,GAAoB1F,eAFjB,EAGL;AACE8D,iCAAe,GAAG,CAAlB;AACH,iBALM,MAKA;AACHA,iCAAe,GAAG,IAAlB;AACH;AACJ;;AAEDA,6BAAe,IAAIE,UAAU,CAACX,CAAD,CAA7B;AACH;AACJ;AACJ,SAhFD;;AAkFA,cAAI,CAAChD,OAAL,CAAa+C,gBAAb,CAA8B,WAA9B,EAA2CoB,MAA3C;;AACA,cAAI,CAACnE,OAAL,CAAa+C,gBAAb,CAA8B,YAA9B,EAA4CoB,MAA5C;;AAEA,cAAI,CAAClG,OAAL,CAAa8E,gBAAb,CAA8B,WAA9B,EAA2CkC,MAA3C;;AACA,cAAI,CAAChH,OAAL,CAAa8E,gBAAb,CAA8B,WAA9B,EAA2CkC,MAA3C;;AAEA1E,gBAAQ,CAACgF,IAAT,CAAcxC,gBAAd,CAA+B,SAA/B,EAA0CgC,IAA1C;AACAxE,gBAAQ,CAACgF,IAAT,CAAcxC,gBAAd,CAA+B,UAA/B,EAA2CgC,IAA3C;;AAEA,cAAI,CAACjF,EAAL,CAAQ,QAAR,EAAkB,YAAM;AACpBS,kBAAQ,CAACgF,IAAT,CAAcC,mBAAd,CAAkC,SAAlC,EAA6CT,IAA7C;AACAxE,kBAAQ,CAACgF,IAAT,CAAcC,mBAAd,CAAkC,UAAlC,EAA8CT,IAA9C;;AACA,gBAAI,CAAC9G,OAAL,CAAauH,mBAAb,CAAiC,WAAjC,EAA8CP,MAA9C;;AACA,gBAAI,CAAChH,OAAL,CAAauH,mBAAb,CAAiC,WAAjC,EAA8CP,MAA9C;AACH,SALD;;AAOA,cAAI,CAACjH,UAAL,CAAgB8B,EAAhB,CAAmB,SAAnB,EAA8B,YAAM;AAChCS,kBAAQ,CAACgF,IAAT,CAAcC,mBAAd,CAAkC,SAAlC,EAA6CT,IAA7C;AACAxE,kBAAQ,CAACgF,IAAT,CAAcC,mBAAd,CAAkC,UAAlC,EAA8CT,IAA9C;AACH,SAHD;AAIH,OAnMD,EADJ;AAqMH;;;2BAEMjB,K,EAAO;AACV,UAAM2B,MAAM,GAAG,KAAKzH,UAAL,CAAgBW,WAAhB,EAAf;;AACA,UAAI,KAAKF,GAAL,GAAWqF,KAAX,GAAmB2B,MAAnB,IAA6B,KAAKlH,KAAL,GAAauF,KAAb,GAAqB,CAAtD,EAAyD;AACrD;AACH;;AAED,WAAK4B,MAAL,CAAY;AACRnH,aAAK,EAAE,KAAKA,KAAL,GAAauF,KADZ;AAERrF,WAAG,EAAE,KAAKA,GAAL,GAAWqF;AAFR,OAAZ;AAIH;;;6BAEQA,K,EAAO6B,S,EAAW;AACvB,UAAIA,SAAS,IAAI,OAAjB,EAA0B;AACtB,aAAKD,MAAL,CAAY;AACRnH,eAAK,EAAEsD,IAAI,CAACU,GAAL,CAAS,KAAKhE,KAAL,GAAauF,KAAtB,EAA6B,KAAKrF,GAAlC,CADC;AAERA,aAAG,EAAEoD,IAAI,CAACS,GAAL,CAAS,KAAK/D,KAAL,GAAauF,KAAtB,EAA6B,KAAKrF,GAAlC;AAFG,SAAZ;AAIH,OALD,MAKO;AACH,aAAKiH,MAAL,CAAY;AACRnH,eAAK,EAAEsD,IAAI,CAACU,GAAL,CAAS,KAAK9D,GAAL,GAAWqF,KAApB,EAA2B,KAAKvF,KAAhC,CADC;AAERE,aAAG,EAAEoD,IAAI,CAACS,GAAL,CAAS,KAAK7D,GAAL,GAAWqF,KAApB,EAA2B,KAAKvF,KAAhC;AAFG,SAAZ;AAIH;AACJ;;;;;AAGL;;;;;;;;;;;AAWA;;;;;;;;;;;;;AAaA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA8BqBqH,a;;;;;;AACjB;;;;;;;;;2BASc9H,M,EAAQ;AAClB,aAAO;AACH+H,YAAI,EAAE,SADH;AAEHC,iBAAS,EAAEhI,MAAM,IAAIA,MAAM,CAACgI,SAAjB,GAA6BhI,MAAM,CAACgI,SAApC,GAAgD,KAFxD;AAGHhI,cAAM,EAAEA,MAHL;AAIHiI,mBAAW,EAAE;AACTC,qBADS,yBACK;AACVC,mBAAO,CAACC,IAAR,CACI,wEADJ;AAGA,iBAAKC,UAAL,CAAgB,SAAhB;AACH,WANQ;AAQTC,mBARS,qBAQCC,OARD,EAQU;AACf,gBAAI,CAAC,KAAKC,qBAAL,CAA2BC,OAAhC,EAAyC;AACrC,mBAAKJ,UAAL,CAAgB,SAAhB;AACH;;AACD,mBAAO,KAAKI,OAAL,CAAaC,GAAb,CAAiBH,OAAjB,CAAP;AACH,WAbQ;AAeTI,sBAfS,0BAeM;AACX,iBAAKF,OAAL,IAAgB,KAAKA,OAAL,CAAaG,KAAb,EAAhB;AACH,WAjBQ;AAmBTC,6BAnBS,+BAmBWN,OAnBX,EAmBoB;AACzB,gBAAI,CAAC,KAAKC,qBAAL,CAA2BC,OAAhC,EAAyC;AACrC,mBAAKJ,UAAL,CAAgB,SAAhB;AACH;;AACD,iBAAKI,OAAL,CAAaI,mBAAb,CAAiCN,OAAjC;AACH,WAxBQ;AA0BTO,8BA1BS,kCA0Bc;AACnB,iBAAKL,OAAL,CAAaK,oBAAb;AACH;AA5BQ,SAJV;AAkCHC,gBAAQ,EAAEjB;AAlCP,OAAP;AAoCH;;;AAED,yBAAY9H,MAAZ,EAAoBC,EAApB,EAAwB;AAAA;;AAAA;;AACpB,SAAKD,MAAL,GAAcA,MAAd;AACA,SAAKE,UAAL,GAAkBD,EAAlB;AACA,SAAKI,IAAL,GAAYJ,EAAE,CAACI,IAAf,CAHoB,CAKpB;;AACA,QAAM2I,qBAAqB,GAAGC,MAAM,CAACC,mBAAP,CAC1B,KAAK7I,IAAL,CAAU8I,QAAV,CAAmBC,SADO,CAA9B;AAGAJ,yBAAqB,CAACK,OAAtB,CAA8B,UAAAC,GAAG,EAAI;AACjCvJ,YAAM,CAACqJ,SAAP,CAAiBE,GAAjB,IAAwB,MAAI,CAACjJ,IAAL,CAAU8I,QAAV,CAAmBC,SAAnB,CAA6BE,GAA7B,CAAxB;AACH,KAFD;AAGA,SAAKpJ,UAAL,CAAgBH,MAAhB,GAAyBA,MAAzB;;AAEA,SAAKwJ,iBAAL,GAAyB,YAAM;AAC3B,YAAI,CAACpJ,OAAL,GAAe,MAAI,CAACD,UAAL,CAAgBE,MAAhB,CAAuBD,OAAtC;;AACA,UAAI,MAAI,CAACH,MAAL,CAAYyI,OAAhB,EAAyB;AACrB,cAAI,CAACzI,MAAL,CAAYyI,OAAZ,CAAoBY,OAApB,CAA4B,UAAAG,MAAM,EAAI;AAClC,gBAAI,CAACd,GAAL,CAASc,MAAT;AACH,SAFD;AAGH;AACJ,KAPD,CAdoB,CAuBpB;;;AACA,SAAKC,IAAL,GAAY,EAAZ;;AACA,SAAKC,QAAL,GAAgB,YAAM;AAClB,UAAI,MAAI,CAAC1J,MAAL,CAAY2J,aAAhB,EAA+B;AAC3B,cAAI,CAACd,mBAAL,CAAyB,MAAI,CAAC7I,MAA9B;AACH;;AACDiJ,YAAM,CAACW,IAAP,CAAY,MAAI,CAACH,IAAjB,EAAuBJ,OAAvB,CAA+B,UAAA9I,EAAE,EAAI;AACjC,cAAI,CAACkJ,IAAL,CAAUlJ,EAAV,EAAckB,YAAd;AACH,OAFD;AAGH,KAPD;AAQH;;;;2BAEM;AACH;AACA,UAAI,KAAKvB,UAAL,CAAgB2J,OAApB,EAA6B;AACzB,aAAKN,iBAAL;;AACA,aAAKG,QAAL;AACH;;AACD,WAAKxJ,UAAL,CAAgB8B,EAAhB,CAAmB,OAAnB,EAA4B,KAAK0H,QAAjC;AACA,WAAKxJ,UAAL,CAAgB8B,EAAhB,CAAmB,iBAAnB,EAAsC,KAAKuH,iBAA3C;AACH;;;8BAES;AACN,WAAKrJ,UAAL,CAAgBkC,EAAhB,CAAmB,OAAnB,EAA4B,KAAKsH,QAAjC;AACA,WAAKxJ,UAAL,CAAgBkC,EAAhB,CAAmB,iBAAnB,EAAsC,KAAKmH,iBAA3C;AACA,WAAKT,oBAAL;AACA,WAAKF,KAAL;AACH;AACD;;;;wBACI5I,M,EAAQ;AAAA;;AACR,UAAMwJ,MAAM,GAAG,IAAI,KAAKtJ,UAAL,CAAgBH,MAApB,CAA2BC,MAA3B,EAAmC,KAAKE,UAAxC,CAAf;AAEA,WAAKuJ,IAAL,CAAUD,MAAM,CAACjJ,EAAjB,IAAuBiJ,MAAvB;AAEAA,YAAM,CAACxH,EAAP,CAAU,QAAV,EAAoB,YAAM;AACtB,eAAO,MAAI,CAACyH,IAAL,CAAUD,MAAM,CAACjJ,EAAjB,CAAP;AACH,OAFD;AAIA,aAAOiJ,MAAP;AACH;AAED;;;;4BACQ;AAAA;;AACJP,YAAM,CAACW,IAAP,CAAY,KAAKH,IAAjB,EAAuBJ,OAAvB,CAA+B,UAAA9I,EAAE,EAAI;AACjC,cAAI,CAACkJ,IAAL,CAAUlJ,EAAV,EAAcuJ,MAAd;AACH,OAFD;AAGH;;;wCAEmB9J,M,EAAQ;AAAA;;AACxB,UAAM+J,IAAI,GAAG/J,MAAM,CAAC+J,IAAP,IAAe,CAA5B;AACA,UAAM1E,SAAS,GAAG,KAAKnF,UAAL,CAAgBE,MAAhB,CAAuBiF,SAAzC;AACA,UAAM3D,MAAM,GACR1B,MAAM,CAAC0B,MAAP,KAAkB,KAAlB,IAA2B,KAAKxB,UAAL,CAAgBF,MAAhB,CAAuB2B,YADtD;AAEA,UAAMC,WAAW,GAAG5B,MAAM,CAAC4B,WAAP,IAAsB,CAA1C;AACA,UAAMC,eAAe,GAAG7B,MAAM,CAAC6B,eAAP,IAA0B,EAAlD;AACA,UAAIZ,IAAJ;AACA,UAAIqE,QAAQ,GAAG,KAAKpF,UAAL,CAAgBW,WAAhB,EAAf;AACA,UAAI4E,SAAJ;AACA,UAAIhF,KAAJ;AACA,UAAI+I,MAAJ;AACA,UAAIhE,OAAJ;AACA,UAAIwE,MAAM,GAAG,CAAb;AACA,UAAIrE,eAAJ;AACA,UAAIC,WAAJ,CAfwB,CAiBxB;;AACA,UAAMC,UAAU,GAAG,SAAbA,UAAa,CAAAX,CAAC,EAAI;AACpB,YAAI,CAACsE,MAAD,IAAW,CAAC7D,eAAhB,EAAiC;AAC7B;AACH,SAHmB,CAKpB;;;AACA,YAAIG,UAAU,GACV,MAAI,CAAC3F,OAAL,CAAa2F,UAAb,GAA0BlE,WAAW,GAAG+D,eAD5C;AAEA,cAAI,CAACxF,OAAL,CAAa2F,UAAb,GAA0BA,UAAU,GAAG/B,IAAI,CAACU,GAAL,CACnCgB,SADmC,EAEnC1B,IAAI,CAACS,GAAL,CAAS,CAAT,EAAYsB,UAAZ,CAFmC,CAAvC,CARoB,CAapB;;AACA,YAAMnF,GAAG,GAAG,MAAI,CAACT,UAAL,CAAgBE,MAAhB,CAAuB2F,WAAvB,CAAmCb,CAAnC,CAAZ;;AACAsE,cAAM,CAAC5B,MAAP,CAAc;AACVnH,eAAK,EAAEsD,IAAI,CAACU,GAAL,CAAS9D,GAAG,GAAG2E,QAAf,EAAyB7E,KAAK,GAAG6E,QAAjC,CADG;AAEV3E,aAAG,EAAEoD,IAAI,CAACS,GAAL,CAAS7D,GAAG,GAAG2E,QAAf,EAAyB7E,KAAK,GAAG6E,QAAjC;AAFK,SAAd,EAfoB,CAoBpB;;AACA,YAAIQ,UAAU,GAAGL,SAAb,IAA0BK,UAAU,GAAG,CAA3C,EAA8C;AAC1CK,gBAAM,CAACC,qBAAP,CAA6B,YAAM;AAC/BP,sBAAU,CAACX,CAAD,CAAV;AACH,WAFD;AAGH;AACJ,OA1BD;;AA4BA,UAAM+E,SAAS,GAAG,SAAZA,SAAY,CAAA/E,CAAC,EAAI;AACnB,YAAIA,CAAC,CAACoB,OAAF,IAAapB,CAAC,CAACoB,OAAF,CAAUC,MAAV,GAAmB,CAApC,EAAuC;AACnC;AACH;;AACDjB,gBAAQ,GAAG,MAAI,CAACpF,UAAL,CAAgBW,WAAhB,EAAX;AACA2E,eAAO,GAAGN,CAAC,CAACsB,aAAF,GAAkBtB,CAAC,CAACsB,aAAF,CAAgB,CAAhB,EAAmBC,UAArC,GAAkD,IAA5D,CALmB,CAOnB;;AACAhB,iBAAS,GAAG,MAAI,CAACtF,OAAL,CAAaS,WAAb,GAA2B,MAAI,CAACT,OAAL,CAAauG,WAApD;AACAd,mBAAW,GAAG,MAAI,CAACzF,OAAL,CAAawG,qBAAb,EAAd;AAEA1F,YAAI,GAAG,IAAP;AACAR,aAAK,GAAG,MAAI,CAACP,UAAL,CAAgBE,MAAhB,CAAuB2F,WAAvB,CAAmCb,CAAnC,EAAsC,IAAtC,CAAR;AACAsE,cAAM,GAAG,IAAT;AACA7D,uBAAe,GAAG,IAAlB;AACH,OAfD;;AAgBA,WAAKxF,OAAL,CAAa8E,gBAAb,CAA8B,WAA9B,EAA2CgF,SAA3C;AACA,WAAK9J,OAAL,CAAa8E,gBAAb,CAA8B,YAA9B,EAA4CgF,SAA5C;AACA,WAAKjI,EAAL,CAAQ,wBAAR,EAAkC,YAAM;AACpC,cAAI,CAAC7B,OAAL,CAAauH,mBAAb,CAAiC,YAAjC,EAA+CuC,SAA/C;;AACA,cAAI,CAAC9J,OAAL,CAAauH,mBAAb,CAAiC,WAAjC,EAA8CuC,SAA9C;AACH,OAHD;;AAKA,UAAMC,OAAO,GAAG,SAAVA,OAAU,CAAAhF,CAAC,EAAI;AACjB,YAAIA,CAAC,CAACoB,OAAF,IAAapB,CAAC,CAACoB,OAAF,CAAUC,MAAV,GAAmB,CAApC,EAAuC;AACnC;AACH;;AAEDtF,YAAI,GAAG,KAAP;AACA+I,cAAM,GAAG,CAAT;AACArE,uBAAe,GAAG,IAAlB;;AAEA,YAAI6D,MAAJ,EAAY;AACR,gBAAI,CAACnJ,IAAL,CAAU6G,YAAV;;AACAsC,gBAAM,CAACvH,SAAP,CAAiB,YAAjB,EAA+BiD,CAA/B;;AACA,gBAAI,CAAChF,UAAL,CAAgB+B,SAAhB,CAA0B,mBAA1B,EAA+CuH,MAA/C,EAAuDtE,CAAvD;AACH;;AAEDsE,cAAM,GAAG,IAAT;AACH,OAhBD;;AAiBA,WAAKrJ,OAAL,CAAa8E,gBAAb,CAA8B,SAA9B,EAAyCiF,OAAzC;AACA,WAAK/J,OAAL,CAAa8E,gBAAb,CAA8B,UAA9B,EAA0CiF,OAA1C;AAEAzH,cAAQ,CAACgF,IAAT,CAAcxC,gBAAd,CAA+B,SAA/B,EAA0CiF,OAA1C;AACAzH,cAAQ,CAACgF,IAAT,CAAcxC,gBAAd,CAA+B,UAA/B,EAA2CiF,OAA3C;AACA,WAAKlI,EAAL,CAAQ,wBAAR,EAAkC,YAAM;AACpCS,gBAAQ,CAACgF,IAAT,CAAcC,mBAAd,CAAkC,SAAlC,EAA6CwC,OAA7C;AACAzH,gBAAQ,CAACgF,IAAT,CAAcC,mBAAd,CAAkC,UAAlC,EAA8CwC,OAA9C;;AACA,cAAI,CAAC/J,OAAL,CAAauH,mBAAb,CAAiC,UAAjC,EAA6CwC,OAA7C;;AACA,cAAI,CAAC/J,OAAL,CAAauH,mBAAb,CAAiC,SAAjC,EAA4CwC,OAA5C;AACH,OALD;;AAOA,UAAMC,SAAS,GAAG,SAAZA,SAAY,CAAAjF,CAAC,EAAI;AACnB,YAAI,CAACjE,IAAL,EAAW;AACP;AACH;;AACD,YAAI,EAAE+I,MAAF,IAAYD,IAAhB,EAAsB;AAClB;AACH;;AAED,YAAI7E,CAAC,CAACoB,OAAF,IAAapB,CAAC,CAACoB,OAAF,CAAUC,MAAV,GAAmB,CAApC,EAAuC;AACnC;AACH;;AACD,YAAIrB,CAAC,CAACsB,aAAF,IAAmBtB,CAAC,CAACsB,aAAF,CAAgB,CAAhB,EAAmBC,UAAnB,IAAiCjB,OAAxD,EAAiE;AAC7D;AACH;;AAED,YAAI,CAACgE,MAAL,EAAa;AACTA,gBAAM,GAAG,MAAI,CAACd,GAAL,CAAS1I,MAAM,IAAI,EAAnB,CAAT;AACH;;AAED,YAAMW,GAAG,GAAG,MAAI,CAACT,UAAL,CAAgBE,MAAhB,CAAuB2F,WAAvB,CAAmCb,CAAnC,CAAZ;;AACAsE,cAAM,CAAC5B,MAAP,CAAc;AACVnH,eAAK,EAAEsD,IAAI,CAACU,GAAL,CAAS9D,GAAG,GAAG2E,QAAf,EAAyB7E,KAAK,GAAG6E,QAAjC,CADG;AAEV3E,aAAG,EAAEoD,IAAI,CAACS,GAAL,CAAS7D,GAAG,GAAG2E,QAAf,EAAyB7E,KAAK,GAAG6E,QAAjC;AAFK,SAAd,EApBmB,CAyBnB;;AACA,YAAI5D,MAAM,IAAI2D,SAAS,CAACqB,WAAV,GAAwB,MAAI,CAACvG,OAAL,CAAaS,WAAnD,EAAgE;AAC5D;AACA,cAAM0G,CAAC,GAAGpC,CAAC,CAACsC,OAAF,GAAY5B,WAAW,CAAClC,IAAlC;;AACA,cAAI4D,CAAC,IAAIzF,eAAT,EAA0B;AACtB8D,2BAAe,GAAG,CAAC,CAAnB;AACH,WAFD,MAEO,IAAI2B,CAAC,IAAI1B,WAAW,CAAC2B,KAAZ,GAAoB1F,eAA7B,EAA8C;AACjD8D,2BAAe,GAAG,CAAlB;AACH,WAFM,MAEA;AACHA,2BAAe,GAAG,IAAlB;AACH;;AACDA,yBAAe,IAAIE,UAAU,CAACX,CAAD,CAA7B;AACH;AACJ,OAtCD;;AAuCA,WAAK/E,OAAL,CAAa8E,gBAAb,CAA8B,WAA9B,EAA2CkF,SAA3C;AACA,WAAKhK,OAAL,CAAa8E,gBAAb,CAA8B,WAA9B,EAA2CkF,SAA3C;AACA,WAAKnI,EAAL,CAAQ,wBAAR,EAAkC,YAAM;AACpC,cAAI,CAAC7B,OAAL,CAAauH,mBAAb,CAAiC,WAAjC,EAA8CyC,SAA9C;;AACA,cAAI,CAAChK,OAAL,CAAauH,mBAAb,CAAiC,WAAjC,EAA8CyC,SAA9C;AACH,OAHD;AAIH;;;2CAEsB;AACnB,WAAKlI,SAAL,CAAe,wBAAf;AACH;AAED;;;;;;;uCAImB;AAAA;;AACf,UAAM6B,IAAI,GAAG,KAAK5D,UAAL,CAAgBkK,cAAhB,EAAb;AACA,UAAI3F,GAAG,GAAG,IAAV;AACAwE,YAAM,CAACW,IAAP,CAAY,KAAKH,IAAjB,EAAuBJ,OAAvB,CAA+B,UAAA9I,EAAE,EAAI;AACjC,YAAM8J,GAAG,GAAG,MAAI,CAACZ,IAAL,CAAUlJ,EAAV,CAAZ;;AACA,YAAI8J,GAAG,CAAC5J,KAAJ,IAAaqD,IAAb,IAAqBuG,GAAG,CAAC1J,GAAJ,IAAWmD,IAApC,EAA0C;AACtC,cAAI,CAACW,GAAD,IAAQ4F,GAAG,CAAC1J,GAAJ,GAAU0J,GAAG,CAAC5J,KAAd,GAAsBgE,GAAG,CAAC9D,GAAJ,GAAU8D,GAAG,CAAChE,KAAhD,EAAuD;AACnDgE,eAAG,GAAG4F,GAAN;AACH;AACJ;AACJ,OAPD;AASA,aAAO5F,GAAP;AACH","file":"wavesurfer.regions.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"regions\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"regions\"] = factory();\n\telse\n\t\troot[\"WaveSurfer\"] = root[\"WaveSurfer\"] || {}, root[\"WaveSurfer\"][\"regions\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"localhost:8080/dist/plugin/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/plugin/regions.js\");\n","/**\n * (Single) Region plugin class\n *\n * Must be turned into an observer before instantiating. This is done in\n * RegionsPlugin (main plugin class)\n *\n * @extends {Observer}\n */\nclass Region {\n    constructor(params, ws) {\n        this.wavesurfer = ws;\n        this.wrapper = ws.drawer.wrapper;\n        this.util = ws.util;\n        this.style = this.util.style;\n\n        this.id = params.id == null ? ws.util.getId() : params.id;\n        this.start = Number(params.start) || 0;\n        this.end =\n            params.end == null\n                ? // small marker-like region\n                  this.start +\n                  (4 / this.wrapper.scrollWidth) * this.wavesurfer.getDuration()\n                : Number(params.end);\n        this.resize =\n            params.resize === undefined ? true : Boolean(params.resize);\n        this.drag = params.drag === undefined ? true : Boolean(params.drag);\n        this.loop = Boolean(params.loop);\n        this.color = params.color || 'rgba(0, 0, 0, 0.1)';\n        this.data = params.data || {};\n        this.attributes = params.attributes || {};\n\n        this.maxLength = params.maxLength;\n        this.minLength = params.minLength;\n        this._onRedraw = () => this.updateRender();\n\n        this.scroll = params.scroll !== false && ws.params.scrollParent;\n        this.scrollSpeed = params.scrollSpeed || 1;\n        this.scrollThreshold = params.scrollThreshold || 10;\n\n        this.bindInOut();\n        this.render();\n        this.wavesurfer.on('zoom', this._onRedraw);\n        this.wavesurfer.on('redraw', this._onRedraw);\n        this.wavesurfer.fireEvent('region-created', this);\n    }\n\n    /* Update region params. */\n    update(params) {\n        if (null != params.start) {\n            this.start = Number(params.start);\n        }\n        if (null != params.end) {\n            this.end = Number(params.end);\n        }\n        if (null != params.loop) {\n            this.loop = Boolean(params.loop);\n        }\n        if (null != params.color) {\n            this.color = params.color;\n        }\n        if (null != params.data) {\n            this.data = params.data;\n        }\n        if (null != params.resize) {\n            this.resize = Boolean(params.resize);\n        }\n        if (null != params.drag) {\n            this.drag = Boolean(params.drag);\n        }\n        if (null != params.maxLength) {\n            this.maxLength = Number(params.maxLength);\n        }\n        if (null != params.minLength) {\n            this.minLength = Number(params.minLength);\n        }\n        if (null != params.attributes) {\n            this.attributes = params.attributes;\n        }\n\n        this.updateRender();\n        this.fireEvent('update');\n        this.wavesurfer.fireEvent('region-updated', this);\n    }\n\n    /* Remove a single region. */\n    remove() {\n        if (this.element) {\n            this.wrapper.removeChild(this.element);\n            this.element = null;\n            this.fireEvent('remove');\n            this.wavesurfer.un('zoom', this._onRedraw);\n            this.wavesurfer.un('redraw', this._onRedraw);\n            this.wavesurfer.fireEvent('region-removed', this);\n        }\n    }\n\n    /* Play the audio region. */\n    play() {\n        this.wavesurfer.play(this.start, this.end);\n        this.fireEvent('play');\n        this.wavesurfer.fireEvent('region-play', this);\n    }\n\n    /* Play the region in loop. */\n    playLoop() {\n        this.play();\n        this.once('out', () => this.playLoop());\n    }\n\n    /* Render a region as a DOM element. */\n    render() {\n        const regionEl = document.createElement('region');\n        regionEl.className = 'wavesurfer-region';\n        regionEl.title = this.formatTime(this.start, this.end);\n        regionEl.setAttribute('data-id', this.id);\n\n        for (const attrname in this.attributes) {\n            regionEl.setAttribute(\n                'data-region-' + attrname,\n                this.attributes[attrname]\n            );\n        }\n\n        const width = this.wrapper.scrollWidth;\n        this.style(regionEl, {\n            position: 'absolute',\n            zIndex: 2,\n            height: '100%',\n            top: '0px'\n        });\n\n        /* Resize handles */\n        if (this.resize) {\n            const handleLeft = regionEl.appendChild(\n                document.createElement('handle')\n            );\n            const handleRight = regionEl.appendChild(\n                document.createElement('handle')\n            );\n            handleLeft.className = 'wavesurfer-handle wavesurfer-handle-start';\n            handleRight.className = 'wavesurfer-handle wavesurfer-handle-end';\n            const css = {\n                cursor: 'col-resize',\n                position: 'absolute',\n                left: '0px',\n                top: '0px',\n                width: '1%',\n                maxWidth: '4px',\n                height: '100%'\n            };\n            this.style(handleLeft, css);\n            this.style(handleRight, css);\n            this.style(handleRight, {\n                left: '100%'\n            });\n        }\n\n        this.element = this.wrapper.appendChild(regionEl);\n        this.updateRender();\n        this.bindEvents(regionEl);\n    }\n\n    formatTime(start, end) {\n        return (start == end ? [start] : [start, end])\n            .map(time =>\n                [\n                    Math.floor((time % 3600) / 60), // minutes\n                    ('00' + Math.floor(time % 60)).slice(-2) // seconds\n                ].join(':')\n            )\n            .join('-');\n    }\n\n    getWidth() {\n        return this.wavesurfer.drawer.width / this.wavesurfer.params.pixelRatio;\n    }\n\n    /* Update element's position, width, color. */\n    updateRender() {\n        // duration varies during loading process, so don't overwrite important data\n        const dur = this.wavesurfer.getDuration();\n        const width = this.getWidth();\n\n        var startLimited = this.start;\n        var endLimited = this.end;\n        if (startLimited < 0) {\n            startLimited = 0;\n            endLimited = endLimited - startLimited;\n        }\n        if (endLimited > dur) {\n            endLimited = dur;\n            startLimited = dur - (endLimited - startLimited);\n        }\n\n        if (this.minLength != null) {\n            endLimited = Math.max(startLimited + this.minLength, endLimited);\n        }\n\n        if (this.maxLength != null) {\n            endLimited = Math.min(startLimited + this.maxLength, endLimited);\n        }\n\n        if (this.element != null) {\n            // Calculate the left and width values of the region such that\n            // no gaps appear between regions.\n            const left = Math.round((startLimited / dur) * width);\n            const regionWidth = Math.round((endLimited / dur) * width) - left;\n\n            this.style(this.element, {\n                left: left + 'px',\n                width: regionWidth + 'px',\n                backgroundColor: this.color,\n                cursor: this.drag ? 'move' : 'default'\n            });\n\n            for (const attrname in this.attributes) {\n                this.element.setAttribute(\n                    'data-region-' + attrname,\n                    this.attributes[attrname]\n                );\n            }\n\n            this.element.title = this.formatTime(this.start, this.end);\n        }\n    }\n\n    /* Bind audio events. */\n    bindInOut() {\n        this.firedIn = false;\n        this.firedOut = false;\n\n        const onProcess = time => {\n            if (\n                !this.firedOut &&\n                this.firedIn &&\n                (this.start >= Math.round(time * 100) / 100 ||\n                    this.end <= Math.round(time * 100) / 100)\n            ) {\n                this.firedOut = true;\n                this.firedIn = false;\n                this.fireEvent('out');\n                this.wavesurfer.fireEvent('region-out', this);\n            }\n            if (!this.firedIn && this.start <= time && this.end > time) {\n                this.firedIn = true;\n                this.firedOut = false;\n                this.fireEvent('in');\n                this.wavesurfer.fireEvent('region-in', this);\n            }\n        };\n\n        this.wavesurfer.backend.on('audioprocess', onProcess);\n\n        this.on('remove', () => {\n            this.wavesurfer.backend.un('audioprocess', onProcess);\n        });\n\n        /* Loop playback. */\n        this.on('out', () => {\n            if (this.loop) {\n                this.wavesurfer.play(this.start);\n            }\n        });\n    }\n\n    /* Bind DOM events. */\n    bindEvents() {\n        this.element.addEventListener('mouseenter', e => {\n            this.fireEvent('mouseenter', e);\n            this.wavesurfer.fireEvent('region-mouseenter', this, e);\n        });\n\n        this.element.addEventListener('mouseleave', e => {\n            this.fireEvent('mouseleave', e);\n            this.wavesurfer.fireEvent('region-mouseleave', this, e);\n        });\n\n        this.element.addEventListener('click', e => {\n            e.preventDefault();\n            this.fireEvent('click', e);\n            this.wavesurfer.fireEvent('region-click', this, e);\n        });\n\n        this.element.addEventListener('dblclick', e => {\n            e.stopPropagation();\n            e.preventDefault();\n            this.fireEvent('dblclick', e);\n            this.wavesurfer.fireEvent('region-dblclick', this, e);\n        });\n\n        /* Drag or resize on mousemove. */\n        (this.drag || this.resize) &&\n            (() => {\n                const container = this.wavesurfer.drawer.container;\n                const duration = this.wavesurfer.getDuration();\n                const scrollSpeed = this.scrollSpeed;\n                const scrollThreshold = this.scrollThreshold;\n                let startTime;\n                let touchId;\n                let drag;\n                let maxScroll;\n                let resize;\n                let updated = false;\n                let scrollDirection;\n                let wrapperRect;\n\n                // Scroll when the user is dragging within the threshold\n                const edgeScroll = e => {\n                    if (!scrollDirection || (!drag && !resize)) {\n                        return;\n                    }\n\n                    // Update scroll position\n                    let scrollLeft =\n                        this.wrapper.scrollLeft + scrollSpeed * scrollDirection;\n                    this.wrapper.scrollLeft = scrollLeft = Math.min(\n                        maxScroll,\n                        Math.max(0, scrollLeft)\n                    );\n\n                    // Update time\n                    const time =\n                        this.wavesurfer.drawer.handleEvent(e) * duration;\n                    const delta = time - startTime;\n                    startTime = time;\n\n                    // Continue dragging or resizing\n                    drag ? this.onDrag(delta) : this.onResize(delta, resize);\n\n                    // Repeat\n                    window.requestAnimationFrame(() => {\n                        edgeScroll(e);\n                    });\n                };\n\n                const onDown = e => {\n                    if (e.touches && e.touches.length > 1) {\n                        return;\n                    }\n                    touchId = e.targetTouches\n                        ? e.targetTouches[0].identifier\n                        : null;\n\n                    e.stopPropagation();\n                    startTime =\n                        this.wavesurfer.drawer.handleEvent(e, true) * duration;\n\n                    // Store for scroll calculations\n                    maxScroll =\n                        this.wrapper.scrollWidth - this.wrapper.clientWidth;\n                    wrapperRect = this.wrapper.getBoundingClientRect();\n\n                    if (e.target.tagName.toLowerCase() == 'handle') {\n                        if (\n                            e.target.classList.contains(\n                                'wavesurfer-handle-start'\n                            )\n                        ) {\n                            resize = 'start';\n                        } else {\n                            resize = 'end';\n                        }\n                    } else {\n                        drag = true;\n                        resize = false;\n                    }\n                };\n                const onUp = e => {\n                    if (e.touches && e.touches.length > 1) {\n                        return;\n                    }\n\n                    if (drag || resize) {\n                        drag = false;\n                        scrollDirection = null;\n                        resize = false;\n                    }\n\n                    if (updated) {\n                        updated = false;\n                        this.util.preventClick();\n                        this.fireEvent('update-end', e);\n                        this.wavesurfer.fireEvent('region-update-end', this, e);\n                    }\n                };\n                const onMove = e => {\n                    if (e.touches && e.touches.length > 1) {\n                        return;\n                    }\n                    if (\n                        e.targetTouches &&\n                        e.targetTouches[0].identifier != touchId\n                    ) {\n                        return;\n                    }\n\n                    if (drag || resize) {\n                        const oldTime = startTime;\n                        const time =\n                            this.wavesurfer.drawer.handleEvent(e) * duration;\n                        const delta = time - startTime;\n                        startTime = time;\n\n                        // Drag\n                        if (this.drag && drag) {\n                            updated = updated || !!delta;\n                            this.onDrag(delta);\n                        }\n\n                        // Resize\n                        if (this.resize && resize) {\n                            updated = updated || !!delta;\n                            this.onResize(delta, resize);\n                        }\n\n                        if (\n                            this.scroll &&\n                            container.clientWidth < this.wrapper.scrollWidth\n                        ) {\n                            if (drag) {\n                                // The threshold is not between the mouse and the container edge\n                                // but is between the region and the container edge\n                                const regionRect = this.element.getBoundingClientRect();\n                                let x = regionRect.left - wrapperRect.left;\n\n                                // Check direction\n                                if (time < oldTime && x >= 0) {\n                                    scrollDirection = -1;\n                                } else if (\n                                    time > oldTime &&\n                                    x + regionRect.width <= wrapperRect.right\n                                ) {\n                                    scrollDirection = 1;\n                                }\n\n                                // Check that we are still beyond the threshold\n                                if (\n                                    (scrollDirection === -1 &&\n                                        x > scrollThreshold) ||\n                                    (scrollDirection === 1 &&\n                                        x + regionRect.width <\n                                            wrapperRect.right - scrollThreshold)\n                                ) {\n                                    scrollDirection = null;\n                                }\n                            } else {\n                                // Mouse based threshold\n                                let x = e.clientX - wrapperRect.left;\n\n                                // Check direction\n                                if (x <= scrollThreshold) {\n                                    scrollDirection = -1;\n                                } else if (\n                                    x >=\n                                    wrapperRect.right - scrollThreshold\n                                ) {\n                                    scrollDirection = 1;\n                                } else {\n                                    scrollDirection = null;\n                                }\n                            }\n\n                            scrollDirection && edgeScroll(e);\n                        }\n                    }\n                };\n\n                this.element.addEventListener('mousedown', onDown);\n                this.element.addEventListener('touchstart', onDown);\n\n                this.wrapper.addEventListener('mousemove', onMove);\n                this.wrapper.addEventListener('touchmove', onMove);\n\n                document.body.addEventListener('mouseup', onUp);\n                document.body.addEventListener('touchend', onUp);\n\n                this.on('remove', () => {\n                    document.body.removeEventListener('mouseup', onUp);\n                    document.body.removeEventListener('touchend', onUp);\n                    this.wrapper.removeEventListener('mousemove', onMove);\n                    this.wrapper.removeEventListener('touchmove', onMove);\n                });\n\n                this.wavesurfer.on('destroy', () => {\n                    document.body.removeEventListener('mouseup', onUp);\n                    document.body.removeEventListener('touchend', onUp);\n                });\n            })();\n    }\n\n    onDrag(delta) {\n        const maxEnd = this.wavesurfer.getDuration();\n        if (this.end + delta > maxEnd || this.start + delta < 0) {\n            return;\n        }\n\n        this.update({\n            start: this.start + delta,\n            end: this.end + delta\n        });\n    }\n\n    onResize(delta, direction) {\n        if (direction == 'start') {\n            this.update({\n                start: Math.min(this.start + delta, this.end),\n                end: Math.max(this.start + delta, this.end)\n            });\n        } else {\n            this.update({\n                start: Math.min(this.end + delta, this.start),\n                end: Math.max(this.end + delta, this.start)\n            });\n        }\n    }\n}\n\n/**\n * @typedef {Object} RegionsPluginParams\n * @property {?boolean} dragSelection Enable creating regions by dragging with\n * the mouse\n * @property {?RegionParams[]} regions Regions that should be added upon\n * initialisation\n * @property {number} slop=2 The sensitivity of the mouse dragging\n * @property {?boolean} deferInit Set to true to manually call\n * `initPlugin('regions')`\n */\n\n/**\n * @typedef {Object} RegionParams\n * @desc The parameters used to describe a region.\n * @example wavesurfer.addRegion(regionParams);\n * @property {string} id=ârandom The id of the region\n * @property {number} start=0 The start position of the region (in seconds).\n * @property {number} end=0 The end position of the region (in seconds).\n * @property {?boolean} loop Whether to loop the region when played back.\n * @property {boolean} drag=true Allow/disallow dragging the region.\n * @property {boolean} resize=true Allow/disallow resizing the region.\n * @property {string} [color='rgba(0, 0, 0, 0.1)'] HTML color code.\n */\n\n/**\n * Regions are visual overlays on waveform that can be used to play and loop\n * portions of audio. Regions can be dragged and resized.\n *\n * Visual customization is possible via CSS (using the selectors\n * `.wavesurfer-region` and `.wavesurfer-handle`).\n *\n * @implements {PluginClass}\n * @extends {Observer}\n *\n * @example\n * // es6\n * import RegionsPlugin from 'wavesurfer.regions.js';\n *\n * // commonjs\n * var RegionsPlugin = require('wavesurfer.regions.js');\n *\n * // if you are using <script> tags\n * var RegionsPlugin = window.WaveSurfer.regions;\n *\n * // ... initialising wavesurfer with the plugin\n * var wavesurfer = WaveSurfer.create({\n *   // wavesurfer options ...\n *   plugins: [\n *     RegionsPlugin.create({\n *       // plugin options ...\n *     })\n *   ]\n * });\n */\nexport default class RegionsPlugin {\n    /**\n     * Regions plugin definition factory\n     *\n     * This function must be used to create a plugin definition which can be\n     * used by wavesurfer to correctly instantiate the plugin.\n     *\n     * @param {RegionsPluginParams} params parameters use to initialise the plugin\n     * @return {PluginDefinition} an object representing the plugin\n     */\n    static create(params) {\n        return {\n            name: 'regions',\n            deferInit: params && params.deferInit ? params.deferInit : false,\n            params: params,\n            staticProps: {\n                initRegions() {\n                    console.warn(\n                        'Deprecated initRegions! Use wavesurfer.initPlugins(\"regions\") instead!'\n                    );\n                    this.initPlugin('regions');\n                },\n\n                addRegion(options) {\n                    if (!this.initialisedPluginList.regions) {\n                        this.initPlugin('regions');\n                    }\n                    return this.regions.add(options);\n                },\n\n                clearRegions() {\n                    this.regions && this.regions.clear();\n                },\n\n                enableDragSelection(options) {\n                    if (!this.initialisedPluginList.regions) {\n                        this.initPlugin('regions');\n                    }\n                    this.regions.enableDragSelection(options);\n                },\n\n                disableDragSelection() {\n                    this.regions.disableDragSelection();\n                }\n            },\n            instance: RegionsPlugin\n        };\n    }\n\n    constructor(params, ws) {\n        this.params = params;\n        this.wavesurfer = ws;\n        this.util = ws.util;\n\n        // turn the plugin instance into an observer\n        const observerPrototypeKeys = Object.getOwnPropertyNames(\n            this.util.Observer.prototype\n        );\n        observerPrototypeKeys.forEach(key => {\n            Region.prototype[key] = this.util.Observer.prototype[key];\n        });\n        this.wavesurfer.Region = Region;\n\n        this._onBackendCreated = () => {\n            this.wrapper = this.wavesurfer.drawer.wrapper;\n            if (this.params.regions) {\n                this.params.regions.forEach(region => {\n                    this.add(region);\n                });\n            }\n        };\n\n        // Id-based hash of regions.\n        this.list = {};\n        this._onReady = () => {\n            if (this.params.dragSelection) {\n                this.enableDragSelection(this.params);\n            }\n            Object.keys(this.list).forEach(id => {\n                this.list[id].updateRender();\n            });\n        };\n    }\n\n    init() {\n        // Check if ws is ready\n        if (this.wavesurfer.isReady) {\n            this._onBackendCreated();\n            this._onReady();\n        }\n        this.wavesurfer.on('ready', this._onReady);\n        this.wavesurfer.on('backend-created', this._onBackendCreated);\n    }\n\n    destroy() {\n        this.wavesurfer.un('ready', this._onReady);\n        this.wavesurfer.un('backend-created', this._onBackendCreated);\n        this.disableDragSelection();\n        this.clear();\n    }\n    /* Add a region. */\n    add(params) {\n        const region = new this.wavesurfer.Region(params, this.wavesurfer);\n\n        this.list[region.id] = region;\n\n        region.on('remove', () => {\n            delete this.list[region.id];\n        });\n\n        return region;\n    }\n\n    /* Remove all regions. */\n    clear() {\n        Object.keys(this.list).forEach(id => {\n            this.list[id].remove();\n        });\n    }\n\n    enableDragSelection(params) {\n        const slop = params.slop || 2;\n        const container = this.wavesurfer.drawer.container;\n        const scroll =\n            params.scroll !== false && this.wavesurfer.params.scrollParent;\n        const scrollSpeed = params.scrollSpeed || 1;\n        const scrollThreshold = params.scrollThreshold || 10;\n        let drag;\n        let duration = this.wavesurfer.getDuration();\n        let maxScroll;\n        let start;\n        let region;\n        let touchId;\n        let pxMove = 0;\n        let scrollDirection;\n        let wrapperRect;\n\n        // Scroll when the user is dragging within the threshold\n        const edgeScroll = e => {\n            if (!region || !scrollDirection) {\n                return;\n            }\n\n            // Update scroll position\n            let scrollLeft =\n                this.wrapper.scrollLeft + scrollSpeed * scrollDirection;\n            this.wrapper.scrollLeft = scrollLeft = Math.min(\n                maxScroll,\n                Math.max(0, scrollLeft)\n            );\n\n            // Update range\n            const end = this.wavesurfer.drawer.handleEvent(e);\n            region.update({\n                start: Math.min(end * duration, start * duration),\n                end: Math.max(end * duration, start * duration)\n            });\n\n            // Check that there is more to scroll and repeat\n            if (scrollLeft < maxScroll && scrollLeft > 0) {\n                window.requestAnimationFrame(() => {\n                    edgeScroll(e);\n                });\n            }\n        };\n\n        const eventDown = e => {\n            if (e.touches && e.touches.length > 1) {\n                return;\n            }\n            duration = this.wavesurfer.getDuration();\n            touchId = e.targetTouches ? e.targetTouches[0].identifier : null;\n\n            // Store for scroll calculations\n            maxScroll = this.wrapper.scrollWidth - this.wrapper.clientWidth;\n            wrapperRect = this.wrapper.getBoundingClientRect();\n\n            drag = true;\n            start = this.wavesurfer.drawer.handleEvent(e, true);\n            region = null;\n            scrollDirection = null;\n        };\n        this.wrapper.addEventListener('mousedown', eventDown);\n        this.wrapper.addEventListener('touchstart', eventDown);\n        this.on('disable-drag-selection', () => {\n            this.wrapper.removeEventListener('touchstart', eventDown);\n            this.wrapper.removeEventListener('mousedown', eventDown);\n        });\n\n        const eventUp = e => {\n            if (e.touches && e.touches.length > 1) {\n                return;\n            }\n\n            drag = false;\n            pxMove = 0;\n            scrollDirection = null;\n\n            if (region) {\n                this.util.preventClick();\n                region.fireEvent('update-end', e);\n                this.wavesurfer.fireEvent('region-update-end', region, e);\n            }\n\n            region = null;\n        };\n        this.wrapper.addEventListener('mouseup', eventUp);\n        this.wrapper.addEventListener('touchend', eventUp);\n\n        document.body.addEventListener('mouseup', eventUp);\n        document.body.addEventListener('touchend', eventUp);\n        this.on('disable-drag-selection', () => {\n            document.body.removeEventListener('mouseup', eventUp);\n            document.body.removeEventListener('touchend', eventUp);\n            this.wrapper.removeEventListener('touchend', eventUp);\n            this.wrapper.removeEventListener('mouseup', eventUp);\n        });\n\n        const eventMove = e => {\n            if (!drag) {\n                return;\n            }\n            if (++pxMove <= slop) {\n                return;\n            }\n\n            if (e.touches && e.touches.length > 1) {\n                return;\n            }\n            if (e.targetTouches && e.targetTouches[0].identifier != touchId) {\n                return;\n            }\n\n            if (!region) {\n                region = this.add(params || {});\n            }\n\n            const end = this.wavesurfer.drawer.handleEvent(e);\n            region.update({\n                start: Math.min(end * duration, start * duration),\n                end: Math.max(end * duration, start * duration)\n            });\n\n            // If scrolling is enabled\n            if (scroll && container.clientWidth < this.wrapper.scrollWidth) {\n                // Check threshold based on mouse\n                const x = e.clientX - wrapperRect.left;\n                if (x <= scrollThreshold) {\n                    scrollDirection = -1;\n                } else if (x >= wrapperRect.right - scrollThreshold) {\n                    scrollDirection = 1;\n                } else {\n                    scrollDirection = null;\n                }\n                scrollDirection && edgeScroll(e);\n            }\n        };\n        this.wrapper.addEventListener('mousemove', eventMove);\n        this.wrapper.addEventListener('touchmove', eventMove);\n        this.on('disable-drag-selection', () => {\n            this.wrapper.removeEventListener('touchmove', eventMove);\n            this.wrapper.removeEventListener('mousemove', eventMove);\n        });\n    }\n\n    disableDragSelection() {\n        this.fireEvent('disable-drag-selection');\n    }\n\n    /* Get current region\n     *  The smallest region that contains the current time.\n     *  If several such regions exist, we take the first.\n     *  Return null if none exist. */\n    getCurrentRegion() {\n        const time = this.wavesurfer.getCurrentTime();\n        let min = null;\n        Object.keys(this.list).forEach(id => {\n            const cur = this.list[id];\n            if (cur.start <= time && cur.end >= time) {\n                if (!min || cur.end - cur.start < min.end - min.start) {\n                    min = cur;\n                }\n            }\n        });\n\n        return min;\n    }\n}\n"],"sourceRoot":""}
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.regions.min.js
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.regions.min.js	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.regions.min.js	(revision 33546)
@@ -0,0 +1,2 @@
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("regions",[],t):"object"==typeof exports?exports.regions=t():(e.WaveSurfer=e.WaveSurfer||{},e.WaveSurfer.regions=t())}(window,(function(){return function(e){var t={};function r(n){if(t[n])return t[n].exports;var i=t[n]={i:n,l:!1,exports:{}};return e[n].call(i.exports,i,i.exports,r),i.l=!0,i.exports}return r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)r.d(n,i,function(t){return e[t]}.bind(null,i));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="localhost:8080/dist/plugin/",r(r.s=2)}({2:function(e,t,r){"use strict";function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}function s(e,t,r){return t&&i(e.prototype,t),r&&i(e,r),e}Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var a=function(){function e(t,r){var i=this;n(this,e),this.wavesurfer=r,this.wrapper=r.drawer.wrapper,this.util=r.util,this.style=this.util.style,this.id=null==t.id?r.util.getId():t.id,this.start=Number(t.start)||0,this.end=null==t.end?this.start+4/this.wrapper.scrollWidth*this.wavesurfer.getDuration():Number(t.end),this.resize=void 0===t.resize||Boolean(t.resize),this.drag=void 0===t.drag||Boolean(t.drag),this.loop=Boolean(t.loop),this.color=t.color||"rgba(0, 0, 0, 0.1)",this.data=t.data||{},this.attributes=t.attributes||{},this.maxLength=t.maxLength,this.minLength=t.minLength,this._onRedraw=function(){return i.updateRender()},this.scroll=!1!==t.scroll&&r.params.scrollParent,this.scrollSpeed=t.scrollSpeed||1,this.scrollThreshold=t.scrollThreshold||10,this.bindInOut(),this.render(),this.wavesurfer.on("zoom",this._onRedraw),this.wavesurfer.on("redraw",this._onRedraw),this.wavesurfer.fireEvent("region-created",this)}return s(e,[{key:"update",value:function(e){null!=e.start&&(this.start=Number(e.start)),null!=e.end&&(this.end=Number(e.end)),null!=e.loop&&(this.loop=Boolean(e.loop)),null!=e.color&&(this.color=e.color),null!=e.data&&(this.data=e.data),null!=e.resize&&(this.resize=Boolean(e.resize)),null!=e.drag&&(this.drag=Boolean(e.drag)),null!=e.maxLength&&(this.maxLength=Number(e.maxLength)),null!=e.minLength&&(this.minLength=Number(e.minLength)),null!=e.attributes&&(this.attributes=e.attributes),this.updateRender(),this.fireEvent("update"),this.wavesurfer.fireEvent("region-updated",this)}},{key:"remove",value:function(){this.element&&(this.wrapper.removeChild(this.element),this.element=null,this.fireEvent("remove"),this.wavesurfer.un("zoom",this._onRedraw),this.wavesurfer.un("redraw",this._onRedraw),this.wavesurfer.fireEvent("region-removed",this))}},{key:"play",value:function(){this.wavesurfer.play(this.start,this.end),this.fireEvent("play"),this.wavesurfer.fireEvent("region-play",this)}},{key:"playLoop",value:function(){var e=this;this.play(),this.once("out",(function(){return e.playLoop()}))}},{key:"render",value:function(){var e=document.createElement("region");for(var t in e.className="wavesurfer-region",e.title=this.formatTime(this.start,this.end),e.setAttribute("data-id",this.id),this.attributes)e.setAttribute("data-region-"+t,this.attributes[t]);this.wrapper.scrollWidth;if(this.style(e,{position:"absolute",zIndex:2,height:"100%",top:"0px"}),this.resize){var r=e.appendChild(document.createElement("handle")),n=e.appendChild(document.createElement("handle"));r.className="wavesurfer-handle wavesurfer-handle-start",n.className="wavesurfer-handle wavesurfer-handle-end";var i={cursor:"col-resize",position:"absolute",left:"0px",top:"0px",width:"1%",maxWidth:"4px",height:"100%"};this.style(r,i),this.style(n,i),this.style(n,{left:"100%"})}this.element=this.wrapper.appendChild(e),this.updateRender(),this.bindEvents(e)}},{key:"formatTime",value:function(e,t){return(e==t?[e]:[e,t]).map((function(e){return[Math.floor(e%3600/60),("00"+Math.floor(e%60)).slice(-2)].join(":")})).join("-")}},{key:"getWidth",value:function(){return this.wavesurfer.drawer.width/this.wavesurfer.params.pixelRatio}},{key:"updateRender",value:function(){var e=this.wavesurfer.getDuration(),t=this.getWidth(),r=this.start,n=this.end;if(r<0&&(n-=r=0),n>e&&(r=e-((n=e)-r)),null!=this.minLength&&(n=Math.max(r+this.minLength,n)),null!=this.maxLength&&(n=Math.min(r+this.maxLength,n)),null!=this.element){var i=Math.round(r/e*t),s=Math.round(n/e*t)-i;for(var a in this.style(this.element,{left:i+"px",width:s+"px",backgroundColor:this.color,cursor:this.drag?"move":"default"}),this.attributes)this.element.setAttribute("data-region-"+a,this.attributes[a]);this.element.title=this.formatTime(this.start,this.end)}}},{key:"bindInOut",value:function(){var e=this;this.firedIn=!1,this.firedOut=!1;var t=function(t){!e.firedOut&&e.firedIn&&(e.start>=Math.round(100*t)/100||e.end<=Math.round(100*t)/100)&&(e.firedOut=!0,e.firedIn=!1,e.fireEvent("out"),e.wavesurfer.fireEvent("region-out",e)),!e.firedIn&&e.start<=t&&e.end>t&&(e.firedIn=!0,e.firedOut=!1,e.fireEvent("in"),e.wavesurfer.fireEvent("region-in",e))};this.wavesurfer.backend.on("audioprocess",t),this.on("remove",(function(){e.wavesurfer.backend.un("audioprocess",t)})),this.on("out",(function(){e.loop&&e.wavesurfer.play(e.start)}))}},{key:"bindEvents",value:function(){var e,t,r,n,i,s,a,o,u,l,d,h,c,f,v,p=this;this.element.addEventListener("mouseenter",(function(e){p.fireEvent("mouseenter",e),p.wavesurfer.fireEvent("region-mouseenter",p,e)})),this.element.addEventListener("mouseleave",(function(e){p.fireEvent("mouseleave",e),p.wavesurfer.fireEvent("region-mouseleave",p,e)})),this.element.addEventListener("click",(function(e){e.preventDefault(),p.fireEvent("click",e),p.wavesurfer.fireEvent("region-click",p,e)})),this.element.addEventListener("dblclick",(function(e){e.stopPropagation(),e.preventDefault(),p.fireEvent("dblclick",e),p.wavesurfer.fireEvent("region-dblclick",p,e)})),(this.drag||this.resize)&&(o=p.wavesurfer.drawer.container,u=p.wavesurfer.getDuration(),l=p.scrollSpeed,d=p.scrollThreshold,h=!1,c=function(s){s.touches&&s.touches.length>1||(t=s.targetTouches?s.targetTouches[0].identifier:null,s.stopPropagation(),e=p.wavesurfer.drawer.handleEvent(s,!0)*u,n=p.wrapper.scrollWidth-p.wrapper.clientWidth,a=p.wrapper.getBoundingClientRect(),"handle"==s.target.tagName.toLowerCase()?i=s.target.classList.contains("wavesurfer-handle-start")?"start":"end":(r=!0,i=!1))},f=function(e){e.touches&&e.touches.length>1||((r||i)&&(r=!1,s=null,i=!1),h&&(h=!1,p.util.preventClick(),p.fireEvent("update-end",e),p.wavesurfer.fireEvent("region-update-end",p,e)))},v=function(c){if(!(c.touches&&c.touches.length>1)&&(!c.targetTouches||c.targetTouches[0].identifier==t)&&(r||i)){var f=e,v=p.wavesurfer.drawer.handleEvent(c)*u,m=v-e;if(e=v,p.drag&&r&&(h=h||!!m,p.onDrag(m)),p.resize&&i&&(h=h||!!m,p.onResize(m,i)),p.scroll&&o.clientWidth<p.wrapper.scrollWidth){if(r){var g=p.element.getBoundingClientRect(),w=g.left-a.left;v<f&&w>=0?s=-1:v>f&&w+g.width<=a.right&&(s=1),(-1===s&&w>d||1===s&&w+g.width<a.right-d)&&(s=null)}else{var b=c.clientX-a.left;s=b<=d?-1:b>=a.right-d?1:null}s&&function t(a){if(s&&(r||i)){var o=p.wrapper.scrollLeft+l*s;p.wrapper.scrollLeft=o=Math.min(n,Math.max(0,o));var d=p.wavesurfer.drawer.handleEvent(a)*u,h=d-e;e=d,r?p.onDrag(h):p.onResize(h,i),window.requestAnimationFrame((function(){t(a)}))}}(c)}}},p.element.addEventListener("mousedown",c),p.element.addEventListener("touchstart",c),p.wrapper.addEventListener("mousemove",v),p.wrapper.addEventListener("touchmove",v),document.body.addEventListener("mouseup",f),document.body.addEventListener("touchend",f),p.on("remove",(function(){document.body.removeEventListener("mouseup",f),document.body.removeEventListener("touchend",f),p.wrapper.removeEventListener("mousemove",v),p.wrapper.removeEventListener("touchmove",v)})),p.wavesurfer.on("destroy",(function(){document.body.removeEventListener("mouseup",f),document.body.removeEventListener("touchend",f)})))}},{key:"onDrag",value:function(e){var t=this.wavesurfer.getDuration();this.end+e>t||this.start+e<0||this.update({start:this.start+e,end:this.end+e})}},{key:"onResize",value:function(e,t){"start"==t?this.update({start:Math.min(this.start+e,this.end),end:Math.max(this.start+e,this.end)}):this.update({start:Math.min(this.end+e,this.start),end:Math.max(this.end+e,this.start)})}}]),e}(),o=function(){function e(t,r){var i=this;n(this,e),this.params=t,this.wavesurfer=r,this.util=r.util,Object.getOwnPropertyNames(this.util.Observer.prototype).forEach((function(e){a.prototype[e]=i.util.Observer.prototype[e]})),this.wavesurfer.Region=a,this._onBackendCreated=function(){i.wrapper=i.wavesurfer.drawer.wrapper,i.params.regions&&i.params.regions.forEach((function(e){i.add(e)}))},this.list={},this._onReady=function(){i.params.dragSelection&&i.enableDragSelection(i.params),Object.keys(i.list).forEach((function(e){i.list[e].updateRender()}))}}return s(e,null,[{key:"create",value:function(t){return{name:"regions",deferInit:!(!t||!t.deferInit)&&t.deferInit,params:t,staticProps:{initRegions:function(){console.warn('Deprecated initRegions! Use wavesurfer.initPlugins("regions") instead!'),this.initPlugin("regions")},addRegion:function(e){return this.initialisedPluginList.regions||this.initPlugin("regions"),this.regions.add(e)},clearRegions:function(){this.regions&&this.regions.clear()},enableDragSelection:function(e){this.initialisedPluginList.regions||this.initPlugin("regions"),this.regions.enableDragSelection(e)},disableDragSelection:function(){this.regions.disableDragSelection()}},instance:e}}}]),s(e,[{key:"init",value:function(){this.wavesurfer.isReady&&(this._onBackendCreated(),this._onReady()),this.wavesurfer.on("ready",this._onReady),this.wavesurfer.on("backend-created",this._onBackendCreated)}},{key:"destroy",value:function(){this.wavesurfer.un("ready",this._onReady),this.wavesurfer.un("backend-created",this._onBackendCreated),this.disableDragSelection(),this.clear()}},{key:"add",value:function(e){var t=this,r=new this.wavesurfer.Region(e,this.wavesurfer);return this.list[r.id]=r,r.on("remove",(function(){delete t.list[r.id]})),r}},{key:"clear",value:function(){var e=this;Object.keys(this.list).forEach((function(t){e.list[t].remove()}))}},{key:"enableDragSelection",value:function(e){var t,r,n,i,s,a,o,u=this,l=e.slop||2,d=this.wavesurfer.drawer.container,h=!1!==e.scroll&&this.wavesurfer.params.scrollParent,c=e.scrollSpeed||1,f=e.scrollThreshold||10,v=this.wavesurfer.getDuration(),p=0,m=function(e){e.touches&&e.touches.length>1||(v=u.wavesurfer.getDuration(),s=e.targetTouches?e.targetTouches[0].identifier:null,r=u.wrapper.scrollWidth-u.wrapper.clientWidth,o=u.wrapper.getBoundingClientRect(),t=!0,n=u.wavesurfer.drawer.handleEvent(e,!0),i=null,a=null)};this.wrapper.addEventListener("mousedown",m),this.wrapper.addEventListener("touchstart",m),this.on("disable-drag-selection",(function(){u.wrapper.removeEventListener("touchstart",m),u.wrapper.removeEventListener("mousedown",m)}));var g=function(e){e.touches&&e.touches.length>1||(t=!1,p=0,a=null,i&&(u.util.preventClick(),i.fireEvent("update-end",e),u.wavesurfer.fireEvent("region-update-end",i,e)),i=null)};this.wrapper.addEventListener("mouseup",g),this.wrapper.addEventListener("touchend",g),document.body.addEventListener("mouseup",g),document.body.addEventListener("touchend",g),this.on("disable-drag-selection",(function(){document.body.removeEventListener("mouseup",g),document.body.removeEventListener("touchend",g),u.wrapper.removeEventListener("touchend",g),u.wrapper.removeEventListener("mouseup",g)}));var w=function(m){if(t&&!(++p<=l||m.touches&&m.touches.length>1||m.targetTouches&&m.targetTouches[0].identifier!=s)){i||(i=u.add(e||{}));var g=u.wavesurfer.drawer.handleEvent(m);if(i.update({start:Math.min(g*v,n*v),end:Math.max(g*v,n*v)}),h&&d.clientWidth<u.wrapper.scrollWidth){var w=m.clientX-o.left;(a=w<=f?-1:w>=o.right-f?1:null)&&function e(t){if(i&&a){var s=u.wrapper.scrollLeft+c*a;u.wrapper.scrollLeft=s=Math.min(r,Math.max(0,s));var o=u.wavesurfer.drawer.handleEvent(t);i.update({start:Math.min(o*v,n*v),end:Math.max(o*v,n*v)}),s<r&&s>0&&window.requestAnimationFrame((function(){e(t)}))}}(m)}}};this.wrapper.addEventListener("mousemove",w),this.wrapper.addEventListener("touchmove",w),this.on("disable-drag-selection",(function(){u.wrapper.removeEventListener("touchmove",w),u.wrapper.removeEventListener("mousemove",w)}))}},{key:"disableDragSelection",value:function(){this.fireEvent("disable-drag-selection")}},{key:"getCurrentRegion",value:function(){var e=this,t=this.wavesurfer.getCurrentTime(),r=null;return Object.keys(this.list).forEach((function(n){var i=e.list[n];i.start<=t&&i.end>=t&&(!r||i.end-i.start<r.end-r.start)&&(r=i)})),r}}]),e}();t.default=o,e.exports=t.default}})}));
+//# sourceMappingURL=wavesurfer.regions.min.js.map
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.regions.min.js.map
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.regions.min.js.map	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.regions.min.js.map	(revision 33546)
@@ -0,0 +1,1 @@
+{"version":3,"sources":["webpack://WaveSurfer.[name]/webpack/universalModuleDefinition","webpack://WaveSurfer.[name]/webpack/bootstrap","webpack://WaveSurfer.[name]/./src/plugin/regions.js"],"names":["root","factory","exports","module","define","amd","window","installedModules","__webpack_require__","moduleId","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","Region","params","ws","this","wavesurfer","wrapper","drawer","util","style","id","getId","start","Number","end","scrollWidth","getDuration","resize","undefined","Boolean","drag","loop","color","data","attributes","maxLength","minLength","_onRedraw","updateRender","scroll","scrollParent","scrollSpeed","scrollThreshold","bindInOut","render","on","fireEvent","element","removeChild","un","play","once","playLoop","regionEl","document","createElement","attrname","className","title","formatTime","setAttribute","position","zIndex","height","top","handleLeft","appendChild","handleRight","css","cursor","left","width","maxWidth","bindEvents","map","time","Math","floor","slice","join","pixelRatio","dur","getWidth","startLimited","endLimited","max","min","round","regionWidth","backgroundColor","firedIn","firedOut","onProcess","backend","startTime","touchId","maxScroll","scrollDirection","wrapperRect","container","duration","updated","onDown","onUp","onMove","addEventListener","e","preventDefault","stopPropagation","touches","length","targetTouches","identifier","handleEvent","clientWidth","getBoundingClientRect","target","tagName","toLowerCase","classList","contains","preventClick","oldTime","delta","onDrag","onResize","regionRect","x","right","clientX","edgeScroll","scrollLeft","requestAnimationFrame","body","removeEventListener","maxEnd","update","direction","RegionsPlugin","getOwnPropertyNames","Observer","forEach","_onBackendCreated","regions","region","add","list","_onReady","dragSelection","enableDragSelection","keys","deferInit","staticProps","initRegions","console","warn","initPlugin","addRegion","options","initialisedPluginList","clearRegions","clear","disableDragSelection","instance","isReady","remove","slop","pxMove","eventDown","eventUp","eventMove","getCurrentTime","cur"],"mappings":"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","file":"wavesurfer.regions.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"regions\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"regions\"] = factory();\n\telse\n\t\troot[\"WaveSurfer\"] = root[\"WaveSurfer\"] || {}, root[\"WaveSurfer\"][\"regions\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"localhost:8080/dist/plugin/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 2);\n","/**\n * (Single) Region plugin class\n *\n * Must be turned into an observer before instantiating. This is done in\n * RegionsPlugin (main plugin class)\n *\n * @extends {Observer}\n */\nclass Region {\n    constructor(params, ws) {\n        this.wavesurfer = ws;\n        this.wrapper = ws.drawer.wrapper;\n        this.util = ws.util;\n        this.style = this.util.style;\n\n        this.id = params.id == null ? ws.util.getId() : params.id;\n        this.start = Number(params.start) || 0;\n        this.end =\n            params.end == null\n                ? // small marker-like region\n                  this.start +\n                  (4 / this.wrapper.scrollWidth) * this.wavesurfer.getDuration()\n                : Number(params.end);\n        this.resize =\n            params.resize === undefined ? true : Boolean(params.resize);\n        this.drag = params.drag === undefined ? true : Boolean(params.drag);\n        this.loop = Boolean(params.loop);\n        this.color = params.color || 'rgba(0, 0, 0, 0.1)';\n        this.data = params.data || {};\n        this.attributes = params.attributes || {};\n\n        this.maxLength = params.maxLength;\n        this.minLength = params.minLength;\n        this._onRedraw = () => this.updateRender();\n\n        this.scroll = params.scroll !== false && ws.params.scrollParent;\n        this.scrollSpeed = params.scrollSpeed || 1;\n        this.scrollThreshold = params.scrollThreshold || 10;\n\n        this.bindInOut();\n        this.render();\n        this.wavesurfer.on('zoom', this._onRedraw);\n        this.wavesurfer.on('redraw', this._onRedraw);\n        this.wavesurfer.fireEvent('region-created', this);\n    }\n\n    /* Update region params. */\n    update(params) {\n        if (null != params.start) {\n            this.start = Number(params.start);\n        }\n        if (null != params.end) {\n            this.end = Number(params.end);\n        }\n        if (null != params.loop) {\n            this.loop = Boolean(params.loop);\n        }\n        if (null != params.color) {\n            this.color = params.color;\n        }\n        if (null != params.data) {\n            this.data = params.data;\n        }\n        if (null != params.resize) {\n            this.resize = Boolean(params.resize);\n        }\n        if (null != params.drag) {\n            this.drag = Boolean(params.drag);\n        }\n        if (null != params.maxLength) {\n            this.maxLength = Number(params.maxLength);\n        }\n        if (null != params.minLength) {\n            this.minLength = Number(params.minLength);\n        }\n        if (null != params.attributes) {\n            this.attributes = params.attributes;\n        }\n\n        this.updateRender();\n        this.fireEvent('update');\n        this.wavesurfer.fireEvent('region-updated', this);\n    }\n\n    /* Remove a single region. */\n    remove() {\n        if (this.element) {\n            this.wrapper.removeChild(this.element);\n            this.element = null;\n            this.fireEvent('remove');\n            this.wavesurfer.un('zoom', this._onRedraw);\n            this.wavesurfer.un('redraw', this._onRedraw);\n            this.wavesurfer.fireEvent('region-removed', this);\n        }\n    }\n\n    /* Play the audio region. */\n    play() {\n        this.wavesurfer.play(this.start, this.end);\n        this.fireEvent('play');\n        this.wavesurfer.fireEvent('region-play', this);\n    }\n\n    /* Play the region in loop. */\n    playLoop() {\n        this.play();\n        this.once('out', () => this.playLoop());\n    }\n\n    /* Render a region as a DOM element. */\n    render() {\n        const regionEl = document.createElement('region');\n        regionEl.className = 'wavesurfer-region';\n        regionEl.title = this.formatTime(this.start, this.end);\n        regionEl.setAttribute('data-id', this.id);\n\n        for (const attrname in this.attributes) {\n            regionEl.setAttribute(\n                'data-region-' + attrname,\n                this.attributes[attrname]\n            );\n        }\n\n        const width = this.wrapper.scrollWidth;\n        this.style(regionEl, {\n            position: 'absolute',\n            zIndex: 2,\n            height: '100%',\n            top: '0px'\n        });\n\n        /* Resize handles */\n        if (this.resize) {\n            const handleLeft = regionEl.appendChild(\n                document.createElement('handle')\n            );\n            const handleRight = regionEl.appendChild(\n                document.createElement('handle')\n            );\n            handleLeft.className = 'wavesurfer-handle wavesurfer-handle-start';\n            handleRight.className = 'wavesurfer-handle wavesurfer-handle-end';\n            const css = {\n                cursor: 'col-resize',\n                position: 'absolute',\n                left: '0px',\n                top: '0px',\n                width: '1%',\n                maxWidth: '4px',\n                height: '100%'\n            };\n            this.style(handleLeft, css);\n            this.style(handleRight, css);\n            this.style(handleRight, {\n                left: '100%'\n            });\n        }\n\n        this.element = this.wrapper.appendChild(regionEl);\n        this.updateRender();\n        this.bindEvents(regionEl);\n    }\n\n    formatTime(start, end) {\n        return (start == end ? [start] : [start, end])\n            .map(time =>\n                [\n                    Math.floor((time % 3600) / 60), // minutes\n                    ('00' + Math.floor(time % 60)).slice(-2) // seconds\n                ].join(':')\n            )\n            .join('-');\n    }\n\n    getWidth() {\n        return this.wavesurfer.drawer.width / this.wavesurfer.params.pixelRatio;\n    }\n\n    /* Update element's position, width, color. */\n    updateRender() {\n        // duration varies during loading process, so don't overwrite important data\n        const dur = this.wavesurfer.getDuration();\n        const width = this.getWidth();\n\n        var startLimited = this.start;\n        var endLimited = this.end;\n        if (startLimited < 0) {\n            startLimited = 0;\n            endLimited = endLimited - startLimited;\n        }\n        if (endLimited > dur) {\n            endLimited = dur;\n            startLimited = dur - (endLimited - startLimited);\n        }\n\n        if (this.minLength != null) {\n            endLimited = Math.max(startLimited + this.minLength, endLimited);\n        }\n\n        if (this.maxLength != null) {\n            endLimited = Math.min(startLimited + this.maxLength, endLimited);\n        }\n\n        if (this.element != null) {\n            // Calculate the left and width values of the region such that\n            // no gaps appear between regions.\n            const left = Math.round((startLimited / dur) * width);\n            const regionWidth = Math.round((endLimited / dur) * width) - left;\n\n            this.style(this.element, {\n                left: left + 'px',\n                width: regionWidth + 'px',\n                backgroundColor: this.color,\n                cursor: this.drag ? 'move' : 'default'\n            });\n\n            for (const attrname in this.attributes) {\n                this.element.setAttribute(\n                    'data-region-' + attrname,\n                    this.attributes[attrname]\n                );\n            }\n\n            this.element.title = this.formatTime(this.start, this.end);\n        }\n    }\n\n    /* Bind audio events. */\n    bindInOut() {\n        this.firedIn = false;\n        this.firedOut = false;\n\n        const onProcess = time => {\n            if (\n                !this.firedOut &&\n                this.firedIn &&\n                (this.start >= Math.round(time * 100) / 100 ||\n                    this.end <= Math.round(time * 100) / 100)\n            ) {\n                this.firedOut = true;\n                this.firedIn = false;\n                this.fireEvent('out');\n                this.wavesurfer.fireEvent('region-out', this);\n            }\n            if (!this.firedIn && this.start <= time && this.end > time) {\n                this.firedIn = true;\n                this.firedOut = false;\n                this.fireEvent('in');\n                this.wavesurfer.fireEvent('region-in', this);\n            }\n        };\n\n        this.wavesurfer.backend.on('audioprocess', onProcess);\n\n        this.on('remove', () => {\n            this.wavesurfer.backend.un('audioprocess', onProcess);\n        });\n\n        /* Loop playback. */\n        this.on('out', () => {\n            if (this.loop) {\n                this.wavesurfer.play(this.start);\n            }\n        });\n    }\n\n    /* Bind DOM events. */\n    bindEvents() {\n        this.element.addEventListener('mouseenter', e => {\n            this.fireEvent('mouseenter', e);\n            this.wavesurfer.fireEvent('region-mouseenter', this, e);\n        });\n\n        this.element.addEventListener('mouseleave', e => {\n            this.fireEvent('mouseleave', e);\n            this.wavesurfer.fireEvent('region-mouseleave', this, e);\n        });\n\n        this.element.addEventListener('click', e => {\n            e.preventDefault();\n            this.fireEvent('click', e);\n            this.wavesurfer.fireEvent('region-click', this, e);\n        });\n\n        this.element.addEventListener('dblclick', e => {\n            e.stopPropagation();\n            e.preventDefault();\n            this.fireEvent('dblclick', e);\n            this.wavesurfer.fireEvent('region-dblclick', this, e);\n        });\n\n        /* Drag or resize on mousemove. */\n        (this.drag || this.resize) &&\n            (() => {\n                const container = this.wavesurfer.drawer.container;\n                const duration = this.wavesurfer.getDuration();\n                const scrollSpeed = this.scrollSpeed;\n                const scrollThreshold = this.scrollThreshold;\n                let startTime;\n                let touchId;\n                let drag;\n                let maxScroll;\n                let resize;\n                let updated = false;\n                let scrollDirection;\n                let wrapperRect;\n\n                // Scroll when the user is dragging within the threshold\n                const edgeScroll = e => {\n                    if (!scrollDirection || (!drag && !resize)) {\n                        return;\n                    }\n\n                    // Update scroll position\n                    let scrollLeft =\n                        this.wrapper.scrollLeft + scrollSpeed * scrollDirection;\n                    this.wrapper.scrollLeft = scrollLeft = Math.min(\n                        maxScroll,\n                        Math.max(0, scrollLeft)\n                    );\n\n                    // Update time\n                    const time =\n                        this.wavesurfer.drawer.handleEvent(e) * duration;\n                    const delta = time - startTime;\n                    startTime = time;\n\n                    // Continue dragging or resizing\n                    drag ? this.onDrag(delta) : this.onResize(delta, resize);\n\n                    // Repeat\n                    window.requestAnimationFrame(() => {\n                        edgeScroll(e);\n                    });\n                };\n\n                const onDown = e => {\n                    if (e.touches && e.touches.length > 1) {\n                        return;\n                    }\n                    touchId = e.targetTouches\n                        ? e.targetTouches[0].identifier\n                        : null;\n\n                    e.stopPropagation();\n                    startTime =\n                        this.wavesurfer.drawer.handleEvent(e, true) * duration;\n\n                    // Store for scroll calculations\n                    maxScroll =\n                        this.wrapper.scrollWidth - this.wrapper.clientWidth;\n                    wrapperRect = this.wrapper.getBoundingClientRect();\n\n                    if (e.target.tagName.toLowerCase() == 'handle') {\n                        if (\n                            e.target.classList.contains(\n                                'wavesurfer-handle-start'\n                            )\n                        ) {\n                            resize = 'start';\n                        } else {\n                            resize = 'end';\n                        }\n                    } else {\n                        drag = true;\n                        resize = false;\n                    }\n                };\n                const onUp = e => {\n                    if (e.touches && e.touches.length > 1) {\n                        return;\n                    }\n\n                    if (drag || resize) {\n                        drag = false;\n                        scrollDirection = null;\n                        resize = false;\n                    }\n\n                    if (updated) {\n                        updated = false;\n                        this.util.preventClick();\n                        this.fireEvent('update-end', e);\n                        this.wavesurfer.fireEvent('region-update-end', this, e);\n                    }\n                };\n                const onMove = e => {\n                    if (e.touches && e.touches.length > 1) {\n                        return;\n                    }\n                    if (\n                        e.targetTouches &&\n                        e.targetTouches[0].identifier != touchId\n                    ) {\n                        return;\n                    }\n\n                    if (drag || resize) {\n                        const oldTime = startTime;\n                        const time =\n                            this.wavesurfer.drawer.handleEvent(e) * duration;\n                        const delta = time - startTime;\n                        startTime = time;\n\n                        // Drag\n                        if (this.drag && drag) {\n                            updated = updated || !!delta;\n                            this.onDrag(delta);\n                        }\n\n                        // Resize\n                        if (this.resize && resize) {\n                            updated = updated || !!delta;\n                            this.onResize(delta, resize);\n                        }\n\n                        if (\n                            this.scroll &&\n                            container.clientWidth < this.wrapper.scrollWidth\n                        ) {\n                            if (drag) {\n                                // The threshold is not between the mouse and the container edge\n                                // but is between the region and the container edge\n                                const regionRect = this.element.getBoundingClientRect();\n                                let x = regionRect.left - wrapperRect.left;\n\n                                // Check direction\n                                if (time < oldTime && x >= 0) {\n                                    scrollDirection = -1;\n                                } else if (\n                                    time > oldTime &&\n                                    x + regionRect.width <= wrapperRect.right\n                                ) {\n                                    scrollDirection = 1;\n                                }\n\n                                // Check that we are still beyond the threshold\n                                if (\n                                    (scrollDirection === -1 &&\n                                        x > scrollThreshold) ||\n                                    (scrollDirection === 1 &&\n                                        x + regionRect.width <\n                                            wrapperRect.right - scrollThreshold)\n                                ) {\n                                    scrollDirection = null;\n                                }\n                            } else {\n                                // Mouse based threshold\n                                let x = e.clientX - wrapperRect.left;\n\n                                // Check direction\n                                if (x <= scrollThreshold) {\n                                    scrollDirection = -1;\n                                } else if (\n                                    x >=\n                                    wrapperRect.right - scrollThreshold\n                                ) {\n                                    scrollDirection = 1;\n                                } else {\n                                    scrollDirection = null;\n                                }\n                            }\n\n                            scrollDirection && edgeScroll(e);\n                        }\n                    }\n                };\n\n                this.element.addEventListener('mousedown', onDown);\n                this.element.addEventListener('touchstart', onDown);\n\n                this.wrapper.addEventListener('mousemove', onMove);\n                this.wrapper.addEventListener('touchmove', onMove);\n\n                document.body.addEventListener('mouseup', onUp);\n                document.body.addEventListener('touchend', onUp);\n\n                this.on('remove', () => {\n                    document.body.removeEventListener('mouseup', onUp);\n                    document.body.removeEventListener('touchend', onUp);\n                    this.wrapper.removeEventListener('mousemove', onMove);\n                    this.wrapper.removeEventListener('touchmove', onMove);\n                });\n\n                this.wavesurfer.on('destroy', () => {\n                    document.body.removeEventListener('mouseup', onUp);\n                    document.body.removeEventListener('touchend', onUp);\n                });\n            })();\n    }\n\n    onDrag(delta) {\n        const maxEnd = this.wavesurfer.getDuration();\n        if (this.end + delta > maxEnd || this.start + delta < 0) {\n            return;\n        }\n\n        this.update({\n            start: this.start + delta,\n            end: this.end + delta\n        });\n    }\n\n    onResize(delta, direction) {\n        if (direction == 'start') {\n            this.update({\n                start: Math.min(this.start + delta, this.end),\n                end: Math.max(this.start + delta, this.end)\n            });\n        } else {\n            this.update({\n                start: Math.min(this.end + delta, this.start),\n                end: Math.max(this.end + delta, this.start)\n            });\n        }\n    }\n}\n\n/**\n * @typedef {Object} RegionsPluginParams\n * @property {?boolean} dragSelection Enable creating regions by dragging with\n * the mouse\n * @property {?RegionParams[]} regions Regions that should be added upon\n * initialisation\n * @property {number} slop=2 The sensitivity of the mouse dragging\n * @property {?boolean} deferInit Set to true to manually call\n * `initPlugin('regions')`\n */\n\n/**\n * @typedef {Object} RegionParams\n * @desc The parameters used to describe a region.\n * @example wavesurfer.addRegion(regionParams);\n * @property {string} id=ârandom The id of the region\n * @property {number} start=0 The start position of the region (in seconds).\n * @property {number} end=0 The end position of the region (in seconds).\n * @property {?boolean} loop Whether to loop the region when played back.\n * @property {boolean} drag=true Allow/disallow dragging the region.\n * @property {boolean} resize=true Allow/disallow resizing the region.\n * @property {string} [color='rgba(0, 0, 0, 0.1)'] HTML color code.\n */\n\n/**\n * Regions are visual overlays on waveform that can be used to play and loop\n * portions of audio. Regions can be dragged and resized.\n *\n * Visual customization is possible via CSS (using the selectors\n * `.wavesurfer-region` and `.wavesurfer-handle`).\n *\n * @implements {PluginClass}\n * @extends {Observer}\n *\n * @example\n * // es6\n * import RegionsPlugin from 'wavesurfer.regions.js';\n *\n * // commonjs\n * var RegionsPlugin = require('wavesurfer.regions.js');\n *\n * // if you are using <script> tags\n * var RegionsPlugin = window.WaveSurfer.regions;\n *\n * // ... initialising wavesurfer with the plugin\n * var wavesurfer = WaveSurfer.create({\n *   // wavesurfer options ...\n *   plugins: [\n *     RegionsPlugin.create({\n *       // plugin options ...\n *     })\n *   ]\n * });\n */\nexport default class RegionsPlugin {\n    /**\n     * Regions plugin definition factory\n     *\n     * This function must be used to create a plugin definition which can be\n     * used by wavesurfer to correctly instantiate the plugin.\n     *\n     * @param {RegionsPluginParams} params parameters use to initialise the plugin\n     * @return {PluginDefinition} an object representing the plugin\n     */\n    static create(params) {\n        return {\n            name: 'regions',\n            deferInit: params && params.deferInit ? params.deferInit : false,\n            params: params,\n            staticProps: {\n                initRegions() {\n                    console.warn(\n                        'Deprecated initRegions! Use wavesurfer.initPlugins(\"regions\") instead!'\n                    );\n                    this.initPlugin('regions');\n                },\n\n                addRegion(options) {\n                    if (!this.initialisedPluginList.regions) {\n                        this.initPlugin('regions');\n                    }\n                    return this.regions.add(options);\n                },\n\n                clearRegions() {\n                    this.regions && this.regions.clear();\n                },\n\n                enableDragSelection(options) {\n                    if (!this.initialisedPluginList.regions) {\n                        this.initPlugin('regions');\n                    }\n                    this.regions.enableDragSelection(options);\n                },\n\n                disableDragSelection() {\n                    this.regions.disableDragSelection();\n                }\n            },\n            instance: RegionsPlugin\n        };\n    }\n\n    constructor(params, ws) {\n        this.params = params;\n        this.wavesurfer = ws;\n        this.util = ws.util;\n\n        // turn the plugin instance into an observer\n        const observerPrototypeKeys = Object.getOwnPropertyNames(\n            this.util.Observer.prototype\n        );\n        observerPrototypeKeys.forEach(key => {\n            Region.prototype[key] = this.util.Observer.prototype[key];\n        });\n        this.wavesurfer.Region = Region;\n\n        this._onBackendCreated = () => {\n            this.wrapper = this.wavesurfer.drawer.wrapper;\n            if (this.params.regions) {\n                this.params.regions.forEach(region => {\n                    this.add(region);\n                });\n            }\n        };\n\n        // Id-based hash of regions.\n        this.list = {};\n        this._onReady = () => {\n            if (this.params.dragSelection) {\n                this.enableDragSelection(this.params);\n            }\n            Object.keys(this.list).forEach(id => {\n                this.list[id].updateRender();\n            });\n        };\n    }\n\n    init() {\n        // Check if ws is ready\n        if (this.wavesurfer.isReady) {\n            this._onBackendCreated();\n            this._onReady();\n        }\n        this.wavesurfer.on('ready', this._onReady);\n        this.wavesurfer.on('backend-created', this._onBackendCreated);\n    }\n\n    destroy() {\n        this.wavesurfer.un('ready', this._onReady);\n        this.wavesurfer.un('backend-created', this._onBackendCreated);\n        this.disableDragSelection();\n        this.clear();\n    }\n    /* Add a region. */\n    add(params) {\n        const region = new this.wavesurfer.Region(params, this.wavesurfer);\n\n        this.list[region.id] = region;\n\n        region.on('remove', () => {\n            delete this.list[region.id];\n        });\n\n        return region;\n    }\n\n    /* Remove all regions. */\n    clear() {\n        Object.keys(this.list).forEach(id => {\n            this.list[id].remove();\n        });\n    }\n\n    enableDragSelection(params) {\n        const slop = params.slop || 2;\n        const container = this.wavesurfer.drawer.container;\n        const scroll =\n            params.scroll !== false && this.wavesurfer.params.scrollParent;\n        const scrollSpeed = params.scrollSpeed || 1;\n        const scrollThreshold = params.scrollThreshold || 10;\n        let drag;\n        let duration = this.wavesurfer.getDuration();\n        let maxScroll;\n        let start;\n        let region;\n        let touchId;\n        let pxMove = 0;\n        let scrollDirection;\n        let wrapperRect;\n\n        // Scroll when the user is dragging within the threshold\n        const edgeScroll = e => {\n            if (!region || !scrollDirection) {\n                return;\n            }\n\n            // Update scroll position\n            let scrollLeft =\n                this.wrapper.scrollLeft + scrollSpeed * scrollDirection;\n            this.wrapper.scrollLeft = scrollLeft = Math.min(\n                maxScroll,\n                Math.max(0, scrollLeft)\n            );\n\n            // Update range\n            const end = this.wavesurfer.drawer.handleEvent(e);\n            region.update({\n                start: Math.min(end * duration, start * duration),\n                end: Math.max(end * duration, start * duration)\n            });\n\n            // Check that there is more to scroll and repeat\n            if (scrollLeft < maxScroll && scrollLeft > 0) {\n                window.requestAnimationFrame(() => {\n                    edgeScroll(e);\n                });\n            }\n        };\n\n        const eventDown = e => {\n            if (e.touches && e.touches.length > 1) {\n                return;\n            }\n            duration = this.wavesurfer.getDuration();\n            touchId = e.targetTouches ? e.targetTouches[0].identifier : null;\n\n            // Store for scroll calculations\n            maxScroll = this.wrapper.scrollWidth - this.wrapper.clientWidth;\n            wrapperRect = this.wrapper.getBoundingClientRect();\n\n            drag = true;\n            start = this.wavesurfer.drawer.handleEvent(e, true);\n            region = null;\n            scrollDirection = null;\n        };\n        this.wrapper.addEventListener('mousedown', eventDown);\n        this.wrapper.addEventListener('touchstart', eventDown);\n        this.on('disable-drag-selection', () => {\n            this.wrapper.removeEventListener('touchstart', eventDown);\n            this.wrapper.removeEventListener('mousedown', eventDown);\n        });\n\n        const eventUp = e => {\n            if (e.touches && e.touches.length > 1) {\n                return;\n            }\n\n            drag = false;\n            pxMove = 0;\n            scrollDirection = null;\n\n            if (region) {\n                this.util.preventClick();\n                region.fireEvent('update-end', e);\n                this.wavesurfer.fireEvent('region-update-end', region, e);\n            }\n\n            region = null;\n        };\n        this.wrapper.addEventListener('mouseup', eventUp);\n        this.wrapper.addEventListener('touchend', eventUp);\n\n        document.body.addEventListener('mouseup', eventUp);\n        document.body.addEventListener('touchend', eventUp);\n        this.on('disable-drag-selection', () => {\n            document.body.removeEventListener('mouseup', eventUp);\n            document.body.removeEventListener('touchend', eventUp);\n            this.wrapper.removeEventListener('touchend', eventUp);\n            this.wrapper.removeEventListener('mouseup', eventUp);\n        });\n\n        const eventMove = e => {\n            if (!drag) {\n                return;\n            }\n            if (++pxMove <= slop) {\n                return;\n            }\n\n            if (e.touches && e.touches.length > 1) {\n                return;\n            }\n            if (e.targetTouches && e.targetTouches[0].identifier != touchId) {\n                return;\n            }\n\n            if (!region) {\n                region = this.add(params || {});\n            }\n\n            const end = this.wavesurfer.drawer.handleEvent(e);\n            region.update({\n                start: Math.min(end * duration, start * duration),\n                end: Math.max(end * duration, start * duration)\n            });\n\n            // If scrolling is enabled\n            if (scroll && container.clientWidth < this.wrapper.scrollWidth) {\n                // Check threshold based on mouse\n                const x = e.clientX - wrapperRect.left;\n                if (x <= scrollThreshold) {\n                    scrollDirection = -1;\n                } else if (x >= wrapperRect.right - scrollThreshold) {\n                    scrollDirection = 1;\n                } else {\n                    scrollDirection = null;\n                }\n                scrollDirection && edgeScroll(e);\n            }\n        };\n        this.wrapper.addEventListener('mousemove', eventMove);\n        this.wrapper.addEventListener('touchmove', eventMove);\n        this.on('disable-drag-selection', () => {\n            this.wrapper.removeEventListener('touchmove', eventMove);\n            this.wrapper.removeEventListener('mousemove', eventMove);\n        });\n    }\n\n    disableDragSelection() {\n        this.fireEvent('disable-drag-selection');\n    }\n\n    /* Get current region\n     *  The smallest region that contains the current time.\n     *  If several such regions exist, we take the first.\n     *  Return null if none exist. */\n    getCurrentRegion() {\n        const time = this.wavesurfer.getCurrentTime();\n        let min = null;\n        Object.keys(this.list).forEach(id => {\n            const cur = this.list[id];\n            if (cur.start <= time && cur.end >= time) {\n                if (!min || cur.end - cur.start < min.end - min.start) {\n                    min = cur;\n                }\n            }\n        });\n\n        return min;\n    }\n}\n"],"sourceRoot":""}
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.spectrogram.js
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.spectrogram.js	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.spectrogram.js	(revision 33546)
@@ -0,0 +1,762 @@
+/*!
+ * wavesurfer.js spectrogram plugin 2.2.1 (2019-09-30)
+ * https://github.com/katspaugh/wavesurfer.js
+ * @license BSD-3-Clause
+ */
+(function webpackUniversalModuleDefinition(root, factory) {
+	if(typeof exports === 'object' && typeof module === 'object')
+		module.exports = factory();
+	else if(typeof define === 'function' && define.amd)
+		define("spectrogram", [], factory);
+	else if(typeof exports === 'object')
+		exports["spectrogram"] = factory();
+	else
+		root["WaveSurfer"] = root["WaveSurfer"] || {}, root["WaveSurfer"]["spectrogram"] = factory();
+})(window, function() {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+/******/
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId]) {
+/******/ 			return installedModules[moduleId].exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			i: moduleId,
+/******/ 			l: false,
+/******/ 			exports: {}
+/******/ 		};
+/******/
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ 		// Flag the module as loaded
+/******/ 		module.l = true;
+/******/
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/
+/******/
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+/******/
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+/******/
+/******/ 	// define getter function for harmony exports
+/******/ 	__webpack_require__.d = function(exports, name, getter) {
+/******/ 		if(!__webpack_require__.o(exports, name)) {
+/******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
+/******/ 		}
+/******/ 	};
+/******/
+/******/ 	// define __esModule on exports
+/******/ 	__webpack_require__.r = function(exports) {
+/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ 		}
+/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
+/******/ 	};
+/******/
+/******/ 	// create a fake namespace object
+/******/ 	// mode & 1: value is a module id, require it
+/******/ 	// mode & 2: merge all properties of value into the ns
+/******/ 	// mode & 4: return value when already ns object
+/******/ 	// mode & 8|1: behave like require
+/******/ 	__webpack_require__.t = function(value, mode) {
+/******/ 		if(mode & 1) value = __webpack_require__(value);
+/******/ 		if(mode & 8) return value;
+/******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
+/******/ 		var ns = Object.create(null);
+/******/ 		__webpack_require__.r(ns);
+/******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
+/******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
+/******/ 		return ns;
+/******/ 	};
+/******/
+/******/ 	// getDefaultExport function for compatibility with non-harmony modules
+/******/ 	__webpack_require__.n = function(module) {
+/******/ 		var getter = module && module.__esModule ?
+/******/ 			function getDefault() { return module['default']; } :
+/******/ 			function getModuleExports() { return module; };
+/******/ 		__webpack_require__.d(getter, 'a', getter);
+/******/ 		return getter;
+/******/ 	};
+/******/
+/******/ 	// Object.prototype.hasOwnProperty.call
+/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "localhost:8080/dist/plugin/";
+/******/
+/******/
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(__webpack_require__.s = "./src/plugin/spectrogram.js");
+/******/ })
+/************************************************************************/
+/******/ ({
+
+/***/ "./src/plugin/spectrogram.js":
+/*!***********************************!*\
+  !*** ./src/plugin/spectrogram.js ***!
+  \***********************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+/**
+ * Calculate FFT - Based on https://github.com/corbanbrook/dsp.js
+ */
+
+/* eslint-disable complexity, no-redeclare, no-var, one-var */
+var FFT = function FFT(bufferSize, sampleRate, windowFunc, alpha) {
+  this.bufferSize = bufferSize;
+  this.sampleRate = sampleRate;
+  this.bandwidth = 2 / bufferSize * (sampleRate / 2);
+  this.sinTable = new Float32Array(bufferSize);
+  this.cosTable = new Float32Array(bufferSize);
+  this.windowValues = new Float32Array(bufferSize);
+  this.reverseTable = new Uint32Array(bufferSize);
+  this.peakBand = 0;
+  this.peak = 0;
+  var i;
+
+  switch (windowFunc) {
+    case 'bartlett':
+      for (i = 0; i < bufferSize; i++) {
+        this.windowValues[i] = 2 / (bufferSize - 1) * ((bufferSize - 1) / 2 - Math.abs(i - (bufferSize - 1) / 2));
+      }
+
+      break;
+
+    case 'bartlettHann':
+      for (i = 0; i < bufferSize; i++) {
+        this.windowValues[i] = 0.62 - 0.48 * Math.abs(i / (bufferSize - 1) - 0.5) - 0.38 * Math.cos(Math.PI * 2 * i / (bufferSize - 1));
+      }
+
+      break;
+
+    case 'blackman':
+      alpha = alpha || 0.16;
+
+      for (i = 0; i < bufferSize; i++) {
+        this.windowValues[i] = (1 - alpha) / 2 - 0.5 * Math.cos(Math.PI * 2 * i / (bufferSize - 1)) + alpha / 2 * Math.cos(4 * Math.PI * i / (bufferSize - 1));
+      }
+
+      break;
+
+    case 'cosine':
+      for (i = 0; i < bufferSize; i++) {
+        this.windowValues[i] = Math.cos(Math.PI * i / (bufferSize - 1) - Math.PI / 2);
+      }
+
+      break;
+
+    case 'gauss':
+      alpha = alpha || 0.25;
+
+      for (i = 0; i < bufferSize; i++) {
+        this.windowValues[i] = Math.pow(Math.E, -0.5 * Math.pow((i - (bufferSize - 1) / 2) / (alpha * (bufferSize - 1) / 2), 2));
+      }
+
+      break;
+
+    case 'hamming':
+      for (i = 0; i < bufferSize; i++) {
+        this.windowValues[i] = (0.54 - 0.46) * Math.cos(Math.PI * 2 * i / (bufferSize - 1));
+      }
+
+      break;
+
+    case 'hann':
+    case undefined:
+      for (i = 0; i < bufferSize; i++) {
+        this.windowValues[i] = 0.5 * (1 - Math.cos(Math.PI * 2 * i / (bufferSize - 1)));
+      }
+
+      break;
+
+    case 'lanczoz':
+      for (i = 0; i < bufferSize; i++) {
+        this.windowValues[i] = Math.sin(Math.PI * (2 * i / (bufferSize - 1) - 1)) / (Math.PI * (2 * i / (bufferSize - 1) - 1));
+      }
+
+      break;
+
+    case 'rectangular':
+      for (i = 0; i < bufferSize; i++) {
+        this.windowValues[i] = 1;
+      }
+
+      break;
+
+    case 'triangular':
+      for (i = 0; i < bufferSize; i++) {
+        this.windowValues[i] = 2 / bufferSize * (bufferSize / 2 - Math.abs(i - (bufferSize - 1) / 2));
+      }
+
+      break;
+
+    default:
+      throw Error("No such window function '" + windowFunc + "'");
+  }
+
+  var limit = 1;
+  var bit = bufferSize >> 1;
+  var i;
+
+  while (limit < bufferSize) {
+    for (i = 0; i < limit; i++) {
+      this.reverseTable[i + limit] = this.reverseTable[i] + bit;
+    }
+
+    limit = limit << 1;
+    bit = bit >> 1;
+  }
+
+  for (i = 0; i < bufferSize; i++) {
+    this.sinTable[i] = Math.sin(-Math.PI / i);
+    this.cosTable[i] = Math.cos(-Math.PI / i);
+  }
+
+  this.calculateSpectrum = function (buffer) {
+    // Locally scope variables for speed up
+    var bufferSize = this.bufferSize,
+        cosTable = this.cosTable,
+        sinTable = this.sinTable,
+        reverseTable = this.reverseTable,
+        real = new Float32Array(bufferSize),
+        imag = new Float32Array(bufferSize),
+        bSi = 2 / this.bufferSize,
+        sqrt = Math.sqrt,
+        rval,
+        ival,
+        mag,
+        spectrum = new Float32Array(bufferSize / 2);
+    var k = Math.floor(Math.log(bufferSize) / Math.LN2);
+
+    if (Math.pow(2, k) !== bufferSize) {
+      throw 'Invalid buffer size, must be a power of 2.';
+    }
+
+    if (bufferSize !== buffer.length) {
+      throw 'Supplied buffer is not the same size as defined FFT. FFT Size: ' + bufferSize + ' Buffer Size: ' + buffer.length;
+    }
+
+    var halfSize = 1,
+        phaseShiftStepReal,
+        phaseShiftStepImag,
+        currentPhaseShiftReal,
+        currentPhaseShiftImag,
+        off,
+        tr,
+        ti,
+        tmpReal;
+
+    for (var i = 0; i < bufferSize; i++) {
+      real[i] = buffer[reverseTable[i]] * this.windowValues[reverseTable[i]];
+      imag[i] = 0;
+    }
+
+    while (halfSize < bufferSize) {
+      phaseShiftStepReal = cosTable[halfSize];
+      phaseShiftStepImag = sinTable[halfSize];
+      currentPhaseShiftReal = 1;
+      currentPhaseShiftImag = 0;
+
+      for (var fftStep = 0; fftStep < halfSize; fftStep++) {
+        var i = fftStep;
+
+        while (i < bufferSize) {
+          off = i + halfSize;
+          tr = currentPhaseShiftReal * real[off] - currentPhaseShiftImag * imag[off];
+          ti = currentPhaseShiftReal * imag[off] + currentPhaseShiftImag * real[off];
+          real[off] = real[i] - tr;
+          imag[off] = imag[i] - ti;
+          real[i] += tr;
+          imag[i] += ti;
+          i += halfSize << 1;
+        }
+
+        tmpReal = currentPhaseShiftReal;
+        currentPhaseShiftReal = tmpReal * phaseShiftStepReal - currentPhaseShiftImag * phaseShiftStepImag;
+        currentPhaseShiftImag = tmpReal * phaseShiftStepImag + currentPhaseShiftImag * phaseShiftStepReal;
+      }
+
+      halfSize = halfSize << 1;
+    }
+
+    for (var i = 0, N = bufferSize / 2; i < N; i++) {
+      rval = real[i];
+      ival = imag[i];
+      mag = bSi * sqrt(rval * rval + ival * ival);
+
+      if (mag > this.peak) {
+        this.peakBand = i;
+        this.peak = mag;
+      }
+
+      spectrum[i] = mag;
+    }
+
+    return spectrum;
+  };
+};
+/* eslint-enable complexity, no-redeclare, no-var, one-var */
+
+/**
+ * @typedef {Object} SpectrogramPluginParams
+ * @property {string|HTMLElement} container Selector of element or element in
+ * which to render
+ * @property {number} fftSamples=512 Number of samples to fetch to FFT. Must be
+ * a power of 2.
+ * @property {boolean} labels Set to true to display frequency labels.
+ * @property {number} noverlap Size of the overlapping window. Must be <
+ * fftSamples. Auto deduced from canvas size by default.
+ * @property {string} windowFunc='hann' The window function to be used. One of
+ * these: `'bartlett'`, `'bartlettHann'`, `'blackman'`, `'cosine'`, `'gauss'`,
+ * `'hamming'`, `'hann'`, `'lanczoz'`, `'rectangular'`, `'triangular'`
+ * @property {?number} alpha Some window functions have this extra value.
+ * (Between 0 and 1)
+ * @property {number} pixelRatio=wavesurfer.params.pixelRatio to control the
+ * size of the spectrogram in relation with its canvas. 1 = Draw on the whole
+ * canvas. 2 = Draw on a quarter (1/2 the length and 1/2 the width)
+ * @property {?boolean} deferInit Set to true to manually call
+ * `initPlugin('spectrogram')`
+ */
+
+/**
+ * Render a spectrogram visualisation of the audio.
+ *
+ * @implements {PluginClass}
+ * @extends {Observer}
+ * @example
+ * // es6
+ * import SpectrogramPlugin from 'wavesurfer.spectrogram.js';
+ *
+ * // commonjs
+ * var SpectrogramPlugin = require('wavesurfer.spectrogram.js');
+ *
+ * // if you are using <script> tags
+ * var SpectrogramPlugin = window.WaveSurfer.spectrogram;
+ *
+ * // ... initialising wavesurfer with the plugin
+ * var wavesurfer = WaveSurfer.create({
+ *   // wavesurfer options ...
+ *   plugins: [
+ *     SpectrogramPlugin.create({
+ *       // plugin options ...
+ *     })
+ *   ]
+ * });
+ */
+
+
+var SpectrogramPlugin =
+/*#__PURE__*/
+function () {
+  _createClass(SpectrogramPlugin, null, [{
+    key: "create",
+
+    /**
+     * Spectrogram plugin definition factory
+     *
+     * This function must be used to create a plugin definition which can be
+     * used by wavesurfer to correctly instantiate the plugin.
+     *
+     * @param  {SpectrogramPluginParams} params Parameters used to initialise the plugin
+     * @return {PluginDefinition} An object representing the plugin.
+     */
+    value: function create(params) {
+      return {
+        name: 'spectrogram',
+        deferInit: params && params.deferInit ? params.deferInit : false,
+        params: params,
+        staticProps: {
+          FFT: FFT
+        },
+        instance: SpectrogramPlugin
+      };
+    }
+  }]);
+
+  function SpectrogramPlugin(params, ws) {
+    var _this = this;
+
+    _classCallCheck(this, SpectrogramPlugin);
+
+    this.params = params;
+    this.wavesurfer = ws;
+    this.util = ws.util;
+    this.frequenciesDataUrl = params.frequenciesDataUrl;
+
+    this._onScroll = function (e) {
+      _this.updateScroll(e);
+    };
+
+    this._onRender = function () {
+      _this.render();
+    };
+
+    this._onWrapperClick = function (e) {
+      _this._wrapperClickHandler(e);
+    };
+
+    this._onReady = function () {
+      var drawer = _this.drawer = ws.drawer;
+      _this.container = 'string' == typeof params.container ? document.querySelector(params.container) : params.container;
+
+      if (!_this.container) {
+        throw Error('No container for WaveSurfer spectrogram');
+      }
+
+      _this.width = drawer.width;
+      _this.pixelRatio = _this.params.pixelRatio || ws.params.pixelRatio;
+      _this.fftSamples = _this.params.fftSamples || ws.params.fftSamples || 512;
+      _this.height = _this.fftSamples / 2;
+      _this.noverlap = params.noverlap;
+      _this.windowFunc = params.windowFunc;
+      _this.alpha = params.alpha;
+
+      _this.createWrapper();
+
+      _this.createCanvas();
+
+      _this.render();
+
+      drawer.wrapper.addEventListener('scroll', _this._onScroll);
+      ws.on('redraw', _this._onRender);
+    };
+  }
+
+  _createClass(SpectrogramPlugin, [{
+    key: "init",
+    value: function init() {
+      // Check if wavesurfer is ready
+      if (this.wavesurfer.isReady) {
+        this._onReady();
+      }
+
+      this.wavesurfer.on('ready', this._onReady);
+    }
+  }, {
+    key: "destroy",
+    value: function destroy() {
+      this.unAll();
+      this.wavesurfer.un('ready', this._onReady);
+      this.wavesurfer.un('redraw', this._onRender);
+      this.drawer.wrapper.removeEventListener('scroll', this._onScroll);
+      this.wavesurfer = null;
+      this.util = null;
+      this.params = null;
+
+      if (this.wrapper) {
+        this.wrapper.removeEventListener('click', this._onWrapperClick);
+        this.wrapper.parentNode.removeChild(this.wrapper);
+        this.wrapper = null;
+      }
+    }
+  }, {
+    key: "createWrapper",
+    value: function createWrapper() {
+      var prevSpectrogram = this.container.querySelector('spectrogram');
+
+      if (prevSpectrogram) {
+        this.container.removeChild(prevSpectrogram);
+      }
+
+      var wsParams = this.wavesurfer.params;
+      this.wrapper = document.createElement('spectrogram'); // if labels are active
+
+      if (this.params.labels) {
+        var labelsEl = this.labelsEl = document.createElement('canvas');
+        labelsEl.classList.add('spec-labels');
+        this.drawer.style(labelsEl, {
+          left: 0,
+          position: 'absolute',
+          zIndex: 9,
+          height: "".concat(this.height / this.pixelRatio, "px"),
+          width: "".concat(55 / this.pixelRatio, "px")
+        });
+        this.wrapper.appendChild(labelsEl);
+        this.loadLabels('rgba(68,68,68,0.5)', '12px', '10px', '', '#fff', '#f7f7f7', 'center', '#specLabels');
+      }
+
+      this.drawer.style(this.wrapper, {
+        display: 'block',
+        position: 'relative',
+        userSelect: 'none',
+        webkitUserSelect: 'none',
+        height: "".concat(this.height / this.pixelRatio, "px")
+      });
+
+      if (wsParams.fillParent || wsParams.scrollParent) {
+        this.drawer.style(this.wrapper, {
+          width: '100%',
+          overflowX: 'hidden',
+          overflowY: 'hidden'
+        });
+      }
+
+      this.container.appendChild(this.wrapper);
+      this.wrapper.addEventListener('click', this._onWrapperClick);
+    }
+  }, {
+    key: "_wrapperClickHandler",
+    value: function _wrapperClickHandler(event) {
+      event.preventDefault();
+      var relX = 'offsetX' in event ? event.offsetX : event.layerX;
+      this.fireEvent('click', relX / this.scrollWidth || 0);
+    }
+  }, {
+    key: "createCanvas",
+    value: function createCanvas() {
+      var canvas = this.canvas = this.wrapper.appendChild(document.createElement('canvas'));
+      this.spectrCc = canvas.getContext('2d');
+      this.util.style(canvas, {
+        position: 'absolute',
+        zIndex: 4
+      });
+    }
+  }, {
+    key: "render",
+    value: function render() {
+      this.updateCanvasStyle();
+
+      if (this.frequenciesDataUrl) {
+        this.loadFrequenciesData(this.frequenciesDataUrl);
+      } else {
+        this.getFrequencies(this.drawSpectrogram);
+      }
+    }
+  }, {
+    key: "updateCanvasStyle",
+    value: function updateCanvasStyle() {
+      var width = Math.round(this.width / this.pixelRatio) + 'px';
+      this.canvas.width = this.width;
+      this.canvas.height = this.height;
+      this.canvas.style.width = width;
+    }
+  }, {
+    key: "drawSpectrogram",
+    value: function drawSpectrogram(frequenciesData, my) {
+      var spectrCc = my.spectrCc;
+      var length = my.wavesurfer.backend.getDuration();
+      var height = my.height;
+      var pixels = my.resample(frequenciesData);
+      var heightFactor = my.buffer ? 2 / my.buffer.numberOfChannels : 1;
+      var i;
+      var j;
+
+      for (i = 0; i < pixels.length; i++) {
+        for (j = 0; j < pixels[i].length; j++) {
+          var colorValue = 255 - pixels[i][j];
+          my.spectrCc.fillStyle = 'rgb(' + colorValue + ', ' + colorValue + ', ' + colorValue + ')';
+          my.spectrCc.fillRect(i, height - j * heightFactor, 1, heightFactor);
+        }
+      }
+    }
+  }, {
+    key: "getFrequencies",
+    value: function getFrequencies(callback) {
+      var fftSamples = this.fftSamples;
+      var buffer = this.buffer = this.wavesurfer.backend.buffer;
+      var channelOne = buffer.getChannelData(0);
+      var bufferLength = buffer.length;
+      var sampleRate = buffer.sampleRate;
+      var frequencies = [];
+
+      if (!buffer) {
+        this.fireEvent('error', 'Web Audio buffer is not available');
+        return;
+      }
+
+      var noverlap = this.noverlap;
+
+      if (!noverlap) {
+        var uniqueSamplesPerPx = buffer.length / this.canvas.width;
+        noverlap = Math.max(0, Math.round(fftSamples - uniqueSamplesPerPx));
+      }
+
+      var fft = new FFT(fftSamples, sampleRate, this.windowFunc, this.alpha);
+      var maxSlicesCount = Math.floor(bufferLength / (fftSamples - noverlap));
+      var currentOffset = 0;
+
+      while (currentOffset + fftSamples < channelOne.length) {
+        var segment = channelOne.slice(currentOffset, currentOffset + fftSamples);
+        var spectrum = fft.calculateSpectrum(segment);
+        var array = new Uint8Array(fftSamples / 2);
+        var j = void 0;
+
+        for (j = 0; j < fftSamples / 2; j++) {
+          array[j] = Math.max(-255, Math.log10(spectrum[j]) * 45);
+        }
+
+        frequencies.push(array);
+        currentOffset += fftSamples - noverlap;
+      }
+
+      callback(frequencies, this);
+    }
+  }, {
+    key: "loadFrequenciesData",
+    value: function loadFrequenciesData(url) {
+      var _this2 = this;
+
+      var ajax = this.util.ajax({
+        url: url
+      });
+      ajax.on('success', function (data) {
+        return _this2.drawSpectrogram(JSON.parse(data), _this2);
+      });
+      ajax.on('error', function (e) {
+        return _this2.fireEvent('error', 'XHR error: ' + e.target.statusText);
+      });
+      return ajax;
+    }
+  }, {
+    key: "freqType",
+    value: function freqType(freq) {
+      return freq >= 1000 ? (freq / 1000).toFixed(1) : Math.round(freq);
+    }
+  }, {
+    key: "unitType",
+    value: function unitType(freq) {
+      return freq >= 1000 ? 'KHz' : 'Hz';
+    }
+  }, {
+    key: "loadLabels",
+    value: function loadLabels(bgFill, fontSizeFreq, fontSizeUnit, fontType, textColorFreq, textColorUnit, textAlign, container) {
+      var frequenciesHeight = this.height;
+      bgFill = bgFill || 'rgba(68,68,68,0)';
+      fontSizeFreq = fontSizeFreq || '12px';
+      fontSizeUnit = fontSizeUnit || '10px';
+      fontType = fontType || 'Helvetica';
+      textColorFreq = textColorFreq || '#fff';
+      textColorUnit = textColorUnit || '#fff';
+      textAlign = textAlign || 'center';
+      container = container || '#specLabels';
+      var getMaxY = frequenciesHeight || 512;
+      var labelIndex = 5 * (getMaxY / 256);
+      var freqStart = 0;
+      var step = (this.wavesurfer.backend.ac.sampleRate / 2 - freqStart) / labelIndex;
+      var ctx = this.labelsEl.getContext('2d');
+      this.labelsEl.height = this.height;
+      this.labelsEl.width = 55;
+      ctx.fillStyle = bgFill;
+      ctx.fillRect(0, 0, 55, getMaxY);
+      ctx.fill();
+      var i;
+
+      for (i = 0; i <= labelIndex; i++) {
+        ctx.textAlign = textAlign;
+        ctx.textBaseline = 'middle';
+        var freq = freqStart + step * i;
+        var index = Math.round(freq / (this.sampleRate / 2) * this.fftSamples);
+        var label = this.freqType(freq);
+        var units = this.unitType(freq);
+        var x = 16;
+        var yLabelOffset = 2;
+
+        if (i == 0) {
+          ctx.fillStyle = textColorUnit;
+          ctx.font = fontSizeUnit + ' ' + fontType;
+          ctx.fillText(units, x + 24, getMaxY + i - 10);
+          ctx.fillStyle = textColorFreq;
+          ctx.font = fontSizeFreq + ' ' + fontType;
+          ctx.fillText(label, x, getMaxY + i - 10);
+        } else {
+          ctx.fillStyle = textColorUnit;
+          ctx.font = fontSizeUnit + ' ' + fontType;
+          ctx.fillText(units, x + 24, getMaxY - i * 50 + yLabelOffset);
+          ctx.fillStyle = textColorFreq;
+          ctx.font = fontSizeFreq + ' ' + fontType;
+          ctx.fillText(label, x, getMaxY - i * 50 + yLabelOffset);
+        }
+      }
+    }
+  }, {
+    key: "updateScroll",
+    value: function updateScroll(e) {
+      if (this.wrapper) {
+        this.wrapper.scrollLeft = e.target.scrollLeft;
+      }
+    }
+  }, {
+    key: "resample",
+    value: function resample(oldMatrix) {
+      var columnsNumber = this.width;
+      var newMatrix = [];
+      var oldPiece = 1 / oldMatrix.length;
+      var newPiece = 1 / columnsNumber;
+      var i;
+
+      for (i = 0; i < columnsNumber; i++) {
+        var column = new Array(oldMatrix[0].length);
+        var j = void 0;
+
+        for (j = 0; j < oldMatrix.length; j++) {
+          var oldStart = j * oldPiece;
+          var oldEnd = oldStart + oldPiece;
+          var newStart = i * newPiece;
+          var newEnd = newStart + newPiece;
+          var overlap = oldEnd <= newStart || newEnd <= oldStart ? 0 : Math.min(Math.max(oldEnd, newStart), Math.max(newEnd, oldStart)) - Math.max(Math.min(oldEnd, newStart), Math.min(newEnd, oldStart));
+          var k = void 0;
+          /* eslint-disable max-depth */
+
+          if (overlap > 0) {
+            for (k = 0; k < oldMatrix[0].length; k++) {
+              if (column[k] == null) {
+                column[k] = 0;
+              }
+
+              column[k] += overlap / newPiece * oldMatrix[j][k];
+            }
+          }
+          /* eslint-enable max-depth */
+
+        }
+
+        var intColumn = new Uint8Array(oldMatrix[0].length);
+        var m = void 0;
+
+        for (m = 0; m < oldMatrix[0].length; m++) {
+          intColumn[m] = column[m];
+        }
+
+        newMatrix.push(intColumn);
+      }
+
+      return newMatrix;
+    }
+  }]);
+
+  return SpectrogramPlugin;
+}();
+
+exports.default = SpectrogramPlugin;
+module.exports = exports.default;
+
+/***/ })
+
+/******/ });
+});
+//# sourceMappingURL=wavesurfer.spectrogram.js.map
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.spectrogram.js.map
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.spectrogram.js.map	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.spectrogram.js.map	(revision 33546)
@@ -0,0 +1,1 @@
+{"version":3,"sources":["webpack://WaveSurfer.[name]/webpack/universalModuleDefinition","webpack://WaveSurfer.[name]/webpack/bootstrap","webpack://WaveSurfer.[name]/./src/plugin/spectrogram.js"],"names":["FFT","bufferSize","sampleRate","windowFunc","alpha","bandwidth","sinTable","Float32Array","cosTable","windowValues","reverseTable","Uint32Array","peakBand","peak","i","Math","abs","cos","PI","pow","E","undefined","sin","Error","limit","bit","calculateSpectrum","buffer","real","imag","bSi","sqrt","rval","ival","mag","spectrum","k","floor","log","LN2","length","halfSize","phaseShiftStepReal","phaseShiftStepImag","currentPhaseShiftReal","currentPhaseShiftImag","off","tr","ti","tmpReal","fftStep","N","SpectrogramPlugin","params","name","deferInit","staticProps","instance","ws","wavesurfer","util","frequenciesDataUrl","_onScroll","e","updateScroll","_onRender","render","_onWrapperClick","_wrapperClickHandler","_onReady","drawer","container","document","querySelector","width","pixelRatio","fftSamples","height","noverlap","createWrapper","createCanvas","wrapper","addEventListener","on","isReady","unAll","un","removeEventListener","parentNode","removeChild","prevSpectrogram","wsParams","createElement","labels","labelsEl","classList","add","style","left","position","zIndex","appendChild","loadLabels","display","userSelect","webkitUserSelect","fillParent","scrollParent","overflowX","overflowY","event","preventDefault","relX","offsetX","layerX","fireEvent","scrollWidth","canvas","spectrCc","getContext","updateCanvasStyle","loadFrequenciesData","getFrequencies","drawSpectrogram","round","frequenciesData","my","backend","getDuration","pixels","resample","heightFactor","numberOfChannels","j","colorValue","fillStyle","fillRect","callback","channelOne","getChannelData","bufferLength","frequencies","uniqueSamplesPerPx","max","fft","maxSlicesCount","currentOffset","segment","slice","array","Uint8Array","log10","push","url","ajax","data","JSON","parse","target","statusText","freq","toFixed","bgFill","fontSizeFreq","fontSizeUnit","fontType","textColorFreq","textColorUnit","textAlign","frequenciesHeight","getMaxY","labelIndex","freqStart","step","ac","ctx","fill","textBaseline","index","label","freqType","units","unitType","x","yLabelOffset","font","fillText","scrollLeft","oldMatrix","columnsNumber","newMatrix","oldPiece","newPiece","column","Array","oldStart","oldEnd","newStart","newEnd","overlap","min","intColumn","m"],"mappings":"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","file":"wavesurfer.spectrogram.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"spectrogram\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"spectrogram\"] = factory();\n\telse\n\t\troot[\"WaveSurfer\"] = root[\"WaveSurfer\"] || {}, root[\"WaveSurfer\"][\"spectrogram\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"localhost:8080/dist/plugin/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/plugin/spectrogram.js\");\n","/**\n * Calculate FFT - Based on https://github.com/corbanbrook/dsp.js\n */\n/* eslint-disable complexity, no-redeclare, no-var, one-var */\nconst FFT = function(bufferSize, sampleRate, windowFunc, alpha) {\n    this.bufferSize = bufferSize;\n    this.sampleRate = sampleRate;\n    this.bandwidth = (2 / bufferSize) * (sampleRate / 2);\n\n    this.sinTable = new Float32Array(bufferSize);\n    this.cosTable = new Float32Array(bufferSize);\n    this.windowValues = new Float32Array(bufferSize);\n    this.reverseTable = new Uint32Array(bufferSize);\n\n    this.peakBand = 0;\n    this.peak = 0;\n\n    var i;\n    switch (windowFunc) {\n        case 'bartlett':\n            for (i = 0; i < bufferSize; i++) {\n                this.windowValues[i] =\n                    (2 / (bufferSize - 1)) *\n                    ((bufferSize - 1) / 2 - Math.abs(i - (bufferSize - 1) / 2));\n            }\n            break;\n        case 'bartlettHann':\n            for (i = 0; i < bufferSize; i++) {\n                this.windowValues[i] =\n                    0.62 -\n                    0.48 * Math.abs(i / (bufferSize - 1) - 0.5) -\n                    0.38 * Math.cos((Math.PI * 2 * i) / (bufferSize - 1));\n            }\n            break;\n        case 'blackman':\n            alpha = alpha || 0.16;\n            for (i = 0; i < bufferSize; i++) {\n                this.windowValues[i] =\n                    (1 - alpha) / 2 -\n                    0.5 * Math.cos((Math.PI * 2 * i) / (bufferSize - 1)) +\n                    (alpha / 2) *\n                        Math.cos((4 * Math.PI * i) / (bufferSize - 1));\n            }\n            break;\n        case 'cosine':\n            for (i = 0; i < bufferSize; i++) {\n                this.windowValues[i] = Math.cos(\n                    (Math.PI * i) / (bufferSize - 1) - Math.PI / 2\n                );\n            }\n            break;\n        case 'gauss':\n            alpha = alpha || 0.25;\n            for (i = 0; i < bufferSize; i++) {\n                this.windowValues[i] = Math.pow(\n                    Math.E,\n                    -0.5 *\n                        Math.pow(\n                            (i - (bufferSize - 1) / 2) /\n                                ((alpha * (bufferSize - 1)) / 2),\n                            2\n                        )\n                );\n            }\n            break;\n        case 'hamming':\n            for (i = 0; i < bufferSize; i++) {\n                this.windowValues[i] =\n                    (0.54 - 0.46) *\n                    Math.cos((Math.PI * 2 * i) / (bufferSize - 1));\n            }\n            break;\n        case 'hann':\n        case undefined:\n            for (i = 0; i < bufferSize; i++) {\n                this.windowValues[i] =\n                    0.5 * (1 - Math.cos((Math.PI * 2 * i) / (bufferSize - 1)));\n            }\n            break;\n        case 'lanczoz':\n            for (i = 0; i < bufferSize; i++) {\n                this.windowValues[i] =\n                    Math.sin(Math.PI * ((2 * i) / (bufferSize - 1) - 1)) /\n                    (Math.PI * ((2 * i) / (bufferSize - 1) - 1));\n            }\n            break;\n        case 'rectangular':\n            for (i = 0; i < bufferSize; i++) {\n                this.windowValues[i] = 1;\n            }\n            break;\n        case 'triangular':\n            for (i = 0; i < bufferSize; i++) {\n                this.windowValues[i] =\n                    (2 / bufferSize) *\n                    (bufferSize / 2 - Math.abs(i - (bufferSize - 1) / 2));\n            }\n            break;\n        default:\n            throw Error(\"No such window function '\" + windowFunc + \"'\");\n    }\n\n    var limit = 1;\n    var bit = bufferSize >> 1;\n    var i;\n\n    while (limit < bufferSize) {\n        for (i = 0; i < limit; i++) {\n            this.reverseTable[i + limit] = this.reverseTable[i] + bit;\n        }\n\n        limit = limit << 1;\n        bit = bit >> 1;\n    }\n\n    for (i = 0; i < bufferSize; i++) {\n        this.sinTable[i] = Math.sin(-Math.PI / i);\n        this.cosTable[i] = Math.cos(-Math.PI / i);\n    }\n\n    this.calculateSpectrum = function(buffer) {\n        // Locally scope variables for speed up\n        var bufferSize = this.bufferSize,\n            cosTable = this.cosTable,\n            sinTable = this.sinTable,\n            reverseTable = this.reverseTable,\n            real = new Float32Array(bufferSize),\n            imag = new Float32Array(bufferSize),\n            bSi = 2 / this.bufferSize,\n            sqrt = Math.sqrt,\n            rval,\n            ival,\n            mag,\n            spectrum = new Float32Array(bufferSize / 2);\n\n        var k = Math.floor(Math.log(bufferSize) / Math.LN2);\n\n        if (Math.pow(2, k) !== bufferSize) {\n            throw 'Invalid buffer size, must be a power of 2.';\n        }\n        if (bufferSize !== buffer.length) {\n            throw 'Supplied buffer is not the same size as defined FFT. FFT Size: ' +\n                bufferSize +\n                ' Buffer Size: ' +\n                buffer.length;\n        }\n\n        var halfSize = 1,\n            phaseShiftStepReal,\n            phaseShiftStepImag,\n            currentPhaseShiftReal,\n            currentPhaseShiftImag,\n            off,\n            tr,\n            ti,\n            tmpReal;\n\n        for (var i = 0; i < bufferSize; i++) {\n            real[i] =\n                buffer[reverseTable[i]] * this.windowValues[reverseTable[i]];\n            imag[i] = 0;\n        }\n\n        while (halfSize < bufferSize) {\n            phaseShiftStepReal = cosTable[halfSize];\n            phaseShiftStepImag = sinTable[halfSize];\n\n            currentPhaseShiftReal = 1;\n            currentPhaseShiftImag = 0;\n\n            for (var fftStep = 0; fftStep < halfSize; fftStep++) {\n                var i = fftStep;\n\n                while (i < bufferSize) {\n                    off = i + halfSize;\n                    tr =\n                        currentPhaseShiftReal * real[off] -\n                        currentPhaseShiftImag * imag[off];\n                    ti =\n                        currentPhaseShiftReal * imag[off] +\n                        currentPhaseShiftImag * real[off];\n\n                    real[off] = real[i] - tr;\n                    imag[off] = imag[i] - ti;\n                    real[i] += tr;\n                    imag[i] += ti;\n\n                    i += halfSize << 1;\n                }\n\n                tmpReal = currentPhaseShiftReal;\n                currentPhaseShiftReal =\n                    tmpReal * phaseShiftStepReal -\n                    currentPhaseShiftImag * phaseShiftStepImag;\n                currentPhaseShiftImag =\n                    tmpReal * phaseShiftStepImag +\n                    currentPhaseShiftImag * phaseShiftStepReal;\n            }\n\n            halfSize = halfSize << 1;\n        }\n\n        for (var i = 0, N = bufferSize / 2; i < N; i++) {\n            rval = real[i];\n            ival = imag[i];\n            mag = bSi * sqrt(rval * rval + ival * ival);\n\n            if (mag > this.peak) {\n                this.peakBand = i;\n                this.peak = mag;\n            }\n            spectrum[i] = mag;\n        }\n        return spectrum;\n    };\n};\n/* eslint-enable complexity, no-redeclare, no-var, one-var */\n\n/**\n * @typedef {Object} SpectrogramPluginParams\n * @property {string|HTMLElement} container Selector of element or element in\n * which to render\n * @property {number} fftSamples=512 Number of samples to fetch to FFT. Must be\n * a power of 2.\n * @property {boolean} labels Set to true to display frequency labels.\n * @property {number} noverlap Size of the overlapping window. Must be <\n * fftSamples. Auto deduced from canvas size by default.\n * @property {string} windowFunc='hann' The window function to be used. One of\n * these: `'bartlett'`, `'bartlettHann'`, `'blackman'`, `'cosine'`, `'gauss'`,\n * `'hamming'`, `'hann'`, `'lanczoz'`, `'rectangular'`, `'triangular'`\n * @property {?number} alpha Some window functions have this extra value.\n * (Between 0 and 1)\n * @property {number} pixelRatio=wavesurfer.params.pixelRatio to control the\n * size of the spectrogram in relation with its canvas. 1 = Draw on the whole\n * canvas. 2 = Draw on a quarter (1/2 the length and 1/2 the width)\n * @property {?boolean} deferInit Set to true to manually call\n * `initPlugin('spectrogram')`\n */\n\n/**\n * Render a spectrogram visualisation of the audio.\n *\n * @implements {PluginClass}\n * @extends {Observer}\n * @example\n * // es6\n * import SpectrogramPlugin from 'wavesurfer.spectrogram.js';\n *\n * // commonjs\n * var SpectrogramPlugin = require('wavesurfer.spectrogram.js');\n *\n * // if you are using <script> tags\n * var SpectrogramPlugin = window.WaveSurfer.spectrogram;\n *\n * // ... initialising wavesurfer with the plugin\n * var wavesurfer = WaveSurfer.create({\n *   // wavesurfer options ...\n *   plugins: [\n *     SpectrogramPlugin.create({\n *       // plugin options ...\n *     })\n *   ]\n * });\n */\nexport default class SpectrogramPlugin {\n    /**\n     * Spectrogram plugin definition factory\n     *\n     * This function must be used to create a plugin definition which can be\n     * used by wavesurfer to correctly instantiate the plugin.\n     *\n     * @param  {SpectrogramPluginParams} params Parameters used to initialise the plugin\n     * @return {PluginDefinition} An object representing the plugin.\n     */\n    static create(params) {\n        return {\n            name: 'spectrogram',\n            deferInit: params && params.deferInit ? params.deferInit : false,\n            params: params,\n            staticProps: {\n                FFT: FFT\n            },\n            instance: SpectrogramPlugin\n        };\n    }\n\n    constructor(params, ws) {\n        this.params = params;\n        this.wavesurfer = ws;\n        this.util = ws.util;\n\n        this.frequenciesDataUrl = params.frequenciesDataUrl;\n        this._onScroll = e => {\n            this.updateScroll(e);\n        };\n        this._onRender = () => {\n            this.render();\n        };\n        this._onWrapperClick = e => {\n            this._wrapperClickHandler(e);\n        };\n        this._onReady = () => {\n            const drawer = (this.drawer = ws.drawer);\n\n            this.container =\n                'string' == typeof params.container\n                    ? document.querySelector(params.container)\n                    : params.container;\n\n            if (!this.container) {\n                throw Error('No container for WaveSurfer spectrogram');\n            }\n\n            this.width = drawer.width;\n            this.pixelRatio = this.params.pixelRatio || ws.params.pixelRatio;\n            this.fftSamples =\n                this.params.fftSamples || ws.params.fftSamples || 512;\n            this.height = this.fftSamples / 2;\n            this.noverlap = params.noverlap;\n            this.windowFunc = params.windowFunc;\n            this.alpha = params.alpha;\n\n            this.createWrapper();\n            this.createCanvas();\n            this.render();\n\n            drawer.wrapper.addEventListener('scroll', this._onScroll);\n            ws.on('redraw', this._onRender);\n        };\n    }\n\n    init() {\n        // Check if wavesurfer is ready\n        if (this.wavesurfer.isReady) {\n            this._onReady();\n        }\n\n        this.wavesurfer.on('ready', this._onReady);\n    }\n\n    destroy() {\n        this.unAll();\n        this.wavesurfer.un('ready', this._onReady);\n        this.wavesurfer.un('redraw', this._onRender);\n        this.drawer.wrapper.removeEventListener('scroll', this._onScroll);\n        this.wavesurfer = null;\n        this.util = null;\n        this.params = null;\n        if (this.wrapper) {\n            this.wrapper.removeEventListener('click', this._onWrapperClick);\n            this.wrapper.parentNode.removeChild(this.wrapper);\n            this.wrapper = null;\n        }\n    }\n\n    createWrapper() {\n        const prevSpectrogram = this.container.querySelector('spectrogram');\n        if (prevSpectrogram) {\n            this.container.removeChild(prevSpectrogram);\n        }\n        const wsParams = this.wavesurfer.params;\n        this.wrapper = document.createElement('spectrogram');\n        // if labels are active\n        if (this.params.labels) {\n            const labelsEl = (this.labelsEl = document.createElement('canvas'));\n            labelsEl.classList.add('spec-labels');\n            this.drawer.style(labelsEl, {\n                left: 0,\n                position: 'absolute',\n                zIndex: 9,\n                height: `${this.height / this.pixelRatio}px`,\n                width: `${55 / this.pixelRatio}px`\n            });\n            this.wrapper.appendChild(labelsEl);\n            this.loadLabels(\n                'rgba(68,68,68,0.5)',\n                '12px',\n                '10px',\n                '',\n                '#fff',\n                '#f7f7f7',\n                'center',\n                '#specLabels'\n            );\n        }\n\n        this.drawer.style(this.wrapper, {\n            display: 'block',\n            position: 'relative',\n            userSelect: 'none',\n            webkitUserSelect: 'none',\n            height: `${this.height / this.pixelRatio}px`\n        });\n\n        if (wsParams.fillParent || wsParams.scrollParent) {\n            this.drawer.style(this.wrapper, {\n                width: '100%',\n                overflowX: 'hidden',\n                overflowY: 'hidden'\n            });\n        }\n        this.container.appendChild(this.wrapper);\n\n        this.wrapper.addEventListener('click', this._onWrapperClick);\n    }\n\n    _wrapperClickHandler(event) {\n        event.preventDefault();\n\n        const relX = 'offsetX' in event ? event.offsetX : event.layerX;\n        this.fireEvent('click', relX / this.scrollWidth || 0);\n    }\n\n    createCanvas() {\n        const canvas = (this.canvas = this.wrapper.appendChild(\n            document.createElement('canvas')\n        ));\n\n        this.spectrCc = canvas.getContext('2d');\n\n        this.util.style(canvas, {\n            position: 'absolute',\n            zIndex: 4\n        });\n    }\n\n    render() {\n        this.updateCanvasStyle();\n\n        if (this.frequenciesDataUrl) {\n            this.loadFrequenciesData(this.frequenciesDataUrl);\n        } else {\n            this.getFrequencies(this.drawSpectrogram);\n        }\n    }\n\n    updateCanvasStyle() {\n        const width = Math.round(this.width / this.pixelRatio) + 'px';\n        this.canvas.width = this.width;\n        this.canvas.height = this.height;\n        this.canvas.style.width = width;\n    }\n\n    drawSpectrogram(frequenciesData, my) {\n        const spectrCc = my.spectrCc;\n        const length = my.wavesurfer.backend.getDuration();\n        const height = my.height;\n        const pixels = my.resample(frequenciesData);\n        const heightFactor = my.buffer ? 2 / my.buffer.numberOfChannels : 1;\n        let i;\n        let j;\n\n        for (i = 0; i < pixels.length; i++) {\n            for (j = 0; j < pixels[i].length; j++) {\n                const colorValue = 255 - pixels[i][j];\n                my.spectrCc.fillStyle =\n                    'rgb(' +\n                    colorValue +\n                    ', ' +\n                    colorValue +\n                    ', ' +\n                    colorValue +\n                    ')';\n                my.spectrCc.fillRect(\n                    i,\n                    height - j * heightFactor,\n                    1,\n                    heightFactor\n                );\n            }\n        }\n    }\n\n    getFrequencies(callback) {\n        const fftSamples = this.fftSamples;\n        const buffer = (this.buffer = this.wavesurfer.backend.buffer);\n        const channelOne = buffer.getChannelData(0);\n        const bufferLength = buffer.length;\n        const sampleRate = buffer.sampleRate;\n        const frequencies = [];\n\n        if (!buffer) {\n            this.fireEvent('error', 'Web Audio buffer is not available');\n            return;\n        }\n\n        let noverlap = this.noverlap;\n        if (!noverlap) {\n            const uniqueSamplesPerPx = buffer.length / this.canvas.width;\n            noverlap = Math.max(0, Math.round(fftSamples - uniqueSamplesPerPx));\n        }\n\n        const fft = new FFT(\n            fftSamples,\n            sampleRate,\n            this.windowFunc,\n            this.alpha\n        );\n        const maxSlicesCount = Math.floor(\n            bufferLength / (fftSamples - noverlap)\n        );\n        let currentOffset = 0;\n\n        while (currentOffset + fftSamples < channelOne.length) {\n            const segment = channelOne.slice(\n                currentOffset,\n                currentOffset + fftSamples\n            );\n            const spectrum = fft.calculateSpectrum(segment);\n            const array = new Uint8Array(fftSamples / 2);\n            let j;\n            for (j = 0; j < fftSamples / 2; j++) {\n                array[j] = Math.max(-255, Math.log10(spectrum[j]) * 45);\n            }\n            frequencies.push(array);\n            currentOffset += fftSamples - noverlap;\n        }\n        callback(frequencies, this);\n    }\n\n    loadFrequenciesData(url) {\n        const ajax = this.util.ajax({ url: url });\n\n        ajax.on('success', data =>\n            this.drawSpectrogram(JSON.parse(data), this)\n        );\n        ajax.on('error', e =>\n            this.fireEvent('error', 'XHR error: ' + e.target.statusText)\n        );\n\n        return ajax;\n    }\n\n    freqType(freq) {\n        return freq >= 1000 ? (freq / 1000).toFixed(1) : Math.round(freq);\n    }\n\n    unitType(freq) {\n        return freq >= 1000 ? 'KHz' : 'Hz';\n    }\n\n    loadLabels(\n        bgFill,\n        fontSizeFreq,\n        fontSizeUnit,\n        fontType,\n        textColorFreq,\n        textColorUnit,\n        textAlign,\n        container\n    ) {\n        const frequenciesHeight = this.height;\n        bgFill = bgFill || 'rgba(68,68,68,0)';\n        fontSizeFreq = fontSizeFreq || '12px';\n        fontSizeUnit = fontSizeUnit || '10px';\n        fontType = fontType || 'Helvetica';\n        textColorFreq = textColorFreq || '#fff';\n        textColorUnit = textColorUnit || '#fff';\n        textAlign = textAlign || 'center';\n        container = container || '#specLabels';\n        const getMaxY = frequenciesHeight || 512;\n        const labelIndex = 5 * (getMaxY / 256);\n        const freqStart = 0;\n        const step =\n            (this.wavesurfer.backend.ac.sampleRate / 2 - freqStart) /\n            labelIndex;\n\n        const ctx = this.labelsEl.getContext('2d');\n        this.labelsEl.height = this.height;\n        this.labelsEl.width = 55;\n\n        ctx.fillStyle = bgFill;\n        ctx.fillRect(0, 0, 55, getMaxY);\n        ctx.fill();\n        let i;\n\n        for (i = 0; i <= labelIndex; i++) {\n            ctx.textAlign = textAlign;\n            ctx.textBaseline = 'middle';\n\n            const freq = freqStart + step * i;\n            const index = Math.round(\n                (freq / (this.sampleRate / 2)) * this.fftSamples\n            );\n            const label = this.freqType(freq);\n            const units = this.unitType(freq);\n            const x = 16;\n            const yLabelOffset = 2;\n\n            if (i == 0) {\n                ctx.fillStyle = textColorUnit;\n                ctx.font = fontSizeUnit + ' ' + fontType;\n                ctx.fillText(units, x + 24, getMaxY + i - 10);\n                ctx.fillStyle = textColorFreq;\n                ctx.font = fontSizeFreq + ' ' + fontType;\n                ctx.fillText(label, x, getMaxY + i - 10);\n            } else {\n                ctx.fillStyle = textColorUnit;\n                ctx.font = fontSizeUnit + ' ' + fontType;\n                ctx.fillText(units, x + 24, getMaxY - i * 50 + yLabelOffset);\n                ctx.fillStyle = textColorFreq;\n                ctx.font = fontSizeFreq + ' ' + fontType;\n                ctx.fillText(label, x, getMaxY - i * 50 + yLabelOffset);\n            }\n        }\n    }\n\n    updateScroll(e) {\n        if (this.wrapper) {\n            this.wrapper.scrollLeft = e.target.scrollLeft;\n        }\n    }\n\n    resample(oldMatrix) {\n        const columnsNumber = this.width;\n        const newMatrix = [];\n\n        const oldPiece = 1 / oldMatrix.length;\n        const newPiece = 1 / columnsNumber;\n        let i;\n\n        for (i = 0; i < columnsNumber; i++) {\n            const column = new Array(oldMatrix[0].length);\n            let j;\n\n            for (j = 0; j < oldMatrix.length; j++) {\n                const oldStart = j * oldPiece;\n                const oldEnd = oldStart + oldPiece;\n                const newStart = i * newPiece;\n                const newEnd = newStart + newPiece;\n\n                const overlap =\n                    oldEnd <= newStart || newEnd <= oldStart\n                        ? 0\n                        : Math.min(\n                              Math.max(oldEnd, newStart),\n                              Math.max(newEnd, oldStart)\n                          ) -\n                          Math.max(\n                              Math.min(oldEnd, newStart),\n                              Math.min(newEnd, oldStart)\n                          );\n                let k;\n                /* eslint-disable max-depth */\n                if (overlap > 0) {\n                    for (k = 0; k < oldMatrix[0].length; k++) {\n                        if (column[k] == null) {\n                            column[k] = 0;\n                        }\n                        column[k] += (overlap / newPiece) * oldMatrix[j][k];\n                    }\n                }\n                /* eslint-enable max-depth */\n            }\n\n            const intColumn = new Uint8Array(oldMatrix[0].length);\n            let m;\n\n            for (m = 0; m < oldMatrix[0].length; m++) {\n                intColumn[m] = column[m];\n            }\n\n            newMatrix.push(intColumn);\n        }\n\n        return newMatrix;\n    }\n}\n"],"sourceRoot":""}
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.spectrogram.min.js
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.spectrogram.min.js	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.spectrogram.min.js	(revision 33546)
@@ -0,0 +1,2 @@
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("spectrogram",[],t):"object"==typeof exports?exports.spectrogram=t():(e.WaveSurfer=e.WaveSurfer||{},e.WaveSurfer.spectrogram=t())}(window,(function(){return function(e){var t={};function r(a){if(t[a])return t[a].exports;var i=t[a]={i:a,l:!1,exports:{}};return e[a].call(i.exports,i,i.exports,r),i.l=!0,i.exports}return r.m=e,r.c=t,r.d=function(e,t,a){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:a})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var a=Object.create(null);if(r.r(a),Object.defineProperty(a,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)r.d(a,i,function(t){return e[t]}.bind(null,i));return a},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="localhost:8080/dist/plugin/",r(r.s=3)}({3:function(e,t,r){"use strict";function a(e,t){for(var r=0;r<t.length;r++){var a=t[r];a.enumerable=a.enumerable||!1,a.configurable=!0,"value"in a&&(a.writable=!0),Object.defineProperty(e,a.key,a)}}function i(e,t,r){return t&&a(e.prototype,t),r&&a(e,r),e}Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n=function(e,t,r,a){switch(this.bufferSize=e,this.sampleRate=t,this.bandwidth=2/e*(t/2),this.sinTable=new Float32Array(e),this.cosTable=new Float32Array(e),this.windowValues=new Float32Array(e),this.reverseTable=new Uint32Array(e),this.peakBand=0,this.peak=0,r){case"bartlett":for(i=0;i<e;i++)this.windowValues[i]=2/(e-1)*((e-1)/2-Math.abs(i-(e-1)/2));break;case"bartlettHann":for(i=0;i<e;i++)this.windowValues[i]=.62-.48*Math.abs(i/(e-1)-.5)-.38*Math.cos(2*Math.PI*i/(e-1));break;case"blackman":for(a=a||.16,i=0;i<e;i++)this.windowValues[i]=(1-a)/2-.5*Math.cos(2*Math.PI*i/(e-1))+a/2*Math.cos(4*Math.PI*i/(e-1));break;case"cosine":for(i=0;i<e;i++)this.windowValues[i]=Math.cos(Math.PI*i/(e-1)-Math.PI/2);break;case"gauss":for(a=a||.25,i=0;i<e;i++)this.windowValues[i]=Math.pow(Math.E,-.5*Math.pow((i-(e-1)/2)/(a*(e-1)/2),2));break;case"hamming":for(i=0;i<e;i++)this.windowValues[i]=(.54-.46)*Math.cos(2*Math.PI*i/(e-1));break;case"hann":case void 0:for(i=0;i<e;i++)this.windowValues[i]=.5*(1-Math.cos(2*Math.PI*i/(e-1)));break;case"lanczoz":for(i=0;i<e;i++)this.windowValues[i]=Math.sin(Math.PI*(2*i/(e-1)-1))/(Math.PI*(2*i/(e-1)-1));break;case"rectangular":for(i=0;i<e;i++)this.windowValues[i]=1;break;case"triangular":for(i=0;i<e;i++)this.windowValues[i]=2/e*(e/2-Math.abs(i-(e-1)/2));break;default:throw Error("No such window function '"+r+"'")}for(var i,n=1,s=e>>1;n<e;){for(i=0;i<n;i++)this.reverseTable[i+n]=this.reverseTable[i]+s;n<<=1,s>>=1}for(i=0;i<e;i++)this.sinTable[i]=Math.sin(-Math.PI/i),this.cosTable[i]=Math.cos(-Math.PI/i);this.calculateSpectrum=function(e){var t,r,a,i=this.bufferSize,n=this.cosTable,s=this.sinTable,o=this.reverseTable,l=new Float32Array(i),h=new Float32Array(i),f=2/this.bufferSize,u=Math.sqrt,c=new Float32Array(i/2),p=Math.floor(Math.log(i)/Math.LN2);if(Math.pow(2,p)!==i)throw"Invalid buffer size, must be a power of 2.";if(i!==e.length)throw"Supplied buffer is not the same size as defined FFT. FFT Size: "+i+" Buffer Size: "+e.length;for(var d,v,w,b,y,m,g,M,k=1,S=0;S<i;S++)l[S]=e[o[S]]*this.windowValues[o[S]],h[S]=0;for(;k<i;){d=n[k],v=s[k],w=1,b=0;for(var x=0;x<k;x++){for(S=x;S<i;)m=w*l[y=S+k]-b*h[y],g=w*h[y]+b*l[y],l[y]=l[S]-m,h[y]=h[S]-g,l[S]+=m,h[S]+=g,S+=k<<1;w=(M=w)*d-b*v,b=M*v+b*d}k<<=1}S=0;for(var T=i/2;S<T;S++)(a=f*u((t=l[S])*t+(r=h[S])*r))>this.peak&&(this.peakBand=S,this.peak=a),c[S]=a;return c}},s=function(){function e(t,r){var a=this;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.params=t,this.wavesurfer=r,this.util=r.util,this.frequenciesDataUrl=t.frequenciesDataUrl,this._onScroll=function(e){a.updateScroll(e)},this._onRender=function(){a.render()},this._onWrapperClick=function(e){a._wrapperClickHandler(e)},this._onReady=function(){var e=a.drawer=r.drawer;if(a.container="string"==typeof t.container?document.querySelector(t.container):t.container,!a.container)throw Error("No container for WaveSurfer spectrogram");a.width=e.width,a.pixelRatio=a.params.pixelRatio||r.params.pixelRatio,a.fftSamples=a.params.fftSamples||r.params.fftSamples||512,a.height=a.fftSamples/2,a.noverlap=t.noverlap,a.windowFunc=t.windowFunc,a.alpha=t.alpha,a.createWrapper(),a.createCanvas(),a.render(),e.wrapper.addEventListener("scroll",a._onScroll),r.on("redraw",a._onRender)}}return i(e,null,[{key:"create",value:function(t){return{name:"spectrogram",deferInit:!(!t||!t.deferInit)&&t.deferInit,params:t,staticProps:{FFT:n},instance:e}}}]),i(e,[{key:"init",value:function(){this.wavesurfer.isReady&&this._onReady(),this.wavesurfer.on("ready",this._onReady)}},{key:"destroy",value:function(){this.unAll(),this.wavesurfer.un("ready",this._onReady),this.wavesurfer.un("redraw",this._onRender),this.drawer.wrapper.removeEventListener("scroll",this._onScroll),this.wavesurfer=null,this.util=null,this.params=null,this.wrapper&&(this.wrapper.removeEventListener("click",this._onWrapperClick),this.wrapper.parentNode.removeChild(this.wrapper),this.wrapper=null)}},{key:"createWrapper",value:function(){var e=this.container.querySelector("spectrogram");e&&this.container.removeChild(e);var t=this.wavesurfer.params;if(this.wrapper=document.createElement("spectrogram"),this.params.labels){var r=this.labelsEl=document.createElement("canvas");r.classList.add("spec-labels"),this.drawer.style(r,{left:0,position:"absolute",zIndex:9,height:"".concat(this.height/this.pixelRatio,"px"),width:"".concat(55/this.pixelRatio,"px")}),this.wrapper.appendChild(r),this.loadLabels("rgba(68,68,68,0.5)","12px","10px","","#fff","#f7f7f7","center","#specLabels")}this.drawer.style(this.wrapper,{display:"block",position:"relative",userSelect:"none",webkitUserSelect:"none",height:"".concat(this.height/this.pixelRatio,"px")}),(t.fillParent||t.scrollParent)&&this.drawer.style(this.wrapper,{width:"100%",overflowX:"hidden",overflowY:"hidden"}),this.container.appendChild(this.wrapper),this.wrapper.addEventListener("click",this._onWrapperClick)}},{key:"_wrapperClickHandler",value:function(e){e.preventDefault();var t="offsetX"in e?e.offsetX:e.layerX;this.fireEvent("click",t/this.scrollWidth||0)}},{key:"createCanvas",value:function(){var e=this.canvas=this.wrapper.appendChild(document.createElement("canvas"));this.spectrCc=e.getContext("2d"),this.util.style(e,{position:"absolute",zIndex:4})}},{key:"render",value:function(){this.updateCanvasStyle(),this.frequenciesDataUrl?this.loadFrequenciesData(this.frequenciesDataUrl):this.getFrequencies(this.drawSpectrogram)}},{key:"updateCanvasStyle",value:function(){var e=Math.round(this.width/this.pixelRatio)+"px";this.canvas.width=this.width,this.canvas.height=this.height,this.canvas.style.width=e}},{key:"drawSpectrogram",value:function(e,t){t.spectrCc,t.wavesurfer.backend.getDuration();var r,a,i=t.height,n=t.resample(e),s=t.buffer?2/t.buffer.numberOfChannels:1;for(r=0;r<n.length;r++)for(a=0;a<n[r].length;a++){var o=255-n[r][a];t.spectrCc.fillStyle="rgb("+o+", "+o+", "+o+")",t.spectrCc.fillRect(r,i-a*s,1,s)}}},{key:"getFrequencies",value:function(e){var t=this.fftSamples,r=this.buffer=this.wavesurfer.backend.buffer,a=r.getChannelData(0),i=r.length,s=r.sampleRate,o=[];if(r){var l=this.noverlap;if(!l){var h=r.length/this.canvas.width;l=Math.max(0,Math.round(t-h))}for(var f=new n(t,s,this.windowFunc,this.alpha),u=(Math.floor(i/(t-l)),0);u+t<a.length;){var c=a.slice(u,u+t),p=f.calculateSpectrum(c),d=new Uint8Array(t/2),v=void 0;for(v=0;v<t/2;v++)d[v]=Math.max(-255,45*Math.log10(p[v]));o.push(d),u+=t-l}e(o,this)}else this.fireEvent("error","Web Audio buffer is not available")}},{key:"loadFrequenciesData",value:function(e){var t=this,r=this.util.ajax({url:e});return r.on("success",(function(e){return t.drawSpectrogram(JSON.parse(e),t)})),r.on("error",(function(e){return t.fireEvent("error","XHR error: "+e.target.statusText)})),r}},{key:"freqType",value:function(e){return e>=1e3?(e/1e3).toFixed(1):Math.round(e)}},{key:"unitType",value:function(e){return e>=1e3?"KHz":"Hz"}},{key:"loadLabels",value:function(e,t,r,a,i,n,s,o){e=e||"rgba(68,68,68,0)",t=t||"12px",r=r||"10px",a=a||"Helvetica",i=i||"#fff",n=n||"#fff",s=s||"center",o=o||"#specLabels";var l,h=this.height||512,f=h/256*5,u=(this.wavesurfer.backend.ac.sampleRate/2-0)/f,c=this.labelsEl.getContext("2d");for(this.labelsEl.height=this.height,this.labelsEl.width=55,c.fillStyle=e,c.fillRect(0,0,55,h),c.fill(),l=0;l<=f;l++){c.textAlign=s,c.textBaseline="middle";var p=0+u*l,d=(Math.round(p/(this.sampleRate/2)*this.fftSamples),this.freqType(p)),v=this.unitType(p);0==l?(c.fillStyle=n,c.font=r+" "+a,c.fillText(v,40,h+l-10),c.fillStyle=i,c.font=t+" "+a,c.fillText(d,16,h+l-10)):(c.fillStyle=n,c.font=r+" "+a,c.fillText(v,40,h-50*l+2),c.fillStyle=i,c.font=t+" "+a,c.fillText(d,16,h-50*l+2))}}},{key:"updateScroll",value:function(e){this.wrapper&&(this.wrapper.scrollLeft=e.target.scrollLeft)}},{key:"resample",value:function(e){var t,r=this.width,a=[],i=1/e.length,n=1/r;for(t=0;t<r;t++){var s=new Array(e[0].length),o=void 0;for(o=0;o<e.length;o++){var l=o*i,h=l+i,f=t*n,u=f+n,c=h<=f||u<=l?0:Math.min(Math.max(h,f),Math.max(u,l))-Math.max(Math.min(h,f),Math.min(u,l)),p=void 0;if(c>0)for(p=0;p<e[0].length;p++)null==s[p]&&(s[p]=0),s[p]+=c/n*e[o][p]}var d=new Uint8Array(e[0].length),v=void 0;for(v=0;v<e[0].length;v++)d[v]=s[v];a.push(d)}return a}}]),e}();t.default=s,e.exports=t.default}})}));
+//# sourceMappingURL=wavesurfer.spectrogram.min.js.map
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.spectrogram.min.js.map
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.spectrogram.min.js.map	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.spectrogram.min.js.map	(revision 33546)
@@ -0,0 +1,1 @@
+{"version":3,"sources":["webpack://WaveSurfer.[name]/webpack/universalModuleDefinition","webpack://WaveSurfer.[name]/webpack/bootstrap","webpack://WaveSurfer.[name]/./src/plugin/spectrogram.js"],"names":["root","factory","exports","module","define","amd","window","installedModules","__webpack_require__","moduleId","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","FFT","bufferSize","sampleRate","windowFunc","alpha","this","bandwidth","sinTable","Float32Array","cosTable","windowValues","reverseTable","Uint32Array","peakBand","peak","Math","abs","cos","PI","pow","E","undefined","sin","Error","limit","bit","calculateSpectrum","buffer","rval","ival","mag","real","imag","bSi","sqrt","spectrum","k","floor","log","LN2","length","phaseShiftStepReal","phaseShiftStepImag","currentPhaseShiftReal","currentPhaseShiftImag","off","tr","ti","tmpReal","halfSize","fftStep","N","SpectrogramPlugin","params","ws","wavesurfer","util","frequenciesDataUrl","_onScroll","e","updateScroll","_onRender","render","_onWrapperClick","_wrapperClickHandler","_onReady","drawer","container","document","querySelector","width","pixelRatio","fftSamples","height","noverlap","createWrapper","createCanvas","wrapper","addEventListener","on","deferInit","staticProps","instance","isReady","unAll","un","removeEventListener","parentNode","removeChild","prevSpectrogram","wsParams","createElement","labels","labelsEl","classList","add","style","left","position","zIndex","appendChild","loadLabels","display","userSelect","webkitUserSelect","fillParent","scrollParent","overflowX","overflowY","event","preventDefault","relX","offsetX","layerX","fireEvent","scrollWidth","canvas","spectrCc","getContext","updateCanvasStyle","loadFrequenciesData","getFrequencies","drawSpectrogram","round","frequenciesData","my","backend","getDuration","j","pixels","resample","heightFactor","numberOfChannels","colorValue","fillStyle","fillRect","callback","channelOne","getChannelData","bufferLength","frequencies","uniqueSamplesPerPx","max","fft","currentOffset","segment","slice","array","Uint8Array","log10","push","url","ajax","data","JSON","parse","target","statusText","freq","toFixed","bgFill","fontSizeFreq","fontSizeUnit","fontType","textColorFreq","textColorUnit","textAlign","getMaxY","labelIndex","step","ac","ctx","fill","textBaseline","label","freqType","units","unitType","font","fillText","x","scrollLeft","oldMatrix","columnsNumber","newMatrix","oldPiece","newPiece","column","Array","oldStart","oldEnd","newStart","newEnd","overlap","min","intColumn"],"mappings":"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","file":"wavesurfer.spectrogram.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"spectrogram\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"spectrogram\"] = factory();\n\telse\n\t\troot[\"WaveSurfer\"] = root[\"WaveSurfer\"] || {}, root[\"WaveSurfer\"][\"spectrogram\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"localhost:8080/dist/plugin/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 3);\n","/**\n * Calculate FFT - Based on https://github.com/corbanbrook/dsp.js\n */\n/* eslint-disable complexity, no-redeclare, no-var, one-var */\nconst FFT = function(bufferSize, sampleRate, windowFunc, alpha) {\n    this.bufferSize = bufferSize;\n    this.sampleRate = sampleRate;\n    this.bandwidth = (2 / bufferSize) * (sampleRate / 2);\n\n    this.sinTable = new Float32Array(bufferSize);\n    this.cosTable = new Float32Array(bufferSize);\n    this.windowValues = new Float32Array(bufferSize);\n    this.reverseTable = new Uint32Array(bufferSize);\n\n    this.peakBand = 0;\n    this.peak = 0;\n\n    var i;\n    switch (windowFunc) {\n        case 'bartlett':\n            for (i = 0; i < bufferSize; i++) {\n                this.windowValues[i] =\n                    (2 / (bufferSize - 1)) *\n                    ((bufferSize - 1) / 2 - Math.abs(i - (bufferSize - 1) / 2));\n            }\n            break;\n        case 'bartlettHann':\n            for (i = 0; i < bufferSize; i++) {\n                this.windowValues[i] =\n                    0.62 -\n                    0.48 * Math.abs(i / (bufferSize - 1) - 0.5) -\n                    0.38 * Math.cos((Math.PI * 2 * i) / (bufferSize - 1));\n            }\n            break;\n        case 'blackman':\n            alpha = alpha || 0.16;\n            for (i = 0; i < bufferSize; i++) {\n                this.windowValues[i] =\n                    (1 - alpha) / 2 -\n                    0.5 * Math.cos((Math.PI * 2 * i) / (bufferSize - 1)) +\n                    (alpha / 2) *\n                        Math.cos((4 * Math.PI * i) / (bufferSize - 1));\n            }\n            break;\n        case 'cosine':\n            for (i = 0; i < bufferSize; i++) {\n                this.windowValues[i] = Math.cos(\n                    (Math.PI * i) / (bufferSize - 1) - Math.PI / 2\n                );\n            }\n            break;\n        case 'gauss':\n            alpha = alpha || 0.25;\n            for (i = 0; i < bufferSize; i++) {\n                this.windowValues[i] = Math.pow(\n                    Math.E,\n                    -0.5 *\n                        Math.pow(\n                            (i - (bufferSize - 1) / 2) /\n                                ((alpha * (bufferSize - 1)) / 2),\n                            2\n                        )\n                );\n            }\n            break;\n        case 'hamming':\n            for (i = 0; i < bufferSize; i++) {\n                this.windowValues[i] =\n                    (0.54 - 0.46) *\n                    Math.cos((Math.PI * 2 * i) / (bufferSize - 1));\n            }\n            break;\n        case 'hann':\n        case undefined:\n            for (i = 0; i < bufferSize; i++) {\n                this.windowValues[i] =\n                    0.5 * (1 - Math.cos((Math.PI * 2 * i) / (bufferSize - 1)));\n            }\n            break;\n        case 'lanczoz':\n            for (i = 0; i < bufferSize; i++) {\n                this.windowValues[i] =\n                    Math.sin(Math.PI * ((2 * i) / (bufferSize - 1) - 1)) /\n                    (Math.PI * ((2 * i) / (bufferSize - 1) - 1));\n            }\n            break;\n        case 'rectangular':\n            for (i = 0; i < bufferSize; i++) {\n                this.windowValues[i] = 1;\n            }\n            break;\n        case 'triangular':\n            for (i = 0; i < bufferSize; i++) {\n                this.windowValues[i] =\n                    (2 / bufferSize) *\n                    (bufferSize / 2 - Math.abs(i - (bufferSize - 1) / 2));\n            }\n            break;\n        default:\n            throw Error(\"No such window function '\" + windowFunc + \"'\");\n    }\n\n    var limit = 1;\n    var bit = bufferSize >> 1;\n    var i;\n\n    while (limit < bufferSize) {\n        for (i = 0; i < limit; i++) {\n            this.reverseTable[i + limit] = this.reverseTable[i] + bit;\n        }\n\n        limit = limit << 1;\n        bit = bit >> 1;\n    }\n\n    for (i = 0; i < bufferSize; i++) {\n        this.sinTable[i] = Math.sin(-Math.PI / i);\n        this.cosTable[i] = Math.cos(-Math.PI / i);\n    }\n\n    this.calculateSpectrum = function(buffer) {\n        // Locally scope variables for speed up\n        var bufferSize = this.bufferSize,\n            cosTable = this.cosTable,\n            sinTable = this.sinTable,\n            reverseTable = this.reverseTable,\n            real = new Float32Array(bufferSize),\n            imag = new Float32Array(bufferSize),\n            bSi = 2 / this.bufferSize,\n            sqrt = Math.sqrt,\n            rval,\n            ival,\n            mag,\n            spectrum = new Float32Array(bufferSize / 2);\n\n        var k = Math.floor(Math.log(bufferSize) / Math.LN2);\n\n        if (Math.pow(2, k) !== bufferSize) {\n            throw 'Invalid buffer size, must be a power of 2.';\n        }\n        if (bufferSize !== buffer.length) {\n            throw 'Supplied buffer is not the same size as defined FFT. FFT Size: ' +\n                bufferSize +\n                ' Buffer Size: ' +\n                buffer.length;\n        }\n\n        var halfSize = 1,\n            phaseShiftStepReal,\n            phaseShiftStepImag,\n            currentPhaseShiftReal,\n            currentPhaseShiftImag,\n            off,\n            tr,\n            ti,\n            tmpReal;\n\n        for (var i = 0; i < bufferSize; i++) {\n            real[i] =\n                buffer[reverseTable[i]] * this.windowValues[reverseTable[i]];\n            imag[i] = 0;\n        }\n\n        while (halfSize < bufferSize) {\n            phaseShiftStepReal = cosTable[halfSize];\n            phaseShiftStepImag = sinTable[halfSize];\n\n            currentPhaseShiftReal = 1;\n            currentPhaseShiftImag = 0;\n\n            for (var fftStep = 0; fftStep < halfSize; fftStep++) {\n                var i = fftStep;\n\n                while (i < bufferSize) {\n                    off = i + halfSize;\n                    tr =\n                        currentPhaseShiftReal * real[off] -\n                        currentPhaseShiftImag * imag[off];\n                    ti =\n                        currentPhaseShiftReal * imag[off] +\n                        currentPhaseShiftImag * real[off];\n\n                    real[off] = real[i] - tr;\n                    imag[off] = imag[i] - ti;\n                    real[i] += tr;\n                    imag[i] += ti;\n\n                    i += halfSize << 1;\n                }\n\n                tmpReal = currentPhaseShiftReal;\n                currentPhaseShiftReal =\n                    tmpReal * phaseShiftStepReal -\n                    currentPhaseShiftImag * phaseShiftStepImag;\n                currentPhaseShiftImag =\n                    tmpReal * phaseShiftStepImag +\n                    currentPhaseShiftImag * phaseShiftStepReal;\n            }\n\n            halfSize = halfSize << 1;\n        }\n\n        for (var i = 0, N = bufferSize / 2; i < N; i++) {\n            rval = real[i];\n            ival = imag[i];\n            mag = bSi * sqrt(rval * rval + ival * ival);\n\n            if (mag > this.peak) {\n                this.peakBand = i;\n                this.peak = mag;\n            }\n            spectrum[i] = mag;\n        }\n        return spectrum;\n    };\n};\n/* eslint-enable complexity, no-redeclare, no-var, one-var */\n\n/**\n * @typedef {Object} SpectrogramPluginParams\n * @property {string|HTMLElement} container Selector of element or element in\n * which to render\n * @property {number} fftSamples=512 Number of samples to fetch to FFT. Must be\n * a power of 2.\n * @property {boolean} labels Set to true to display frequency labels.\n * @property {number} noverlap Size of the overlapping window. Must be <\n * fftSamples. Auto deduced from canvas size by default.\n * @property {string} windowFunc='hann' The window function to be used. One of\n * these: `'bartlett'`, `'bartlettHann'`, `'blackman'`, `'cosine'`, `'gauss'`,\n * `'hamming'`, `'hann'`, `'lanczoz'`, `'rectangular'`, `'triangular'`\n * @property {?number} alpha Some window functions have this extra value.\n * (Between 0 and 1)\n * @property {number} pixelRatio=wavesurfer.params.pixelRatio to control the\n * size of the spectrogram in relation with its canvas. 1 = Draw on the whole\n * canvas. 2 = Draw on a quarter (1/2 the length and 1/2 the width)\n * @property {?boolean} deferInit Set to true to manually call\n * `initPlugin('spectrogram')`\n */\n\n/**\n * Render a spectrogram visualisation of the audio.\n *\n * @implements {PluginClass}\n * @extends {Observer}\n * @example\n * // es6\n * import SpectrogramPlugin from 'wavesurfer.spectrogram.js';\n *\n * // commonjs\n * var SpectrogramPlugin = require('wavesurfer.spectrogram.js');\n *\n * // if you are using <script> tags\n * var SpectrogramPlugin = window.WaveSurfer.spectrogram;\n *\n * // ... initialising wavesurfer with the plugin\n * var wavesurfer = WaveSurfer.create({\n *   // wavesurfer options ...\n *   plugins: [\n *     SpectrogramPlugin.create({\n *       // plugin options ...\n *     })\n *   ]\n * });\n */\nexport default class SpectrogramPlugin {\n    /**\n     * Spectrogram plugin definition factory\n     *\n     * This function must be used to create a plugin definition which can be\n     * used by wavesurfer to correctly instantiate the plugin.\n     *\n     * @param  {SpectrogramPluginParams} params Parameters used to initialise the plugin\n     * @return {PluginDefinition} An object representing the plugin.\n     */\n    static create(params) {\n        return {\n            name: 'spectrogram',\n            deferInit: params && params.deferInit ? params.deferInit : false,\n            params: params,\n            staticProps: {\n                FFT: FFT\n            },\n            instance: SpectrogramPlugin\n        };\n    }\n\n    constructor(params, ws) {\n        this.params = params;\n        this.wavesurfer = ws;\n        this.util = ws.util;\n\n        this.frequenciesDataUrl = params.frequenciesDataUrl;\n        this._onScroll = e => {\n            this.updateScroll(e);\n        };\n        this._onRender = () => {\n            this.render();\n        };\n        this._onWrapperClick = e => {\n            this._wrapperClickHandler(e);\n        };\n        this._onReady = () => {\n            const drawer = (this.drawer = ws.drawer);\n\n            this.container =\n                'string' == typeof params.container\n                    ? document.querySelector(params.container)\n                    : params.container;\n\n            if (!this.container) {\n                throw Error('No container for WaveSurfer spectrogram');\n            }\n\n            this.width = drawer.width;\n            this.pixelRatio = this.params.pixelRatio || ws.params.pixelRatio;\n            this.fftSamples =\n                this.params.fftSamples || ws.params.fftSamples || 512;\n            this.height = this.fftSamples / 2;\n            this.noverlap = params.noverlap;\n            this.windowFunc = params.windowFunc;\n            this.alpha = params.alpha;\n\n            this.createWrapper();\n            this.createCanvas();\n            this.render();\n\n            drawer.wrapper.addEventListener('scroll', this._onScroll);\n            ws.on('redraw', this._onRender);\n        };\n    }\n\n    init() {\n        // Check if wavesurfer is ready\n        if (this.wavesurfer.isReady) {\n            this._onReady();\n        }\n\n        this.wavesurfer.on('ready', this._onReady);\n    }\n\n    destroy() {\n        this.unAll();\n        this.wavesurfer.un('ready', this._onReady);\n        this.wavesurfer.un('redraw', this._onRender);\n        this.drawer.wrapper.removeEventListener('scroll', this._onScroll);\n        this.wavesurfer = null;\n        this.util = null;\n        this.params = null;\n        if (this.wrapper) {\n            this.wrapper.removeEventListener('click', this._onWrapperClick);\n            this.wrapper.parentNode.removeChild(this.wrapper);\n            this.wrapper = null;\n        }\n    }\n\n    createWrapper() {\n        const prevSpectrogram = this.container.querySelector('spectrogram');\n        if (prevSpectrogram) {\n            this.container.removeChild(prevSpectrogram);\n        }\n        const wsParams = this.wavesurfer.params;\n        this.wrapper = document.createElement('spectrogram');\n        // if labels are active\n        if (this.params.labels) {\n            const labelsEl = (this.labelsEl = document.createElement('canvas'));\n            labelsEl.classList.add('spec-labels');\n            this.drawer.style(labelsEl, {\n                left: 0,\n                position: 'absolute',\n                zIndex: 9,\n                height: `${this.height / this.pixelRatio}px`,\n                width: `${55 / this.pixelRatio}px`\n            });\n            this.wrapper.appendChild(labelsEl);\n            this.loadLabels(\n                'rgba(68,68,68,0.5)',\n                '12px',\n                '10px',\n                '',\n                '#fff',\n                '#f7f7f7',\n                'center',\n                '#specLabels'\n            );\n        }\n\n        this.drawer.style(this.wrapper, {\n            display: 'block',\n            position: 'relative',\n            userSelect: 'none',\n            webkitUserSelect: 'none',\n            height: `${this.height / this.pixelRatio}px`\n        });\n\n        if (wsParams.fillParent || wsParams.scrollParent) {\n            this.drawer.style(this.wrapper, {\n                width: '100%',\n                overflowX: 'hidden',\n                overflowY: 'hidden'\n            });\n        }\n        this.container.appendChild(this.wrapper);\n\n        this.wrapper.addEventListener('click', this._onWrapperClick);\n    }\n\n    _wrapperClickHandler(event) {\n        event.preventDefault();\n\n        const relX = 'offsetX' in event ? event.offsetX : event.layerX;\n        this.fireEvent('click', relX / this.scrollWidth || 0);\n    }\n\n    createCanvas() {\n        const canvas = (this.canvas = this.wrapper.appendChild(\n            document.createElement('canvas')\n        ));\n\n        this.spectrCc = canvas.getContext('2d');\n\n        this.util.style(canvas, {\n            position: 'absolute',\n            zIndex: 4\n        });\n    }\n\n    render() {\n        this.updateCanvasStyle();\n\n        if (this.frequenciesDataUrl) {\n            this.loadFrequenciesData(this.frequenciesDataUrl);\n        } else {\n            this.getFrequencies(this.drawSpectrogram);\n        }\n    }\n\n    updateCanvasStyle() {\n        const width = Math.round(this.width / this.pixelRatio) + 'px';\n        this.canvas.width = this.width;\n        this.canvas.height = this.height;\n        this.canvas.style.width = width;\n    }\n\n    drawSpectrogram(frequenciesData, my) {\n        const spectrCc = my.spectrCc;\n        const length = my.wavesurfer.backend.getDuration();\n        const height = my.height;\n        const pixels = my.resample(frequenciesData);\n        const heightFactor = my.buffer ? 2 / my.buffer.numberOfChannels : 1;\n        let i;\n        let j;\n\n        for (i = 0; i < pixels.length; i++) {\n            for (j = 0; j < pixels[i].length; j++) {\n                const colorValue = 255 - pixels[i][j];\n                my.spectrCc.fillStyle =\n                    'rgb(' +\n                    colorValue +\n                    ', ' +\n                    colorValue +\n                    ', ' +\n                    colorValue +\n                    ')';\n                my.spectrCc.fillRect(\n                    i,\n                    height - j * heightFactor,\n                    1,\n                    heightFactor\n                );\n            }\n        }\n    }\n\n    getFrequencies(callback) {\n        const fftSamples = this.fftSamples;\n        const buffer = (this.buffer = this.wavesurfer.backend.buffer);\n        const channelOne = buffer.getChannelData(0);\n        const bufferLength = buffer.length;\n        const sampleRate = buffer.sampleRate;\n        const frequencies = [];\n\n        if (!buffer) {\n            this.fireEvent('error', 'Web Audio buffer is not available');\n            return;\n        }\n\n        let noverlap = this.noverlap;\n        if (!noverlap) {\n            const uniqueSamplesPerPx = buffer.length / this.canvas.width;\n            noverlap = Math.max(0, Math.round(fftSamples - uniqueSamplesPerPx));\n        }\n\n        const fft = new FFT(\n            fftSamples,\n            sampleRate,\n            this.windowFunc,\n            this.alpha\n        );\n        const maxSlicesCount = Math.floor(\n            bufferLength / (fftSamples - noverlap)\n        );\n        let currentOffset = 0;\n\n        while (currentOffset + fftSamples < channelOne.length) {\n            const segment = channelOne.slice(\n                currentOffset,\n                currentOffset + fftSamples\n            );\n            const spectrum = fft.calculateSpectrum(segment);\n            const array = new Uint8Array(fftSamples / 2);\n            let j;\n            for (j = 0; j < fftSamples / 2; j++) {\n                array[j] = Math.max(-255, Math.log10(spectrum[j]) * 45);\n            }\n            frequencies.push(array);\n            currentOffset += fftSamples - noverlap;\n        }\n        callback(frequencies, this);\n    }\n\n    loadFrequenciesData(url) {\n        const ajax = this.util.ajax({ url: url });\n\n        ajax.on('success', data =>\n            this.drawSpectrogram(JSON.parse(data), this)\n        );\n        ajax.on('error', e =>\n            this.fireEvent('error', 'XHR error: ' + e.target.statusText)\n        );\n\n        return ajax;\n    }\n\n    freqType(freq) {\n        return freq >= 1000 ? (freq / 1000).toFixed(1) : Math.round(freq);\n    }\n\n    unitType(freq) {\n        return freq >= 1000 ? 'KHz' : 'Hz';\n    }\n\n    loadLabels(\n        bgFill,\n        fontSizeFreq,\n        fontSizeUnit,\n        fontType,\n        textColorFreq,\n        textColorUnit,\n        textAlign,\n        container\n    ) {\n        const frequenciesHeight = this.height;\n        bgFill = bgFill || 'rgba(68,68,68,0)';\n        fontSizeFreq = fontSizeFreq || '12px';\n        fontSizeUnit = fontSizeUnit || '10px';\n        fontType = fontType || 'Helvetica';\n        textColorFreq = textColorFreq || '#fff';\n        textColorUnit = textColorUnit || '#fff';\n        textAlign = textAlign || 'center';\n        container = container || '#specLabels';\n        const getMaxY = frequenciesHeight || 512;\n        const labelIndex = 5 * (getMaxY / 256);\n        const freqStart = 0;\n        const step =\n            (this.wavesurfer.backend.ac.sampleRate / 2 - freqStart) /\n            labelIndex;\n\n        const ctx = this.labelsEl.getContext('2d');\n        this.labelsEl.height = this.height;\n        this.labelsEl.width = 55;\n\n        ctx.fillStyle = bgFill;\n        ctx.fillRect(0, 0, 55, getMaxY);\n        ctx.fill();\n        let i;\n\n        for (i = 0; i <= labelIndex; i++) {\n            ctx.textAlign = textAlign;\n            ctx.textBaseline = 'middle';\n\n            const freq = freqStart + step * i;\n            const index = Math.round(\n                (freq / (this.sampleRate / 2)) * this.fftSamples\n            );\n            const label = this.freqType(freq);\n            const units = this.unitType(freq);\n            const x = 16;\n            const yLabelOffset = 2;\n\n            if (i == 0) {\n                ctx.fillStyle = textColorUnit;\n                ctx.font = fontSizeUnit + ' ' + fontType;\n                ctx.fillText(units, x + 24, getMaxY + i - 10);\n                ctx.fillStyle = textColorFreq;\n                ctx.font = fontSizeFreq + ' ' + fontType;\n                ctx.fillText(label, x, getMaxY + i - 10);\n            } else {\n                ctx.fillStyle = textColorUnit;\n                ctx.font = fontSizeUnit + ' ' + fontType;\n                ctx.fillText(units, x + 24, getMaxY - i * 50 + yLabelOffset);\n                ctx.fillStyle = textColorFreq;\n                ctx.font = fontSizeFreq + ' ' + fontType;\n                ctx.fillText(label, x, getMaxY - i * 50 + yLabelOffset);\n            }\n        }\n    }\n\n    updateScroll(e) {\n        if (this.wrapper) {\n            this.wrapper.scrollLeft = e.target.scrollLeft;\n        }\n    }\n\n    resample(oldMatrix) {\n        const columnsNumber = this.width;\n        const newMatrix = [];\n\n        const oldPiece = 1 / oldMatrix.length;\n        const newPiece = 1 / columnsNumber;\n        let i;\n\n        for (i = 0; i < columnsNumber; i++) {\n            const column = new Array(oldMatrix[0].length);\n            let j;\n\n            for (j = 0; j < oldMatrix.length; j++) {\n                const oldStart = j * oldPiece;\n                const oldEnd = oldStart + oldPiece;\n                const newStart = i * newPiece;\n                const newEnd = newStart + newPiece;\n\n                const overlap =\n                    oldEnd <= newStart || newEnd <= oldStart\n                        ? 0\n                        : Math.min(\n                              Math.max(oldEnd, newStart),\n                              Math.max(newEnd, oldStart)\n                          ) -\n                          Math.max(\n                              Math.min(oldEnd, newStart),\n                              Math.min(newEnd, oldStart)\n                          );\n                let k;\n                /* eslint-disable max-depth */\n                if (overlap > 0) {\n                    for (k = 0; k < oldMatrix[0].length; k++) {\n                        if (column[k] == null) {\n                            column[k] = 0;\n                        }\n                        column[k] += (overlap / newPiece) * oldMatrix[j][k];\n                    }\n                }\n                /* eslint-enable max-depth */\n            }\n\n            const intColumn = new Uint8Array(oldMatrix[0].length);\n            let m;\n\n            for (m = 0; m < oldMatrix[0].length; m++) {\n                intColumn[m] = column[m];\n            }\n\n            newMatrix.push(intColumn);\n        }\n\n        return newMatrix;\n    }\n}\n"],"sourceRoot":""}
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.timeline.js
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.timeline.js	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.timeline.js	(revision 33546)
@@ -0,0 +1,740 @@
+/*!
+ * wavesurfer.js timeline plugin 2.2.1 (2019-09-30)
+ * https://github.com/katspaugh/wavesurfer.js
+ * @license BSD-3-Clause
+ */
+(function webpackUniversalModuleDefinition(root, factory) {
+	if(typeof exports === 'object' && typeof module === 'object')
+		module.exports = factory();
+	else if(typeof define === 'function' && define.amd)
+		define("timeline", [], factory);
+	else if(typeof exports === 'object')
+		exports["timeline"] = factory();
+	else
+		root["WaveSurfer"] = root["WaveSurfer"] || {}, root["WaveSurfer"]["timeline"] = factory();
+})(window, function() {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+/******/
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId]) {
+/******/ 			return installedModules[moduleId].exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			i: moduleId,
+/******/ 			l: false,
+/******/ 			exports: {}
+/******/ 		};
+/******/
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ 		// Flag the module as loaded
+/******/ 		module.l = true;
+/******/
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/
+/******/
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+/******/
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+/******/
+/******/ 	// define getter function for harmony exports
+/******/ 	__webpack_require__.d = function(exports, name, getter) {
+/******/ 		if(!__webpack_require__.o(exports, name)) {
+/******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
+/******/ 		}
+/******/ 	};
+/******/
+/******/ 	// define __esModule on exports
+/******/ 	__webpack_require__.r = function(exports) {
+/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ 		}
+/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
+/******/ 	};
+/******/
+/******/ 	// create a fake namespace object
+/******/ 	// mode & 1: value is a module id, require it
+/******/ 	// mode & 2: merge all properties of value into the ns
+/******/ 	// mode & 4: return value when already ns object
+/******/ 	// mode & 8|1: behave like require
+/******/ 	__webpack_require__.t = function(value, mode) {
+/******/ 		if(mode & 1) value = __webpack_require__(value);
+/******/ 		if(mode & 8) return value;
+/******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
+/******/ 		var ns = Object.create(null);
+/******/ 		__webpack_require__.r(ns);
+/******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
+/******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
+/******/ 		return ns;
+/******/ 	};
+/******/
+/******/ 	// getDefaultExport function for compatibility with non-harmony modules
+/******/ 	__webpack_require__.n = function(module) {
+/******/ 		var getter = module && module.__esModule ?
+/******/ 			function getDefault() { return module['default']; } :
+/******/ 			function getModuleExports() { return module; };
+/******/ 		__webpack_require__.d(getter, 'a', getter);
+/******/ 		return getter;
+/******/ 	};
+/******/
+/******/ 	// Object.prototype.hasOwnProperty.call
+/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "localhost:8080/dist/plugin/";
+/******/
+/******/
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(__webpack_require__.s = "./src/plugin/timeline.js");
+/******/ })
+/************************************************************************/
+/******/ ({
+
+/***/ "./src/plugin/timeline.js":
+/*!********************************!*\
+  !*** ./src/plugin/timeline.js ***!
+  \********************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+/**
+ * @typedef {Object} TimelinePluginParams
+ * @desc Extends the `WavesurferParams` wavesurfer was initialised with
+ * @property {!string|HTMLElement} container CSS selector or HTML element where
+ * the timeline should be drawn. This is the only required parameter.
+ * @property {number} notchPercentHeight=90 Height of notches in percent
+ * @property {string} unlabeledNotchColor='#c0c0c0' The colour of the notches
+ * that do not have labels
+ * @property {string} primaryColor='#000' The colour of the main notches
+ * @property {string} secondaryColor='#c0c0c0' The colour of the secondary
+ * notches
+ * @property {string} primaryFontColor='#000' The colour of the labels next to
+ * the main notches
+ * @property {string} secondaryFontColor='#000' The colour of the labels next to
+ * the secondary notches
+ * @property {number} labelPadding=5 The padding between the label and the notch
+ * @property {?number} zoomDebounce A debounce timeout to increase rendering
+ * performance for large files
+ * @property {string} fontFamily='Arial'
+ * @property {number} fontSize=10 Font size of labels in pixels
+ * @property {?number} duration Length of the track in seconds. Overrides
+ * getDuration() for setting length of timeline
+ * @property {function} formatTimeCallback (sec, pxPerSec) -> label
+ * @property {function} timeInterval (pxPerSec) -> seconds between notches
+ * @property {function} primaryLabelInterval (pxPerSec) -> cadence between
+ * labels in primary color
+ * @property {function} secondaryLabelInterval (pxPerSec) -> cadence between
+ * labels in secondary color
+ * @property {?boolean} deferInit Set to true to manually call
+ * `initPlugin('timeline')`
+ */
+
+/**
+ * Adds a timeline to the waveform.
+ *
+ * @implements {PluginClass}
+ * @extends {Observer}
+ * @example
+ * // es6
+ * import TimelinePlugin from 'wavesurfer.timeline.js';
+ *
+ * // commonjs
+ * var TimelinePlugin = require('wavesurfer.timeline.js');
+ *
+ * // if you are using <script> tags
+ * var TimelinePlugin = window.WaveSurfer.timeline;
+ *
+ * // ... initialising wavesurfer with the plugin
+ * var wavesurfer = WaveSurfer.create({
+ *   // wavesurfer options ...
+ *   plugins: [
+ *     TimelinePlugin.create({
+ *       // plugin options ...
+ *     })
+ *   ]
+ * });
+ */
+var TimelinePlugin =
+/*#__PURE__*/
+function () {
+  _createClass(TimelinePlugin, null, [{
+    key: "create",
+
+    /**
+     * Timeline plugin definition factory
+     *
+     * This function must be used to create a plugin definition which can be
+     * used by wavesurfer to correctly instantiate the plugin.
+     *
+     * @param  {TimelinePluginParams} params parameters use to initialise the plugin
+     * @return {PluginDefinition} an object representing the plugin
+     */
+    value: function create(params) {
+      return {
+        name: 'timeline',
+        deferInit: params && params.deferInit ? params.deferInit : false,
+        params: params,
+        instance: TimelinePlugin
+      };
+    } // event handlers
+
+    /** @private */
+
+  }]);
+
+  /**
+   * Creates an instance of TimelinePlugin.
+   *
+   * You probably want to use TimelinePlugin.create()
+   *
+   * @param {TimelinePluginParams} params Plugin parameters
+   * @param {object} ws Wavesurfer instance
+   */
+  function TimelinePlugin(params, ws) {
+    var _this = this;
+
+    _classCallCheck(this, TimelinePlugin);
+
+    _initialiseProps.call(this);
+
+    /** @private */
+    this.container = 'string' == typeof params.container ? document.querySelector(params.container) : params.container;
+
+    if (!this.container) {
+      throw new Error('No container for wavesurfer timeline');
+    }
+    /** @private */
+
+
+    this.wavesurfer = ws;
+    /** @private */
+
+    this.util = ws.util;
+    /** @private */
+
+    this.params = this.util.extend({}, {
+      height: 20,
+      notchPercentHeight: 90,
+      labelPadding: 5,
+      unlabeledNotchColor: '#c0c0c0',
+      primaryColor: '#000',
+      secondaryColor: '#c0c0c0',
+      primaryFontColor: '#000',
+      secondaryFontColor: '#000',
+      fontFamily: 'Arial',
+      fontSize: 10,
+      duration: null,
+      zoomDebounce: false,
+      formatTimeCallback: this.defaultFormatTimeCallback,
+      timeInterval: this.defaultTimeInterval,
+      primaryLabelInterval: this.defaultPrimaryLabelInterval,
+      secondaryLabelInterval: this.defaultSecondaryLabelInterval
+    }, params);
+    /** @private */
+
+    this.canvases = [];
+    /** @private */
+
+    this.wrapper = null;
+    /** @private */
+
+    this.drawer = null;
+    /** @private */
+
+    this.pixelRatio = null;
+    /** @private */
+
+    this.maxCanvasWidth = null;
+    /** @private */
+
+    this.maxCanvasElementWidth = null;
+    /**
+     * This event handler has to be in the constructor function because it
+     * relies on the debounce function which is only available after
+     * instantiation
+     *
+     * Use a debounced function if zoomDebounce is defined
+     *
+     * @private
+     */
+
+    this._onZoom = this.params.zoomDebounce ? this.wavesurfer.util.debounce(function () {
+      return _this.render();
+    }, this.params.zoomDebounce) : function () {
+      return _this.render();
+    };
+  }
+  /**
+   * Initialisation function used by the plugin API
+   */
+
+
+  _createClass(TimelinePlugin, [{
+    key: "init",
+    value: function init() {
+      this.wavesurfer.on('ready', this._onReady); // Check if ws is ready
+
+      if (this.wavesurfer.isReady) {
+        this._onReady();
+      }
+    }
+    /**
+     * Destroy function used by the plugin API
+     */
+
+  }, {
+    key: "destroy",
+    value: function destroy() {
+      this.unAll();
+      this.wavesurfer.un('redraw', this._onRedraw);
+      this.wavesurfer.un('zoom', this._onZoom);
+      this.wavesurfer.un('ready', this._onReady);
+      this.wavesurfer.drawer.wrapper.removeEventListener('scroll', this._onScroll);
+
+      if (this.wrapper && this.wrapper.parentNode) {
+        this.wrapper.removeEventListener('click', this._onWrapperClick);
+        this.wrapper.parentNode.removeChild(this.wrapper);
+        this.wrapper = null;
+      }
+    }
+    /**
+     * Create a timeline element to wrap the canvases drawn by this plugin
+     *
+     * @private
+     */
+
+  }, {
+    key: "createWrapper",
+    value: function createWrapper() {
+      var wsParams = this.wavesurfer.params;
+      this.container.innerHTML = '';
+      this.wrapper = this.container.appendChild(document.createElement('timeline'));
+      this.util.style(this.wrapper, {
+        display: 'block',
+        position: 'relative',
+        userSelect: 'none',
+        webkitUserSelect: 'none',
+        height: "".concat(this.params.height, "px")
+      });
+
+      if (wsParams.fillParent || wsParams.scrollParent) {
+        this.util.style(this.wrapper, {
+          width: '100%',
+          overflowX: 'hidden',
+          overflowY: 'hidden'
+        });
+      }
+
+      this.wrapper.addEventListener('click', this._onWrapperClick);
+    }
+    /**
+     * Render the timeline (also updates the already rendered timeline)
+     *
+     * @private
+     */
+
+  }, {
+    key: "render",
+    value: function render() {
+      if (!this.wrapper) {
+        this.createWrapper();
+      }
+
+      this.updateCanvases();
+      this.updateCanvasesPositioning();
+      this.renderCanvases();
+    }
+    /**
+     * Make sure the correct of timeline canvas elements exist and are cached in
+     * this.canvases
+     *
+     * @private
+     */
+
+  }, {
+    key: "updateCanvases",
+    value: function updateCanvases() {
+      var _this2 = this;
+
+      var addCanvas = function addCanvas() {
+        var canvas = _this2.wrapper.appendChild(document.createElement('canvas'));
+
+        _this2.canvases.push(canvas);
+
+        _this2.util.style(canvas, {
+          position: 'absolute',
+          zIndex: 4
+        });
+      };
+
+      var removeCanvas = function removeCanvas() {
+        var canvas = _this2.canvases.pop();
+
+        canvas.parentElement.removeChild(canvas);
+      };
+
+      var totalWidth = Math.round(this.drawer.wrapper.scrollWidth);
+      var requiredCanvases = Math.ceil(totalWidth / this.maxCanvasElementWidth);
+
+      while (this.canvases.length < requiredCanvases) {
+        addCanvas();
+      }
+
+      while (this.canvases.length > requiredCanvases) {
+        removeCanvas();
+      }
+    }
+    /**
+     * Update the dimensions and positioning style for all the timeline canvases
+     *
+     * @private
+     */
+
+  }, {
+    key: "updateCanvasesPositioning",
+    value: function updateCanvasesPositioning() {
+      var _this3 = this;
+
+      // cache length for performance
+      var canvasesLength = this.canvases.length;
+      this.canvases.forEach(function (canvas, i) {
+        // canvas width is the max element width, or if it is the last the
+        // required width
+        var canvasWidth = i === canvasesLength - 1 ? _this3.drawer.wrapper.scrollWidth - _this3.maxCanvasElementWidth * (canvasesLength - 1) : _this3.maxCanvasElementWidth; // set dimensions and style
+
+        canvas.width = canvasWidth * _this3.pixelRatio; // on certain pixel ratios the canvas appears cut off at the bottom,
+        // therefore leave 1px extra
+
+        canvas.height = (_this3.params.height + 1) * _this3.pixelRatio;
+
+        _this3.util.style(canvas, {
+          width: "".concat(canvasWidth, "px"),
+          height: "".concat(_this3.params.height, "px"),
+          left: "".concat(i * _this3.maxCanvasElementWidth, "px")
+        });
+      });
+    }
+    /**
+     * Render the timeline labels and notches
+     *
+     * @private
+     */
+
+  }, {
+    key: "renderCanvases",
+    value: function renderCanvases() {
+      var _this4 = this;
+
+      var duration = this.wavesurfer.timeline.params.duration || this.wavesurfer.backend.getDuration();
+
+      if (duration <= 0) {
+        return;
+      }
+
+      var wsParams = this.wavesurfer.params;
+      var fontSize = this.params.fontSize * wsParams.pixelRatio;
+      var totalSeconds = parseInt(duration, 10) + 1;
+      var width = wsParams.fillParent && !wsParams.scrollParent ? this.drawer.getWidth() : this.drawer.wrapper.scrollWidth * wsParams.pixelRatio;
+      var height1 = this.params.height * this.pixelRatio;
+      var height2 = this.params.height * (this.params.notchPercentHeight / 100) * this.pixelRatio;
+      var pixelsPerSecond = width / duration;
+      var formatTime = this.params.formatTimeCallback; // if parameter is function, call the function with
+      // pixelsPerSecond, otherwise simply take the value as-is
+
+      var intervalFnOrVal = function intervalFnOrVal(option) {
+        return typeof option === 'function' ? option(pixelsPerSecond) : option;
+      };
+
+      var timeInterval = intervalFnOrVal(this.params.timeInterval);
+      var primaryLabelInterval = intervalFnOrVal(this.params.primaryLabelInterval);
+      var secondaryLabelInterval = intervalFnOrVal(this.params.secondaryLabelInterval);
+      var curPixel = 0;
+      var curSeconds = 0;
+      var i; // build an array of position data with index, second and pixel data,
+      // this is then used multiple times below
+
+      var positioning = [];
+
+      for (i = 0; i < totalSeconds / timeInterval; i++) {
+        positioning.push([i, curSeconds, curPixel]);
+        curSeconds += timeInterval;
+        curPixel += pixelsPerSecond * timeInterval;
+      } // iterate over each position
+
+
+      var renderPositions = function renderPositions(cb) {
+        positioning.forEach(function (pos) {
+          cb(pos[0], pos[1], pos[2]);
+        });
+      }; // render primary labels
+
+
+      this.setFillStyles(this.params.primaryColor);
+      this.setFonts("".concat(fontSize, "px ").concat(this.params.fontFamily));
+      this.setFillStyles(this.params.primaryFontColor);
+      renderPositions(function (i, curSeconds, curPixel) {
+        if (i % primaryLabelInterval === 0) {
+          _this4.fillRect(curPixel, 0, 1, height1);
+
+          _this4.fillText(formatTime(curSeconds, pixelsPerSecond), curPixel + _this4.params.labelPadding * _this4.pixelRatio, height1);
+        }
+      }); // render secondary labels
+
+      this.setFillStyles(this.params.secondaryColor);
+      this.setFonts("".concat(fontSize, "px ").concat(this.params.fontFamily));
+      this.setFillStyles(this.params.secondaryFontColor);
+      renderPositions(function (i, curSeconds, curPixel) {
+        if (i % secondaryLabelInterval === 0) {
+          _this4.fillRect(curPixel, 0, 1, height1);
+
+          _this4.fillText(formatTime(curSeconds, pixelsPerSecond), curPixel + _this4.params.labelPadding * _this4.pixelRatio, height1);
+        }
+      }); // render the actual notches (when no labels are used)
+
+      this.setFillStyles(this.params.unlabeledNotchColor);
+      renderPositions(function (i, curSeconds, curPixel) {
+        if (i % secondaryLabelInterval !== 0 && i % primaryLabelInterval !== 0) {
+          _this4.fillRect(curPixel, 0, 1, height2);
+        }
+      });
+    }
+    /**
+     * Set the canvas fill style
+     *
+     * @param {DOMString|CanvasGradient|CanvasPattern} fillStyle
+     * @private
+     */
+
+  }, {
+    key: "setFillStyles",
+    value: function setFillStyles(fillStyle) {
+      this.canvases.forEach(function (canvas) {
+        canvas.getContext('2d').fillStyle = fillStyle;
+      });
+    }
+    /**
+     * Set the canvas font
+     *
+     * @param {DOMString} font
+     * @private
+     */
+
+  }, {
+    key: "setFonts",
+    value: function setFonts(font) {
+      this.canvases.forEach(function (canvas) {
+        canvas.getContext('2d').font = font;
+      });
+    }
+    /**
+     * Draw a rectangle on the canvases
+     *
+     * (it figures out the offset for each canvas)
+     *
+     * @param {number} x
+     * @param {number} y
+     * @param {number} width
+     * @param {number} height
+     * @private
+     */
+
+  }, {
+    key: "fillRect",
+    value: function fillRect(x, y, width, height) {
+      var _this5 = this;
+
+      this.canvases.forEach(function (canvas, i) {
+        var leftOffset = i * _this5.maxCanvasWidth;
+        var intersection = {
+          x1: Math.max(x, i * _this5.maxCanvasWidth),
+          y1: y,
+          x2: Math.min(x + width, i * _this5.maxCanvasWidth + canvas.width),
+          y2: y + height
+        };
+
+        if (intersection.x1 < intersection.x2) {
+          canvas.getContext('2d').fillRect(intersection.x1 - leftOffset, intersection.y1, intersection.x2 - intersection.x1, intersection.y2 - intersection.y1);
+        }
+      });
+    }
+    /**
+     * Fill a given text on the canvases
+     *
+     * @param {string} text
+     * @param {number} x
+     * @param {number} y
+     * @private
+     */
+
+  }, {
+    key: "fillText",
+    value: function fillText(text, x, y) {
+      var textWidth;
+      var xOffset = 0;
+      this.canvases.forEach(function (canvas) {
+        var context = canvas.getContext('2d');
+        var canvasWidth = context.canvas.width;
+
+        if (xOffset > x + textWidth) {
+          return;
+        }
+
+        if (xOffset + canvasWidth > x) {
+          textWidth = context.measureText(text).width;
+          context.fillText(text, x - xOffset, y);
+        }
+
+        xOffset += canvasWidth;
+      });
+    }
+    /**
+     * Turn the time into a suitable label for the time.
+     *
+     * @param {number} seconds
+     * @param {number} pxPerSec
+     */
+
+  }, {
+    key: "defaultFormatTimeCallback",
+    value: function defaultFormatTimeCallback(seconds, pxPerSec) {
+      if (seconds / 60 > 1) {
+        // calculate minutes and seconds from seconds count
+        var minutes = parseInt(seconds / 60, 10);
+        seconds = parseInt(seconds % 60, 10); // fill up seconds with zeroes
+
+        seconds = seconds < 10 ? '0' + seconds : seconds;
+        return "".concat(minutes, ":").concat(seconds);
+      }
+
+      return Math.round(seconds * 1000) / 1000;
+    }
+    /**
+     * Return how many seconds should be between each notch
+     *
+     * @param pxPerSec
+     */
+
+  }, {
+    key: "defaultTimeInterval",
+    value: function defaultTimeInterval(pxPerSec) {
+      if (pxPerSec >= 25) {
+        return 1;
+      } else if (pxPerSec * 5 >= 25) {
+        return 5;
+      } else if (pxPerSec * 15 >= 25) {
+        return 15;
+      }
+
+      return Math.ceil(0.5 / pxPerSec) * 60;
+    }
+    /**
+     * Return the cadence of notches that get labels in the primary color.
+     *
+     * @param pxPerSec
+     */
+
+  }, {
+    key: "defaultPrimaryLabelInterval",
+    value: function defaultPrimaryLabelInterval(pxPerSec) {
+      if (pxPerSec >= 25) {
+        return 10;
+      } else if (pxPerSec * 5 >= 25) {
+        return 6;
+      } else if (pxPerSec * 15 >= 25) {
+        return 4;
+      }
+
+      return 4;
+    }
+    /**
+     * Return the cadence of notches that get labels in the secondary color.
+     *
+     * @param pxPerSec
+     */
+
+  }, {
+    key: "defaultSecondaryLabelInterval",
+    value: function defaultSecondaryLabelInterval(pxPerSec) {
+      if (pxPerSec >= 25) {
+        return 5;
+      } else if (pxPerSec * 5 >= 25) {
+        return 2;
+      } else if (pxPerSec * 15 >= 25) {
+        return 2;
+      }
+
+      return 2;
+    }
+  }]);
+
+  return TimelinePlugin;
+}();
+
+exports.default = TimelinePlugin;
+
+var _initialiseProps = function _initialiseProps() {
+  var _this6 = this;
+
+  this._onScroll = function () {
+    if (_this6.wrapper && _this6.drawer.wrapper) {
+      _this6.wrapper.scrollLeft = _this6.drawer.wrapper.scrollLeft;
+    }
+  };
+
+  this._onRedraw = function () {
+    return _this6.render();
+  };
+
+  this._onReady = function () {
+    var ws = _this6.wavesurfer;
+    _this6.drawer = ws.drawer;
+    _this6.pixelRatio = ws.drawer.params.pixelRatio;
+    _this6.maxCanvasWidth = ws.drawer.maxCanvasWidth || ws.drawer.width;
+    _this6.maxCanvasElementWidth = ws.drawer.maxCanvasElementWidth || Math.round(_this6.maxCanvasWidth / _this6.pixelRatio);
+    ws.drawer.wrapper.addEventListener('scroll', _this6._onScroll);
+    ws.on('redraw', _this6._onRedraw);
+    ws.on('zoom', _this6._onZoom);
+
+    _this6.render();
+  };
+
+  this._onWrapperClick = function (e) {
+    e.preventDefault();
+    var relX = 'offsetX' in e ? e.offsetX : e.layerX;
+
+    _this6.fireEvent('click', relX / _this6.wrapper.scrollWidth || 0);
+  };
+};
+
+module.exports = exports.default;
+
+/***/ })
+
+/******/ });
+});
+//# sourceMappingURL=wavesurfer.timeline.js.map
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.timeline.js.map
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.timeline.js.map	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.timeline.js.map	(revision 33546)
@@ -0,0 +1,1 @@
+{"version":3,"sources":["webpack://WaveSurfer.[name]/webpack/universalModuleDefinition","webpack://WaveSurfer.[name]/webpack/bootstrap","webpack://WaveSurfer.[name]/./src/plugin/timeline.js"],"names":["TimelinePlugin","params","name","deferInit","instance","ws","container","document","querySelector","Error","wavesurfer","util","extend","height","notchPercentHeight","labelPadding","unlabeledNotchColor","primaryColor","secondaryColor","primaryFontColor","secondaryFontColor","fontFamily","fontSize","duration","zoomDebounce","formatTimeCallback","defaultFormatTimeCallback","timeInterval","defaultTimeInterval","primaryLabelInterval","defaultPrimaryLabelInterval","secondaryLabelInterval","defaultSecondaryLabelInterval","canvases","wrapper","drawer","pixelRatio","maxCanvasWidth","maxCanvasElementWidth","_onZoom","debounce","render","on","_onReady","isReady","unAll","un","_onRedraw","removeEventListener","_onScroll","parentNode","_onWrapperClick","removeChild","wsParams","innerHTML","appendChild","createElement","style","display","position","userSelect","webkitUserSelect","fillParent","scrollParent","width","overflowX","overflowY","addEventListener","createWrapper","updateCanvases","updateCanvasesPositioning","renderCanvases","addCanvas","canvas","push","zIndex","removeCanvas","pop","parentElement","totalWidth","Math","round","scrollWidth","requiredCanvases","ceil","length","canvasesLength","forEach","i","canvasWidth","left","timeline","backend","getDuration","totalSeconds","parseInt","getWidth","height1","height2","pixelsPerSecond","formatTime","intervalFnOrVal","option","curPixel","curSeconds","positioning","renderPositions","cb","pos","setFillStyles","setFonts","fillRect","fillText","fillStyle","getContext","font","x","y","leftOffset","intersection","x1","max","y1","x2","min","y2","text","textWidth","xOffset","context","measureText","seconds","pxPerSec","minutes","scrollLeft","e","preventDefault","relX","offsetX","layerX","fireEvent"],"mappings":"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","file":"wavesurfer.timeline.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"timeline\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"timeline\"] = factory();\n\telse\n\t\troot[\"WaveSurfer\"] = root[\"WaveSurfer\"] || {}, root[\"WaveSurfer\"][\"timeline\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"localhost:8080/dist/plugin/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/plugin/timeline.js\");\n","/**\n * @typedef {Object} TimelinePluginParams\n * @desc Extends the `WavesurferParams` wavesurfer was initialised with\n * @property {!string|HTMLElement} container CSS selector or HTML element where\n * the timeline should be drawn. This is the only required parameter.\n * @property {number} notchPercentHeight=90 Height of notches in percent\n * @property {string} unlabeledNotchColor='#c0c0c0' The colour of the notches\n * that do not have labels\n * @property {string} primaryColor='#000' The colour of the main notches\n * @property {string} secondaryColor='#c0c0c0' The colour of the secondary\n * notches\n * @property {string} primaryFontColor='#000' The colour of the labels next to\n * the main notches\n * @property {string} secondaryFontColor='#000' The colour of the labels next to\n * the secondary notches\n * @property {number} labelPadding=5 The padding between the label and the notch\n * @property {?number} zoomDebounce A debounce timeout to increase rendering\n * performance for large files\n * @property {string} fontFamily='Arial'\n * @property {number} fontSize=10 Font size of labels in pixels\n * @property {?number} duration Length of the track in seconds. Overrides\n * getDuration() for setting length of timeline\n * @property {function} formatTimeCallback (sec, pxPerSec) -> label\n * @property {function} timeInterval (pxPerSec) -> seconds between notches\n * @property {function} primaryLabelInterval (pxPerSec) -> cadence between\n * labels in primary color\n * @property {function} secondaryLabelInterval (pxPerSec) -> cadence between\n * labels in secondary color\n * @property {?boolean} deferInit Set to true to manually call\n * `initPlugin('timeline')`\n */\n\n/**\n * Adds a timeline to the waveform.\n *\n * @implements {PluginClass}\n * @extends {Observer}\n * @example\n * // es6\n * import TimelinePlugin from 'wavesurfer.timeline.js';\n *\n * // commonjs\n * var TimelinePlugin = require('wavesurfer.timeline.js');\n *\n * // if you are using <script> tags\n * var TimelinePlugin = window.WaveSurfer.timeline;\n *\n * // ... initialising wavesurfer with the plugin\n * var wavesurfer = WaveSurfer.create({\n *   // wavesurfer options ...\n *   plugins: [\n *     TimelinePlugin.create({\n *       // plugin options ...\n *     })\n *   ]\n * });\n */\nexport default class TimelinePlugin {\n    /**\n     * Timeline plugin definition factory\n     *\n     * This function must be used to create a plugin definition which can be\n     * used by wavesurfer to correctly instantiate the plugin.\n     *\n     * @param  {TimelinePluginParams} params parameters use to initialise the plugin\n     * @return {PluginDefinition} an object representing the plugin\n     */\n    static create(params) {\n        return {\n            name: 'timeline',\n            deferInit: params && params.deferInit ? params.deferInit : false,\n            params: params,\n            instance: TimelinePlugin\n        };\n    }\n\n    // event handlers\n    /** @private */\n    _onScroll = () => {\n        if (this.wrapper && this.drawer.wrapper) {\n            this.wrapper.scrollLeft = this.drawer.wrapper.scrollLeft;\n        }\n    };\n    /** @private */\n    _onRedraw = () => this.render();\n    /** @private */\n    _onReady = () => {\n        const ws = this.wavesurfer;\n        this.drawer = ws.drawer;\n        this.pixelRatio = ws.drawer.params.pixelRatio;\n        this.maxCanvasWidth = ws.drawer.maxCanvasWidth || ws.drawer.width;\n        this.maxCanvasElementWidth =\n            ws.drawer.maxCanvasElementWidth ||\n            Math.round(this.maxCanvasWidth / this.pixelRatio);\n\n        ws.drawer.wrapper.addEventListener('scroll', this._onScroll);\n        ws.on('redraw', this._onRedraw);\n        ws.on('zoom', this._onZoom);\n        this.render();\n    };\n    /** @private */\n    _onWrapperClick = e => {\n        e.preventDefault();\n        const relX = 'offsetX' in e ? e.offsetX : e.layerX;\n        this.fireEvent('click', relX / this.wrapper.scrollWidth || 0);\n    };\n\n    /**\n     * Creates an instance of TimelinePlugin.\n     *\n     * You probably want to use TimelinePlugin.create()\n     *\n     * @param {TimelinePluginParams} params Plugin parameters\n     * @param {object} ws Wavesurfer instance\n     */\n    constructor(params, ws) {\n        /** @private */\n        this.container =\n            'string' == typeof params.container\n                ? document.querySelector(params.container)\n                : params.container;\n\n        if (!this.container) {\n            throw new Error('No container for wavesurfer timeline');\n        }\n        /** @private */\n        this.wavesurfer = ws;\n        /** @private */\n        this.util = ws.util;\n        /** @private */\n        this.params = this.util.extend(\n            {},\n            {\n                height: 20,\n                notchPercentHeight: 90,\n                labelPadding: 5,\n                unlabeledNotchColor: '#c0c0c0',\n                primaryColor: '#000',\n                secondaryColor: '#c0c0c0',\n                primaryFontColor: '#000',\n                secondaryFontColor: '#000',\n                fontFamily: 'Arial',\n                fontSize: 10,\n                duration: null,\n                zoomDebounce: false,\n                formatTimeCallback: this.defaultFormatTimeCallback,\n                timeInterval: this.defaultTimeInterval,\n                primaryLabelInterval: this.defaultPrimaryLabelInterval,\n                secondaryLabelInterval: this.defaultSecondaryLabelInterval\n            },\n            params\n        );\n\n        /** @private */\n        this.canvases = [];\n        /** @private */\n        this.wrapper = null;\n        /** @private */\n        this.drawer = null;\n        /** @private */\n        this.pixelRatio = null;\n        /** @private */\n        this.maxCanvasWidth = null;\n        /** @private */\n        this.maxCanvasElementWidth = null;\n        /**\n         * This event handler has to be in the constructor function because it\n         * relies on the debounce function which is only available after\n         * instantiation\n         *\n         * Use a debounced function if zoomDebounce is defined\n         *\n         * @private\n         */\n        this._onZoom = this.params.zoomDebounce\n            ? this.wavesurfer.util.debounce(\n                  () => this.render(),\n                  this.params.zoomDebounce\n              )\n            : () => this.render();\n    }\n\n    /**\n     * Initialisation function used by the plugin API\n     */\n    init() {\n        this.wavesurfer.on('ready', this._onReady);\n        // Check if ws is ready\n        if (this.wavesurfer.isReady) {\n            this._onReady();\n        }\n    }\n\n    /**\n     * Destroy function used by the plugin API\n     */\n    destroy() {\n        this.unAll();\n        this.wavesurfer.un('redraw', this._onRedraw);\n        this.wavesurfer.un('zoom', this._onZoom);\n        this.wavesurfer.un('ready', this._onReady);\n        this.wavesurfer.drawer.wrapper.removeEventListener(\n            'scroll',\n            this._onScroll\n        );\n        if (this.wrapper && this.wrapper.parentNode) {\n            this.wrapper.removeEventListener('click', this._onWrapperClick);\n            this.wrapper.parentNode.removeChild(this.wrapper);\n            this.wrapper = null;\n        }\n    }\n\n    /**\n     * Create a timeline element to wrap the canvases drawn by this plugin\n     *\n     * @private\n     */\n    createWrapper() {\n        const wsParams = this.wavesurfer.params;\n        this.container.innerHTML = '';\n        this.wrapper = this.container.appendChild(\n            document.createElement('timeline')\n        );\n        this.util.style(this.wrapper, {\n            display: 'block',\n            position: 'relative',\n            userSelect: 'none',\n            webkitUserSelect: 'none',\n            height: `${this.params.height}px`\n        });\n\n        if (wsParams.fillParent || wsParams.scrollParent) {\n            this.util.style(this.wrapper, {\n                width: '100%',\n                overflowX: 'hidden',\n                overflowY: 'hidden'\n            });\n        }\n\n        this.wrapper.addEventListener('click', this._onWrapperClick);\n    }\n\n    /**\n     * Render the timeline (also updates the already rendered timeline)\n     *\n     * @private\n     */\n    render() {\n        if (!this.wrapper) {\n            this.createWrapper();\n        }\n        this.updateCanvases();\n        this.updateCanvasesPositioning();\n        this.renderCanvases();\n    }\n\n    /**\n     * Make sure the correct of timeline canvas elements exist and are cached in\n     * this.canvases\n     *\n     * @private\n     */\n    updateCanvases() {\n        const addCanvas = () => {\n            const canvas = this.wrapper.appendChild(\n                document.createElement('canvas')\n            );\n            this.canvases.push(canvas);\n            this.util.style(canvas, {\n                position: 'absolute',\n                zIndex: 4\n            });\n        };\n        const removeCanvas = () => {\n            const canvas = this.canvases.pop();\n            canvas.parentElement.removeChild(canvas);\n        };\n\n        const totalWidth = Math.round(this.drawer.wrapper.scrollWidth);\n        const requiredCanvases = Math.ceil(\n            totalWidth / this.maxCanvasElementWidth\n        );\n        while (this.canvases.length < requiredCanvases) {\n            addCanvas();\n        }\n\n        while (this.canvases.length > requiredCanvases) {\n            removeCanvas();\n        }\n    }\n\n    /**\n     * Update the dimensions and positioning style for all the timeline canvases\n     *\n     * @private\n     */\n    updateCanvasesPositioning() {\n        // cache length for performance\n        const canvasesLength = this.canvases.length;\n        this.canvases.forEach((canvas, i) => {\n            // canvas width is the max element width, or if it is the last the\n            // required width\n            const canvasWidth =\n                i === canvasesLength - 1\n                    ? this.drawer.wrapper.scrollWidth -\n                      this.maxCanvasElementWidth * (canvasesLength - 1)\n                    : this.maxCanvasElementWidth;\n            // set dimensions and style\n            canvas.width = canvasWidth * this.pixelRatio;\n            // on certain pixel ratios the canvas appears cut off at the bottom,\n            // therefore leave 1px extra\n            canvas.height = (this.params.height + 1) * this.pixelRatio;\n            this.util.style(canvas, {\n                width: `${canvasWidth}px`,\n                height: `${this.params.height}px`,\n                left: `${i * this.maxCanvasElementWidth}px`\n            });\n        });\n    }\n\n    /**\n     * Render the timeline labels and notches\n     *\n     * @private\n     */\n    renderCanvases() {\n        const duration =\n            this.wavesurfer.timeline.params.duration ||\n            this.wavesurfer.backend.getDuration();\n\n        if (duration <= 0) {\n            return;\n        }\n        const wsParams = this.wavesurfer.params;\n        const fontSize = this.params.fontSize * wsParams.pixelRatio;\n        const totalSeconds = parseInt(duration, 10) + 1;\n        const width =\n            wsParams.fillParent && !wsParams.scrollParent\n                ? this.drawer.getWidth()\n                : this.drawer.wrapper.scrollWidth * wsParams.pixelRatio;\n        const height1 = this.params.height * this.pixelRatio;\n        const height2 =\n            this.params.height *\n            (this.params.notchPercentHeight / 100) *\n            this.pixelRatio;\n        const pixelsPerSecond = width / duration;\n\n        const formatTime = this.params.formatTimeCallback;\n        // if parameter is function, call the function with\n        // pixelsPerSecond, otherwise simply take the value as-is\n        const intervalFnOrVal = option =>\n            typeof option === 'function' ? option(pixelsPerSecond) : option;\n        const timeInterval = intervalFnOrVal(this.params.timeInterval);\n        const primaryLabelInterval = intervalFnOrVal(\n            this.params.primaryLabelInterval\n        );\n        const secondaryLabelInterval = intervalFnOrVal(\n            this.params.secondaryLabelInterval\n        );\n\n        let curPixel = 0;\n        let curSeconds = 0;\n        let i;\n        // build an array of position data with index, second and pixel data,\n        // this is then used multiple times below\n        const positioning = [];\n        for (i = 0; i < totalSeconds / timeInterval; i++) {\n            positioning.push([i, curSeconds, curPixel]);\n            curSeconds += timeInterval;\n            curPixel += pixelsPerSecond * timeInterval;\n        }\n\n        // iterate over each position\n        const renderPositions = cb => {\n            positioning.forEach(pos => {\n                cb(pos[0], pos[1], pos[2]);\n            });\n        };\n\n        // render primary labels\n        this.setFillStyles(this.params.primaryColor);\n        this.setFonts(`${fontSize}px ${this.params.fontFamily}`);\n        this.setFillStyles(this.params.primaryFontColor);\n        renderPositions((i, curSeconds, curPixel) => {\n            if (i % primaryLabelInterval === 0) {\n                this.fillRect(curPixel, 0, 1, height1);\n                this.fillText(\n                    formatTime(curSeconds, pixelsPerSecond),\n                    curPixel + this.params.labelPadding * this.pixelRatio,\n                    height1\n                );\n            }\n        });\n\n        // render secondary labels\n        this.setFillStyles(this.params.secondaryColor);\n        this.setFonts(`${fontSize}px ${this.params.fontFamily}`);\n        this.setFillStyles(this.params.secondaryFontColor);\n        renderPositions((i, curSeconds, curPixel) => {\n            if (i % secondaryLabelInterval === 0) {\n                this.fillRect(curPixel, 0, 1, height1);\n                this.fillText(\n                    formatTime(curSeconds, pixelsPerSecond),\n                    curPixel + this.params.labelPadding * this.pixelRatio,\n                    height1\n                );\n            }\n        });\n\n        // render the actual notches (when no labels are used)\n        this.setFillStyles(this.params.unlabeledNotchColor);\n        renderPositions((i, curSeconds, curPixel) => {\n            if (\n                i % secondaryLabelInterval !== 0 &&\n                i % primaryLabelInterval !== 0\n            ) {\n                this.fillRect(curPixel, 0, 1, height2);\n            }\n        });\n    }\n\n    /**\n     * Set the canvas fill style\n     *\n     * @param {DOMString|CanvasGradient|CanvasPattern} fillStyle\n     * @private\n     */\n    setFillStyles(fillStyle) {\n        this.canvases.forEach(canvas => {\n            canvas.getContext('2d').fillStyle = fillStyle;\n        });\n    }\n\n    /**\n     * Set the canvas font\n     *\n     * @param {DOMString} font\n     * @private\n     */\n    setFonts(font) {\n        this.canvases.forEach(canvas => {\n            canvas.getContext('2d').font = font;\n        });\n    }\n\n    /**\n     * Draw a rectangle on the canvases\n     *\n     * (it figures out the offset for each canvas)\n     *\n     * @param {number} x\n     * @param {number} y\n     * @param {number} width\n     * @param {number} height\n     * @private\n     */\n    fillRect(x, y, width, height) {\n        this.canvases.forEach((canvas, i) => {\n            const leftOffset = i * this.maxCanvasWidth;\n\n            const intersection = {\n                x1: Math.max(x, i * this.maxCanvasWidth),\n                y1: y,\n                x2: Math.min(x + width, i * this.maxCanvasWidth + canvas.width),\n                y2: y + height\n            };\n\n            if (intersection.x1 < intersection.x2) {\n                canvas\n                    .getContext('2d')\n                    .fillRect(\n                        intersection.x1 - leftOffset,\n                        intersection.y1,\n                        intersection.x2 - intersection.x1,\n                        intersection.y2 - intersection.y1\n                    );\n            }\n        });\n    }\n\n    /**\n     * Fill a given text on the canvases\n     *\n     * @param {string} text\n     * @param {number} x\n     * @param {number} y\n     * @private\n     */\n    fillText(text, x, y) {\n        let textWidth;\n        let xOffset = 0;\n\n        this.canvases.forEach(canvas => {\n            const context = canvas.getContext('2d');\n            const canvasWidth = context.canvas.width;\n\n            if (xOffset > x + textWidth) {\n                return;\n            }\n\n            if (xOffset + canvasWidth > x) {\n                textWidth = context.measureText(text).width;\n                context.fillText(text, x - xOffset, y);\n            }\n\n            xOffset += canvasWidth;\n        });\n    }\n\n    /**\n     * Turn the time into a suitable label for the time.\n     *\n     * @param {number} seconds\n     * @param {number} pxPerSec\n     */\n    defaultFormatTimeCallback(seconds, pxPerSec) {\n        if (seconds / 60 > 1) {\n            // calculate minutes and seconds from seconds count\n            const minutes = parseInt(seconds / 60, 10);\n            seconds = parseInt(seconds % 60, 10);\n            // fill up seconds with zeroes\n            seconds = seconds < 10 ? '0' + seconds : seconds;\n            return `${minutes}:${seconds}`;\n        }\n        return Math.round(seconds * 1000) / 1000;\n    }\n\n    /**\n     * Return how many seconds should be between each notch\n     *\n     * @param pxPerSec\n     */\n    defaultTimeInterval(pxPerSec) {\n        if (pxPerSec >= 25) {\n            return 1;\n        } else if (pxPerSec * 5 >= 25) {\n            return 5;\n        } else if (pxPerSec * 15 >= 25) {\n            return 15;\n        }\n        return Math.ceil(0.5 / pxPerSec) * 60;\n    }\n\n    /**\n     * Return the cadence of notches that get labels in the primary color.\n     *\n     * @param pxPerSec\n     */\n    defaultPrimaryLabelInterval(pxPerSec) {\n        if (pxPerSec >= 25) {\n            return 10;\n        } else if (pxPerSec * 5 >= 25) {\n            return 6;\n        } else if (pxPerSec * 15 >= 25) {\n            return 4;\n        }\n        return 4;\n    }\n\n    /**\n     * Return the cadence of notches that get labels in the secondary color.\n     *\n     * @param pxPerSec\n     */\n    defaultSecondaryLabelInterval(pxPerSec) {\n        if (pxPerSec >= 25) {\n            return 5;\n        } else if (pxPerSec * 5 >= 25) {\n            return 2;\n        } else if (pxPerSec * 15 >= 25) {\n            return 2;\n        }\n        return 2;\n    }\n}\n"],"sourceRoot":""}
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.timeline.min.js
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.timeline.min.js	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.timeline.min.js	(revision 33546)
@@ -0,0 +1,2 @@
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("timeline",[],t):"object"==typeof exports?exports.timeline=t():(e.WaveSurfer=e.WaveSurfer||{},e.WaveSurfer.timeline=t())}(window,(function(){return function(e){var t={};function a(r){if(t[r])return t[r].exports;var n=t[r]={i:r,l:!1,exports:{}};return e[r].call(n.exports,n,n.exports,a),n.l=!0,n.exports}return a.m=e,a.c=t,a.d=function(e,t,r){a.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},a.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,t){if(1&t&&(e=a(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(a.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)a.d(r,n,function(t){return e[t]}.bind(null,n));return r},a.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(t,"a",t),t},a.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},a.p="localhost:8080/dist/plugin/",a(a.s=0)}([function(e,t,a){"use strict";function r(e,t){for(var a=0;a<t.length;a++){var r=t[a];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function n(e,t,a){return t&&r(e.prototype,t),a&&r(e,a),e}Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var i=function(){function e(t,a){var r=this;if(function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),o.call(this),this.container="string"==typeof t.container?document.querySelector(t.container):t.container,!this.container)throw new Error("No container for wavesurfer timeline");this.wavesurfer=a,this.util=a.util,this.params=this.util.extend({},{height:20,notchPercentHeight:90,labelPadding:5,unlabeledNotchColor:"#c0c0c0",primaryColor:"#000",secondaryColor:"#c0c0c0",primaryFontColor:"#000",secondaryFontColor:"#000",fontFamily:"Arial",fontSize:10,duration:null,zoomDebounce:!1,formatTimeCallback:this.defaultFormatTimeCallback,timeInterval:this.defaultTimeInterval,primaryLabelInterval:this.defaultPrimaryLabelInterval,secondaryLabelInterval:this.defaultSecondaryLabelInterval},t),this.canvases=[],this.wrapper=null,this.drawer=null,this.pixelRatio=null,this.maxCanvasWidth=null,this.maxCanvasElementWidth=null,this._onZoom=this.params.zoomDebounce?this.wavesurfer.util.debounce((function(){return r.render()}),this.params.zoomDebounce):function(){return r.render()}}return n(e,null,[{key:"create",value:function(t){return{name:"timeline",deferInit:!(!t||!t.deferInit)&&t.deferInit,params:t,instance:e}}}]),n(e,[{key:"init",value:function(){this.wavesurfer.on("ready",this._onReady),this.wavesurfer.isReady&&this._onReady()}},{key:"destroy",value:function(){this.unAll(),this.wavesurfer.un("redraw",this._onRedraw),this.wavesurfer.un("zoom",this._onZoom),this.wavesurfer.un("ready",this._onReady),this.wavesurfer.drawer.wrapper.removeEventListener("scroll",this._onScroll),this.wrapper&&this.wrapper.parentNode&&(this.wrapper.removeEventListener("click",this._onWrapperClick),this.wrapper.parentNode.removeChild(this.wrapper),this.wrapper=null)}},{key:"createWrapper",value:function(){var e=this.wavesurfer.params;this.container.innerHTML="",this.wrapper=this.container.appendChild(document.createElement("timeline")),this.util.style(this.wrapper,{display:"block",position:"relative",userSelect:"none",webkitUserSelect:"none",height:"".concat(this.params.height,"px")}),(e.fillParent||e.scrollParent)&&this.util.style(this.wrapper,{width:"100%",overflowX:"hidden",overflowY:"hidden"}),this.wrapper.addEventListener("click",this._onWrapperClick)}},{key:"render",value:function(){this.wrapper||this.createWrapper(),this.updateCanvases(),this.updateCanvasesPositioning(),this.renderCanvases()}},{key:"updateCanvases",value:function(){for(var e,t=this,a=function(){var e=t.canvases.pop();e.parentElement.removeChild(e)},r=Math.round(this.drawer.wrapper.scrollWidth),n=Math.ceil(r/this.maxCanvasElementWidth);this.canvases.length<n;)e=void 0,e=t.wrapper.appendChild(document.createElement("canvas")),t.canvases.push(e),t.util.style(e,{position:"absolute",zIndex:4});for(;this.canvases.length>n;)a()}},{key:"updateCanvasesPositioning",value:function(){var e=this,t=this.canvases.length;this.canvases.forEach((function(a,r){var n=r===t-1?e.drawer.wrapper.scrollWidth-e.maxCanvasElementWidth*(t-1):e.maxCanvasElementWidth;a.width=n*e.pixelRatio,a.height=(e.params.height+1)*e.pixelRatio,e.util.style(a,{width:"".concat(n,"px"),height:"".concat(e.params.height,"px"),left:"".concat(r*e.maxCanvasElementWidth,"px")})}))}},{key:"renderCanvases",value:function(){var e=this,t=this.wavesurfer.timeline.params.duration||this.wavesurfer.backend.getDuration();if(!(t<=0)){var a,r=this.wavesurfer.params,n=this.params.fontSize*r.pixelRatio,i=parseInt(t,10)+1,o=r.fillParent&&!r.scrollParent?this.drawer.getWidth():this.drawer.wrapper.scrollWidth*r.pixelRatio,s=this.params.height*this.pixelRatio,l=this.params.height*(this.params.notchPercentHeight/100)*this.pixelRatio,c=o/t,u=this.params.formatTimeCallback,h=function(e){return"function"==typeof e?e(c):e},p=h(this.params.timeInterval),f=h(this.params.primaryLabelInterval),d=h(this.params.secondaryLabelInterval),v=0,m=0,y=[];for(a=0;a<i/p;a++)y.push([a,m,v]),m+=p,v+=c*p;var w=function(e){y.forEach((function(t){e(t[0],t[1],t[2])}))};this.setFillStyles(this.params.primaryColor),this.setFonts("".concat(n,"px ").concat(this.params.fontFamily)),this.setFillStyles(this.params.primaryFontColor),w((function(t,a,r){t%f==0&&(e.fillRect(r,0,1,s),e.fillText(u(a,c),r+e.params.labelPadding*e.pixelRatio,s))})),this.setFillStyles(this.params.secondaryColor),this.setFonts("".concat(n,"px ").concat(this.params.fontFamily)),this.setFillStyles(this.params.secondaryFontColor),w((function(t,a,r){t%d==0&&(e.fillRect(r,0,1,s),e.fillText(u(a,c),r+e.params.labelPadding*e.pixelRatio,s))})),this.setFillStyles(this.params.unlabeledNotchColor),w((function(t,a,r){t%d!=0&&t%f!=0&&e.fillRect(r,0,1,l)}))}}},{key:"setFillStyles",value:function(e){this.canvases.forEach((function(t){t.getContext("2d").fillStyle=e}))}},{key:"setFonts",value:function(e){this.canvases.forEach((function(t){t.getContext("2d").font=e}))}},{key:"fillRect",value:function(e,t,a,r){var n=this;this.canvases.forEach((function(i,o){var s=o*n.maxCanvasWidth,l={x1:Math.max(e,o*n.maxCanvasWidth),y1:t,x2:Math.min(e+a,o*n.maxCanvasWidth+i.width),y2:t+r};l.x1<l.x2&&i.getContext("2d").fillRect(l.x1-s,l.y1,l.x2-l.x1,l.y2-l.y1)}))}},{key:"fillText",value:function(e,t,a){var r,n=0;this.canvases.forEach((function(i){var o=i.getContext("2d"),s=o.canvas.width;n>t+r||(n+s>t&&(r=o.measureText(e).width,o.fillText(e,t-n,a)),n+=s)}))}},{key:"defaultFormatTimeCallback",value:function(e,t){if(e/60>1){var a=parseInt(e/60,10);return e=(e=parseInt(e%60,10))<10?"0"+e:e,"".concat(a,":").concat(e)}return Math.round(1e3*e)/1e3}},{key:"defaultTimeInterval",value:function(e){return e>=25?1:5*e>=25?5:15*e>=25?15:60*Math.ceil(.5/e)}},{key:"defaultPrimaryLabelInterval",value:function(e){return e>=25?10:5*e>=25?6:4}},{key:"defaultSecondaryLabelInterval",value:function(e){return e>=25?5:2}}]),e}();t.default=i;var o=function(){var e=this;this._onScroll=function(){e.wrapper&&e.drawer.wrapper&&(e.wrapper.scrollLeft=e.drawer.wrapper.scrollLeft)},this._onRedraw=function(){return e.render()},this._onReady=function(){var t=e.wavesurfer;e.drawer=t.drawer,e.pixelRatio=t.drawer.params.pixelRatio,e.maxCanvasWidth=t.drawer.maxCanvasWidth||t.drawer.width,e.maxCanvasElementWidth=t.drawer.maxCanvasElementWidth||Math.round(e.maxCanvasWidth/e.pixelRatio),t.drawer.wrapper.addEventListener("scroll",e._onScroll),t.on("redraw",e._onRedraw),t.on("zoom",e._onZoom),e.render()},this._onWrapperClick=function(t){t.preventDefault();var a="offsetX"in t?t.offsetX:t.layerX;e.fireEvent("click",a/e.wrapper.scrollWidth||0)}};e.exports=t.default}])}));
+//# sourceMappingURL=wavesurfer.timeline.min.js.map
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.timeline.min.js.map
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.timeline.min.js.map	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/plugin/wavesurfer.timeline.min.js.map	(revision 33546)
@@ -0,0 +1,1 @@
+{"version":3,"sources":["webpack://WaveSurfer.[name]/webpack/universalModuleDefinition","webpack://WaveSurfer.[name]/webpack/bootstrap","webpack://WaveSurfer.[name]/./src/plugin/timeline.js"],"names":["root","factory","exports","module","define","amd","window","installedModules","__webpack_require__","moduleId","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","TimelinePlugin","params","ws","this","container","document","querySelector","Error","wavesurfer","util","extend","height","notchPercentHeight","labelPadding","unlabeledNotchColor","primaryColor","secondaryColor","primaryFontColor","secondaryFontColor","fontFamily","fontSize","duration","zoomDebounce","formatTimeCallback","defaultFormatTimeCallback","timeInterval","defaultTimeInterval","primaryLabelInterval","defaultPrimaryLabelInterval","secondaryLabelInterval","defaultSecondaryLabelInterval","canvases","wrapper","drawer","pixelRatio","maxCanvasWidth","maxCanvasElementWidth","_onZoom","debounce","render","deferInit","instance","on","_onReady","isReady","unAll","un","_onRedraw","removeEventListener","_onScroll","parentNode","_onWrapperClick","removeChild","wsParams","innerHTML","appendChild","createElement","style","display","position","userSelect","webkitUserSelect","fillParent","scrollParent","width","overflowX","overflowY","addEventListener","createWrapper","updateCanvases","updateCanvasesPositioning","renderCanvases","canvas","removeCanvas","pop","parentElement","totalWidth","Math","round","scrollWidth","requiredCanvases","ceil","length","push","zIndex","canvasesLength","forEach","canvasWidth","left","timeline","backend","getDuration","totalSeconds","parseInt","getWidth","height1","height2","pixelsPerSecond","formatTime","intervalFnOrVal","option","curPixel","curSeconds","positioning","renderPositions","cb","pos","setFillStyles","setFonts","fillRect","fillText","fillStyle","getContext","font","x","y","leftOffset","intersection","x1","max","y1","x2","min","y2","text","textWidth","xOffset","context","measureText","seconds","pxPerSec","minutes","scrollLeft","e","preventDefault","relX","offsetX","layerX","fireEvent"],"mappings":"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","file":"wavesurfer.timeline.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"timeline\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"timeline\"] = factory();\n\telse\n\t\troot[\"WaveSurfer\"] = root[\"WaveSurfer\"] || {}, root[\"WaveSurfer\"][\"timeline\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"localhost:8080/dist/plugin/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n","/**\n * @typedef {Object} TimelinePluginParams\n * @desc Extends the `WavesurferParams` wavesurfer was initialised with\n * @property {!string|HTMLElement} container CSS selector or HTML element where\n * the timeline should be drawn. This is the only required parameter.\n * @property {number} notchPercentHeight=90 Height of notches in percent\n * @property {string} unlabeledNotchColor='#c0c0c0' The colour of the notches\n * that do not have labels\n * @property {string} primaryColor='#000' The colour of the main notches\n * @property {string} secondaryColor='#c0c0c0' The colour of the secondary\n * notches\n * @property {string} primaryFontColor='#000' The colour of the labels next to\n * the main notches\n * @property {string} secondaryFontColor='#000' The colour of the labels next to\n * the secondary notches\n * @property {number} labelPadding=5 The padding between the label and the notch\n * @property {?number} zoomDebounce A debounce timeout to increase rendering\n * performance for large files\n * @property {string} fontFamily='Arial'\n * @property {number} fontSize=10 Font size of labels in pixels\n * @property {?number} duration Length of the track in seconds. Overrides\n * getDuration() for setting length of timeline\n * @property {function} formatTimeCallback (sec, pxPerSec) -> label\n * @property {function} timeInterval (pxPerSec) -> seconds between notches\n * @property {function} primaryLabelInterval (pxPerSec) -> cadence between\n * labels in primary color\n * @property {function} secondaryLabelInterval (pxPerSec) -> cadence between\n * labels in secondary color\n * @property {?boolean} deferInit Set to true to manually call\n * `initPlugin('timeline')`\n */\n\n/**\n * Adds a timeline to the waveform.\n *\n * @implements {PluginClass}\n * @extends {Observer}\n * @example\n * // es6\n * import TimelinePlugin from 'wavesurfer.timeline.js';\n *\n * // commonjs\n * var TimelinePlugin = require('wavesurfer.timeline.js');\n *\n * // if you are using <script> tags\n * var TimelinePlugin = window.WaveSurfer.timeline;\n *\n * // ... initialising wavesurfer with the plugin\n * var wavesurfer = WaveSurfer.create({\n *   // wavesurfer options ...\n *   plugins: [\n *     TimelinePlugin.create({\n *       // plugin options ...\n *     })\n *   ]\n * });\n */\nexport default class TimelinePlugin {\n    /**\n     * Timeline plugin definition factory\n     *\n     * This function must be used to create a plugin definition which can be\n     * used by wavesurfer to correctly instantiate the plugin.\n     *\n     * @param  {TimelinePluginParams} params parameters use to initialise the plugin\n     * @return {PluginDefinition} an object representing the plugin\n     */\n    static create(params) {\n        return {\n            name: 'timeline',\n            deferInit: params && params.deferInit ? params.deferInit : false,\n            params: params,\n            instance: TimelinePlugin\n        };\n    }\n\n    // event handlers\n    /** @private */\n    _onScroll = () => {\n        if (this.wrapper && this.drawer.wrapper) {\n            this.wrapper.scrollLeft = this.drawer.wrapper.scrollLeft;\n        }\n    };\n    /** @private */\n    _onRedraw = () => this.render();\n    /** @private */\n    _onReady = () => {\n        const ws = this.wavesurfer;\n        this.drawer = ws.drawer;\n        this.pixelRatio = ws.drawer.params.pixelRatio;\n        this.maxCanvasWidth = ws.drawer.maxCanvasWidth || ws.drawer.width;\n        this.maxCanvasElementWidth =\n            ws.drawer.maxCanvasElementWidth ||\n            Math.round(this.maxCanvasWidth / this.pixelRatio);\n\n        ws.drawer.wrapper.addEventListener('scroll', this._onScroll);\n        ws.on('redraw', this._onRedraw);\n        ws.on('zoom', this._onZoom);\n        this.render();\n    };\n    /** @private */\n    _onWrapperClick = e => {\n        e.preventDefault();\n        const relX = 'offsetX' in e ? e.offsetX : e.layerX;\n        this.fireEvent('click', relX / this.wrapper.scrollWidth || 0);\n    };\n\n    /**\n     * Creates an instance of TimelinePlugin.\n     *\n     * You probably want to use TimelinePlugin.create()\n     *\n     * @param {TimelinePluginParams} params Plugin parameters\n     * @param {object} ws Wavesurfer instance\n     */\n    constructor(params, ws) {\n        /** @private */\n        this.container =\n            'string' == typeof params.container\n                ? document.querySelector(params.container)\n                : params.container;\n\n        if (!this.container) {\n            throw new Error('No container for wavesurfer timeline');\n        }\n        /** @private */\n        this.wavesurfer = ws;\n        /** @private */\n        this.util = ws.util;\n        /** @private */\n        this.params = this.util.extend(\n            {},\n            {\n                height: 20,\n                notchPercentHeight: 90,\n                labelPadding: 5,\n                unlabeledNotchColor: '#c0c0c0',\n                primaryColor: '#000',\n                secondaryColor: '#c0c0c0',\n                primaryFontColor: '#000',\n                secondaryFontColor: '#000',\n                fontFamily: 'Arial',\n                fontSize: 10,\n                duration: null,\n                zoomDebounce: false,\n                formatTimeCallback: this.defaultFormatTimeCallback,\n                timeInterval: this.defaultTimeInterval,\n                primaryLabelInterval: this.defaultPrimaryLabelInterval,\n                secondaryLabelInterval: this.defaultSecondaryLabelInterval\n            },\n            params\n        );\n\n        /** @private */\n        this.canvases = [];\n        /** @private */\n        this.wrapper = null;\n        /** @private */\n        this.drawer = null;\n        /** @private */\n        this.pixelRatio = null;\n        /** @private */\n        this.maxCanvasWidth = null;\n        /** @private */\n        this.maxCanvasElementWidth = null;\n        /**\n         * This event handler has to be in the constructor function because it\n         * relies on the debounce function which is only available after\n         * instantiation\n         *\n         * Use a debounced function if zoomDebounce is defined\n         *\n         * @private\n         */\n        this._onZoom = this.params.zoomDebounce\n            ? this.wavesurfer.util.debounce(\n                  () => this.render(),\n                  this.params.zoomDebounce\n              )\n            : () => this.render();\n    }\n\n    /**\n     * Initialisation function used by the plugin API\n     */\n    init() {\n        this.wavesurfer.on('ready', this._onReady);\n        // Check if ws is ready\n        if (this.wavesurfer.isReady) {\n            this._onReady();\n        }\n    }\n\n    /**\n     * Destroy function used by the plugin API\n     */\n    destroy() {\n        this.unAll();\n        this.wavesurfer.un('redraw', this._onRedraw);\n        this.wavesurfer.un('zoom', this._onZoom);\n        this.wavesurfer.un('ready', this._onReady);\n        this.wavesurfer.drawer.wrapper.removeEventListener(\n            'scroll',\n            this._onScroll\n        );\n        if (this.wrapper && this.wrapper.parentNode) {\n            this.wrapper.removeEventListener('click', this._onWrapperClick);\n            this.wrapper.parentNode.removeChild(this.wrapper);\n            this.wrapper = null;\n        }\n    }\n\n    /**\n     * Create a timeline element to wrap the canvases drawn by this plugin\n     *\n     * @private\n     */\n    createWrapper() {\n        const wsParams = this.wavesurfer.params;\n        this.container.innerHTML = '';\n        this.wrapper = this.container.appendChild(\n            document.createElement('timeline')\n        );\n        this.util.style(this.wrapper, {\n            display: 'block',\n            position: 'relative',\n            userSelect: 'none',\n            webkitUserSelect: 'none',\n            height: `${this.params.height}px`\n        });\n\n        if (wsParams.fillParent || wsParams.scrollParent) {\n            this.util.style(this.wrapper, {\n                width: '100%',\n                overflowX: 'hidden',\n                overflowY: 'hidden'\n            });\n        }\n\n        this.wrapper.addEventListener('click', this._onWrapperClick);\n    }\n\n    /**\n     * Render the timeline (also updates the already rendered timeline)\n     *\n     * @private\n     */\n    render() {\n        if (!this.wrapper) {\n            this.createWrapper();\n        }\n        this.updateCanvases();\n        this.updateCanvasesPositioning();\n        this.renderCanvases();\n    }\n\n    /**\n     * Make sure the correct of timeline canvas elements exist and are cached in\n     * this.canvases\n     *\n     * @private\n     */\n    updateCanvases() {\n        const addCanvas = () => {\n            const canvas = this.wrapper.appendChild(\n                document.createElement('canvas')\n            );\n            this.canvases.push(canvas);\n            this.util.style(canvas, {\n                position: 'absolute',\n                zIndex: 4\n            });\n        };\n        const removeCanvas = () => {\n            const canvas = this.canvases.pop();\n            canvas.parentElement.removeChild(canvas);\n        };\n\n        const totalWidth = Math.round(this.drawer.wrapper.scrollWidth);\n        const requiredCanvases = Math.ceil(\n            totalWidth / this.maxCanvasElementWidth\n        );\n        while (this.canvases.length < requiredCanvases) {\n            addCanvas();\n        }\n\n        while (this.canvases.length > requiredCanvases) {\n            removeCanvas();\n        }\n    }\n\n    /**\n     * Update the dimensions and positioning style for all the timeline canvases\n     *\n     * @private\n     */\n    updateCanvasesPositioning() {\n        // cache length for performance\n        const canvasesLength = this.canvases.length;\n        this.canvases.forEach((canvas, i) => {\n            // canvas width is the max element width, or if it is the last the\n            // required width\n            const canvasWidth =\n                i === canvasesLength - 1\n                    ? this.drawer.wrapper.scrollWidth -\n                      this.maxCanvasElementWidth * (canvasesLength - 1)\n                    : this.maxCanvasElementWidth;\n            // set dimensions and style\n            canvas.width = canvasWidth * this.pixelRatio;\n            // on certain pixel ratios the canvas appears cut off at the bottom,\n            // therefore leave 1px extra\n            canvas.height = (this.params.height + 1) * this.pixelRatio;\n            this.util.style(canvas, {\n                width: `${canvasWidth}px`,\n                height: `${this.params.height}px`,\n                left: `${i * this.maxCanvasElementWidth}px`\n            });\n        });\n    }\n\n    /**\n     * Render the timeline labels and notches\n     *\n     * @private\n     */\n    renderCanvases() {\n        const duration =\n            this.wavesurfer.timeline.params.duration ||\n            this.wavesurfer.backend.getDuration();\n\n        if (duration <= 0) {\n            return;\n        }\n        const wsParams = this.wavesurfer.params;\n        const fontSize = this.params.fontSize * wsParams.pixelRatio;\n        const totalSeconds = parseInt(duration, 10) + 1;\n        const width =\n            wsParams.fillParent && !wsParams.scrollParent\n                ? this.drawer.getWidth()\n                : this.drawer.wrapper.scrollWidth * wsParams.pixelRatio;\n        const height1 = this.params.height * this.pixelRatio;\n        const height2 =\n            this.params.height *\n            (this.params.notchPercentHeight / 100) *\n            this.pixelRatio;\n        const pixelsPerSecond = width / duration;\n\n        const formatTime = this.params.formatTimeCallback;\n        // if parameter is function, call the function with\n        // pixelsPerSecond, otherwise simply take the value as-is\n        const intervalFnOrVal = option =>\n            typeof option === 'function' ? option(pixelsPerSecond) : option;\n        const timeInterval = intervalFnOrVal(this.params.timeInterval);\n        const primaryLabelInterval = intervalFnOrVal(\n            this.params.primaryLabelInterval\n        );\n        const secondaryLabelInterval = intervalFnOrVal(\n            this.params.secondaryLabelInterval\n        );\n\n        let curPixel = 0;\n        let curSeconds = 0;\n        let i;\n        // build an array of position data with index, second and pixel data,\n        // this is then used multiple times below\n        const positioning = [];\n        for (i = 0; i < totalSeconds / timeInterval; i++) {\n            positioning.push([i, curSeconds, curPixel]);\n            curSeconds += timeInterval;\n            curPixel += pixelsPerSecond * timeInterval;\n        }\n\n        // iterate over each position\n        const renderPositions = cb => {\n            positioning.forEach(pos => {\n                cb(pos[0], pos[1], pos[2]);\n            });\n        };\n\n        // render primary labels\n        this.setFillStyles(this.params.primaryColor);\n        this.setFonts(`${fontSize}px ${this.params.fontFamily}`);\n        this.setFillStyles(this.params.primaryFontColor);\n        renderPositions((i, curSeconds, curPixel) => {\n            if (i % primaryLabelInterval === 0) {\n                this.fillRect(curPixel, 0, 1, height1);\n                this.fillText(\n                    formatTime(curSeconds, pixelsPerSecond),\n                    curPixel + this.params.labelPadding * this.pixelRatio,\n                    height1\n                );\n            }\n        });\n\n        // render secondary labels\n        this.setFillStyles(this.params.secondaryColor);\n        this.setFonts(`${fontSize}px ${this.params.fontFamily}`);\n        this.setFillStyles(this.params.secondaryFontColor);\n        renderPositions((i, curSeconds, curPixel) => {\n            if (i % secondaryLabelInterval === 0) {\n                this.fillRect(curPixel, 0, 1, height1);\n                this.fillText(\n                    formatTime(curSeconds, pixelsPerSecond),\n                    curPixel + this.params.labelPadding * this.pixelRatio,\n                    height1\n                );\n            }\n        });\n\n        // render the actual notches (when no labels are used)\n        this.setFillStyles(this.params.unlabeledNotchColor);\n        renderPositions((i, curSeconds, curPixel) => {\n            if (\n                i % secondaryLabelInterval !== 0 &&\n                i % primaryLabelInterval !== 0\n            ) {\n                this.fillRect(curPixel, 0, 1, height2);\n            }\n        });\n    }\n\n    /**\n     * Set the canvas fill style\n     *\n     * @param {DOMString|CanvasGradient|CanvasPattern} fillStyle\n     * @private\n     */\n    setFillStyles(fillStyle) {\n        this.canvases.forEach(canvas => {\n            canvas.getContext('2d').fillStyle = fillStyle;\n        });\n    }\n\n    /**\n     * Set the canvas font\n     *\n     * @param {DOMString} font\n     * @private\n     */\n    setFonts(font) {\n        this.canvases.forEach(canvas => {\n            canvas.getContext('2d').font = font;\n        });\n    }\n\n    /**\n     * Draw a rectangle on the canvases\n     *\n     * (it figures out the offset for each canvas)\n     *\n     * @param {number} x\n     * @param {number} y\n     * @param {number} width\n     * @param {number} height\n     * @private\n     */\n    fillRect(x, y, width, height) {\n        this.canvases.forEach((canvas, i) => {\n            const leftOffset = i * this.maxCanvasWidth;\n\n            const intersection = {\n                x1: Math.max(x, i * this.maxCanvasWidth),\n                y1: y,\n                x2: Math.min(x + width, i * this.maxCanvasWidth + canvas.width),\n                y2: y + height\n            };\n\n            if (intersection.x1 < intersection.x2) {\n                canvas\n                    .getContext('2d')\n                    .fillRect(\n                        intersection.x1 - leftOffset,\n                        intersection.y1,\n                        intersection.x2 - intersection.x1,\n                        intersection.y2 - intersection.y1\n                    );\n            }\n        });\n    }\n\n    /**\n     * Fill a given text on the canvases\n     *\n     * @param {string} text\n     * @param {number} x\n     * @param {number} y\n     * @private\n     */\n    fillText(text, x, y) {\n        let textWidth;\n        let xOffset = 0;\n\n        this.canvases.forEach(canvas => {\n            const context = canvas.getContext('2d');\n            const canvasWidth = context.canvas.width;\n\n            if (xOffset > x + textWidth) {\n                return;\n            }\n\n            if (xOffset + canvasWidth > x) {\n                textWidth = context.measureText(text).width;\n                context.fillText(text, x - xOffset, y);\n            }\n\n            xOffset += canvasWidth;\n        });\n    }\n\n    /**\n     * Turn the time into a suitable label for the time.\n     *\n     * @param {number} seconds\n     * @param {number} pxPerSec\n     */\n    defaultFormatTimeCallback(seconds, pxPerSec) {\n        if (seconds / 60 > 1) {\n            // calculate minutes and seconds from seconds count\n            const minutes = parseInt(seconds / 60, 10);\n            seconds = parseInt(seconds % 60, 10);\n            // fill up seconds with zeroes\n            seconds = seconds < 10 ? '0' + seconds : seconds;\n            return `${minutes}:${seconds}`;\n        }\n        return Math.round(seconds * 1000) / 1000;\n    }\n\n    /**\n     * Return how many seconds should be between each notch\n     *\n     * @param pxPerSec\n     */\n    defaultTimeInterval(pxPerSec) {\n        if (pxPerSec >= 25) {\n            return 1;\n        } else if (pxPerSec * 5 >= 25) {\n            return 5;\n        } else if (pxPerSec * 15 >= 25) {\n            return 15;\n        }\n        return Math.ceil(0.5 / pxPerSec) * 60;\n    }\n\n    /**\n     * Return the cadence of notches that get labels in the primary color.\n     *\n     * @param pxPerSec\n     */\n    defaultPrimaryLabelInterval(pxPerSec) {\n        if (pxPerSec >= 25) {\n            return 10;\n        } else if (pxPerSec * 5 >= 25) {\n            return 6;\n        } else if (pxPerSec * 15 >= 25) {\n            return 4;\n        }\n        return 4;\n    }\n\n    /**\n     * Return the cadence of notches that get labels in the secondary color.\n     *\n     * @param pxPerSec\n     */\n    defaultSecondaryLabelInterval(pxPerSec) {\n        if (pxPerSec >= 25) {\n            return 5;\n        } else if (pxPerSec * 5 >= 25) {\n            return 2;\n        } else if (pxPerSec * 15 >= 25) {\n            return 2;\n        }\n        return 2;\n    }\n}\n"],"sourceRoot":""}
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/wavesurfer-html-init.js
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/wavesurfer-html-init.js	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/wavesurfer-html-init.js	(revision 33546)
@@ -0,0 +1,454 @@
+/*!
+ * wavesurfer.js 2.2.1 (2019-09-30)
+ * https://github.com/katspaugh/wavesurfer.js
+ * @license BSD-3-Clause
+ */
+(function webpackUniversalModuleDefinition(root, factory) {
+	if(typeof exports === 'object' && typeof module === 'object')
+		module.exports = factory();
+	else if(typeof define === 'function' && define.amd)
+		define("html-init", [], factory);
+	else if(typeof exports === 'object')
+		exports["html-init"] = factory();
+	else
+		root["WaveSurfer"] = root["WaveSurfer"] || {}, root["WaveSurfer"]["html-init"] = factory();
+})(window, function() {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+/******/
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId]) {
+/******/ 			return installedModules[moduleId].exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			i: moduleId,
+/******/ 			l: false,
+/******/ 			exports: {}
+/******/ 		};
+/******/
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ 		// Flag the module as loaded
+/******/ 		module.l = true;
+/******/
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/
+/******/
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+/******/
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+/******/
+/******/ 	// define getter function for harmony exports
+/******/ 	__webpack_require__.d = function(exports, name, getter) {
+/******/ 		if(!__webpack_require__.o(exports, name)) {
+/******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
+/******/ 		}
+/******/ 	};
+/******/
+/******/ 	// define __esModule on exports
+/******/ 	__webpack_require__.r = function(exports) {
+/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ 		}
+/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
+/******/ 	};
+/******/
+/******/ 	// create a fake namespace object
+/******/ 	// mode & 1: value is a module id, require it
+/******/ 	// mode & 2: merge all properties of value into the ns
+/******/ 	// mode & 4: return value when already ns object
+/******/ 	// mode & 8|1: behave like require
+/******/ 	__webpack_require__.t = function(value, mode) {
+/******/ 		if(mode & 1) value = __webpack_require__(value);
+/******/ 		if(mode & 8) return value;
+/******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
+/******/ 		var ns = Object.create(null);
+/******/ 		__webpack_require__.r(ns);
+/******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
+/******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
+/******/ 		return ns;
+/******/ 	};
+/******/
+/******/ 	// getDefaultExport function for compatibility with non-harmony modules
+/******/ 	__webpack_require__.n = function(module) {
+/******/ 		var getter = module && module.__esModule ?
+/******/ 			function getDefault() { return module['default']; } :
+/******/ 			function getModuleExports() { return module; };
+/******/ 		__webpack_require__.d(getter, 'a', getter);
+/******/ 		return getter;
+/******/ 	};
+/******/
+/******/ 	// Object.prototype.hasOwnProperty.call
+/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "";
+/******/
+/******/
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(__webpack_require__.s = "./src/html-init.js");
+/******/ })
+/************************************************************************/
+/******/ ({
+
+/***/ "./node_modules/load-script/index.js":
+/*!*******************************************!*\
+  !*** ./node_modules/load-script/index.js ***!
+  \*******************************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+
+module.exports = function load (src, opts, cb) {
+  var head = document.head || document.getElementsByTagName('head')[0]
+  var script = document.createElement('script')
+
+  if (typeof opts === 'function') {
+    cb = opts
+    opts = {}
+  }
+
+  opts = opts || {}
+  cb = cb || function() {}
+
+  script.type = opts.type || 'text/javascript'
+  script.charset = opts.charset || 'utf8';
+  script.async = 'async' in opts ? !!opts.async : true
+  script.src = src
+
+  if (opts.attrs) {
+    setAttributes(script, opts.attrs)
+  }
+
+  if (opts.text) {
+    script.text = '' + opts.text
+  }
+
+  var onend = 'onload' in script ? stdOnEnd : ieOnEnd
+  onend(script, cb)
+
+  // some good legacy browsers (firefox) fail the 'in' detection above
+  // so as a fallback we always set onload
+  // old IE will ignore this and new IE will set onload
+  if (!script.onload) {
+    stdOnEnd(script, cb);
+  }
+
+  head.appendChild(script)
+}
+
+function setAttributes(script, attrs) {
+  for (var attr in attrs) {
+    script.setAttribute(attr, attrs[attr]);
+  }
+}
+
+function stdOnEnd (script, cb) {
+  script.onload = function () {
+    this.onerror = this.onload = null
+    cb(null, script)
+  }
+  script.onerror = function () {
+    // this.onload = null here is necessary
+    // because even IE9 works not like others
+    this.onerror = this.onload = null
+    cb(new Error('Failed to load ' + this.src), script)
+  }
+}
+
+function ieOnEnd (script, cb) {
+  script.onreadystatechange = function () {
+    if (this.readyState != 'complete' && this.readyState != 'loaded') return
+    this.onreadystatechange = null
+    cb(null, script) // there is no way to catch loading errors in IE8
+  }
+}
+
+
+/***/ }),
+
+/***/ "./src/html-init.js":
+/*!**************************!*\
+  !*** ./src/html-init.js ***!
+  \**************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _loadScript = _interopRequireDefault(__webpack_require__(/*! load-script */ "./node_modules/load-script/index.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _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); }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+/**
+ * @typedef {Object} InitParams
+ * @property {WavesurferParams} [defaults={backend: 'MediaElement,
+ * mediaControls: true}] The default wavesurfer initialisation parameters
+ * @property {string|NodeList} containers='wavesurfer' Selector or NodeList of
+ * elements to attach instances to
+ * @property {string}
+ * pluginCdnTemplate='//localhost:8080/dist/plugin/wavesurfer.[name].js' URL
+ * template for the dynamic loading of plugins
+ * @property {function} loadPlugin If set overwrites the default ajax function,
+ * can be used to inject plugins differently.
+ */
+
+/**
+ * The HTML initialisation API is not part of the main library bundle file and
+ * must be additionally included.
+ *
+ * The API attaches wavesurfer instances to all `<wavesurfer>` (can be
+ * customised), parsing their `data-` attributes to construct an options object
+ * for initialisation. Among other things it can dynamically load plugin code.
+ *
+ * The automatic initialisation can be prevented by setting the
+ * `window.WS_StopAutoInit` flag to true. The `html-init[.min].js` file exports
+ * the `Init` class, which can be called manually.
+ *
+ * Site-wide defaults can be added by setting `window.WS_InitOptions`.
+ *
+ * @example
+ * <!-- with minimap and timeline plugin -->
+ * <wavesurfer
+ *   data-url="../media/demo.wav"
+ *   data-plugins="minimap,timeline"
+ *   data-minimap-height="30"
+ *   data-minimap-wave-color="#ddd"
+ *   data-minimap-progress-color="#999"
+ *   data-timeline-font-size="13px"
+ *   data-timeline-container="#timeline"
+ * >
+ * </wavesurfer>
+ * <div id="timeline"></div>
+ *
+ * <!-- with regions plugin -->
+ * <wavesurfer
+ *   data-url="../media/demo.wav"
+ *   data-plugins="regions"
+ *   data-regions-regions='[{"start": 1,"end": 3,"color": "hsla(400, 100%, 30%, 0.5)"}]'
+ * >
+ * </wavesurfer>
+ */
+var Init =
+/*#__PURE__*/
+function () {
+  /**
+   * Instantiate Init class and initialize elements
+   *
+   * This is done automatically if `window` is defined and
+   * `window.WS_StopAutoInit` is not set to true
+   *
+   * @param {WaveSurfer} WaveSurfer The WaveSurfer library object
+   * @param {InitParams} params initialisation options
+   */
+  function Init(WaveSurfer) {
+    var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+
+    _classCallCheck(this, Init);
+
+    if (!WaveSurfer) {
+      throw new Error('WaveSurfer is not available!');
+    }
+    /**
+     * cache WaveSurfer
+     * @private
+     */
+
+
+    this.WaveSurfer = WaveSurfer;
+    /**
+     * build parameters, cache them in _params so minified builds are smaller
+     * @private
+     */
+
+    var _params = this.params = WaveSurfer.util.extend({}, {
+      // wavesurfer parameter defaults so by default the audio player is
+      // usable with native media element controls
+      defaults: {
+        backend: 'MediaElement',
+        mediaControls: true
+      },
+      // containers to instantiate on, can be selector string or NodeList
+      containers: 'wavesurfer',
+      // @TODO insert plugin CDN URIs
+      pluginCdnTemplate: '//localhost:8080/dist/plugin/wavesurfer.[name].js',
+      // loadPlugin function can be overridden to inject plugin definition
+      // objects, this default function uses load-script to load a plugin
+      // and pass it to a callback
+      loadPlugin: function loadPlugin(name, cb) {
+        var src = _params.pluginCdnTemplate.replace('[name]', name);
+
+        (0, _loadScript.default)(src, {
+          async: false
+        }, function (err, plugin) {
+          if (err) {
+            return console.error("WaveSurfer plugin ".concat(name, " not found at ").concat(src));
+          }
+
+          cb(window.WaveSurfer[name]);
+        });
+      }
+    }, params);
+    /**
+     * The nodes that should have instances attached to them
+     * @type {NodeList}
+     */
+
+
+    this.containers = typeof _params.containers == 'string' ? document.querySelectorAll(_params.containers) : _params.containers;
+    /** @private */
+
+    this.pluginCache = {};
+    /**
+     * An array of wavesurfer instances
+     * @type {Object[]}
+     */
+
+    this.instances = [];
+    this.initAllEls();
+  }
+  /**
+   * Initialize all container elements
+   */
+
+
+  _createClass(Init, [{
+    key: "initAllEls",
+    value: function initAllEls() {
+      var _this = this;
+
+      // iterate over all the container elements
+      Array.prototype.forEach.call(this.containers, function (el) {
+        // load the plugins as an array of plugin names
+        var plugins = el.dataset.plugins ? el.dataset.plugins.split(',') : []; // no plugins to be loaded, just render
+
+        if (!plugins.length) {
+          return _this.initEl(el);
+        } // âŠ or: iterate over all the plugins
+
+
+        plugins.forEach(function (name, i) {
+          // plugin is not cached already, load it
+          if (!_this.pluginCache[name]) {
+            _this.params.loadPlugin(name, function (lib) {
+              _this.pluginCache[name] = lib; // plugins were all loaded, render the element
+
+              if (i + 1 === plugins.length) {
+                _this.initEl(el, plugins);
+              }
+            });
+          } else if (i === plugins.length) {
+            // plugin was cached and this plugin was the last
+            _this.initEl(el, plugins);
+          }
+        });
+      });
+    }
+    /**
+     * Initialize a single container element and add to `this.instances`
+     *
+     * @param  {HTMLElement} el The container to instantiate wavesurfer to
+     * @param  {PluginDefinition[]} plugins An Array of plugin names to initialize with
+     * @return {Object} Wavesurfer instance
+     */
+
+  }, {
+    key: "initEl",
+    value: function initEl(el) {
+      var _this2 = this;
+
+      var plugins = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
+      var jsonRegex = /^[[|{]/; // initialize plugins with the correct options
+
+      var initialisedPlugins = plugins.map(function (plugin) {
+        var options = {}; // the regex to find this plugin attributes
+
+        var attrNameRegex = new RegExp('^' + plugin);
+        var attrName; // iterate over all the data attributes and find ones for this
+        // plugin
+
+        for (attrName in el.dataset) {
+          var regexResult = attrNameRegex.exec(attrName);
+
+          if (regexResult) {
+            var attr = el.dataset[attrName]; // if the string begins with a [ or a { parse it as JSON
+
+            var prop = jsonRegex.test(attr) ? JSON.parse(attr) : attr; // this removes the plugin prefix and changes the first letter
+            // of the resulting string to lower case to follow the naming
+            // convention of ws params
+
+            var unprefixedOptionName = attrName.slice(plugin.length, plugin.length + 1).toLowerCase() + attrName.slice(plugin.length + 1);
+            options[unprefixedOptionName] = prop;
+          }
+        }
+
+        return _this2.pluginCache[plugin].create(options);
+      }); // build parameter object for this container
+
+      var params = this.WaveSurfer.util.extend({
+        container: el
+      }, this.params.defaults, el.dataset, {
+        plugins: initialisedPlugins
+      }); // @TODO make nicer
+
+      el.style.display = 'block'; // initialize wavesurfer, load audio (with peaks if provided)
+
+      var instance = this.WaveSurfer.create(params);
+      var peaks = params.peaks ? JSON.parse(params.peaks) : undefined;
+      instance.load(params.url, peaks); // push this instance into the instances cache
+
+      this.instances.push(instance);
+      return instance;
+    }
+  }]);
+
+  return Init;
+}(); // if window object exists and window.WS_StopAutoInit is not true
+
+
+if ((typeof window === "undefined" ? "undefined" : _typeof(window)) === 'object' && !window.WS_StopAutoInit) {
+  // call init when document is ready, apply any custom default settings
+  // in window.WS_InitOptions
+  if (document.readyState === 'complete') {
+    window.WaveSurferInit = new Init(window.WaveSurfer, window.WS_InitOptions);
+  } else {
+    window.addEventListener('load', function () {
+      window.WaveSurferInit = new Init(window.WaveSurfer, window.WS_InitOptions);
+    });
+  }
+} // export init for manual usage
+
+
+var _default = Init;
+exports.default = _default;
+module.exports = exports.default;
+
+/***/ })
+
+/******/ });
+});
+//# sourceMappingURL=wavesurfer-html-init.js.map
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/wavesurfer-html-init.js.map
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/wavesurfer-html-init.js.map	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/wavesurfer-html-init.js.map	(revision 33546)
@@ -0,0 +1,1 @@
+{"version":3,"sources":["webpack://WaveSurfer.[name]/webpack/universalModuleDefinition","webpack://WaveSurfer.[name]/webpack/bootstrap","webpack://WaveSurfer.[name]/./node_modules/load-script/index.js","webpack://WaveSurfer.[name]/./src/html-init.js"],"names":["Init","WaveSurfer","params","Error","_params","util","extend","defaults","backend","mediaControls","containers","pluginCdnTemplate","loadPlugin","name","cb","src","replace","async","err","plugin","console","error","window","document","querySelectorAll","pluginCache","instances","initAllEls","Array","prototype","forEach","call","el","plugins","dataset","split","length","initEl","i","lib","jsonRegex","initialisedPlugins","map","options","attrNameRegex","RegExp","attrName","regexResult","exec","attr","prop","test","JSON","parse","unprefixedOptionName","slice","toLowerCase","create","container","style","display","instance","peaks","undefined","load","url","push","WS_StopAutoInit","readyState","WaveSurferInit","WS_InitOptions","addEventListener"],"mappings":"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","file":"wavesurfer-html-init.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"html-init\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"html-init\"] = factory();\n\telse\n\t\troot[\"WaveSurfer\"] = root[\"WaveSurfer\"] || {}, root[\"WaveSurfer\"][\"html-init\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/html-init.js\");\n","\nmodule.exports = function load (src, opts, cb) {\n  var head = document.head || document.getElementsByTagName('head')[0]\n  var script = document.createElement('script')\n\n  if (typeof opts === 'function') {\n    cb = opts\n    opts = {}\n  }\n\n  opts = opts || {}\n  cb = cb || function() {}\n\n  script.type = opts.type || 'text/javascript'\n  script.charset = opts.charset || 'utf8';\n  script.async = 'async' in opts ? !!opts.async : true\n  script.src = src\n\n  if (opts.attrs) {\n    setAttributes(script, opts.attrs)\n  }\n\n  if (opts.text) {\n    script.text = '' + opts.text\n  }\n\n  var onend = 'onload' in script ? stdOnEnd : ieOnEnd\n  onend(script, cb)\n\n  // some good legacy browsers (firefox) fail the 'in' detection above\n  // so as a fallback we always set onload\n  // old IE will ignore this and new IE will set onload\n  if (!script.onload) {\n    stdOnEnd(script, cb);\n  }\n\n  head.appendChild(script)\n}\n\nfunction setAttributes(script, attrs) {\n  for (var attr in attrs) {\n    script.setAttribute(attr, attrs[attr]);\n  }\n}\n\nfunction stdOnEnd (script, cb) {\n  script.onload = function () {\n    this.onerror = this.onload = null\n    cb(null, script)\n  }\n  script.onerror = function () {\n    // this.onload = null here is necessary\n    // because even IE9 works not like others\n    this.onerror = this.onload = null\n    cb(new Error('Failed to load ' + this.src), script)\n  }\n}\n\nfunction ieOnEnd (script, cb) {\n  script.onreadystatechange = function () {\n    if (this.readyState != 'complete' && this.readyState != 'loaded') return\n    this.onreadystatechange = null\n    cb(null, script) // there is no way to catch loading errors in IE8\n  }\n}\n","import loadScript from 'load-script';\n\n/**\n * @typedef {Object} InitParams\n * @property {WavesurferParams} [defaults={backend: 'MediaElement,\n * mediaControls: true}] The default wavesurfer initialisation parameters\n * @property {string|NodeList} containers='wavesurfer' Selector or NodeList of\n * elements to attach instances to\n * @property {string}\n * pluginCdnTemplate='//localhost:8080/dist/plugin/wavesurfer.[name].js' URL\n * template for the dynamic loading of plugins\n * @property {function} loadPlugin If set overwrites the default ajax function,\n * can be used to inject plugins differently.\n */\n/**\n * The HTML initialisation API is not part of the main library bundle file and\n * must be additionally included.\n *\n * The API attaches wavesurfer instances to all `<wavesurfer>` (can be\n * customised), parsing their `data-` attributes to construct an options object\n * for initialisation. Among other things it can dynamically load plugin code.\n *\n * The automatic initialisation can be prevented by setting the\n * `window.WS_StopAutoInit` flag to true. The `html-init[.min].js` file exports\n * the `Init` class, which can be called manually.\n *\n * Site-wide defaults can be added by setting `window.WS_InitOptions`.\n *\n * @example\n * <!-- with minimap and timeline plugin -->\n * <wavesurfer\n *   data-url=\"../media/demo.wav\"\n *   data-plugins=\"minimap,timeline\"\n *   data-minimap-height=\"30\"\n *   data-minimap-wave-color=\"#ddd\"\n *   data-minimap-progress-color=\"#999\"\n *   data-timeline-font-size=\"13px\"\n *   data-timeline-container=\"#timeline\"\n * >\n * </wavesurfer>\n * <div id=\"timeline\"></div>\n *\n * <!-- with regions plugin -->\n * <wavesurfer\n *   data-url=\"../media/demo.wav\"\n *   data-plugins=\"regions\"\n *   data-regions-regions='[{\"start\": 1,\"end\": 3,\"color\": \"hsla(400, 100%, 30%, 0.5)\"}]'\n * >\n * </wavesurfer>\n */\nclass Init {\n    /**\n     * Instantiate Init class and initialize elements\n     *\n     * This is done automatically if `window` is defined and\n     * `window.WS_StopAutoInit` is not set to true\n     *\n     * @param {WaveSurfer} WaveSurfer The WaveSurfer library object\n     * @param {InitParams} params initialisation options\n     */\n    constructor(WaveSurfer, params = {}) {\n        if (!WaveSurfer) {\n            throw new Error('WaveSurfer is not available!');\n        }\n\n        /**\n         * cache WaveSurfer\n         * @private\n         */\n        this.WaveSurfer = WaveSurfer;\n\n        /**\n         * build parameters, cache them in _params so minified builds are smaller\n         * @private\n         */\n        const _params = (this.params = WaveSurfer.util.extend(\n            {},\n            {\n                // wavesurfer parameter defaults so by default the audio player is\n                // usable with native media element controls\n                defaults: {\n                    backend: 'MediaElement',\n                    mediaControls: true\n                },\n                // containers to instantiate on, can be selector string or NodeList\n                containers: 'wavesurfer',\n                // @TODO insert plugin CDN URIs\n                pluginCdnTemplate:\n                    '//localhost:8080/dist/plugin/wavesurfer.[name].js',\n                // loadPlugin function can be overridden to inject plugin definition\n                // objects, this default function uses load-script to load a plugin\n                // and pass it to a callback\n                loadPlugin(name, cb) {\n                    const src = _params.pluginCdnTemplate.replace(\n                        '[name]',\n                        name\n                    );\n                    loadScript(src, { async: false }, (err, plugin) => {\n                        if (err) {\n                            return console.error(\n                                `WaveSurfer plugin ${name} not found at ${src}`\n                            );\n                        }\n                        cb(window.WaveSurfer[name]);\n                    });\n                }\n            },\n            params\n        ));\n        /**\n         * The nodes that should have instances attached to them\n         * @type {NodeList}\n         */\n        this.containers =\n            typeof _params.containers == 'string'\n                ? document.querySelectorAll(_params.containers)\n                : _params.containers;\n        /** @private */\n        this.pluginCache = {};\n        /**\n         * An array of wavesurfer instances\n         * @type {Object[]}\n         */\n        this.instances = [];\n\n        this.initAllEls();\n    }\n\n    /**\n     * Initialize all container elements\n     */\n    initAllEls() {\n        // iterate over all the container elements\n        Array.prototype.forEach.call(this.containers, el => {\n            // load the plugins as an array of plugin names\n            const plugins = el.dataset.plugins\n                ? el.dataset.plugins.split(',')\n                : [];\n\n            // no plugins to be loaded, just render\n            if (!plugins.length) {\n                return this.initEl(el);\n            }\n            // âŠ or: iterate over all the plugins\n            plugins.forEach((name, i) => {\n                // plugin is not cached already, load it\n                if (!this.pluginCache[name]) {\n                    this.params.loadPlugin(name, lib => {\n                        this.pluginCache[name] = lib;\n                        // plugins were all loaded, render the element\n                        if (i + 1 === plugins.length) {\n                            this.initEl(el, plugins);\n                        }\n                    });\n                } else if (i === plugins.length) {\n                    // plugin was cached and this plugin was the last\n                    this.initEl(el, plugins);\n                }\n            });\n        });\n    }\n\n    /**\n     * Initialize a single container element and add to `this.instances`\n     *\n     * @param  {HTMLElement} el The container to instantiate wavesurfer to\n     * @param  {PluginDefinition[]} plugins An Array of plugin names to initialize with\n     * @return {Object} Wavesurfer instance\n     */\n    initEl(el, plugins = []) {\n        const jsonRegex = /^[[|{]/;\n        // initialize plugins with the correct options\n        const initialisedPlugins = plugins.map(plugin => {\n            const options = {};\n            // the regex to find this plugin attributes\n            const attrNameRegex = new RegExp('^' + plugin);\n            let attrName;\n            // iterate over all the data attributes and find ones for this\n            // plugin\n            for (attrName in el.dataset) {\n                const regexResult = attrNameRegex.exec(attrName);\n                if (regexResult) {\n                    const attr = el.dataset[attrName];\n                    // if the string begins with a [ or a { parse it as JSON\n                    const prop = jsonRegex.test(attr) ? JSON.parse(attr) : attr;\n                    // this removes the plugin prefix and changes the first letter\n                    // of the resulting string to lower case to follow the naming\n                    // convention of ws params\n                    const unprefixedOptionName =\n                        attrName\n                            .slice(plugin.length, plugin.length + 1)\n                            .toLowerCase() + attrName.slice(plugin.length + 1);\n                    options[unprefixedOptionName] = prop;\n                }\n            }\n            return this.pluginCache[plugin].create(options);\n        });\n        // build parameter object for this container\n        const params = this.WaveSurfer.util.extend(\n            { container: el },\n            this.params.defaults,\n            el.dataset,\n            { plugins: initialisedPlugins }\n        );\n\n        // @TODO make nicer\n        el.style.display = 'block';\n\n        // initialize wavesurfer, load audio (with peaks if provided)\n        const instance = this.WaveSurfer.create(params);\n        const peaks = params.peaks ? JSON.parse(params.peaks) : undefined;\n        instance.load(params.url, peaks);\n\n        // push this instance into the instances cache\n        this.instances.push(instance);\n        return instance;\n    }\n}\n\n// if window object exists and window.WS_StopAutoInit is not true\nif (typeof window === 'object' && !window.WS_StopAutoInit) {\n    // call init when document is ready, apply any custom default settings\n    // in window.WS_InitOptions\n    if (document.readyState === 'complete') {\n        window.WaveSurferInit = new Init(\n            window.WaveSurfer,\n            window.WS_InitOptions\n        );\n    } else {\n        window.addEventListener('load', () => {\n            window.WaveSurferInit = new Init(\n                window.WaveSurfer,\n                window.WS_InitOptions\n            );\n        });\n    }\n}\n\n// export init for manual usage\nexport default Init;\n"],"sourceRoot":""}
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/wavesurfer-html-init.min.js
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/wavesurfer-html-init.min.js	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/wavesurfer-html-init.min.js	(revision 33546)
@@ -0,0 +1,2 @@
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("html-init",[],t):"object"==typeof exports?exports["html-init"]=t():(e.WaveSurfer=e.WaveSurfer||{},e.WaveSurfer["html-init"]=t())}(window,(function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var r,o=(r=n(1))&&r.__esModule?r:{default:r};function i(e){return(i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function a(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}var u=function(){function e(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),!t)throw new Error("WaveSurfer is not available!");this.WaveSurfer=t;var r=this.params=t.util.extend({},{defaults:{backend:"MediaElement",mediaControls:!0},containers:"wavesurfer",pluginCdnTemplate:"//localhost:8080/dist/plugin/wavesurfer.[name].js",loadPlugin:function(e,t){var n=r.pluginCdnTemplate.replace("[name]",e);(0,o.default)(n,{async:!1},(function(r,o){if(r)return console.error("WaveSurfer plugin ".concat(e," not found at ").concat(n));t(window.WaveSurfer[e])}))}},n);this.containers="string"==typeof r.containers?document.querySelectorAll(r.containers):r.containers,this.pluginCache={},this.instances=[],this.initAllEls()}var t,n,r;return t=e,(n=[{key:"initAllEls",value:function(){var e=this;Array.prototype.forEach.call(this.containers,(function(t){var n=t.dataset.plugins?t.dataset.plugins.split(","):[];if(!n.length)return e.initEl(t);n.forEach((function(r,o){e.pluginCache[r]?o===n.length&&e.initEl(t,n):e.params.loadPlugin(r,(function(i){e.pluginCache[r]=i,o+1===n.length&&e.initEl(t,n)}))}))}))}},{key:"initEl",value:function(e){var t=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],r=/^[[|{]/,o=n.map((function(n){var o,i={},a=new RegExp("^"+n);for(o in e.dataset)if(a.exec(o)){var u=e.dataset[o],l=r.test(u)?JSON.parse(u):u;i[o.slice(n.length,n.length+1).toLowerCase()+o.slice(n.length+1)]=l}return t.pluginCache[n].create(i)})),i=this.WaveSurfer.util.extend({container:e},this.params.defaults,e.dataset,{plugins:o});e.style.display="block";var a=this.WaveSurfer.create(i),u=i.peaks?JSON.parse(i.peaks):void 0;return a.load(i.url,u),this.instances.push(a),a}}])&&a(t.prototype,n),r&&a(t,r),e}();"object"!==("undefined"==typeof window?"undefined":i(window))||window.WS_StopAutoInit||("complete"===document.readyState?window.WaveSurferInit=new u(window.WaveSurfer,window.WS_InitOptions):window.addEventListener("load",(function(){window.WaveSurferInit=new u(window.WaveSurfer,window.WS_InitOptions)})));var l=u;t.default=l,e.exports=t.default},function(e,t){function n(e,t){e.onload=function(){this.onerror=this.onload=null,t(null,e)},e.onerror=function(){this.onerror=this.onload=null,t(new Error("Failed to load "+this.src),e)}}function r(e,t){e.onreadystatechange=function(){"complete"!=this.readyState&&"loaded"!=this.readyState||(this.onreadystatechange=null,t(null,e))}}e.exports=function(e,t,o){var i=document.head||document.getElementsByTagName("head")[0],a=document.createElement("script");"function"==typeof t&&(o=t,t={}),t=t||{},o=o||function(){},a.type=t.type||"text/javascript",a.charset=t.charset||"utf8",a.async=!("async"in t)||!!t.async,a.src=e,t.attrs&&function(e,t){for(var n in t)e.setAttribute(n,t[n])}(a,t.attrs),t.text&&(a.text=""+t.text),("onload"in a?n:r)(a,o),a.onload||n(a,o),i.appendChild(a)}}])}));
+//# sourceMappingURL=wavesurfer-html-init.min.js.map
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/wavesurfer-html-init.min.js.map
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/wavesurfer-html-init.min.js.map	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/wavesurfer-html-init.min.js.map	(revision 33546)
@@ -0,0 +1,1 @@
+{"version":3,"sources":["webpack://WaveSurfer.[name]/webpack/universalModuleDefinition","webpack://WaveSurfer.[name]/webpack/bootstrap","webpack://WaveSurfer.[name]/./src/html-init.js","webpack://WaveSurfer.[name]/./node_modules/load-script/index.js"],"names":["root","factory","exports","module","define","amd","window","installedModules","__webpack_require__","moduleId","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","Init","WaveSurfer","params","Error","this","_params","util","extend","defaults","backend","mediaControls","containers","pluginCdnTemplate","loadPlugin","cb","src","replace","async","err","plugin","console","error","document","querySelectorAll","pluginCache","instances","initAllEls","Array","forEach","el","plugins","dataset","split","length","initEl","lib","jsonRegex","initialisedPlugins","map","attrName","options","attrNameRegex","RegExp","exec","attr","prop","test","JSON","parse","slice","toLowerCase","container","style","display","instance","peaks","undefined","load","url","push","WS_StopAutoInit","readyState","WaveSurferInit","WS_InitOptions","addEventListener","stdOnEnd","script","onload","onerror","ieOnEnd","onreadystatechange","opts","head","getElementsByTagName","createElement","type","charset","attrs","setAttribute","setAttributes","text","appendChild"],"mappings":"CAAA,SAA2CA,EAAMC,GAC1B,iBAAZC,SAA0C,iBAAXC,OACxCA,OAAOD,QAAUD,IACQ,mBAAXG,QAAyBA,OAAOC,IAC9CD,OAAO,YAAa,GAAIH,GACE,iBAAZC,QACdA,QAAQ,aAAeD,KAEvBD,EAAiB,WAAIA,EAAiB,YAAK,GAAIA,EAAiB,WAAE,aAAeC,KARnF,CASGK,QAAQ,WACX,O,YCTE,IAAIC,EAAmB,GAGvB,SAASC,EAAoBC,GAG5B,GAAGF,EAAiBE,GACnB,OAAOF,EAAiBE,GAAUP,QAGnC,IAAIC,EAASI,EAAiBE,GAAY,CACzCC,EAAGD,EACHE,GAAG,EACHT,QAAS,IAUV,OANAU,EAAQH,GAAUI,KAAKV,EAAOD,QAASC,EAAQA,EAAOD,QAASM,GAG/DL,EAAOQ,GAAI,EAGJR,EAAOD,QA0Df,OArDAM,EAAoBM,EAAIF,EAGxBJ,EAAoBO,EAAIR,EAGxBC,EAAoBQ,EAAI,SAASd,EAASe,EAAMC,GAC3CV,EAAoBW,EAAEjB,EAASe,IAClCG,OAAOC,eAAenB,EAASe,EAAM,CAAEK,YAAY,EAAMC,IAAKL,KAKhEV,EAAoBgB,EAAI,SAAStB,GACX,oBAAXuB,QAA0BA,OAAOC,aAC1CN,OAAOC,eAAenB,EAASuB,OAAOC,YAAa,CAAEC,MAAO,WAE7DP,OAAOC,eAAenB,EAAS,aAAc,CAAEyB,OAAO,KAQvDnB,EAAoBoB,EAAI,SAASD,EAAOE,GAEvC,GADU,EAAPA,IAAUF,EAAQnB,EAAoBmB,IAC/B,EAAPE,EAAU,OAAOF,EACpB,GAAW,EAAPE,GAA8B,iBAAVF,GAAsBA,GAASA,EAAMG,WAAY,OAAOH,EAChF,IAAII,EAAKX,OAAOY,OAAO,MAGvB,GAFAxB,EAAoBgB,EAAEO,GACtBX,OAAOC,eAAeU,EAAI,UAAW,CAAET,YAAY,EAAMK,MAAOA,IACtD,EAAPE,GAA4B,iBAATF,EAAmB,IAAI,IAAIM,KAAON,EAAOnB,EAAoBQ,EAAEe,EAAIE,EAAK,SAASA,GAAO,OAAON,EAAMM,IAAQC,KAAK,KAAMD,IAC9I,OAAOF,GAIRvB,EAAoB2B,EAAI,SAAShC,GAChC,IAAIe,EAASf,GAAUA,EAAO2B,WAC7B,WAAwB,OAAO3B,EAAgB,SAC/C,WAA8B,OAAOA,GAEtC,OADAK,EAAoBQ,EAAEE,EAAQ,IAAKA,GAC5BA,GAIRV,EAAoBW,EAAI,SAASiB,EAAQC,GAAY,OAAOjB,OAAOkB,UAAUC,eAAe1B,KAAKuB,EAAQC,IAGzG7B,EAAoBgC,EAAI,GAIjBhC,EAAoBA,EAAoBiC,EAAI,G,iGClFrD,I,EAAA,G,EAAA,O,0aAkDMC,E,WAUF,WAAYC,GAAyB,IAAbC,EAAa,uDAAJ,GAC7B,G,4FADiC,UAC5BD,EACD,MAAM,IAAIE,MAAM,gCAOpBC,KAAKH,WAAaA,EAMlB,IAAMI,EAAWD,KAAKF,OAASD,EAAWK,KAAKC,OAC3C,GACA,CAGIC,SAAU,CACNC,QAAS,eACTC,eAAe,GAGnBC,WAAY,aAEZC,kBACI,oDAIJC,WAfJ,SAeetC,EAAMuC,GACb,IAAMC,EAAMV,EAAQO,kBAAkBI,QAClC,SACAzC,IAEJ,aAAWwC,EAAK,CAAEE,OAAO,IAAS,SAACC,EAAKC,GACpC,GAAID,EACA,OAAOE,QAAQC,MAAR,4BACkB9C,EADlB,yBACuCwC,IAGlDD,EAAGlD,OAAOqC,WAAW1B,SAIjC2B,GAMJE,KAAKO,WAC4B,iBAAtBN,EAAQM,WACTW,SAASC,iBAAiBlB,EAAQM,YAClCN,EAAQM,WAElBP,KAAKoB,YAAc,GAKnBpB,KAAKqB,UAAY,GAEjBrB,KAAKsB,a,4DAMI,WAETC,MAAM/B,UAAUgC,QAAQzD,KAAKiC,KAAKO,YAAY,SAAAkB,GAE1C,IAAMC,EAAUD,EAAGE,QAAQD,QACrBD,EAAGE,QAAQD,QAAQE,MAAM,KACzB,GAGN,IAAKF,EAAQG,OACT,OAAO,EAAKC,OAAOL,GAGvBC,EAAQF,SAAQ,SAACrD,EAAMP,GAEd,EAAKwD,YAAYjD,GAQXP,IAAM8D,EAAQG,QAErB,EAAKC,OAAOL,EAAIC,GAThB,EAAK5B,OAAOW,WAAWtC,GAAM,SAAA4D,GACzB,EAAKX,YAAYjD,GAAQ4D,EAErBnE,EAAI,IAAM8D,EAAQG,QAClB,EAAKC,OAAOL,EAAIC,c,6BAkBjCD,GAAkB,WAAdC,EAAc,uDAAJ,GACXM,EAAY,SAEZC,EAAqBP,EAAQQ,KAAI,SAAAnB,GACnC,IAGIoB,EAHEC,EAAU,GAEVC,EAAgB,IAAIC,OAAO,IAAMvB,GAIvC,IAAKoB,KAAYV,EAAGE,QAEhB,GADoBU,EAAcE,KAAKJ,GACtB,CACb,IAAMK,EAAOf,EAAGE,QAAQQ,GAElBM,EAAOT,EAAUU,KAAKF,GAAQG,KAAKC,MAAMJ,GAAQA,EAQvDJ,EAHID,EACKU,MAAM9B,EAAOc,OAAQd,EAAOc,OAAS,GACrCiB,cAAgBX,EAASU,MAAM9B,EAAOc,OAAS,IACxBY,EAGxC,OAAO,EAAKrB,YAAYL,GAAQ7B,OAAOkD,MAGrCtC,EAASE,KAAKH,WAAWK,KAAKC,OAChC,CAAE4C,UAAWtB,GACbzB,KAAKF,OAAOM,SACZqB,EAAGE,QACH,CAAED,QAASO,IAIfR,EAAGuB,MAAMC,QAAU,QAGnB,IAAMC,EAAWlD,KAAKH,WAAWX,OAAOY,GAClCqD,EAAQrD,EAAOqD,MAAQR,KAAKC,MAAM9C,EAAOqD,YAASC,EAKxD,OAJAF,EAASG,KAAKvD,EAAOwD,IAAKH,GAG1BnD,KAAKqB,UAAUkC,KAAKL,GACbA,O,gCAKO,YAAlB,oBAAO1F,OAAP,cAAOA,UAAwBA,OAAOgG,kBAGV,aAAxBtC,SAASuC,WACTjG,OAAOkG,eAAiB,IAAI9D,EACxBpC,OAAOqC,WACPrC,OAAOmG,gBAGXnG,OAAOoG,iBAAiB,QAAQ,WAC5BpG,OAAOkG,eAAiB,IAAI9D,EACxBpC,OAAOqC,WACPrC,OAAOmG,oB,MAOR/D,E,+CClMf,SAASiE,EAAUC,EAAQpD,GACzBoD,EAAOC,OAAS,WACd/D,KAAKgE,QAAUhE,KAAK+D,OAAS,KAC7BrD,EAAG,KAAMoD,IAEXA,EAAOE,QAAU,WAGfhE,KAAKgE,QAAUhE,KAAK+D,OAAS,KAC7BrD,EAAG,IAAIX,MAAM,kBAAoBC,KAAKW,KAAMmD,IAIhD,SAASG,EAASH,EAAQpD,GACxBoD,EAAOI,mBAAqB,WACH,YAAnBlE,KAAKyD,YAA+C,UAAnBzD,KAAKyD,aAC1CzD,KAAKkE,mBAAqB,KAC1BxD,EAAG,KAAMoD,KA7DbzG,EAAOD,QAAU,SAAeuD,EAAKwD,EAAMzD,GACzC,IAAI0D,EAAOlD,SAASkD,MAAQlD,SAASmD,qBAAqB,QAAQ,GAC9DP,EAAS5C,SAASoD,cAAc,UAEhB,mBAATH,IACTzD,EAAKyD,EACLA,EAAO,IAGTA,EAAOA,GAAQ,GACfzD,EAAKA,GAAM,aAEXoD,EAAOS,KAAOJ,EAAKI,MAAQ,kBAC3BT,EAAOU,QAAUL,EAAKK,SAAW,OACjCV,EAAOjD,QAAQ,UAAWsD,MAASA,EAAKtD,MACxCiD,EAAOnD,IAAMA,EAETwD,EAAKM,OAqBX,SAAuBX,EAAQW,GAC7B,IAAK,IAAIjC,KAAQiC,EACfX,EAAOY,aAAalC,EAAMiC,EAAMjC,IAtBhCmC,CAAcb,EAAQK,EAAKM,OAGzBN,EAAKS,OACPd,EAAOc,KAAO,GAAKT,EAAKS,OAGd,WAAYd,EAASD,EAAWI,GACtCH,EAAQpD,GAKToD,EAAOC,QACVF,EAASC,EAAQpD,GAGnB0D,EAAKS,YAAYf","file":"wavesurfer-html-init.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"html-init\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"html-init\"] = factory();\n\telse\n\t\troot[\"WaveSurfer\"] = root[\"WaveSurfer\"] || {}, root[\"WaveSurfer\"][\"html-init\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n","import loadScript from 'load-script';\n\n/**\n * @typedef {Object} InitParams\n * @property {WavesurferParams} [defaults={backend: 'MediaElement,\n * mediaControls: true}] The default wavesurfer initialisation parameters\n * @property {string|NodeList} containers='wavesurfer' Selector or NodeList of\n * elements to attach instances to\n * @property {string}\n * pluginCdnTemplate='//localhost:8080/dist/plugin/wavesurfer.[name].js' URL\n * template for the dynamic loading of plugins\n * @property {function} loadPlugin If set overwrites the default ajax function,\n * can be used to inject plugins differently.\n */\n/**\n * The HTML initialisation API is not part of the main library bundle file and\n * must be additionally included.\n *\n * The API attaches wavesurfer instances to all `<wavesurfer>` (can be\n * customised), parsing their `data-` attributes to construct an options object\n * for initialisation. Among other things it can dynamically load plugin code.\n *\n * The automatic initialisation can be prevented by setting the\n * `window.WS_StopAutoInit` flag to true. The `html-init[.min].js` file exports\n * the `Init` class, which can be called manually.\n *\n * Site-wide defaults can be added by setting `window.WS_InitOptions`.\n *\n * @example\n * <!-- with minimap and timeline plugin -->\n * <wavesurfer\n *   data-url=\"../media/demo.wav\"\n *   data-plugins=\"minimap,timeline\"\n *   data-minimap-height=\"30\"\n *   data-minimap-wave-color=\"#ddd\"\n *   data-minimap-progress-color=\"#999\"\n *   data-timeline-font-size=\"13px\"\n *   data-timeline-container=\"#timeline\"\n * >\n * </wavesurfer>\n * <div id=\"timeline\"></div>\n *\n * <!-- with regions plugin -->\n * <wavesurfer\n *   data-url=\"../media/demo.wav\"\n *   data-plugins=\"regions\"\n *   data-regions-regions='[{\"start\": 1,\"end\": 3,\"color\": \"hsla(400, 100%, 30%, 0.5)\"}]'\n * >\n * </wavesurfer>\n */\nclass Init {\n    /**\n     * Instantiate Init class and initialize elements\n     *\n     * This is done automatically if `window` is defined and\n     * `window.WS_StopAutoInit` is not set to true\n     *\n     * @param {WaveSurfer} WaveSurfer The WaveSurfer library object\n     * @param {InitParams} params initialisation options\n     */\n    constructor(WaveSurfer, params = {}) {\n        if (!WaveSurfer) {\n            throw new Error('WaveSurfer is not available!');\n        }\n\n        /**\n         * cache WaveSurfer\n         * @private\n         */\n        this.WaveSurfer = WaveSurfer;\n\n        /**\n         * build parameters, cache them in _params so minified builds are smaller\n         * @private\n         */\n        const _params = (this.params = WaveSurfer.util.extend(\n            {},\n            {\n                // wavesurfer parameter defaults so by default the audio player is\n                // usable with native media element controls\n                defaults: {\n                    backend: 'MediaElement',\n                    mediaControls: true\n                },\n                // containers to instantiate on, can be selector string or NodeList\n                containers: 'wavesurfer',\n                // @TODO insert plugin CDN URIs\n                pluginCdnTemplate:\n                    '//localhost:8080/dist/plugin/wavesurfer.[name].js',\n                // loadPlugin function can be overridden to inject plugin definition\n                // objects, this default function uses load-script to load a plugin\n                // and pass it to a callback\n                loadPlugin(name, cb) {\n                    const src = _params.pluginCdnTemplate.replace(\n                        '[name]',\n                        name\n                    );\n                    loadScript(src, { async: false }, (err, plugin) => {\n                        if (err) {\n                            return console.error(\n                                `WaveSurfer plugin ${name} not found at ${src}`\n                            );\n                        }\n                        cb(window.WaveSurfer[name]);\n                    });\n                }\n            },\n            params\n        ));\n        /**\n         * The nodes that should have instances attached to them\n         * @type {NodeList}\n         */\n        this.containers =\n            typeof _params.containers == 'string'\n                ? document.querySelectorAll(_params.containers)\n                : _params.containers;\n        /** @private */\n        this.pluginCache = {};\n        /**\n         * An array of wavesurfer instances\n         * @type {Object[]}\n         */\n        this.instances = [];\n\n        this.initAllEls();\n    }\n\n    /**\n     * Initialize all container elements\n     */\n    initAllEls() {\n        // iterate over all the container elements\n        Array.prototype.forEach.call(this.containers, el => {\n            // load the plugins as an array of plugin names\n            const plugins = el.dataset.plugins\n                ? el.dataset.plugins.split(',')\n                : [];\n\n            // no plugins to be loaded, just render\n            if (!plugins.length) {\n                return this.initEl(el);\n            }\n            // âŠ or: iterate over all the plugins\n            plugins.forEach((name, i) => {\n                // plugin is not cached already, load it\n                if (!this.pluginCache[name]) {\n                    this.params.loadPlugin(name, lib => {\n                        this.pluginCache[name] = lib;\n                        // plugins were all loaded, render the element\n                        if (i + 1 === plugins.length) {\n                            this.initEl(el, plugins);\n                        }\n                    });\n                } else if (i === plugins.length) {\n                    // plugin was cached and this plugin was the last\n                    this.initEl(el, plugins);\n                }\n            });\n        });\n    }\n\n    /**\n     * Initialize a single container element and add to `this.instances`\n     *\n     * @param  {HTMLElement} el The container to instantiate wavesurfer to\n     * @param  {PluginDefinition[]} plugins An Array of plugin names to initialize with\n     * @return {Object} Wavesurfer instance\n     */\n    initEl(el, plugins = []) {\n        const jsonRegex = /^[[|{]/;\n        // initialize plugins with the correct options\n        const initialisedPlugins = plugins.map(plugin => {\n            const options = {};\n            // the regex to find this plugin attributes\n            const attrNameRegex = new RegExp('^' + plugin);\n            let attrName;\n            // iterate over all the data attributes and find ones for this\n            // plugin\n            for (attrName in el.dataset) {\n                const regexResult = attrNameRegex.exec(attrName);\n                if (regexResult) {\n                    const attr = el.dataset[attrName];\n                    // if the string begins with a [ or a { parse it as JSON\n                    const prop = jsonRegex.test(attr) ? JSON.parse(attr) : attr;\n                    // this removes the plugin prefix and changes the first letter\n                    // of the resulting string to lower case to follow the naming\n                    // convention of ws params\n                    const unprefixedOptionName =\n                        attrName\n                            .slice(plugin.length, plugin.length + 1)\n                            .toLowerCase() + attrName.slice(plugin.length + 1);\n                    options[unprefixedOptionName] = prop;\n                }\n            }\n            return this.pluginCache[plugin].create(options);\n        });\n        // build parameter object for this container\n        const params = this.WaveSurfer.util.extend(\n            { container: el },\n            this.params.defaults,\n            el.dataset,\n            { plugins: initialisedPlugins }\n        );\n\n        // @TODO make nicer\n        el.style.display = 'block';\n\n        // initialize wavesurfer, load audio (with peaks if provided)\n        const instance = this.WaveSurfer.create(params);\n        const peaks = params.peaks ? JSON.parse(params.peaks) : undefined;\n        instance.load(params.url, peaks);\n\n        // push this instance into the instances cache\n        this.instances.push(instance);\n        return instance;\n    }\n}\n\n// if window object exists and window.WS_StopAutoInit is not true\nif (typeof window === 'object' && !window.WS_StopAutoInit) {\n    // call init when document is ready, apply any custom default settings\n    // in window.WS_InitOptions\n    if (document.readyState === 'complete') {\n        window.WaveSurferInit = new Init(\n            window.WaveSurfer,\n            window.WS_InitOptions\n        );\n    } else {\n        window.addEventListener('load', () => {\n            window.WaveSurferInit = new Init(\n                window.WaveSurfer,\n                window.WS_InitOptions\n            );\n        });\n    }\n}\n\n// export init for manual usage\nexport default Init;\n","\nmodule.exports = function load (src, opts, cb) {\n  var head = document.head || document.getElementsByTagName('head')[0]\n  var script = document.createElement('script')\n\n  if (typeof opts === 'function') {\n    cb = opts\n    opts = {}\n  }\n\n  opts = opts || {}\n  cb = cb || function() {}\n\n  script.type = opts.type || 'text/javascript'\n  script.charset = opts.charset || 'utf8';\n  script.async = 'async' in opts ? !!opts.async : true\n  script.src = src\n\n  if (opts.attrs) {\n    setAttributes(script, opts.attrs)\n  }\n\n  if (opts.text) {\n    script.text = '' + opts.text\n  }\n\n  var onend = 'onload' in script ? stdOnEnd : ieOnEnd\n  onend(script, cb)\n\n  // some good legacy browsers (firefox) fail the 'in' detection above\n  // so as a fallback we always set onload\n  // old IE will ignore this and new IE will set onload\n  if (!script.onload) {\n    stdOnEnd(script, cb);\n  }\n\n  head.appendChild(script)\n}\n\nfunction setAttributes(script, attrs) {\n  for (var attr in attrs) {\n    script.setAttribute(attr, attrs[attr]);\n  }\n}\n\nfunction stdOnEnd (script, cb) {\n  script.onload = function () {\n    this.onerror = this.onload = null\n    cb(null, script)\n  }\n  script.onerror = function () {\n    // this.onload = null here is necessary\n    // because even IE9 works not like others\n    this.onerror = this.onload = null\n    cb(new Error('Failed to load ' + this.src), script)\n  }\n}\n\nfunction ieOnEnd (script, cb) {\n  script.onreadystatechange = function () {\n    if (this.readyState != 'complete' && this.readyState != 'loaded') return\n    this.onreadystatechange = null\n    cb(null, script) // there is no way to catch loading errors in IE8\n  }\n}\n"],"sourceRoot":""}
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/wavesurfer.js
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/wavesurfer.js	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/wavesurfer.js	(revision 33546)
@@ -0,0 +1,5204 @@
+/*!
+ * wavesurfer.js 2.2.1 (2019-09-30)
+ * https://github.com/katspaugh/wavesurfer.js
+ * @license BSD-3-Clause
+ */
+(function webpackUniversalModuleDefinition(root, factory) {
+	if(typeof exports === 'object' && typeof module === 'object')
+		module.exports = factory();
+	else if(typeof define === 'function' && define.amd)
+		define("WaveSurfer", [], factory);
+	else if(typeof exports === 'object')
+		exports["WaveSurfer"] = factory();
+	else
+		root["WaveSurfer"] = factory();
+})(window, function() {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+/******/
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId]) {
+/******/ 			return installedModules[moduleId].exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			i: moduleId,
+/******/ 			l: false,
+/******/ 			exports: {}
+/******/ 		};
+/******/
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ 		// Flag the module as loaded
+/******/ 		module.l = true;
+/******/
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/
+/******/
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+/******/
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+/******/
+/******/ 	// define getter function for harmony exports
+/******/ 	__webpack_require__.d = function(exports, name, getter) {
+/******/ 		if(!__webpack_require__.o(exports, name)) {
+/******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
+/******/ 		}
+/******/ 	};
+/******/
+/******/ 	// define __esModule on exports
+/******/ 	__webpack_require__.r = function(exports) {
+/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ 		}
+/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
+/******/ 	};
+/******/
+/******/ 	// create a fake namespace object
+/******/ 	// mode & 1: value is a module id, require it
+/******/ 	// mode & 2: merge all properties of value into the ns
+/******/ 	// mode & 4: return value when already ns object
+/******/ 	// mode & 8|1: behave like require
+/******/ 	__webpack_require__.t = function(value, mode) {
+/******/ 		if(mode & 1) value = __webpack_require__(value);
+/******/ 		if(mode & 8) return value;
+/******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
+/******/ 		var ns = Object.create(null);
+/******/ 		__webpack_require__.r(ns);
+/******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
+/******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
+/******/ 		return ns;
+/******/ 	};
+/******/
+/******/ 	// getDefaultExport function for compatibility with non-harmony modules
+/******/ 	__webpack_require__.n = function(module) {
+/******/ 		var getter = module && module.__esModule ?
+/******/ 			function getDefault() { return module['default']; } :
+/******/ 			function getModuleExports() { return module; };
+/******/ 		__webpack_require__.d(getter, 'a', getter);
+/******/ 		return getter;
+/******/ 	};
+/******/
+/******/ 	// Object.prototype.hasOwnProperty.call
+/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "";
+/******/
+/******/
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(__webpack_require__.s = "./src/wavesurfer.js");
+/******/ })
+/************************************************************************/
+/******/ ({
+
+/***/ "./node_modules/debounce/index.js":
+/*!****************************************!*\
+  !*** ./node_modules/debounce/index.js ***!
+  \****************************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+/**
+ * Returns a function, that, as long as it continues to be invoked, will not
+ * be triggered. The function will be called after it stops being called for
+ * N milliseconds. If `immediate` is passed, trigger the function on the
+ * leading edge, instead of the trailing. The function also has a property 'clear' 
+ * that is a function which will clear the timer to prevent previously scheduled executions. 
+ *
+ * @source underscore.js
+ * @see http://unscriptable.com/2009/03/20/debouncing-javascript-methods/
+ * @param {Function} function to wrap
+ * @param {Number} timeout in ms (`100`)
+ * @param {Boolean} whether to execute at the beginning (`false`)
+ * @api public
+ */
+function debounce(func, wait, immediate){
+  var timeout, args, context, timestamp, result;
+  if (null == wait) wait = 100;
+
+  function later() {
+    var last = Date.now() - timestamp;
+
+    if (last < wait && last >= 0) {
+      timeout = setTimeout(later, wait - last);
+    } else {
+      timeout = null;
+      if (!immediate) {
+        result = func.apply(context, args);
+        context = args = null;
+      }
+    }
+  };
+
+  var debounced = function(){
+    context = this;
+    args = arguments;
+    timestamp = Date.now();
+    var callNow = immediate && !timeout;
+    if (!timeout) timeout = setTimeout(later, wait);
+    if (callNow) {
+      result = func.apply(context, args);
+      context = args = null;
+    }
+
+    return result;
+  };
+
+  debounced.clear = function() {
+    if (timeout) {
+      clearTimeout(timeout);
+      timeout = null;
+    }
+  };
+  
+  debounced.flush = function() {
+    if (timeout) {
+      result = func.apply(context, args);
+      context = args = null;
+      
+      clearTimeout(timeout);
+      timeout = null;
+    }
+  };
+
+  return debounced;
+};
+
+// Adds compatibility for ES modules
+debounce.debounce = debounce;
+
+module.exports = debounce;
+
+
+/***/ }),
+
+/***/ "./src/drawer.js":
+/*!***********************!*\
+  !*** ./src/drawer.js ***!
+  \***********************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var util = _interopRequireWildcard(__webpack_require__(/*! ./util */ "./src/util/index.js"));
+
+function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; if (obj != null) { 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; }
+
+function _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); }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
+
+function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
+
+function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
+
+function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
+
+/**
+ * Parent class for renderers
+ *
+ * @extends {Observer}
+ */
+var Drawer =
+/*#__PURE__*/
+function (_util$Observer) {
+  _inherits(Drawer, _util$Observer);
+
+  /**
+   * @param {HTMLElement} container The container node of the wavesurfer instance
+   * @param {WavesurferParams} params The wavesurfer initialisation options
+   */
+  function Drawer(container, params) {
+    var _this;
+
+    _classCallCheck(this, Drawer);
+
+    _this = _possibleConstructorReturn(this, _getPrototypeOf(Drawer).call(this));
+    /** @private */
+
+    _this.container = container;
+    /**
+     * @type {WavesurferParams}
+     * @private
+     */
+
+    _this.params = params;
+    /**
+     * The width of the renderer
+     * @type {number}
+     */
+
+    _this.width = 0;
+    /**
+     * The height of the renderer
+     * @type {number}
+     */
+
+    _this.height = params.height * _this.params.pixelRatio;
+    /** @private */
+
+    _this.lastPos = 0;
+    /**
+     * The `<wave>` element which is added to the container
+     * @type {HTMLElement}
+     */
+
+    _this.wrapper = null;
+    return _this;
+  }
+  /**
+   * Alias of `util.style`
+   *
+   * @param {HTMLElement} el The element that the styles will be applied to
+   * @param {Object} styles The map of propName: attribute, both are used as-is
+   * @return {HTMLElement} el
+   */
+
+
+  _createClass(Drawer, [{
+    key: "style",
+    value: function style(el, styles) {
+      return util.style(el, styles);
+    }
+    /**
+     * Create the wrapper `<wave>` element, style it and set up the events for
+     * interaction
+     */
+
+  }, {
+    key: "createWrapper",
+    value: function createWrapper() {
+      this.wrapper = this.container.appendChild(document.createElement('wave'));
+      this.style(this.wrapper, {
+        display: 'block',
+        position: 'relative',
+        userSelect: 'none',
+        webkitUserSelect: 'none',
+        height: this.params.height + 'px'
+      });
+
+      if (this.params.fillParent || this.params.scrollParent) {
+        this.style(this.wrapper, {
+          width: '100%',
+          overflowX: this.params.hideScrollbar ? 'hidden' : 'auto',
+          overflowY: 'hidden'
+        });
+      }
+
+      this.setupWrapperEvents();
+    }
+    /**
+     * Handle click event
+     *
+     * @param {Event} e Click event
+     * @param {?boolean} noPrevent Set to true to not call `e.preventDefault()`
+     * @return {number} Playback position from 0 to 1
+     */
+
+  }, {
+    key: "handleEvent",
+    value: function handleEvent(e, noPrevent) {
+      !noPrevent && e.preventDefault();
+      var clientX = e.targetTouches ? e.targetTouches[0].clientX : e.clientX;
+      var bbox = this.wrapper.getBoundingClientRect();
+      var nominalWidth = this.width;
+      var parentWidth = this.getWidth();
+      var progress;
+
+      if (!this.params.fillParent && nominalWidth < parentWidth) {
+        progress = (this.params.rtl ? bbox.right - clientX : clientX - bbox.left) * (this.params.pixelRatio / nominalWidth) || 0;
+
+        if (progress > 1) {
+          progress = 1;
+        }
+      } else {
+        progress = ((this.params.rtl ? bbox.right - clientX : clientX - bbox.left) + this.wrapper.scrollLeft) / this.wrapper.scrollWidth || 0;
+      }
+
+      return progress;
+    }
+    /**
+     * @private
+     */
+
+  }, {
+    key: "setupWrapperEvents",
+    value: function setupWrapperEvents() {
+      var _this2 = this;
+
+      this.wrapper.addEventListener('click', function (e) {
+        var scrollbarHeight = _this2.wrapper.offsetHeight - _this2.wrapper.clientHeight;
+
+        if (scrollbarHeight != 0) {
+          // scrollbar is visible.  Check if click was on it
+          var bbox = _this2.wrapper.getBoundingClientRect();
+
+          if (e.clientY >= bbox.bottom - scrollbarHeight) {
+            // ignore mousedown as it was on the scrollbar
+            return;
+          }
+        }
+
+        if (_this2.params.interact) {
+          _this2.fireEvent('click', e, _this2.handleEvent(e));
+        }
+      });
+      this.wrapper.addEventListener('scroll', function (e) {
+        return _this2.fireEvent('scroll', e);
+      });
+    }
+    /**
+     * Draw peaks on the canvas
+     *
+     * @param {number[]|number[][]} peaks Can also be an array of arrays for split channel
+     * rendering
+     * @param {number} length The width of the area that should be drawn
+     * @param {number} start The x-offset of the beginning of the area that
+     * should be rendered
+     * @param {number} end The x-offset of the end of the area that should be
+     * rendered
+     */
+
+  }, {
+    key: "drawPeaks",
+    value: function drawPeaks(peaks, length, start, end) {
+      if (!this.setWidth(length)) {
+        this.clearWave();
+      }
+
+      this.params.barWidth ? this.drawBars(peaks, 0, start, end) : this.drawWave(peaks, 0, start, end);
+    }
+    /**
+     * Scroll to the beginning
+     */
+
+  }, {
+    key: "resetScroll",
+    value: function resetScroll() {
+      if (this.wrapper !== null) {
+        this.wrapper.scrollLeft = 0;
+      }
+    }
+    /**
+     * Recenter the view-port at a certain percent of the waveform
+     *
+     * @param {number} percent Value from 0 to 1 on the waveform
+     */
+
+  }, {
+    key: "recenter",
+    value: function recenter(percent) {
+      var position = this.wrapper.scrollWidth * percent;
+      this.recenterOnPosition(position, true);
+    }
+    /**
+     * Recenter the view-port on a position, either scroll there immediately or
+     * in steps of 5 pixels
+     *
+     * @param {number} position X-offset in pixels
+     * @param {boolean} immediate Set to true to immediately scroll somewhere
+     */
+
+  }, {
+    key: "recenterOnPosition",
+    value: function recenterOnPosition(position, immediate) {
+      var scrollLeft = this.wrapper.scrollLeft;
+      var half = ~~(this.wrapper.clientWidth / 2);
+      var maxScroll = this.wrapper.scrollWidth - this.wrapper.clientWidth;
+      var target = position - half;
+      var offset = target - scrollLeft;
+
+      if (maxScroll == 0) {
+        // no need to continue if scrollbar is not there
+        return;
+      } // if the cursor is currently visible...
+
+
+      if (!immediate && -half <= offset && offset < half) {
+        // we'll limit the "re-center" rate.
+        var rate = 5;
+        offset = Math.max(-rate, Math.min(rate, offset));
+        target = scrollLeft + offset;
+      } // limit target to valid range (0 to maxScroll)
+
+
+      target = Math.max(0, Math.min(maxScroll, target)); // no use attempting to scroll if we're not moving
+
+      if (target != scrollLeft) {
+        this.wrapper.scrollLeft = target;
+      }
+    }
+    /**
+     * Get the current scroll position in pixels
+     *
+     * @return {number}
+     */
+
+  }, {
+    key: "getScrollX",
+    value: function getScrollX() {
+      var x = 0;
+
+      if (this.wrapper) {
+        var pixelRatio = this.params.pixelRatio;
+        x = Math.round(this.wrapper.scrollLeft * pixelRatio); // In cases of elastic scroll (safari with mouse wheel) you can
+        // scroll beyond the limits of the container
+        // Calculate and floor the scrollable extent to make sure an out
+        // of bounds value is not returned
+        // Ticket #1312
+
+        if (this.params.scrollParent) {
+          var maxScroll = ~~(this.wrapper.scrollWidth * pixelRatio - this.getWidth());
+          x = Math.min(maxScroll, Math.max(0, x));
+        }
+      }
+
+      return x;
+    }
+    /**
+     * Get the width of the container
+     *
+     * @return {number}
+     */
+
+  }, {
+    key: "getWidth",
+    value: function getWidth() {
+      return Math.round(this.container.clientWidth * this.params.pixelRatio);
+    }
+    /**
+     * Set the width of the container
+     *
+     * @param {number} width
+     */
+
+  }, {
+    key: "setWidth",
+    value: function setWidth(width) {
+      if (this.width == width) {
+        return false;
+      }
+
+      this.width = width;
+
+      if (this.params.fillParent || this.params.scrollParent) {
+        this.style(this.wrapper, {
+          width: ''
+        });
+      } else {
+        this.style(this.wrapper, {
+          width: ~~(this.width / this.params.pixelRatio) + 'px'
+        });
+      }
+
+      this.updateSize();
+      return true;
+    }
+    /**
+     * Set the height of the container
+     *
+     * @param {number} height
+     */
+
+  }, {
+    key: "setHeight",
+    value: function setHeight(height) {
+      if (height == this.height) {
+        return false;
+      }
+
+      this.height = height;
+      this.style(this.wrapper, {
+        height: ~~(this.height / this.params.pixelRatio) + 'px'
+      });
+      this.updateSize();
+      return true;
+    }
+    /**
+     * Called by wavesurfer when progress should be rendered
+     *
+     * @param {number} progress From 0 to 1
+     */
+
+  }, {
+    key: "progress",
+    value: function progress(_progress) {
+      var minPxDelta = 1 / this.params.pixelRatio;
+      var pos = Math.round(_progress * this.width) * minPxDelta;
+
+      if (pos < this.lastPos || pos - this.lastPos >= minPxDelta) {
+        this.lastPos = pos;
+
+        if (this.params.scrollParent && this.params.autoCenter) {
+          var newPos = ~~(this.wrapper.scrollWidth * _progress);
+          this.recenterOnPosition(newPos);
+        }
+
+        this.updateProgress(pos);
+      }
+    }
+    /**
+     * This is called when wavesurfer is destroyed
+     */
+
+  }, {
+    key: "destroy",
+    value: function destroy() {
+      this.unAll();
+
+      if (this.wrapper) {
+        if (this.wrapper.parentNode == this.container) {
+          this.container.removeChild(this.wrapper);
+        }
+
+        this.wrapper = null;
+      }
+    }
+    /* Renderer-specific methods */
+
+    /**
+     * Called after cursor related params have changed.
+     *
+     * @abstract
+     */
+
+  }, {
+    key: "updateCursor",
+    value: function updateCursor() {}
+    /**
+     * Called when the size of the container changes so the renderer can adjust
+     *
+     * @abstract
+     */
+
+  }, {
+    key: "updateSize",
+    value: function updateSize() {}
+    /**
+     * Draw a waveform with bars
+     *
+     * @abstract
+     * @param {number[]|number[][]} peaks Can also be an array of arrays for split channel
+     * rendering
+     * @param {number} channelIndex The index of the current channel. Normally
+     * should be 0
+     * @param {number} start The x-offset of the beginning of the area that
+     * should be rendered
+     * @param {number} end The x-offset of the end of the area that should be
+     * rendered
+     */
+
+  }, {
+    key: "drawBars",
+    value: function drawBars(peaks, channelIndex, start, end) {}
+    /**
+     * Draw a waveform
+     *
+     * @abstract
+     * @param {number[]|number[][]} peaks Can also be an array of arrays for split channel
+     * rendering
+     * @param {number} channelIndex The index of the current channel. Normally
+     * should be 0
+     * @param {number} start The x-offset of the beginning of the area that
+     * should be rendered
+     * @param {number} end The x-offset of the end of the area that should be
+     * rendered
+     */
+
+  }, {
+    key: "drawWave",
+    value: function drawWave(peaks, channelIndex, start, end) {}
+    /**
+     * Clear the waveform
+     *
+     * @abstract
+     */
+
+  }, {
+    key: "clearWave",
+    value: function clearWave() {}
+    /**
+     * Render the new progress
+     *
+     * @abstract
+     * @param {number} position X-Offset of progress position in pixels
+     */
+
+  }, {
+    key: "updateProgress",
+    value: function updateProgress(position) {}
+  }]);
+
+  return Drawer;
+}(util.Observer);
+
+exports.default = Drawer;
+module.exports = exports.default;
+
+/***/ }),
+
+/***/ "./src/drawer.multicanvas.js":
+/*!***********************************!*\
+  !*** ./src/drawer.multicanvas.js ***!
+  \***********************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _drawer = _interopRequireDefault(__webpack_require__(/*! ./drawer */ "./src/drawer.js"));
+
+var util = _interopRequireWildcard(__webpack_require__(/*! ./util */ "./src/util/index.js"));
+
+function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; if (obj != null) { 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; }
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _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); }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
+
+function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
+
+function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
+
+function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
+
+/**
+ * @typedef {Object} CanvasEntry
+ * @private
+ * @property {HTMLElement} wave The wave node
+ * @property {CanvasRenderingContext2D} waveCtx The canvas rendering context
+ * @property {?HTMLElement} progress The progress wave node
+ * @property {?CanvasRenderingContext2D} progressCtx The progress wave canvas
+ * rendering context
+ * @property {?number} start Start of the area the canvas should render, between 0 and 1
+ * @property {?number} end End of the area the canvas should render, between 0 and 1
+ */
+
+/**
+ * MultiCanvas renderer for wavesurfer. Is currently the default and sole built
+ * in renderer.
+ */
+var MultiCanvas =
+/*#__PURE__*/
+function (_Drawer) {
+  _inherits(MultiCanvas, _Drawer);
+
+  /**
+   * @param {HTMLElement} container The container node of the wavesurfer instance
+   * @param {WavesurferParams} params The wavesurfer initialisation options
+   */
+  function MultiCanvas(container, params) {
+    var _this;
+
+    _classCallCheck(this, MultiCanvas);
+
+    _this = _possibleConstructorReturn(this, _getPrototypeOf(MultiCanvas).call(this, container, params));
+    /**
+     * @type {number}
+     * @private
+     */
+
+    _this.maxCanvasWidth = params.maxCanvasWidth;
+    /**
+     * @private
+     * @type {number}
+     */
+
+    _this.maxCanvasElementWidth = Math.round(params.maxCanvasWidth / params.pixelRatio);
+    /**
+     * Whether or not the progress wave is rendered. If the `waveColor`
+     * and `progressColor` are the same color it is not.
+     * @type {boolean}
+     */
+
+    _this.hasProgressCanvas = params.waveColor != params.progressColor;
+    /**
+     * @private
+     * @type {number}
+     */
+
+    _this.halfPixel = 0.5 / params.pixelRatio;
+    /**
+     * @private
+     * @type {Array}
+     */
+
+    _this.canvases = [];
+    /** @private */
+
+    _this.progressWave = null;
+    return _this;
+  }
+  /**
+   * Initialize the drawer
+   */
+
+
+  _createClass(MultiCanvas, [{
+    key: "init",
+    value: function init() {
+      this.createWrapper();
+      this.createElements();
+    }
+    /**
+     * Create the canvas elements and style them
+     *
+     * @private
+     */
+
+  }, {
+    key: "createElements",
+    value: function createElements() {
+      this.progressWave = this.wrapper.appendChild(this.style(document.createElement('wave'), {
+        position: 'absolute',
+        zIndex: 3,
+        left: 0,
+        top: 0,
+        bottom: 0,
+        overflow: 'hidden',
+        width: '0',
+        display: 'none',
+        boxSizing: 'border-box',
+        borderRightStyle: 'solid',
+        pointerEvents: 'none'
+      }));
+      this.addCanvas();
+      this.updateCursor();
+    }
+    /**
+     * Update cursor style from params.
+     */
+
+  }, {
+    key: "updateCursor",
+    value: function updateCursor() {
+      this.style(this.progressWave, {
+        borderRightWidth: this.params.cursorWidth + 'px',
+        borderRightColor: this.params.cursorColor
+      });
+    }
+    /**
+     * Adjust to the updated size by adding or removing canvases
+     */
+
+  }, {
+    key: "updateSize",
+    value: function updateSize() {
+      var _this2 = this;
+
+      var totalWidth = Math.round(this.width / this.params.pixelRatio); // No need more canvas if it's only for 2 peaks (there the same for overlaps !)
+
+      var requiredCanvases = Math.ceil(totalWidth / (this.maxCanvasElementWidth + 2));
+
+      while (this.canvases.length < requiredCanvases) {
+        this.addCanvas();
+      }
+
+      while (this.canvases.length > requiredCanvases) {
+        this.removeCanvas();
+      }
+
+      this.canvases.forEach(function (entry, i) {
+        // Add some overlap to prevent vertical white stripes, keep the
+        // width even for simplicity
+        var canvasWidth = _this2.maxCanvasWidth + 2 * Math.ceil(_this2.params.pixelRatio / 2);
+
+        if (i == _this2.canvases.length - 1) {
+          canvasWidth = _this2.width - _this2.maxCanvasWidth * (_this2.canvases.length - 1);
+        }
+
+        _this2.updateDimensions(entry, canvasWidth, _this2.height);
+
+        _this2.clearWaveForEntry(entry);
+      });
+    }
+    /**
+     * Add a canvas to the canvas list
+     *
+     * @private
+     */
+
+  }, {
+    key: "addCanvas",
+    value: function addCanvas() {
+      var entry = {};
+      var leftOffset = this.maxCanvasElementWidth * this.canvases.length;
+      entry.wave = this.wrapper.appendChild(this.style(document.createElement('canvas'), {
+        position: 'absolute',
+        zIndex: 2,
+        left: leftOffset + 'px',
+        top: 0,
+        bottom: 0,
+        height: '100%',
+        pointerEvents: 'none'
+      }));
+      entry.waveCtx = entry.wave.getContext('2d');
+
+      if (this.hasProgressCanvas) {
+        entry.progress = this.progressWave.appendChild(this.style(document.createElement('canvas'), {
+          position: 'absolute',
+          left: leftOffset + 'px',
+          top: 0,
+          bottom: 0,
+          height: '100%'
+        }));
+        entry.progressCtx = entry.progress.getContext('2d');
+      }
+
+      this.canvases.push(entry);
+    }
+    /**
+     * Pop one canvas from the list
+     *
+     * @private
+     */
+
+  }, {
+    key: "removeCanvas",
+    value: function removeCanvas() {
+      var lastEntry = this.canvases.pop();
+      lastEntry.wave.parentElement.removeChild(lastEntry.wave);
+
+      if (this.hasProgressCanvas) {
+        lastEntry.progress.parentElement.removeChild(lastEntry.progress);
+      }
+    }
+    /**
+     * Update the dimensions of a canvas element
+     *
+     * @private
+     * @param {CanvasEntry} entry
+     * @param {number} width The new width of the element
+     * @param {number} height The new height of the element
+     */
+
+  }, {
+    key: "updateDimensions",
+    value: function updateDimensions(entry, width, height) {
+      var elementWidth = Math.round(width / this.params.pixelRatio);
+      var totalWidth = Math.round(this.width / this.params.pixelRatio); // Where the canvas starts and ends in the waveform, represented as a
+      // decimal between 0 and 1.
+
+      entry.start = entry.waveCtx.canvas.offsetLeft / totalWidth || 0;
+      entry.end = entry.start + elementWidth / totalWidth;
+      entry.waveCtx.canvas.width = width;
+      entry.waveCtx.canvas.height = height;
+      this.style(entry.waveCtx.canvas, {
+        width: elementWidth + 'px'
+      });
+      this.style(this.progressWave, {
+        display: 'block'
+      });
+
+      if (this.hasProgressCanvas) {
+        entry.progressCtx.canvas.width = width;
+        entry.progressCtx.canvas.height = height;
+        this.style(entry.progressCtx.canvas, {
+          width: elementWidth + 'px'
+        });
+      }
+    }
+    /**
+     * Clear the whole waveform
+     */
+
+  }, {
+    key: "clearWave",
+    value: function clearWave() {
+      var _this3 = this;
+
+      this.canvases.forEach(function (entry) {
+        return _this3.clearWaveForEntry(entry);
+      });
+    }
+    /**
+     * Clear one canvas
+     *
+     * @private
+     * @param {CanvasEntry} entry
+     */
+
+  }, {
+    key: "clearWaveForEntry",
+    value: function clearWaveForEntry(entry) {
+      entry.waveCtx.clearRect(0, 0, entry.waveCtx.canvas.width, entry.waveCtx.canvas.height);
+
+      if (this.hasProgressCanvas) {
+        entry.progressCtx.clearRect(0, 0, entry.progressCtx.canvas.width, entry.progressCtx.canvas.height);
+      }
+    }
+    /**
+     * Draw a waveform with bars
+     *
+     * @param {number[]|number[][]} peaks Can also be an array of arrays for split channel
+     * rendering
+     * @param {number} channelIndex The index of the current channel. Normally
+     * should be 0. Must be an integer.
+     * @param {number} start The x-offset of the beginning of the area that
+     * should be rendered
+     * @param {number} end The x-offset of the end of the area that should be
+     * rendered
+     */
+
+  }, {
+    key: "drawBars",
+    value: function drawBars(peaks, channelIndex, start, end) {
+      var _this4 = this;
+
+      return this.prepareDraw(peaks, channelIndex, start, end, function (_ref) {
+        var absmax = _ref.absmax,
+            hasMinVals = _ref.hasMinVals,
+            height = _ref.height,
+            offsetY = _ref.offsetY,
+            halfH = _ref.halfH,
+            peaks = _ref.peaks;
+
+        // if drawBars was called within ws.empty we don't pass a start and
+        // don't want anything to happen
+        if (start === undefined) {
+          return;
+        } // Skip every other value if there are negatives.
+
+
+        var peakIndexScale = hasMinVals ? 2 : 1;
+        var length = peaks.length / peakIndexScale;
+        var bar = _this4.params.barWidth * _this4.params.pixelRatio;
+        var gap = _this4.params.barGap === null ? Math.max(_this4.params.pixelRatio, ~~(bar / 2)) : Math.max(_this4.params.pixelRatio, _this4.params.barGap * _this4.params.pixelRatio);
+        var step = bar + gap;
+        var scale = length / _this4.width;
+        var first = start;
+        var last = end;
+        var i;
+
+        for (i = first; i < last; i += step) {
+          var peak = peaks[Math.floor(i * scale * peakIndexScale)] || 0;
+          var h = Math.round(peak / absmax * halfH);
+
+          _this4.fillRect(i + _this4.halfPixel, halfH - h + offsetY, bar + _this4.halfPixel, h * 2);
+        }
+      });
+    }
+    /**
+     * Draw a waveform
+     *
+     * @param {number[]|number[][]} peaks Can also be an array of arrays for split channel
+     * rendering
+     * @param {number} channelIndex The index of the current channel. Normally
+     * should be 0
+     * @param {number?} start The x-offset of the beginning of the area that
+     * should be rendered (If this isn't set only a flat line is rendered)
+     * @param {number?} end The x-offset of the end of the area that should be
+     * rendered
+     */
+
+  }, {
+    key: "drawWave",
+    value: function drawWave(peaks, channelIndex, start, end) {
+      var _this5 = this;
+
+      return this.prepareDraw(peaks, channelIndex, start, end, function (_ref2) {
+        var absmax = _ref2.absmax,
+            hasMinVals = _ref2.hasMinVals,
+            height = _ref2.height,
+            offsetY = _ref2.offsetY,
+            halfH = _ref2.halfH,
+            peaks = _ref2.peaks;
+
+        if (!hasMinVals) {
+          var reflectedPeaks = [];
+          var len = peaks.length;
+          var i;
+
+          for (i = 0; i < len; i++) {
+            reflectedPeaks[2 * i] = peaks[i];
+            reflectedPeaks[2 * i + 1] = -peaks[i];
+          }
+
+          peaks = reflectedPeaks;
+        } // if drawWave was called within ws.empty we don't pass a start and
+        // end and simply want a flat line
+
+
+        if (start !== undefined) {
+          _this5.drawLine(peaks, absmax, halfH, offsetY, start, end);
+        } // Always draw a median line
+
+
+        _this5.fillRect(0, halfH + offsetY - _this5.halfPixel, _this5.width, _this5.halfPixel);
+      });
+    }
+    /**
+     * Tell the canvas entries to render their portion of the waveform
+     *
+     * @private
+     * @param {number[]} peaks Peak data
+     * @param {number} absmax Maximum peak value (absolute)
+     * @param {number} halfH Half the height of the waveform
+     * @param {number} offsetY Offset to the top
+     * @param {number} start The x-offset of the beginning of the area that
+     * should be rendered
+     * @param {number} end The x-offset of the end of the area that
+     * should be rendered
+     */
+
+  }, {
+    key: "drawLine",
+    value: function drawLine(peaks, absmax, halfH, offsetY, start, end) {
+      var _this6 = this;
+
+      this.canvases.forEach(function (entry) {
+        _this6.setFillStyles(entry);
+
+        _this6.drawLineToContext(entry, entry.waveCtx, peaks, absmax, halfH, offsetY, start, end);
+
+        _this6.drawLineToContext(entry, entry.progressCtx, peaks, absmax, halfH, offsetY, start, end);
+      });
+    }
+    /**
+     * Render the actual waveform line on a canvas
+     *
+     * @private
+     * @param {CanvasEntry} entry
+     * @param {Canvas2DContextAttributes} ctx Essentially `entry.[wave|progress]Ctx`
+     * @param {number[]} peaks
+     * @param {number} absmax Maximum peak value (absolute)
+     * @param {number} halfH Half the height of the waveform
+     * @param {number} offsetY Offset to the top
+     * @param {number} start The x-offset of the beginning of the area that
+     * should be rendered
+     * @param {number} end The x-offset of the end of the area that
+     * should be rendered
+     */
+
+  }, {
+    key: "drawLineToContext",
+    value: function drawLineToContext(entry, ctx, peaks, absmax, halfH, offsetY, start, end) {
+      if (!ctx) {
+        return;
+      }
+
+      var length = peaks.length / 2;
+      var first = Math.round(length * entry.start); // Use one more peak value to make sure we join peaks at ends -- unless,
+      // of course, this is the last canvas.
+
+      var last = Math.round(length * entry.end) + 1;
+      var canvasStart = first;
+      var canvasEnd = last;
+      var i;
+      var j;
+      var scale = entry.progress.width / (canvasEnd - canvasStart - 1); // optimization
+
+      var halfOffset = halfH + offsetY;
+      var absmaxHalf = absmax / halfH;
+      ctx.beginPath();
+      ctx.moveTo((canvasStart - first) * scale, halfOffset);
+      ctx.lineTo((canvasStart - first) * scale, halfOffset - Math.round((peaks[2 * canvasStart] || 0) / absmaxHalf));
+
+      for (i = canvasStart; i < canvasEnd; i++) {
+        var peak = peaks[2 * i] || 0;
+        var h = Math.round(peak / absmaxHalf);
+        ctx.lineTo((i - first) * scale + this.halfPixel, halfOffset - h);
+      } // Draw the bottom edge going backwards, to make a single
+      // closed hull to fill.
+
+
+      for (j = canvasEnd - 1; j >= canvasStart; j--) {
+        var _peak = peaks[2 * j + 1] || 0;
+
+        var _h = Math.round(_peak / absmaxHalf);
+
+        ctx.lineTo((j - first) * scale + this.halfPixel, halfOffset - _h);
+      }
+
+      ctx.lineTo((canvasStart - first) * scale, halfOffset - Math.round((peaks[2 * canvasStart + 1] || 0) / absmaxHalf));
+      ctx.closePath();
+      ctx.fill();
+    }
+    /**
+     * Draw a rectangle on the waveform
+     *
+     * @param {number} x
+     * @param {number} y
+     * @param {number} width
+     * @param {number} height
+     */
+
+  }, {
+    key: "fillRect",
+    value: function fillRect(x, y, width, height) {
+      var startCanvas = Math.floor(x / this.maxCanvasWidth);
+      var endCanvas = Math.min(Math.ceil((x + width) / this.maxCanvasWidth) + 1, this.canvases.length);
+      var i;
+
+      for (i = startCanvas; i < endCanvas; i++) {
+        var entry = this.canvases[i];
+        var leftOffset = i * this.maxCanvasWidth;
+        var intersection = {
+          x1: Math.max(x, i * this.maxCanvasWidth),
+          y1: y,
+          x2: Math.min(x + width, i * this.maxCanvasWidth + entry.waveCtx.canvas.width),
+          y2: y + height
+        };
+
+        if (intersection.x1 < intersection.x2) {
+          this.setFillStyles(entry);
+          this.fillRectToContext(entry.waveCtx, intersection.x1 - leftOffset, intersection.y1, intersection.x2 - intersection.x1, intersection.y2 - intersection.y1);
+          this.fillRectToContext(entry.progressCtx, intersection.x1 - leftOffset, intersection.y1, intersection.x2 - intersection.x1, intersection.y2 - intersection.y1);
+        }
+      }
+    }
+    /**
+     * Performs preparation tasks and calculations which are shared by drawBars and drawWave
+     *
+     * @private
+     * @param {number[]|number[][]} peaks Can also be an array of arrays for split channel
+     * rendering
+     * @param {number} channelIndex The index of the current channel. Normally
+     * should be 0
+     * @param {number?} start The x-offset of the beginning of the area that
+     * should be rendered (If this isn't set only a flat line is rendered)
+     * @param {number?} end The x-offset of the end of the area that should be
+     * rendered
+     * @param {function} fn The render function to call
+     */
+
+  }, {
+    key: "prepareDraw",
+    value: function prepareDraw(peaks, channelIndex, start, end, fn) {
+      var _this7 = this;
+
+      return util.frame(function () {
+        // Split channels and call this function with the channelIndex set
+        if (peaks[0] instanceof Array) {
+          var channels = peaks;
+
+          if (_this7.params.splitChannels) {
+            _this7.setHeight(channels.length * _this7.params.height * _this7.params.pixelRatio);
+
+            return channels.forEach(function (channelPeaks, i) {
+              return _this7.prepareDraw(channelPeaks, i, start, end, fn);
+            });
+          }
+
+          peaks = channels[0];
+        } // calculate maximum modulation value, either from the barHeight
+        // parameter or if normalize=true from the largest value in the peak
+        // set
+
+
+        var absmax = 1 / _this7.params.barHeight;
+
+        if (_this7.params.normalize) {
+          var max = util.max(peaks);
+          var min = util.min(peaks);
+          absmax = -min > max ? -min : max;
+        } // Bar wave draws the bottom only as a reflection of the top,
+        // so we don't need negative values
+
+
+        var hasMinVals = [].some.call(peaks, function (val) {
+          return val < 0;
+        });
+        var height = _this7.params.height * _this7.params.pixelRatio;
+        var offsetY = height * channelIndex || 0;
+        var halfH = height / 2;
+        return fn({
+          absmax: absmax,
+          hasMinVals: hasMinVals,
+          height: height,
+          offsetY: offsetY,
+          halfH: halfH,
+          peaks: peaks
+        });
+      })();
+    }
+    /**
+     * Draw the actual rectangle on a canvas
+     *
+     * @private
+     * @param {Canvas2DContextAttributes} ctx
+     * @param {number} x
+     * @param {number} y
+     * @param {number} width
+     * @param {number} height
+     */
+
+  }, {
+    key: "fillRectToContext",
+    value: function fillRectToContext(ctx, x, y, width, height) {
+      if (!ctx) {
+        return;
+      }
+
+      ctx.fillRect(x, y, width, height);
+    }
+    /**
+     * Set the fill styles for a certain entry (wave and progress)
+     *
+     * @private
+     * @param {CanvasEntry} entry
+     */
+
+  }, {
+    key: "setFillStyles",
+    value: function setFillStyles(entry) {
+      entry.waveCtx.fillStyle = this.params.waveColor;
+
+      if (this.hasProgressCanvas) {
+        entry.progressCtx.fillStyle = this.params.progressColor;
+      }
+    }
+    /**
+     * Return image data of the waveform
+     *
+     * @param {string} type='image/png' An optional value of a format type.
+     * @param {number} quality=0.92 An optional value between 0 and 1.
+     * @return {string|string[]} images A data URL or an array of data URLs
+     */
+
+  }, {
+    key: "getImage",
+    value: function getImage(type, quality) {
+      var images = this.canvases.map(function (entry) {
+        return entry.wave.toDataURL(type, quality);
+      });
+      return images.length > 1 ? images : images[0];
+    }
+    /**
+     * Render the new progress
+     *
+     * @param {number} position X-Offset of progress position in pixels
+     */
+
+  }, {
+    key: "updateProgress",
+    value: function updateProgress(position) {
+      this.style(this.progressWave, {
+        width: position + 'px'
+      });
+    }
+  }]);
+
+  return MultiCanvas;
+}(_drawer.default);
+
+exports.default = MultiCanvas;
+module.exports = exports.default;
+
+/***/ }),
+
+/***/ "./src/mediaelement.js":
+/*!*****************************!*\
+  !*** ./src/mediaelement.js ***!
+  \*****************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var _webaudio = _interopRequireDefault(__webpack_require__(/*! ./webaudio */ "./src/webaudio.js"));
+
+var util = _interopRequireWildcard(__webpack_require__(/*! ./util */ "./src/util/index.js"));
+
+function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; if (obj != null) { 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; }
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _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); }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
+
+function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
+
+function _get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); }
+
+function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }
+
+function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
+
+function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
+
+/**
+ * MediaElement backend
+ */
+var MediaElement =
+/*#__PURE__*/
+function (_WebAudio) {
+  _inherits(MediaElement, _WebAudio);
+
+  /**
+   * Construct the backend
+   *
+   * @param {WavesurferParams} params
+   */
+  function MediaElement(params) {
+    var _this;
+
+    _classCallCheck(this, MediaElement);
+
+    _this = _possibleConstructorReturn(this, _getPrototypeOf(MediaElement).call(this, params));
+    /** @private */
+
+    _this.params = params; // Dummy media to catch errors
+
+    /** @private */
+
+    _this.media = {
+      currentTime: 0,
+      duration: 0,
+      paused: true,
+      playbackRate: 1,
+      play: function play() {},
+      pause: function pause() {},
+      volume: 0
+    };
+    /** @private */
+
+    _this.mediaType = params.mediaType.toLowerCase();
+    /** @private */
+
+    _this.elementPosition = params.elementPosition;
+    /** @private */
+
+    _this.peaks = null;
+    /** @private */
+
+    _this.playbackRate = 1;
+    /** @private */
+
+    _this.volume = 1;
+    /** @private */
+
+    _this.buffer = null;
+    /** @private */
+
+    _this.onPlayEnd = null;
+    return _this;
+  }
+  /**
+   * Initialise the backend, called in `wavesurfer.createBackend()`
+   */
+
+
+  _createClass(MediaElement, [{
+    key: "init",
+    value: function init() {
+      this.setPlaybackRate(this.params.audioRate);
+      this.createTimer();
+    }
+    /**
+     * Create a timer to provide a more precise `audioprocess` event.
+     *
+     * @private
+     */
+
+  }, {
+    key: "createTimer",
+    value: function createTimer() {
+      var _this2 = this;
+
+      var onAudioProcess = function onAudioProcess() {
+        if (_this2.isPaused()) {
+          return;
+        }
+
+        _this2.fireEvent('audioprocess', _this2.getCurrentTime()); // Call again in the next frame
+
+
+        var requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame;
+        requestAnimationFrame(onAudioProcess);
+      };
+
+      this.on('play', onAudioProcess); // Update the progress one more time to prevent it from being stuck in
+      // case of lower framerates
+
+      this.on('pause', function () {
+        _this2.fireEvent('audioprocess', _this2.getCurrentTime());
+      });
+    }
+    /**
+     * Create media element with url as its source,
+     * and append to container element.
+     *
+     * @param {string} url Path to media file
+     * @param {HTMLElement} container HTML element
+     * @param {number[]|number[][]} peaks Array of peak data
+     * @param {string} preload HTML 5 preload attribute value
+     */
+
+  }, {
+    key: "load",
+    value: function load(url, container, peaks, preload) {
+      var media = document.createElement(this.mediaType);
+      media.controls = this.params.mediaControls;
+      media.autoplay = this.params.autoplay || false;
+      media.preload = preload == null ? 'auto' : preload;
+      media.src = url;
+      media.style.width = '100%';
+      var prevMedia = container.querySelector(this.mediaType);
+
+      if (prevMedia) {
+        container.removeChild(prevMedia);
+      }
+
+      container.appendChild(media);
+
+      this._load(media, peaks);
+    }
+    /**
+     * Load existing media element.
+     *
+     * @param {HTMLMediaElement} elt HTML5 Audio or Video element
+     * @param {number[]|number[][]} peaks Array of peak data
+     */
+
+  }, {
+    key: "loadElt",
+    value: function loadElt(elt, peaks) {
+      elt.controls = this.params.mediaControls;
+      elt.autoplay = this.params.autoplay || false;
+
+      this._load(elt, peaks);
+    }
+    /**
+     * Private method called by both load (from url)
+     * and loadElt (existing media element).
+     *
+     * @param {HTMLMediaElement} media HTML5 Audio or Video element
+     * @param {number[]|number[][]} peaks Array of peak data
+     * @private
+     */
+
+  }, {
+    key: "_load",
+    value: function _load(media, peaks) {
+      var _this3 = this;
+
+      // load must be called manually on iOS, otherwise peaks won't draw
+      // until a user interaction triggers load --> 'ready' event
+      if (typeof media.load == 'function') {
+        // Resets the media element and restarts the media resource. Any
+        // pending events are discarded. How much media data is fetched is
+        // still affected by the preload attribute.
+        media.load();
+      }
+
+      media.addEventListener('error', function () {
+        _this3.fireEvent('error', 'Error loading media element');
+      });
+      media.addEventListener('canplay', function () {
+        _this3.fireEvent('canplay');
+      });
+      media.addEventListener('ended', function () {
+        _this3.fireEvent('finish');
+      }); // Listen to and relay play and pause events to enable
+      // playback control from the external media element
+
+      media.addEventListener('play', function () {
+        _this3.fireEvent('play');
+      });
+      media.addEventListener('pause', function () {
+        _this3.fireEvent('pause');
+      });
+      this.media = media;
+      this.peaks = peaks;
+      this.onPlayEnd = null;
+      this.buffer = null;
+      this.setPlaybackRate(this.playbackRate);
+      this.setVolume(this.volume);
+    }
+    /**
+     * Used by `wavesurfer.isPlaying()` and `wavesurfer.playPause()`
+     *
+     * @return {boolean}
+     */
+
+  }, {
+    key: "isPaused",
+    value: function isPaused() {
+      return !this.media || this.media.paused;
+    }
+    /**
+     * Used by `wavesurfer.getDuration()`
+     *
+     * @return {number}
+     */
+
+  }, {
+    key: "getDuration",
+    value: function getDuration() {
+      if (this.explicitDuration) {
+        return this.explicitDuration;
+      }
+
+      var duration = (this.buffer || this.media).duration;
+
+      if (duration >= Infinity) {
+        // streaming audio
+        duration = this.media.seekable.end(0);
+      }
+
+      return duration;
+    }
+    /**
+     * Returns the current time in seconds relative to the audio-clip's
+     * duration.
+     *
+     * @return {number}
+     */
+
+  }, {
+    key: "getCurrentTime",
+    value: function getCurrentTime() {
+      return this.media && this.media.currentTime;
+    }
+    /**
+     * Get the position from 0 to 1
+     *
+     * @return {number}
+     */
+
+  }, {
+    key: "getPlayedPercents",
+    value: function getPlayedPercents() {
+      return this.getCurrentTime() / this.getDuration() || 0;
+    }
+    /**
+     * Get the audio source playback rate.
+     *
+     * @return {number}
+     */
+
+  }, {
+    key: "getPlaybackRate",
+    value: function getPlaybackRate() {
+      return this.playbackRate || this.media.playbackRate;
+    }
+    /**
+     * Set the audio source playback rate.
+     *
+     * @param {number} value
+     */
+
+  }, {
+    key: "setPlaybackRate",
+    value: function setPlaybackRate(value) {
+      this.playbackRate = value || 1;
+      this.media.playbackRate = this.playbackRate;
+    }
+    /**
+     * Used by `wavesurfer.seekTo()`
+     *
+     * @param {number} start Position to start at in seconds
+     */
+
+  }, {
+    key: "seekTo",
+    value: function seekTo(start) {
+      if (start != null) {
+        this.media.currentTime = start;
+      }
+
+      this.clearPlayEnd();
+    }
+    /**
+     * Plays the loaded audio region.
+     *
+     * @param {number} start Start offset in seconds, relative to the beginning
+     * of a clip.
+     * @param {number} end When to stop, relative to the beginning of a clip.
+     * @emits MediaElement#play
+     * @return {Promise}
+     */
+
+  }, {
+    key: "play",
+    value: function play(start, end) {
+      this.seekTo(start);
+      var promise = this.media.play();
+      end && this.setPlayEnd(end);
+      return promise;
+    }
+    /**
+     * Pauses the loaded audio.
+     *
+     * @emits MediaElement#pause
+     * @return {Promise}
+     */
+
+  }, {
+    key: "pause",
+    value: function pause() {
+      var promise;
+
+      if (this.media) {
+        promise = this.media.pause();
+      }
+
+      this.clearPlayEnd();
+      return promise;
+    }
+    /** @private */
+
+  }, {
+    key: "setPlayEnd",
+    value: function setPlayEnd(end) {
+      var _this4 = this;
+
+      this._onPlayEnd = function (time) {
+        if (time >= end) {
+          _this4.pause();
+
+          _this4.seekTo(end);
+        }
+      };
+
+      this.on('audioprocess', this._onPlayEnd);
+    }
+    /** @private */
+
+  }, {
+    key: "clearPlayEnd",
+    value: function clearPlayEnd() {
+      if (this._onPlayEnd) {
+        this.un('audioprocess', this._onPlayEnd);
+        this._onPlayEnd = null;
+      }
+    }
+    /**
+     * Compute the max and min value of the waveform when broken into
+     * <length> subranges.
+     *
+     * @param {number} length How many subranges to break the waveform into.
+     * @param {number} first First sample in the required range.
+     * @param {number} last Last sample in the required range.
+     * @return {number[]|number[][]} Array of 2*<length> peaks or array of
+     * arrays of peaks consisting of (max, min) values for each subrange.
+     */
+
+  }, {
+    key: "getPeaks",
+    value: function getPeaks(length, first, last) {
+      if (this.buffer) {
+        return _get(_getPrototypeOf(MediaElement.prototype), "getPeaks", this).call(this, length, first, last);
+      }
+
+      return this.peaks || [];
+    }
+    /**
+     * Set the sink id for the media player
+     *
+     * @param {string} deviceId String value representing audio device id.
+     */
+
+  }, {
+    key: "setSinkId",
+    value: function setSinkId(deviceId) {
+      if (deviceId) {
+        if (!this.media.setSinkId) {
+          return Promise.reject(new Error('setSinkId is not supported in your browser'));
+        }
+
+        return this.media.setSinkId(deviceId);
+      }
+
+      return Promise.reject(new Error('Invalid deviceId: ' + deviceId));
+    }
+    /**
+     * Get the current volume
+     *
+     * @return {number} value A floating point value between 0 and 1.
+     */
+
+  }, {
+    key: "getVolume",
+    value: function getVolume() {
+      return this.volume || this.media.volume;
+    }
+    /**
+     * Set the audio volume
+     *
+     * @param {number} value A floating point value between 0 and 1.
+     */
+
+  }, {
+    key: "setVolume",
+    value: function setVolume(value) {
+      this.volume = value;
+      this.media.volume = this.volume;
+    }
+    /**
+     * This is called when wavesurfer is destroyed
+     *
+     */
+
+  }, {
+    key: "destroy",
+    value: function destroy() {
+      this.pause();
+      this.unAll();
+
+      if (this.params.removeMediaElementOnDestroy && this.media && this.media.parentNode) {
+        this.media.parentNode.removeChild(this.media);
+      }
+
+      this.media = null;
+    }
+  }]);
+
+  return MediaElement;
+}(_webaudio.default);
+
+exports.default = MediaElement;
+module.exports = exports.default;
+
+/***/ }),
+
+/***/ "./src/peakcache.js":
+/*!**************************!*\
+  !*** ./src/peakcache.js ***!
+  \**************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+/**
+ * Caches the decoded peaks data to improve rendering speed for large audio
+ *
+ * Is used if the option parameter `partialRender` is set to `true`
+ */
+var PeakCache =
+/*#__PURE__*/
+function () {
+  /**
+   * Instantiate cache
+   */
+  function PeakCache() {
+    _classCallCheck(this, PeakCache);
+
+    this.clearPeakCache();
+  }
+  /**
+   * Empty the cache
+   */
+
+
+  _createClass(PeakCache, [{
+    key: "clearPeakCache",
+    value: function clearPeakCache() {
+      /**
+       * Flat array with entries that are always in pairs to mark the
+       * beginning and end of each subrange.  This is a convenience so we can
+       * iterate over the pairs for easy set difference operations.
+       * @private
+       */
+      this.peakCacheRanges = [];
+      /**
+       * Length of the entire cachable region, used for resetting the cache
+       * when this changes (zoom events, for instance).
+       * @private
+       */
+
+      this.peakCacheLength = -1;
+    }
+    /**
+     * Add a range of peaks to the cache
+     *
+     * @param {number} length The length of the range
+     * @param {number} start The x offset of the start of the range
+     * @param {number} end The x offset of the end of the range
+     * @return {number[][]}
+     */
+
+  }, {
+    key: "addRangeToPeakCache",
+    value: function addRangeToPeakCache(length, start, end) {
+      if (length != this.peakCacheLength) {
+        this.clearPeakCache();
+        this.peakCacheLength = length;
+      } // Return ranges that weren't in the cache before the call.
+
+
+      var uncachedRanges = [];
+      var i = 0; // Skip ranges before the current start.
+
+      while (i < this.peakCacheRanges.length && this.peakCacheRanges[i] < start) {
+        i++;
+      } // If |i| is even, |start| falls after an existing range.  Otherwise,
+      // |start| falls between an existing range, and the uncached region
+      // starts when we encounter the next node in |peakCacheRanges| or
+      // |end|, whichever comes first.
+
+
+      if (i % 2 == 0) {
+        uncachedRanges.push(start);
+      }
+
+      while (i < this.peakCacheRanges.length && this.peakCacheRanges[i] <= end) {
+        uncachedRanges.push(this.peakCacheRanges[i]);
+        i++;
+      } // If |i| is even, |end| is after all existing ranges.
+
+
+      if (i % 2 == 0) {
+        uncachedRanges.push(end);
+      } // Filter out the 0-length ranges.
+
+
+      uncachedRanges = uncachedRanges.filter(function (item, pos, arr) {
+        if (pos == 0) {
+          return item != arr[pos + 1];
+        } else if (pos == arr.length - 1) {
+          return item != arr[pos - 1];
+        }
+
+        return item != arr[pos - 1] && item != arr[pos + 1];
+      }); // Merge the two ranges together, uncachedRanges will either contain
+      // wholly new points, or duplicates of points in peakCacheRanges.  If
+      // duplicates are detected, remove both and extend the range.
+
+      this.peakCacheRanges = this.peakCacheRanges.concat(uncachedRanges);
+      this.peakCacheRanges = this.peakCacheRanges.sort(function (a, b) {
+        return a - b;
+      }).filter(function (item, pos, arr) {
+        if (pos == 0) {
+          return item != arr[pos + 1];
+        } else if (pos == arr.length - 1) {
+          return item != arr[pos - 1];
+        }
+
+        return item != arr[pos - 1] && item != arr[pos + 1];
+      }); // Push the uncached ranges into an array of arrays for ease of
+      // iteration in the functions that call this.
+
+      var uncachedRangePairs = [];
+
+      for (i = 0; i < uncachedRanges.length; i += 2) {
+        uncachedRangePairs.push([uncachedRanges[i], uncachedRanges[i + 1]]);
+      }
+
+      return uncachedRangePairs;
+    }
+    /**
+     * For testing
+     *
+     * @return {number[][]}
+     */
+
+  }, {
+    key: "getCacheRanges",
+    value: function getCacheRanges() {
+      var peakCacheRangePairs = [];
+      var i;
+
+      for (i = 0; i < this.peakCacheRanges.length; i += 2) {
+        peakCacheRangePairs.push([this.peakCacheRanges[i], this.peakCacheRanges[i + 1]]);
+      }
+
+      return peakCacheRangePairs;
+    }
+  }]);
+
+  return PeakCache;
+}();
+
+exports.default = PeakCache;
+module.exports = exports.default;
+
+/***/ }),
+
+/***/ "./src/util/ajax.js":
+/*!**************************!*\
+  !*** ./src/util/ajax.js ***!
+  \**************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = ajax;
+
+var _observer = _interopRequireDefault(__webpack_require__(/*! ./observer */ "./src/util/observer.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Perform an ajax request
+ *
+ * @param {Options} options Description
+ *
+ * @returns {Object} Observer instance
+ */
+function ajax(options) {
+  var instance = new _observer.default();
+  var xhr = new XMLHttpRequest();
+  var fired100 = false;
+  xhr.open(options.method || 'GET', options.url, true);
+  xhr.responseType = options.responseType || 'json';
+
+  if (options.xhr) {
+    if (options.xhr.requestHeaders) {
+      // add custom request headers
+      options.xhr.requestHeaders.forEach(function (header) {
+        xhr.setRequestHeader(header.key, header.value);
+      });
+    }
+
+    if (options.xhr.withCredentials) {
+      // use credentials
+      xhr.withCredentials = true;
+    }
+  }
+
+  xhr.addEventListener('progress', function (e) {
+    instance.fireEvent('progress', e);
+
+    if (e.lengthComputable && e.loaded == e.total) {
+      fired100 = true;
+    }
+  });
+  xhr.addEventListener('load', function (e) {
+    if (!fired100) {
+      instance.fireEvent('progress', e);
+    }
+
+    instance.fireEvent('load', e);
+
+    if (200 == xhr.status || 206 == xhr.status) {
+      instance.fireEvent('success', xhr.response, e);
+    } else {
+      instance.fireEvent('error', e);
+    }
+  });
+  xhr.addEventListener('error', function (e) {
+    return instance.fireEvent('error', e);
+  });
+  xhr.send();
+  instance.xhr = xhr;
+  return instance;
+}
+
+module.exports = exports.default;
+
+/***/ }),
+
+/***/ "./src/util/extend.js":
+/*!****************************!*\
+  !*** ./src/util/extend.js ***!
+  \****************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = extend;
+
+/**
+ * Extend an object shallowly with others
+ *
+ * @param {Object} dest The target object
+ * @param {Object[]} sources The objects to use for extending
+ *
+ * @return {Object} Merged object
+ */
+function extend(dest) {
+  for (var _len = arguments.length, sources = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
+    sources[_key - 1] = arguments[_key];
+  }
+
+  sources.forEach(function (source) {
+    Object.keys(source).forEach(function (key) {
+      dest[key] = source[key];
+    });
+  });
+  return dest;
+}
+
+module.exports = exports.default;
+
+/***/ }),
+
+/***/ "./src/util/frame.js":
+/*!***************************!*\
+  !*** ./src/util/frame.js ***!
+  \***************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = frame;
+
+var _requestAnimationFrame = _interopRequireDefault(__webpack_require__(/*! ./request-animation-frame */ "./src/util/request-animation-frame.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Create a function which will be called at the next requestAnimationFrame
+ * cycle
+ *
+ * @param {function} func The function to call
+ *
+ * @return {func} The function wrapped within a requestAnimationFrame
+ */
+function frame(func) {
+  return function () {
+    for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
+      args[_key] = arguments[_key];
+    }
+
+    return (0, _requestAnimationFrame.default)(function () {
+      return func.apply(void 0, args);
+    });
+  };
+}
+
+module.exports = exports.default;
+
+/***/ }),
+
+/***/ "./src/util/get-id.js":
+/*!****************************!*\
+  !*** ./src/util/get-id.js ***!
+  \****************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = getId;
+
+/**
+ * Get a random prefixed ID
+ *
+ * @returns {String} Random ID
+ */
+function getId() {
+  return 'wavesurfer_' + Math.random().toString(32).substring(2);
+}
+
+module.exports = exports.default;
+
+/***/ }),
+
+/***/ "./src/util/index.js":
+/*!***************************!*\
+  !*** ./src/util/index.js ***!
+  \***************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+Object.defineProperty(exports, "ajax", {
+  enumerable: true,
+  get: function get() {
+    return _ajax.default;
+  }
+});
+Object.defineProperty(exports, "getId", {
+  enumerable: true,
+  get: function get() {
+    return _getId.default;
+  }
+});
+Object.defineProperty(exports, "max", {
+  enumerable: true,
+  get: function get() {
+    return _max.default;
+  }
+});
+Object.defineProperty(exports, "min", {
+  enumerable: true,
+  get: function get() {
+    return _min.default;
+  }
+});
+Object.defineProperty(exports, "Observer", {
+  enumerable: true,
+  get: function get() {
+    return _observer.default;
+  }
+});
+Object.defineProperty(exports, "extend", {
+  enumerable: true,
+  get: function get() {
+    return _extend.default;
+  }
+});
+Object.defineProperty(exports, "style", {
+  enumerable: true,
+  get: function get() {
+    return _style.default;
+  }
+});
+Object.defineProperty(exports, "requestAnimationFrame", {
+  enumerable: true,
+  get: function get() {
+    return _requestAnimationFrame.default;
+  }
+});
+Object.defineProperty(exports, "frame", {
+  enumerable: true,
+  get: function get() {
+    return _frame.default;
+  }
+});
+Object.defineProperty(exports, "debounce", {
+  enumerable: true,
+  get: function get() {
+    return _debounce.default;
+  }
+});
+Object.defineProperty(exports, "preventClick", {
+  enumerable: true,
+  get: function get() {
+    return _preventClick.default;
+  }
+});
+
+var _ajax = _interopRequireDefault(__webpack_require__(/*! ./ajax */ "./src/util/ajax.js"));
+
+var _getId = _interopRequireDefault(__webpack_require__(/*! ./get-id */ "./src/util/get-id.js"));
+
+var _max = _interopRequireDefault(__webpack_require__(/*! ./max */ "./src/util/max.js"));
+
+var _min = _interopRequireDefault(__webpack_require__(/*! ./min */ "./src/util/min.js"));
+
+var _observer = _interopRequireDefault(__webpack_require__(/*! ./observer */ "./src/util/observer.js"));
+
+var _extend = _interopRequireDefault(__webpack_require__(/*! ./extend */ "./src/util/extend.js"));
+
+var _style = _interopRequireDefault(__webpack_require__(/*! ./style */ "./src/util/style.js"));
+
+var _requestAnimationFrame = _interopRequireDefault(__webpack_require__(/*! ./request-animation-frame */ "./src/util/request-animation-frame.js"));
+
+var _frame = _interopRequireDefault(__webpack_require__(/*! ./frame */ "./src/util/frame.js"));
+
+var _debounce = _interopRequireDefault(__webpack_require__(/*! debounce */ "./node_modules/debounce/index.js"));
+
+var _preventClick = _interopRequireDefault(__webpack_require__(/*! ./prevent-click */ "./src/util/prevent-click.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/***/ }),
+
+/***/ "./src/util/max.js":
+/*!*************************!*\
+  !*** ./src/util/max.js ***!
+  \*************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = max;
+
+/**
+ * Get the largest value
+ *
+ * @param   {Array} values Array of numbers
+ * @returns {Number} Largest number found
+ */
+function max(values) {
+  var largest = -Infinity;
+  Object.keys(values).forEach(function (i) {
+    if (values[i] > largest) {
+      largest = values[i];
+    }
+  });
+  return largest;
+}
+
+module.exports = exports.default;
+
+/***/ }),
+
+/***/ "./src/util/min.js":
+/*!*************************!*\
+  !*** ./src/util/min.js ***!
+  \*************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = min;
+
+/**
+ * Get the smallest value
+ *
+ * @param   {Array} values Array of numbers
+ * @returns {Number}       Smallest number found
+ */
+function min(values) {
+  var smallest = Number(Infinity);
+  Object.keys(values).forEach(function (i) {
+    if (values[i] < smallest) {
+      smallest = values[i];
+    }
+  });
+  return smallest;
+}
+
+module.exports = exports.default;
+
+/***/ }),
+
+/***/ "./src/util/observer.js":
+/*!******************************!*\
+  !*** ./src/util/observer.js ***!
+  \******************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+/**
+ * @typedef {Object} ListenerDescriptor
+ * @property {string} name The name of the event
+ * @property {function} callback The callback
+ * @property {function} un The function to call to remove the listener
+ */
+
+/**
+ * Observer class
+ */
+var Observer =
+/*#__PURE__*/
+function () {
+  /**
+   * Instantiate Observer
+   */
+  function Observer() {
+    _classCallCheck(this, Observer);
+
+    /**
+     * @private
+     * @todo Initialise the handlers here already and remove the conditional
+     * assignment in `on()`
+     */
+    this.handlers = null;
+  }
+  /**
+   * Attach a handler function for an event.
+   *
+   * @param {string} event Name of the event to listen to
+   * @param {function} fn The callback to trigger when the event is fired
+   * @return {ListenerDescriptor}
+   */
+
+
+  _createClass(Observer, [{
+    key: "on",
+    value: function on(event, fn) {
+      var _this = this;
+
+      if (!this.handlers) {
+        this.handlers = {};
+      }
+
+      var handlers = this.handlers[event];
+
+      if (!handlers) {
+        handlers = this.handlers[event] = [];
+      }
+
+      handlers.push(fn); // Return an event descriptor
+
+      return {
+        name: event,
+        callback: fn,
+        un: function un(e, fn) {
+          return _this.un(e, fn);
+        }
+      };
+    }
+    /**
+     * Remove an event handler.
+     *
+     * @param {string} event Name of the event the listener that should be
+     * removed listens to
+     * @param {function} fn The callback that should be removed
+     */
+
+  }, {
+    key: "un",
+    value: function un(event, fn) {
+      if (!this.handlers) {
+        return;
+      }
+
+      var handlers = this.handlers[event];
+      var i;
+
+      if (handlers) {
+        if (fn) {
+          for (i = handlers.length - 1; i >= 0; i--) {
+            if (handlers[i] == fn) {
+              handlers.splice(i, 1);
+            }
+          }
+        } else {
+          handlers.length = 0;
+        }
+      }
+    }
+    /**
+     * Remove all event handlers.
+     */
+
+  }, {
+    key: "unAll",
+    value: function unAll() {
+      this.handlers = null;
+    }
+    /**
+     * Attach a handler to an event. The handler is executed at most once per
+     * event type.
+     *
+     * @param {string} event The event to listen to
+     * @param {function} handler The callback that is only to be called once
+     * @return {ListenerDescriptor}
+     */
+
+  }, {
+    key: "once",
+    value: function once(event, handler) {
+      var _this2 = this;
+
+      var fn = function fn() {
+        for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
+          args[_key] = arguments[_key];
+        }
+
+        /*  eslint-disable no-invalid-this */
+        handler.apply(_this2, args);
+        /*  eslint-enable no-invalid-this */
+
+        setTimeout(function () {
+          _this2.un(event, fn);
+        }, 0);
+      };
+
+      return this.on(event, fn);
+    }
+    /**
+     * Manually fire an event
+     *
+     * @param {string} event The event to fire manually
+     * @param {...any} args The arguments with which to call the listeners
+     */
+
+  }, {
+    key: "fireEvent",
+    value: function fireEvent(event) {
+      for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
+        args[_key2 - 1] = arguments[_key2];
+      }
+
+      if (!this.handlers) {
+        return;
+      }
+
+      var handlers = this.handlers[event];
+      handlers && handlers.forEach(function (fn) {
+        fn.apply(void 0, args);
+      });
+    }
+  }]);
+
+  return Observer;
+}();
+
+exports.default = Observer;
+module.exports = exports.default;
+
+/***/ }),
+
+/***/ "./src/util/prevent-click.js":
+/*!***********************************!*\
+  !*** ./src/util/prevent-click.js ***!
+  \***********************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = preventClick;
+
+function preventClickHandler(e) {
+  e.stopPropagation();
+  document.body.removeEventListener('click', preventClickHandler, true);
+}
+
+function preventClick(values) {
+  document.body.addEventListener('click', preventClickHandler, true);
+}
+
+module.exports = exports.default;
+
+/***/ }),
+
+/***/ "./src/util/request-animation-frame.js":
+/*!*********************************************!*\
+  !*** ./src/util/request-animation-frame.js ***!
+  \*********************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+/**
+ * Returns the requestAnimationFrame function for the browser, or a shim with
+ * setTimeout if none is found
+ *
+ * @return {function}
+ */
+var _default = (window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback, element) {
+  return setTimeout(callback, 1000 / 60);
+}).bind(window);
+
+exports.default = _default;
+module.exports = exports.default;
+
+/***/ }),
+
+/***/ "./src/util/style.js":
+/*!***************************!*\
+  !*** ./src/util/style.js ***!
+  \***************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = style;
+
+/**
+ * Apply a map of styles to an element
+ *
+ * @param {HTMLElement} el The element that the styles will be applied to
+ * @param {Object} styles The map of propName: attribute, both are used as-is
+ *
+ * @return {HTMLElement} el
+ */
+function style(el, styles) {
+  Object.keys(styles).forEach(function (prop) {
+    if (el.style[prop] !== styles[prop]) {
+      el.style[prop] = styles[prop];
+    }
+  });
+  return el;
+}
+
+module.exports = exports.default;
+
+/***/ }),
+
+/***/ "./src/wavesurfer.js":
+/*!***************************!*\
+  !*** ./src/wavesurfer.js ***!
+  \***************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var util = _interopRequireWildcard(__webpack_require__(/*! ./util */ "./src/util/index.js"));
+
+var _drawer = _interopRequireDefault(__webpack_require__(/*! ./drawer.multicanvas */ "./src/drawer.multicanvas.js"));
+
+var _webaudio = _interopRequireDefault(__webpack_require__(/*! ./webaudio */ "./src/webaudio.js"));
+
+var _mediaelement = _interopRequireDefault(__webpack_require__(/*! ./mediaelement */ "./src/mediaelement.js"));
+
+var _peakcache = _interopRequireDefault(__webpack_require__(/*! ./peakcache */ "./src/peakcache.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; if (obj != null) { 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; }
+
+function _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); }
+
+function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
+
+function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
+
+function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
+
+function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+/*
+ * This work is licensed under a BSD-3-Clause License.
+ */
+
+/** @external {HTMLElement} https://developer.mozilla.org/en/docs/Web/API/HTMLElement */
+
+/** @external {OfflineAudioContext} https://developer.mozilla.org/en-US/docs/Web/API/OfflineAudioContext */
+
+/** @external {File} https://developer.mozilla.org/en-US/docs/Web/API/File */
+
+/** @external {Blob} https://developer.mozilla.org/en-US/docs/Web/API/Blob */
+
+/** @external {CanvasRenderingContext2D} https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D */
+
+/** @external {MediaStreamConstraints} https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamConstraints */
+
+/** @external {AudioNode} https://developer.mozilla.org/de/docs/Web/API/AudioNode */
+
+/**
+ * @typedef {Object} WavesurferParams
+ * @property {AudioContext} audioContext=null Use your own previously
+ * initialized AudioContext or leave blank.
+ * @property {number} audioRate=1 Speed at which to play audio. Lower number is
+ * slower.
+ * @property {ScriptProcessorNode} audioScriptProcessor=null Use your own previously
+ * initialized ScriptProcessorNode or leave blank.
+ * @property {boolean} autoCenter=true If a scrollbar is present, center the
+ * waveform around the progress
+ * @property {string} backend='WebAudio' `'WebAudio'|'MediaElement'` In most cases
+ * you don't have to set this manually. MediaElement is a fallback for
+ * unsupported browsers.
+ * @property {string} backgroundColor=null Change background color of the
+ * waveform container.
+ * @property {number} barHeight=1 The height of the wave
+ * @property {number} barGap=null The optional spacing between bars of the wave,
+ * if not provided will be calculated in legacy format.
+ * @property {boolean} closeAudioContext=false Close and nullify all audio
+ * contexts when the destroy method is called.
+ * @property {!string|HTMLElement} container CSS selector or HTML element where
+ * the waveform should be drawn. This is the only required parameter.
+ * @property {string} cursorColor='#333' The fill color of the cursor indicating
+ * the playhead position.
+ * @property {number} cursorWidth=1 Measured in pixels.
+ * @property {number} duration=null Optional audio length so pre-rendered peaks
+ * can be display immediately for example.
+ * @property {boolean} fillParent=true Whether to fill the entire container or
+ * draw only according to `minPxPerSec`.
+ * @property {boolean} forceDecode=false Force decoding of audio using web audio
+ * when zooming to get a more detailed waveform.
+ * @property {number} height=128 The height of the waveform. Measured in
+ * pixels.
+ * @property {boolean} hideScrollbar=false Whether to hide the horizontal
+ * scrollbar when one would normally be shown.
+ * @property {boolean} interact=true Whether the mouse interaction will be
+ * enabled at initialization. You can switch this parameter at any time later
+ * on.
+ * @property {boolean} loopSelection=true (Use with regions plugin) Enable
+ * looping of selected regions
+ * @property {number} maxCanvasWidth=4000 Maximum width of a single canvas in
+ * pixels, excluding a small overlap (2 * `pixelRatio`, rounded up to the next
+ * even integer). If the waveform is longer than this value, additional canvases
+ * will be used to render the waveform, which is useful for very large waveforms
+ * that may be too wide for browsers to draw on a single canvas.
+ * @property {boolean} mediaControls=false (Use with backend `MediaElement`)
+ * this enables the native controls for the media element
+ * @property {string} mediaType='audio' (Use with backend `MediaElement`)
+ * `'audio'|'video'`
+ * @property {number} minPxPerSec=20 Minimum number of pixels per second of
+ * audio.
+ * @property {boolean} normalize=false If true, normalize by the maximum peak
+ * instead of 1.0.
+ * @property {boolean} partialRender=false Use the PeakCache to improve
+ * rendering speed of large waveforms
+ * @property {number} pixelRatio=window.devicePixelRatio The pixel ratio used to
+ * calculate display
+ * @property {PluginDefinition[]} plugins=[] An array of plugin definitions to
+ * register during instantiation, they will be directly initialised unless they
+ * are added with the `deferInit` property set to true.
+ * @property {string} progressColor='#555' The fill color of the part of the
+ * waveform behind the cursor.
+ * @property {boolean} removeMediaElementOnDestroy=true Set to false to keep the
+ * media element in the DOM when the player is destroyed. This is useful when
+ * reusing an existing media element via the `loadMediaElement` method.
+ * @property {Object} renderer=MultiCanvas Can be used to inject a custom
+ * renderer.
+ * @property {boolean|number} responsive=false If set to `true` resize the
+ * waveform, when the window is resized. This is debounced with a `100ms`
+ * timeout by default. If this parameter is a number it represents that timeout.
+ * @property {boolean} rtl=false If set to `true`, renders waveform from
+ * right-to-left.
+ * @property {boolean} scrollParent=false Whether to scroll the container with a
+ * lengthy waveform. Otherwise the waveform is shrunk to the container width
+ * (see fillParent).
+ * @property {number} skipLength=2 Number of seconds to skip with the
+ * skipForward() and skipBackward() methods.
+ * @property {boolean} splitChannels=false Render with separate waveforms for
+ * the channels of the audio
+ * @property {string} waveColor='#999' The fill color of the waveform after the
+ * cursor.
+ * @property {object} xhr={} XHR options.
+ */
+
+/**
+ * @typedef {Object} PluginDefinition
+ * @desc The Object used to describe a plugin
+ * @example wavesurfer.addPlugin(pluginDefinition);
+ * @property {string} name The name of the plugin, the plugin instance will be
+ * added as a property to the wavesurfer instance under this name
+ * @property {?Object} staticProps The properties that should be added to the
+ * wavesurfer instance as static properties
+ * @property {?boolean} deferInit Don't initialise plugin
+ * automatically
+ * @property {Object} params={} The plugin parameters, they are the first parameter
+ * passed to the plugin class constructor function
+ * @property {PluginClass} instance The plugin instance factory, is called with
+ * the dependency specified in extends. Returns the plugin class.
+ */
+
+/**
+ * @interface PluginClass
+ *
+ * @desc This is the interface which is implemented by all plugin classes. Note
+ * that this only turns into an observer after being passed through
+ * `wavesurfer.addPlugin`.
+ *
+ * @extends {Observer}
+ */
+var PluginClass =
+/*#__PURE__*/
+function () {
+  _createClass(PluginClass, [{
+    key: "create",
+
+    /**
+     * Plugin definition factory
+     *
+     * This function must be used to create a plugin definition which can be
+     * used by wavesurfer to correctly instantiate the plugin.
+     *
+     * @param  {Object} params={} The plugin params (specific to the plugin)
+     * @return {PluginDefinition} an object representing the plugin
+     */
+    value: function create(params) {}
+    /**
+     * Construct the plugin
+     *
+     * @param {Object} params={} The plugin params (specific to the plugin)
+     * @param {Object} ws The wavesurfer instance
+     */
+
+  }]);
+
+  function PluginClass(params, ws) {
+    _classCallCheck(this, PluginClass);
+  }
+  /**
+   * Initialise the plugin
+   *
+   * Start doing something. This is called by
+   * `wavesurfer.initPlugin(pluginName)`
+   */
+
+
+  _createClass(PluginClass, [{
+    key: "init",
+    value: function init() {}
+    /**
+     * Destroy the plugin instance
+     *
+     * Stop doing something. This is called by
+     * `wavesurfer.destroyPlugin(pluginName)`
+     */
+
+  }, {
+    key: "destroy",
+    value: function destroy() {}
+  }]);
+
+  return PluginClass;
+}();
+/**
+ * WaveSurfer core library class
+ *
+ * @extends {Observer}
+ * @example
+ * const params = {
+ *   container: '#waveform',
+ *   waveColor: 'violet',
+ *   progressColor: 'purple'
+ * };
+ *
+ * // initialise like this
+ * const wavesurfer = WaveSurfer.create(params);
+ *
+ * // or like this ...
+ * const wavesurfer = new WaveSurfer(params);
+ * wavesurfer.init();
+ *
+ * // load audio file
+ * wavesurfer.load('example/media/demo.wav');
+ */
+
+
+var WaveSurfer =
+/*#__PURE__*/
+function (_util$Observer) {
+  _inherits(WaveSurfer, _util$Observer);
+
+  _createClass(WaveSurfer, null, [{
+    key: "create",
+
+    /** @private */
+
+    /** @private */
+
+    /**
+     * Instantiate this class, call its `init` function and returns it
+     *
+     * @param {WavesurferParams} params
+     * @return {Object} WaveSurfer instance
+     * @example const wavesurfer = WaveSurfer.create(params);
+     */
+    value: function create(params) {
+      var wavesurfer = new WaveSurfer(params);
+      return wavesurfer.init();
+    }
+    /**
+     * The library version number is available as a static property of the
+     * WaveSurfer class
+     *
+     * @type {String}
+     * @example
+     * console.log('Using wavesurfer.js ' + WaveSurfer.VERSION);
+     */
+
+  }]);
+
+  /**
+   * Initialise wavesurfer instance
+   *
+   * @param {WavesurferParams} params Instantiation options for wavesurfer
+   * @example
+   * const wavesurfer = new WaveSurfer(params);
+   * @returns {this}
+   */
+  function WaveSurfer(params) {
+    var _this;
+
+    _classCallCheck(this, WaveSurfer);
+
+    _this = _possibleConstructorReturn(this, _getPrototypeOf(WaveSurfer).call(this));
+    /**
+     * Extract relevant parameters (or defaults)
+     * @private
+     */
+
+    _this.defaultParams = {
+      audioContext: null,
+      audioScriptProcessor: null,
+      audioRate: 1,
+      autoCenter: true,
+      backend: 'WebAudio',
+      backgroundColor: null,
+      barHeight: 1,
+      barGap: null,
+      container: null,
+      cursorColor: '#333',
+      cursorWidth: 1,
+      dragSelection: true,
+      duration: null,
+      fillParent: true,
+      forceDecode: false,
+      height: 128,
+      hideScrollbar: false,
+      interact: true,
+      loopSelection: true,
+      maxCanvasWidth: 4000,
+      mediaContainer: null,
+      mediaControls: false,
+      mediaType: 'audio',
+      minPxPerSec: 20,
+      normalize: false,
+      partialRender: false,
+      pixelRatio: window.devicePixelRatio || screen.deviceXDPI / screen.logicalXDPI,
+      plugins: [],
+      progressColor: '#555',
+      removeMediaElementOnDestroy: true,
+      renderer: _drawer.default,
+      responsive: false,
+      rtl: false,
+      scrollParent: false,
+      skipLength: 2,
+      splitChannels: false,
+      waveColor: '#999',
+      xhr: {}
+    };
+    _this.backends = {
+      MediaElement: _mediaelement.default,
+      WebAudio: _webaudio.default
+    };
+    _this.util = util;
+    _this.params = util.extend({}, _this.defaultParams, params);
+    /** @private */
+
+    _this.container = 'string' == typeof params.container ? document.querySelector(_this.params.container) : _this.params.container;
+
+    if (!_this.container) {
+      throw new Error('Container element not found');
+    }
+
+    if (_this.params.mediaContainer == null) {
+      /** @private */
+      _this.mediaContainer = _this.container;
+    } else if (typeof _this.params.mediaContainer == 'string') {
+      /** @private */
+      _this.mediaContainer = document.querySelector(_this.params.mediaContainer);
+    } else {
+      /** @private */
+      _this.mediaContainer = _this.params.mediaContainer;
+    }
+
+    if (!_this.mediaContainer) {
+      throw new Error('Media Container element not found');
+    }
+
+    if (_this.params.maxCanvasWidth <= 1) {
+      throw new Error('maxCanvasWidth must be greater than 1');
+    } else if (_this.params.maxCanvasWidth % 2 == 1) {
+      throw new Error('maxCanvasWidth must be an even number');
+    }
+
+    if (_this.params.rtl === true) {
+      util.style(_this.container, {
+        transform: 'rotateY(180deg)'
+      });
+    }
+
+    if (_this.params.backgroundColor) {
+      _this.setBackgroundColor(_this.params.backgroundColor);
+    }
+    /**
+     * @private Used to save the current volume when muting so we can
+     * restore once unmuted
+     * @type {number}
+     */
+
+
+    _this.savedVolume = 0;
+    /**
+     * @private The current muted state
+     * @type {boolean}
+     */
+
+    _this.isMuted = false;
+    /**
+     * @private Will hold a list of event descriptors that need to be
+     * canceled on subsequent loads of audio
+     * @type {Object[]}
+     */
+
+    _this.tmpEvents = [];
+    /**
+     * @private Holds any running audio downloads
+     * @type {Observer}
+     */
+
+    _this.currentAjax = null;
+    /** @private */
+
+    _this.arraybuffer = null;
+    /** @private */
+
+    _this.drawer = null;
+    /** @private */
+
+    _this.backend = null;
+    /** @private */
+
+    _this.peakCache = null; // cache constructor objects
+
+    if (typeof _this.params.renderer !== 'function') {
+      throw new Error('Renderer parameter is invalid');
+    }
+    /**
+     * @private The uninitialised Drawer class
+     */
+
+
+    _this.Drawer = _this.params.renderer;
+    /**
+     * @private The uninitialised Backend class
+     */
+
+    _this.Backend = _this.backends[_this.params.backend];
+    /**
+     * @private map of plugin names that are currently initialised
+     */
+
+    _this.initialisedPluginList = {};
+    /** @private */
+
+    _this.isDestroyed = false;
+    /** @private */
+
+    _this.isReady = false; // responsive debounced event listener. If this.params.responsive is not
+    // set, this is never called. Use 100ms or this.params.responsive as
+    // timeout for the debounce function.
+
+    var prevWidth = 0;
+    _this._onResize = util.debounce(function () {
+      if (prevWidth != _this.drawer.wrapper.clientWidth && !_this.params.scrollParent) {
+        prevWidth = _this.drawer.wrapper.clientWidth;
+
+        _this.drawer.fireEvent('redraw');
+      }
+    }, typeof _this.params.responsive === 'number' ? _this.params.responsive : 100);
+    return _possibleConstructorReturn(_this, _assertThisInitialized(_this));
+  }
+  /**
+   * Initialise the wave
+   *
+   * @example
+   * var wavesurfer = new WaveSurfer(params);
+   * wavesurfer.init();
+   * @return {this}
+   */
+
+
+  _createClass(WaveSurfer, [{
+    key: "init",
+    value: function init() {
+      this.registerPlugins(this.params.plugins);
+      this.createDrawer();
+      this.createBackend();
+      this.createPeakCache();
+      return this;
+    }
+    /**
+     * Add and initialise array of plugins (if `plugin.deferInit` is falsey),
+     * this function is called in the init function of wavesurfer
+     *
+     * @param {PluginDefinition[]} plugins An array of plugin definitions
+     * @emits {WaveSurfer#plugins-registered} Called with the array of plugin definitions
+     * @return {this}
+     */
+
+  }, {
+    key: "registerPlugins",
+    value: function registerPlugins(plugins) {
+      var _this2 = this;
+
+      // first instantiate all the plugins
+      plugins.forEach(function (plugin) {
+        return _this2.addPlugin(plugin);
+      }); // now run the init functions
+
+      plugins.forEach(function (plugin) {
+        // call init function of the plugin if deferInit is falsey
+        // in that case you would manually use initPlugins()
+        if (!plugin.deferInit) {
+          _this2.initPlugin(plugin.name);
+        }
+      });
+      this.fireEvent('plugins-registered', plugins);
+      return this;
+    }
+    /**
+     * Add a plugin object to wavesurfer
+     *
+     * @param {PluginDefinition} plugin A plugin definition
+     * @emits {WaveSurfer#plugin-added} Called with the name of the plugin that was added
+     * @example wavesurfer.addPlugin(WaveSurfer.minimap());
+     * @return {this}
+     */
+
+  }, {
+    key: "addPlugin",
+    value: function addPlugin(plugin) {
+      var _this3 = this;
+
+      if (!plugin.name) {
+        throw new Error('Plugin does not have a name!');
+      }
+
+      if (!plugin.instance) {
+        throw new Error("Plugin ".concat(plugin.name, " does not have an instance property!"));
+      } // staticProps properties are applied to wavesurfer instance
+
+
+      if (plugin.staticProps) {
+        Object.keys(plugin.staticProps).forEach(function (pluginStaticProp) {
+          /**
+           * Properties defined in a plugin definition's `staticProps` property are added as
+           * staticProps properties of the WaveSurfer instance
+           */
+          _this3[pluginStaticProp] = plugin.staticProps[pluginStaticProp];
+        });
+      }
+
+      var Instance = plugin.instance; // turn the plugin instance into an observer
+
+      var observerPrototypeKeys = Object.getOwnPropertyNames(util.Observer.prototype);
+      observerPrototypeKeys.forEach(function (key) {
+        Instance.prototype[key] = util.Observer.prototype[key];
+      });
+      /**
+       * Instantiated plugin classes are added as a property of the wavesurfer
+       * instance
+       * @type {Object}
+       */
+
+      this[plugin.name] = new Instance(plugin.params || {}, this);
+      this.fireEvent('plugin-added', plugin.name);
+      return this;
+    }
+    /**
+     * Initialise a plugin
+     *
+     * @param {string} name A plugin name
+     * @emits WaveSurfer#plugin-initialised
+     * @example wavesurfer.initPlugin('minimap');
+     * @return {this}
+     */
+
+  }, {
+    key: "initPlugin",
+    value: function initPlugin(name) {
+      if (!this[name]) {
+        throw new Error("Plugin ".concat(name, " has not been added yet!"));
+      }
+
+      if (this.initialisedPluginList[name]) {
+        // destroy any already initialised plugins
+        this.destroyPlugin(name);
+      }
+
+      this[name].init();
+      this.initialisedPluginList[name] = true;
+      this.fireEvent('plugin-initialised', name);
+      return this;
+    }
+    /**
+     * Destroy a plugin
+     *
+     * @param {string} name A plugin name
+     * @emits WaveSurfer#plugin-destroyed
+     * @example wavesurfer.destroyPlugin('minimap');
+     * @returns {this}
+     */
+
+  }, {
+    key: "destroyPlugin",
+    value: function destroyPlugin(name) {
+      if (!this[name]) {
+        throw new Error("Plugin ".concat(name, " has not been added yet and cannot be destroyed!"));
+      }
+
+      if (!this.initialisedPluginList[name]) {
+        throw new Error("Plugin ".concat(name, " is not active and cannot be destroyed!"));
+      }
+
+      if (typeof this[name].destroy !== 'function') {
+        throw new Error("Plugin ".concat(name, " does not have a destroy function!"));
+      }
+
+      this[name].destroy();
+      delete this.initialisedPluginList[name];
+      this.fireEvent('plugin-destroyed', name);
+      return this;
+    }
+    /**
+     * Destroy all initialised plugins. Convenience function to use when
+     * wavesurfer is removed
+     *
+     * @private
+     */
+
+  }, {
+    key: "destroyAllPlugins",
+    value: function destroyAllPlugins() {
+      var _this4 = this;
+
+      Object.keys(this.initialisedPluginList).forEach(function (name) {
+        return _this4.destroyPlugin(name);
+      });
+    }
+    /**
+     * Create the drawer and draw the waveform
+     *
+     * @private
+     * @emits WaveSurfer#drawer-created
+     */
+
+  }, {
+    key: "createDrawer",
+    value: function createDrawer() {
+      var _this5 = this;
+
+      this.drawer = new this.Drawer(this.container, this.params);
+      this.drawer.init();
+      this.fireEvent('drawer-created', this.drawer);
+
+      if (this.params.responsive !== false) {
+        window.addEventListener('resize', this._onResize, true);
+        window.addEventListener('orientationchange', this._onResize, true);
+      }
+
+      this.drawer.on('redraw', function () {
+        _this5.drawBuffer();
+
+        _this5.drawer.progress(_this5.backend.getPlayedPercents());
+      }); // Click-to-seek
+
+      this.drawer.on('click', function (e, progress) {
+        setTimeout(function () {
+          return _this5.seekTo(progress);
+        }, 0);
+      }); // Relay the scroll event from the drawer
+
+      this.drawer.on('scroll', function (e) {
+        if (_this5.params.partialRender) {
+          _this5.drawBuffer();
+        }
+
+        _this5.fireEvent('scroll', e);
+      });
+    }
+    /**
+     * Create the backend
+     *
+     * @private
+     * @emits WaveSurfer#backend-created
+     */
+
+  }, {
+    key: "createBackend",
+    value: function createBackend() {
+      var _this6 = this;
+
+      if (this.backend) {
+        this.backend.destroy();
+      } // Back compat
+
+
+      if (this.params.backend == 'AudioElement') {
+        this.params.backend = 'MediaElement';
+      }
+
+      if (this.params.backend == 'WebAudio' && !this.Backend.prototype.supportsWebAudio.call(null)) {
+        this.params.backend = 'MediaElement';
+      }
+
+      this.backend = new this.Backend(this.params);
+      this.backend.init();
+      this.fireEvent('backend-created', this.backend);
+      this.backend.on('finish', function () {
+        _this6.drawer.progress(_this6.backend.getPlayedPercents());
+
+        _this6.fireEvent('finish');
+      });
+      this.backend.on('play', function () {
+        return _this6.fireEvent('play');
+      });
+      this.backend.on('pause', function () {
+        return _this6.fireEvent('pause');
+      });
+      this.backend.on('audioprocess', function (time) {
+        _this6.drawer.progress(_this6.backend.getPlayedPercents());
+
+        _this6.fireEvent('audioprocess', time);
+      });
+    }
+    /**
+     * Create the peak cache
+     *
+     * @private
+     */
+
+  }, {
+    key: "createPeakCache",
+    value: function createPeakCache() {
+      if (this.params.partialRender) {
+        this.peakCache = new _peakcache.default();
+      }
+    }
+    /**
+     * Get the duration of the audio clip
+     *
+     * @example const duration = wavesurfer.getDuration();
+     * @return {number} Duration in seconds
+     */
+
+  }, {
+    key: "getDuration",
+    value: function getDuration() {
+      return this.backend.getDuration();
+    }
+    /**
+     * Get the current playback position
+     *
+     * @example const currentTime = wavesurfer.getCurrentTime();
+     * @return {number} Playback position in seconds
+     */
+
+  }, {
+    key: "getCurrentTime",
+    value: function getCurrentTime() {
+      return this.backend.getCurrentTime();
+    }
+    /**
+     * Set the current play time in seconds.
+     *
+     * @param {number} seconds A positive number in seconds. E.g. 10 means 10
+     * seconds, 60 means 1 minute
+     */
+
+  }, {
+    key: "setCurrentTime",
+    value: function setCurrentTime(seconds) {
+      if (seconds >= this.getDuration()) {
+        this.seekTo(1);
+      } else {
+        this.seekTo(seconds / this.getDuration());
+      }
+    }
+    /**
+     * Starts playback from the current position. Optional start and end
+     * measured in seconds can be used to set the range of audio to play.
+     *
+     * @param {?number} start Position to start at
+     * @param {?number} end Position to end at
+     * @emits WaveSurfer#interaction
+     * @return {Promise}
+     * @example
+     * // play from second 1 to 5
+     * wavesurfer.play(1, 5);
+     */
+
+  }, {
+    key: "play",
+    value: function play(start, end) {
+      var _this7 = this;
+
+      this.fireEvent('interaction', function () {
+        return _this7.play(start, end);
+      });
+      return this.backend.play(start, end);
+    }
+    /**
+     * Stops playback
+     *
+     * @example wavesurfer.pause();
+     * @return {Promise}
+     */
+
+  }, {
+    key: "pause",
+    value: function pause() {
+      if (!this.backend.isPaused()) {
+        return this.backend.pause();
+      }
+    }
+    /**
+     * Toggle playback
+     *
+     * @example wavesurfer.playPause();
+     * @return {Promise}
+     */
+
+  }, {
+    key: "playPause",
+    value: function playPause() {
+      return this.backend.isPaused() ? this.play() : this.pause();
+    }
+    /**
+     * Get the current playback state
+     *
+     * @example const isPlaying = wavesurfer.isPlaying();
+     * @return {boolean} False if paused, true if playing
+     */
+
+  }, {
+    key: "isPlaying",
+    value: function isPlaying() {
+      return !this.backend.isPaused();
+    }
+    /**
+     * Skip backward
+     *
+     * @param {?number} seconds Amount to skip back, if not specified `skipLength`
+     * is used
+     * @example wavesurfer.skipBackward();
+     */
+
+  }, {
+    key: "skipBackward",
+    value: function skipBackward(seconds) {
+      this.skip(-seconds || -this.params.skipLength);
+    }
+    /**
+     * Skip forward
+     *
+     * @param {?number} seconds Amount to skip back, if not specified `skipLength`
+     * is used
+     * @example wavesurfer.skipForward();
+     */
+
+  }, {
+    key: "skipForward",
+    value: function skipForward(seconds) {
+      this.skip(seconds || this.params.skipLength);
+    }
+    /**
+     * Skip a number of seconds from the current position (use a negative value
+     * to go backwards).
+     *
+     * @param {number} offset Amount to skip back or forwards
+     * @example
+     * // go back 2 seconds
+     * wavesurfer.skip(-2);
+     */
+
+  }, {
+    key: "skip",
+    value: function skip(offset) {
+      var duration = this.getDuration() || 1;
+      var position = this.getCurrentTime() || 0;
+      position = Math.max(0, Math.min(duration, position + (offset || 0)));
+      this.seekAndCenter(position / duration);
+    }
+    /**
+     * Seeks to a position and centers the view
+     *
+     * @param {number} progress Between 0 (=beginning) and 1 (=end)
+     * @example
+     * // seek and go to the middle of the audio
+     * wavesurfer.seekTo(0.5);
+     */
+
+  }, {
+    key: "seekAndCenter",
+    value: function seekAndCenter(progress) {
+      this.seekTo(progress);
+      this.drawer.recenter(progress);
+    }
+    /**
+     * Seeks to a position
+     *
+     * @param {number} progress Between 0 (=beginning) and 1 (=end)
+     * @emits WaveSurfer#interaction
+     * @emits WaveSurfer#seek
+     * @example
+     * // seek to the middle of the audio
+     * wavesurfer.seekTo(0.5);
+     */
+
+  }, {
+    key: "seekTo",
+    value: function seekTo(progress) {
+      var _this8 = this;
+
+      // return an error if progress is not a number between 0 and 1
+      if (typeof progress !== 'number' || !isFinite(progress) || progress < 0 || progress > 1) {
+        return console.error('Error calling wavesurfer.seekTo, parameter must be a number between 0 and 1!');
+      }
+
+      this.fireEvent('interaction', function () {
+        return _this8.seekTo(progress);
+      });
+      var paused = this.backend.isPaused(); // avoid draw wrong position while playing backward seeking
+
+      if (!paused) {
+        this.backend.pause();
+      } // avoid small scrolls while paused seeking
+
+
+      var oldScrollParent = this.params.scrollParent;
+      this.params.scrollParent = false;
+      this.backend.seekTo(progress * this.getDuration());
+      this.drawer.progress(progress);
+
+      if (!paused) {
+        this.backend.play();
+      }
+
+      this.params.scrollParent = oldScrollParent;
+      this.fireEvent('seek', progress);
+    }
+    /**
+     * Stops and goes to the beginning.
+     *
+     * @example wavesurfer.stop();
+     */
+
+  }, {
+    key: "stop",
+    value: function stop() {
+      this.pause();
+      this.seekTo(0);
+      this.drawer.progress(0);
+    }
+    /**
+     * Set the playback volume.
+     *
+     * @param {string} deviceId String value representing underlying output device
+     */
+
+  }, {
+    key: "setSinkId",
+    value: function setSinkId(deviceId) {
+      return this.backend.setSinkId(deviceId);
+    }
+    /**
+     * Set the playback volume.
+     *
+     * @param {number} newVolume A value between 0 and 1, 0 being no
+     * volume and 1 being full volume.
+     * @emits WaveSurfer#volume
+     */
+
+  }, {
+    key: "setVolume",
+    value: function setVolume(newVolume) {
+      this.backend.setVolume(newVolume);
+      this.fireEvent('volume', newVolume);
+    }
+    /**
+     * Get the playback volume.
+     *
+     * @return {number} A value between 0 and 1, 0 being no
+     * volume and 1 being full volume.
+     */
+
+  }, {
+    key: "getVolume",
+    value: function getVolume() {
+      return this.backend.getVolume();
+    }
+    /**
+     * Set the playback rate.
+     *
+     * @param {number} rate A positive number. E.g. 0.5 means half the normal
+     * speed, 2 means double speed and so on.
+     * @example wavesurfer.setPlaybackRate(2);
+     */
+
+  }, {
+    key: "setPlaybackRate",
+    value: function setPlaybackRate(rate) {
+      this.backend.setPlaybackRate(rate);
+    }
+    /**
+     * Get the playback rate.
+     *
+     * @return {number}
+     */
+
+  }, {
+    key: "getPlaybackRate",
+    value: function getPlaybackRate() {
+      return this.backend.getPlaybackRate();
+    }
+    /**
+     * Toggle the volume on and off. If not currently muted it will save the
+     * current volume value and turn the volume off. If currently muted then it
+     * will restore the volume to the saved value, and then rest the saved
+     * value.
+     *
+     * @example wavesurfer.toggleMute();
+     */
+
+  }, {
+    key: "toggleMute",
+    value: function toggleMute() {
+      this.setMute(!this.isMuted);
+    }
+    /**
+     * Enable or disable muted audio
+     *
+     * @param {boolean} mute
+     * @emits WaveSurfer#volume
+     * @emits WaveSurfer#mute
+     * @example
+     * // unmute
+     * wavesurfer.setMute(false);
+     */
+
+  }, {
+    key: "setMute",
+    value: function setMute(mute) {
+      // ignore all muting requests if the audio is already in that state
+      if (mute === this.isMuted) {
+        this.fireEvent('mute', this.isMuted);
+        return;
+      }
+
+      if (mute) {
+        // If currently not muted then save current volume,
+        // turn off the volume and update the mute properties
+        this.savedVolume = this.backend.getVolume();
+        this.backend.setVolume(0);
+        this.isMuted = true;
+        this.fireEvent('volume', 0);
+      } else {
+        // If currently muted then restore to the saved volume
+        // and update the mute properties
+        this.backend.setVolume(this.savedVolume);
+        this.isMuted = false;
+        this.fireEvent('volume', this.savedVolume);
+      }
+
+      this.fireEvent('mute', this.isMuted);
+    }
+    /**
+     * Get the current mute status.
+     *
+     * @example const isMuted = wavesurfer.getMute();
+     * @return {boolean}
+     */
+
+  }, {
+    key: "getMute",
+    value: function getMute() {
+      return this.isMuted;
+    }
+    /**
+     * Get the current ready status.
+     *
+     * @example const isReady = wavesurfer.isReady();
+     * @return {boolean}
+     */
+
+  }, {
+    key: "isReady",
+    value: function isReady() {
+      return this.isReady;
+    }
+    /**
+     * Get the list of current set filters as an array.
+     *
+     * Filters must be set with setFilters method first
+     *
+     * @return {array}
+     */
+
+  }, {
+    key: "getFilters",
+    value: function getFilters() {
+      return this.backend.filters || [];
+    }
+    /**
+     * Toggles `scrollParent` and redraws
+     *
+     * @example wavesurfer.toggleScroll();
+     */
+
+  }, {
+    key: "toggleScroll",
+    value: function toggleScroll() {
+      this.params.scrollParent = !this.params.scrollParent;
+      this.drawBuffer();
+    }
+    /**
+     * Toggle mouse interaction
+     *
+     * @example wavesurfer.toggleInteraction();
+     */
+
+  }, {
+    key: "toggleInteraction",
+    value: function toggleInteraction() {
+      this.params.interact = !this.params.interact;
+    }
+    /**
+     * Get the fill color of the waveform after the cursor.
+     *
+     * @return {string} A CSS color string.
+     */
+
+  }, {
+    key: "getWaveColor",
+    value: function getWaveColor() {
+      return this.params.waveColor;
+    }
+    /**
+     * Set the fill color of the waveform after the cursor.
+     *
+     * @param {string} color A CSS color string.
+     * @example wavesurfer.setWaveColor('#ddd');
+     */
+
+  }, {
+    key: "setWaveColor",
+    value: function setWaveColor(color) {
+      this.params.waveColor = color;
+      this.drawBuffer();
+    }
+    /**
+     * Get the fill color of the waveform behind the cursor.
+     *
+     * @return {string} A CSS color string.
+     */
+
+  }, {
+    key: "getProgressColor",
+    value: function getProgressColor() {
+      return this.params.progressColor;
+    }
+    /**
+     * Set the fill color of the waveform behind the cursor.
+     *
+     * @param {string} color A CSS color string.
+     * @example wavesurfer.setProgressColor('#400');
+     */
+
+  }, {
+    key: "setProgressColor",
+    value: function setProgressColor(color) {
+      this.params.progressColor = color;
+      this.drawBuffer();
+    }
+    /**
+     * Get the background color of the waveform container.
+     *
+     * @return {string} A CSS color string.
+     */
+
+  }, {
+    key: "getBackgroundColor",
+    value: function getBackgroundColor() {
+      return this.params.backgroundColor;
+    }
+    /**
+     * Set the background color of the waveform container.
+     *
+     * @param {string} color A CSS color string.
+     * @example wavesurfer.setBackgroundColor('#FF00FF');
+     */
+
+  }, {
+    key: "setBackgroundColor",
+    value: function setBackgroundColor(color) {
+      this.params.backgroundColor = color;
+      util.style(this.container, {
+        background: this.params.backgroundColor
+      });
+    }
+    /**
+     * Get the fill color of the cursor indicating the playhead
+     * position.
+     *
+     * @return {string} A CSS color string.
+     */
+
+  }, {
+    key: "getCursorColor",
+    value: function getCursorColor() {
+      return this.params.cursorColor;
+    }
+    /**
+     * Set the fill color of the cursor indicating the playhead
+     * position.
+     *
+     * @param {string} color A CSS color string.
+     * @example wavesurfer.setCursorColor('#222');
+     */
+
+  }, {
+    key: "setCursorColor",
+    value: function setCursorColor(color) {
+      this.params.cursorColor = color;
+      this.drawer.updateCursor();
+    }
+    /**
+     * Get the height of the waveform.
+     *
+     * @return {number} Height measured in pixels.
+     */
+
+  }, {
+    key: "getHeight",
+    value: function getHeight() {
+      return this.params.height;
+    }
+    /**
+     * Set the height of the waveform.
+     *
+     * @param {number} height Height measured in pixels.
+     * @example wavesurfer.setHeight(200);
+     */
+
+  }, {
+    key: "setHeight",
+    value: function setHeight(height) {
+      this.params.height = height;
+      this.drawer.setHeight(height * this.params.pixelRatio);
+      this.drawBuffer();
+    }
+    /**
+     * Get the correct peaks for current wave view-port and render wave
+     *
+     * @private
+     * @emits WaveSurfer#redraw
+     */
+
+  }, {
+    key: "drawBuffer",
+    value: function drawBuffer() {
+      var nominalWidth = Math.round(this.getDuration() * this.params.minPxPerSec * this.params.pixelRatio);
+      var parentWidth = this.drawer.getWidth();
+      var width = nominalWidth; // always start at 0 after zooming for scrolling : issue redraw left part
+
+      var start = 0;
+      var end = Math.max(start + parentWidth, width); // Fill container
+
+      if (this.params.fillParent && (!this.params.scrollParent || nominalWidth < parentWidth)) {
+        width = parentWidth;
+        start = 0;
+        end = width;
+      }
+
+      var peaks;
+
+      if (this.params.partialRender) {
+        var newRanges = this.peakCache.addRangeToPeakCache(width, start, end);
+        var i;
+
+        for (i = 0; i < newRanges.length; i++) {
+          peaks = this.backend.getPeaks(width, newRanges[i][0], newRanges[i][1]);
+          this.drawer.drawPeaks(peaks, width, newRanges[i][0], newRanges[i][1]);
+        }
+      } else {
+        peaks = this.backend.getPeaks(width, start, end);
+        this.drawer.drawPeaks(peaks, width, start, end);
+      }
+
+      this.fireEvent('redraw', peaks, width);
+    }
+    /**
+     * Horizontally zooms the waveform in and out. It also changes the parameter
+     * `minPxPerSec` and enables the `scrollParent` option. Calling the function
+     * with a falsey parameter will reset the zoom state.
+     *
+     * @param {?number} pxPerSec Number of horizontal pixels per second of
+     * audio, if none is set the waveform returns to unzoomed state
+     * @emits WaveSurfer#zoom
+     * @example wavesurfer.zoom(20);
+     */
+
+  }, {
+    key: "zoom",
+    value: function zoom(pxPerSec) {
+      if (!pxPerSec) {
+        this.params.minPxPerSec = this.defaultParams.minPxPerSec;
+        this.params.scrollParent = false;
+      } else {
+        this.params.minPxPerSec = pxPerSec;
+        this.params.scrollParent = true;
+      }
+
+      this.drawBuffer();
+      this.drawer.progress(this.backend.getPlayedPercents());
+      this.drawer.recenter(this.getCurrentTime() / this.getDuration());
+      this.fireEvent('zoom', pxPerSec);
+    }
+    /**
+     * Decode buffer and load
+     *
+     * @private
+     * @param {ArrayBuffer} arraybuffer
+     */
+
+  }, {
+    key: "loadArrayBuffer",
+    value: function loadArrayBuffer(arraybuffer) {
+      var _this9 = this;
+
+      this.decodeArrayBuffer(arraybuffer, function (data) {
+        if (!_this9.isDestroyed) {
+          _this9.loadDecodedBuffer(data);
+        }
+      });
+    }
+    /**
+     * Directly load an externally decoded AudioBuffer
+     *
+     * @private
+     * @param {AudioBuffer} buffer
+     * @emits WaveSurfer#ready
+     */
+
+  }, {
+    key: "loadDecodedBuffer",
+    value: function loadDecodedBuffer(buffer) {
+      this.backend.load(buffer);
+      this.drawBuffer();
+      this.fireEvent('ready');
+      this.isReady = true;
+    }
+    /**
+     * Loads audio data from a Blob or File object
+     *
+     * @param {Blob|File} blob Audio data
+     * @example
+     */
+
+  }, {
+    key: "loadBlob",
+    value: function loadBlob(blob) {
+      var _this10 = this;
+
+      // Create file reader
+      var reader = new FileReader();
+      reader.addEventListener('progress', function (e) {
+        return _this10.onProgress(e);
+      });
+      reader.addEventListener('load', function (e) {
+        return _this10.loadArrayBuffer(e.target.result);
+      });
+      reader.addEventListener('error', function () {
+        return _this10.fireEvent('error', 'Error reading file');
+      });
+      reader.readAsArrayBuffer(blob);
+      this.empty();
+    }
+    /**
+     * Loads audio and re-renders the waveform.
+     *
+     * @param {string|HTMLMediaElement} url The url of the audio file or the
+     * audio element with the audio
+     * @param {?number[]|number[][]} peaks Wavesurfer does not have to decode
+     * the audio to render the waveform if this is specified
+     * @param {?string} preload (Use with backend `MediaElement`)
+     * `'none'|'metadata'|'auto'` Preload attribute for the media element
+     * @param {?number} duration The duration of the audio. This is used to
+     * render the peaks data in the correct size for the audio duration (as
+     * befits the current minPxPerSec and zoom value) without having to decode
+     * the audio.
+     * @example
+     * // using ajax or media element to load (depending on backend)
+     * wavesurfer.load('http://example.com/demo.wav');
+     *
+     * // setting preload attribute with media element backend and supplying
+     * peaks wavesurfer.load(
+     *   'http://example.com/demo.wav',
+     *   [0.0218, 0.0183, 0.0165, 0.0198, 0.2137, 0.2888],
+     *   true,
+     * );
+     */
+
+  }, {
+    key: "load",
+    value: function load(url, peaks, preload, duration) {
+      this.empty();
+
+      if (preload) {
+        // check whether the preload attribute will be usable and if not log
+        // a warning listing the reasons why not and nullify the variable
+        var preloadIgnoreReasons = {
+          "Preload is not 'auto', 'none' or 'metadata'": ['auto', 'metadata', 'none'].indexOf(preload) === -1,
+          'Peaks are not provided': !peaks,
+          'Backend is not of type MediaElement': this.params.backend !== 'MediaElement',
+          'Url is not of type string': typeof url !== 'string'
+        };
+        var activeReasons = Object.keys(preloadIgnoreReasons).filter(function (reason) {
+          return preloadIgnoreReasons[reason];
+        });
+
+        if (activeReasons.length) {
+          console.warn('Preload parameter of wavesurfer.load will be ignored because:\n\t- ' + activeReasons.join('\n\t- ')); // stop invalid values from being used
+
+          preload = null;
+        }
+      }
+
+      switch (this.params.backend) {
+        case 'WebAudio':
+          return this.loadBuffer(url, peaks, duration);
+
+        case 'MediaElement':
+          return this.loadMediaElement(url, peaks, preload, duration);
+      }
+    }
+    /**
+     * Loads audio using Web Audio buffer backend.
+     *
+     * @private
+     * @param {string} url
+     * @param {?number[]|number[][]} peaks
+     * @param {?number} duration
+     */
+
+  }, {
+    key: "loadBuffer",
+    value: function loadBuffer(url, peaks, duration) {
+      var _this11 = this;
+
+      var load = function load(action) {
+        if (action) {
+          _this11.tmpEvents.push(_this11.once('ready', action));
+        }
+
+        return _this11.getArrayBuffer(url, function (data) {
+          return _this11.loadArrayBuffer(data);
+        });
+      };
+
+      if (peaks) {
+        this.backend.setPeaks(peaks, duration);
+        this.drawBuffer();
+        this.tmpEvents.push(this.once('interaction', load));
+      } else {
+        return load();
+      }
+    }
+    /**
+     * Either create a media element, or load an existing media element.
+     *
+     * @private
+     * @param {string|HTMLMediaElement} urlOrElt Either a path to a media file, or an
+     * existing HTML5 Audio/Video Element
+     * @param {number[]|number[][]} peaks Array of peaks. Required to bypass web audio
+     * dependency
+     * @param {?boolean} preload Set to true if the preload attribute of the
+     * audio element should be enabled
+     * @param {?number} duration
+     */
+
+  }, {
+    key: "loadMediaElement",
+    value: function loadMediaElement(urlOrElt, peaks, preload, duration) {
+      var _this12 = this;
+
+      var url = urlOrElt;
+
+      if (typeof urlOrElt === 'string') {
+        this.backend.load(url, this.mediaContainer, peaks, preload);
+      } else {
+        var elt = urlOrElt;
+        this.backend.loadElt(elt, peaks); // If peaks are not provided,
+        // url = element.src so we can get peaks with web audio
+
+        url = elt.src;
+      }
+
+      this.tmpEvents.push(this.backend.once('canplay', function () {
+        _this12.drawBuffer();
+
+        _this12.fireEvent('ready');
+
+        _this12.isReady = true;
+      }), this.backend.once('error', function (err) {
+        return _this12.fireEvent('error', err);
+      })); // If no pre-decoded peaks provided or pre-decoded peaks are
+      // provided with forceDecode flag, attempt to download the
+      // audio file and decode it with Web Audio.
+
+      if (peaks) {
+        this.backend.setPeaks(peaks, duration);
+      }
+
+      if ((!peaks || this.params.forceDecode) && this.backend.supportsWebAudio()) {
+        this.getArrayBuffer(url, function (arraybuffer) {
+          _this12.decodeArrayBuffer(arraybuffer, function (buffer) {
+            _this12.backend.buffer = buffer;
+
+            _this12.backend.setPeaks(null);
+
+            _this12.drawBuffer();
+
+            _this12.fireEvent('waveform-ready');
+          });
+        });
+      }
+    }
+    /**
+     * Decode an array buffer and pass data to a callback
+     *
+     * @private
+     * @param {Object} arraybuffer
+     * @param {function} callback
+     */
+
+  }, {
+    key: "decodeArrayBuffer",
+    value: function decodeArrayBuffer(arraybuffer, callback) {
+      var _this13 = this;
+
+      this.arraybuffer = arraybuffer;
+      this.backend.decodeArrayBuffer(arraybuffer, function (data) {
+        // Only use the decoded data if we haven't been destroyed or
+        // another decode started in the meantime
+        if (!_this13.isDestroyed && _this13.arraybuffer == arraybuffer) {
+          callback(data);
+          _this13.arraybuffer = null;
+        }
+      }, function () {
+        return _this13.fireEvent('error', 'Error decoding audiobuffer');
+      });
+    }
+    /**
+     * Load an array buffer by ajax and pass to a callback
+     *
+     * @param {string} url
+     * @param {function} callback
+     * @private
+     */
+
+  }, {
+    key: "getArrayBuffer",
+    value: function getArrayBuffer(url, callback) {
+      var _this14 = this;
+
+      var ajax = util.ajax({
+        url: url,
+        responseType: 'arraybuffer',
+        xhr: this.params.xhr
+      });
+      this.currentAjax = ajax;
+      this.tmpEvents.push(ajax.on('progress', function (e) {
+        _this14.onProgress(e);
+      }), ajax.on('success', function (data, e) {
+        callback(data);
+        _this14.currentAjax = null;
+      }), ajax.on('error', function (e) {
+        _this14.fireEvent('error', 'XHR error: ' + e.target.statusText);
+
+        _this14.currentAjax = null;
+      }));
+      return ajax;
+    }
+    /**
+     * Called while the audio file is loading
+     *
+     * @private
+     * @param {Event} e
+     * @emits WaveSurfer#loading
+     */
+
+  }, {
+    key: "onProgress",
+    value: function onProgress(e) {
+      var percentComplete;
+
+      if (e.lengthComputable) {
+        percentComplete = e.loaded / e.total;
+      } else {
+        // Approximate progress with an asymptotic
+        // function, and assume downloads in the 1-3 MB range.
+        percentComplete = e.loaded / (e.loaded + 1000000);
+      }
+
+      this.fireEvent('loading', Math.round(percentComplete * 100), e.target);
+    }
+    /**
+     * Exports PCM data into a JSON array and opens in a new window.
+     *
+     * @param {number} length=1024 The scale in which to export the peaks. (Integer)
+     * @param {number} accuracy=10000 (Integer)
+     * @param {?boolean} noWindow Set to true to disable opening a new
+     * window with the JSON
+     * @param {number} start
+     * @todo Update exportPCM to work with new getPeaks signature
+     * @return {string} JSON of peaks
+     */
+
+  }, {
+    key: "exportPCM",
+    value: function exportPCM(length, accuracy, noWindow, start) {
+      length = length || 1024;
+      start = start || 0;
+      accuracy = accuracy || 10000;
+      noWindow = noWindow || false;
+      var peaks = this.backend.getPeaks(length, start);
+      var arr = [].map.call(peaks, function (val) {
+        return Math.round(val * accuracy) / accuracy;
+      });
+      var json = JSON.stringify(arr);
+
+      if (!noWindow) {
+        window.open('data:application/json;charset=utf-8,' + encodeURIComponent(json));
+      }
+
+      return json;
+    }
+    /**
+     * Save waveform image as data URI.
+     *
+     * The default format is `image/png`. Other supported types are
+     * `image/jpeg` and `image/webp`.
+     *
+     * @param {string} format='image/png'
+     * @param {number} quality=1
+     * @return {string} data URI of image
+     */
+
+  }, {
+    key: "exportImage",
+    value: function exportImage(format, quality) {
+      if (!format) {
+        format = 'image/png';
+      }
+
+      if (!quality) {
+        quality = 1;
+      }
+
+      return this.drawer.getImage(format, quality);
+    }
+    /**
+     * Cancel any ajax request currently in progress
+     */
+
+  }, {
+    key: "cancelAjax",
+    value: function cancelAjax() {
+      if (this.currentAjax) {
+        this.currentAjax.xhr.abort();
+        this.currentAjax = null;
+      }
+    }
+    /**
+     * @private
+     */
+
+  }, {
+    key: "clearTmpEvents",
+    value: function clearTmpEvents() {
+      this.tmpEvents.forEach(function (e) {
+        return e.un();
+      });
+    }
+    /**
+     * Display empty waveform.
+     */
+
+  }, {
+    key: "empty",
+    value: function empty() {
+      if (!this.backend.isPaused()) {
+        this.stop();
+        this.backend.disconnectSource();
+      }
+
+      this.isReady = false;
+      this.cancelAjax();
+      this.clearTmpEvents();
+      this.drawer.progress(0);
+      this.drawer.setWidth(0);
+      this.drawer.drawPeaks({
+        length: this.drawer.getWidth()
+      }, 0);
+    }
+    /**
+     * Remove events, elements and disconnect WebAudio nodes.
+     *
+     * @emits WaveSurfer#destroy
+     */
+
+  }, {
+    key: "destroy",
+    value: function destroy() {
+      this.destroyAllPlugins();
+      this.fireEvent('destroy');
+      this.cancelAjax();
+      this.clearTmpEvents();
+      this.unAll();
+
+      if (this.params.responsive !== false) {
+        window.removeEventListener('resize', this._onResize, true);
+        window.removeEventListener('orientationchange', this._onResize, true);
+      }
+
+      this.backend.destroy();
+      this.drawer.destroy();
+      this.isDestroyed = true;
+      this.isReady = false;
+      this.arraybuffer = null;
+    }
+  }]);
+
+  return WaveSurfer;
+}(util.Observer);
+
+exports.default = WaveSurfer;
+WaveSurfer.VERSION = "2.2.1";
+WaveSurfer.util = util;
+module.exports = exports.default;
+
+/***/ }),
+
+/***/ "./src/webaudio.js":
+/*!*************************!*\
+  !*** ./src/webaudio.js ***!
+  \*************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = void 0;
+
+var util = _interopRequireWildcard(__webpack_require__(/*! ./util */ "./src/util/index.js"));
+
+function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; if (obj != null) { 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; }
+
+function _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); }
+
+function _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; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
+
+function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
+
+function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
+
+function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
+
+// using constants to prevent someone writing the string wrong
+var PLAYING = 'playing';
+var PAUSED = 'paused';
+var FINISHED = 'finished';
+/**
+ * WebAudio backend
+ *
+ * @extends {Observer}
+ */
+
+var WebAudio =
+/*#__PURE__*/
+function (_util$Observer) {
+  _inherits(WebAudio, _util$Observer);
+
+  _createClass(WebAudio, [{
+    key: "supportsWebAudio",
+
+    /** @private */
+
+    /** @private */
+
+    /** @private */
+
+    /** @private */
+
+    /**
+     * Does the browser support this backend
+     *
+     * @return {boolean}
+     */
+    value: function supportsWebAudio() {
+      return !!(window.AudioContext || window.webkitAudioContext);
+    }
+    /**
+     * Get the audio context used by this backend or create one
+     *
+     * @return {AudioContext}
+     */
+
+  }, {
+    key: "getAudioContext",
+    value: function getAudioContext() {
+      if (!window.WaveSurferAudioContext) {
+        window.WaveSurferAudioContext = new (window.AudioContext || window.webkitAudioContext)();
+      }
+
+      return window.WaveSurferAudioContext;
+    }
+    /**
+     * Get the offline audio context used by this backend or create one
+     *
+     * @param {number} sampleRate
+     * @return {OfflineAudioContext}
+     */
+
+  }, {
+    key: "getOfflineAudioContext",
+    value: function getOfflineAudioContext(sampleRate) {
+      if (!window.WaveSurferOfflineAudioContext) {
+        window.WaveSurferOfflineAudioContext = new (window.OfflineAudioContext || window.webkitOfflineAudioContext)(1, 2, sampleRate);
+      }
+
+      return window.WaveSurferOfflineAudioContext;
+    }
+    /**
+     * Construct the backend
+     *
+     * @param {WavesurferParams} params
+     */
+
+  }]);
+
+  function WebAudio(params) {
+    var _this$stateBehaviors, _this$states;
+
+    var _this;
+
+    _classCallCheck(this, WebAudio);
+
+    _this = _possibleConstructorReturn(this, _getPrototypeOf(WebAudio).call(this));
+    /** @private */
+
+    _this.audioContext = null;
+    _this.offlineAudioContext = null;
+    _this.stateBehaviors = (_this$stateBehaviors = {}, _defineProperty(_this$stateBehaviors, PLAYING, {
+      init: function init() {
+        this.addOnAudioProcess();
+      },
+      getPlayedPercents: function getPlayedPercents() {
+        var duration = this.getDuration();
+        return this.getCurrentTime() / duration || 0;
+      },
+      getCurrentTime: function getCurrentTime() {
+        return this.startPosition + this.getPlayedTime();
+      }
+    }), _defineProperty(_this$stateBehaviors, PAUSED, {
+      init: function init() {
+        this.removeOnAudioProcess();
+      },
+      getPlayedPercents: function getPlayedPercents() {
+        var duration = this.getDuration();
+        return this.getCurrentTime() / duration || 0;
+      },
+      getCurrentTime: function getCurrentTime() {
+        return this.startPosition;
+      }
+    }), _defineProperty(_this$stateBehaviors, FINISHED, {
+      init: function init() {
+        this.removeOnAudioProcess();
+        this.fireEvent('finish');
+      },
+      getPlayedPercents: function getPlayedPercents() {
+        return 1;
+      },
+      getCurrentTime: function getCurrentTime() {
+        return this.getDuration();
+      }
+    }), _this$stateBehaviors);
+    _this.params = params;
+    /** @private */
+
+    _this.ac = params.audioContext || _this.getAudioContext();
+    /**@private */
+
+    _this.lastPlay = _this.ac.currentTime;
+    /** @private */
+
+    _this.startPosition = 0;
+    /** @private  */
+
+    _this.scheduledPause = null;
+    /** @private */
+
+    _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);
+    /** @private */
+
+    _this.analyser = null;
+    /** @private */
+
+    _this.buffer = null;
+    /** @private */
+
+    _this.filters = [];
+    /** @private */
+
+    _this.gainNode = null;
+    /** @private */
+
+    _this.mergedPeaks = null;
+    /** @private */
+
+    _this.offlineAc = null;
+    /** @private */
+
+    _this.peaks = null;
+    /** @private */
+
+    _this.playbackRate = 1;
+    /** @private */
+
+    _this.analyser = null;
+    /** @private */
+
+    _this.scriptNode = null;
+    /** @private */
+
+    _this.source = null;
+    /** @private */
+
+    _this.splitPeaks = [];
+    /** @private */
+
+    _this.state = null;
+    /** @private */
+
+    _this.explicitDuration = params.duration;
+    return _this;
+  }
+  /**
+   * Initialise the backend, called in `wavesurfer.createBackend()`
+   */
+
+
+  _createClass(WebAudio, [{
+    key: "init",
+    value: function init() {
+      this.createVolumeNode();
+      this.createScriptNode();
+      this.createAnalyserNode();
+      this.setState(PAUSED);
+      this.setPlaybackRate(this.params.audioRate);
+      this.setLength(0);
+    }
+    /** @private */
+
+  }, {
+    key: "disconnectFilters",
+    value: function disconnectFilters() {
+      if (this.filters) {
+        this.filters.forEach(function (filter) {
+          filter && filter.disconnect();
+        });
+        this.filters = null; // Reconnect direct path
+
+        this.analyser.connect(this.gainNode);
+      }
+    }
+    /** @private */
+
+  }, {
+    key: "setState",
+    value: function setState(state) {
+      if (this.state !== this.states[state]) {
+        this.state = this.states[state];
+        this.state.init.call(this);
+      }
+    }
+    /**
+     * Unpacked `setFilters()`
+     *
+     * @param {...AudioNode} filters
+     */
+
+  }, {
+    key: "setFilter",
+    value: function setFilter() {
+      for (var _len = arguments.length, filters = new Array(_len), _key = 0; _key < _len; _key++) {
+        filters[_key] = arguments[_key];
+      }
+
+      this.setFilters(filters);
+    }
+    /**
+     * Insert custom Web Audio nodes into the graph
+     *
+     * @param {AudioNode[]} filters Packed filters array
+     * @example
+     * const lowpass = wavesurfer.backend.ac.createBiquadFilter();
+     * wavesurfer.backend.setFilter(lowpass);
+     */
+
+  }, {
+    key: "setFilters",
+    value: function setFilters(filters) {
+      // Remove existing filters
+      this.disconnectFilters(); // Insert filters if filter array not empty
+
+      if (filters && filters.length) {
+        this.filters = filters; // Disconnect direct path before inserting filters
+
+        this.analyser.disconnect(); // Connect each filter in turn
+
+        filters.reduce(function (prev, curr) {
+          prev.connect(curr);
+          return curr;
+        }, this.analyser).connect(this.gainNode);
+      }
+    }
+    /** @private */
+
+  }, {
+    key: "createScriptNode",
+    value: function createScriptNode() {
+      if (this.params.audioScriptProcessor) {
+        this.scriptNode = this.params.audioScriptProcessor;
+      } else {
+        if (this.ac.createScriptProcessor) {
+          this.scriptNode = this.ac.createScriptProcessor(WebAudio.scriptBufferSize);
+        } else {
+          this.scriptNode = this.ac.createJavaScriptNode(WebAudio.scriptBufferSize);
+        }
+      }
+
+      this.scriptNode.connect(this.ac.destination);
+    }
+    /** @private */
+
+  }, {
+    key: "addOnAudioProcess",
+    value: function addOnAudioProcess() {
+      var _this2 = this;
+
+      this.scriptNode.onaudioprocess = function () {
+        var time = _this2.getCurrentTime();
+
+        if (time >= _this2.getDuration()) {
+          _this2.setState(FINISHED);
+
+          _this2.fireEvent('pause');
+        } else if (time >= _this2.scheduledPause) {
+          _this2.pause();
+        } else if (_this2.state === _this2.states[PLAYING]) {
+          _this2.fireEvent('audioprocess', time);
+        }
+      };
+    }
+    /** @private */
+
+  }, {
+    key: "removeOnAudioProcess",
+    value: function removeOnAudioProcess() {
+      this.scriptNode.onaudioprocess = function () {};
+    }
+    /** @private */
+
+  }, {
+    key: "createAnalyserNode",
+    value: function createAnalyserNode() {
+      this.analyser = this.ac.createAnalyser();
+      this.analyser.connect(this.gainNode);
+    }
+    /**
+     * Create the gain node needed to control the playback volume.
+     *
+     * @private
+     */
+
+  }, {
+    key: "createVolumeNode",
+    value: function createVolumeNode() {
+      // Create gain node using the AudioContext
+      if (this.ac.createGain) {
+        this.gainNode = this.ac.createGain();
+      } else {
+        this.gainNode = this.ac.createGainNode();
+      } // Add the gain node to the graph
+
+
+      this.gainNode.connect(this.ac.destination);
+    }
+    /**
+     * Set the sink id for the media player
+     *
+     * @param {string} deviceId String value representing audio device id.
+     */
+
+  }, {
+    key: "setSinkId",
+    value: function setSinkId(deviceId) {
+      if (deviceId) {
+        /**
+         * The webaudio API doesn't currently support setting the device
+         * output. Here we create an HTMLAudioElement, connect the
+         * webaudio stream to that element and setSinkId there.
+         */
+        var audio = new window.Audio();
+
+        if (!audio.setSinkId) {
+          return Promise.reject(new Error('setSinkId is not supported in your browser'));
+        }
+
+        audio.autoplay = true;
+        var dest = this.ac.createMediaStreamDestination();
+        this.gainNode.disconnect();
+        this.gainNode.connect(dest);
+        audio.srcObject = dest.stream;
+        return audio.setSinkId(deviceId);
+      } else {
+        return Promise.reject(new Error('Invalid deviceId: ' + deviceId));
+      }
+    }
+    /**
+     * Set the audio volume
+     *
+     * @param {number} value A floating point value between 0 and 1.
+     */
+
+  }, {
+    key: "setVolume",
+    value: function setVolume(value) {
+      this.gainNode.gain.setValueAtTime(value, this.ac.currentTime);
+    }
+    /**
+     * Get the current volume
+     *
+     * @return {number} value A floating point value between 0 and 1.
+     */
+
+  }, {
+    key: "getVolume",
+    value: function getVolume() {
+      return this.gainNode.gain.value;
+    }
+    /** @private */
+
+  }, {
+    key: "decodeArrayBuffer",
+    value: function decodeArrayBuffer(arraybuffer, callback, errback) {
+      if (!this.offlineAc) {
+        this.offlineAc = this.getOfflineAudioContext(this.ac && this.ac.sampleRate ? this.ac.sampleRate : 44100);
+      }
+
+      this.offlineAc.decodeAudioData(arraybuffer, function (data) {
+        return callback(data);
+      }, errback);
+    }
+    /**
+     * Set pre-decoded peaks
+     *
+     * @param {number[]|number[][]} peaks
+     * @param {?number} duration
+     */
+
+  }, {
+    key: "setPeaks",
+    value: function setPeaks(peaks, duration) {
+      if (duration != null) {
+        this.explicitDuration = duration;
+      }
+
+      this.peaks = peaks;
+    }
+    /**
+     * Set the rendered length (different from the length of the audio).
+     *
+     * @param {number} length
+     */
+
+  }, {
+    key: "setLength",
+    value: function setLength(length) {
+      // No resize, we can preserve the cached peaks.
+      if (this.mergedPeaks && length == 2 * this.mergedPeaks.length - 1 + 2) {
+        return;
+      }
+
+      this.splitPeaks = [];
+      this.mergedPeaks = []; // Set the last element of the sparse array so the peak arrays are
+      // appropriately sized for other calculations.
+
+      var channels = this.buffer ? this.buffer.numberOfChannels : 1;
+      var c;
+
+      for (c = 0; c < channels; c++) {
+        this.splitPeaks[c] = [];
+        this.splitPeaks[c][2 * (length - 1)] = 0;
+        this.splitPeaks[c][2 * (length - 1) + 1] = 0;
+      }
+
+      this.mergedPeaks[2 * (length - 1)] = 0;
+      this.mergedPeaks[2 * (length - 1) + 1] = 0;
+    }
+    /**
+     * Compute the max and min value of the waveform when broken into <length> subranges.
+     *
+     * @param {number} length How many subranges to break the waveform into.
+     * @param {number} first First sample in the required range.
+     * @param {number} last Last sample in the required range.
+     * @return {number[]|number[][]} Array of 2*<length> peaks or array of arrays of
+     * peaks consisting of (max, min) values for each subrange.
+     */
+
+  }, {
+    key: "getPeaks",
+    value: function getPeaks(length, first, last) {
+      if (this.peaks) {
+        return this.peaks;
+      }
+
+      if (!this.buffer) {
+        return [];
+      }
+
+      first = first || 0;
+      last = last || length - 1;
+      this.setLength(length);
+
+      if (!this.buffer) {
+        return this.params.splitChannels ? this.splitPeaks : this.mergedPeaks;
+      }
+      /**
+       * The following snippet fixes a buffering data issue on the Safari
+       * browser which returned undefined It creates the missing buffer based
+       * on 1 channel, 4096 samples and the sampleRate from the current
+       * webaudio context 4096 samples seemed to be the best fit for rendering
+       * will review this code once a stable version of Safari TP is out
+       */
+
+
+      if (!this.buffer.length) {
+        var newBuffer = this.createBuffer(1, 4096, this.sampleRate);
+        this.buffer = newBuffer.buffer;
+      }
+
+      var sampleSize = this.buffer.length / length;
+      var sampleStep = ~~(sampleSize / 10) || 1;
+      var channels = this.buffer.numberOfChannels;
+      var c;
+
+      for (c = 0; c < channels; c++) {
+        var peaks = this.splitPeaks[c];
+        var chan = this.buffer.getChannelData(c);
+        var i = void 0;
+
+        for (i = first; i <= last; i++) {
+          var start = ~~(i * sampleSize);
+          var end = ~~(start + sampleSize);
+          var min = 0;
+          var max = 0;
+          var j = void 0;
+
+          for (j = start; j < end; j += sampleStep) {
+            var value = chan[j];
+
+            if (value > max) {
+              max = value;
+            }
+
+            if (value < min) {
+              min = value;
+            }
+          }
+
+          peaks[2 * i] = max;
+          peaks[2 * i + 1] = min;
+
+          if (c == 0 || max > this.mergedPeaks[2 * i]) {
+            this.mergedPeaks[2 * i] = max;
+          }
+
+          if (c == 0 || min < this.mergedPeaks[2 * i + 1]) {
+            this.mergedPeaks[2 * i + 1] = min;
+          }
+        }
+      }
+
+      return this.params.splitChannels ? this.splitPeaks : this.mergedPeaks;
+    }
+    /**
+     * Get the position from 0 to 1
+     *
+     * @return {number}
+     */
+
+  }, {
+    key: "getPlayedPercents",
+    value: function getPlayedPercents() {
+      return this.state.getPlayedPercents.call(this);
+    }
+    /** @private */
+
+  }, {
+    key: "disconnectSource",
+    value: function disconnectSource() {
+      if (this.source) {
+        this.source.disconnect();
+      }
+    }
+    /**
+     * This is called when wavesurfer is destroyed
+     */
+
+  }, {
+    key: "destroy",
+    value: function destroy() {
+      if (!this.isPaused()) {
+        this.pause();
+      }
+
+      this.unAll();
+      this.buffer = null;
+      this.disconnectFilters();
+      this.disconnectSource();
+      this.gainNode.disconnect();
+      this.scriptNode.disconnect();
+      this.analyser.disconnect(); // close the audioContext if closeAudioContext option is set to true
+
+      if (this.params.closeAudioContext) {
+        // check if browser supports AudioContext.close()
+        if (typeof this.ac.close === 'function' && this.ac.state != 'closed') {
+          this.ac.close();
+        } // clear the reference to the audiocontext
+
+
+        this.ac = null; // clear the actual audiocontext, either passed as param or the
+        // global singleton
+
+        if (!this.params.audioContext) {
+          window.WaveSurferAudioContext = null;
+        } else {
+          this.params.audioContext = null;
+        } // clear the offlineAudioContext
+
+
+        window.WaveSurferOfflineAudioContext = null;
+      }
+    }
+    /**
+     * Loaded a decoded audio buffer
+     *
+     * @param {Object} buffer
+     */
+
+  }, {
+    key: "load",
+    value: function load(buffer) {
+      this.startPosition = 0;
+      this.lastPlay = this.ac.currentTime;
+      this.buffer = buffer;
+      this.createSource();
+    }
+    /** @private */
+
+  }, {
+    key: "createSource",
+    value: function createSource() {
+      this.disconnectSource();
+      this.source = this.ac.createBufferSource(); // adjust for old browsers
+
+      this.source.start = this.source.start || this.source.noteGrainOn;
+      this.source.stop = this.source.stop || this.source.noteOff;
+      this.source.playbackRate.setValueAtTime(this.playbackRate, this.ac.currentTime);
+      this.source.buffer = this.buffer;
+      this.source.connect(this.analyser);
+    }
+    /**
+     * Used by `wavesurfer.isPlaying()` and `wavesurfer.playPause()`
+     *
+     * @return {boolean}
+     */
+
+  }, {
+    key: "isPaused",
+    value: function isPaused() {
+      return this.state !== this.states[PLAYING];
+    }
+    /**
+     * Used by `wavesurfer.getDuration()`
+     *
+     * @return {number}
+     */
+
+  }, {
+    key: "getDuration",
+    value: function getDuration() {
+      if (this.explicitDuration) {
+        return this.explicitDuration;
+      }
+
+      if (!this.buffer) {
+        return 0;
+      }
+
+      return this.buffer.duration;
+    }
+    /**
+     * Used by `wavesurfer.seekTo()`
+     *
+     * @param {number} start Position to start at in seconds
+     * @param {number} end Position to end at in seconds
+     * @return {{start: number, end: number}}
+     */
+
+  }, {
+    key: "seekTo",
+    value: function seekTo(start, end) {
+      if (!this.buffer) {
+        return;
+      }
+
+      this.scheduledPause = null;
+
+      if (start == null) {
+        start = this.getCurrentTime();
+
+        if (start >= this.getDuration()) {
+          start = 0;
+        }
+      }
+
+      if (end == null) {
+        end = this.getDuration();
+      }
+
+      this.startPosition = start;
+      this.lastPlay = this.ac.currentTime;
+
+      if (this.state === this.states[FINISHED]) {
+        this.setState(PAUSED);
+      }
+
+      return {
+        start: start,
+        end: end
+      };
+    }
+    /**
+     * Get the playback position in seconds
+     *
+     * @return {number}
+     */
+
+  }, {
+    key: "getPlayedTime",
+    value: function getPlayedTime() {
+      return (this.ac.currentTime - this.lastPlay) * this.playbackRate;
+    }
+    /**
+     * Plays the loaded audio region.
+     *
+     * @param {number} start Start offset in seconds, relative to the beginning
+     * of a clip.
+     * @param {number} end When to stop relative to the beginning of a clip.
+     */
+
+  }, {
+    key: "play",
+    value: function play(start, end) {
+      if (!this.buffer) {
+        return;
+      } // need to re-create source on each playback
+
+
+      this.createSource();
+      var adjustedTime = this.seekTo(start, end);
+      start = adjustedTime.start;
+      end = adjustedTime.end;
+      this.scheduledPause = end;
+      this.source.start(0, start, end - start);
+
+      if (this.ac.state == 'suspended') {
+        this.ac.resume && this.ac.resume();
+      }
+
+      this.setState(PLAYING);
+      this.fireEvent('play');
+    }
+    /**
+     * Pauses the loaded audio.
+     */
+
+  }, {
+    key: "pause",
+    value: function pause() {
+      this.scheduledPause = null;
+      this.startPosition += this.getPlayedTime();
+      this.source && this.source.stop(0);
+      this.setState(PAUSED);
+      this.fireEvent('pause');
+    }
+    /**
+     * Returns the current time in seconds relative to the audio-clip's
+     * duration.
+     *
+     * @return {number}
+     */
+
+  }, {
+    key: "getCurrentTime",
+    value: function getCurrentTime() {
+      return this.state.getCurrentTime.call(this);
+    }
+    /**
+     * Returns the current playback rate. (0=no playback, 1=normal playback)
+     *
+     * @return {number}
+     */
+
+  }, {
+    key: "getPlaybackRate",
+    value: function getPlaybackRate() {
+      return this.playbackRate;
+    }
+    /**
+     * Set the audio source playback rate.
+     *
+     * @param {number} value
+     */
+
+  }, {
+    key: "setPlaybackRate",
+    value: function setPlaybackRate(value) {
+      value = value || 1;
+
+      if (this.isPaused()) {
+        this.playbackRate = value;
+      } else {
+        this.pause();
+        this.playbackRate = value;
+        this.play();
+      }
+    }
+  }]);
+
+  return WebAudio;
+}(util.Observer);
+
+exports.default = WebAudio;
+WebAudio.scriptBufferSize = 256;
+module.exports = exports.default;
+
+/***/ })
+
+/******/ });
+});
+//# sourceMappingURL=wavesurfer.js.map
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/wavesurfer.js.map
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/wavesurfer.js.map	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/wavesurfer.js.map	(revision 33546)
@@ -0,0 +1,1 @@
+{"version":3,"sources":["webpack://WaveSurfer/webpack/universalModuleDefinition","webpack://WaveSurfer/webpack/bootstrap","webpack://WaveSurfer/./node_modules/debounce/index.js","webpack://WaveSurfer/./src/drawer.js","webpack://WaveSurfer/./src/drawer.multicanvas.js","webpack://WaveSurfer/./src/mediaelement.js","webpack://WaveSurfer/./src/peakcache.js","webpack://WaveSurfer/./src/util/ajax.js","webpack://WaveSurfer/./src/util/extend.js","webpack://WaveSurfer/./src/util/frame.js","webpack://WaveSurfer/./src/util/get-id.js","webpack://WaveSurfer/./src/util/index.js","webpack://WaveSurfer/./src/util/max.js","webpack://WaveSurfer/./src/util/min.js","webpack://WaveSurfer/./src/util/observer.js","webpack://WaveSurfer/./src/util/prevent-click.js","webpack://WaveSurfer/./src/util/request-animation-frame.js","webpack://WaveSurfer/./src/util/style.js","webpack://WaveSurfer/./src/wavesurfer.js","webpack://WaveSurfer/./src/webaudio.js"],"names":["Drawer","container","params","width","height","pixelRatio","lastPos","wrapper","el","styles","util","style","appendChild","document","createElement","display","position","userSelect","webkitUserSelect","fillParent","scrollParent","overflowX","hideScrollbar","overflowY","setupWrapperEvents","e","noPrevent","preventDefault","clientX","targetTouches","bbox","getBoundingClientRect","nominalWidth","parentWidth","getWidth","progress","rtl","right","left","scrollLeft","scrollWidth","addEventListener","scrollbarHeight","offsetHeight","clientHeight","clientY","bottom","interact","fireEvent","handleEvent","peaks","length","start","end","setWidth","clearWave","barWidth","drawBars","drawWave","percent","recenterOnPosition","immediate","half","clientWidth","maxScroll","target","offset","rate","Math","max","min","x","round","updateSize","minPxDelta","pos","autoCenter","newPos","updateProgress","unAll","parentNode","removeChild","channelIndex","Observer","MultiCanvas","maxCanvasWidth","maxCanvasElementWidth","hasProgressCanvas","waveColor","progressColor","halfPixel","canvases","progressWave","createWrapper","createElements","zIndex","top","overflow","boxSizing","borderRightStyle","pointerEvents","addCanvas","updateCursor","borderRightWidth","cursorWidth","borderRightColor","cursorColor","totalWidth","requiredCanvases","ceil","removeCanvas","forEach","entry","i","canvasWidth","updateDimensions","clearWaveForEntry","leftOffset","wave","waveCtx","getContext","progressCtx","push","lastEntry","pop","parentElement","elementWidth","canvas","offsetLeft","clearRect","prepareDraw","absmax","hasMinVals","offsetY","halfH","undefined","peakIndexScale","bar","gap","barGap","step","scale","first","last","peak","floor","h","fillRect","reflectedPeaks","len","drawLine","setFillStyles","drawLineToContext","ctx","canvasStart","canvasEnd","j","halfOffset","absmaxHalf","beginPath","moveTo","lineTo","closePath","fill","y","startCanvas","endCanvas","intersection","x1","y1","x2","y2","fillRectToContext","fn","frame","Array","channels","splitChannels","setHeight","channelPeaks","barHeight","normalize","some","call","val","fillStyle","type","quality","images","map","toDataURL","MediaElement","media","currentTime","duration","paused","playbackRate","play","pause","volume","mediaType","toLowerCase","elementPosition","buffer","onPlayEnd","setPlaybackRate","audioRate","createTimer","onAudioProcess","isPaused","getCurrentTime","requestAnimationFrame","window","webkitRequestAnimationFrame","on","url","preload","controls","mediaControls","autoplay","src","prevMedia","querySelector","_load","elt","load","setVolume","explicitDuration","Infinity","seekable","getDuration","value","clearPlayEnd","seekTo","promise","setPlayEnd","_onPlayEnd","time","un","deviceId","setSinkId","Promise","reject","Error","removeMediaElementOnDestroy","WebAudio","PeakCache","clearPeakCache","peakCacheRanges","peakCacheLength","uncachedRanges","filter","item","arr","concat","sort","a","b","uncachedRangePairs","peakCacheRangePairs","ajax","options","instance","xhr","XMLHttpRequest","fired100","open","method","responseType","requestHeaders","header","setRequestHeader","key","withCredentials","lengthComputable","loaded","total","status","response","send","extend","dest","sources","source","Object","keys","func","args","getId","random","toString","substring","values","largest","smallest","Number","handlers","event","name","callback","splice","handler","apply","setTimeout","preventClickHandler","stopPropagation","body","removeEventListener","preventClick","mozRequestAnimationFrame","oRequestAnimationFrame","msRequestAnimationFrame","element","bind","prop","PluginClass","ws","WaveSurfer","wavesurfer","init","defaultParams","audioContext","audioScriptProcessor","backend","backgroundColor","dragSelection","forceDecode","loopSelection","mediaContainer","minPxPerSec","partialRender","devicePixelRatio","screen","deviceXDPI","logicalXDPI","plugins","renderer","responsive","skipLength","backends","transform","setBackgroundColor","savedVolume","isMuted","tmpEvents","currentAjax","arraybuffer","drawer","peakCache","Backend","initialisedPluginList","isDestroyed","isReady","prevWidth","_onResize","debounce","registerPlugins","createDrawer","createBackend","createPeakCache","plugin","addPlugin","deferInit","initPlugin","staticProps","pluginStaticProp","Instance","observerPrototypeKeys","getOwnPropertyNames","prototype","destroyPlugin","destroy","drawBuffer","getPlayedPercents","supportsWebAudio","seconds","skip","seekAndCenter","recenter","isFinite","console","error","oldScrollParent","newVolume","getVolume","getPlaybackRate","setMute","mute","filters","color","background","newRanges","addRangeToPeakCache","getPeaks","drawPeaks","pxPerSec","decodeArrayBuffer","data","loadDecodedBuffer","blob","reader","FileReader","onProgress","loadArrayBuffer","result","readAsArrayBuffer","empty","preloadIgnoreReasons","indexOf","activeReasons","reason","warn","join","loadBuffer","loadMediaElement","action","once","getArrayBuffer","setPeaks","urlOrElt","loadElt","err","statusText","percentComplete","accuracy","noWindow","json","JSON","stringify","encodeURIComponent","format","getImage","abort","stop","disconnectSource","cancelAjax","clearTmpEvents","destroyAllPlugins","VERSION","__VERSION__","PLAYING","PAUSED","FINISHED","AudioContext","webkitAudioContext","WaveSurferAudioContext","sampleRate","WaveSurferOfflineAudioContext","OfflineAudioContext","webkitOfflineAudioContext","offlineAudioContext","stateBehaviors","addOnAudioProcess","startPosition","getPlayedTime","removeOnAudioProcess","ac","getAudioContext","lastPlay","scheduledPause","states","create","analyser","gainNode","mergedPeaks","offlineAc","scriptNode","splitPeaks","state","createVolumeNode","createScriptNode","createAnalyserNode","setState","setLength","disconnect","connect","setFilters","disconnectFilters","reduce","prev","curr","createScriptProcessor","scriptBufferSize","createJavaScriptNode","destination","onaudioprocess","createAnalyser","createGain","createGainNode","audio","Audio","createMediaStreamDestination","srcObject","stream","gain","setValueAtTime","errback","getOfflineAudioContext","decodeAudioData","numberOfChannels","c","newBuffer","createBuffer","sampleSize","sampleStep","chan","getChannelData","closeAudioContext","close","createSource","createBufferSource","noteGrainOn","noteOff","adjustedTime","resume"],"mappings":";;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AACD,O;QCVA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;;QAEA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;;;QAGA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA,0CAA0C,gCAAgC;QAC1E;QACA;;QAEA;QACA;QACA;QACA,wDAAwD,kBAAkB;QAC1E;QACA,iDAAiD,cAAc;QAC/D;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA,yCAAyC,iCAAiC;QAC1E,gHAAgH,mBAAmB,EAAE;QACrI;QACA;;QAEA;QACA;QACA;QACA,2BAA2B,0BAA0B,EAAE;QACvD,iCAAiC,eAAe;QAChD;QACA;QACA;;QAEA;QACA,sDAAsD,+DAA+D;;QAErH;QACA;;;QAGA;QACA;;;;;;;;;;;;AClFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW,SAAS;AACpB,WAAW,OAAO;AAClB,WAAW,QAAQ;AACnB;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;;;;;;;;;;;;;;;;;;;ACrEA;;;;;;;;;;;;;;;;;;;;;;;;AAEA;;;;;IAKqBA,M;;;;;AACjB;;;;AAIA,kBAAYC,SAAZ,EAAuBC,MAAvB,EAA+B;AAAA;;AAAA;;AAC3B;AACA;;AACA,UAAKD,SAAL,GAAiBA,SAAjB;AACA;;;;;AAIA,UAAKC,MAAL,GAAcA,MAAd;AACA;;;;;AAIA,UAAKC,KAAL,GAAa,CAAb;AACA;;;;;AAIA,UAAKC,MAAL,GAAcF,MAAM,CAACE,MAAP,GAAgB,MAAK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","file":"wavesurfer.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"WaveSurfer\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"WaveSurfer\"] = factory();\n\telse\n\t\troot[\"WaveSurfer\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/wavesurfer.js\");\n","/**\n * Returns a function, that, as long as it continues to be invoked, will not\n * be triggered. The function will be called after it stops being called for\n * N milliseconds. If `immediate` is passed, trigger the function on the\n * leading edge, instead of the trailing. The function also has a property 'clear' \n * that is a function which will clear the timer to prevent previously scheduled executions. \n *\n * @source underscore.js\n * @see http://unscriptable.com/2009/03/20/debouncing-javascript-methods/\n * @param {Function} function to wrap\n * @param {Number} timeout in ms (`100`)\n * @param {Boolean} whether to execute at the beginning (`false`)\n * @api public\n */\nfunction debounce(func, wait, immediate){\n  var timeout, args, context, timestamp, result;\n  if (null == wait) wait = 100;\n\n  function later() {\n    var last = Date.now() - timestamp;\n\n    if (last < wait && last >= 0) {\n      timeout = setTimeout(later, wait - last);\n    } else {\n      timeout = null;\n      if (!immediate) {\n        result = func.apply(context, args);\n        context = args = null;\n      }\n    }\n  };\n\n  var debounced = function(){\n    context = this;\n    args = arguments;\n    timestamp = Date.now();\n    var callNow = immediate && !timeout;\n    if (!timeout) timeout = setTimeout(later, wait);\n    if (callNow) {\n      result = func.apply(context, args);\n      context = args = null;\n    }\n\n    return result;\n  };\n\n  debounced.clear = function() {\n    if (timeout) {\n      clearTimeout(timeout);\n      timeout = null;\n    }\n  };\n  \n  debounced.flush = function() {\n    if (timeout) {\n      result = func.apply(context, args);\n      context = args = null;\n      \n      clearTimeout(timeout);\n      timeout = null;\n    }\n  };\n\n  return debounced;\n};\n\n// Adds compatibility for ES modules\ndebounce.debounce = debounce;\n\nmodule.exports = debounce;\n","import * as util from './util';\n\n/**\n * Parent class for renderers\n *\n * @extends {Observer}\n */\nexport default class Drawer extends util.Observer {\n    /**\n     * @param {HTMLElement} container The container node of the wavesurfer instance\n     * @param {WavesurferParams} params The wavesurfer initialisation options\n     */\n    constructor(container, params) {\n        super();\n        /** @private */\n        this.container = container;\n        /**\n         * @type {WavesurferParams}\n         * @private\n         */\n        this.params = params;\n        /**\n         * The width of the renderer\n         * @type {number}\n         */\n        this.width = 0;\n        /**\n         * The height of the renderer\n         * @type {number}\n         */\n        this.height = params.height * this.params.pixelRatio;\n        /** @private */\n        this.lastPos = 0;\n        /**\n         * The `<wave>` element which is added to the container\n         * @type {HTMLElement}\n         */\n        this.wrapper = null;\n    }\n\n    /**\n     * Alias of `util.style`\n     *\n     * @param {HTMLElement} el The element that the styles will be applied to\n     * @param {Object} styles The map of propName: attribute, both are used as-is\n     * @return {HTMLElement} el\n     */\n    style(el, styles) {\n        return util.style(el, styles);\n    }\n\n    /**\n     * Create the wrapper `<wave>` element, style it and set up the events for\n     * interaction\n     */\n    createWrapper() {\n        this.wrapper = this.container.appendChild(\n            document.createElement('wave')\n        );\n\n        this.style(this.wrapper, {\n            display: 'block',\n            position: 'relative',\n            userSelect: 'none',\n            webkitUserSelect: 'none',\n            height: this.params.height + 'px'\n        });\n\n        if (this.params.fillParent || this.params.scrollParent) {\n            this.style(this.wrapper, {\n                width: '100%',\n                overflowX: this.params.hideScrollbar ? 'hidden' : 'auto',\n                overflowY: 'hidden'\n            });\n        }\n\n        this.setupWrapperEvents();\n    }\n\n    /**\n     * Handle click event\n     *\n     * @param {Event} e Click event\n     * @param {?boolean} noPrevent Set to true to not call `e.preventDefault()`\n     * @return {number} Playback position from 0 to 1\n     */\n    handleEvent(e, noPrevent) {\n        !noPrevent && e.preventDefault();\n\n        const clientX = e.targetTouches\n            ? e.targetTouches[0].clientX\n            : e.clientX;\n        const bbox = this.wrapper.getBoundingClientRect();\n\n        const nominalWidth = this.width;\n        const parentWidth = this.getWidth();\n\n        let progress;\n        if (!this.params.fillParent && nominalWidth < parentWidth) {\n            progress =\n                (this.params.rtl ? bbox.right - clientX : clientX - bbox.left) *\n                    (this.params.pixelRatio / nominalWidth) || 0;\n\n            if (progress > 1) {\n                progress = 1;\n            }\n        } else {\n            progress =\n                ((this.params.rtl\n                    ? bbox.right - clientX\n                    : clientX - bbox.left) +\n                    this.wrapper.scrollLeft) /\n                    this.wrapper.scrollWidth || 0;\n        }\n\n        return progress;\n    }\n\n    /**\n     * @private\n     */\n    setupWrapperEvents() {\n        this.wrapper.addEventListener('click', e => {\n            const scrollbarHeight =\n                this.wrapper.offsetHeight - this.wrapper.clientHeight;\n            if (scrollbarHeight != 0) {\n                // scrollbar is visible.  Check if click was on it\n                const bbox = this.wrapper.getBoundingClientRect();\n                if (e.clientY >= bbox.bottom - scrollbarHeight) {\n                    // ignore mousedown as it was on the scrollbar\n                    return;\n                }\n            }\n\n            if (this.params.interact) {\n                this.fireEvent('click', e, this.handleEvent(e));\n            }\n        });\n\n        this.wrapper.addEventListener('scroll', e =>\n            this.fireEvent('scroll', e)\n        );\n    }\n\n    /**\n     * Draw peaks on the canvas\n     *\n     * @param {number[]|number[][]} peaks Can also be an array of arrays for split channel\n     * rendering\n     * @param {number} length The width of the area that should be drawn\n     * @param {number} start The x-offset of the beginning of the area that\n     * should be rendered\n     * @param {number} end The x-offset of the end of the area that should be\n     * rendered\n     */\n    drawPeaks(peaks, length, start, end) {\n        if (!this.setWidth(length)) {\n            this.clearWave();\n        }\n\n        this.params.barWidth\n            ? this.drawBars(peaks, 0, start, end)\n            : this.drawWave(peaks, 0, start, end);\n    }\n\n    /**\n     * Scroll to the beginning\n     */\n    resetScroll() {\n        if (this.wrapper !== null) {\n            this.wrapper.scrollLeft = 0;\n        }\n    }\n\n    /**\n     * Recenter the view-port at a certain percent of the waveform\n     *\n     * @param {number} percent Value from 0 to 1 on the waveform\n     */\n    recenter(percent) {\n        const position = this.wrapper.scrollWidth * percent;\n        this.recenterOnPosition(position, true);\n    }\n\n    /**\n     * Recenter the view-port on a position, either scroll there immediately or\n     * in steps of 5 pixels\n     *\n     * @param {number} position X-offset in pixels\n     * @param {boolean} immediate Set to true to immediately scroll somewhere\n     */\n    recenterOnPosition(position, immediate) {\n        const scrollLeft = this.wrapper.scrollLeft;\n        const half = ~~(this.wrapper.clientWidth / 2);\n        const maxScroll = this.wrapper.scrollWidth - this.wrapper.clientWidth;\n        let target = position - half;\n        let offset = target - scrollLeft;\n\n        if (maxScroll == 0) {\n            // no need to continue if scrollbar is not there\n            return;\n        }\n\n        // if the cursor is currently visible...\n        if (!immediate && -half <= offset && offset < half) {\n            // we'll limit the \"re-center\" rate.\n            const rate = 5;\n            offset = Math.max(-rate, Math.min(rate, offset));\n            target = scrollLeft + offset;\n        }\n\n        // limit target to valid range (0 to maxScroll)\n        target = Math.max(0, Math.min(maxScroll, target));\n        // no use attempting to scroll if we're not moving\n        if (target != scrollLeft) {\n            this.wrapper.scrollLeft = target;\n        }\n    }\n\n    /**\n     * Get the current scroll position in pixels\n     *\n     * @return {number}\n     */\n    getScrollX() {\n        let x = 0;\n        if (this.wrapper) {\n            const pixelRatio = this.params.pixelRatio;\n            x = Math.round(this.wrapper.scrollLeft * pixelRatio);\n\n            // In cases of elastic scroll (safari with mouse wheel) you can\n            // scroll beyond the limits of the container\n            // Calculate and floor the scrollable extent to make sure an out\n            // of bounds value is not returned\n            // Ticket #1312\n            if (this.params.scrollParent) {\n                const maxScroll = ~~(\n                    this.wrapper.scrollWidth * pixelRatio -\n                    this.getWidth()\n                );\n                x = Math.min(maxScroll, Math.max(0, x));\n            }\n        }\n        return x;\n    }\n\n    /**\n     * Get the width of the container\n     *\n     * @return {number}\n     */\n    getWidth() {\n        return Math.round(this.container.clientWidth * this.params.pixelRatio);\n    }\n\n    /**\n     * Set the width of the container\n     *\n     * @param {number} width\n     */\n    setWidth(width) {\n        if (this.width == width) {\n            return false;\n        }\n\n        this.width = width;\n\n        if (this.params.fillParent || this.params.scrollParent) {\n            this.style(this.wrapper, {\n                width: ''\n            });\n        } else {\n            this.style(this.wrapper, {\n                width: ~~(this.width / this.params.pixelRatio) + 'px'\n            });\n        }\n\n        this.updateSize();\n        return true;\n    }\n\n    /**\n     * Set the height of the container\n     *\n     * @param {number} height\n     */\n    setHeight(height) {\n        if (height == this.height) {\n            return false;\n        }\n        this.height = height;\n\n        this.style(this.wrapper, {\n            height: ~~(this.height / this.params.pixelRatio) + 'px'\n        });\n\n        this.updateSize();\n        return true;\n    }\n\n    /**\n     * Called by wavesurfer when progress should be rendered\n     *\n     * @param {number} progress From 0 to 1\n     */\n    progress(progress) {\n        const minPxDelta = 1 / this.params.pixelRatio;\n        const pos = Math.round(progress * this.width) * minPxDelta;\n\n        if (pos < this.lastPos || pos - this.lastPos >= minPxDelta) {\n            this.lastPos = pos;\n\n            if (this.params.scrollParent && this.params.autoCenter) {\n                const newPos = ~~(this.wrapper.scrollWidth * progress);\n                this.recenterOnPosition(newPos);\n            }\n\n            this.updateProgress(pos);\n        }\n    }\n\n    /**\n     * This is called when wavesurfer is destroyed\n     */\n    destroy() {\n        this.unAll();\n        if (this.wrapper) {\n            if (this.wrapper.parentNode == this.container) {\n                this.container.removeChild(this.wrapper);\n            }\n            this.wrapper = null;\n        }\n    }\n\n    /* Renderer-specific methods */\n\n    /**\n     * Called after cursor related params have changed.\n     *\n     * @abstract\n     */\n    updateCursor() {}\n\n    /**\n     * Called when the size of the container changes so the renderer can adjust\n     *\n     * @abstract\n     */\n    updateSize() {}\n\n    /**\n     * Draw a waveform with bars\n     *\n     * @abstract\n     * @param {number[]|number[][]} peaks Can also be an array of arrays for split channel\n     * rendering\n     * @param {number} channelIndex The index of the current channel. Normally\n     * should be 0\n     * @param {number} start The x-offset of the beginning of the area that\n     * should be rendered\n     * @param {number} end The x-offset of the end of the area that should be\n     * rendered\n     */\n    drawBars(peaks, channelIndex, start, end) {}\n\n    /**\n     * Draw a waveform\n     *\n     * @abstract\n     * @param {number[]|number[][]} peaks Can also be an array of arrays for split channel\n     * rendering\n     * @param {number} channelIndex The index of the current channel. Normally\n     * should be 0\n     * @param {number} start The x-offset of the beginning of the area that\n     * should be rendered\n     * @param {number} end The x-offset of the end of the area that should be\n     * rendered\n     */\n    drawWave(peaks, channelIndex, start, end) {}\n\n    /**\n     * Clear the waveform\n     *\n     * @abstract\n     */\n    clearWave() {}\n\n    /**\n     * Render the new progress\n     *\n     * @abstract\n     * @param {number} position X-Offset of progress position in pixels\n     */\n    updateProgress(position) {}\n}\n","import Drawer from './drawer';\nimport * as util from './util';\n\n/**\n * @typedef {Object} CanvasEntry\n * @private\n * @property {HTMLElement} wave The wave node\n * @property {CanvasRenderingContext2D} waveCtx The canvas rendering context\n * @property {?HTMLElement} progress The progress wave node\n * @property {?CanvasRenderingContext2D} progressCtx The progress wave canvas\n * rendering context\n * @property {?number} start Start of the area the canvas should render, between 0 and 1\n * @property {?number} end End of the area the canvas should render, between 0 and 1\n */\n\n/**\n * MultiCanvas renderer for wavesurfer. Is currently the default and sole built\n * in renderer.\n */\nexport default class MultiCanvas extends Drawer {\n    /**\n     * @param {HTMLElement} container The container node of the wavesurfer instance\n     * @param {WavesurferParams} params The wavesurfer initialisation options\n     */\n    constructor(container, params) {\n        super(container, params);\n        /**\n         * @type {number}\n         * @private\n         */\n        this.maxCanvasWidth = params.maxCanvasWidth;\n        /**\n         * @private\n         * @type {number}\n         */\n        this.maxCanvasElementWidth = Math.round(\n            params.maxCanvasWidth / params.pixelRatio\n        );\n\n        /**\n         * Whether or not the progress wave is rendered. If the `waveColor`\n         * and `progressColor` are the same color it is not.\n         * @type {boolean}\n         */\n        this.hasProgressCanvas = params.waveColor != params.progressColor;\n        /**\n         * @private\n         * @type {number}\n         */\n        this.halfPixel = 0.5 / params.pixelRatio;\n        /**\n         * @private\n         * @type {Array}\n         */\n        this.canvases = [];\n        /** @private */\n        this.progressWave = null;\n    }\n\n    /**\n     * Initialize the drawer\n     */\n    init() {\n        this.createWrapper();\n        this.createElements();\n    }\n\n    /**\n     * Create the canvas elements and style them\n     *\n     * @private\n     */\n    createElements() {\n        this.progressWave = this.wrapper.appendChild(\n            this.style(document.createElement('wave'), {\n                position: 'absolute',\n                zIndex: 3,\n                left: 0,\n                top: 0,\n                bottom: 0,\n                overflow: 'hidden',\n                width: '0',\n                display: 'none',\n                boxSizing: 'border-box',\n                borderRightStyle: 'solid',\n                pointerEvents: 'none'\n            })\n        );\n\n        this.addCanvas();\n        this.updateCursor();\n    }\n\n    /**\n     * Update cursor style from params.\n     */\n    updateCursor() {\n        this.style(this.progressWave, {\n            borderRightWidth: this.params.cursorWidth + 'px',\n            borderRightColor: this.params.cursorColor\n        });\n    }\n\n    /**\n     * Adjust to the updated size by adding or removing canvases\n     */\n    updateSize() {\n        const totalWidth = Math.round(this.width / this.params.pixelRatio);\n        // No need more canvas if it's only for 2 peaks (there the same for overlaps !)\n        const requiredCanvases = Math.ceil(\n            totalWidth / (this.maxCanvasElementWidth + 2)\n        );\n\n        while (this.canvases.length < requiredCanvases) {\n            this.addCanvas();\n        }\n\n        while (this.canvases.length > requiredCanvases) {\n            this.removeCanvas();\n        }\n\n        this.canvases.forEach((entry, i) => {\n            // Add some overlap to prevent vertical white stripes, keep the\n            // width even for simplicity\n            let canvasWidth =\n                this.maxCanvasWidth + 2 * Math.ceil(this.params.pixelRatio / 2);\n\n            if (i == this.canvases.length - 1) {\n                canvasWidth =\n                    this.width -\n                    this.maxCanvasWidth * (this.canvases.length - 1);\n            }\n\n            this.updateDimensions(entry, canvasWidth, this.height);\n            this.clearWaveForEntry(entry);\n        });\n    }\n\n    /**\n     * Add a canvas to the canvas list\n     *\n     * @private\n     */\n    addCanvas() {\n        const entry = {};\n        const leftOffset = this.maxCanvasElementWidth * this.canvases.length;\n\n        entry.wave = this.wrapper.appendChild(\n            this.style(document.createElement('canvas'), {\n                position: 'absolute',\n                zIndex: 2,\n                left: leftOffset + 'px',\n                top: 0,\n                bottom: 0,\n                height: '100%',\n                pointerEvents: 'none'\n            })\n        );\n        entry.waveCtx = entry.wave.getContext('2d');\n\n        if (this.hasProgressCanvas) {\n            entry.progress = this.progressWave.appendChild(\n                this.style(document.createElement('canvas'), {\n                    position: 'absolute',\n                    left: leftOffset + 'px',\n                    top: 0,\n                    bottom: 0,\n                    height: '100%'\n                })\n            );\n            entry.progressCtx = entry.progress.getContext('2d');\n        }\n\n        this.canvases.push(entry);\n    }\n\n    /**\n     * Pop one canvas from the list\n     *\n     * @private\n     */\n    removeCanvas() {\n        const lastEntry = this.canvases.pop();\n        lastEntry.wave.parentElement.removeChild(lastEntry.wave);\n        if (this.hasProgressCanvas) {\n            lastEntry.progress.parentElement.removeChild(lastEntry.progress);\n        }\n    }\n\n    /**\n     * Update the dimensions of a canvas element\n     *\n     * @private\n     * @param {CanvasEntry} entry\n     * @param {number} width The new width of the element\n     * @param {number} height The new height of the element\n     */\n    updateDimensions(entry, width, height) {\n        const elementWidth = Math.round(width / this.params.pixelRatio);\n        const totalWidth = Math.round(this.width / this.params.pixelRatio);\n\n        // Where the canvas starts and ends in the waveform, represented as a\n        // decimal between 0 and 1.\n        entry.start = entry.waveCtx.canvas.offsetLeft / totalWidth || 0;\n        entry.end = entry.start + elementWidth / totalWidth;\n\n        entry.waveCtx.canvas.width = width;\n        entry.waveCtx.canvas.height = height;\n        this.style(entry.waveCtx.canvas, { width: elementWidth + 'px' });\n\n        this.style(this.progressWave, { display: 'block' });\n\n        if (this.hasProgressCanvas) {\n            entry.progressCtx.canvas.width = width;\n            entry.progressCtx.canvas.height = height;\n            this.style(entry.progressCtx.canvas, {\n                width: elementWidth + 'px'\n            });\n        }\n    }\n\n    /**\n     * Clear the whole waveform\n     */\n    clearWave() {\n        this.canvases.forEach(entry => this.clearWaveForEntry(entry));\n    }\n\n    /**\n     * Clear one canvas\n     *\n     * @private\n     * @param {CanvasEntry} entry\n     */\n    clearWaveForEntry(entry) {\n        entry.waveCtx.clearRect(\n            0,\n            0,\n            entry.waveCtx.canvas.width,\n            entry.waveCtx.canvas.height\n        );\n        if (this.hasProgressCanvas) {\n            entry.progressCtx.clearRect(\n                0,\n                0,\n                entry.progressCtx.canvas.width,\n                entry.progressCtx.canvas.height\n            );\n        }\n    }\n\n    /**\n     * Draw a waveform with bars\n     *\n     * @param {number[]|number[][]} peaks Can also be an array of arrays for split channel\n     * rendering\n     * @param {number} channelIndex The index of the current channel. Normally\n     * should be 0. Must be an integer.\n     * @param {number} start The x-offset of the beginning of the area that\n     * should be rendered\n     * @param {number} end The x-offset of the end of the area that should be\n     * rendered\n     */\n    drawBars(peaks, channelIndex, start, end) {\n        return this.prepareDraw(\n            peaks,\n            channelIndex,\n            start,\n            end,\n            ({ absmax, hasMinVals, height, offsetY, halfH, peaks }) => {\n                // if drawBars was called within ws.empty we don't pass a start and\n                // don't want anything to happen\n                if (start === undefined) {\n                    return;\n                }\n                // Skip every other value if there are negatives.\n                const peakIndexScale = hasMinVals ? 2 : 1;\n                const length = peaks.length / peakIndexScale;\n                const bar = this.params.barWidth * this.params.pixelRatio;\n                const gap =\n                    this.params.barGap === null\n                        ? Math.max(this.params.pixelRatio, ~~(bar / 2))\n                        : Math.max(\n                              this.params.pixelRatio,\n                              this.params.barGap * this.params.pixelRatio\n                          );\n                const step = bar + gap;\n\n                const scale = length / this.width;\n                const first = start;\n                const last = end;\n                let i;\n\n                for (i = first; i < last; i += step) {\n                    const peak =\n                        peaks[Math.floor(i * scale * peakIndexScale)] || 0;\n                    const h = Math.round((peak / absmax) * halfH);\n                    this.fillRect(\n                        i + this.halfPixel,\n                        halfH - h + offsetY,\n                        bar + this.halfPixel,\n                        h * 2\n                    );\n                }\n            }\n        );\n    }\n\n    /**\n     * Draw a waveform\n     *\n     * @param {number[]|number[][]} peaks Can also be an array of arrays for split channel\n     * rendering\n     * @param {number} channelIndex The index of the current channel. Normally\n     * should be 0\n     * @param {number?} start The x-offset of the beginning of the area that\n     * should be rendered (If this isn't set only a flat line is rendered)\n     * @param {number?} end The x-offset of the end of the area that should be\n     * rendered\n     */\n    drawWave(peaks, channelIndex, start, end) {\n        return this.prepareDraw(\n            peaks,\n            channelIndex,\n            start,\n            end,\n            ({ absmax, hasMinVals, height, offsetY, halfH, peaks }) => {\n                if (!hasMinVals) {\n                    const reflectedPeaks = [];\n                    const len = peaks.length;\n                    let i;\n                    for (i = 0; i < len; i++) {\n                        reflectedPeaks[2 * i] = peaks[i];\n                        reflectedPeaks[2 * i + 1] = -peaks[i];\n                    }\n                    peaks = reflectedPeaks;\n                }\n\n                // if drawWave was called within ws.empty we don't pass a start and\n                // end and simply want a flat line\n                if (start !== undefined) {\n                    this.drawLine(peaks, absmax, halfH, offsetY, start, end);\n                }\n\n                // Always draw a median line\n                this.fillRect(\n                    0,\n                    halfH + offsetY - this.halfPixel,\n                    this.width,\n                    this.halfPixel\n                );\n            }\n        );\n    }\n\n    /**\n     * Tell the canvas entries to render their portion of the waveform\n     *\n     * @private\n     * @param {number[]} peaks Peak data\n     * @param {number} absmax Maximum peak value (absolute)\n     * @param {number} halfH Half the height of the waveform\n     * @param {number} offsetY Offset to the top\n     * @param {number} start The x-offset of the beginning of the area that\n     * should be rendered\n     * @param {number} end The x-offset of the end of the area that\n     * should be rendered\n     */\n    drawLine(peaks, absmax, halfH, offsetY, start, end) {\n        this.canvases.forEach(entry => {\n            this.setFillStyles(entry);\n            this.drawLineToContext(\n                entry,\n                entry.waveCtx,\n                peaks,\n                absmax,\n                halfH,\n                offsetY,\n                start,\n                end\n            );\n            this.drawLineToContext(\n                entry,\n                entry.progressCtx,\n                peaks,\n                absmax,\n                halfH,\n                offsetY,\n                start,\n                end\n            );\n        });\n    }\n\n    /**\n     * Render the actual waveform line on a canvas\n     *\n     * @private\n     * @param {CanvasEntry} entry\n     * @param {Canvas2DContextAttributes} ctx Essentially `entry.[wave|progress]Ctx`\n     * @param {number[]} peaks\n     * @param {number} absmax Maximum peak value (absolute)\n     * @param {number} halfH Half the height of the waveform\n     * @param {number} offsetY Offset to the top\n     * @param {number} start The x-offset of the beginning of the area that\n     * should be rendered\n     * @param {number} end The x-offset of the end of the area that\n     * should be rendered\n     */\n    drawLineToContext(entry, ctx, peaks, absmax, halfH, offsetY, start, end) {\n        if (!ctx) {\n            return;\n        }\n\n        const length = peaks.length / 2;\n\n        const first = Math.round(length * entry.start);\n        // Use one more peak value to make sure we join peaks at ends -- unless,\n        // of course, this is the last canvas.\n        const last = Math.round(length * entry.end) + 1;\n\n        const canvasStart = first;\n        const canvasEnd = last;\n        let i;\n        let j;\n\n        const scale = entry.progress.width / (canvasEnd - canvasStart - 1);\n        // optimization\n        const halfOffset = halfH + offsetY;\n        const absmaxHalf = absmax / halfH;\n\n        ctx.beginPath();\n        ctx.moveTo((canvasStart - first) * scale, halfOffset);\n\n        ctx.lineTo(\n            (canvasStart - first) * scale,\n            halfOffset - Math.round((peaks[2 * canvasStart] || 0) / absmaxHalf)\n        );\n\n        for (i = canvasStart; i < canvasEnd; i++) {\n            const peak = peaks[2 * i] || 0;\n            const h = Math.round(peak / absmaxHalf);\n            ctx.lineTo((i - first) * scale + this.halfPixel, halfOffset - h);\n        }\n\n        // Draw the bottom edge going backwards, to make a single\n        // closed hull to fill.\n        for (j = canvasEnd - 1; j >= canvasStart; j--) {\n            const peak = peaks[2 * j + 1] || 0;\n            const h = Math.round(peak / absmaxHalf);\n            ctx.lineTo((j - first) * scale + this.halfPixel, halfOffset - h);\n        }\n\n        ctx.lineTo(\n            (canvasStart - first) * scale,\n            halfOffset -\n                Math.round((peaks[2 * canvasStart + 1] || 0) / absmaxHalf)\n        );\n\n        ctx.closePath();\n        ctx.fill();\n    }\n\n    /**\n     * Draw a rectangle on the waveform\n     *\n     * @param {number} x\n     * @param {number} y\n     * @param {number} width\n     * @param {number} height\n     */\n    fillRect(x, y, width, height) {\n        const startCanvas = Math.floor(x / this.maxCanvasWidth);\n        const endCanvas = Math.min(\n            Math.ceil((x + width) / this.maxCanvasWidth) + 1,\n            this.canvases.length\n        );\n        let i;\n        for (i = startCanvas; i < endCanvas; i++) {\n            const entry = this.canvases[i];\n            const leftOffset = i * this.maxCanvasWidth;\n\n            const intersection = {\n                x1: Math.max(x, i * this.maxCanvasWidth),\n                y1: y,\n                x2: Math.min(\n                    x + width,\n                    i * this.maxCanvasWidth + entry.waveCtx.canvas.width\n                ),\n                y2: y + height\n            };\n\n            if (intersection.x1 < intersection.x2) {\n                this.setFillStyles(entry);\n\n                this.fillRectToContext(\n                    entry.waveCtx,\n                    intersection.x1 - leftOffset,\n                    intersection.y1,\n                    intersection.x2 - intersection.x1,\n                    intersection.y2 - intersection.y1\n                );\n\n                this.fillRectToContext(\n                    entry.progressCtx,\n                    intersection.x1 - leftOffset,\n                    intersection.y1,\n                    intersection.x2 - intersection.x1,\n                    intersection.y2 - intersection.y1\n                );\n            }\n        }\n    }\n\n    /**\n     * Performs preparation tasks and calculations which are shared by drawBars and drawWave\n     *\n     * @private\n     * @param {number[]|number[][]} peaks Can also be an array of arrays for split channel\n     * rendering\n     * @param {number} channelIndex The index of the current channel. Normally\n     * should be 0\n     * @param {number?} start The x-offset of the beginning of the area that\n     * should be rendered (If this isn't set only a flat line is rendered)\n     * @param {number?} end The x-offset of the end of the area that should be\n     * rendered\n     * @param {function} fn The render function to call\n     */\n    prepareDraw(peaks, channelIndex, start, end, fn) {\n        return util.frame(() => {\n            // Split channels and call this function with the channelIndex set\n            if (peaks[0] instanceof Array) {\n                const channels = peaks;\n                if (this.params.splitChannels) {\n                    this.setHeight(\n                        channels.length *\n                            this.params.height *\n                            this.params.pixelRatio\n                    );\n                    return channels.forEach((channelPeaks, i) =>\n                        this.prepareDraw(channelPeaks, i, start, end, fn)\n                    );\n                }\n                peaks = channels[0];\n            }\n            // calculate maximum modulation value, either from the barHeight\n            // parameter or if normalize=true from the largest value in the peak\n            // set\n            let absmax = 1 / this.params.barHeight;\n            if (this.params.normalize) {\n                const max = util.max(peaks);\n                const min = util.min(peaks);\n                absmax = -min > max ? -min : max;\n            }\n\n            // Bar wave draws the bottom only as a reflection of the top,\n            // so we don't need negative values\n            const hasMinVals = [].some.call(peaks, val => val < 0);\n            const height = this.params.height * this.params.pixelRatio;\n            const offsetY = height * channelIndex || 0;\n            const halfH = height / 2;\n\n            return fn({\n                absmax: absmax,\n                hasMinVals: hasMinVals,\n                height: height,\n                offsetY: offsetY,\n                halfH: halfH,\n                peaks: peaks\n            });\n        })();\n    }\n\n    /**\n     * Draw the actual rectangle on a canvas\n     *\n     * @private\n     * @param {Canvas2DContextAttributes} ctx\n     * @param {number} x\n     * @param {number} y\n     * @param {number} width\n     * @param {number} height\n     */\n    fillRectToContext(ctx, x, y, width, height) {\n        if (!ctx) {\n            return;\n        }\n        ctx.fillRect(x, y, width, height);\n    }\n\n    /**\n     * Set the fill styles for a certain entry (wave and progress)\n     *\n     * @private\n     * @param {CanvasEntry} entry\n     */\n    setFillStyles(entry) {\n        entry.waveCtx.fillStyle = this.params.waveColor;\n        if (this.hasProgressCanvas) {\n            entry.progressCtx.fillStyle = this.params.progressColor;\n        }\n    }\n\n    /**\n     * Return image data of the waveform\n     *\n     * @param {string} type='image/png' An optional value of a format type.\n     * @param {number} quality=0.92 An optional value between 0 and 1.\n     * @return {string|string[]} images A data URL or an array of data URLs\n     */\n    getImage(type, quality) {\n        const images = this.canvases.map(entry =>\n            entry.wave.toDataURL(type, quality)\n        );\n        return images.length > 1 ? images : images[0];\n    }\n\n    /**\n     * Render the new progress\n     *\n     * @param {number} position X-Offset of progress position in pixels\n     */\n    updateProgress(position) {\n        this.style(this.progressWave, { width: position + 'px' });\n    }\n}\n","import WebAudio from './webaudio';\nimport * as util from './util';\n\n/**\n * MediaElement backend\n */\nexport default class MediaElement extends WebAudio {\n    /**\n     * Construct the backend\n     *\n     * @param {WavesurferParams} params\n     */\n    constructor(params) {\n        super(params);\n        /** @private */\n        this.params = params;\n\n        // Dummy media to catch errors\n        /** @private */\n        this.media = {\n            currentTime: 0,\n            duration: 0,\n            paused: true,\n            playbackRate: 1,\n            play() {},\n            pause() {},\n            volume: 0\n        };\n\n        /** @private */\n        this.mediaType = params.mediaType.toLowerCase();\n        /** @private */\n        this.elementPosition = params.elementPosition;\n        /** @private */\n        this.peaks = null;\n        /** @private */\n        this.playbackRate = 1;\n        /** @private */\n        this.volume = 1;\n        /** @private */\n        this.buffer = null;\n        /** @private */\n        this.onPlayEnd = null;\n    }\n\n    /**\n     * Initialise the backend, called in `wavesurfer.createBackend()`\n     */\n    init() {\n        this.setPlaybackRate(this.params.audioRate);\n        this.createTimer();\n    }\n\n    /**\n     * Create a timer to provide a more precise `audioprocess` event.\n     *\n     * @private\n     */\n    createTimer() {\n        const onAudioProcess = () => {\n            if (this.isPaused()) {\n                return;\n            }\n            this.fireEvent('audioprocess', this.getCurrentTime());\n\n            // Call again in the next frame\n            const requestAnimationFrame =\n                window.requestAnimationFrame ||\n                window.webkitRequestAnimationFrame;\n            requestAnimationFrame(onAudioProcess);\n        };\n\n        this.on('play', onAudioProcess);\n\n        // Update the progress one more time to prevent it from being stuck in\n        // case of lower framerates\n        this.on('pause', () => {\n            this.fireEvent('audioprocess', this.getCurrentTime());\n        });\n    }\n\n    /**\n     * Create media element with url as its source,\n     * and append to container element.\n     *\n     * @param {string} url Path to media file\n     * @param {HTMLElement} container HTML element\n     * @param {number[]|number[][]} peaks Array of peak data\n     * @param {string} preload HTML 5 preload attribute value\n     */\n    load(url, container, peaks, preload) {\n        const media = document.createElement(this.mediaType);\n        media.controls = this.params.mediaControls;\n        media.autoplay = this.params.autoplay || false;\n        media.preload = preload == null ? 'auto' : preload;\n        media.src = url;\n        media.style.width = '100%';\n\n        const prevMedia = container.querySelector(this.mediaType);\n        if (prevMedia) {\n            container.removeChild(prevMedia);\n        }\n        container.appendChild(media);\n\n        this._load(media, peaks);\n    }\n\n    /**\n     * Load existing media element.\n     *\n     * @param {HTMLMediaElement} elt HTML5 Audio or Video element\n     * @param {number[]|number[][]} peaks Array of peak data\n     */\n    loadElt(elt, peaks) {\n        elt.controls = this.params.mediaControls;\n        elt.autoplay = this.params.autoplay || false;\n\n        this._load(elt, peaks);\n    }\n\n    /**\n     * Private method called by both load (from url)\n     * and loadElt (existing media element).\n     *\n     * @param {HTMLMediaElement} media HTML5 Audio or Video element\n     * @param {number[]|number[][]} peaks Array of peak data\n     * @private\n     */\n    _load(media, peaks) {\n        // load must be called manually on iOS, otherwise peaks won't draw\n        // until a user interaction triggers load --> 'ready' event\n        if (typeof media.load == 'function') {\n            // Resets the media element and restarts the media resource. Any\n            // pending events are discarded. How much media data is fetched is\n            // still affected by the preload attribute.\n            media.load();\n        }\n\n        media.addEventListener('error', () => {\n            this.fireEvent('error', 'Error loading media element');\n        });\n\n        media.addEventListener('canplay', () => {\n            this.fireEvent('canplay');\n        });\n\n        media.addEventListener('ended', () => {\n            this.fireEvent('finish');\n        });\n\n        // Listen to and relay play and pause events to enable\n        // playback control from the external media element\n        media.addEventListener('play', () => {\n            this.fireEvent('play');\n        });\n\n        media.addEventListener('pause', () => {\n            this.fireEvent('pause');\n        });\n\n        this.media = media;\n        this.peaks = peaks;\n        this.onPlayEnd = null;\n        this.buffer = null;\n        this.setPlaybackRate(this.playbackRate);\n        this.setVolume(this.volume);\n    }\n\n    /**\n     * Used by `wavesurfer.isPlaying()` and `wavesurfer.playPause()`\n     *\n     * @return {boolean}\n     */\n    isPaused() {\n        return !this.media || this.media.paused;\n    }\n\n    /**\n     * Used by `wavesurfer.getDuration()`\n     *\n     * @return {number}\n     */\n    getDuration() {\n        if (this.explicitDuration) {\n            return this.explicitDuration;\n        }\n        let duration = (this.buffer || this.media).duration;\n        if (duration >= Infinity) {\n            // streaming audio\n            duration = this.media.seekable.end(0);\n        }\n        return duration;\n    }\n\n    /**\n     * Returns the current time in seconds relative to the audio-clip's\n     * duration.\n     *\n     * @return {number}\n     */\n    getCurrentTime() {\n        return this.media && this.media.currentTime;\n    }\n\n    /**\n     * Get the position from 0 to 1\n     *\n     * @return {number}\n     */\n    getPlayedPercents() {\n        return this.getCurrentTime() / this.getDuration() || 0;\n    }\n\n    /**\n     * Get the audio source playback rate.\n     *\n     * @return {number}\n     */\n    getPlaybackRate() {\n        return this.playbackRate || this.media.playbackRate;\n    }\n\n    /**\n     * Set the audio source playback rate.\n     *\n     * @param {number} value\n     */\n    setPlaybackRate(value) {\n        this.playbackRate = value || 1;\n        this.media.playbackRate = this.playbackRate;\n    }\n\n    /**\n     * Used by `wavesurfer.seekTo()`\n     *\n     * @param {number} start Position to start at in seconds\n     */\n    seekTo(start) {\n        if (start != null) {\n            this.media.currentTime = start;\n        }\n        this.clearPlayEnd();\n    }\n\n    /**\n     * Plays the loaded audio region.\n     *\n     * @param {number} start Start offset in seconds, relative to the beginning\n     * of a clip.\n     * @param {number} end When to stop, relative to the beginning of a clip.\n     * @emits MediaElement#play\n     * @return {Promise}\n     */\n    play(start, end) {\n        this.seekTo(start);\n        const promise = this.media.play();\n        end && this.setPlayEnd(end);\n\n        return promise;\n    }\n\n    /**\n     * Pauses the loaded audio.\n     *\n     * @emits MediaElement#pause\n     * @return {Promise}\n     */\n    pause() {\n        let promise;\n\n        if (this.media) {\n            promise = this.media.pause();\n        }\n        this.clearPlayEnd();\n\n        return promise;\n    }\n\n    /** @private */\n    setPlayEnd(end) {\n        this._onPlayEnd = time => {\n            if (time >= end) {\n                this.pause();\n                this.seekTo(end);\n            }\n        };\n        this.on('audioprocess', this._onPlayEnd);\n    }\n\n    /** @private */\n    clearPlayEnd() {\n        if (this._onPlayEnd) {\n            this.un('audioprocess', this._onPlayEnd);\n            this._onPlayEnd = null;\n        }\n    }\n\n    /**\n     * Compute the max and min value of the waveform when broken into\n     * <length> subranges.\n     *\n     * @param {number} length How many subranges to break the waveform into.\n     * @param {number} first First sample in the required range.\n     * @param {number} last Last sample in the required range.\n     * @return {number[]|number[][]} Array of 2*<length> peaks or array of\n     * arrays of peaks consisting of (max, min) values for each subrange.\n     */\n    getPeaks(length, first, last) {\n        if (this.buffer) {\n            return super.getPeaks(length, first, last);\n        }\n        return this.peaks || [];\n    }\n\n    /**\n     * Set the sink id for the media player\n     *\n     * @param {string} deviceId String value representing audio device id.\n     */\n    setSinkId(deviceId) {\n        if (deviceId) {\n            if (!this.media.setSinkId) {\n                return Promise.reject(\n                    new Error('setSinkId is not supported in your browser')\n                );\n            }\n            return this.media.setSinkId(deviceId);\n        }\n\n        return Promise.reject(new Error('Invalid deviceId: ' + deviceId));\n    }\n\n    /**\n     * Get the current volume\n     *\n     * @return {number} value A floating point value between 0 and 1.\n     */\n    getVolume() {\n        return this.volume || this.media.volume;\n    }\n\n    /**\n     * Set the audio volume\n     *\n     * @param {number} value A floating point value between 0 and 1.\n     */\n    setVolume(value) {\n        this.volume = value;\n        this.media.volume = this.volume;\n    }\n\n    /**\n     * This is called when wavesurfer is destroyed\n     *\n     */\n    destroy() {\n        this.pause();\n        this.unAll();\n\n        if (\n            this.params.removeMediaElementOnDestroy &&\n            this.media &&\n            this.media.parentNode\n        ) {\n            this.media.parentNode.removeChild(this.media);\n        }\n\n        this.media = null;\n    }\n}\n","/**\n * Caches the decoded peaks data to improve rendering speed for large audio\n *\n * Is used if the option parameter `partialRender` is set to `true`\n */\nexport default class PeakCache {\n    /**\n     * Instantiate cache\n     */\n    constructor() {\n        this.clearPeakCache();\n    }\n\n    /**\n     * Empty the cache\n     */\n    clearPeakCache() {\n        /**\n         * Flat array with entries that are always in pairs to mark the\n         * beginning and end of each subrange.  This is a convenience so we can\n         * iterate over the pairs for easy set difference operations.\n         * @private\n         */\n        this.peakCacheRanges = [];\n        /**\n         * Length of the entire cachable region, used for resetting the cache\n         * when this changes (zoom events, for instance).\n         * @private\n         */\n        this.peakCacheLength = -1;\n    }\n\n    /**\n     * Add a range of peaks to the cache\n     *\n     * @param {number} length The length of the range\n     * @param {number} start The x offset of the start of the range\n     * @param {number} end The x offset of the end of the range\n     * @return {number[][]}\n     */\n    addRangeToPeakCache(length, start, end) {\n        if (length != this.peakCacheLength) {\n            this.clearPeakCache();\n            this.peakCacheLength = length;\n        }\n\n        // Return ranges that weren't in the cache before the call.\n        let uncachedRanges = [];\n        let i = 0;\n        // Skip ranges before the current start.\n        while (\n            i < this.peakCacheRanges.length &&\n            this.peakCacheRanges[i] < start\n        ) {\n            i++;\n        }\n        // If |i| is even, |start| falls after an existing range.  Otherwise,\n        // |start| falls between an existing range, and the uncached region\n        // starts when we encounter the next node in |peakCacheRanges| or\n        // |end|, whichever comes first.\n        if (i % 2 == 0) {\n            uncachedRanges.push(start);\n        }\n        while (\n            i < this.peakCacheRanges.length &&\n            this.peakCacheRanges[i] <= end\n        ) {\n            uncachedRanges.push(this.peakCacheRanges[i]);\n            i++;\n        }\n        // If |i| is even, |end| is after all existing ranges.\n        if (i % 2 == 0) {\n            uncachedRanges.push(end);\n        }\n\n        // Filter out the 0-length ranges.\n        uncachedRanges = uncachedRanges.filter((item, pos, arr) => {\n            if (pos == 0) {\n                return item != arr[pos + 1];\n            } else if (pos == arr.length - 1) {\n                return item != arr[pos - 1];\n            }\n            return item != arr[pos - 1] && item != arr[pos + 1];\n        });\n\n        // Merge the two ranges together, uncachedRanges will either contain\n        // wholly new points, or duplicates of points in peakCacheRanges.  If\n        // duplicates are detected, remove both and extend the range.\n        this.peakCacheRanges = this.peakCacheRanges.concat(uncachedRanges);\n        this.peakCacheRanges = this.peakCacheRanges\n            .sort((a, b) => a - b)\n            .filter((item, pos, arr) => {\n                if (pos == 0) {\n                    return item != arr[pos + 1];\n                } else if (pos == arr.length - 1) {\n                    return item != arr[pos - 1];\n                }\n                return item != arr[pos - 1] && item != arr[pos + 1];\n            });\n\n        // Push the uncached ranges into an array of arrays for ease of\n        // iteration in the functions that call this.\n        const uncachedRangePairs = [];\n        for (i = 0; i < uncachedRanges.length; i += 2) {\n            uncachedRangePairs.push([uncachedRanges[i], uncachedRanges[i + 1]]);\n        }\n\n        return uncachedRangePairs;\n    }\n\n    /**\n     * For testing\n     *\n     * @return {number[][]}\n     */\n    getCacheRanges() {\n        const peakCacheRangePairs = [];\n        let i;\n        for (i = 0; i < this.peakCacheRanges.length; i += 2) {\n            peakCacheRangePairs.push([\n                this.peakCacheRanges[i],\n                this.peakCacheRanges[i + 1]\n            ]);\n        }\n        return peakCacheRangePairs;\n    }\n}\n","import Observer from './observer';\n\n/**\n * Perform an ajax request\n *\n * @param {Options} options Description\n *\n * @returns {Object} Observer instance\n */\nexport default function ajax(options) {\n    const instance = new Observer();\n    const xhr = new XMLHttpRequest();\n    let fired100 = false;\n    xhr.open(options.method || 'GET', options.url, true);\n    xhr.responseType = options.responseType || 'json';\n\n    if (options.xhr) {\n        if (options.xhr.requestHeaders) {\n            // add custom request headers\n            options.xhr.requestHeaders.forEach(header => {\n                xhr.setRequestHeader(header.key, header.value);\n            });\n        }\n        if (options.xhr.withCredentials) {\n            // use credentials\n            xhr.withCredentials = true;\n        }\n    }\n\n    xhr.addEventListener('progress', e => {\n        instance.fireEvent('progress', e);\n        if (e.lengthComputable && e.loaded == e.total) {\n            fired100 = true;\n        }\n    });\n    xhr.addEventListener('load', e => {\n        if (!fired100) {\n            instance.fireEvent('progress', e);\n        }\n        instance.fireEvent('load', e);\n        if (200 == xhr.status || 206 == xhr.status) {\n            instance.fireEvent('success', xhr.response, e);\n        } else {\n            instance.fireEvent('error', e);\n        }\n    });\n    xhr.addEventListener('error', e => instance.fireEvent('error', e));\n    xhr.send();\n    instance.xhr = xhr;\n    return instance;\n}\n","/**\n * Extend an object shallowly with others\n *\n * @param {Object} dest The target object\n * @param {Object[]} sources The objects to use for extending\n *\n * @return {Object} Merged object\n */\nexport default function extend(dest, ...sources) {\n    sources.forEach(source => {\n        Object.keys(source).forEach(key => {\n            dest[key] = source[key];\n        });\n    });\n    return dest;\n}\n","import reqAnimationFrame from './request-animation-frame';\n\n/**\n * Create a function which will be called at the next requestAnimationFrame\n * cycle\n *\n * @param {function} func The function to call\n *\n * @return {func} The function wrapped within a requestAnimationFrame\n */\nexport default function frame(func) {\n    return (...args) => reqAnimationFrame(() => func(...args));\n}\n","/**\n * Get a random prefixed ID\n *\n * @returns {String} Random ID\n */\nexport default function getId() {\n    return (\n        'wavesurfer_' +\n        Math.random()\n            .toString(32)\n            .substring(2)\n    );\n}\n","export { default as ajax } from './ajax';\nexport { default as getId } from './get-id';\nexport { default as max } from './max';\nexport { default as min } from './min';\nexport { default as Observer } from './observer';\nexport { default as extend } from './extend';\nexport { default as style } from './style';\nexport { default as requestAnimationFrame } from './request-animation-frame';\nexport { default as frame } from './frame';\nexport { default as debounce } from 'debounce';\nexport { default as preventClick } from './prevent-click';\n","/**\n * Get the largest value\n *\n * @param   {Array} values Array of numbers\n * @returns {Number} Largest number found\n */\nexport default function max(values) {\n    let largest = -Infinity;\n    Object.keys(values).forEach(i => {\n        if (values[i] > largest) {\n            largest = values[i];\n        }\n    });\n    return largest;\n}\n","/**\n * Get the smallest value\n *\n * @param   {Array} values Array of numbers\n * @returns {Number}       Smallest number found\n */\nexport default function min(values) {\n    let smallest = Number(Infinity);\n    Object.keys(values).forEach(i => {\n        if (values[i] < smallest) {\n            smallest = values[i];\n        }\n    });\n    return smallest;\n}\n","/**\n * @typedef {Object} ListenerDescriptor\n * @property {string} name The name of the event\n * @property {function} callback The callback\n * @property {function} un The function to call to remove the listener\n */\n\n/**\n * Observer class\n */\nexport default class Observer {\n    /**\n     * Instantiate Observer\n     */\n    constructor() {\n        /**\n         * @private\n         * @todo Initialise the handlers here already and remove the conditional\n         * assignment in `on()`\n         */\n        this.handlers = null;\n    }\n    /**\n     * Attach a handler function for an event.\n     *\n     * @param {string} event Name of the event to listen to\n     * @param {function} fn The callback to trigger when the event is fired\n     * @return {ListenerDescriptor}\n     */\n    on(event, fn) {\n        if (!this.handlers) {\n            this.handlers = {};\n        }\n\n        let handlers = this.handlers[event];\n        if (!handlers) {\n            handlers = this.handlers[event] = [];\n        }\n        handlers.push(fn);\n\n        // Return an event descriptor\n        return {\n            name: event,\n            callback: fn,\n            un: (e, fn) => this.un(e, fn)\n        };\n    }\n\n    /**\n     * Remove an event handler.\n     *\n     * @param {string} event Name of the event the listener that should be\n     * removed listens to\n     * @param {function} fn The callback that should be removed\n     */\n    un(event, fn) {\n        if (!this.handlers) {\n            return;\n        }\n\n        const handlers = this.handlers[event];\n        let i;\n        if (handlers) {\n            if (fn) {\n                for (i = handlers.length - 1; i >= 0; i--) {\n                    if (handlers[i] == fn) {\n                        handlers.splice(i, 1);\n                    }\n                }\n            } else {\n                handlers.length = 0;\n            }\n        }\n    }\n\n    /**\n     * Remove all event handlers.\n     */\n    unAll() {\n        this.handlers = null;\n    }\n\n    /**\n     * Attach a handler to an event. The handler is executed at most once per\n     * event type.\n     *\n     * @param {string} event The event to listen to\n     * @param {function} handler The callback that is only to be called once\n     * @return {ListenerDescriptor}\n     */\n    once(event, handler) {\n        const fn = (...args) => {\n            /*  eslint-disable no-invalid-this */\n            handler.apply(this, args);\n            /*  eslint-enable no-invalid-this */\n            setTimeout(() => {\n                this.un(event, fn);\n            }, 0);\n        };\n        return this.on(event, fn);\n    }\n\n    /**\n     * Manually fire an event\n     *\n     * @param {string} event The event to fire manually\n     * @param {...any} args The arguments with which to call the listeners\n     */\n    fireEvent(event, ...args) {\n        if (!this.handlers) {\n            return;\n        }\n        const handlers = this.handlers[event];\n        handlers &&\n            handlers.forEach(fn => {\n                fn(...args);\n            });\n    }\n}\n","function preventClickHandler(e) {\n    e.stopPropagation();\n    document.body.removeEventListener('click', preventClickHandler, true);\n}\n\nexport default function preventClick(values) {\n    document.body.addEventListener('click', preventClickHandler, true);\n}\n","/**\n * Returns the requestAnimationFrame function for the browser, or a shim with\n * setTimeout if none is found\n *\n * @return {function}\n */\nexport default (\n    window.requestAnimationFrame ||\n    window.webkitRequestAnimationFrame ||\n    window.mozRequestAnimationFrame ||\n    window.oRequestAnimationFrame ||\n    window.msRequestAnimationFrame ||\n    ((callback, element) => setTimeout(callback, 1000 / 60))\n).bind(window);\n","/**\n * Apply a map of styles to an element\n *\n * @param {HTMLElement} el The element that the styles will be applied to\n * @param {Object} styles The map of propName: attribute, both are used as-is\n *\n * @return {HTMLElement} el\n */\nexport default function style(el, styles) {\n    Object.keys(styles).forEach(prop => {\n        if (el.style[prop] !== styles[prop]) {\n            el.style[prop] = styles[prop];\n        }\n    });\n    return el;\n}\n","import * as util from './util';\nimport MultiCanvas from './drawer.multicanvas';\nimport WebAudio from './webaudio';\nimport MediaElement from './mediaelement';\nimport PeakCache from './peakcache';\n\n/*\n * This work is licensed under a BSD-3-Clause License.\n */\n\n/** @external {HTMLElement} https://developer.mozilla.org/en/docs/Web/API/HTMLElement */\n/** @external {OfflineAudioContext} https://developer.mozilla.org/en-US/docs/Web/API/OfflineAudioContext */\n/** @external {File} https://developer.mozilla.org/en-US/docs/Web/API/File */\n/** @external {Blob} https://developer.mozilla.org/en-US/docs/Web/API/Blob */\n/** @external {CanvasRenderingContext2D} https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D */\n/** @external {MediaStreamConstraints} https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamConstraints */\n/** @external {AudioNode} https://developer.mozilla.org/de/docs/Web/API/AudioNode */\n\n/**\n * @typedef {Object} WavesurferParams\n * @property {AudioContext} audioContext=null Use your own previously\n * initialized AudioContext or leave blank.\n * @property {number} audioRate=1 Speed at which to play audio. Lower number is\n * slower.\n * @property {ScriptProcessorNode} audioScriptProcessor=null Use your own previously\n * initialized ScriptProcessorNode or leave blank.\n * @property {boolean} autoCenter=true If a scrollbar is present, center the\n * waveform around the progress\n * @property {string} backend='WebAudio' `'WebAudio'|'MediaElement'` In most cases\n * you don't have to set this manually. MediaElement is a fallback for\n * unsupported browsers.\n * @property {string} backgroundColor=null Change background color of the\n * waveform container.\n * @property {number} barHeight=1 The height of the wave\n * @property {number} barGap=null The optional spacing between bars of the wave,\n * if not provided will be calculated in legacy format.\n * @property {boolean} closeAudioContext=false Close and nullify all audio\n * contexts when the destroy method is called.\n * @property {!string|HTMLElement} container CSS selector or HTML element where\n * the waveform should be drawn. This is the only required parameter.\n * @property {string} cursorColor='#333' The fill color of the cursor indicating\n * the playhead position.\n * @property {number} cursorWidth=1 Measured in pixels.\n * @property {number} duration=null Optional audio length so pre-rendered peaks\n * can be display immediately for example.\n * @property {boolean} fillParent=true Whether to fill the entire container or\n * draw only according to `minPxPerSec`.\n * @property {boolean} forceDecode=false Force decoding of audio using web audio\n * when zooming to get a more detailed waveform.\n * @property {number} height=128 The height of the waveform. Measured in\n * pixels.\n * @property {boolean} hideScrollbar=false Whether to hide the horizontal\n * scrollbar when one would normally be shown.\n * @property {boolean} interact=true Whether the mouse interaction will be\n * enabled at initialization. You can switch this parameter at any time later\n * on.\n * @property {boolean} loopSelection=true (Use with regions plugin) Enable\n * looping of selected regions\n * @property {number} maxCanvasWidth=4000 Maximum width of a single canvas in\n * pixels, excluding a small overlap (2 * `pixelRatio`, rounded up to the next\n * even integer). If the waveform is longer than this value, additional canvases\n * will be used to render the waveform, which is useful for very large waveforms\n * that may be too wide for browsers to draw on a single canvas.\n * @property {boolean} mediaControls=false (Use with backend `MediaElement`)\n * this enables the native controls for the media element\n * @property {string} mediaType='audio' (Use with backend `MediaElement`)\n * `'audio'|'video'`\n * @property {number} minPxPerSec=20 Minimum number of pixels per second of\n * audio.\n * @property {boolean} normalize=false If true, normalize by the maximum peak\n * instead of 1.0.\n * @property {boolean} partialRender=false Use the PeakCache to improve\n * rendering speed of large waveforms\n * @property {number} pixelRatio=window.devicePixelRatio The pixel ratio used to\n * calculate display\n * @property {PluginDefinition[]} plugins=[] An array of plugin definitions to\n * register during instantiation, they will be directly initialised unless they\n * are added with the `deferInit` property set to true.\n * @property {string} progressColor='#555' The fill color of the part of the\n * waveform behind the cursor.\n * @property {boolean} removeMediaElementOnDestroy=true Set to false to keep the\n * media element in the DOM when the player is destroyed. This is useful when\n * reusing an existing media element via the `loadMediaElement` method.\n * @property {Object} renderer=MultiCanvas Can be used to inject a custom\n * renderer.\n * @property {boolean|number} responsive=false If set to `true` resize the\n * waveform, when the window is resized. This is debounced with a `100ms`\n * timeout by default. If this parameter is a number it represents that timeout.\n * @property {boolean} rtl=false If set to `true`, renders waveform from\n * right-to-left.\n * @property {boolean} scrollParent=false Whether to scroll the container with a\n * lengthy waveform. Otherwise the waveform is shrunk to the container width\n * (see fillParent).\n * @property {number} skipLength=2 Number of seconds to skip with the\n * skipForward() and skipBackward() methods.\n * @property {boolean} splitChannels=false Render with separate waveforms for\n * the channels of the audio\n * @property {string} waveColor='#999' The fill color of the waveform after the\n * cursor.\n * @property {object} xhr={} XHR options.\n */\n\n/**\n * @typedef {Object} PluginDefinition\n * @desc The Object used to describe a plugin\n * @example wavesurfer.addPlugin(pluginDefinition);\n * @property {string} name The name of the plugin, the plugin instance will be\n * added as a property to the wavesurfer instance under this name\n * @property {?Object} staticProps The properties that should be added to the\n * wavesurfer instance as static properties\n * @property {?boolean} deferInit Don't initialise plugin\n * automatically\n * @property {Object} params={} The plugin parameters, they are the first parameter\n * passed to the plugin class constructor function\n * @property {PluginClass} instance The plugin instance factory, is called with\n * the dependency specified in extends. Returns the plugin class.\n */\n\n/**\n * @interface PluginClass\n *\n * @desc This is the interface which is implemented by all plugin classes. Note\n * that this only turns into an observer after being passed through\n * `wavesurfer.addPlugin`.\n *\n * @extends {Observer}\n */\nclass PluginClass {\n    /**\n     * Plugin definition factory\n     *\n     * This function must be used to create a plugin definition which can be\n     * used by wavesurfer to correctly instantiate the plugin.\n     *\n     * @param  {Object} params={} The plugin params (specific to the plugin)\n     * @return {PluginDefinition} an object representing the plugin\n     */\n    create(params) {}\n    /**\n     * Construct the plugin\n     *\n     * @param {Object} params={} The plugin params (specific to the plugin)\n     * @param {Object} ws The wavesurfer instance\n     */\n    constructor(params, ws) {}\n    /**\n     * Initialise the plugin\n     *\n     * Start doing something. This is called by\n     * `wavesurfer.initPlugin(pluginName)`\n     */\n    init() {}\n    /**\n     * Destroy the plugin instance\n     *\n     * Stop doing something. This is called by\n     * `wavesurfer.destroyPlugin(pluginName)`\n     */\n    destroy() {}\n}\n\n/**\n * WaveSurfer core library class\n *\n * @extends {Observer}\n * @example\n * const params = {\n *   container: '#waveform',\n *   waveColor: 'violet',\n *   progressColor: 'purple'\n * };\n *\n * // initialise like this\n * const wavesurfer = WaveSurfer.create(params);\n *\n * // or like this ...\n * const wavesurfer = new WaveSurfer(params);\n * wavesurfer.init();\n *\n * // load audio file\n * wavesurfer.load('example/media/demo.wav');\n */\nexport default class WaveSurfer extends util.Observer {\n    /** @private */\n    defaultParams = {\n        audioContext: null,\n        audioScriptProcessor: null,\n        audioRate: 1,\n        autoCenter: true,\n        backend: 'WebAudio',\n        backgroundColor: null,\n        barHeight: 1,\n        barGap: null,\n        container: null,\n        cursorColor: '#333',\n        cursorWidth: 1,\n        dragSelection: true,\n        duration: null,\n        fillParent: true,\n        forceDecode: false,\n        height: 128,\n        hideScrollbar: false,\n        interact: true,\n        loopSelection: true,\n        maxCanvasWidth: 4000,\n        mediaContainer: null,\n        mediaControls: false,\n        mediaType: 'audio',\n        minPxPerSec: 20,\n        normalize: false,\n        partialRender: false,\n        pixelRatio:\n            window.devicePixelRatio || screen.deviceXDPI / screen.logicalXDPI,\n        plugins: [],\n        progressColor: '#555',\n        removeMediaElementOnDestroy: true,\n        renderer: MultiCanvas,\n        responsive: false,\n        rtl: false,\n        scrollParent: false,\n        skipLength: 2,\n        splitChannels: false,\n        waveColor: '#999',\n        xhr: {}\n    };\n\n    /** @private */\n    backends = {\n        MediaElement,\n        WebAudio\n    };\n\n    /**\n     * Instantiate this class, call its `init` function and returns it\n     *\n     * @param {WavesurferParams} params\n     * @return {Object} WaveSurfer instance\n     * @example const wavesurfer = WaveSurfer.create(params);\n     */\n    static create(params) {\n        const wavesurfer = new WaveSurfer(params);\n        return wavesurfer.init();\n    }\n\n    /**\n     * The library version number is available as a static property of the\n     * WaveSurfer class\n     *\n     * @type {String}\n     * @example\n     * console.log('Using wavesurfer.js ' + WaveSurfer.VERSION);\n     */\n    static VERSION = __VERSION__;\n\n    /**\n     * Functions in the `util` property are available as a prototype property to\n     * all instances\n     *\n     * @type {Object}\n     * @example\n     * const wavesurfer = WaveSurfer.create(params);\n     * wavesurfer.util.style(myElement, { background: 'blue' });\n     */\n    util = util;\n\n    /**\n     * Functions in the `util` property are available as a static property of the\n     * WaveSurfer class\n     *\n     * @type {Object}\n     * @example\n     * WaveSurfer.util.style(myElement, { background: 'blue' });\n     */\n    static util = util;\n\n    /**\n     * Initialise wavesurfer instance\n     *\n     * @param {WavesurferParams} params Instantiation options for wavesurfer\n     * @example\n     * const wavesurfer = new WaveSurfer(params);\n     * @returns {this}\n     */\n    constructor(params) {\n        super();\n        /**\n         * Extract relevant parameters (or defaults)\n         * @private\n         */\n        this.params = util.extend({}, this.defaultParams, params);\n\n        /** @private */\n        this.container =\n            'string' == typeof params.container\n                ? document.querySelector(this.params.container)\n                : this.params.container;\n\n        if (!this.container) {\n            throw new Error('Container element not found');\n        }\n\n        if (this.params.mediaContainer == null) {\n            /** @private */\n            this.mediaContainer = this.container;\n        } else if (typeof this.params.mediaContainer == 'string') {\n            /** @private */\n            this.mediaContainer = document.querySelector(\n                this.params.mediaContainer\n            );\n        } else {\n            /** @private */\n            this.mediaContainer = this.params.mediaContainer;\n        }\n\n        if (!this.mediaContainer) {\n            throw new Error('Media Container element not found');\n        }\n\n        if (this.params.maxCanvasWidth <= 1) {\n            throw new Error('maxCanvasWidth must be greater than 1');\n        } else if (this.params.maxCanvasWidth % 2 == 1) {\n            throw new Error('maxCanvasWidth must be an even number');\n        }\n\n        if (this.params.rtl === true) {\n            util.style(this.container, { transform: 'rotateY(180deg)' });\n        }\n\n        if (this.params.backgroundColor) {\n            this.setBackgroundColor(this.params.backgroundColor);\n        }\n\n        /**\n         * @private Used to save the current volume when muting so we can\n         * restore once unmuted\n         * @type {number}\n         */\n        this.savedVolume = 0;\n\n        /**\n         * @private The current muted state\n         * @type {boolean}\n         */\n        this.isMuted = false;\n\n        /**\n         * @private Will hold a list of event descriptors that need to be\n         * canceled on subsequent loads of audio\n         * @type {Object[]}\n         */\n        this.tmpEvents = [];\n\n        /**\n         * @private Holds any running audio downloads\n         * @type {Observer}\n         */\n        this.currentAjax = null;\n        /** @private */\n        this.arraybuffer = null;\n        /** @private */\n        this.drawer = null;\n        /** @private */\n        this.backend = null;\n        /** @private */\n        this.peakCache = null;\n\n        // cache constructor objects\n        if (typeof this.params.renderer !== 'function') {\n            throw new Error('Renderer parameter is invalid');\n        }\n        /**\n         * @private The uninitialised Drawer class\n         */\n        this.Drawer = this.params.renderer;\n        /**\n         * @private The uninitialised Backend class\n         */\n        this.Backend = this.backends[this.params.backend];\n\n        /**\n         * @private map of plugin names that are currently initialised\n         */\n        this.initialisedPluginList = {};\n        /** @private */\n        this.isDestroyed = false;\n        /** @private */\n        this.isReady = false;\n\n        // responsive debounced event listener. If this.params.responsive is not\n        // set, this is never called. Use 100ms or this.params.responsive as\n        // timeout for the debounce function.\n        let prevWidth = 0;\n        this._onResize = util.debounce(\n            () => {\n                if (\n                    prevWidth != this.drawer.wrapper.clientWidth &&\n                    !this.params.scrollParent\n                ) {\n                    prevWidth = this.drawer.wrapper.clientWidth;\n                    this.drawer.fireEvent('redraw');\n                }\n            },\n            typeof this.params.responsive === 'number'\n                ? this.params.responsive\n                : 100\n        );\n\n        return this;\n    }\n\n    /**\n     * Initialise the wave\n     *\n     * @example\n     * var wavesurfer = new WaveSurfer(params);\n     * wavesurfer.init();\n     * @return {this}\n     */\n    init() {\n        this.registerPlugins(this.params.plugins);\n        this.createDrawer();\n        this.createBackend();\n        this.createPeakCache();\n        return this;\n    }\n\n    /**\n     * Add and initialise array of plugins (if `plugin.deferInit` is falsey),\n     * this function is called in the init function of wavesurfer\n     *\n     * @param {PluginDefinition[]} plugins An array of plugin definitions\n     * @emits {WaveSurfer#plugins-registered} Called with the array of plugin definitions\n     * @return {this}\n     */\n    registerPlugins(plugins) {\n        // first instantiate all the plugins\n        plugins.forEach(plugin => this.addPlugin(plugin));\n\n        // now run the init functions\n        plugins.forEach(plugin => {\n            // call init function of the plugin if deferInit is falsey\n            // in that case you would manually use initPlugins()\n            if (!plugin.deferInit) {\n                this.initPlugin(plugin.name);\n            }\n        });\n        this.fireEvent('plugins-registered', plugins);\n        return this;\n    }\n\n    /**\n     * Add a plugin object to wavesurfer\n     *\n     * @param {PluginDefinition} plugin A plugin definition\n     * @emits {WaveSurfer#plugin-added} Called with the name of the plugin that was added\n     * @example wavesurfer.addPlugin(WaveSurfer.minimap());\n     * @return {this}\n     */\n    addPlugin(plugin) {\n        if (!plugin.name) {\n            throw new Error('Plugin does not have a name!');\n        }\n        if (!plugin.instance) {\n            throw new Error(\n                `Plugin ${plugin.name} does not have an instance property!`\n            );\n        }\n\n        // staticProps properties are applied to wavesurfer instance\n        if (plugin.staticProps) {\n            Object.keys(plugin.staticProps).forEach(pluginStaticProp => {\n                /**\n                 * Properties defined in a plugin definition's `staticProps` property are added as\n                 * staticProps properties of the WaveSurfer instance\n                 */\n                this[pluginStaticProp] = plugin.staticProps[pluginStaticProp];\n            });\n        }\n\n        const Instance = plugin.instance;\n\n        // turn the plugin instance into an observer\n        const observerPrototypeKeys = Object.getOwnPropertyNames(\n            util.Observer.prototype\n        );\n        observerPrototypeKeys.forEach(key => {\n            Instance.prototype[key] = util.Observer.prototype[key];\n        });\n\n        /**\n         * Instantiated plugin classes are added as a property of the wavesurfer\n         * instance\n         * @type {Object}\n         */\n        this[plugin.name] = new Instance(plugin.params || {}, this);\n        this.fireEvent('plugin-added', plugin.name);\n        return this;\n    }\n\n    /**\n     * Initialise a plugin\n     *\n     * @param {string} name A plugin name\n     * @emits WaveSurfer#plugin-initialised\n     * @example wavesurfer.initPlugin('minimap');\n     * @return {this}\n     */\n    initPlugin(name) {\n        if (!this[name]) {\n            throw new Error(`Plugin ${name} has not been added yet!`);\n        }\n        if (this.initialisedPluginList[name]) {\n            // destroy any already initialised plugins\n            this.destroyPlugin(name);\n        }\n        this[name].init();\n        this.initialisedPluginList[name] = true;\n        this.fireEvent('plugin-initialised', name);\n        return this;\n    }\n\n    /**\n     * Destroy a plugin\n     *\n     * @param {string} name A plugin name\n     * @emits WaveSurfer#plugin-destroyed\n     * @example wavesurfer.destroyPlugin('minimap');\n     * @returns {this}\n     */\n    destroyPlugin(name) {\n        if (!this[name]) {\n            throw new Error(\n                `Plugin ${name} has not been added yet and cannot be destroyed!`\n            );\n        }\n        if (!this.initialisedPluginList[name]) {\n            throw new Error(\n                `Plugin ${name} is not active and cannot be destroyed!`\n            );\n        }\n        if (typeof this[name].destroy !== 'function') {\n            throw new Error(`Plugin ${name} does not have a destroy function!`);\n        }\n\n        this[name].destroy();\n        delete this.initialisedPluginList[name];\n        this.fireEvent('plugin-destroyed', name);\n        return this;\n    }\n\n    /**\n     * Destroy all initialised plugins. Convenience function to use when\n     * wavesurfer is removed\n     *\n     * @private\n     */\n    destroyAllPlugins() {\n        Object.keys(this.initialisedPluginList).forEach(name =>\n            this.destroyPlugin(name)\n        );\n    }\n\n    /**\n     * Create the drawer and draw the waveform\n     *\n     * @private\n     * @emits WaveSurfer#drawer-created\n     */\n    createDrawer() {\n        this.drawer = new this.Drawer(this.container, this.params);\n        this.drawer.init();\n        this.fireEvent('drawer-created', this.drawer);\n\n        if (this.params.responsive !== false) {\n            window.addEventListener('resize', this._onResize, true);\n            window.addEventListener('orientationchange', this._onResize, true);\n        }\n\n        this.drawer.on('redraw', () => {\n            this.drawBuffer();\n            this.drawer.progress(this.backend.getPlayedPercents());\n        });\n\n        // Click-to-seek\n        this.drawer.on('click', (e, progress) => {\n            setTimeout(() => this.seekTo(progress), 0);\n        });\n\n        // Relay the scroll event from the drawer\n        this.drawer.on('scroll', e => {\n            if (this.params.partialRender) {\n                this.drawBuffer();\n            }\n            this.fireEvent('scroll', e);\n        });\n    }\n\n    /**\n     * Create the backend\n     *\n     * @private\n     * @emits WaveSurfer#backend-created\n     */\n    createBackend() {\n        if (this.backend) {\n            this.backend.destroy();\n        }\n\n        // Back compat\n        if (this.params.backend == 'AudioElement') {\n            this.params.backend = 'MediaElement';\n        }\n\n        if (\n            this.params.backend == 'WebAudio' &&\n            !this.Backend.prototype.supportsWebAudio.call(null)\n        ) {\n            this.params.backend = 'MediaElement';\n        }\n\n        this.backend = new this.Backend(this.params);\n        this.backend.init();\n        this.fireEvent('backend-created', this.backend);\n\n        this.backend.on('finish', () => {\n            this.drawer.progress(this.backend.getPlayedPercents());\n            this.fireEvent('finish');\n        });\n        this.backend.on('play', () => this.fireEvent('play'));\n        this.backend.on('pause', () => this.fireEvent('pause'));\n\n        this.backend.on('audioprocess', time => {\n            this.drawer.progress(this.backend.getPlayedPercents());\n            this.fireEvent('audioprocess', time);\n        });\n    }\n\n    /**\n     * Create the peak cache\n     *\n     * @private\n     */\n    createPeakCache() {\n        if (this.params.partialRender) {\n            this.peakCache = new PeakCache();\n        }\n    }\n\n    /**\n     * Get the duration of the audio clip\n     *\n     * @example const duration = wavesurfer.getDuration();\n     * @return {number} Duration in seconds\n     */\n    getDuration() {\n        return this.backend.getDuration();\n    }\n\n    /**\n     * Get the current playback position\n     *\n     * @example const currentTime = wavesurfer.getCurrentTime();\n     * @return {number} Playback position in seconds\n     */\n    getCurrentTime() {\n        return this.backend.getCurrentTime();\n    }\n\n    /**\n     * Set the current play time in seconds.\n     *\n     * @param {number} seconds A positive number in seconds. E.g. 10 means 10\n     * seconds, 60 means 1 minute\n     */\n    setCurrentTime(seconds) {\n        if (seconds >= this.getDuration()) {\n            this.seekTo(1);\n        } else {\n            this.seekTo(seconds / this.getDuration());\n        }\n    }\n\n    /**\n     * Starts playback from the current position. Optional start and end\n     * measured in seconds can be used to set the range of audio to play.\n     *\n     * @param {?number} start Position to start at\n     * @param {?number} end Position to end at\n     * @emits WaveSurfer#interaction\n     * @return {Promise}\n     * @example\n     * // play from second 1 to 5\n     * wavesurfer.play(1, 5);\n     */\n    play(start, end) {\n        this.fireEvent('interaction', () => this.play(start, end));\n        return this.backend.play(start, end);\n    }\n\n    /**\n     * Stops playback\n     *\n     * @example wavesurfer.pause();\n     * @return {Promise}\n     */\n    pause() {\n        if (!this.backend.isPaused()) {\n            return this.backend.pause();\n        }\n    }\n\n    /**\n     * Toggle playback\n     *\n     * @example wavesurfer.playPause();\n     * @return {Promise}\n     */\n    playPause() {\n        return this.backend.isPaused() ? this.play() : this.pause();\n    }\n\n    /**\n     * Get the current playback state\n     *\n     * @example const isPlaying = wavesurfer.isPlaying();\n     * @return {boolean} False if paused, true if playing\n     */\n    isPlaying() {\n        return !this.backend.isPaused();\n    }\n\n    /**\n     * Skip backward\n     *\n     * @param {?number} seconds Amount to skip back, if not specified `skipLength`\n     * is used\n     * @example wavesurfer.skipBackward();\n     */\n    skipBackward(seconds) {\n        this.skip(-seconds || -this.params.skipLength);\n    }\n\n    /**\n     * Skip forward\n     *\n     * @param {?number} seconds Amount to skip back, if not specified `skipLength`\n     * is used\n     * @example wavesurfer.skipForward();\n     */\n    skipForward(seconds) {\n        this.skip(seconds || this.params.skipLength);\n    }\n\n    /**\n     * Skip a number of seconds from the current position (use a negative value\n     * to go backwards).\n     *\n     * @param {number} offset Amount to skip back or forwards\n     * @example\n     * // go back 2 seconds\n     * wavesurfer.skip(-2);\n     */\n    skip(offset) {\n        const duration = this.getDuration() || 1;\n        let position = this.getCurrentTime() || 0;\n        position = Math.max(0, Math.min(duration, position + (offset || 0)));\n        this.seekAndCenter(position / duration);\n    }\n\n    /**\n     * Seeks to a position and centers the view\n     *\n     * @param {number} progress Between 0 (=beginning) and 1 (=end)\n     * @example\n     * // seek and go to the middle of the audio\n     * wavesurfer.seekTo(0.5);\n     */\n    seekAndCenter(progress) {\n        this.seekTo(progress);\n        this.drawer.recenter(progress);\n    }\n\n    /**\n     * Seeks to a position\n     *\n     * @param {number} progress Between 0 (=beginning) and 1 (=end)\n     * @emits WaveSurfer#interaction\n     * @emits WaveSurfer#seek\n     * @example\n     * // seek to the middle of the audio\n     * wavesurfer.seekTo(0.5);\n     */\n    seekTo(progress) {\n        // return an error if progress is not a number between 0 and 1\n        if (\n            typeof progress !== 'number' ||\n            !isFinite(progress) ||\n            progress < 0 ||\n            progress > 1\n        ) {\n            return console.error(\n                'Error calling wavesurfer.seekTo, parameter must be a number between 0 and 1!'\n            );\n        }\n        this.fireEvent('interaction', () => this.seekTo(progress));\n\n        const paused = this.backend.isPaused();\n        // avoid draw wrong position while playing backward seeking\n        if (!paused) {\n            this.backend.pause();\n        }\n        // avoid small scrolls while paused seeking\n        const oldScrollParent = this.params.scrollParent;\n        this.params.scrollParent = false;\n        this.backend.seekTo(progress * this.getDuration());\n        this.drawer.progress(progress);\n\n        if (!paused) {\n            this.backend.play();\n        }\n        this.params.scrollParent = oldScrollParent;\n        this.fireEvent('seek', progress);\n    }\n\n    /**\n     * Stops and goes to the beginning.\n     *\n     * @example wavesurfer.stop();\n     */\n    stop() {\n        this.pause();\n        this.seekTo(0);\n        this.drawer.progress(0);\n    }\n\n    /**\n     * Set the playback volume.\n     *\n     * @param {string} deviceId String value representing underlying output device\n     */\n    setSinkId(deviceId) {\n        return this.backend.setSinkId(deviceId);\n    }\n\n    /**\n     * Set the playback volume.\n     *\n     * @param {number} newVolume A value between 0 and 1, 0 being no\n     * volume and 1 being full volume.\n     * @emits WaveSurfer#volume\n     */\n    setVolume(newVolume) {\n        this.backend.setVolume(newVolume);\n        this.fireEvent('volume', newVolume);\n    }\n\n    /**\n     * Get the playback volume.\n     *\n     * @return {number} A value between 0 and 1, 0 being no\n     * volume and 1 being full volume.\n     */\n    getVolume() {\n        return this.backend.getVolume();\n    }\n\n    /**\n     * Set the playback rate.\n     *\n     * @param {number} rate A positive number. E.g. 0.5 means half the normal\n     * speed, 2 means double speed and so on.\n     * @example wavesurfer.setPlaybackRate(2);\n     */\n    setPlaybackRate(rate) {\n        this.backend.setPlaybackRate(rate);\n    }\n\n    /**\n     * Get the playback rate.\n     *\n     * @return {number}\n     */\n    getPlaybackRate() {\n        return this.backend.getPlaybackRate();\n    }\n\n    /**\n     * Toggle the volume on and off. If not currently muted it will save the\n     * current volume value and turn the volume off. If currently muted then it\n     * will restore the volume to the saved value, and then rest the saved\n     * value.\n     *\n     * @example wavesurfer.toggleMute();\n     */\n    toggleMute() {\n        this.setMute(!this.isMuted);\n    }\n\n    /**\n     * Enable or disable muted audio\n     *\n     * @param {boolean} mute\n     * @emits WaveSurfer#volume\n     * @emits WaveSurfer#mute\n     * @example\n     * // unmute\n     * wavesurfer.setMute(false);\n     */\n    setMute(mute) {\n        // ignore all muting requests if the audio is already in that state\n        if (mute === this.isMuted) {\n            this.fireEvent('mute', this.isMuted);\n            return;\n        }\n\n        if (mute) {\n            // If currently not muted then save current volume,\n            // turn off the volume and update the mute properties\n            this.savedVolume = this.backend.getVolume();\n            this.backend.setVolume(0);\n            this.isMuted = true;\n            this.fireEvent('volume', 0);\n        } else {\n            // If currently muted then restore to the saved volume\n            // and update the mute properties\n            this.backend.setVolume(this.savedVolume);\n            this.isMuted = false;\n            this.fireEvent('volume', this.savedVolume);\n        }\n        this.fireEvent('mute', this.isMuted);\n    }\n\n    /**\n     * Get the current mute status.\n     *\n     * @example const isMuted = wavesurfer.getMute();\n     * @return {boolean}\n     */\n    getMute() {\n        return this.isMuted;\n    }\n\n    /**\n     * Get the current ready status.\n     *\n     * @example const isReady = wavesurfer.isReady();\n     * @return {boolean}\n     */\n    isReady() {\n        return this.isReady;\n    }\n\n    /**\n     * Get the list of current set filters as an array.\n     *\n     * Filters must be set with setFilters method first\n     *\n     * @return {array}\n     */\n    getFilters() {\n        return this.backend.filters || [];\n    }\n\n    /**\n     * Toggles `scrollParent` and redraws\n     *\n     * @example wavesurfer.toggleScroll();\n     */\n    toggleScroll() {\n        this.params.scrollParent = !this.params.scrollParent;\n        this.drawBuffer();\n    }\n\n    /**\n     * Toggle mouse interaction\n     *\n     * @example wavesurfer.toggleInteraction();\n     */\n    toggleInteraction() {\n        this.params.interact = !this.params.interact;\n    }\n\n    /**\n     * Get the fill color of the waveform after the cursor.\n     *\n     * @return {string} A CSS color string.\n     */\n    getWaveColor() {\n        return this.params.waveColor;\n    }\n\n    /**\n     * Set the fill color of the waveform after the cursor.\n     *\n     * @param {string} color A CSS color string.\n     * @example wavesurfer.setWaveColor('#ddd');\n     */\n    setWaveColor(color) {\n        this.params.waveColor = color;\n        this.drawBuffer();\n    }\n\n    /**\n     * Get the fill color of the waveform behind the cursor.\n     *\n     * @return {string} A CSS color string.\n     */\n    getProgressColor() {\n        return this.params.progressColor;\n    }\n\n    /**\n     * Set the fill color of the waveform behind the cursor.\n     *\n     * @param {string} color A CSS color string.\n     * @example wavesurfer.setProgressColor('#400');\n     */\n    setProgressColor(color) {\n        this.params.progressColor = color;\n        this.drawBuffer();\n    }\n\n    /**\n     * Get the background color of the waveform container.\n     *\n     * @return {string} A CSS color string.\n     */\n    getBackgroundColor() {\n        return this.params.backgroundColor;\n    }\n\n    /**\n     * Set the background color of the waveform container.\n     *\n     * @param {string} color A CSS color string.\n     * @example wavesurfer.setBackgroundColor('#FF00FF');\n     */\n    setBackgroundColor(color) {\n        this.params.backgroundColor = color;\n        util.style(this.container, { background: this.params.backgroundColor });\n    }\n\n    /**\n     * Get the fill color of the cursor indicating the playhead\n     * position.\n     *\n     * @return {string} A CSS color string.\n     */\n    getCursorColor() {\n        return this.params.cursorColor;\n    }\n\n    /**\n     * Set the fill color of the cursor indicating the playhead\n     * position.\n     *\n     * @param {string} color A CSS color string.\n     * @example wavesurfer.setCursorColor('#222');\n     */\n    setCursorColor(color) {\n        this.params.cursorColor = color;\n        this.drawer.updateCursor();\n    }\n\n    /**\n     * Get the height of the waveform.\n     *\n     * @return {number} Height measured in pixels.\n     */\n    getHeight() {\n        return this.params.height;\n    }\n\n    /**\n     * Set the height of the waveform.\n     *\n     * @param {number} height Height measured in pixels.\n     * @example wavesurfer.setHeight(200);\n     */\n    setHeight(height) {\n        this.params.height = height;\n        this.drawer.setHeight(height * this.params.pixelRatio);\n        this.drawBuffer();\n    }\n\n    /**\n     * Get the correct peaks for current wave view-port and render wave\n     *\n     * @private\n     * @emits WaveSurfer#redraw\n     */\n    drawBuffer() {\n        const nominalWidth = Math.round(\n            this.getDuration() *\n                this.params.minPxPerSec *\n                this.params.pixelRatio\n        );\n        const parentWidth = this.drawer.getWidth();\n        let width = nominalWidth;\n        // always start at 0 after zooming for scrolling : issue redraw left part\n        let start = 0;\n        let end = Math.max(start + parentWidth, width);\n        // Fill container\n        if (\n            this.params.fillParent &&\n            (!this.params.scrollParent || nominalWidth < parentWidth)\n        ) {\n            width = parentWidth;\n            start = 0;\n            end = width;\n        }\n\n        let peaks;\n        if (this.params.partialRender) {\n            const newRanges = this.peakCache.addRangeToPeakCache(\n                width,\n                start,\n                end\n            );\n            let i;\n            for (i = 0; i < newRanges.length; i++) {\n                peaks = this.backend.getPeaks(\n                    width,\n                    newRanges[i][0],\n                    newRanges[i][1]\n                );\n                this.drawer.drawPeaks(\n                    peaks,\n                    width,\n                    newRanges[i][0],\n                    newRanges[i][1]\n                );\n            }\n        } else {\n            peaks = this.backend.getPeaks(width, start, end);\n            this.drawer.drawPeaks(peaks, width, start, end);\n        }\n        this.fireEvent('redraw', peaks, width);\n    }\n\n    /**\n     * Horizontally zooms the waveform in and out. It also changes the parameter\n     * `minPxPerSec` and enables the `scrollParent` option. Calling the function\n     * with a falsey parameter will reset the zoom state.\n     *\n     * @param {?number} pxPerSec Number of horizontal pixels per second of\n     * audio, if none is set the waveform returns to unzoomed state\n     * @emits WaveSurfer#zoom\n     * @example wavesurfer.zoom(20);\n     */\n    zoom(pxPerSec) {\n        if (!pxPerSec) {\n            this.params.minPxPerSec = this.defaultParams.minPxPerSec;\n            this.params.scrollParent = false;\n        } else {\n            this.params.minPxPerSec = pxPerSec;\n            this.params.scrollParent = true;\n        }\n\n        this.drawBuffer();\n        this.drawer.progress(this.backend.getPlayedPercents());\n\n        this.drawer.recenter(this.getCurrentTime() / this.getDuration());\n        this.fireEvent('zoom', pxPerSec);\n    }\n\n    /**\n     * Decode buffer and load\n     *\n     * @private\n     * @param {ArrayBuffer} arraybuffer\n     */\n    loadArrayBuffer(arraybuffer) {\n        this.decodeArrayBuffer(arraybuffer, data => {\n            if (!this.isDestroyed) {\n                this.loadDecodedBuffer(data);\n            }\n        });\n    }\n\n    /**\n     * Directly load an externally decoded AudioBuffer\n     *\n     * @private\n     * @param {AudioBuffer} buffer\n     * @emits WaveSurfer#ready\n     */\n    loadDecodedBuffer(buffer) {\n        this.backend.load(buffer);\n        this.drawBuffer();\n        this.fireEvent('ready');\n        this.isReady = true;\n    }\n\n    /**\n     * Loads audio data from a Blob or File object\n     *\n     * @param {Blob|File} blob Audio data\n     * @example\n     */\n    loadBlob(blob) {\n        // Create file reader\n        const reader = new FileReader();\n        reader.addEventListener('progress', e => this.onProgress(e));\n        reader.addEventListener('load', e =>\n            this.loadArrayBuffer(e.target.result)\n        );\n        reader.addEventListener('error', () =>\n            this.fireEvent('error', 'Error reading file')\n        );\n        reader.readAsArrayBuffer(blob);\n        this.empty();\n    }\n\n    /**\n     * Loads audio and re-renders the waveform.\n     *\n     * @param {string|HTMLMediaElement} url The url of the audio file or the\n     * audio element with the audio\n     * @param {?number[]|number[][]} peaks Wavesurfer does not have to decode\n     * the audio to render the waveform if this is specified\n     * @param {?string} preload (Use with backend `MediaElement`)\n     * `'none'|'metadata'|'auto'` Preload attribute for the media element\n     * @param {?number} duration The duration of the audio. This is used to\n     * render the peaks data in the correct size for the audio duration (as\n     * befits the current minPxPerSec and zoom value) without having to decode\n     * the audio.\n     * @example\n     * // using ajax or media element to load (depending on backend)\n     * wavesurfer.load('http://example.com/demo.wav');\n     *\n     * // setting preload attribute with media element backend and supplying\n     * peaks wavesurfer.load(\n     *   'http://example.com/demo.wav',\n     *   [0.0218, 0.0183, 0.0165, 0.0198, 0.2137, 0.2888],\n     *   true,\n     * );\n     */\n    load(url, peaks, preload, duration) {\n        this.empty();\n\n        if (preload) {\n            // check whether the preload attribute will be usable and if not log\n            // a warning listing the reasons why not and nullify the variable\n            const preloadIgnoreReasons = {\n                \"Preload is not 'auto', 'none' or 'metadata'\":\n                    ['auto', 'metadata', 'none'].indexOf(preload) === -1,\n                'Peaks are not provided': !peaks,\n                'Backend is not of type MediaElement':\n                    this.params.backend !== 'MediaElement',\n                'Url is not of type string': typeof url !== 'string'\n            };\n            const activeReasons = Object.keys(preloadIgnoreReasons).filter(\n                reason => preloadIgnoreReasons[reason]\n            );\n            if (activeReasons.length) {\n                console.warn(\n                    'Preload parameter of wavesurfer.load will be ignored because:\\n\\t- ' +\n                        activeReasons.join('\\n\\t- ')\n                );\n                // stop invalid values from being used\n                preload = null;\n            }\n        }\n\n        switch (this.params.backend) {\n            case 'WebAudio':\n                return this.loadBuffer(url, peaks, duration);\n            case 'MediaElement':\n                return this.loadMediaElement(url, peaks, preload, duration);\n        }\n    }\n\n    /**\n     * Loads audio using Web Audio buffer backend.\n     *\n     * @private\n     * @param {string} url\n     * @param {?number[]|number[][]} peaks\n     * @param {?number} duration\n     */\n    loadBuffer(url, peaks, duration) {\n        const load = action => {\n            if (action) {\n                this.tmpEvents.push(this.once('ready', action));\n            }\n            return this.getArrayBuffer(url, data => this.loadArrayBuffer(data));\n        };\n\n        if (peaks) {\n            this.backend.setPeaks(peaks, duration);\n            this.drawBuffer();\n            this.tmpEvents.push(this.once('interaction', load));\n        } else {\n            return load();\n        }\n    }\n\n    /**\n     * Either create a media element, or load an existing media element.\n     *\n     * @private\n     * @param {string|HTMLMediaElement} urlOrElt Either a path to a media file, or an\n     * existing HTML5 Audio/Video Element\n     * @param {number[]|number[][]} peaks Array of peaks. Required to bypass web audio\n     * dependency\n     * @param {?boolean} preload Set to true if the preload attribute of the\n     * audio element should be enabled\n     * @param {?number} duration\n     */\n    loadMediaElement(urlOrElt, peaks, preload, duration) {\n        let url = urlOrElt;\n\n        if (typeof urlOrElt === 'string') {\n            this.backend.load(url, this.mediaContainer, peaks, preload);\n        } else {\n            const elt = urlOrElt;\n            this.backend.loadElt(elt, peaks);\n\n            // If peaks are not provided,\n            // url = element.src so we can get peaks with web audio\n            url = elt.src;\n        }\n\n        this.tmpEvents.push(\n            this.backend.once('canplay', () => {\n                this.drawBuffer();\n                this.fireEvent('ready');\n                this.isReady = true;\n            }),\n            this.backend.once('error', err => this.fireEvent('error', err))\n        );\n\n        // If no pre-decoded peaks provided or pre-decoded peaks are\n        // provided with forceDecode flag, attempt to download the\n        // audio file and decode it with Web Audio.\n        if (peaks) {\n            this.backend.setPeaks(peaks, duration);\n        }\n\n        if (\n            (!peaks || this.params.forceDecode) &&\n            this.backend.supportsWebAudio()\n        ) {\n            this.getArrayBuffer(url, arraybuffer => {\n                this.decodeArrayBuffer(arraybuffer, buffer => {\n                    this.backend.buffer = buffer;\n                    this.backend.setPeaks(null);\n                    this.drawBuffer();\n                    this.fireEvent('waveform-ready');\n                });\n            });\n        }\n    }\n\n    /**\n     * Decode an array buffer and pass data to a callback\n     *\n     * @private\n     * @param {Object} arraybuffer\n     * @param {function} callback\n     */\n    decodeArrayBuffer(arraybuffer, callback) {\n        this.arraybuffer = arraybuffer;\n\n        this.backend.decodeArrayBuffer(\n            arraybuffer,\n            data => {\n                // Only use the decoded data if we haven't been destroyed or\n                // another decode started in the meantime\n                if (!this.isDestroyed && this.arraybuffer == arraybuffer) {\n                    callback(data);\n                    this.arraybuffer = null;\n                }\n            },\n            () => this.fireEvent('error', 'Error decoding audiobuffer')\n        );\n    }\n\n    /**\n     * Load an array buffer by ajax and pass to a callback\n     *\n     * @param {string} url\n     * @param {function} callback\n     * @private\n     */\n    getArrayBuffer(url, callback) {\n        const ajax = util.ajax({\n            url: url,\n            responseType: 'arraybuffer',\n            xhr: this.params.xhr\n        });\n\n        this.currentAjax = ajax;\n\n        this.tmpEvents.push(\n            ajax.on('progress', e => {\n                this.onProgress(e);\n            }),\n            ajax.on('success', (data, e) => {\n                callback(data);\n                this.currentAjax = null;\n            }),\n            ajax.on('error', e => {\n                this.fireEvent('error', 'XHR error: ' + e.target.statusText);\n                this.currentAjax = null;\n            })\n        );\n\n        return ajax;\n    }\n\n    /**\n     * Called while the audio file is loading\n     *\n     * @private\n     * @param {Event} e\n     * @emits WaveSurfer#loading\n     */\n    onProgress(e) {\n        let percentComplete;\n        if (e.lengthComputable) {\n            percentComplete = e.loaded / e.total;\n        } else {\n            // Approximate progress with an asymptotic\n            // function, and assume downloads in the 1-3 MB range.\n            percentComplete = e.loaded / (e.loaded + 1000000);\n        }\n        this.fireEvent('loading', Math.round(percentComplete * 100), e.target);\n    }\n\n    /**\n     * Exports PCM data into a JSON array and opens in a new window.\n     *\n     * @param {number} length=1024 The scale in which to export the peaks. (Integer)\n     * @param {number} accuracy=10000 (Integer)\n     * @param {?boolean} noWindow Set to true to disable opening a new\n     * window with the JSON\n     * @param {number} start\n     * @todo Update exportPCM to work with new getPeaks signature\n     * @return {string} JSON of peaks\n     */\n    exportPCM(length, accuracy, noWindow, start) {\n        length = length || 1024;\n        start = start || 0;\n        accuracy = accuracy || 10000;\n        noWindow = noWindow || false;\n        const peaks = this.backend.getPeaks(length, start);\n        const arr = [].map.call(\n            peaks,\n            val => Math.round(val * accuracy) / accuracy\n        );\n        const json = JSON.stringify(arr);\n        if (!noWindow) {\n            window.open(\n                'data:application/json;charset=utf-8,' +\n                    encodeURIComponent(json)\n            );\n        }\n        return json;\n    }\n\n    /**\n     * Save waveform image as data URI.\n     *\n     * The default format is `image/png`. Other supported types are\n     * `image/jpeg` and `image/webp`.\n     *\n     * @param {string} format='image/png'\n     * @param {number} quality=1\n     * @return {string} data URI of image\n     */\n    exportImage(format, quality) {\n        if (!format) {\n            format = 'image/png';\n        }\n        if (!quality) {\n            quality = 1;\n        }\n\n        return this.drawer.getImage(format, quality);\n    }\n\n    /**\n     * Cancel any ajax request currently in progress\n     */\n    cancelAjax() {\n        if (this.currentAjax) {\n            this.currentAjax.xhr.abort();\n            this.currentAjax = null;\n        }\n    }\n\n    /**\n     * @private\n     */\n    clearTmpEvents() {\n        this.tmpEvents.forEach(e => e.un());\n    }\n\n    /**\n     * Display empty waveform.\n     */\n    empty() {\n        if (!this.backend.isPaused()) {\n            this.stop();\n            this.backend.disconnectSource();\n        }\n        this.isReady = false;\n        this.cancelAjax();\n        this.clearTmpEvents();\n        this.drawer.progress(0);\n        this.drawer.setWidth(0);\n        this.drawer.drawPeaks({ length: this.drawer.getWidth() }, 0);\n    }\n\n    /**\n     * Remove events, elements and disconnect WebAudio nodes.\n     *\n     * @emits WaveSurfer#destroy\n     */\n    destroy() {\n        this.destroyAllPlugins();\n        this.fireEvent('destroy');\n        this.cancelAjax();\n        this.clearTmpEvents();\n        this.unAll();\n        if (this.params.responsive !== false) {\n            window.removeEventListener('resize', this._onResize, true);\n            window.removeEventListener(\n                'orientationchange',\n                this._onResize,\n                true\n            );\n        }\n        this.backend.destroy();\n        this.drawer.destroy();\n        this.isDestroyed = true;\n        this.isReady = false;\n        this.arraybuffer = null;\n    }\n}\n","import * as util from './util';\n\n// using constants to prevent someone writing the string wrong\nconst PLAYING = 'playing';\nconst PAUSED = 'paused';\nconst FINISHED = 'finished';\n\n/**\n * WebAudio backend\n *\n * @extends {Observer}\n */\nexport default class WebAudio extends util.Observer {\n    /** @private */\n    static scriptBufferSize = 256;\n    /** @private */\n    audioContext = null;\n    /** @private */\n    offlineAudioContext = null;\n    /** @private */\n    stateBehaviors = {\n        [PLAYING]: {\n            init() {\n                this.addOnAudioProcess();\n            },\n            getPlayedPercents() {\n                const duration = this.getDuration();\n                return this.getCurrentTime() / duration || 0;\n            },\n            getCurrentTime() {\n                return this.startPosition + this.getPlayedTime();\n            }\n        },\n        [PAUSED]: {\n            init() {\n                this.removeOnAudioProcess();\n            },\n            getPlayedPercents() {\n                const duration = this.getDuration();\n                return this.getCurrentTime() / duration || 0;\n            },\n            getCurrentTime() {\n                return this.startPosition;\n            }\n        },\n        [FINISHED]: {\n            init() {\n                this.removeOnAudioProcess();\n                this.fireEvent('finish');\n            },\n            getPlayedPercents() {\n                return 1;\n            },\n            getCurrentTime() {\n                return this.getDuration();\n            }\n        }\n    };\n\n    /**\n     * Does the browser support this backend\n     *\n     * @return {boolean}\n     */\n    supportsWebAudio() {\n        return !!(window.AudioContext || window.webkitAudioContext);\n    }\n\n    /**\n     * Get the audio context used by this backend or create one\n     *\n     * @return {AudioContext}\n     */\n    getAudioContext() {\n        if (!window.WaveSurferAudioContext) {\n            window.WaveSurferAudioContext = new (window.AudioContext ||\n                window.webkitAudioContext)();\n        }\n        return window.WaveSurferAudioContext;\n    }\n\n    /**\n     * Get the offline audio context used by this backend or create one\n     *\n     * @param {number} sampleRate\n     * @return {OfflineAudioContext}\n     */\n    getOfflineAudioContext(sampleRate) {\n        if (!window.WaveSurferOfflineAudioContext) {\n            window.WaveSurferOfflineAudioContext = new (window.OfflineAudioContext ||\n                window.webkitOfflineAudioContext)(1, 2, sampleRate);\n        }\n        return window.WaveSurferOfflineAudioContext;\n    }\n\n    /**\n     * Construct the backend\n     *\n     * @param {WavesurferParams} params\n     */\n    constructor(params) {\n        super();\n        /** @private */\n        this.params = params;\n        /** @private */\n        this.ac = params.audioContext || this.getAudioContext();\n        /**@private */\n        this.lastPlay = this.ac.currentTime;\n        /** @private */\n        this.startPosition = 0;\n        /** @private  */\n        this.scheduledPause = null;\n        /** @private */\n        this.states = {\n            [PLAYING]: Object.create(this.stateBehaviors[PLAYING]),\n            [PAUSED]: Object.create(this.stateBehaviors[PAUSED]),\n            [FINISHED]: Object.create(this.stateBehaviors[FINISHED])\n        };\n        /** @private */\n        this.analyser = null;\n        /** @private */\n        this.buffer = null;\n        /** @private */\n        this.filters = [];\n        /** @private */\n        this.gainNode = null;\n        /** @private */\n        this.mergedPeaks = null;\n        /** @private */\n        this.offlineAc = null;\n        /** @private */\n        this.peaks = null;\n        /** @private */\n        this.playbackRate = 1;\n        /** @private */\n        this.analyser = null;\n        /** @private */\n        this.scriptNode = null;\n        /** @private */\n        this.source = null;\n        /** @private */\n        this.splitPeaks = [];\n        /** @private */\n        this.state = null;\n        /** @private */\n        this.explicitDuration = params.duration;\n    }\n\n    /**\n     * Initialise the backend, called in `wavesurfer.createBackend()`\n     */\n    init() {\n        this.createVolumeNode();\n        this.createScriptNode();\n        this.createAnalyserNode();\n\n        this.setState(PAUSED);\n        this.setPlaybackRate(this.params.audioRate);\n        this.setLength(0);\n    }\n\n    /** @private */\n    disconnectFilters() {\n        if (this.filters) {\n            this.filters.forEach(filter => {\n                filter && filter.disconnect();\n            });\n            this.filters = null;\n            // Reconnect direct path\n            this.analyser.connect(this.gainNode);\n        }\n    }\n\n    /** @private */\n    setState(state) {\n        if (this.state !== this.states[state]) {\n            this.state = this.states[state];\n            this.state.init.call(this);\n        }\n    }\n\n    /**\n     * Unpacked `setFilters()`\n     *\n     * @param {...AudioNode} filters\n     */\n    setFilter(...filters) {\n        this.setFilters(filters);\n    }\n\n    /**\n     * Insert custom Web Audio nodes into the graph\n     *\n     * @param {AudioNode[]} filters Packed filters array\n     * @example\n     * const lowpass = wavesurfer.backend.ac.createBiquadFilter();\n     * wavesurfer.backend.setFilter(lowpass);\n     */\n    setFilters(filters) {\n        // Remove existing filters\n        this.disconnectFilters();\n\n        // Insert filters if filter array not empty\n        if (filters && filters.length) {\n            this.filters = filters;\n\n            // Disconnect direct path before inserting filters\n            this.analyser.disconnect();\n\n            // Connect each filter in turn\n            filters\n                .reduce((prev, curr) => {\n                    prev.connect(curr);\n                    return curr;\n                }, this.analyser)\n                .connect(this.gainNode);\n        }\n    }\n\n    /** @private */\n    createScriptNode() {\n        if (this.params.audioScriptProcessor) {\n            this.scriptNode = this.params.audioScriptProcessor;\n        } else {\n            if (this.ac.createScriptProcessor) {\n                this.scriptNode = this.ac.createScriptProcessor(\n                    WebAudio.scriptBufferSize\n                );\n            } else {\n                this.scriptNode = this.ac.createJavaScriptNode(\n                    WebAudio.scriptBufferSize\n                );\n            }\n        }\n        this.scriptNode.connect(this.ac.destination);\n    }\n\n    /** @private */\n    addOnAudioProcess() {\n        this.scriptNode.onaudioprocess = () => {\n            const time = this.getCurrentTime();\n\n            if (time >= this.getDuration()) {\n                this.setState(FINISHED);\n                this.fireEvent('pause');\n            } else if (time >= this.scheduledPause) {\n                this.pause();\n            } else if (this.state === this.states[PLAYING]) {\n                this.fireEvent('audioprocess', time);\n            }\n        };\n    }\n\n    /** @private */\n    removeOnAudioProcess() {\n        this.scriptNode.onaudioprocess = () => {};\n    }\n\n    /** @private */\n    createAnalyserNode() {\n        this.analyser = this.ac.createAnalyser();\n        this.analyser.connect(this.gainNode);\n    }\n\n    /**\n     * Create the gain node needed to control the playback volume.\n     *\n     * @private\n     */\n    createVolumeNode() {\n        // Create gain node using the AudioContext\n        if (this.ac.createGain) {\n            this.gainNode = this.ac.createGain();\n        } else {\n            this.gainNode = this.ac.createGainNode();\n        }\n        // Add the gain node to the graph\n        this.gainNode.connect(this.ac.destination);\n    }\n\n    /**\n     * Set the sink id for the media player\n     *\n     * @param {string} deviceId String value representing audio device id.\n     */\n    setSinkId(deviceId) {\n        if (deviceId) {\n            /**\n             * The webaudio API doesn't currently support setting the device\n             * output. Here we create an HTMLAudioElement, connect the\n             * webaudio stream to that element and setSinkId there.\n             */\n            let audio = new window.Audio();\n            if (!audio.setSinkId) {\n                return Promise.reject(\n                    new Error('setSinkId is not supported in your browser')\n                );\n            }\n            audio.autoplay = true;\n            var dest = this.ac.createMediaStreamDestination();\n            this.gainNode.disconnect();\n            this.gainNode.connect(dest);\n            audio.srcObject = dest.stream;\n\n            return audio.setSinkId(deviceId);\n        } else {\n            return Promise.reject(new Error('Invalid deviceId: ' + deviceId));\n        }\n    }\n\n    /**\n     * Set the audio volume\n     *\n     * @param {number} value A floating point value between 0 and 1.\n     */\n    setVolume(value) {\n        this.gainNode.gain.setValueAtTime(value, this.ac.currentTime);\n    }\n\n    /**\n     * Get the current volume\n     *\n     * @return {number} value A floating point value between 0 and 1.\n     */\n    getVolume() {\n        return this.gainNode.gain.value;\n    }\n\n    /** @private */\n    decodeArrayBuffer(arraybuffer, callback, errback) {\n        if (!this.offlineAc) {\n            this.offlineAc = this.getOfflineAudioContext(\n                this.ac && this.ac.sampleRate ? this.ac.sampleRate : 44100\n            );\n        }\n        this.offlineAc.decodeAudioData(\n            arraybuffer,\n            data => callback(data),\n            errback\n        );\n    }\n\n    /**\n     * Set pre-decoded peaks\n     *\n     * @param {number[]|number[][]} peaks\n     * @param {?number} duration\n     */\n    setPeaks(peaks, duration) {\n        if (duration != null) {\n            this.explicitDuration = duration;\n        }\n        this.peaks = peaks;\n    }\n\n    /**\n     * Set the rendered length (different from the length of the audio).\n     *\n     * @param {number} length\n     */\n    setLength(length) {\n        // No resize, we can preserve the cached peaks.\n        if (this.mergedPeaks && length == 2 * this.mergedPeaks.length - 1 + 2) {\n            return;\n        }\n\n        this.splitPeaks = [];\n        this.mergedPeaks = [];\n        // Set the last element of the sparse array so the peak arrays are\n        // appropriately sized for other calculations.\n        const channels = this.buffer ? this.buffer.numberOfChannels : 1;\n        let c;\n        for (c = 0; c < channels; c++) {\n            this.splitPeaks[c] = [];\n            this.splitPeaks[c][2 * (length - 1)] = 0;\n            this.splitPeaks[c][2 * (length - 1) + 1] = 0;\n        }\n        this.mergedPeaks[2 * (length - 1)] = 0;\n        this.mergedPeaks[2 * (length - 1) + 1] = 0;\n    }\n\n    /**\n     * Compute the max and min value of the waveform when broken into <length> subranges.\n     *\n     * @param {number} length How many subranges to break the waveform into.\n     * @param {number} first First sample in the required range.\n     * @param {number} last Last sample in the required range.\n     * @return {number[]|number[][]} Array of 2*<length> peaks or array of arrays of\n     * peaks consisting of (max, min) values for each subrange.\n     */\n    getPeaks(length, first, last) {\n        if (this.peaks) {\n            return this.peaks;\n        }\n        if (!this.buffer) {\n            return [];\n        }\n\n        first = first || 0;\n        last = last || length - 1;\n\n        this.setLength(length);\n\n        if (!this.buffer) {\n            return this.params.splitChannels\n                ? this.splitPeaks\n                : this.mergedPeaks;\n        }\n\n        /**\n         * The following snippet fixes a buffering data issue on the Safari\n         * browser which returned undefined It creates the missing buffer based\n         * on 1 channel, 4096 samples and the sampleRate from the current\n         * webaudio context 4096 samples seemed to be the best fit for rendering\n         * will review this code once a stable version of Safari TP is out\n         */\n        if (!this.buffer.length) {\n            const newBuffer = this.createBuffer(1, 4096, this.sampleRate);\n            this.buffer = newBuffer.buffer;\n        }\n\n        const sampleSize = this.buffer.length / length;\n        const sampleStep = ~~(sampleSize / 10) || 1;\n        const channels = this.buffer.numberOfChannels;\n        let c;\n\n        for (c = 0; c < channels; c++) {\n            const peaks = this.splitPeaks[c];\n            const chan = this.buffer.getChannelData(c);\n            let i;\n\n            for (i = first; i <= last; i++) {\n                const start = ~~(i * sampleSize);\n                const end = ~~(start + sampleSize);\n                let min = 0;\n                let max = 0;\n                let j;\n\n                for (j = start; j < end; j += sampleStep) {\n                    const value = chan[j];\n\n                    if (value > max) {\n                        max = value;\n                    }\n\n                    if (value < min) {\n                        min = value;\n                    }\n                }\n\n                peaks[2 * i] = max;\n                peaks[2 * i + 1] = min;\n\n                if (c == 0 || max > this.mergedPeaks[2 * i]) {\n                    this.mergedPeaks[2 * i] = max;\n                }\n\n                if (c == 0 || min < this.mergedPeaks[2 * i + 1]) {\n                    this.mergedPeaks[2 * i + 1] = min;\n                }\n            }\n        }\n\n        return this.params.splitChannels ? this.splitPeaks : this.mergedPeaks;\n    }\n\n    /**\n     * Get the position from 0 to 1\n     *\n     * @return {number}\n     */\n    getPlayedPercents() {\n        return this.state.getPlayedPercents.call(this);\n    }\n\n    /** @private */\n    disconnectSource() {\n        if (this.source) {\n            this.source.disconnect();\n        }\n    }\n\n    /**\n     * This is called when wavesurfer is destroyed\n     */\n    destroy() {\n        if (!this.isPaused()) {\n            this.pause();\n        }\n        this.unAll();\n        this.buffer = null;\n        this.disconnectFilters();\n        this.disconnectSource();\n        this.gainNode.disconnect();\n        this.scriptNode.disconnect();\n        this.analyser.disconnect();\n\n        // close the audioContext if closeAudioContext option is set to true\n        if (this.params.closeAudioContext) {\n            // check if browser supports AudioContext.close()\n            if (\n                typeof this.ac.close === 'function' &&\n                this.ac.state != 'closed'\n            ) {\n                this.ac.close();\n            }\n            // clear the reference to the audiocontext\n            this.ac = null;\n            // clear the actual audiocontext, either passed as param or the\n            // global singleton\n            if (!this.params.audioContext) {\n                window.WaveSurferAudioContext = null;\n            } else {\n                this.params.audioContext = null;\n            }\n            // clear the offlineAudioContext\n            window.WaveSurferOfflineAudioContext = null;\n        }\n    }\n\n    /**\n     * Loaded a decoded audio buffer\n     *\n     * @param {Object} buffer\n     */\n    load(buffer) {\n        this.startPosition = 0;\n        this.lastPlay = this.ac.currentTime;\n        this.buffer = buffer;\n        this.createSource();\n    }\n\n    /** @private */\n    createSource() {\n        this.disconnectSource();\n        this.source = this.ac.createBufferSource();\n\n        // adjust for old browsers\n        this.source.start = this.source.start || this.source.noteGrainOn;\n        this.source.stop = this.source.stop || this.source.noteOff;\n\n        this.source.playbackRate.setValueAtTime(\n            this.playbackRate,\n            this.ac.currentTime\n        );\n        this.source.buffer = this.buffer;\n        this.source.connect(this.analyser);\n    }\n\n    /**\n     * Used by `wavesurfer.isPlaying()` and `wavesurfer.playPause()`\n     *\n     * @return {boolean}\n     */\n    isPaused() {\n        return this.state !== this.states[PLAYING];\n    }\n\n    /**\n     * Used by `wavesurfer.getDuration()`\n     *\n     * @return {number}\n     */\n    getDuration() {\n        if (this.explicitDuration) {\n            return this.explicitDuration;\n        }\n        if (!this.buffer) {\n            return 0;\n        }\n        return this.buffer.duration;\n    }\n\n    /**\n     * Used by `wavesurfer.seekTo()`\n     *\n     * @param {number} start Position to start at in seconds\n     * @param {number} end Position to end at in seconds\n     * @return {{start: number, end: number}}\n     */\n    seekTo(start, end) {\n        if (!this.buffer) {\n            return;\n        }\n\n        this.scheduledPause = null;\n\n        if (start == null) {\n            start = this.getCurrentTime();\n            if (start >= this.getDuration()) {\n                start = 0;\n            }\n        }\n        if (end == null) {\n            end = this.getDuration();\n        }\n\n        this.startPosition = start;\n        this.lastPlay = this.ac.currentTime;\n\n        if (this.state === this.states[FINISHED]) {\n            this.setState(PAUSED);\n        }\n\n        return {\n            start: start,\n            end: end\n        };\n    }\n\n    /**\n     * Get the playback position in seconds\n     *\n     * @return {number}\n     */\n    getPlayedTime() {\n        return (this.ac.currentTime - this.lastPlay) * this.playbackRate;\n    }\n\n    /**\n     * Plays the loaded audio region.\n     *\n     * @param {number} start Start offset in seconds, relative to the beginning\n     * of a clip.\n     * @param {number} end When to stop relative to the beginning of a clip.\n     */\n    play(start, end) {\n        if (!this.buffer) {\n            return;\n        }\n\n        // need to re-create source on each playback\n        this.createSource();\n\n        const adjustedTime = this.seekTo(start, end);\n\n        start = adjustedTime.start;\n        end = adjustedTime.end;\n\n        this.scheduledPause = end;\n\n        this.source.start(0, start, end - start);\n\n        if (this.ac.state == 'suspended') {\n            this.ac.resume && this.ac.resume();\n        }\n\n        this.setState(PLAYING);\n\n        this.fireEvent('play');\n    }\n\n    /**\n     * Pauses the loaded audio.\n     */\n    pause() {\n        this.scheduledPause = null;\n\n        this.startPosition += this.getPlayedTime();\n        this.source && this.source.stop(0);\n\n        this.setState(PAUSED);\n\n        this.fireEvent('pause');\n    }\n\n    /**\n     * Returns the current time in seconds relative to the audio-clip's\n     * duration.\n     *\n     * @return {number}\n     */\n    getCurrentTime() {\n        return this.state.getCurrentTime.call(this);\n    }\n\n    /**\n     * Returns the current playback rate. (0=no playback, 1=normal playback)\n     *\n     * @return {number}\n     */\n    getPlaybackRate() {\n        return this.playbackRate;\n    }\n\n    /**\n     * Set the audio source playback rate.\n     *\n     * @param {number} value\n     */\n    setPlaybackRate(value) {\n        value = value || 1;\n        if (this.isPaused()) {\n            this.playbackRate = value;\n        } else {\n            this.pause();\n            this.playbackRate = value;\n            this.play();\n        }\n    }\n}\n"],"sourceRoot":""}
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/wavesurfer.min.js
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/wavesurfer.min.js	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/wavesurfer.min.js	(revision 33546)
@@ -0,0 +1,2 @@
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("WaveSurfer",[],t):"object"==typeof exports?exports.WaveSurfer=t():e.WaveSurfer=t()}(window,(function(){return function(e){var t={};function r(n){if(t[n])return t[n].exports;var i=t[n]={i:n,l:!1,exports:{}};return e[n].call(i.exports,i,i.exports,r),i.l=!0,i.exports}return r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)r.d(n,i,function(t){return e[t]}.bind(null,i));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=4)}([function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"ajax",{enumerable:!0,get:function(){return n.default}}),Object.defineProperty(t,"getId",{enumerable:!0,get:function(){return i.default}}),Object.defineProperty(t,"max",{enumerable:!0,get:function(){return a.default}}),Object.defineProperty(t,"min",{enumerable:!0,get:function(){return s.default}}),Object.defineProperty(t,"Observer",{enumerable:!0,get:function(){return o.default}}),Object.defineProperty(t,"extend",{enumerable:!0,get:function(){return u.default}}),Object.defineProperty(t,"style",{enumerable:!0,get:function(){return l.default}}),Object.defineProperty(t,"requestAnimationFrame",{enumerable:!0,get:function(){return c.default}}),Object.defineProperty(t,"frame",{enumerable:!0,get:function(){return f.default}}),Object.defineProperty(t,"debounce",{enumerable:!0,get:function(){return h.default}}),Object.defineProperty(t,"preventClick",{enumerable:!0,get:function(){return d.default}});var n=p(r(5)),i=p(r(6)),a=p(r(7)),s=p(r(8)),o=p(r(1)),u=p(r(9)),l=p(r(10)),c=p(r(2)),f=p(r(11)),h=p(r(12)),d=p(r(13));function p(e){return e&&e.__esModule?e:{default:e}}},function(e,t,r){"use strict";function n(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var i=function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.handlers=null}var t,r,i;return t=e,(r=[{key:"on",value:function(e,t){var r=this;this.handlers||(this.handlers={});var n=this.handlers[e];return n||(n=this.handlers[e]=[]),n.push(t),{name:e,callback:t,un:function(e,t){return r.un(e,t)}}}},{key:"un",value:function(e,t){if(this.handlers){var r,n=this.handlers[e];if(n)if(t)for(r=n.length-1;r>=0;r--)n[r]==t&&n.splice(r,1);else n.length=0}}},{key:"unAll",value:function(){this.handlers=null}},{key:"once",value:function(e,t){var r=this;return this.on(e,(function n(){for(var i=arguments.length,a=new Array(i),s=0;s<i;s++)a[s]=arguments[s];t.apply(r,a),setTimeout((function(){r.un(e,n)}),0)}))}},{key:"fireEvent",value:function(e){for(var t=arguments.length,r=new Array(t>1?t-1:0),n=1;n<t;n++)r[n-1]=arguments[n];if(this.handlers){var i=this.handlers[e];i&&i.forEach((function(e){e.apply(void 0,r)}))}}}])&&n(t.prototype,r),i&&n(t,i),e}();t.default=i,e.exports=t.default},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n=(window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(e,t){return setTimeout(e,1e3/60)}).bind(window);t.default=n,e.exports=t.default},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n=function(e){if(e&&e.__esModule)return e;var t=i();if(t&&t.has(e))return t.get(e);var r={};if(null!=e){var n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if(Object.prototype.hasOwnProperty.call(e,a)){var s=n?Object.getOwnPropertyDescriptor(e,a):null;s&&(s.get||s.set)?Object.defineProperty(r,a,s):r[a]=e[a]}}r.default=e,t&&t.set(e,r);return r}(r(0));function i(){if("function"!=typeof WeakMap)return null;var e=new WeakMap;return i=function(){return e},e}function a(e){return(a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function s(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function o(e,t){return!t||"object"!==a(t)&&"function"!=typeof t?function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e):t}function u(e){return(u=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function l(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}function c(e,t,r){return t&&l(e.prototype,t),r&&l(e,r),e}function f(e,t){return(f=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}var h="playing",d="paused",p="finished",v=function(e){function t(e){var r,n,i;return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),(i=o(this,u(t).call(this))).audioContext=null,i.offlineAudioContext=null,i.stateBehaviors=(s(r={},h,{init:function(){this.addOnAudioProcess()},getPlayedPercents:function(){var e=this.getDuration();return this.getCurrentTime()/e||0},getCurrentTime:function(){return this.startPosition+this.getPlayedTime()}}),s(r,d,{init:function(){this.removeOnAudioProcess()},getPlayedPercents:function(){var e=this.getDuration();return this.getCurrentTime()/e||0},getCurrentTime:function(){return this.startPosition}}),s(r,p,{init:function(){this.removeOnAudioProcess(),this.fireEvent("finish")},getPlayedPercents:function(){return 1},getCurrentTime:function(){return this.getDuration()}}),r),i.params=e,i.ac=e.audioContext||i.getAudioContext(),i.lastPlay=i.ac.currentTime,i.startPosition=0,i.scheduledPause=null,i.states=(s(n={},h,Object.create(i.stateBehaviors[h])),s(n,d,Object.create(i.stateBehaviors[d])),s(n,p,Object.create(i.stateBehaviors[p])),n),i.analyser=null,i.buffer=null,i.filters=[],i.gainNode=null,i.mergedPeaks=null,i.offlineAc=null,i.peaks=null,i.playbackRate=1,i.analyser=null,i.scriptNode=null,i.source=null,i.splitPeaks=[],i.state=null,i.explicitDuration=e.duration,i}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&f(e,t)}(t,e),c(t,[{key:"supportsWebAudio",value:function(){return!(!window.AudioContext&&!window.webkitAudioContext)}},{key:"getAudioContext",value:function(){return window.WaveSurferAudioContext||(window.WaveSurferAudioContext=new(window.AudioContext||window.webkitAudioContext)),window.WaveSurferAudioContext}},{key:"getOfflineAudioContext",value:function(e){return window.WaveSurferOfflineAudioContext||(window.WaveSurferOfflineAudioContext=new(window.OfflineAudioContext||window.webkitOfflineAudioContext)(1,2,e)),window.WaveSurferOfflineAudioContext}}]),c(t,[{key:"init",value:function(){this.createVolumeNode(),this.createScriptNode(),this.createAnalyserNode(),this.setState(d),this.setPlaybackRate(this.params.audioRate),this.setLength(0)}},{key:"disconnectFilters",value:function(){this.filters&&(this.filters.forEach((function(e){e&&e.disconnect()})),this.filters=null,this.analyser.connect(this.gainNode))}},{key:"setState",value:function(e){this.state!==this.states[e]&&(this.state=this.states[e],this.state.init.call(this))}},{key:"setFilter",value:function(){for(var e=arguments.length,t=new Array(e),r=0;r<e;r++)t[r]=arguments[r];this.setFilters(t)}},{key:"setFilters",value:function(e){this.disconnectFilters(),e&&e.length&&(this.filters=e,this.analyser.disconnect(),e.reduce((function(e,t){return e.connect(t),t}),this.analyser).connect(this.gainNode))}},{key:"createScriptNode",value:function(){this.params.audioScriptProcessor?this.scriptNode=this.params.audioScriptProcessor:this.ac.createScriptProcessor?this.scriptNode=this.ac.createScriptProcessor(t.scriptBufferSize):this.scriptNode=this.ac.createJavaScriptNode(t.scriptBufferSize),this.scriptNode.connect(this.ac.destination)}},{key:"addOnAudioProcess",value:function(){var e=this;this.scriptNode.onaudioprocess=function(){var t=e.getCurrentTime();t>=e.getDuration()?(e.setState(p),e.fireEvent("pause")):t>=e.scheduledPause?e.pause():e.state===e.states[h]&&e.fireEvent("audioprocess",t)}}},{key:"removeOnAudioProcess",value:function(){this.scriptNode.onaudioprocess=function(){}}},{key:"createAnalyserNode",value:function(){this.analyser=this.ac.createAnalyser(),this.analyser.connect(this.gainNode)}},{key:"createVolumeNode",value:function(){this.ac.createGain?this.gainNode=this.ac.createGain():this.gainNode=this.ac.createGainNode(),this.gainNode.connect(this.ac.destination)}},{key:"setSinkId",value:function(e){if(e){var t=new window.Audio;if(!t.setSinkId)return Promise.reject(new Error("setSinkId is not supported in your browser"));t.autoplay=!0;var r=this.ac.createMediaStreamDestination();return this.gainNode.disconnect(),this.gainNode.connect(r),t.srcObject=r.stream,t.setSinkId(e)}return Promise.reject(new Error("Invalid deviceId: "+e))}},{key:"setVolume",value:function(e){this.gainNode.gain.setValueAtTime(e,this.ac.currentTime)}},{key:"getVolume",value:function(){return this.gainNode.gain.value}},{key:"decodeArrayBuffer",value:function(e,t,r){this.offlineAc||(this.offlineAc=this.getOfflineAudioContext(this.ac&&this.ac.sampleRate?this.ac.sampleRate:44100)),this.offlineAc.decodeAudioData(e,(function(e){return t(e)}),r)}},{key:"setPeaks",value:function(e,t){null!=t&&(this.explicitDuration=t),this.peaks=e}},{key:"setLength",value:function(e){if(!this.mergedPeaks||e!=2*this.mergedPeaks.length-1+2){this.splitPeaks=[],this.mergedPeaks=[];var t,r=this.buffer?this.buffer.numberOfChannels:1;for(t=0;t<r;t++)this.splitPeaks[t]=[],this.splitPeaks[t][2*(e-1)]=0,this.splitPeaks[t][2*(e-1)+1]=0;this.mergedPeaks[2*(e-1)]=0,this.mergedPeaks[2*(e-1)+1]=0}}},{key:"getPeaks",value:function(e,t,r){if(this.peaks)return this.peaks;if(!this.buffer)return[];if(t=t||0,r=r||e-1,this.setLength(e),!this.buffer)return this.params.splitChannels?this.splitPeaks:this.mergedPeaks;if(!this.buffer.length){var n=this.createBuffer(1,4096,this.sampleRate);this.buffer=n.buffer}var i,a=this.buffer.length/e,s=~~(a/10)||1,o=this.buffer.numberOfChannels;for(i=0;i<o;i++){var u=this.splitPeaks[i],l=this.buffer.getChannelData(i),c=void 0;for(c=t;c<=r;c++){var f=~~(c*a),h=~~(f+a),d=0,p=0,v=void 0;for(v=f;v<h;v+=s){var y=l[v];y>p&&(p=y),y<d&&(d=y)}u[2*c]=p,u[2*c+1]=d,(0==i||p>this.mergedPeaks[2*c])&&(this.mergedPeaks[2*c]=p),(0==i||d<this.mergedPeaks[2*c+1])&&(this.mergedPeaks[2*c+1]=d)}}return this.params.splitChannels?this.splitPeaks:this.mergedPeaks}},{key:"getPlayedPercents",value:function(){return this.state.getPlayedPercents.call(this)}},{key:"disconnectSource",value:function(){this.source&&this.source.disconnect()}},{key:"destroy",value:function(){this.isPaused()||this.pause(),this.unAll(),this.buffer=null,this.disconnectFilters(),this.disconnectSource(),this.gainNode.disconnect(),this.scriptNode.disconnect(),this.analyser.disconnect(),this.params.closeAudioContext&&("function"==typeof this.ac.close&&"closed"!=this.ac.state&&this.ac.close(),this.ac=null,this.params.audioContext?this.params.audioContext=null:window.WaveSurferAudioContext=null,window.WaveSurferOfflineAudioContext=null)}},{key:"load",value:function(e){this.startPosition=0,this.lastPlay=this.ac.currentTime,this.buffer=e,this.createSource()}},{key:"createSource",value:function(){this.disconnectSource(),this.source=this.ac.createBufferSource(),this.source.start=this.source.start||this.source.noteGrainOn,this.source.stop=this.source.stop||this.source.noteOff,this.source.playbackRate.setValueAtTime(this.playbackRate,this.ac.currentTime),this.source.buffer=this.buffer,this.source.connect(this.analyser)}},{key:"isPaused",value:function(){return this.state!==this.states[h]}},{key:"getDuration",value:function(){return this.explicitDuration?this.explicitDuration:this.buffer?this.buffer.duration:0}},{key:"seekTo",value:function(e,t){if(this.buffer)return this.scheduledPause=null,null==e&&(e=this.getCurrentTime())>=this.getDuration()&&(e=0),null==t&&(t=this.getDuration()),this.startPosition=e,this.lastPlay=this.ac.currentTime,this.state===this.states[p]&&this.setState(d),{start:e,end:t}}},{key:"getPlayedTime",value:function(){return(this.ac.currentTime-this.lastPlay)*this.playbackRate}},{key:"play",value:function(e,t){if(this.buffer){this.createSource();var r=this.seekTo(e,t);e=r.start,t=r.end,this.scheduledPause=t,this.source.start(0,e,t-e),"suspended"==this.ac.state&&this.ac.resume&&this.ac.resume(),this.setState(h),this.fireEvent("play")}}},{key:"pause",value:function(){this.scheduledPause=null,this.startPosition+=this.getPlayedTime(),this.source&&this.source.stop(0),this.setState(d),this.fireEvent("pause")}},{key:"getCurrentTime",value:function(){return this.state.getCurrentTime.call(this)}},{key:"getPlaybackRate",value:function(){return this.playbackRate}},{key:"setPlaybackRate",value:function(e){e=e||1,this.isPaused()?this.playbackRate=e:(this.pause(),this.playbackRate=e,this.play())}}]),t}(n.Observer);t.default=v,v.scriptBufferSize=256,e.exports=t.default},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n=function(e){if(e&&e.__esModule)return e;var t=l();if(t&&t.has(e))return t.get(e);var r={};if(null!=e){var n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var i in e)if(Object.prototype.hasOwnProperty.call(e,i)){var a=n?Object.getOwnPropertyDescriptor(e,i):null;a&&(a.get||a.set)?Object.defineProperty(r,i,a):r[i]=e[i]}}r.default=e,t&&t.set(e,r);return r}(r(0)),i=u(r(14)),a=u(r(3)),s=u(r(16)),o=u(r(17));function u(e){return e&&e.__esModule?e:{default:e}}function l(){if("function"!=typeof WeakMap)return null;var e=new WeakMap;return l=function(){return e},e}function c(e){return(c="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function f(e,t){return!t||"object"!==c(t)&&"function"!=typeof t?d(e):t}function h(e){return(h=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function d(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function p(e,t){return(p=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function v(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function y(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}function m(e,t,r){return t&&y(e.prototype,t),r&&y(e,r),e}var b=function(e){function t(e){var r;if(v(this,t),(r=f(this,h(t).call(this))).defaultParams={audioContext:null,audioScriptProcessor:null,audioRate:1,autoCenter:!0,backend:"WebAudio",backgroundColor:null,barHeight:1,barGap:null,container:null,cursorColor:"#333",cursorWidth:1,dragSelection:!0,duration:null,fillParent:!0,forceDecode:!1,height:128,hideScrollbar:!1,interact:!0,loopSelection:!0,maxCanvasWidth:4e3,mediaContainer:null,mediaControls:!1,mediaType:"audio",minPxPerSec:20,normalize:!1,partialRender:!1,pixelRatio:window.devicePixelRatio||screen.deviceXDPI/screen.logicalXDPI,plugins:[],progressColor:"#555",removeMediaElementOnDestroy:!0,renderer:i.default,responsive:!1,rtl:!1,scrollParent:!1,skipLength:2,splitChannels:!1,waveColor:"#999",xhr:{}},r.backends={MediaElement:s.default,WebAudio:a.default},r.util=n,r.params=n.extend({},r.defaultParams,e),r.container="string"==typeof e.container?document.querySelector(r.params.container):r.params.container,!r.container)throw new Error("Container element not found");if(null==r.params.mediaContainer?r.mediaContainer=r.container:"string"==typeof r.params.mediaContainer?r.mediaContainer=document.querySelector(r.params.mediaContainer):r.mediaContainer=r.params.mediaContainer,!r.mediaContainer)throw new Error("Media Container element not found");if(r.params.maxCanvasWidth<=1)throw new Error("maxCanvasWidth must be greater than 1");if(r.params.maxCanvasWidth%2==1)throw new Error("maxCanvasWidth must be an even number");if(!0===r.params.rtl&&n.style(r.container,{transform:"rotateY(180deg)"}),r.params.backgroundColor&&r.setBackgroundColor(r.params.backgroundColor),r.savedVolume=0,r.isMuted=!1,r.tmpEvents=[],r.currentAjax=null,r.arraybuffer=null,r.drawer=null,r.backend=null,r.peakCache=null,"function"!=typeof r.params.renderer)throw new Error("Renderer parameter is invalid");r.Drawer=r.params.renderer,r.Backend=r.backends[r.params.backend],r.initialisedPluginList={},r.isDestroyed=!1,r.isReady=!1;var o=0;return r._onResize=n.debounce((function(){o==r.drawer.wrapper.clientWidth||r.params.scrollParent||(o=r.drawer.wrapper.clientWidth,r.drawer.fireEvent("redraw"))}),"number"==typeof r.params.responsive?r.params.responsive:100),f(r,d(r))}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&p(e,t)}(t,e),m(t,null,[{key:"create",value:function(e){return new t(e).init()}}]),m(t,[{key:"init",value:function(){return this.registerPlugins(this.params.plugins),this.createDrawer(),this.createBackend(),this.createPeakCache(),this}},{key:"registerPlugins",value:function(e){var t=this;return e.forEach((function(e){return t.addPlugin(e)})),e.forEach((function(e){e.deferInit||t.initPlugin(e.name)})),this.fireEvent("plugins-registered",e),this}},{key:"addPlugin",value:function(e){var t=this;if(!e.name)throw new Error("Plugin does not have a name!");if(!e.instance)throw new Error("Plugin ".concat(e.name," does not have an instance property!"));e.staticProps&&Object.keys(e.staticProps).forEach((function(r){t[r]=e.staticProps[r]}));var r=e.instance;return Object.getOwnPropertyNames(n.Observer.prototype).forEach((function(e){r.prototype[e]=n.Observer.prototype[e]})),this[e.name]=new r(e.params||{},this),this.fireEvent("plugin-added",e.name),this}},{key:"initPlugin",value:function(e){if(!this[e])throw new Error("Plugin ".concat(e," has not been added yet!"));return this.initialisedPluginList[e]&&this.destroyPlugin(e),this[e].init(),this.initialisedPluginList[e]=!0,this.fireEvent("plugin-initialised",e),this}},{key:"destroyPlugin",value:function(e){if(!this[e])throw new Error("Plugin ".concat(e," has not been added yet and cannot be destroyed!"));if(!this.initialisedPluginList[e])throw new Error("Plugin ".concat(e," is not active and cannot be destroyed!"));if("function"!=typeof this[e].destroy)throw new Error("Plugin ".concat(e," does not have a destroy function!"));return this[e].destroy(),delete this.initialisedPluginList[e],this.fireEvent("plugin-destroyed",e),this}},{key:"destroyAllPlugins",value:function(){var e=this;Object.keys(this.initialisedPluginList).forEach((function(t){return e.destroyPlugin(t)}))}},{key:"createDrawer",value:function(){var e=this;this.drawer=new this.Drawer(this.container,this.params),this.drawer.init(),this.fireEvent("drawer-created",this.drawer),!1!==this.params.responsive&&(window.addEventListener("resize",this._onResize,!0),window.addEventListener("orientationchange",this._onResize,!0)),this.drawer.on("redraw",(function(){e.drawBuffer(),e.drawer.progress(e.backend.getPlayedPercents())})),this.drawer.on("click",(function(t,r){setTimeout((function(){return e.seekTo(r)}),0)})),this.drawer.on("scroll",(function(t){e.params.partialRender&&e.drawBuffer(),e.fireEvent("scroll",t)}))}},{key:"createBackend",value:function(){var e=this;this.backend&&this.backend.destroy(),"AudioElement"==this.params.backend&&(this.params.backend="MediaElement"),"WebAudio"!=this.params.backend||this.Backend.prototype.supportsWebAudio.call(null)||(this.params.backend="MediaElement"),this.backend=new this.Backend(this.params),this.backend.init(),this.fireEvent("backend-created",this.backend),this.backend.on("finish",(function(){e.drawer.progress(e.backend.getPlayedPercents()),e.fireEvent("finish")})),this.backend.on("play",(function(){return e.fireEvent("play")})),this.backend.on("pause",(function(){return e.fireEvent("pause")})),this.backend.on("audioprocess",(function(t){e.drawer.progress(e.backend.getPlayedPercents()),e.fireEvent("audioprocess",t)}))}},{key:"createPeakCache",value:function(){this.params.partialRender&&(this.peakCache=new o.default)}},{key:"getDuration",value:function(){return this.backend.getDuration()}},{key:"getCurrentTime",value:function(){return this.backend.getCurrentTime()}},{key:"setCurrentTime",value:function(e){e>=this.getDuration()?this.seekTo(1):this.seekTo(e/this.getDuration())}},{key:"play",value:function(e,t){var r=this;return this.fireEvent("interaction",(function(){return r.play(e,t)})),this.backend.play(e,t)}},{key:"pause",value:function(){if(!this.backend.isPaused())return this.backend.pause()}},{key:"playPause",value:function(){return this.backend.isPaused()?this.play():this.pause()}},{key:"isPlaying",value:function(){return!this.backend.isPaused()}},{key:"skipBackward",value:function(e){this.skip(-e||-this.params.skipLength)}},{key:"skipForward",value:function(e){this.skip(e||this.params.skipLength)}},{key:"skip",value:function(e){var t=this.getDuration()||1,r=this.getCurrentTime()||0;r=Math.max(0,Math.min(t,r+(e||0))),this.seekAndCenter(r/t)}},{key:"seekAndCenter",value:function(e){this.seekTo(e),this.drawer.recenter(e)}},{key:"seekTo",value:function(e){var t=this;if("number"!=typeof e||!isFinite(e)||e<0||e>1)return console.error("Error calling wavesurfer.seekTo, parameter must be a number between 0 and 1!");this.fireEvent("interaction",(function(){return t.seekTo(e)}));var r=this.backend.isPaused();r||this.backend.pause();var n=this.params.scrollParent;this.params.scrollParent=!1,this.backend.seekTo(e*this.getDuration()),this.drawer.progress(e),r||this.backend.play(),this.params.scrollParent=n,this.fireEvent("seek",e)}},{key:"stop",value:function(){this.pause(),this.seekTo(0),this.drawer.progress(0)}},{key:"setSinkId",value:function(e){return this.backend.setSinkId(e)}},{key:"setVolume",value:function(e){this.backend.setVolume(e),this.fireEvent("volume",e)}},{key:"getVolume",value:function(){return this.backend.getVolume()}},{key:"setPlaybackRate",value:function(e){this.backend.setPlaybackRate(e)}},{key:"getPlaybackRate",value:function(){return this.backend.getPlaybackRate()}},{key:"toggleMute",value:function(){this.setMute(!this.isMuted)}},{key:"setMute",value:function(e){e!==this.isMuted?(e?(this.savedVolume=this.backend.getVolume(),this.backend.setVolume(0),this.isMuted=!0,this.fireEvent("volume",0)):(this.backend.setVolume(this.savedVolume),this.isMuted=!1,this.fireEvent("volume",this.savedVolume)),this.fireEvent("mute",this.isMuted)):this.fireEvent("mute",this.isMuted)}},{key:"getMute",value:function(){return this.isMuted}},{key:"isReady",value:function(){return this.isReady}},{key:"getFilters",value:function(){return this.backend.filters||[]}},{key:"toggleScroll",value:function(){this.params.scrollParent=!this.params.scrollParent,this.drawBuffer()}},{key:"toggleInteraction",value:function(){this.params.interact=!this.params.interact}},{key:"getWaveColor",value:function(){return this.params.waveColor}},{key:"setWaveColor",value:function(e){this.params.waveColor=e,this.drawBuffer()}},{key:"getProgressColor",value:function(){return this.params.progressColor}},{key:"setProgressColor",value:function(e){this.params.progressColor=e,this.drawBuffer()}},{key:"getBackgroundColor",value:function(){return this.params.backgroundColor}},{key:"setBackgroundColor",value:function(e){this.params.backgroundColor=e,n.style(this.container,{background:this.params.backgroundColor})}},{key:"getCursorColor",value:function(){return this.params.cursorColor}},{key:"setCursorColor",value:function(e){this.params.cursorColor=e,this.drawer.updateCursor()}},{key:"getHeight",value:function(){return this.params.height}},{key:"setHeight",value:function(e){this.params.height=e,this.drawer.setHeight(e*this.params.pixelRatio),this.drawBuffer()}},{key:"drawBuffer",value:function(){var e,t=Math.round(this.getDuration()*this.params.minPxPerSec*this.params.pixelRatio),r=this.drawer.getWidth(),n=t,i=0,a=Math.max(i+r,n);if(this.params.fillParent&&(!this.params.scrollParent||t<r)&&(i=0,a=n=r),this.params.partialRender){var s,o=this.peakCache.addRangeToPeakCache(n,i,a);for(s=0;s<o.length;s++)e=this.backend.getPeaks(n,o[s][0],o[s][1]),this.drawer.drawPeaks(e,n,o[s][0],o[s][1])}else e=this.backend.getPeaks(n,i,a),this.drawer.drawPeaks(e,n,i,a);this.fireEvent("redraw",e,n)}},{key:"zoom",value:function(e){e?(this.params.minPxPerSec=e,this.params.scrollParent=!0):(this.params.minPxPerSec=this.defaultParams.minPxPerSec,this.params.scrollParent=!1),this.drawBuffer(),this.drawer.progress(this.backend.getPlayedPercents()),this.drawer.recenter(this.getCurrentTime()/this.getDuration()),this.fireEvent("zoom",e)}},{key:"loadArrayBuffer",value:function(e){var t=this;this.decodeArrayBuffer(e,(function(e){t.isDestroyed||t.loadDecodedBuffer(e)}))}},{key:"loadDecodedBuffer",value:function(e){this.backend.load(e),this.drawBuffer(),this.fireEvent("ready"),this.isReady=!0}},{key:"loadBlob",value:function(e){var t=this,r=new FileReader;r.addEventListener("progress",(function(e){return t.onProgress(e)})),r.addEventListener("load",(function(e){return t.loadArrayBuffer(e.target.result)})),r.addEventListener("error",(function(){return t.fireEvent("error","Error reading file")})),r.readAsArrayBuffer(e),this.empty()}},{key:"load",value:function(e,t,r,n){if(this.empty(),r){var i={"Preload is not 'auto', 'none' or 'metadata'":-1===["auto","metadata","none"].indexOf(r),"Peaks are not provided":!t,"Backend is not of type MediaElement":"MediaElement"!==this.params.backend,"Url is not of type string":"string"!=typeof e},a=Object.keys(i).filter((function(e){return i[e]}));a.length&&(console.warn("Preload parameter of wavesurfer.load will be ignored because:\n\t- "+a.join("\n\t- ")),r=null)}switch(this.params.backend){case"WebAudio":return this.loadBuffer(e,t,n);case"MediaElement":return this.loadMediaElement(e,t,r,n)}}},{key:"loadBuffer",value:function(e,t,r){var n=this,i=function(t){return t&&n.tmpEvents.push(n.once("ready",t)),n.getArrayBuffer(e,(function(e){return n.loadArrayBuffer(e)}))};if(!t)return i();this.backend.setPeaks(t,r),this.drawBuffer(),this.tmpEvents.push(this.once("interaction",i))}},{key:"loadMediaElement",value:function(e,t,r,n){var i=this,a=e;if("string"==typeof e)this.backend.load(a,this.mediaContainer,t,r);else{var s=e;this.backend.loadElt(s,t),a=s.src}this.tmpEvents.push(this.backend.once("canplay",(function(){i.drawBuffer(),i.fireEvent("ready"),i.isReady=!0})),this.backend.once("error",(function(e){return i.fireEvent("error",e)}))),t&&this.backend.setPeaks(t,n),t&&!this.params.forceDecode||!this.backend.supportsWebAudio()||this.getArrayBuffer(a,(function(e){i.decodeArrayBuffer(e,(function(e){i.backend.buffer=e,i.backend.setPeaks(null),i.drawBuffer(),i.fireEvent("waveform-ready")}))}))}},{key:"decodeArrayBuffer",value:function(e,t){var r=this;this.arraybuffer=e,this.backend.decodeArrayBuffer(e,(function(n){r.isDestroyed||r.arraybuffer!=e||(t(n),r.arraybuffer=null)}),(function(){return r.fireEvent("error","Error decoding audiobuffer")}))}},{key:"getArrayBuffer",value:function(e,t){var r=this,i=n.ajax({url:e,responseType:"arraybuffer",xhr:this.params.xhr});return this.currentAjax=i,this.tmpEvents.push(i.on("progress",(function(e){r.onProgress(e)})),i.on("success",(function(e,n){t(e),r.currentAjax=null})),i.on("error",(function(e){r.fireEvent("error","XHR error: "+e.target.statusText),r.currentAjax=null}))),i}},{key:"onProgress",value:function(e){var t;t=e.lengthComputable?e.loaded/e.total:e.loaded/(e.loaded+1e6),this.fireEvent("loading",Math.round(100*t),e.target)}},{key:"exportPCM",value:function(e,t,r,n){e=e||1024,n=n||0,t=t||1e4,r=r||!1;var i=this.backend.getPeaks(e,n),a=[].map.call(i,(function(e){return Math.round(e*t)/t})),s=JSON.stringify(a);return r||window.open("data:application/json;charset=utf-8,"+encodeURIComponent(s)),s}},{key:"exportImage",value:function(e,t){return e||(e="image/png"),t||(t=1),this.drawer.getImage(e,t)}},{key:"cancelAjax",value:function(){this.currentAjax&&(this.currentAjax.xhr.abort(),this.currentAjax=null)}},{key:"clearTmpEvents",value:function(){this.tmpEvents.forEach((function(e){return e.un()}))}},{key:"empty",value:function(){this.backend.isPaused()||(this.stop(),this.backend.disconnectSource()),this.isReady=!1,this.cancelAjax(),this.clearTmpEvents(),this.drawer.progress(0),this.drawer.setWidth(0),this.drawer.drawPeaks({length:this.drawer.getWidth()},0)}},{key:"destroy",value:function(){this.destroyAllPlugins(),this.fireEvent("destroy"),this.cancelAjax(),this.clearTmpEvents(),this.unAll(),!1!==this.params.responsive&&(window.removeEventListener("resize",this._onResize,!0),window.removeEventListener("orientationchange",this._onResize,!0)),this.backend.destroy(),this.drawer.destroy(),this.isDestroyed=!0,this.isReady=!1,this.arraybuffer=null}}]),t}(n.Observer);t.default=b,b.VERSION="2.2.1",b.util=n,e.exports=t.default},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){var t=new i.default,r=new XMLHttpRequest,n=!1;r.open(e.method||"GET",e.url,!0),r.responseType=e.responseType||"json",e.xhr&&(e.xhr.requestHeaders&&e.xhr.requestHeaders.forEach((function(e){r.setRequestHeader(e.key,e.value)})),e.xhr.withCredentials&&(r.withCredentials=!0));return r.addEventListener("progress",(function(e){t.fireEvent("progress",e),e.lengthComputable&&e.loaded==e.total&&(n=!0)})),r.addEventListener("load",(function(e){n||t.fireEvent("progress",e),t.fireEvent("load",e),200==r.status||206==r.status?t.fireEvent("success",r.response,e):t.fireEvent("error",e)})),r.addEventListener("error",(function(e){return t.fireEvent("error",e)})),r.send(),t.xhr=r,t};var n,i=(n=r(1))&&n.__esModule?n:{default:n};e.exports=t.default},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(){return"wavesurfer_"+Math.random().toString(32).substring(2)},e.exports=t.default},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){var t=-1/0;return Object.keys(e).forEach((function(r){e[r]>t&&(t=e[r])})),t},e.exports=t.default},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){var t=Number(1/0);return Object.keys(e).forEach((function(r){e[r]<t&&(t=e[r])})),t},e.exports=t.default},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){for(var t=arguments.length,r=new Array(t>1?t-1:0),n=1;n<t;n++)r[n-1]=arguments[n];return r.forEach((function(t){Object.keys(t).forEach((function(r){e[r]=t[r]}))})),e},e.exports=t.default},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){return Object.keys(t).forEach((function(r){e.style[r]!==t[r]&&(e.style[r]=t[r])})),e},e.exports=t.default},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){return function(){for(var t=arguments.length,r=new Array(t),n=0;n<t;n++)r[n]=arguments[n];return(0,i.default)((function(){return e.apply(void 0,r)}))}};var n,i=(n=r(2))&&n.__esModule?n:{default:n};e.exports=t.default},function(e,t){function r(e,t,r){var n,i,a,s,o;function u(){var l=Date.now()-s;l<t&&l>=0?n=setTimeout(u,t-l):(n=null,r||(o=e.apply(a,i),a=i=null))}null==t&&(t=100);var l=function(){a=this,i=arguments,s=Date.now();var l=r&&!n;return n||(n=setTimeout(u,t)),l&&(o=e.apply(a,i),a=i=null),o};return l.clear=function(){n&&(clearTimeout(n),n=null)},l.flush=function(){n&&(o=e.apply(a,i),a=i=null,clearTimeout(n),n=null)},l}r.debounce=r,e.exports=r},function(e,t,r){"use strict";function n(e){e.stopPropagation(),document.body.removeEventListener("click",n,!0)}Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){document.body.addEventListener("click",n,!0)},e.exports=t.default},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n,i=(n=r(15))&&n.__esModule?n:{default:n},a=function(e){if(e&&e.__esModule)return e;var t=s();if(t&&t.has(e))return t.get(e);var r={};if(null!=e){var n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var i in e)if(Object.prototype.hasOwnProperty.call(e,i)){var a=n?Object.getOwnPropertyDescriptor(e,i):null;a&&(a.get||a.set)?Object.defineProperty(r,i,a):r[i]=e[i]}}r.default=e,t&&t.set(e,r);return r}(r(0));function s(){if("function"!=typeof WeakMap)return null;var e=new WeakMap;return s=function(){return e},e}function o(e){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function u(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}function l(e,t){return!t||"object"!==o(t)&&"function"!=typeof t?function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e):t}function c(e){return(c=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function f(e,t){return(f=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}var h=function(e){function t(e,r){var n;return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),(n=l(this,c(t).call(this,e,r))).maxCanvasWidth=r.maxCanvasWidth,n.maxCanvasElementWidth=Math.round(r.maxCanvasWidth/r.pixelRatio),n.hasProgressCanvas=r.waveColor!=r.progressColor,n.halfPixel=.5/r.pixelRatio,n.canvases=[],n.progressWave=null,n}var r,n,i;return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&f(e,t)}(t,e),r=t,(n=[{key:"init",value:function(){this.createWrapper(),this.createElements()}},{key:"createElements",value:function(){this.progressWave=this.wrapper.appendChild(this.style(document.createElement("wave"),{position:"absolute",zIndex:3,left:0,top:0,bottom:0,overflow:"hidden",width:"0",display:"none",boxSizing:"border-box",borderRightStyle:"solid",pointerEvents:"none"})),this.addCanvas(),this.updateCursor()}},{key:"updateCursor",value:function(){this.style(this.progressWave,{borderRightWidth:this.params.cursorWidth+"px",borderRightColor:this.params.cursorColor})}},{key:"updateSize",value:function(){for(var e=this,t=Math.round(this.width/this.params.pixelRatio),r=Math.ceil(t/(this.maxCanvasElementWidth+2));this.canvases.length<r;)this.addCanvas();for(;this.canvases.length>r;)this.removeCanvas();this.canvases.forEach((function(t,r){var n=e.maxCanvasWidth+2*Math.ceil(e.params.pixelRatio/2);r==e.canvases.length-1&&(n=e.width-e.maxCanvasWidth*(e.canvases.length-1)),e.updateDimensions(t,n,e.height),e.clearWaveForEntry(t)}))}},{key:"addCanvas",value:function(){var e={},t=this.maxCanvasElementWidth*this.canvases.length;e.wave=this.wrapper.appendChild(this.style(document.createElement("canvas"),{position:"absolute",zIndex:2,left:t+"px",top:0,bottom:0,height:"100%",pointerEvents:"none"})),e.waveCtx=e.wave.getContext("2d"),this.hasProgressCanvas&&(e.progress=this.progressWave.appendChild(this.style(document.createElement("canvas"),{position:"absolute",left:t+"px",top:0,bottom:0,height:"100%"})),e.progressCtx=e.progress.getContext("2d")),this.canvases.push(e)}},{key:"removeCanvas",value:function(){var e=this.canvases.pop();e.wave.parentElement.removeChild(e.wave),this.hasProgressCanvas&&e.progress.parentElement.removeChild(e.progress)}},{key:"updateDimensions",value:function(e,t,r){var n=Math.round(t/this.params.pixelRatio),i=Math.round(this.width/this.params.pixelRatio);e.start=e.waveCtx.canvas.offsetLeft/i||0,e.end=e.start+n/i,e.waveCtx.canvas.width=t,e.waveCtx.canvas.height=r,this.style(e.waveCtx.canvas,{width:n+"px"}),this.style(this.progressWave,{display:"block"}),this.hasProgressCanvas&&(e.progressCtx.canvas.width=t,e.progressCtx.canvas.height=r,this.style(e.progressCtx.canvas,{width:n+"px"}))}},{key:"clearWave",value:function(){var e=this;this.canvases.forEach((function(t){return e.clearWaveForEntry(t)}))}},{key:"clearWaveForEntry",value:function(e){e.waveCtx.clearRect(0,0,e.waveCtx.canvas.width,e.waveCtx.canvas.height),this.hasProgressCanvas&&e.progressCtx.clearRect(0,0,e.progressCtx.canvas.width,e.progressCtx.canvas.height)}},{key:"drawBars",value:function(e,t,r,n){var i=this;return this.prepareDraw(e,t,r,n,(function(e){var t=e.absmax,a=e.hasMinVals,s=(e.height,e.offsetY),o=e.halfH,u=e.peaks;if(void 0!==r){var l,c=a?2:1,f=u.length/c,h=i.params.barWidth*i.params.pixelRatio,d=h+(null===i.params.barGap?Math.max(i.params.pixelRatio,~~(h/2)):Math.max(i.params.pixelRatio,i.params.barGap*i.params.pixelRatio)),p=f/i.width,v=n;for(l=r;l<v;l+=d){var y=u[Math.floor(l*p*c)]||0,m=Math.round(y/t*o);i.fillRect(l+i.halfPixel,o-m+s,h+i.halfPixel,2*m)}}}))}},{key:"drawWave",value:function(e,t,r,n){var i=this;return this.prepareDraw(e,t,r,n,(function(e){var t=e.absmax,a=e.hasMinVals,s=(e.height,e.offsetY),o=e.halfH,u=e.peaks;if(!a){var l,c=[],f=u.length;for(l=0;l<f;l++)c[2*l]=u[l],c[2*l+1]=-u[l];u=c}void 0!==r&&i.drawLine(u,t,o,s,r,n),i.fillRect(0,o+s-i.halfPixel,i.width,i.halfPixel)}))}},{key:"drawLine",value:function(e,t,r,n,i,a){var s=this;this.canvases.forEach((function(o){s.setFillStyles(o),s.drawLineToContext(o,o.waveCtx,e,t,r,n,i,a),s.drawLineToContext(o,o.progressCtx,e,t,r,n,i,a)}))}},{key:"drawLineToContext",value:function(e,t,r,n,i,a,s,o){if(t){var u,l,c=r.length/2,f=Math.round(c*e.start),h=f,d=Math.round(c*e.end)+1,p=e.progress.width/(d-h-1),v=i+a,y=n/i;for(t.beginPath(),t.moveTo((h-f)*p,v),t.lineTo((h-f)*p,v-Math.round((r[2*h]||0)/y)),u=h;u<d;u++){var m=r[2*u]||0,b=Math.round(m/y);t.lineTo((u-f)*p+this.halfPixel,v-b)}for(l=d-1;l>=h;l--){var g=r[2*l+1]||0,k=Math.round(g/y);t.lineTo((l-f)*p+this.halfPixel,v-k)}t.lineTo((h-f)*p,v-Math.round((r[2*h+1]||0)/y)),t.closePath(),t.fill()}}},{key:"fillRect",value:function(e,t,r,n){var i,a=Math.floor(e/this.maxCanvasWidth),s=Math.min(Math.ceil((e+r)/this.maxCanvasWidth)+1,this.canvases.length);for(i=a;i<s;i++){var o=this.canvases[i],u=i*this.maxCanvasWidth,l={x1:Math.max(e,i*this.maxCanvasWidth),y1:t,x2:Math.min(e+r,i*this.maxCanvasWidth+o.waveCtx.canvas.width),y2:t+n};l.x1<l.x2&&(this.setFillStyles(o),this.fillRectToContext(o.waveCtx,l.x1-u,l.y1,l.x2-l.x1,l.y2-l.y1),this.fillRectToContext(o.progressCtx,l.x1-u,l.y1,l.x2-l.x1,l.y2-l.y1))}}},{key:"prepareDraw",value:function(e,t,r,n,i){var s=this;return a.frame((function(){if(e[0]instanceof Array){var o=e;if(s.params.splitChannels)return s.setHeight(o.length*s.params.height*s.params.pixelRatio),o.forEach((function(e,t){return s.prepareDraw(e,t,r,n,i)}));e=o[0]}var u=1/s.params.barHeight;if(s.params.normalize){var l=a.max(e),c=a.min(e);u=-c>l?-c:l}var f=[].some.call(e,(function(e){return e<0})),h=s.params.height*s.params.pixelRatio;return i({absmax:u,hasMinVals:f,height:h,offsetY:h*t||0,halfH:h/2,peaks:e})}))()}},{key:"fillRectToContext",value:function(e,t,r,n,i){e&&e.fillRect(t,r,n,i)}},{key:"setFillStyles",value:function(e){e.waveCtx.fillStyle=this.params.waveColor,this.hasProgressCanvas&&(e.progressCtx.fillStyle=this.params.progressColor)}},{key:"getImage",value:function(e,t){var r=this.canvases.map((function(r){return r.wave.toDataURL(e,t)}));return r.length>1?r:r[0]}},{key:"updateProgress",value:function(e){this.style(this.progressWave,{width:e+"px"})}}])&&u(r.prototype,n),i&&u(r,i),t}(i.default);t.default=h,e.exports=t.default},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n=function(e){if(e&&e.__esModule)return e;var t=i();if(t&&t.has(e))return t.get(e);var r={};if(null!=e){var n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if(Object.prototype.hasOwnProperty.call(e,a)){var s=n?Object.getOwnPropertyDescriptor(e,a):null;s&&(s.get||s.set)?Object.defineProperty(r,a,s):r[a]=e[a]}}r.default=e,t&&t.set(e,r);return r}(r(0));function i(){if("function"!=typeof WeakMap)return null;var e=new WeakMap;return i=function(){return e},e}function a(e){return(a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function s(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}function o(e,t){return!t||"object"!==a(t)&&"function"!=typeof t?function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e):t}function u(e){return(u=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function l(e,t){return(l=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}var c=function(e){function t(e,r){var n;return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),(n=o(this,u(t).call(this))).container=e,n.params=r,n.width=0,n.height=r.height*n.params.pixelRatio,n.lastPos=0,n.wrapper=null,n}var r,i,a;return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&l(e,t)}(t,e),r=t,(i=[{key:"style",value:function(e,t){return n.style(e,t)}},{key:"createWrapper",value:function(){this.wrapper=this.container.appendChild(document.createElement("wave")),this.style(this.wrapper,{display:"block",position:"relative",userSelect:"none",webkitUserSelect:"none",height:this.params.height+"px"}),(this.params.fillParent||this.params.scrollParent)&&this.style(this.wrapper,{width:"100%",overflowX:this.params.hideScrollbar?"hidden":"auto",overflowY:"hidden"}),this.setupWrapperEvents()}},{key:"handleEvent",value:function(e,t){!t&&e.preventDefault();var r,n=e.targetTouches?e.targetTouches[0].clientX:e.clientX,i=this.wrapper.getBoundingClientRect(),a=this.width,s=this.getWidth();return!this.params.fillParent&&a<s?(r=(this.params.rtl?i.right-n:n-i.left)*(this.params.pixelRatio/a)||0)>1&&(r=1):r=((this.params.rtl?i.right-n:n-i.left)+this.wrapper.scrollLeft)/this.wrapper.scrollWidth||0,r}},{key:"setupWrapperEvents",value:function(){var e=this;this.wrapper.addEventListener("click",(function(t){var r=e.wrapper.offsetHeight-e.wrapper.clientHeight;if(0!=r){var n=e.wrapper.getBoundingClientRect();if(t.clientY>=n.bottom-r)return}e.params.interact&&e.fireEvent("click",t,e.handleEvent(t))})),this.wrapper.addEventListener("scroll",(function(t){return e.fireEvent("scroll",t)}))}},{key:"drawPeaks",value:function(e,t,r,n){this.setWidth(t)||this.clearWave(),this.params.barWidth?this.drawBars(e,0,r,n):this.drawWave(e,0,r,n)}},{key:"resetScroll",value:function(){null!==this.wrapper&&(this.wrapper.scrollLeft=0)}},{key:"recenter",value:function(e){var t=this.wrapper.scrollWidth*e;this.recenterOnPosition(t,!0)}},{key:"recenterOnPosition",value:function(e,t){var r=this.wrapper.scrollLeft,n=~~(this.wrapper.clientWidth/2),i=this.wrapper.scrollWidth-this.wrapper.clientWidth,a=e-n,s=a-r;0!=i&&(!t&&-n<=s&&s<n&&(a=r+(s=Math.max(-5,Math.min(5,s)))),(a=Math.max(0,Math.min(i,a)))!=r&&(this.wrapper.scrollLeft=a))}},{key:"getScrollX",value:function(){var e=0;if(this.wrapper){var t=this.params.pixelRatio;if(e=Math.round(this.wrapper.scrollLeft*t),this.params.scrollParent){var r=~~(this.wrapper.scrollWidth*t-this.getWidth());e=Math.min(r,Math.max(0,e))}}return e}},{key:"getWidth",value:function(){return Math.round(this.container.clientWidth*this.params.pixelRatio)}},{key:"setWidth",value:function(e){return this.width!=e&&(this.width=e,this.params.fillParent||this.params.scrollParent?this.style(this.wrapper,{width:""}):this.style(this.wrapper,{width:~~(this.width/this.params.pixelRatio)+"px"}),this.updateSize(),!0)}},{key:"setHeight",value:function(e){return e!=this.height&&(this.height=e,this.style(this.wrapper,{height:~~(this.height/this.params.pixelRatio)+"px"}),this.updateSize(),!0)}},{key:"progress",value:function(e){var t=1/this.params.pixelRatio,r=Math.round(e*this.width)*t;if(r<this.lastPos||r-this.lastPos>=t){if(this.lastPos=r,this.params.scrollParent&&this.params.autoCenter){var n=~~(this.wrapper.scrollWidth*e);this.recenterOnPosition(n)}this.updateProgress(r)}}},{key:"destroy",value:function(){this.unAll(),this.wrapper&&(this.wrapper.parentNode==this.container&&this.container.removeChild(this.wrapper),this.wrapper=null)}},{key:"updateCursor",value:function(){}},{key:"updateSize",value:function(){}},{key:"drawBars",value:function(e,t,r,n){}},{key:"drawWave",value:function(e,t,r,n){}},{key:"clearWave",value:function(){}},{key:"updateProgress",value:function(e){}}])&&s(r.prototype,i),a&&s(r,a),t}(n.Observer);t.default=c,e.exports=t.default},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n,i=(n=r(3))&&n.__esModule?n:{default:n};!function(e){if(e&&e.__esModule)return e;var t=a();if(t&&t.has(e))return t.get(e);var r={};if(null!=e){var n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var i in e)if(Object.prototype.hasOwnProperty.call(e,i)){var s=n?Object.getOwnPropertyDescriptor(e,i):null;s&&(s.get||s.set)?Object.defineProperty(r,i,s):r[i]=e[i]}}r.default=e,t&&t.set(e,r)}(r(0));function a(){if("function"!=typeof WeakMap)return null;var e=new WeakMap;return a=function(){return e},e}function s(e){return(s="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function o(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}function u(e,t){return!t||"object"!==s(t)&&"function"!=typeof t?function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e):t}function l(e,t,r){return(l="undefined"!=typeof Reflect&&Reflect.get?Reflect.get:function(e,t,r){var n=function(e,t){for(;!Object.prototype.hasOwnProperty.call(e,t)&&null!==(e=c(e)););return e}(e,t);if(n){var i=Object.getOwnPropertyDescriptor(n,t);return i.get?i.get.call(r):i.value}})(e,t,r||e)}function c(e){return(c=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function f(e,t){return(f=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}var h=function(e){function t(e){var r;return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),(r=u(this,c(t).call(this,e))).params=e,r.media={currentTime:0,duration:0,paused:!0,playbackRate:1,play:function(){},pause:function(){},volume:0},r.mediaType=e.mediaType.toLowerCase(),r.elementPosition=e.elementPosition,r.peaks=null,r.playbackRate=1,r.volume=1,r.buffer=null,r.onPlayEnd=null,r}var r,n,i;return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&f(e,t)}(t,e),r=t,(n=[{key:"init",value:function(){this.setPlaybackRate(this.params.audioRate),this.createTimer()}},{key:"createTimer",value:function(){var e=this;this.on("play",(function t(){e.isPaused()||(e.fireEvent("audioprocess",e.getCurrentTime()),(window.requestAnimationFrame||window.webkitRequestAnimationFrame)(t))})),this.on("pause",(function(){e.fireEvent("audioprocess",e.getCurrentTime())}))}},{key:"load",value:function(e,t,r,n){var i=document.createElement(this.mediaType);i.controls=this.params.mediaControls,i.autoplay=this.params.autoplay||!1,i.preload=null==n?"auto":n,i.src=e,i.style.width="100%";var a=t.querySelector(this.mediaType);a&&t.removeChild(a),t.appendChild(i),this._load(i,r)}},{key:"loadElt",value:function(e,t){e.controls=this.params.mediaControls,e.autoplay=this.params.autoplay||!1,this._load(e,t)}},{key:"_load",value:function(e,t){var r=this;"function"==typeof e.load&&e.load(),e.addEventListener("error",(function(){r.fireEvent("error","Error loading media element")})),e.addEventListener("canplay",(function(){r.fireEvent("canplay")})),e.addEventListener("ended",(function(){r.fireEvent("finish")})),e.addEventListener("play",(function(){r.fireEvent("play")})),e.addEventListener("pause",(function(){r.fireEvent("pause")})),this.media=e,this.peaks=t,this.onPlayEnd=null,this.buffer=null,this.setPlaybackRate(this.playbackRate),this.setVolume(this.volume)}},{key:"isPaused",value:function(){return!this.media||this.media.paused}},{key:"getDuration",value:function(){if(this.explicitDuration)return this.explicitDuration;var e=(this.buffer||this.media).duration;return e>=1/0&&(e=this.media.seekable.end(0)),e}},{key:"getCurrentTime",value:function(){return this.media&&this.media.currentTime}},{key:"getPlayedPercents",value:function(){return this.getCurrentTime()/this.getDuration()||0}},{key:"getPlaybackRate",value:function(){return this.playbackRate||this.media.playbackRate}},{key:"setPlaybackRate",value:function(e){this.playbackRate=e||1,this.media.playbackRate=this.playbackRate}},{key:"seekTo",value:function(e){null!=e&&(this.media.currentTime=e),this.clearPlayEnd()}},{key:"play",value:function(e,t){this.seekTo(e);var r=this.media.play();return t&&this.setPlayEnd(t),r}},{key:"pause",value:function(){var e;return this.media&&(e=this.media.pause()),this.clearPlayEnd(),e}},{key:"setPlayEnd",value:function(e){var t=this;this._onPlayEnd=function(r){r>=e&&(t.pause(),t.seekTo(e))},this.on("audioprocess",this._onPlayEnd)}},{key:"clearPlayEnd",value:function(){this._onPlayEnd&&(this.un("audioprocess",this._onPlayEnd),this._onPlayEnd=null)}},{key:"getPeaks",value:function(e,r,n){return this.buffer?l(c(t.prototype),"getPeaks",this).call(this,e,r,n):this.peaks||[]}},{key:"setSinkId",value:function(e){return e?this.media.setSinkId?this.media.setSinkId(e):Promise.reject(new Error("setSinkId is not supported in your browser")):Promise.reject(new Error("Invalid deviceId: "+e))}},{key:"getVolume",value:function(){return this.volume||this.media.volume}},{key:"setVolume",value:function(e){this.volume=e,this.media.volume=this.volume}},{key:"destroy",value:function(){this.pause(),this.unAll(),this.params.removeMediaElementOnDestroy&&this.media&&this.media.parentNode&&this.media.parentNode.removeChild(this.media),this.media=null}}])&&o(r.prototype,n),i&&o(r,i),t}(i.default);t.default=h,e.exports=t.default},function(e,t,r){"use strict";function n(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var i=function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.clearPeakCache()}var t,r,i;return t=e,(r=[{key:"clearPeakCache",value:function(){this.peakCacheRanges=[],this.peakCacheLength=-1}},{key:"addRangeToPeakCache",value:function(e,t,r){e!=this.peakCacheLength&&(this.clearPeakCache(),this.peakCacheLength=e);for(var n=[],i=0;i<this.peakCacheRanges.length&&this.peakCacheRanges[i]<t;)i++;for(i%2==0&&n.push(t);i<this.peakCacheRanges.length&&this.peakCacheRanges[i]<=r;)n.push(this.peakCacheRanges[i]),i++;i%2==0&&n.push(r),n=n.filter((function(e,t,r){return 0==t?e!=r[t+1]:t==r.length-1?e!=r[t-1]:e!=r[t-1]&&e!=r[t+1]})),this.peakCacheRanges=this.peakCacheRanges.concat(n),this.peakCacheRanges=this.peakCacheRanges.sort((function(e,t){return e-t})).filter((function(e,t,r){return 0==t?e!=r[t+1]:t==r.length-1?e!=r[t-1]:e!=r[t-1]&&e!=r[t+1]}));var a=[];for(i=0;i<n.length;i+=2)a.push([n[i],n[i+1]]);return a}},{key:"getCacheRanges",value:function(){var e,t=[];for(e=0;e<this.peakCacheRanges.length;e+=2)t.push([this.peakCacheRanges[e],this.peakCacheRanges[e+1]]);return t}}])&&n(t.prototype,r),i&&n(t,i),e}();t.default=i,e.exports=t.default}])}));
+//# sourceMappingURL=wavesurfer.min.js.map
Index: /gs3-extensions/web-audio/trunk/wavesurfer/ws/wavesurfer.min.js.map
===================================================================
--- /gs3-extensions/web-audio/trunk/wavesurfer/ws/wavesurfer.min.js.map	(revision 33546)
+++ /gs3-extensions/web-audio/trunk/wavesurfer/ws/wavesurfer.min.js.map	(revision 33546)
@@ -0,0 +1,1 @@
+{"version":3,"sources":["webpack://WaveSurfer/webpack/universalModuleDefinition","webpack://WaveSurfer/webpack/bootstrap","webpack://WaveSurfer/./src/util/index.js","webpack://WaveSurfer/./src/util/observer.js","webpack://WaveSurfer/./src/util/request-animation-frame.js","webpack://WaveSurfer/./src/webaudio.js","webpack://WaveSurfer/./src/wavesurfer.js","webpack://WaveSurfer/./src/util/ajax.js","webpack://WaveSurfer/./src/util/get-id.js","webpack://WaveSurfer/./src/util/max.js","webpack://WaveSurfer/./src/util/min.js","webpack://WaveSurfer/./src/util/extend.js","webpack://WaveSurfer/./src/util/style.js","webpack://WaveSurfer/./src/util/frame.js","webpack://WaveSurfer/./node_modules/debounce/index.js","webpack://WaveSurfer/./src/util/prevent-click.js","webpack://WaveSurfer/./src/drawer.multicanvas.js","webpack://WaveSurfer/./src/drawer.js","webpack://WaveSurfer/./src/mediaelement.js","webpack://WaveSurfer/./src/peakcache.js"],"names":["root","factory","exports","module","define","amd","window","installedModules","__webpack_require__","moduleId","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","Observer","this","handlers","event","fn","push","callback","un","e","length","splice","handler","on","args","apply","setTimeout","forEach","requestAnimationFrame","webkitRequestAnimationFrame","mozRequestAnimationFrame","oRequestAnimationFrame","msRequestAnimationFrame","element","PLAYING","PAUSED","FINISHED","WebAudio","params","audioContext","offlineAudioContext","stateBehaviors","init","addOnAudioProcess","getPlayedPercents","duration","getDuration","getCurrentTime","startPosition","getPlayedTime","removeOnAudioProcess","fireEvent","ac","getAudioContext","lastPlay","currentTime","scheduledPause","states","analyser","buffer","filters","gainNode","mergedPeaks","offlineAc","peaks","playbackRate","scriptNode","source","splitPeaks","state","explicitDuration","AudioContext","webkitAudioContext","WaveSurferAudioContext","sampleRate","WaveSurferOfflineAudioContext","OfflineAudioContext","webkitOfflineAudioContext","createVolumeNode","createScriptNode","createAnalyserNode","setState","setPlaybackRate","audioRate","setLength","filter","disconnect","connect","setFilters","disconnectFilters","reduce","prev","curr","audioScriptProcessor","createScriptProcessor","scriptBufferSize","createJavaScriptNode","destination","onaudioprocess","time","pause","createAnalyser","createGain","createGainNode","deviceId","audio","Audio","setSinkId","Promise","reject","Error","autoplay","dest","createMediaStreamDestination","srcObject","stream","gain","setValueAtTime","arraybuffer","errback","getOfflineAudioContext","decodeAudioData","data","channels","numberOfChannels","first","last","splitChannels","newBuffer","createBuffer","sampleSize","sampleStep","chan","getChannelData","start","end","min","max","j","isPaused","unAll","disconnectSource","closeAudioContext","close","createSource","createBufferSource","noteGrainOn","stop","noteOff","adjustedTime","seekTo","resume","play","util","WaveSurfer","defaultParams","autoCenter","backend","backgroundColor","barHeight","barGap","container","cursorColor","cursorWidth","dragSelection","fillParent","forceDecode","height","hideScrollbar","interact","loopSelection","maxCanvasWidth","mediaContainer","mediaControls","mediaType","minPxPerSec","normalize","partialRender","pixelRatio","devicePixelRatio","screen","deviceXDPI","logicalXDPI","plugins","progressColor","removeMediaElementOnDestroy","renderer","MultiCanvas","responsive","rtl","scrollParent","skipLength","waveColor","xhr","backends","MediaElement","extend","document","querySelector","style","transform","setBackgroundColor","savedVolume","isMuted","tmpEvents","currentAjax","drawer","peakCache","Drawer","Backend","initialisedPluginList","isDestroyed","isReady","prevWidth","_onResize","debounce","wrapper","clientWidth","registerPlugins","createDrawer","createBackend","createPeakCache","plugin","addPlugin","deferInit","initPlugin","instance","staticProps","keys","pluginStaticProp","Instance","getOwnPropertyNames","destroyPlugin","destroy","addEventListener","drawBuffer","progress","supportsWebAudio","PeakCache","seconds","skip","offset","position","Math","seekAndCenter","recenter","isFinite","console","error","paused","oldScrollParent","newVolume","setVolume","getVolume","rate","getPlaybackRate","setMute","mute","color","background","updateCursor","setHeight","nominalWidth","round","parentWidth","getWidth","width","newRanges","addRangeToPeakCache","getPeaks","drawPeaks","pxPerSec","decodeArrayBuffer","loadDecodedBuffer","load","blob","reader","FileReader","onProgress","loadArrayBuffer","target","result","readAsArrayBuffer","empty","url","preload","preloadIgnoreReasons","indexOf","activeReasons","reason","warn","join","loadBuffer","loadMediaElement","action","once","getArrayBuffer","setPeaks","urlOrElt","elt","loadElt","src","err","ajax","responseType","statusText","percentComplete","lengthComputable","loaded","total","accuracy","noWindow","arr","map","val","json","JSON","stringify","open","encodeURIComponent","format","quality","getImage","abort","cancelAjax","clearTmpEvents","setWidth","destroyAllPlugins","removeEventListener","VERSION","__VERSION__","options","XMLHttpRequest","fired100","method","requestHeaders","header","setRequestHeader","withCredentials","status","response","send","random","toString","substring","values","largest","Infinity","smallest","Number","sources","el","styles","prop","func","wait","immediate","timeout","context","timestamp","later","Date","now","debounced","arguments","callNow","clear","clearTimeout","flush","preventClickHandler","stopPropagation","body","maxCanvasElementWidth","hasProgressCanvas","halfPixel","canvases","progressWave","createWrapper","createElements","appendChild","createElement","zIndex","left","top","bottom","overflow","display","boxSizing","borderRightStyle","pointerEvents","addCanvas","borderRightWidth","borderRightColor","totalWidth","requiredCanvases","ceil","removeCanvas","entry","canvasWidth","updateDimensions","clearWaveForEntry","leftOffset","wave","waveCtx","getContext","progressCtx","lastEntry","pop","parentElement","removeChild","elementWidth","canvas","offsetLeft","clearRect","channelIndex","prepareDraw","absmax","hasMinVals","offsetY","halfH","undefined","peakIndexScale","bar","barWidth","step","scale","peak","floor","h","fillRect","reflectedPeaks","len","drawLine","setFillStyles","drawLineToContext","ctx","canvasStart","canvasEnd","halfOffset","absmaxHalf","beginPath","moveTo","lineTo","closePath","fill","x","y","startCanvas","endCanvas","intersection","x1","y1","x2","y2","fillRectToContext","frame","Array","channelPeaks","some","fillStyle","type","images","toDataURL","lastPos","userSelect","webkitUserSelect","overflowX","overflowY","setupWrapperEvents","noPrevent","preventDefault","clientX","targetTouches","bbox","getBoundingClientRect","right","scrollLeft","scrollWidth","scrollbarHeight","offsetHeight","clientHeight","clientY","handleEvent","clearWave","drawBars","drawWave","percent","recenterOnPosition","half","maxScroll","updateSize","minPxDelta","pos","newPos","updateProgress","parentNode","media","volume","toLowerCase","elementPosition","onPlayEnd","createTimer","onAudioProcess","controls","prevMedia","_load","seekable","clearPlayEnd","promise","setPlayEnd","_onPlayEnd","clearPeakCache","peakCacheRanges","peakCacheLength","uncachedRanges","item","concat","sort","a","b","uncachedRangePairs","peakCacheRangePairs"],"mappings":"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","file":"wavesurfer.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"WaveSurfer\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"WaveSurfer\"] = factory();\n\telse\n\t\troot[\"WaveSurfer\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 4);\n","export { default as ajax } from './ajax';\nexport { default as getId } from './get-id';\nexport { default as max } from './max';\nexport { default as min } from './min';\nexport { default as Observer } from './observer';\nexport { default as extend } from './extend';\nexport { default as style } from './style';\nexport { default as requestAnimationFrame } from './request-animation-frame';\nexport { default as frame } from './frame';\nexport { default as debounce } from 'debounce';\nexport { default as preventClick } from './prevent-click';\n","/**\n * @typedef {Object} ListenerDescriptor\n * @property {string} name The name of the event\n * @property {function} callback The callback\n * @property {function} un The function to call to remove the listener\n */\n\n/**\n * Observer class\n */\nexport default class Observer {\n    /**\n     * Instantiate Observer\n     */\n    constructor() {\n        /**\n         * @private\n         * @todo Initialise the handlers here already and remove the conditional\n         * assignment in `on()`\n         */\n        this.handlers = null;\n    }\n    /**\n     * Attach a handler function for an event.\n     *\n     * @param {string} event Name of the event to listen to\n     * @param {function} fn The callback to trigger when the event is fired\n     * @return {ListenerDescriptor}\n     */\n    on(event, fn) {\n        if (!this.handlers) {\n            this.handlers = {};\n        }\n\n        let handlers = this.handlers[event];\n        if (!handlers) {\n            handlers = this.handlers[event] = [];\n        }\n        handlers.push(fn);\n\n        // Return an event descriptor\n        return {\n            name: event,\n            callback: fn,\n            un: (e, fn) => this.un(e, fn)\n        };\n    }\n\n    /**\n     * Remove an event handler.\n     *\n     * @param {string} event Name of the event the listener that should be\n     * removed listens to\n     * @param {function} fn The callback that should be removed\n     */\n    un(event, fn) {\n        if (!this.handlers) {\n            return;\n        }\n\n        const handlers = this.handlers[event];\n        let i;\n        if (handlers) {\n            if (fn) {\n                for (i = handlers.length - 1; i >= 0; i--) {\n                    if (handlers[i] == fn) {\n                        handlers.splice(i, 1);\n                    }\n                }\n            } else {\n                handlers.length = 0;\n            }\n        }\n    }\n\n    /**\n     * Remove all event handlers.\n     */\n    unAll() {\n        this.handlers = null;\n    }\n\n    /**\n     * Attach a handler to an event. The handler is executed at most once per\n     * event type.\n     *\n     * @param {string} event The event to listen to\n     * @param {function} handler The callback that is only to be called once\n     * @return {ListenerDescriptor}\n     */\n    once(event, handler) {\n        const fn = (...args) => {\n            /*  eslint-disable no-invalid-this */\n            handler.apply(this, args);\n            /*  eslint-enable no-invalid-this */\n            setTimeout(() => {\n                this.un(event, fn);\n            }, 0);\n        };\n        return this.on(event, fn);\n    }\n\n    /**\n     * Manually fire an event\n     *\n     * @param {string} event The event to fire manually\n     * @param {...any} args The arguments with which to call the listeners\n     */\n    fireEvent(event, ...args) {\n        if (!this.handlers) {\n            return;\n        }\n        const handlers = this.handlers[event];\n        handlers &&\n            handlers.forEach(fn => {\n                fn(...args);\n            });\n    }\n}\n","/**\n * Returns the requestAnimationFrame function for the browser, or a shim with\n * setTimeout if none is found\n *\n * @return {function}\n */\nexport default (\n    window.requestAnimationFrame ||\n    window.webkitRequestAnimationFrame ||\n    window.mozRequestAnimationFrame ||\n    window.oRequestAnimationFrame ||\n    window.msRequestAnimationFrame ||\n    ((callback, element) => setTimeout(callback, 1000 / 60))\n).bind(window);\n","import * as util from './util';\n\n// using constants to prevent someone writing the string wrong\nconst PLAYING = 'playing';\nconst PAUSED = 'paused';\nconst FINISHED = 'finished';\n\n/**\n * WebAudio backend\n *\n * @extends {Observer}\n */\nexport default class WebAudio extends util.Observer {\n    /** @private */\n    static scriptBufferSize = 256;\n    /** @private */\n    audioContext = null;\n    /** @private */\n    offlineAudioContext = null;\n    /** @private */\n    stateBehaviors = {\n        [PLAYING]: {\n            init() {\n                this.addOnAudioProcess();\n            },\n            getPlayedPercents() {\n                const duration = this.getDuration();\n                return this.getCurrentTime() / duration || 0;\n            },\n            getCurrentTime() {\n                return this.startPosition + this.getPlayedTime();\n            }\n        },\n        [PAUSED]: {\n            init() {\n                this.removeOnAudioProcess();\n            },\n            getPlayedPercents() {\n                const duration = this.getDuration();\n                return this.getCurrentTime() / duration || 0;\n            },\n            getCurrentTime() {\n                return this.startPosition;\n            }\n        },\n        [FINISHED]: {\n            init() {\n                this.removeOnAudioProcess();\n                this.fireEvent('finish');\n            },\n            getPlayedPercents() {\n                return 1;\n            },\n            getCurrentTime() {\n                return this.getDuration();\n            }\n        }\n    };\n\n    /**\n     * Does the browser support this backend\n     *\n     * @return {boolean}\n     */\n    supportsWebAudio() {\n        return !!(window.AudioContext || window.webkitAudioContext);\n    }\n\n    /**\n     * Get the audio context used by this backend or create one\n     *\n     * @return {AudioContext}\n     */\n    getAudioContext() {\n        if (!window.WaveSurferAudioContext) {\n            window.WaveSurferAudioContext = new (window.AudioContext ||\n                window.webkitAudioContext)();\n        }\n        return window.WaveSurferAudioContext;\n    }\n\n    /**\n     * Get the offline audio context used by this backend or create one\n     *\n     * @param {number} sampleRate\n     * @return {OfflineAudioContext}\n     */\n    getOfflineAudioContext(sampleRate) {\n        if (!window.WaveSurferOfflineAudioContext) {\n            window.WaveSurferOfflineAudioContext = new (window.OfflineAudioContext ||\n                window.webkitOfflineAudioContext)(1, 2, sampleRate);\n        }\n        return window.WaveSurferOfflineAudioContext;\n    }\n\n    /**\n     * Construct the backend\n     *\n     * @param {WavesurferParams} params\n     */\n    constructor(params) {\n        super();\n        /** @private */\n        this.params = params;\n        /** @private */\n        this.ac = params.audioContext || this.getAudioContext();\n        /**@private */\n        this.lastPlay = this.ac.currentTime;\n        /** @private */\n        this.startPosition = 0;\n        /** @private  */\n        this.scheduledPause = null;\n        /** @private */\n        this.states = {\n            [PLAYING]: Object.create(this.stateBehaviors[PLAYING]),\n            [PAUSED]: Object.create(this.stateBehaviors[PAUSED]),\n            [FINISHED]: Object.create(this.stateBehaviors[FINISHED])\n        };\n        /** @private */\n        this.analyser = null;\n        /** @private */\n        this.buffer = null;\n        /** @private */\n        this.filters = [];\n        /** @private */\n        this.gainNode = null;\n        /** @private */\n        this.mergedPeaks = null;\n        /** @private */\n        this.offlineAc = null;\n        /** @private */\n        this.peaks = null;\n        /** @private */\n        this.playbackRate = 1;\n        /** @private */\n        this.analyser = null;\n        /** @private */\n        this.scriptNode = null;\n        /** @private */\n        this.source = null;\n        /** @private */\n        this.splitPeaks = [];\n        /** @private */\n        this.state = null;\n        /** @private */\n        this.explicitDuration = params.duration;\n    }\n\n    /**\n     * Initialise the backend, called in `wavesurfer.createBackend()`\n     */\n    init() {\n        this.createVolumeNode();\n        this.createScriptNode();\n        this.createAnalyserNode();\n\n        this.setState(PAUSED);\n        this.setPlaybackRate(this.params.audioRate);\n        this.setLength(0);\n    }\n\n    /** @private */\n    disconnectFilters() {\n        if (this.filters) {\n            this.filters.forEach(filter => {\n                filter && filter.disconnect();\n            });\n            this.filters = null;\n            // Reconnect direct path\n            this.analyser.connect(this.gainNode);\n        }\n    }\n\n    /** @private */\n    setState(state) {\n        if (this.state !== this.states[state]) {\n            this.state = this.states[state];\n            this.state.init.call(this);\n        }\n    }\n\n    /**\n     * Unpacked `setFilters()`\n     *\n     * @param {...AudioNode} filters\n     */\n    setFilter(...filters) {\n        this.setFilters(filters);\n    }\n\n    /**\n     * Insert custom Web Audio nodes into the graph\n     *\n     * @param {AudioNode[]} filters Packed filters array\n     * @example\n     * const lowpass = wavesurfer.backend.ac.createBiquadFilter();\n     * wavesurfer.backend.setFilter(lowpass);\n     */\n    setFilters(filters) {\n        // Remove existing filters\n        this.disconnectFilters();\n\n        // Insert filters if filter array not empty\n        if (filters && filters.length) {\n            this.filters = filters;\n\n            // Disconnect direct path before inserting filters\n            this.analyser.disconnect();\n\n            // Connect each filter in turn\n            filters\n                .reduce((prev, curr) => {\n                    prev.connect(curr);\n                    return curr;\n                }, this.analyser)\n                .connect(this.gainNode);\n        }\n    }\n\n    /** @private */\n    createScriptNode() {\n        if (this.params.audioScriptProcessor) {\n            this.scriptNode = this.params.audioScriptProcessor;\n        } else {\n            if (this.ac.createScriptProcessor) {\n                this.scriptNode = this.ac.createScriptProcessor(\n                    WebAudio.scriptBufferSize\n                );\n            } else {\n                this.scriptNode = this.ac.createJavaScriptNode(\n                    WebAudio.scriptBufferSize\n                );\n            }\n        }\n        this.scriptNode.connect(this.ac.destination);\n    }\n\n    /** @private */\n    addOnAudioProcess() {\n        this.scriptNode.onaudioprocess = () => {\n            const time = this.getCurrentTime();\n\n            if (time >= this.getDuration()) {\n                this.setState(FINISHED);\n                this.fireEvent('pause');\n            } else if (time >= this.scheduledPause) {\n                this.pause();\n            } else if (this.state === this.states[PLAYING]) {\n                this.fireEvent('audioprocess', time);\n            }\n        };\n    }\n\n    /** @private */\n    removeOnAudioProcess() {\n        this.scriptNode.onaudioprocess = () => {};\n    }\n\n    /** @private */\n    createAnalyserNode() {\n        this.analyser = this.ac.createAnalyser();\n        this.analyser.connect(this.gainNode);\n    }\n\n    /**\n     * Create the gain node needed to control the playback volume.\n     *\n     * @private\n     */\n    createVolumeNode() {\n        // Create gain node using the AudioContext\n        if (this.ac.createGain) {\n            this.gainNode = this.ac.createGain();\n        } else {\n            this.gainNode = this.ac.createGainNode();\n        }\n        // Add the gain node to the graph\n        this.gainNode.connect(this.ac.destination);\n    }\n\n    /**\n     * Set the sink id for the media player\n     *\n     * @param {string} deviceId String value representing audio device id.\n     */\n    setSinkId(deviceId) {\n        if (deviceId) {\n            /**\n             * The webaudio API doesn't currently support setting the device\n             * output. Here we create an HTMLAudioElement, connect the\n             * webaudio stream to that element and setSinkId there.\n             */\n            let audio = new window.Audio();\n            if (!audio.setSinkId) {\n                return Promise.reject(\n                    new Error('setSinkId is not supported in your browser')\n                );\n            }\n            audio.autoplay = true;\n            var dest = this.ac.createMediaStreamDestination();\n            this.gainNode.disconnect();\n            this.gainNode.connect(dest);\n            audio.srcObject = dest.stream;\n\n            return audio.setSinkId(deviceId);\n        } else {\n            return Promise.reject(new Error('Invalid deviceId: ' + deviceId));\n        }\n    }\n\n    /**\n     * Set the audio volume\n     *\n     * @param {number} value A floating point value between 0 and 1.\n     */\n    setVolume(value) {\n        this.gainNode.gain.setValueAtTime(value, this.ac.currentTime);\n    }\n\n    /**\n     * Get the current volume\n     *\n     * @return {number} value A floating point value between 0 and 1.\n     */\n    getVolume() {\n        return this.gainNode.gain.value;\n    }\n\n    /** @private */\n    decodeArrayBuffer(arraybuffer, callback, errback) {\n        if (!this.offlineAc) {\n            this.offlineAc = this.getOfflineAudioContext(\n                this.ac && this.ac.sampleRate ? this.ac.sampleRate : 44100\n            );\n        }\n        this.offlineAc.decodeAudioData(\n            arraybuffer,\n            data => callback(data),\n            errback\n        );\n    }\n\n    /**\n     * Set pre-decoded peaks\n     *\n     * @param {number[]|number[][]} peaks\n     * @param {?number} duration\n     */\n    setPeaks(peaks, duration) {\n        if (duration != null) {\n            this.explicitDuration = duration;\n        }\n        this.peaks = peaks;\n    }\n\n    /**\n     * Set the rendered length (different from the length of the audio).\n     *\n     * @param {number} length\n     */\n    setLength(length) {\n        // No resize, we can preserve the cached peaks.\n        if (this.mergedPeaks && length == 2 * this.mergedPeaks.length - 1 + 2) {\n            return;\n        }\n\n        this.splitPeaks = [];\n        this.mergedPeaks = [];\n        // Set the last element of the sparse array so the peak arrays are\n        // appropriately sized for other calculations.\n        const channels = this.buffer ? this.buffer.numberOfChannels : 1;\n        let c;\n        for (c = 0; c < channels; c++) {\n            this.splitPeaks[c] = [];\n            this.splitPeaks[c][2 * (length - 1)] = 0;\n            this.splitPeaks[c][2 * (length - 1) + 1] = 0;\n        }\n        this.mergedPeaks[2 * (length - 1)] = 0;\n        this.mergedPeaks[2 * (length - 1) + 1] = 0;\n    }\n\n    /**\n     * Compute the max and min value of the waveform when broken into <length> subranges.\n     *\n     * @param {number} length How many subranges to break the waveform into.\n     * @param {number} first First sample in the required range.\n     * @param {number} last Last sample in the required range.\n     * @return {number[]|number[][]} Array of 2*<length> peaks or array of arrays of\n     * peaks consisting of (max, min) values for each subrange.\n     */\n    getPeaks(length, first, last) {\n        if (this.peaks) {\n            return this.peaks;\n        }\n        if (!this.buffer) {\n            return [];\n        }\n\n        first = first || 0;\n        last = last || length - 1;\n\n        this.setLength(length);\n\n        if (!this.buffer) {\n            return this.params.splitChannels\n                ? this.splitPeaks\n                : this.mergedPeaks;\n        }\n\n        /**\n         * The following snippet fixes a buffering data issue on the Safari\n         * browser which returned undefined It creates the missing buffer based\n         * on 1 channel, 4096 samples and the sampleRate from the current\n         * webaudio context 4096 samples seemed to be the best fit for rendering\n         * will review this code once a stable version of Safari TP is out\n         */\n        if (!this.buffer.length) {\n            const newBuffer = this.createBuffer(1, 4096, this.sampleRate);\n            this.buffer = newBuffer.buffer;\n        }\n\n        const sampleSize = this.buffer.length / length;\n        const sampleStep = ~~(sampleSize / 10) || 1;\n        const channels = this.buffer.numberOfChannels;\n        let c;\n\n        for (c = 0; c < channels; c++) {\n            const peaks = this.splitPeaks[c];\n            const chan = this.buffer.getChannelData(c);\n            let i;\n\n            for (i = first; i <= last; i++) {\n                const start = ~~(i * sampleSize);\n                const end = ~~(start + sampleSize);\n                let min = 0;\n                let max = 0;\n                let j;\n\n                for (j = start; j < end; j += sampleStep) {\n                    const value = chan[j];\n\n                    if (value > max) {\n                        max = value;\n                    }\n\n                    if (value < min) {\n                        min = value;\n                    }\n                }\n\n                peaks[2 * i] = max;\n                peaks[2 * i + 1] = min;\n\n                if (c == 0 || max > this.mergedPeaks[2 * i]) {\n                    this.mergedPeaks[2 * i] = max;\n                }\n\n                if (c == 0 || min < this.mergedPeaks[2 * i + 1]) {\n                    this.mergedPeaks[2 * i + 1] = min;\n                }\n            }\n        }\n\n        return this.params.splitChannels ? this.splitPeaks : this.mergedPeaks;\n    }\n\n    /**\n     * Get the position from 0 to 1\n     *\n     * @return {number}\n     */\n    getPlayedPercents() {\n        return this.state.getPlayedPercents.call(this);\n    }\n\n    /** @private */\n    disconnectSource() {\n        if (this.source) {\n            this.source.disconnect();\n        }\n    }\n\n    /**\n     * This is called when wavesurfer is destroyed\n     */\n    destroy() {\n        if (!this.isPaused()) {\n            this.pause();\n        }\n        this.unAll();\n        this.buffer = null;\n        this.disconnectFilters();\n        this.disconnectSource();\n        this.gainNode.disconnect();\n        this.scriptNode.disconnect();\n        this.analyser.disconnect();\n\n        // close the audioContext if closeAudioContext option is set to true\n        if (this.params.closeAudioContext) {\n            // check if browser supports AudioContext.close()\n            if (\n                typeof this.ac.close === 'function' &&\n                this.ac.state != 'closed'\n            ) {\n                this.ac.close();\n            }\n            // clear the reference to the audiocontext\n            this.ac = null;\n            // clear the actual audiocontext, either passed as param or the\n            // global singleton\n            if (!this.params.audioContext) {\n                window.WaveSurferAudioContext = null;\n            } else {\n                this.params.audioContext = null;\n            }\n            // clear the offlineAudioContext\n            window.WaveSurferOfflineAudioContext = null;\n        }\n    }\n\n    /**\n     * Loaded a decoded audio buffer\n     *\n     * @param {Object} buffer\n     */\n    load(buffer) {\n        this.startPosition = 0;\n        this.lastPlay = this.ac.currentTime;\n        this.buffer = buffer;\n        this.createSource();\n    }\n\n    /** @private */\n    createSource() {\n        this.disconnectSource();\n        this.source = this.ac.createBufferSource();\n\n        // adjust for old browsers\n        this.source.start = this.source.start || this.source.noteGrainOn;\n        this.source.stop = this.source.stop || this.source.noteOff;\n\n        this.source.playbackRate.setValueAtTime(\n            this.playbackRate,\n            this.ac.currentTime\n        );\n        this.source.buffer = this.buffer;\n        this.source.connect(this.analyser);\n    }\n\n    /**\n     * Used by `wavesurfer.isPlaying()` and `wavesurfer.playPause()`\n     *\n     * @return {boolean}\n     */\n    isPaused() {\n        return this.state !== this.states[PLAYING];\n    }\n\n    /**\n     * Used by `wavesurfer.getDuration()`\n     *\n     * @return {number}\n     */\n    getDuration() {\n        if (this.explicitDuration) {\n            return this.explicitDuration;\n        }\n        if (!this.buffer) {\n            return 0;\n        }\n        return this.buffer.duration;\n    }\n\n    /**\n     * Used by `wavesurfer.seekTo()`\n     *\n     * @param {number} start Position to start at in seconds\n     * @param {number} end Position to end at in seconds\n     * @return {{start: number, end: number}}\n     */\n    seekTo(start, end) {\n        if (!this.buffer) {\n            return;\n        }\n\n        this.scheduledPause = null;\n\n        if (start == null) {\n            start = this.getCurrentTime();\n            if (start >= this.getDuration()) {\n                start = 0;\n            }\n        }\n        if (end == null) {\n            end = this.getDuration();\n        }\n\n        this.startPosition = start;\n        this.lastPlay = this.ac.currentTime;\n\n        if (this.state === this.states[FINISHED]) {\n            this.setState(PAUSED);\n        }\n\n        return {\n            start: start,\n            end: end\n        };\n    }\n\n    /**\n     * Get the playback position in seconds\n     *\n     * @return {number}\n     */\n    getPlayedTime() {\n        return (this.ac.currentTime - this.lastPlay) * this.playbackRate;\n    }\n\n    /**\n     * Plays the loaded audio region.\n     *\n     * @param {number} start Start offset in seconds, relative to the beginning\n     * of a clip.\n     * @param {number} end When to stop relative to the beginning of a clip.\n     */\n    play(start, end) {\n        if (!this.buffer) {\n            return;\n        }\n\n        // need to re-create source on each playback\n        this.createSource();\n\n        const adjustedTime = this.seekTo(start, end);\n\n        start = adjustedTime.start;\n        end = adjustedTime.end;\n\n        this.scheduledPause = end;\n\n        this.source.start(0, start, end - start);\n\n        if (this.ac.state == 'suspended') {\n            this.ac.resume && this.ac.resume();\n        }\n\n        this.setState(PLAYING);\n\n        this.fireEvent('play');\n    }\n\n    /**\n     * Pauses the loaded audio.\n     */\n    pause() {\n        this.scheduledPause = null;\n\n        this.startPosition += this.getPlayedTime();\n        this.source && this.source.stop(0);\n\n        this.setState(PAUSED);\n\n        this.fireEvent('pause');\n    }\n\n    /**\n     * Returns the current time in seconds relative to the audio-clip's\n     * duration.\n     *\n     * @return {number}\n     */\n    getCurrentTime() {\n        return this.state.getCurrentTime.call(this);\n    }\n\n    /**\n     * Returns the current playback rate. (0=no playback, 1=normal playback)\n     *\n     * @return {number}\n     */\n    getPlaybackRate() {\n        return this.playbackRate;\n    }\n\n    /**\n     * Set the audio source playback rate.\n     *\n     * @param {number} value\n     */\n    setPlaybackRate(value) {\n        value = value || 1;\n        if (this.isPaused()) {\n            this.playbackRate = value;\n        } else {\n            this.pause();\n            this.playbackRate = value;\n            this.play();\n        }\n    }\n}\n","import * as util from './util';\nimport MultiCanvas from './drawer.multicanvas';\nimport WebAudio from './webaudio';\nimport MediaElement from './mediaelement';\nimport PeakCache from './peakcache';\n\n/*\n * This work is licensed under a BSD-3-Clause License.\n */\n\n/** @external {HTMLElement} https://developer.mozilla.org/en/docs/Web/API/HTMLElement */\n/** @external {OfflineAudioContext} https://developer.mozilla.org/en-US/docs/Web/API/OfflineAudioContext */\n/** @external {File} https://developer.mozilla.org/en-US/docs/Web/API/File */\n/** @external {Blob} https://developer.mozilla.org/en-US/docs/Web/API/Blob */\n/** @external {CanvasRenderingContext2D} https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D */\n/** @external {MediaStreamConstraints} https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamConstraints */\n/** @external {AudioNode} https://developer.mozilla.org/de/docs/Web/API/AudioNode */\n\n/**\n * @typedef {Object} WavesurferParams\n * @property {AudioContext} audioContext=null Use your own previously\n * initialized AudioContext or leave blank.\n * @property {number} audioRate=1 Speed at which to play audio. Lower number is\n * slower.\n * @property {ScriptProcessorNode} audioScriptProcessor=null Use your own previously\n * initialized ScriptProcessorNode or leave blank.\n * @property {boolean} autoCenter=true If a scrollbar is present, center the\n * waveform around the progress\n * @property {string} backend='WebAudio' `'WebAudio'|'MediaElement'` In most cases\n * you don't have to set this manually. MediaElement is a fallback for\n * unsupported browsers.\n * @property {string} backgroundColor=null Change background color of the\n * waveform container.\n * @property {number} barHeight=1 The height of the wave\n * @property {number} barGap=null The optional spacing between bars of the wave,\n * if not provided will be calculated in legacy format.\n * @property {boolean} closeAudioContext=false Close and nullify all audio\n * contexts when the destroy method is called.\n * @property {!string|HTMLElement} container CSS selector or HTML element where\n * the waveform should be drawn. This is the only required parameter.\n * @property {string} cursorColor='#333' The fill color of the cursor indicating\n * the playhead position.\n * @property {number} cursorWidth=1 Measured in pixels.\n * @property {number} duration=null Optional audio length so pre-rendered peaks\n * can be display immediately for example.\n * @property {boolean} fillParent=true Whether to fill the entire container or\n * draw only according to `minPxPerSec`.\n * @property {boolean} forceDecode=false Force decoding of audio using web audio\n * when zooming to get a more detailed waveform.\n * @property {number} height=128 The height of the waveform. Measured in\n * pixels.\n * @property {boolean} hideScrollbar=false Whether to hide the horizontal\n * scrollbar when one would normally be shown.\n * @property {boolean} interact=true Whether the mouse interaction will be\n * enabled at initialization. You can switch this parameter at any time later\n * on.\n * @property {boolean} loopSelection=true (Use with regions plugin) Enable\n * looping of selected regions\n * @property {number} maxCanvasWidth=4000 Maximum width of a single canvas in\n * pixels, excluding a small overlap (2 * `pixelRatio`, rounded up to the next\n * even integer). If the waveform is longer than this value, additional canvases\n * will be used to render the waveform, which is useful for very large waveforms\n * that may be too wide for browsers to draw on a single canvas.\n * @property {boolean} mediaControls=false (Use with backend `MediaElement`)\n * this enables the native controls for the media element\n * @property {string} mediaType='audio' (Use with backend `MediaElement`)\n * `'audio'|'video'`\n * @property {number} minPxPerSec=20 Minimum number of pixels per second of\n * audio.\n * @property {boolean} normalize=false If true, normalize by the maximum peak\n * instead of 1.0.\n * @property {boolean} partialRender=false Use the PeakCache to improve\n * rendering speed of large waveforms\n * @property {number} pixelRatio=window.devicePixelRatio The pixel ratio used to\n * calculate display\n * @property {PluginDefinition[]} plugins=[] An array of plugin definitions to\n * register during instantiation, they will be directly initialised unless they\n * are added with the `deferInit` property set to true.\n * @property {string} progressColor='#555' The fill color of the part of the\n * waveform behind the cursor.\n * @property {boolean} removeMediaElementOnDestroy=true Set to false to keep the\n * media element in the DOM when the player is destroyed. This is useful when\n * reusing an existing media element via the `loadMediaElement` method.\n * @property {Object} renderer=MultiCanvas Can be used to inject a custom\n * renderer.\n * @property {boolean|number} responsive=false If set to `true` resize the\n * waveform, when the window is resized. This is debounced with a `100ms`\n * timeout by default. If this parameter is a number it represents that timeout.\n * @property {boolean} rtl=false If set to `true`, renders waveform from\n * right-to-left.\n * @property {boolean} scrollParent=false Whether to scroll the container with a\n * lengthy waveform. Otherwise the waveform is shrunk to the container width\n * (see fillParent).\n * @property {number} skipLength=2 Number of seconds to skip with the\n * skipForward() and skipBackward() methods.\n * @property {boolean} splitChannels=false Render with separate waveforms for\n * the channels of the audio\n * @property {string} waveColor='#999' The fill color of the waveform after the\n * cursor.\n * @property {object} xhr={} XHR options.\n */\n\n/**\n * @typedef {Object} PluginDefinition\n * @desc The Object used to describe a plugin\n * @example wavesurfer.addPlugin(pluginDefinition);\n * @property {string} name The name of the plugin, the plugin instance will be\n * added as a property to the wavesurfer instance under this name\n * @property {?Object} staticProps The properties that should be added to the\n * wavesurfer instance as static properties\n * @property {?boolean} deferInit Don't initialise plugin\n * automatically\n * @property {Object} params={} The plugin parameters, they are the first parameter\n * passed to the plugin class constructor function\n * @property {PluginClass} instance The plugin instance factory, is called with\n * the dependency specified in extends. Returns the plugin class.\n */\n\n/**\n * @interface PluginClass\n *\n * @desc This is the interface which is implemented by all plugin classes. Note\n * that this only turns into an observer after being passed through\n * `wavesurfer.addPlugin`.\n *\n * @extends {Observer}\n */\nclass PluginClass {\n    /**\n     * Plugin definition factory\n     *\n     * This function must be used to create a plugin definition which can be\n     * used by wavesurfer to correctly instantiate the plugin.\n     *\n     * @param  {Object} params={} The plugin params (specific to the plugin)\n     * @return {PluginDefinition} an object representing the plugin\n     */\n    create(params) {}\n    /**\n     * Construct the plugin\n     *\n     * @param {Object} params={} The plugin params (specific to the plugin)\n     * @param {Object} ws The wavesurfer instance\n     */\n    constructor(params, ws) {}\n    /**\n     * Initialise the plugin\n     *\n     * Start doing something. This is called by\n     * `wavesurfer.initPlugin(pluginName)`\n     */\n    init() {}\n    /**\n     * Destroy the plugin instance\n     *\n     * Stop doing something. This is called by\n     * `wavesurfer.destroyPlugin(pluginName)`\n     */\n    destroy() {}\n}\n\n/**\n * WaveSurfer core library class\n *\n * @extends {Observer}\n * @example\n * const params = {\n *   container: '#waveform',\n *   waveColor: 'violet',\n *   progressColor: 'purple'\n * };\n *\n * // initialise like this\n * const wavesurfer = WaveSurfer.create(params);\n *\n * // or like this ...\n * const wavesurfer = new WaveSurfer(params);\n * wavesurfer.init();\n *\n * // load audio file\n * wavesurfer.load('example/media/demo.wav');\n */\nexport default class WaveSurfer extends util.Observer {\n    /** @private */\n    defaultParams = {\n        audioContext: null,\n        audioScriptProcessor: null,\n        audioRate: 1,\n        autoCenter: true,\n        backend: 'WebAudio',\n        backgroundColor: null,\n        barHeight: 1,\n        barGap: null,\n        container: null,\n        cursorColor: '#333',\n        cursorWidth: 1,\n        dragSelection: true,\n        duration: null,\n        fillParent: true,\n        forceDecode: false,\n        height: 128,\n        hideScrollbar: false,\n        interact: true,\n        loopSelection: true,\n        maxCanvasWidth: 4000,\n        mediaContainer: null,\n        mediaControls: false,\n        mediaType: 'audio',\n        minPxPerSec: 20,\n        normalize: false,\n        partialRender: false,\n        pixelRatio:\n            window.devicePixelRatio || screen.deviceXDPI / screen.logicalXDPI,\n        plugins: [],\n        progressColor: '#555',\n        removeMediaElementOnDestroy: true,\n        renderer: MultiCanvas,\n        responsive: false,\n        rtl: false,\n        scrollParent: false,\n        skipLength: 2,\n        splitChannels: false,\n        waveColor: '#999',\n        xhr: {}\n    };\n\n    /** @private */\n    backends = {\n        MediaElement,\n        WebAudio\n    };\n\n    /**\n     * Instantiate this class, call its `init` function and returns it\n     *\n     * @param {WavesurferParams} params\n     * @return {Object} WaveSurfer instance\n     * @example const wavesurfer = WaveSurfer.create(params);\n     */\n    static create(params) {\n        const wavesurfer = new WaveSurfer(params);\n        return wavesurfer.init();\n    }\n\n    /**\n     * The library version number is available as a static property of the\n     * WaveSurfer class\n     *\n     * @type {String}\n     * @example\n     * console.log('Using wavesurfer.js ' + WaveSurfer.VERSION);\n     */\n    static VERSION = __VERSION__;\n\n    /**\n     * Functions in the `util` property are available as a prototype property to\n     * all instances\n     *\n     * @type {Object}\n     * @example\n     * const wavesurfer = WaveSurfer.create(params);\n     * wavesurfer.util.style(myElement, { background: 'blue' });\n     */\n    util = util;\n\n    /**\n     * Functions in the `util` property are available as a static property of the\n     * WaveSurfer class\n     *\n     * @type {Object}\n     * @example\n     * WaveSurfer.util.style(myElement, { background: 'blue' });\n     */\n    static util = util;\n\n    /**\n     * Initialise wavesurfer instance\n     *\n     * @param {WavesurferParams} params Instantiation options for wavesurfer\n     * @example\n     * const wavesurfer = new WaveSurfer(params);\n     * @returns {this}\n     */\n    constructor(params) {\n        super();\n        /**\n         * Extract relevant parameters (or defaults)\n         * @private\n         */\n        this.params = util.extend({}, this.defaultParams, params);\n\n        /** @private */\n        this.container =\n            'string' == typeof params.container\n                ? document.querySelector(this.params.container)\n                : this.params.container;\n\n        if (!this.container) {\n            throw new Error('Container element not found');\n        }\n\n        if (this.params.mediaContainer == null) {\n            /** @private */\n            this.mediaContainer = this.container;\n        } else if (typeof this.params.mediaContainer == 'string') {\n            /** @private */\n            this.mediaContainer = document.querySelector(\n                this.params.mediaContainer\n            );\n        } else {\n            /** @private */\n            this.mediaContainer = this.params.mediaContainer;\n        }\n\n        if (!this.mediaContainer) {\n            throw new Error('Media Container element not found');\n        }\n\n        if (this.params.maxCanvasWidth <= 1) {\n            throw new Error('maxCanvasWidth must be greater than 1');\n        } else if (this.params.maxCanvasWidth % 2 == 1) {\n            throw new Error('maxCanvasWidth must be an even number');\n        }\n\n        if (this.params.rtl === true) {\n            util.style(this.container, { transform: 'rotateY(180deg)' });\n        }\n\n        if (this.params.backgroundColor) {\n            this.setBackgroundColor(this.params.backgroundColor);\n        }\n\n        /**\n         * @private Used to save the current volume when muting so we can\n         * restore once unmuted\n         * @type {number}\n         */\n        this.savedVolume = 0;\n\n        /**\n         * @private The current muted state\n         * @type {boolean}\n         */\n        this.isMuted = false;\n\n        /**\n         * @private Will hold a list of event descriptors that need to be\n         * canceled on subsequent loads of audio\n         * @type {Object[]}\n         */\n        this.tmpEvents = [];\n\n        /**\n         * @private Holds any running audio downloads\n         * @type {Observer}\n         */\n        this.currentAjax = null;\n        /** @private */\n        this.arraybuffer = null;\n        /** @private */\n        this.drawer = null;\n        /** @private */\n        this.backend = null;\n        /** @private */\n        this.peakCache = null;\n\n        // cache constructor objects\n        if (typeof this.params.renderer !== 'function') {\n            throw new Error('Renderer parameter is invalid');\n        }\n        /**\n         * @private The uninitialised Drawer class\n         */\n        this.Drawer = this.params.renderer;\n        /**\n         * @private The uninitialised Backend class\n         */\n        this.Backend = this.backends[this.params.backend];\n\n        /**\n         * @private map of plugin names that are currently initialised\n         */\n        this.initialisedPluginList = {};\n        /** @private */\n        this.isDestroyed = false;\n        /** @private */\n        this.isReady = false;\n\n        // responsive debounced event listener. If this.params.responsive is not\n        // set, this is never called. Use 100ms or this.params.responsive as\n        // timeout for the debounce function.\n        let prevWidth = 0;\n        this._onResize = util.debounce(\n            () => {\n                if (\n                    prevWidth != this.drawer.wrapper.clientWidth &&\n                    !this.params.scrollParent\n                ) {\n                    prevWidth = this.drawer.wrapper.clientWidth;\n                    this.drawer.fireEvent('redraw');\n                }\n            },\n            typeof this.params.responsive === 'number'\n                ? this.params.responsive\n                : 100\n        );\n\n        return this;\n    }\n\n    /**\n     * Initialise the wave\n     *\n     * @example\n     * var wavesurfer = new WaveSurfer(params);\n     * wavesurfer.init();\n     * @return {this}\n     */\n    init() {\n        this.registerPlugins(this.params.plugins);\n        this.createDrawer();\n        this.createBackend();\n        this.createPeakCache();\n        return this;\n    }\n\n    /**\n     * Add and initialise array of plugins (if `plugin.deferInit` is falsey),\n     * this function is called in the init function of wavesurfer\n     *\n     * @param {PluginDefinition[]} plugins An array of plugin definitions\n     * @emits {WaveSurfer#plugins-registered} Called with the array of plugin definitions\n     * @return {this}\n     */\n    registerPlugins(plugins) {\n        // first instantiate all the plugins\n        plugins.forEach(plugin => this.addPlugin(plugin));\n\n        // now run the init functions\n        plugins.forEach(plugin => {\n            // call init function of the plugin if deferInit is falsey\n            // in that case you would manually use initPlugins()\n            if (!plugin.deferInit) {\n                this.initPlugin(plugin.name);\n            }\n        });\n        this.fireEvent('plugins-registered', plugins);\n        return this;\n    }\n\n    /**\n     * Add a plugin object to wavesurfer\n     *\n     * @param {PluginDefinition} plugin A plugin definition\n     * @emits {WaveSurfer#plugin-added} Called with the name of the plugin that was added\n     * @example wavesurfer.addPlugin(WaveSurfer.minimap());\n     * @return {this}\n     */\n    addPlugin(plugin) {\n        if (!plugin.name) {\n            throw new Error('Plugin does not have a name!');\n        }\n        if (!plugin.instance) {\n            throw new Error(\n                `Plugin ${plugin.name} does not have an instance property!`\n            );\n        }\n\n        // staticProps properties are applied to wavesurfer instance\n        if (plugin.staticProps) {\n            Object.keys(plugin.staticProps).forEach(pluginStaticProp => {\n                /**\n                 * Properties defined in a plugin definition's `staticProps` property are added as\n                 * staticProps properties of the WaveSurfer instance\n                 */\n                this[pluginStaticProp] = plugin.staticProps[pluginStaticProp];\n            });\n        }\n\n        const Instance = plugin.instance;\n\n        // turn the plugin instance into an observer\n        const observerPrototypeKeys = Object.getOwnPropertyNames(\n            util.Observer.prototype\n        );\n        observerPrototypeKeys.forEach(key => {\n            Instance.prototype[key] = util.Observer.prototype[key];\n        });\n\n        /**\n         * Instantiated plugin classes are added as a property of the wavesurfer\n         * instance\n         * @type {Object}\n         */\n        this[plugin.name] = new Instance(plugin.params || {}, this);\n        this.fireEvent('plugin-added', plugin.name);\n        return this;\n    }\n\n    /**\n     * Initialise a plugin\n     *\n     * @param {string} name A plugin name\n     * @emits WaveSurfer#plugin-initialised\n     * @example wavesurfer.initPlugin('minimap');\n     * @return {this}\n     */\n    initPlugin(name) {\n        if (!this[name]) {\n            throw new Error(`Plugin ${name} has not been added yet!`);\n        }\n        if (this.initialisedPluginList[name]) {\n            // destroy any already initialised plugins\n            this.destroyPlugin(name);\n        }\n        this[name].init();\n        this.initialisedPluginList[name] = true;\n        this.fireEvent('plugin-initialised', name);\n        return this;\n    }\n\n    /**\n     * Destroy a plugin\n     *\n     * @param {string} name A plugin name\n     * @emits WaveSurfer#plugin-destroyed\n     * @example wavesurfer.destroyPlugin('minimap');\n     * @returns {this}\n     */\n    destroyPlugin(name) {\n        if (!this[name]) {\n            throw new Error(\n                `Plugin ${name} has not been added yet and cannot be destroyed!`\n            );\n        }\n        if (!this.initialisedPluginList[name]) {\n            throw new Error(\n                `Plugin ${name} is not active and cannot be destroyed!`\n            );\n        }\n        if (typeof this[name].destroy !== 'function') {\n            throw new Error(`Plugin ${name} does not have a destroy function!`);\n        }\n\n        this[name].destroy();\n        delete this.initialisedPluginList[name];\n        this.fireEvent('plugin-destroyed', name);\n        return this;\n    }\n\n    /**\n     * Destroy all initialised plugins. Convenience function to use when\n     * wavesurfer is removed\n     *\n     * @private\n     */\n    destroyAllPlugins() {\n        Object.keys(this.initialisedPluginList).forEach(name =>\n            this.destroyPlugin(name)\n        );\n    }\n\n    /**\n     * Create the drawer and draw the waveform\n     *\n     * @private\n     * @emits WaveSurfer#drawer-created\n     */\n    createDrawer() {\n        this.drawer = new this.Drawer(this.container, this.params);\n        this.drawer.init();\n        this.fireEvent('drawer-created', this.drawer);\n\n        if (this.params.responsive !== false) {\n            window.addEventListener('resize', this._onResize, true);\n            window.addEventListener('orientationchange', this._onResize, true);\n        }\n\n        this.drawer.on('redraw', () => {\n            this.drawBuffer();\n            this.drawer.progress(this.backend.getPlayedPercents());\n        });\n\n        // Click-to-seek\n        this.drawer.on('click', (e, progress) => {\n            setTimeout(() => this.seekTo(progress), 0);\n        });\n\n        // Relay the scroll event from the drawer\n        this.drawer.on('scroll', e => {\n            if (this.params.partialRender) {\n                this.drawBuffer();\n            }\n            this.fireEvent('scroll', e);\n        });\n    }\n\n    /**\n     * Create the backend\n     *\n     * @private\n     * @emits WaveSurfer#backend-created\n     */\n    createBackend() {\n        if (this.backend) {\n            this.backend.destroy();\n        }\n\n        // Back compat\n        if (this.params.backend == 'AudioElement') {\n            this.params.backend = 'MediaElement';\n        }\n\n        if (\n            this.params.backend == 'WebAudio' &&\n            !this.Backend.prototype.supportsWebAudio.call(null)\n        ) {\n            this.params.backend = 'MediaElement';\n        }\n\n        this.backend = new this.Backend(this.params);\n        this.backend.init();\n        this.fireEvent('backend-created', this.backend);\n\n        this.backend.on('finish', () => {\n            this.drawer.progress(this.backend.getPlayedPercents());\n            this.fireEvent('finish');\n        });\n        this.backend.on('play', () => this.fireEvent('play'));\n        this.backend.on('pause', () => this.fireEvent('pause'));\n\n        this.backend.on('audioprocess', time => {\n            this.drawer.progress(this.backend.getPlayedPercents());\n            this.fireEvent('audioprocess', time);\n        });\n    }\n\n    /**\n     * Create the peak cache\n     *\n     * @private\n     */\n    createPeakCache() {\n        if (this.params.partialRender) {\n            this.peakCache = new PeakCache();\n        }\n    }\n\n    /**\n     * Get the duration of the audio clip\n     *\n     * @example const duration = wavesurfer.getDuration();\n     * @return {number} Duration in seconds\n     */\n    getDuration() {\n        return this.backend.getDuration();\n    }\n\n    /**\n     * Get the current playback position\n     *\n     * @example const currentTime = wavesurfer.getCurrentTime();\n     * @return {number} Playback position in seconds\n     */\n    getCurrentTime() {\n        return this.backend.getCurrentTime();\n    }\n\n    /**\n     * Set the current play time in seconds.\n     *\n     * @param {number} seconds A positive number in seconds. E.g. 10 means 10\n     * seconds, 60 means 1 minute\n     */\n    setCurrentTime(seconds) {\n        if (seconds >= this.getDuration()) {\n            this.seekTo(1);\n        } else {\n            this.seekTo(seconds / this.getDuration());\n        }\n    }\n\n    /**\n     * Starts playback from the current position. Optional start and end\n     * measured in seconds can be used to set the range of audio to play.\n     *\n     * @param {?number} start Position to start at\n     * @param {?number} end Position to end at\n     * @emits WaveSurfer#interaction\n     * @return {Promise}\n     * @example\n     * // play from second 1 to 5\n     * wavesurfer.play(1, 5);\n     */\n    play(start, end) {\n        this.fireEvent('interaction', () => this.play(start, end));\n        return this.backend.play(start, end);\n    }\n\n    /**\n     * Stops playback\n     *\n     * @example wavesurfer.pause();\n     * @return {Promise}\n     */\n    pause() {\n        if (!this.backend.isPaused()) {\n            return this.backend.pause();\n        }\n    }\n\n    /**\n     * Toggle playback\n     *\n     * @example wavesurfer.playPause();\n     * @return {Promise}\n     */\n    playPause() {\n        return this.backend.isPaused() ? this.play() : this.pause();\n    }\n\n    /**\n     * Get the current playback state\n     *\n     * @example const isPlaying = wavesurfer.isPlaying();\n     * @return {boolean} False if paused, true if playing\n     */\n    isPlaying() {\n        return !this.backend.isPaused();\n    }\n\n    /**\n     * Skip backward\n     *\n     * @param {?number} seconds Amount to skip back, if not specified `skipLength`\n     * is used\n     * @example wavesurfer.skipBackward();\n     */\n    skipBackward(seconds) {\n        this.skip(-seconds || -this.params.skipLength);\n    }\n\n    /**\n     * Skip forward\n     *\n     * @param {?number} seconds Amount to skip back, if not specified `skipLength`\n     * is used\n     * @example wavesurfer.skipForward();\n     */\n    skipForward(seconds) {\n        this.skip(seconds || this.params.skipLength);\n    }\n\n    /**\n     * Skip a number of seconds from the current position (use a negative value\n     * to go backwards).\n     *\n     * @param {number} offset Amount to skip back or forwards\n     * @example\n     * // go back 2 seconds\n     * wavesurfer.skip(-2);\n     */\n    skip(offset) {\n        const duration = this.getDuration() || 1;\n        let position = this.getCurrentTime() || 0;\n        position = Math.max(0, Math.min(duration, position + (offset || 0)));\n        this.seekAndCenter(position / duration);\n    }\n\n    /**\n     * Seeks to a position and centers the view\n     *\n     * @param {number} progress Between 0 (=beginning) and 1 (=end)\n     * @example\n     * // seek and go to the middle of the audio\n     * wavesurfer.seekTo(0.5);\n     */\n    seekAndCenter(progress) {\n        this.seekTo(progress);\n        this.drawer.recenter(progress);\n    }\n\n    /**\n     * Seeks to a position\n     *\n     * @param {number} progress Between 0 (=beginning) and 1 (=end)\n     * @emits WaveSurfer#interaction\n     * @emits WaveSurfer#seek\n     * @example\n     * // seek to the middle of the audio\n     * wavesurfer.seekTo(0.5);\n     */\n    seekTo(progress) {\n        // return an error if progress is not a number between 0 and 1\n        if (\n            typeof progress !== 'number' ||\n            !isFinite(progress) ||\n            progress < 0 ||\n            progress > 1\n        ) {\n            return console.error(\n                'Error calling wavesurfer.seekTo, parameter must be a number between 0 and 1!'\n            );\n        }\n        this.fireEvent('interaction', () => this.seekTo(progress));\n\n        const paused = this.backend.isPaused();\n        // avoid draw wrong position while playing backward seeking\n        if (!paused) {\n            this.backend.pause();\n        }\n        // avoid small scrolls while paused seeking\n        const oldScrollParent = this.params.scrollParent;\n        this.params.scrollParent = false;\n        this.backend.seekTo(progress * this.getDuration());\n        this.drawer.progress(progress);\n\n        if (!paused) {\n            this.backend.play();\n        }\n        this.params.scrollParent = oldScrollParent;\n        this.fireEvent('seek', progress);\n    }\n\n    /**\n     * Stops and goes to the beginning.\n     *\n     * @example wavesurfer.stop();\n     */\n    stop() {\n        this.pause();\n        this.seekTo(0);\n        this.drawer.progress(0);\n    }\n\n    /**\n     * Set the playback volume.\n     *\n     * @param {string} deviceId String value representing underlying output device\n     */\n    setSinkId(deviceId) {\n        return this.backend.setSinkId(deviceId);\n    }\n\n    /**\n     * Set the playback volume.\n     *\n     * @param {number} newVolume A value between 0 and 1, 0 being no\n     * volume and 1 being full volume.\n     * @emits WaveSurfer#volume\n     */\n    setVolume(newVolume) {\n        this.backend.setVolume(newVolume);\n        this.fireEvent('volume', newVolume);\n    }\n\n    /**\n     * Get the playback volume.\n     *\n     * @return {number} A value between 0 and 1, 0 being no\n     * volume and 1 being full volume.\n     */\n    getVolume() {\n        return this.backend.getVolume();\n    }\n\n    /**\n     * Set the playback rate.\n     *\n     * @param {number} rate A positive number. E.g. 0.5 means half the normal\n     * speed, 2 means double speed and so on.\n     * @example wavesurfer.setPlaybackRate(2);\n     */\n    setPlaybackRate(rate) {\n        this.backend.setPlaybackRate(rate);\n    }\n\n    /**\n     * Get the playback rate.\n     *\n     * @return {number}\n     */\n    getPlaybackRate() {\n        return this.backend.getPlaybackRate();\n    }\n\n    /**\n     * Toggle the volume on and off. If not currently muted it will save the\n     * current volume value and turn the volume off. If currently muted then it\n     * will restore the volume to the saved value, and then rest the saved\n     * value.\n     *\n     * @example wavesurfer.toggleMute();\n     */\n    toggleMute() {\n        this.setMute(!this.isMuted);\n    }\n\n    /**\n     * Enable or disable muted audio\n     *\n     * @param {boolean} mute\n     * @emits WaveSurfer#volume\n     * @emits WaveSurfer#mute\n     * @example\n     * // unmute\n     * wavesurfer.setMute(false);\n     */\n    setMute(mute) {\n        // ignore all muting requests if the audio is already in that state\n        if (mute === this.isMuted) {\n            this.fireEvent('mute', this.isMuted);\n            return;\n        }\n\n        if (mute) {\n            // If currently not muted then save current volume,\n            // turn off the volume and update the mute properties\n            this.savedVolume = this.backend.getVolume();\n            this.backend.setVolume(0);\n            this.isMuted = true;\n            this.fireEvent('volume', 0);\n        } else {\n            // If currently muted then restore to the saved volume\n            // and update the mute properties\n            this.backend.setVolume(this.savedVolume);\n            this.isMuted = false;\n            this.fireEvent('volume', this.savedVolume);\n        }\n        this.fireEvent('mute', this.isMuted);\n    }\n\n    /**\n     * Get the current mute status.\n     *\n     * @example const isMuted = wavesurfer.getMute();\n     * @return {boolean}\n     */\n    getMute() {\n        return this.isMuted;\n    }\n\n    /**\n     * Get the current ready status.\n     *\n     * @example const isReady = wavesurfer.isReady();\n     * @return {boolean}\n     */\n    isReady() {\n        return this.isReady;\n    }\n\n    /**\n     * Get the list of current set filters as an array.\n     *\n     * Filters must be set with setFilters method first\n     *\n     * @return {array}\n     */\n    getFilters() {\n        return this.backend.filters || [];\n    }\n\n    /**\n     * Toggles `scrollParent` and redraws\n     *\n     * @example wavesurfer.toggleScroll();\n     */\n    toggleScroll() {\n        this.params.scrollParent = !this.params.scrollParent;\n        this.drawBuffer();\n    }\n\n    /**\n     * Toggle mouse interaction\n     *\n     * @example wavesurfer.toggleInteraction();\n     */\n    toggleInteraction() {\n        this.params.interact = !this.params.interact;\n    }\n\n    /**\n     * Get the fill color of the waveform after the cursor.\n     *\n     * @return {string} A CSS color string.\n     */\n    getWaveColor() {\n        return this.params.waveColor;\n    }\n\n    /**\n     * Set the fill color of the waveform after the cursor.\n     *\n     * @param {string} color A CSS color string.\n     * @example wavesurfer.setWaveColor('#ddd');\n     */\n    setWaveColor(color) {\n        this.params.waveColor = color;\n        this.drawBuffer();\n    }\n\n    /**\n     * Get the fill color of the waveform behind the cursor.\n     *\n     * @return {string} A CSS color string.\n     */\n    getProgressColor() {\n        return this.params.progressColor;\n    }\n\n    /**\n     * Set the fill color of the waveform behind the cursor.\n     *\n     * @param {string} color A CSS color string.\n     * @example wavesurfer.setProgressColor('#400');\n     */\n    setProgressColor(color) {\n        this.params.progressColor = color;\n        this.drawBuffer();\n    }\n\n    /**\n     * Get the background color of the waveform container.\n     *\n     * @return {string} A CSS color string.\n     */\n    getBackgroundColor() {\n        return this.params.backgroundColor;\n    }\n\n    /**\n     * Set the background color of the waveform container.\n     *\n     * @param {string} color A CSS color string.\n     * @example wavesurfer.setBackgroundColor('#FF00FF');\n     */\n    setBackgroundColor(color) {\n        this.params.backgroundColor = color;\n        util.style(this.container, { background: this.params.backgroundColor });\n    }\n\n    /**\n     * Get the fill color of the cursor indicating the playhead\n     * position.\n     *\n     * @return {string} A CSS color string.\n     */\n    getCursorColor() {\n        return this.params.cursorColor;\n    }\n\n    /**\n     * Set the fill color of the cursor indicating the playhead\n     * position.\n     *\n     * @param {string} color A CSS color string.\n     * @example wavesurfer.setCursorColor('#222');\n     */\n    setCursorColor(color) {\n        this.params.cursorColor = color;\n        this.drawer.updateCursor();\n    }\n\n    /**\n     * Get the height of the waveform.\n     *\n     * @return {number} Height measured in pixels.\n     */\n    getHeight() {\n        return this.params.height;\n    }\n\n    /**\n     * Set the height of the waveform.\n     *\n     * @param {number} height Height measured in pixels.\n     * @example wavesurfer.setHeight(200);\n     */\n    setHeight(height) {\n        this.params.height = height;\n        this.drawer.setHeight(height * this.params.pixelRatio);\n        this.drawBuffer();\n    }\n\n    /**\n     * Get the correct peaks for current wave view-port and render wave\n     *\n     * @private\n     * @emits WaveSurfer#redraw\n     */\n    drawBuffer() {\n        const nominalWidth = Math.round(\n            this.getDuration() *\n                this.params.minPxPerSec *\n                this.params.pixelRatio\n        );\n        const parentWidth = this.drawer.getWidth();\n        let width = nominalWidth;\n        // always start at 0 after zooming for scrolling : issue redraw left part\n        let start = 0;\n        let end = Math.max(start + parentWidth, width);\n        // Fill container\n        if (\n            this.params.fillParent &&\n            (!this.params.scrollParent || nominalWidth < parentWidth)\n        ) {\n            width = parentWidth;\n            start = 0;\n            end = width;\n        }\n\n        let peaks;\n        if (this.params.partialRender) {\n            const newRanges = this.peakCache.addRangeToPeakCache(\n                width,\n                start,\n                end\n            );\n            let i;\n            for (i = 0; i < newRanges.length; i++) {\n                peaks = this.backend.getPeaks(\n                    width,\n                    newRanges[i][0],\n                    newRanges[i][1]\n                );\n                this.drawer.drawPeaks(\n                    peaks,\n                    width,\n                    newRanges[i][0],\n                    newRanges[i][1]\n                );\n            }\n        } else {\n            peaks = this.backend.getPeaks(width, start, end);\n            this.drawer.drawPeaks(peaks, width, start, end);\n        }\n        this.fireEvent('redraw', peaks, width);\n    }\n\n    /**\n     * Horizontally zooms the waveform in and out. It also changes the parameter\n     * `minPxPerSec` and enables the `scrollParent` option. Calling the function\n     * with a falsey parameter will reset the zoom state.\n     *\n     * @param {?number} pxPerSec Number of horizontal pixels per second of\n     * audio, if none is set the waveform returns to unzoomed state\n     * @emits WaveSurfer#zoom\n     * @example wavesurfer.zoom(20);\n     */\n    zoom(pxPerSec) {\n        if (!pxPerSec) {\n            this.params.minPxPerSec = this.defaultParams.minPxPerSec;\n            this.params.scrollParent = false;\n        } else {\n            this.params.minPxPerSec = pxPerSec;\n            this.params.scrollParent = true;\n        }\n\n        this.drawBuffer();\n        this.drawer.progress(this.backend.getPlayedPercents());\n\n        this.drawer.recenter(this.getCurrentTime() / this.getDuration());\n        this.fireEvent('zoom', pxPerSec);\n    }\n\n    /**\n     * Decode buffer and load\n     *\n     * @private\n     * @param {ArrayBuffer} arraybuffer\n     */\n    loadArrayBuffer(arraybuffer) {\n        this.decodeArrayBuffer(arraybuffer, data => {\n            if (!this.isDestroyed) {\n                this.loadDecodedBuffer(data);\n            }\n        });\n    }\n\n    /**\n     * Directly load an externally decoded AudioBuffer\n     *\n     * @private\n     * @param {AudioBuffer} buffer\n     * @emits WaveSurfer#ready\n     */\n    loadDecodedBuffer(buffer) {\n        this.backend.load(buffer);\n        this.drawBuffer();\n        this.fireEvent('ready');\n        this.isReady = true;\n    }\n\n    /**\n     * Loads audio data from a Blob or File object\n     *\n     * @param {Blob|File} blob Audio data\n     * @example\n     */\n    loadBlob(blob) {\n        // Create file reader\n        const reader = new FileReader();\n        reader.addEventListener('progress', e => this.onProgress(e));\n        reader.addEventListener('load', e =>\n            this.loadArrayBuffer(e.target.result)\n        );\n        reader.addEventListener('error', () =>\n            this.fireEvent('error', 'Error reading file')\n        );\n        reader.readAsArrayBuffer(blob);\n        this.empty();\n    }\n\n    /**\n     * Loads audio and re-renders the waveform.\n     *\n     * @param {string|HTMLMediaElement} url The url of the audio file or the\n     * audio element with the audio\n     * @param {?number[]|number[][]} peaks Wavesurfer does not have to decode\n     * the audio to render the waveform if this is specified\n     * @param {?string} preload (Use with backend `MediaElement`)\n     * `'none'|'metadata'|'auto'` Preload attribute for the media element\n     * @param {?number} duration The duration of the audio. This is used to\n     * render the peaks data in the correct size for the audio duration (as\n     * befits the current minPxPerSec and zoom value) without having to decode\n     * the audio.\n     * @example\n     * // using ajax or media element to load (depending on backend)\n     * wavesurfer.load('http://example.com/demo.wav');\n     *\n     * // setting preload attribute with media element backend and supplying\n     * peaks wavesurfer.load(\n     *   'http://example.com/demo.wav',\n     *   [0.0218, 0.0183, 0.0165, 0.0198, 0.2137, 0.2888],\n     *   true,\n     * );\n     */\n    load(url, peaks, preload, duration) {\n        this.empty();\n\n        if (preload) {\n            // check whether the preload attribute will be usable and if not log\n            // a warning listing the reasons why not and nullify the variable\n            const preloadIgnoreReasons = {\n                \"Preload is not 'auto', 'none' or 'metadata'\":\n                    ['auto', 'metadata', 'none'].indexOf(preload) === -1,\n                'Peaks are not provided': !peaks,\n                'Backend is not of type MediaElement':\n                    this.params.backend !== 'MediaElement',\n                'Url is not of type string': typeof url !== 'string'\n            };\n            const activeReasons = Object.keys(preloadIgnoreReasons).filter(\n                reason => preloadIgnoreReasons[reason]\n            );\n            if (activeReasons.length) {\n                console.warn(\n                    'Preload parameter of wavesurfer.load will be ignored because:\\n\\t- ' +\n                        activeReasons.join('\\n\\t- ')\n                );\n                // stop invalid values from being used\n                preload = null;\n            }\n        }\n\n        switch (this.params.backend) {\n            case 'WebAudio':\n                return this.loadBuffer(url, peaks, duration);\n            case 'MediaElement':\n                return this.loadMediaElement(url, peaks, preload, duration);\n        }\n    }\n\n    /**\n     * Loads audio using Web Audio buffer backend.\n     *\n     * @private\n     * @param {string} url\n     * @param {?number[]|number[][]} peaks\n     * @param {?number} duration\n     */\n    loadBuffer(url, peaks, duration) {\n        const load = action => {\n            if (action) {\n                this.tmpEvents.push(this.once('ready', action));\n            }\n            return this.getArrayBuffer(url, data => this.loadArrayBuffer(data));\n        };\n\n        if (peaks) {\n            this.backend.setPeaks(peaks, duration);\n            this.drawBuffer();\n            this.tmpEvents.push(this.once('interaction', load));\n        } else {\n            return load();\n        }\n    }\n\n    /**\n     * Either create a media element, or load an existing media element.\n     *\n     * @private\n     * @param {string|HTMLMediaElement} urlOrElt Either a path to a media file, or an\n     * existing HTML5 Audio/Video Element\n     * @param {number[]|number[][]} peaks Array of peaks. Required to bypass web audio\n     * dependency\n     * @param {?boolean} preload Set to true if the preload attribute of the\n     * audio element should be enabled\n     * @param {?number} duration\n     */\n    loadMediaElement(urlOrElt, peaks, preload, duration) {\n        let url = urlOrElt;\n\n        if (typeof urlOrElt === 'string') {\n            this.backend.load(url, this.mediaContainer, peaks, preload);\n        } else {\n            const elt = urlOrElt;\n            this.backend.loadElt(elt, peaks);\n\n            // If peaks are not provided,\n            // url = element.src so we can get peaks with web audio\n            url = elt.src;\n        }\n\n        this.tmpEvents.push(\n            this.backend.once('canplay', () => {\n                this.drawBuffer();\n                this.fireEvent('ready');\n                this.isReady = true;\n            }),\n            this.backend.once('error', err => this.fireEvent('error', err))\n        );\n\n        // If no pre-decoded peaks provided or pre-decoded peaks are\n        // provided with forceDecode flag, attempt to download the\n        // audio file and decode it with Web Audio.\n        if (peaks) {\n            this.backend.setPeaks(peaks, duration);\n        }\n\n        if (\n            (!peaks || this.params.forceDecode) &&\n            this.backend.supportsWebAudio()\n        ) {\n            this.getArrayBuffer(url, arraybuffer => {\n                this.decodeArrayBuffer(arraybuffer, buffer => {\n                    this.backend.buffer = buffer;\n                    this.backend.setPeaks(null);\n                    this.drawBuffer();\n                    this.fireEvent('waveform-ready');\n                });\n            });\n        }\n    }\n\n    /**\n     * Decode an array buffer and pass data to a callback\n     *\n     * @private\n     * @param {Object} arraybuffer\n     * @param {function} callback\n     */\n    decodeArrayBuffer(arraybuffer, callback) {\n        this.arraybuffer = arraybuffer;\n\n        this.backend.decodeArrayBuffer(\n            arraybuffer,\n            data => {\n                // Only use the decoded data if we haven't been destroyed or\n                // another decode started in the meantime\n                if (!this.isDestroyed && this.arraybuffer == arraybuffer) {\n                    callback(data);\n                    this.arraybuffer = null;\n                }\n            },\n            () => this.fireEvent('error', 'Error decoding audiobuffer')\n        );\n    }\n\n    /**\n     * Load an array buffer by ajax and pass to a callback\n     *\n     * @param {string} url\n     * @param {function} callback\n     * @private\n     */\n    getArrayBuffer(url, callback) {\n        const ajax = util.ajax({\n            url: url,\n            responseType: 'arraybuffer',\n            xhr: this.params.xhr\n        });\n\n        this.currentAjax = ajax;\n\n        this.tmpEvents.push(\n            ajax.on('progress', e => {\n                this.onProgress(e);\n            }),\n            ajax.on('success', (data, e) => {\n                callback(data);\n                this.currentAjax = null;\n            }),\n            ajax.on('error', e => {\n                this.fireEvent('error', 'XHR error: ' + e.target.statusText);\n                this.currentAjax = null;\n            })\n        );\n\n        return ajax;\n    }\n\n    /**\n     * Called while the audio file is loading\n     *\n     * @private\n     * @param {Event} e\n     * @emits WaveSurfer#loading\n     */\n    onProgress(e) {\n        let percentComplete;\n        if (e.lengthComputable) {\n            percentComplete = e.loaded / e.total;\n        } else {\n            // Approximate progress with an asymptotic\n            // function, and assume downloads in the 1-3 MB range.\n            percentComplete = e.loaded / (e.loaded + 1000000);\n        }\n        this.fireEvent('loading', Math.round(percentComplete * 100), e.target);\n    }\n\n    /**\n     * Exports PCM data into a JSON array and opens in a new window.\n     *\n     * @param {number} length=1024 The scale in which to export the peaks. (Integer)\n     * @param {number} accuracy=10000 (Integer)\n     * @param {?boolean} noWindow Set to true to disable opening a new\n     * window with the JSON\n     * @param {number} start\n     * @todo Update exportPCM to work with new getPeaks signature\n     * @return {string} JSON of peaks\n     */\n    exportPCM(length, accuracy, noWindow, start) {\n        length = length || 1024;\n        start = start || 0;\n        accuracy = accuracy || 10000;\n        noWindow = noWindow || false;\n        const peaks = this.backend.getPeaks(length, start);\n        const arr = [].map.call(\n            peaks,\n            val => Math.round(val * accuracy) / accuracy\n        );\n        const json = JSON.stringify(arr);\n        if (!noWindow) {\n            window.open(\n                'data:application/json;charset=utf-8,' +\n                    encodeURIComponent(json)\n            );\n        }\n        return json;\n    }\n\n    /**\n     * Save waveform image as data URI.\n     *\n     * The default format is `image/png`. Other supported types are\n     * `image/jpeg` and `image/webp`.\n     *\n     * @param {string} format='image/png'\n     * @param {number} quality=1\n     * @return {string} data URI of image\n     */\n    exportImage(format, quality) {\n        if (!format) {\n            format = 'image/png';\n        }\n        if (!quality) {\n            quality = 1;\n        }\n\n        return this.drawer.getImage(format, quality);\n    }\n\n    /**\n     * Cancel any ajax request currently in progress\n     */\n    cancelAjax() {\n        if (this.currentAjax) {\n            this.currentAjax.xhr.abort();\n            this.currentAjax = null;\n        }\n    }\n\n    /**\n     * @private\n     */\n    clearTmpEvents() {\n        this.tmpEvents.forEach(e => e.un());\n    }\n\n    /**\n     * Display empty waveform.\n     */\n    empty() {\n        if (!this.backend.isPaused()) {\n            this.stop();\n            this.backend.disconnectSource();\n        }\n        this.isReady = false;\n        this.cancelAjax();\n        this.clearTmpEvents();\n        this.drawer.progress(0);\n        this.drawer.setWidth(0);\n        this.drawer.drawPeaks({ length: this.drawer.getWidth() }, 0);\n    }\n\n    /**\n     * Remove events, elements and disconnect WebAudio nodes.\n     *\n     * @emits WaveSurfer#destroy\n     */\n    destroy() {\n        this.destroyAllPlugins();\n        this.fireEvent('destroy');\n        this.cancelAjax();\n        this.clearTmpEvents();\n        this.unAll();\n        if (this.params.responsive !== false) {\n            window.removeEventListener('resize', this._onResize, true);\n            window.removeEventListener(\n                'orientationchange',\n                this._onResize,\n                true\n            );\n        }\n        this.backend.destroy();\n        this.drawer.destroy();\n        this.isDestroyed = true;\n        this.isReady = false;\n        this.arraybuffer = null;\n    }\n}\n","import Observer from './observer';\n\n/**\n * Perform an ajax request\n *\n * @param {Options} options Description\n *\n * @returns {Object} Observer instance\n */\nexport default function ajax(options) {\n    const instance = new Observer();\n    const xhr = new XMLHttpRequest();\n    let fired100 = false;\n    xhr.open(options.method || 'GET', options.url, true);\n    xhr.responseType = options.responseType || 'json';\n\n    if (options.xhr) {\n        if (options.xhr.requestHeaders) {\n            // add custom request headers\n            options.xhr.requestHeaders.forEach(header => {\n                xhr.setRequestHeader(header.key, header.value);\n            });\n        }\n        if (options.xhr.withCredentials) {\n            // use credentials\n            xhr.withCredentials = true;\n        }\n    }\n\n    xhr.addEventListener('progress', e => {\n        instance.fireEvent('progress', e);\n        if (e.lengthComputable && e.loaded == e.total) {\n            fired100 = true;\n        }\n    });\n    xhr.addEventListener('load', e => {\n        if (!fired100) {\n            instance.fireEvent('progress', e);\n        }\n        instance.fireEvent('load', e);\n        if (200 == xhr.status || 206 == xhr.status) {\n            instance.fireEvent('success', xhr.response, e);\n        } else {\n            instance.fireEvent('error', e);\n        }\n    });\n    xhr.addEventListener('error', e => instance.fireEvent('error', e));\n    xhr.send();\n    instance.xhr = xhr;\n    return instance;\n}\n","/**\n * Get a random prefixed ID\n *\n * @returns {String} Random ID\n */\nexport default function getId() {\n    return (\n        'wavesurfer_' +\n        Math.random()\n            .toString(32)\n            .substring(2)\n    );\n}\n","/**\n * Get the largest value\n *\n * @param   {Array} values Array of numbers\n * @returns {Number} Largest number found\n */\nexport default function max(values) {\n    let largest = -Infinity;\n    Object.keys(values).forEach(i => {\n        if (values[i] > largest) {\n            largest = values[i];\n        }\n    });\n    return largest;\n}\n","/**\n * Get the smallest value\n *\n * @param   {Array} values Array of numbers\n * @returns {Number}       Smallest number found\n */\nexport default function min(values) {\n    let smallest = Number(Infinity);\n    Object.keys(values).forEach(i => {\n        if (values[i] < smallest) {\n            smallest = values[i];\n        }\n    });\n    return smallest;\n}\n","/**\n * Extend an object shallowly with others\n *\n * @param {Object} dest The target object\n * @param {Object[]} sources The objects to use for extending\n *\n * @return {Object} Merged object\n */\nexport default function extend(dest, ...sources) {\n    sources.forEach(source => {\n        Object.keys(source).forEach(key => {\n            dest[key] = source[key];\n        });\n    });\n    return dest;\n}\n","/**\n * Apply a map of styles to an element\n *\n * @param {HTMLElement} el The element that the styles will be applied to\n * @param {Object} styles The map of propName: attribute, both are used as-is\n *\n * @return {HTMLElement} el\n */\nexport default function style(el, styles) {\n    Object.keys(styles).forEach(prop => {\n        if (el.style[prop] !== styles[prop]) {\n            el.style[prop] = styles[prop];\n        }\n    });\n    return el;\n}\n","import reqAnimationFrame from './request-animation-frame';\n\n/**\n * Create a function which will be called at the next requestAnimationFrame\n * cycle\n *\n * @param {function} func The function to call\n *\n * @return {func} The function wrapped within a requestAnimationFrame\n */\nexport default function frame(func) {\n    return (...args) => reqAnimationFrame(() => func(...args));\n}\n","/**\n * Returns a function, that, as long as it continues to be invoked, will not\n * be triggered. The function will be called after it stops being called for\n * N milliseconds. If `immediate` is passed, trigger the function on the\n * leading edge, instead of the trailing. The function also has a property 'clear' \n * that is a function which will clear the timer to prevent previously scheduled executions. \n *\n * @source underscore.js\n * @see http://unscriptable.com/2009/03/20/debouncing-javascript-methods/\n * @param {Function} function to wrap\n * @param {Number} timeout in ms (`100`)\n * @param {Boolean} whether to execute at the beginning (`false`)\n * @api public\n */\nfunction debounce(func, wait, immediate){\n  var timeout, args, context, timestamp, result;\n  if (null == wait) wait = 100;\n\n  function later() {\n    var last = Date.now() - timestamp;\n\n    if (last < wait && last >= 0) {\n      timeout = setTimeout(later, wait - last);\n    } else {\n      timeout = null;\n      if (!immediate) {\n        result = func.apply(context, args);\n        context = args = null;\n      }\n    }\n  };\n\n  var debounced = function(){\n    context = this;\n    args = arguments;\n    timestamp = Date.now();\n    var callNow = immediate && !timeout;\n    if (!timeout) timeout = setTimeout(later, wait);\n    if (callNow) {\n      result = func.apply(context, args);\n      context = args = null;\n    }\n\n    return result;\n  };\n\n  debounced.clear = function() {\n    if (timeout) {\n      clearTimeout(timeout);\n      timeout = null;\n    }\n  };\n  \n  debounced.flush = function() {\n    if (timeout) {\n      result = func.apply(context, args);\n      context = args = null;\n      \n      clearTimeout(timeout);\n      timeout = null;\n    }\n  };\n\n  return debounced;\n};\n\n// Adds compatibility for ES modules\ndebounce.debounce = debounce;\n\nmodule.exports = debounce;\n","function preventClickHandler(e) {\n    e.stopPropagation();\n    document.body.removeEventListener('click', preventClickHandler, true);\n}\n\nexport default function preventClick(values) {\n    document.body.addEventListener('click', preventClickHandler, true);\n}\n","import Drawer from './drawer';\nimport * as util from './util';\n\n/**\n * @typedef {Object} CanvasEntry\n * @private\n * @property {HTMLElement} wave The wave node\n * @property {CanvasRenderingContext2D} waveCtx The canvas rendering context\n * @property {?HTMLElement} progress The progress wave node\n * @property {?CanvasRenderingContext2D} progressCtx The progress wave canvas\n * rendering context\n * @property {?number} start Start of the area the canvas should render, between 0 and 1\n * @property {?number} end End of the area the canvas should render, between 0 and 1\n */\n\n/**\n * MultiCanvas renderer for wavesurfer. Is currently the default and sole built\n * in renderer.\n */\nexport default class MultiCanvas extends Drawer {\n    /**\n     * @param {HTMLElement} container The container node of the wavesurfer instance\n     * @param {WavesurferParams} params The wavesurfer initialisation options\n     */\n    constructor(container, params) {\n        super(container, params);\n        /**\n         * @type {number}\n         * @private\n         */\n        this.maxCanvasWidth = params.maxCanvasWidth;\n        /**\n         * @private\n         * @type {number}\n         */\n        this.maxCanvasElementWidth = Math.round(\n            params.maxCanvasWidth / params.pixelRatio\n        );\n\n        /**\n         * Whether or not the progress wave is rendered. If the `waveColor`\n         * and `progressColor` are the same color it is not.\n         * @type {boolean}\n         */\n        this.hasProgressCanvas = params.waveColor != params.progressColor;\n        /**\n         * @private\n         * @type {number}\n         */\n        this.halfPixel = 0.5 / params.pixelRatio;\n        /**\n         * @private\n         * @type {Array}\n         */\n        this.canvases = [];\n        /** @private */\n        this.progressWave = null;\n    }\n\n    /**\n     * Initialize the drawer\n     */\n    init() {\n        this.createWrapper();\n        this.createElements();\n    }\n\n    /**\n     * Create the canvas elements and style them\n     *\n     * @private\n     */\n    createElements() {\n        this.progressWave = this.wrapper.appendChild(\n            this.style(document.createElement('wave'), {\n                position: 'absolute',\n                zIndex: 3,\n                left: 0,\n                top: 0,\n                bottom: 0,\n                overflow: 'hidden',\n                width: '0',\n                display: 'none',\n                boxSizing: 'border-box',\n                borderRightStyle: 'solid',\n                pointerEvents: 'none'\n            })\n        );\n\n        this.addCanvas();\n        this.updateCursor();\n    }\n\n    /**\n     * Update cursor style from params.\n     */\n    updateCursor() {\n        this.style(this.progressWave, {\n            borderRightWidth: this.params.cursorWidth + 'px',\n            borderRightColor: this.params.cursorColor\n        });\n    }\n\n    /**\n     * Adjust to the updated size by adding or removing canvases\n     */\n    updateSize() {\n        const totalWidth = Math.round(this.width / this.params.pixelRatio);\n        // No need more canvas if it's only for 2 peaks (there the same for overlaps !)\n        const requiredCanvases = Math.ceil(\n            totalWidth / (this.maxCanvasElementWidth + 2)\n        );\n\n        while (this.canvases.length < requiredCanvases) {\n            this.addCanvas();\n        }\n\n        while (this.canvases.length > requiredCanvases) {\n            this.removeCanvas();\n        }\n\n        this.canvases.forEach((entry, i) => {\n            // Add some overlap to prevent vertical white stripes, keep the\n            // width even for simplicity\n            let canvasWidth =\n                this.maxCanvasWidth + 2 * Math.ceil(this.params.pixelRatio / 2);\n\n            if (i == this.canvases.length - 1) {\n                canvasWidth =\n                    this.width -\n                    this.maxCanvasWidth * (this.canvases.length - 1);\n            }\n\n            this.updateDimensions(entry, canvasWidth, this.height);\n            this.clearWaveForEntry(entry);\n        });\n    }\n\n    /**\n     * Add a canvas to the canvas list\n     *\n     * @private\n     */\n    addCanvas() {\n        const entry = {};\n        const leftOffset = this.maxCanvasElementWidth * this.canvases.length;\n\n        entry.wave = this.wrapper.appendChild(\n            this.style(document.createElement('canvas'), {\n                position: 'absolute',\n                zIndex: 2,\n                left: leftOffset + 'px',\n                top: 0,\n                bottom: 0,\n                height: '100%',\n                pointerEvents: 'none'\n            })\n        );\n        entry.waveCtx = entry.wave.getContext('2d');\n\n        if (this.hasProgressCanvas) {\n            entry.progress = this.progressWave.appendChild(\n                this.style(document.createElement('canvas'), {\n                    position: 'absolute',\n                    left: leftOffset + 'px',\n                    top: 0,\n                    bottom: 0,\n                    height: '100%'\n                })\n            );\n            entry.progressCtx = entry.progress.getContext('2d');\n        }\n\n        this.canvases.push(entry);\n    }\n\n    /**\n     * Pop one canvas from the list\n     *\n     * @private\n     */\n    removeCanvas() {\n        const lastEntry = this.canvases.pop();\n        lastEntry.wave.parentElement.removeChild(lastEntry.wave);\n        if (this.hasProgressCanvas) {\n            lastEntry.progress.parentElement.removeChild(lastEntry.progress);\n        }\n    }\n\n    /**\n     * Update the dimensions of a canvas element\n     *\n     * @private\n     * @param {CanvasEntry} entry\n     * @param {number} width The new width of the element\n     * @param {number} height The new height of the element\n     */\n    updateDimensions(entry, width, height) {\n        const elementWidth = Math.round(width / this.params.pixelRatio);\n        const totalWidth = Math.round(this.width / this.params.pixelRatio);\n\n        // Where the canvas starts and ends in the waveform, represented as a\n        // decimal between 0 and 1.\n        entry.start = entry.waveCtx.canvas.offsetLeft / totalWidth || 0;\n        entry.end = entry.start + elementWidth / totalWidth;\n\n        entry.waveCtx.canvas.width = width;\n        entry.waveCtx.canvas.height = height;\n        this.style(entry.waveCtx.canvas, { width: elementWidth + 'px' });\n\n        this.style(this.progressWave, { display: 'block' });\n\n        if (this.hasProgressCanvas) {\n            entry.progressCtx.canvas.width = width;\n            entry.progressCtx.canvas.height = height;\n            this.style(entry.progressCtx.canvas, {\n                width: elementWidth + 'px'\n            });\n        }\n    }\n\n    /**\n     * Clear the whole waveform\n     */\n    clearWave() {\n        this.canvases.forEach(entry => this.clearWaveForEntry(entry));\n    }\n\n    /**\n     * Clear one canvas\n     *\n     * @private\n     * @param {CanvasEntry} entry\n     */\n    clearWaveForEntry(entry) {\n        entry.waveCtx.clearRect(\n            0,\n            0,\n            entry.waveCtx.canvas.width,\n            entry.waveCtx.canvas.height\n        );\n        if (this.hasProgressCanvas) {\n            entry.progressCtx.clearRect(\n                0,\n                0,\n                entry.progressCtx.canvas.width,\n                entry.progressCtx.canvas.height\n            );\n        }\n    }\n\n    /**\n     * Draw a waveform with bars\n     *\n     * @param {number[]|number[][]} peaks Can also be an array of arrays for split channel\n     * rendering\n     * @param {number} channelIndex The index of the current channel. Normally\n     * should be 0. Must be an integer.\n     * @param {number} start The x-offset of the beginning of the area that\n     * should be rendered\n     * @param {number} end The x-offset of the end of the area that should be\n     * rendered\n     */\n    drawBars(peaks, channelIndex, start, end) {\n        return this.prepareDraw(\n            peaks,\n            channelIndex,\n            start,\n            end,\n            ({ absmax, hasMinVals, height, offsetY, halfH, peaks }) => {\n                // if drawBars was called within ws.empty we don't pass a start and\n                // don't want anything to happen\n                if (start === undefined) {\n                    return;\n                }\n                // Skip every other value if there are negatives.\n                const peakIndexScale = hasMinVals ? 2 : 1;\n                const length = peaks.length / peakIndexScale;\n                const bar = this.params.barWidth * this.params.pixelRatio;\n                const gap =\n                    this.params.barGap === null\n                        ? Math.max(this.params.pixelRatio, ~~(bar / 2))\n                        : Math.max(\n                              this.params.pixelRatio,\n                              this.params.barGap * this.params.pixelRatio\n                          );\n                const step = bar + gap;\n\n                const scale = length / this.width;\n                const first = start;\n                const last = end;\n                let i;\n\n                for (i = first; i < last; i += step) {\n                    const peak =\n                        peaks[Math.floor(i * scale * peakIndexScale)] || 0;\n                    const h = Math.round((peak / absmax) * halfH);\n                    this.fillRect(\n                        i + this.halfPixel,\n                        halfH - h + offsetY,\n                        bar + this.halfPixel,\n                        h * 2\n                    );\n                }\n            }\n        );\n    }\n\n    /**\n     * Draw a waveform\n     *\n     * @param {number[]|number[][]} peaks Can also be an array of arrays for split channel\n     * rendering\n     * @param {number} channelIndex The index of the current channel. Normally\n     * should be 0\n     * @param {number?} start The x-offset of the beginning of the area that\n     * should be rendered (If this isn't set only a flat line is rendered)\n     * @param {number?} end The x-offset of the end of the area that should be\n     * rendered\n     */\n    drawWave(peaks, channelIndex, start, end) {\n        return this.prepareDraw(\n            peaks,\n            channelIndex,\n            start,\n            end,\n            ({ absmax, hasMinVals, height, offsetY, halfH, peaks }) => {\n                if (!hasMinVals) {\n                    const reflectedPeaks = [];\n                    const len = peaks.length;\n                    let i;\n                    for (i = 0; i < len; i++) {\n                        reflectedPeaks[2 * i] = peaks[i];\n                        reflectedPeaks[2 * i + 1] = -peaks[i];\n                    }\n                    peaks = reflectedPeaks;\n                }\n\n                // if drawWave was called within ws.empty we don't pass a start and\n                // end and simply want a flat line\n                if (start !== undefined) {\n                    this.drawLine(peaks, absmax, halfH, offsetY, start, end);\n                }\n\n                // Always draw a median line\n                this.fillRect(\n                    0,\n                    halfH + offsetY - this.halfPixel,\n                    this.width,\n                    this.halfPixel\n                );\n            }\n        );\n    }\n\n    /**\n     * Tell the canvas entries to render their portion of the waveform\n     *\n     * @private\n     * @param {number[]} peaks Peak data\n     * @param {number} absmax Maximum peak value (absolute)\n     * @param {number} halfH Half the height of the waveform\n     * @param {number} offsetY Offset to the top\n     * @param {number} start The x-offset of the beginning of the area that\n     * should be rendered\n     * @param {number} end The x-offset of the end of the area that\n     * should be rendered\n     */\n    drawLine(peaks, absmax, halfH, offsetY, start, end) {\n        this.canvases.forEach(entry => {\n            this.setFillStyles(entry);\n            this.drawLineToContext(\n                entry,\n                entry.waveCtx,\n                peaks,\n                absmax,\n                halfH,\n                offsetY,\n                start,\n                end\n            );\n            this.drawLineToContext(\n                entry,\n                entry.progressCtx,\n                peaks,\n                absmax,\n                halfH,\n                offsetY,\n                start,\n                end\n            );\n        });\n    }\n\n    /**\n     * Render the actual waveform line on a canvas\n     *\n     * @private\n     * @param {CanvasEntry} entry\n     * @param {Canvas2DContextAttributes} ctx Essentially `entry.[wave|progress]Ctx`\n     * @param {number[]} peaks\n     * @param {number} absmax Maximum peak value (absolute)\n     * @param {number} halfH Half the height of the waveform\n     * @param {number} offsetY Offset to the top\n     * @param {number} start The x-offset of the beginning of the area that\n     * should be rendered\n     * @param {number} end The x-offset of the end of the area that\n     * should be rendered\n     */\n    drawLineToContext(entry, ctx, peaks, absmax, halfH, offsetY, start, end) {\n        if (!ctx) {\n            return;\n        }\n\n        const length = peaks.length / 2;\n\n        const first = Math.round(length * entry.start);\n        // Use one more peak value to make sure we join peaks at ends -- unless,\n        // of course, this is the last canvas.\n        const last = Math.round(length * entry.end) + 1;\n\n        const canvasStart = first;\n        const canvasEnd = last;\n        let i;\n        let j;\n\n        const scale = entry.progress.width / (canvasEnd - canvasStart - 1);\n        // optimization\n        const halfOffset = halfH + offsetY;\n        const absmaxHalf = absmax / halfH;\n\n        ctx.beginPath();\n        ctx.moveTo((canvasStart - first) * scale, halfOffset);\n\n        ctx.lineTo(\n            (canvasStart - first) * scale,\n            halfOffset - Math.round((peaks[2 * canvasStart] || 0) / absmaxHalf)\n        );\n\n        for (i = canvasStart; i < canvasEnd; i++) {\n            const peak = peaks[2 * i] || 0;\n            const h = Math.round(peak / absmaxHalf);\n            ctx.lineTo((i - first) * scale + this.halfPixel, halfOffset - h);\n        }\n\n        // Draw the bottom edge going backwards, to make a single\n        // closed hull to fill.\n        for (j = canvasEnd - 1; j >= canvasStart; j--) {\n            const peak = peaks[2 * j + 1] || 0;\n            const h = Math.round(peak / absmaxHalf);\n            ctx.lineTo((j - first) * scale + this.halfPixel, halfOffset - h);\n        }\n\n        ctx.lineTo(\n            (canvasStart - first) * scale,\n            halfOffset -\n                Math.round((peaks[2 * canvasStart + 1] || 0) / absmaxHalf)\n        );\n\n        ctx.closePath();\n        ctx.fill();\n    }\n\n    /**\n     * Draw a rectangle on the waveform\n     *\n     * @param {number} x\n     * @param {number} y\n     * @param {number} width\n     * @param {number} height\n     */\n    fillRect(x, y, width, height) {\n        const startCanvas = Math.floor(x / this.maxCanvasWidth);\n        const endCanvas = Math.min(\n            Math.ceil((x + width) / this.maxCanvasWidth) + 1,\n            this.canvases.length\n        );\n        let i;\n        for (i = startCanvas; i < endCanvas; i++) {\n            const entry = this.canvases[i];\n            const leftOffset = i * this.maxCanvasWidth;\n\n            const intersection = {\n                x1: Math.max(x, i * this.maxCanvasWidth),\n                y1: y,\n                x2: Math.min(\n                    x + width,\n                    i * this.maxCanvasWidth + entry.waveCtx.canvas.width\n                ),\n                y2: y + height\n            };\n\n            if (intersection.x1 < intersection.x2) {\n                this.setFillStyles(entry);\n\n                this.fillRectToContext(\n                    entry.waveCtx,\n                    intersection.x1 - leftOffset,\n                    intersection.y1,\n                    intersection.x2 - intersection.x1,\n                    intersection.y2 - intersection.y1\n                );\n\n                this.fillRectToContext(\n                    entry.progressCtx,\n                    intersection.x1 - leftOffset,\n                    intersection.y1,\n                    intersection.x2 - intersection.x1,\n                    intersection.y2 - intersection.y1\n                );\n            }\n        }\n    }\n\n    /**\n     * Performs preparation tasks and calculations which are shared by drawBars and drawWave\n     *\n     * @private\n     * @param {number[]|number[][]} peaks Can also be an array of arrays for split channel\n     * rendering\n     * @param {number} channelIndex The index of the current channel. Normally\n     * should be 0\n     * @param {number?} start The x-offset of the beginning of the area that\n     * should be rendered (If this isn't set only a flat line is rendered)\n     * @param {number?} end The x-offset of the end of the area that should be\n     * rendered\n     * @param {function} fn The render function to call\n     */\n    prepareDraw(peaks, channelIndex, start, end, fn) {\n        return util.frame(() => {\n            // Split channels and call this function with the channelIndex set\n            if (peaks[0] instanceof Array) {\n                const channels = peaks;\n                if (this.params.splitChannels) {\n                    this.setHeight(\n                        channels.length *\n                            this.params.height *\n                            this.params.pixelRatio\n                    );\n                    return channels.forEach((channelPeaks, i) =>\n                        this.prepareDraw(channelPeaks, i, start, end, fn)\n                    );\n                }\n                peaks = channels[0];\n            }\n            // calculate maximum modulation value, either from the barHeight\n            // parameter or if normalize=true from the largest value in the peak\n            // set\n            let absmax = 1 / this.params.barHeight;\n            if (this.params.normalize) {\n                const max = util.max(peaks);\n                const min = util.min(peaks);\n                absmax = -min > max ? -min : max;\n            }\n\n            // Bar wave draws the bottom only as a reflection of the top,\n            // so we don't need negative values\n            const hasMinVals = [].some.call(peaks, val => val < 0);\n            const height = this.params.height * this.params.pixelRatio;\n            const offsetY = height * channelIndex || 0;\n            const halfH = height / 2;\n\n            return fn({\n                absmax: absmax,\n                hasMinVals: hasMinVals,\n                height: height,\n                offsetY: offsetY,\n                halfH: halfH,\n                peaks: peaks\n            });\n        })();\n    }\n\n    /**\n     * Draw the actual rectangle on a canvas\n     *\n     * @private\n     * @param {Canvas2DContextAttributes} ctx\n     * @param {number} x\n     * @param {number} y\n     * @param {number} width\n     * @param {number} height\n     */\n    fillRectToContext(ctx, x, y, width, height) {\n        if (!ctx) {\n            return;\n        }\n        ctx.fillRect(x, y, width, height);\n    }\n\n    /**\n     * Set the fill styles for a certain entry (wave and progress)\n     *\n     * @private\n     * @param {CanvasEntry} entry\n     */\n    setFillStyles(entry) {\n        entry.waveCtx.fillStyle = this.params.waveColor;\n        if (this.hasProgressCanvas) {\n            entry.progressCtx.fillStyle = this.params.progressColor;\n        }\n    }\n\n    /**\n     * Return image data of the waveform\n     *\n     * @param {string} type='image/png' An optional value of a format type.\n     * @param {number} quality=0.92 An optional value between 0 and 1.\n     * @return {string|string[]} images A data URL or an array of data URLs\n     */\n    getImage(type, quality) {\n        const images = this.canvases.map(entry =>\n            entry.wave.toDataURL(type, quality)\n        );\n        return images.length > 1 ? images : images[0];\n    }\n\n    /**\n     * Render the new progress\n     *\n     * @param {number} position X-Offset of progress position in pixels\n     */\n    updateProgress(position) {\n        this.style(this.progressWave, { width: position + 'px' });\n    }\n}\n","import * as util from './util';\n\n/**\n * Parent class for renderers\n *\n * @extends {Observer}\n */\nexport default class Drawer extends util.Observer {\n    /**\n     * @param {HTMLElement} container The container node of the wavesurfer instance\n     * @param {WavesurferParams} params The wavesurfer initialisation options\n     */\n    constructor(container, params) {\n        super();\n        /** @private */\n        this.container = container;\n        /**\n         * @type {WavesurferParams}\n         * @private\n         */\n        this.params = params;\n        /**\n         * The width of the renderer\n         * @type {number}\n         */\n        this.width = 0;\n        /**\n         * The height of the renderer\n         * @type {number}\n         */\n        this.height = params.height * this.params.pixelRatio;\n        /** @private */\n        this.lastPos = 0;\n        /**\n         * The `<wave>` element which is added to the container\n         * @type {HTMLElement}\n         */\n        this.wrapper = null;\n    }\n\n    /**\n     * Alias of `util.style`\n     *\n     * @param {HTMLElement} el The element that the styles will be applied to\n     * @param {Object} styles The map of propName: attribute, both are used as-is\n     * @return {HTMLElement} el\n     */\n    style(el, styles) {\n        return util.style(el, styles);\n    }\n\n    /**\n     * Create the wrapper `<wave>` element, style it and set up the events for\n     * interaction\n     */\n    createWrapper() {\n        this.wrapper = this.container.appendChild(\n            document.createElement('wave')\n        );\n\n        this.style(this.wrapper, {\n            display: 'block',\n            position: 'relative',\n            userSelect: 'none',\n            webkitUserSelect: 'none',\n            height: this.params.height + 'px'\n        });\n\n        if (this.params.fillParent || this.params.scrollParent) {\n            this.style(this.wrapper, {\n                width: '100%',\n                overflowX: this.params.hideScrollbar ? 'hidden' : 'auto',\n                overflowY: 'hidden'\n            });\n        }\n\n        this.setupWrapperEvents();\n    }\n\n    /**\n     * Handle click event\n     *\n     * @param {Event} e Click event\n     * @param {?boolean} noPrevent Set to true to not call `e.preventDefault()`\n     * @return {number} Playback position from 0 to 1\n     */\n    handleEvent(e, noPrevent) {\n        !noPrevent && e.preventDefault();\n\n        const clientX = e.targetTouches\n            ? e.targetTouches[0].clientX\n            : e.clientX;\n        const bbox = this.wrapper.getBoundingClientRect();\n\n        const nominalWidth = this.width;\n        const parentWidth = this.getWidth();\n\n        let progress;\n        if (!this.params.fillParent && nominalWidth < parentWidth) {\n            progress =\n                (this.params.rtl ? bbox.right - clientX : clientX - bbox.left) *\n                    (this.params.pixelRatio / nominalWidth) || 0;\n\n            if (progress > 1) {\n                progress = 1;\n            }\n        } else {\n            progress =\n                ((this.params.rtl\n                    ? bbox.right - clientX\n                    : clientX - bbox.left) +\n                    this.wrapper.scrollLeft) /\n                    this.wrapper.scrollWidth || 0;\n        }\n\n        return progress;\n    }\n\n    /**\n     * @private\n     */\n    setupWrapperEvents() {\n        this.wrapper.addEventListener('click', e => {\n            const scrollbarHeight =\n                this.wrapper.offsetHeight - this.wrapper.clientHeight;\n            if (scrollbarHeight != 0) {\n                // scrollbar is visible.  Check if click was on it\n                const bbox = this.wrapper.getBoundingClientRect();\n                if (e.clientY >= bbox.bottom - scrollbarHeight) {\n                    // ignore mousedown as it was on the scrollbar\n                    return;\n                }\n            }\n\n            if (this.params.interact) {\n                this.fireEvent('click', e, this.handleEvent(e));\n            }\n        });\n\n        this.wrapper.addEventListener('scroll', e =>\n            this.fireEvent('scroll', e)\n        );\n    }\n\n    /**\n     * Draw peaks on the canvas\n     *\n     * @param {number[]|number[][]} peaks Can also be an array of arrays for split channel\n     * rendering\n     * @param {number} length The width of the area that should be drawn\n     * @param {number} start The x-offset of the beginning of the area that\n     * should be rendered\n     * @param {number} end The x-offset of the end of the area that should be\n     * rendered\n     */\n    drawPeaks(peaks, length, start, end) {\n        if (!this.setWidth(length)) {\n            this.clearWave();\n        }\n\n        this.params.barWidth\n            ? this.drawBars(peaks, 0, start, end)\n            : this.drawWave(peaks, 0, start, end);\n    }\n\n    /**\n     * Scroll to the beginning\n     */\n    resetScroll() {\n        if (this.wrapper !== null) {\n            this.wrapper.scrollLeft = 0;\n        }\n    }\n\n    /**\n     * Recenter the view-port at a certain percent of the waveform\n     *\n     * @param {number} percent Value from 0 to 1 on the waveform\n     */\n    recenter(percent) {\n        const position = this.wrapper.scrollWidth * percent;\n        this.recenterOnPosition(position, true);\n    }\n\n    /**\n     * Recenter the view-port on a position, either scroll there immediately or\n     * in steps of 5 pixels\n     *\n     * @param {number} position X-offset in pixels\n     * @param {boolean} immediate Set to true to immediately scroll somewhere\n     */\n    recenterOnPosition(position, immediate) {\n        const scrollLeft = this.wrapper.scrollLeft;\n        const half = ~~(this.wrapper.clientWidth / 2);\n        const maxScroll = this.wrapper.scrollWidth - this.wrapper.clientWidth;\n        let target = position - half;\n        let offset = target - scrollLeft;\n\n        if (maxScroll == 0) {\n            // no need to continue if scrollbar is not there\n            return;\n        }\n\n        // if the cursor is currently visible...\n        if (!immediate && -half <= offset && offset < half) {\n            // we'll limit the \"re-center\" rate.\n            const rate = 5;\n            offset = Math.max(-rate, Math.min(rate, offset));\n            target = scrollLeft + offset;\n        }\n\n        // limit target to valid range (0 to maxScroll)\n        target = Math.max(0, Math.min(maxScroll, target));\n        // no use attempting to scroll if we're not moving\n        if (target != scrollLeft) {\n            this.wrapper.scrollLeft = target;\n        }\n    }\n\n    /**\n     * Get the current scroll position in pixels\n     *\n     * @return {number}\n     */\n    getScrollX() {\n        let x = 0;\n        if (this.wrapper) {\n            const pixelRatio = this.params.pixelRatio;\n            x = Math.round(this.wrapper.scrollLeft * pixelRatio);\n\n            // In cases of elastic scroll (safari with mouse wheel) you can\n            // scroll beyond the limits of the container\n            // Calculate and floor the scrollable extent to make sure an out\n            // of bounds value is not returned\n            // Ticket #1312\n            if (this.params.scrollParent) {\n                const maxScroll = ~~(\n                    this.wrapper.scrollWidth * pixelRatio -\n                    this.getWidth()\n                );\n                x = Math.min(maxScroll, Math.max(0, x));\n            }\n        }\n        return x;\n    }\n\n    /**\n     * Get the width of the container\n     *\n     * @return {number}\n     */\n    getWidth() {\n        return Math.round(this.container.clientWidth * this.params.pixelRatio);\n    }\n\n    /**\n     * Set the width of the container\n     *\n     * @param {number} width\n     */\n    setWidth(width) {\n        if (this.width == width) {\n            return false;\n        }\n\n        this.width = width;\n\n        if (this.params.fillParent || this.params.scrollParent) {\n            this.style(this.wrapper, {\n                width: ''\n            });\n        } else {\n            this.style(this.wrapper, {\n                width: ~~(this.width / this.params.pixelRatio) + 'px'\n            });\n        }\n\n        this.updateSize();\n        return true;\n    }\n\n    /**\n     * Set the height of the container\n     *\n     * @param {number} height\n     */\n    setHeight(height) {\n        if (height == this.height) {\n            return false;\n        }\n        this.height = height;\n\n        this.style(this.wrapper, {\n            height: ~~(this.height / this.params.pixelRatio) + 'px'\n        });\n\n        this.updateSize();\n        return true;\n    }\n\n    /**\n     * Called by wavesurfer when progress should be rendered\n     *\n     * @param {number} progress From 0 to 1\n     */\n    progress(progress) {\n        const minPxDelta = 1 / this.params.pixelRatio;\n        const pos = Math.round(progress * this.width) * minPxDelta;\n\n        if (pos < this.lastPos || pos - this.lastPos >= minPxDelta) {\n            this.lastPos = pos;\n\n            if (this.params.scrollParent && this.params.autoCenter) {\n                const newPos = ~~(this.wrapper.scrollWidth * progress);\n                this.recenterOnPosition(newPos);\n            }\n\n            this.updateProgress(pos);\n        }\n    }\n\n    /**\n     * This is called when wavesurfer is destroyed\n     */\n    destroy() {\n        this.unAll();\n        if (this.wrapper) {\n            if (this.wrapper.parentNode == this.container) {\n                this.container.removeChild(this.wrapper);\n            }\n            this.wrapper = null;\n        }\n    }\n\n    /* Renderer-specific methods */\n\n    /**\n     * Called after cursor related params have changed.\n     *\n     * @abstract\n     */\n    updateCursor() {}\n\n    /**\n     * Called when the size of the container changes so the renderer can adjust\n     *\n     * @abstract\n     */\n    updateSize() {}\n\n    /**\n     * Draw a waveform with bars\n     *\n     * @abstract\n     * @param {number[]|number[][]} peaks Can also be an array of arrays for split channel\n     * rendering\n     * @param {number} channelIndex The index of the current channel. Normally\n     * should be 0\n     * @param {number} start The x-offset of the beginning of the area that\n     * should be rendered\n     * @param {number} end The x-offset of the end of the area that should be\n     * rendered\n     */\n    drawBars(peaks, channelIndex, start, end) {}\n\n    /**\n     * Draw a waveform\n     *\n     * @abstract\n     * @param {number[]|number[][]} peaks Can also be an array of arrays for split channel\n     * rendering\n     * @param {number} channelIndex The index of the current channel. Normally\n     * should be 0\n     * @param {number} start The x-offset of the beginning of the area that\n     * should be rendered\n     * @param {number} end The x-offset of the end of the area that should be\n     * rendered\n     */\n    drawWave(peaks, channelIndex, start, end) {}\n\n    /**\n     * Clear the waveform\n     *\n     * @abstract\n     */\n    clearWave() {}\n\n    /**\n     * Render the new progress\n     *\n     * @abstract\n     * @param {number} position X-Offset of progress position in pixels\n     */\n    updateProgress(position) {}\n}\n","import WebAudio from './webaudio';\nimport * as util from './util';\n\n/**\n * MediaElement backend\n */\nexport default class MediaElement extends WebAudio {\n    /**\n     * Construct the backend\n     *\n     * @param {WavesurferParams} params\n     */\n    constructor(params) {\n        super(params);\n        /** @private */\n        this.params = params;\n\n        // Dummy media to catch errors\n        /** @private */\n        this.media = {\n            currentTime: 0,\n            duration: 0,\n            paused: true,\n            playbackRate: 1,\n            play() {},\n            pause() {},\n            volume: 0\n        };\n\n        /** @private */\n        this.mediaType = params.mediaType.toLowerCase();\n        /** @private */\n        this.elementPosition = params.elementPosition;\n        /** @private */\n        this.peaks = null;\n        /** @private */\n        this.playbackRate = 1;\n        /** @private */\n        this.volume = 1;\n        /** @private */\n        this.buffer = null;\n        /** @private */\n        this.onPlayEnd = null;\n    }\n\n    /**\n     * Initialise the backend, called in `wavesurfer.createBackend()`\n     */\n    init() {\n        this.setPlaybackRate(this.params.audioRate);\n        this.createTimer();\n    }\n\n    /**\n     * Create a timer to provide a more precise `audioprocess` event.\n     *\n     * @private\n     */\n    createTimer() {\n        const onAudioProcess = () => {\n            if (this.isPaused()) {\n                return;\n            }\n            this.fireEvent('audioprocess', this.getCurrentTime());\n\n            // Call again in the next frame\n            const requestAnimationFrame =\n                window.requestAnimationFrame ||\n                window.webkitRequestAnimationFrame;\n            requestAnimationFrame(onAudioProcess);\n        };\n\n        this.on('play', onAudioProcess);\n\n        // Update the progress one more time to prevent it from being stuck in\n        // case of lower framerates\n        this.on('pause', () => {\n            this.fireEvent('audioprocess', this.getCurrentTime());\n        });\n    }\n\n    /**\n     * Create media element with url as its source,\n     * and append to container element.\n     *\n     * @param {string} url Path to media file\n     * @param {HTMLElement} container HTML element\n     * @param {number[]|number[][]} peaks Array of peak data\n     * @param {string} preload HTML 5 preload attribute value\n     */\n    load(url, container, peaks, preload) {\n        const media = document.createElement(this.mediaType);\n        media.controls = this.params.mediaControls;\n        media.autoplay = this.params.autoplay || false;\n        media.preload = preload == null ? 'auto' : preload;\n        media.src = url;\n        media.style.width = '100%';\n\n        const prevMedia = container.querySelector(this.mediaType);\n        if (prevMedia) {\n            container.removeChild(prevMedia);\n        }\n        container.appendChild(media);\n\n        this._load(media, peaks);\n    }\n\n    /**\n     * Load existing media element.\n     *\n     * @param {HTMLMediaElement} elt HTML5 Audio or Video element\n     * @param {number[]|number[][]} peaks Array of peak data\n     */\n    loadElt(elt, peaks) {\n        elt.controls = this.params.mediaControls;\n        elt.autoplay = this.params.autoplay || false;\n\n        this._load(elt, peaks);\n    }\n\n    /**\n     * Private method called by both load (from url)\n     * and loadElt (existing media element).\n     *\n     * @param {HTMLMediaElement} media HTML5 Audio or Video element\n     * @param {number[]|number[][]} peaks Array of peak data\n     * @private\n     */\n    _load(media, peaks) {\n        // load must be called manually on iOS, otherwise peaks won't draw\n        // until a user interaction triggers load --> 'ready' event\n        if (typeof media.load == 'function') {\n            // Resets the media element and restarts the media resource. Any\n            // pending events are discarded. How much media data is fetched is\n            // still affected by the preload attribute.\n            media.load();\n        }\n\n        media.addEventListener('error', () => {\n            this.fireEvent('error', 'Error loading media element');\n        });\n\n        media.addEventListener('canplay', () => {\n            this.fireEvent('canplay');\n        });\n\n        media.addEventListener('ended', () => {\n            this.fireEvent('finish');\n        });\n\n        // Listen to and relay play and pause events to enable\n        // playback control from the external media element\n        media.addEventListener('play', () => {\n            this.fireEvent('play');\n        });\n\n        media.addEventListener('pause', () => {\n            this.fireEvent('pause');\n        });\n\n        this.media = media;\n        this.peaks = peaks;\n        this.onPlayEnd = null;\n        this.buffer = null;\n        this.setPlaybackRate(this.playbackRate);\n        this.setVolume(this.volume);\n    }\n\n    /**\n     * Used by `wavesurfer.isPlaying()` and `wavesurfer.playPause()`\n     *\n     * @return {boolean}\n     */\n    isPaused() {\n        return !this.media || this.media.paused;\n    }\n\n    /**\n     * Used by `wavesurfer.getDuration()`\n     *\n     * @return {number}\n     */\n    getDuration() {\n        if (this.explicitDuration) {\n            return this.explicitDuration;\n        }\n        let duration = (this.buffer || this.media).duration;\n        if (duration >= Infinity) {\n            // streaming audio\n            duration = this.media.seekable.end(0);\n        }\n        return duration;\n    }\n\n    /**\n     * Returns the current time in seconds relative to the audio-clip's\n     * duration.\n     *\n     * @return {number}\n     */\n    getCurrentTime() {\n        return this.media && this.media.currentTime;\n    }\n\n    /**\n     * Get the position from 0 to 1\n     *\n     * @return {number}\n     */\n    getPlayedPercents() {\n        return this.getCurrentTime() / this.getDuration() || 0;\n    }\n\n    /**\n     * Get the audio source playback rate.\n     *\n     * @return {number}\n     */\n    getPlaybackRate() {\n        return this.playbackRate || this.media.playbackRate;\n    }\n\n    /**\n     * Set the audio source playback rate.\n     *\n     * @param {number} value\n     */\n    setPlaybackRate(value) {\n        this.playbackRate = value || 1;\n        this.media.playbackRate = this.playbackRate;\n    }\n\n    /**\n     * Used by `wavesurfer.seekTo()`\n     *\n     * @param {number} start Position to start at in seconds\n     */\n    seekTo(start) {\n        if (start != null) {\n            this.media.currentTime = start;\n        }\n        this.clearPlayEnd();\n    }\n\n    /**\n     * Plays the loaded audio region.\n     *\n     * @param {number} start Start offset in seconds, relative to the beginning\n     * of a clip.\n     * @param {number} end When to stop, relative to the beginning of a clip.\n     * @emits MediaElement#play\n     * @return {Promise}\n     */\n    play(start, end) {\n        this.seekTo(start);\n        const promise = this.media.play();\n        end && this.setPlayEnd(end);\n\n        return promise;\n    }\n\n    /**\n     * Pauses the loaded audio.\n     *\n     * @emits MediaElement#pause\n     * @return {Promise}\n     */\n    pause() {\n        let promise;\n\n        if (this.media) {\n            promise = this.media.pause();\n        }\n        this.clearPlayEnd();\n\n        return promise;\n    }\n\n    /** @private */\n    setPlayEnd(end) {\n        this._onPlayEnd = time => {\n            if (time >= end) {\n                this.pause();\n                this.seekTo(end);\n            }\n        };\n        this.on('audioprocess', this._onPlayEnd);\n    }\n\n    /** @private */\n    clearPlayEnd() {\n        if (this._onPlayEnd) {\n            this.un('audioprocess', this._onPlayEnd);\n            this._onPlayEnd = null;\n        }\n    }\n\n    /**\n     * Compute the max and min value of the waveform when broken into\n     * <length> subranges.\n     *\n     * @param {number} length How many subranges to break the waveform into.\n     * @param {number} first First sample in the required range.\n     * @param {number} last Last sample in the required range.\n     * @return {number[]|number[][]} Array of 2*<length> peaks or array of\n     * arrays of peaks consisting of (max, min) values for each subrange.\n     */\n    getPeaks(length, first, last) {\n        if (this.buffer) {\n            return super.getPeaks(length, first, last);\n        }\n        return this.peaks || [];\n    }\n\n    /**\n     * Set the sink id for the media player\n     *\n     * @param {string} deviceId String value representing audio device id.\n     */\n    setSinkId(deviceId) {\n        if (deviceId) {\n            if (!this.media.setSinkId) {\n                return Promise.reject(\n                    new Error('setSinkId is not supported in your browser')\n                );\n            }\n            return this.media.setSinkId(deviceId);\n        }\n\n        return Promise.reject(new Error('Invalid deviceId: ' + deviceId));\n    }\n\n    /**\n     * Get the current volume\n     *\n     * @return {number} value A floating point value between 0 and 1.\n     */\n    getVolume() {\n        return this.volume || this.media.volume;\n    }\n\n    /**\n     * Set the audio volume\n     *\n     * @param {number} value A floating point value between 0 and 1.\n     */\n    setVolume(value) {\n        this.volume = value;\n        this.media.volume = this.volume;\n    }\n\n    /**\n     * This is called when wavesurfer is destroyed\n     *\n     */\n    destroy() {\n        this.pause();\n        this.unAll();\n\n        if (\n            this.params.removeMediaElementOnDestroy &&\n            this.media &&\n            this.media.parentNode\n        ) {\n            this.media.parentNode.removeChild(this.media);\n        }\n\n        this.media = null;\n    }\n}\n","/**\n * Caches the decoded peaks data to improve rendering speed for large audio\n *\n * Is used if the option parameter `partialRender` is set to `true`\n */\nexport default class PeakCache {\n    /**\n     * Instantiate cache\n     */\n    constructor() {\n        this.clearPeakCache();\n    }\n\n    /**\n     * Empty the cache\n     */\n    clearPeakCache() {\n        /**\n         * Flat array with entries that are always in pairs to mark the\n         * beginning and end of each subrange.  This is a convenience so we can\n         * iterate over the pairs for easy set difference operations.\n         * @private\n         */\n        this.peakCacheRanges = [];\n        /**\n         * Length of the entire cachable region, used for resetting the cache\n         * when this changes (zoom events, for instance).\n         * @private\n         */\n        this.peakCacheLength = -1;\n    }\n\n    /**\n     * Add a range of peaks to the cache\n     *\n     * @param {number} length The length of the range\n     * @param {number} start The x offset of the start of the range\n     * @param {number} end The x offset of the end of the range\n     * @return {number[][]}\n     */\n    addRangeToPeakCache(length, start, end) {\n        if (length != this.peakCacheLength) {\n            this.clearPeakCache();\n            this.peakCacheLength = length;\n        }\n\n        // Return ranges that weren't in the cache before the call.\n        let uncachedRanges = [];\n        let i = 0;\n        // Skip ranges before the current start.\n        while (\n            i < this.peakCacheRanges.length &&\n            this.peakCacheRanges[i] < start\n        ) {\n            i++;\n        }\n        // If |i| is even, |start| falls after an existing range.  Otherwise,\n        // |start| falls between an existing range, and the uncached region\n        // starts when we encounter the next node in |peakCacheRanges| or\n        // |end|, whichever comes first.\n        if (i % 2 == 0) {\n            uncachedRanges.push(start);\n        }\n        while (\n            i < this.peakCacheRanges.length &&\n            this.peakCacheRanges[i] <= end\n        ) {\n            uncachedRanges.push(this.peakCacheRanges[i]);\n            i++;\n        }\n        // If |i| is even, |end| is after all existing ranges.\n        if (i % 2 == 0) {\n            uncachedRanges.push(end);\n        }\n\n        // Filter out the 0-length ranges.\n        uncachedRanges = uncachedRanges.filter((item, pos, arr) => {\n            if (pos == 0) {\n                return item != arr[pos + 1];\n            } else if (pos == arr.length - 1) {\n                return item != arr[pos - 1];\n            }\n            return item != arr[pos - 1] && item != arr[pos + 1];\n        });\n\n        // Merge the two ranges together, uncachedRanges will either contain\n        // wholly new points, or duplicates of points in peakCacheRanges.  If\n        // duplicates are detected, remove both and extend the range.\n        this.peakCacheRanges = this.peakCacheRanges.concat(uncachedRanges);\n        this.peakCacheRanges = this.peakCacheRanges\n            .sort((a, b) => a - b)\n            .filter((item, pos, arr) => {\n                if (pos == 0) {\n                    return item != arr[pos + 1];\n                } else if (pos == arr.length - 1) {\n                    return item != arr[pos - 1];\n                }\n                return item != arr[pos - 1] && item != arr[pos + 1];\n            });\n\n        // Push the uncached ranges into an array of arrays for ease of\n        // iteration in the functions that call this.\n        const uncachedRangePairs = [];\n        for (i = 0; i < uncachedRanges.length; i += 2) {\n            uncachedRangePairs.push([uncachedRanges[i], uncachedRanges[i + 1]]);\n        }\n\n        return uncachedRangePairs;\n    }\n\n    /**\n     * For testing\n     *\n     * @return {number[][]}\n     */\n    getCacheRanges() {\n        const peakCacheRangePairs = [];\n        let i;\n        for (i = 0; i < this.peakCacheRanges.length; i += 2) {\n            peakCacheRangePairs.push([\n                this.peakCacheRanges[i],\n                this.peakCacheRanges[i + 1]\n            ]);\n        }\n        return peakCacheRangePairs;\n    }\n}\n"],"sourceRoot":""}
