wavesurfer.js 6.5.1 → 7.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/.eslintrc.json +24 -0
  2. package/.prettierrc +8 -0
  3. package/README.md +26 -117
  4. package/dist/base-plugin.d.ts +10 -0
  5. package/dist/base-plugin.js +13 -0
  6. package/dist/decoder.d.ts +10 -0
  7. package/dist/decoder.js +43 -0
  8. package/dist/event-emitter.d.ts +11 -0
  9. package/dist/event-emitter.js +21 -0
  10. package/dist/fetcher.d.ts +4 -0
  11. package/dist/fetcher.js +17 -0
  12. package/dist/index.d.ts +92 -0
  13. package/dist/index.js +166 -0
  14. package/dist/player-webaudio.d.ts +8 -0
  15. package/dist/player-webaudio.js +31 -0
  16. package/dist/player.d.ts +16 -0
  17. package/dist/player.js +40 -0
  18. package/dist/plugins/regions.d.ts +48 -0
  19. package/dist/plugins/regions.js +183 -0
  20. package/dist/renderer.d.ts +34 -0
  21. package/dist/renderer.js +193 -0
  22. package/dist/timer.d.ts +10 -0
  23. package/dist/timer.js +17 -0
  24. package/examples/audio.ogg +0 -0
  25. package/examples/bars.js +19 -0
  26. package/examples/basic.js +8 -0
  27. package/examples/gradient.js +28 -0
  28. package/examples/regions.js +63 -0
  29. package/examples/video.js +19 -0
  30. package/examples/webaudio.js +14 -0
  31. package/package.json +19 -99
  32. package/src/base-plugin.ts +20 -0
  33. package/src/decoder.ts +41 -0
  34. package/src/event-emitter.ts +35 -0
  35. package/src/fetcher.ts +7 -0
  36. package/src/index.ts +252 -0
  37. package/src/player-webaudio.ts +34 -0
  38. package/src/player.ts +50 -0
  39. package/src/plugins/regions.ts +240 -0
  40. package/src/renderer.ts +250 -0
  41. package/src/timer.ts +27 -0
  42. package/tsconfig.json +105 -0
  43. package/tutorial/index.html +47 -0
  44. package/tutorial/src/editor.js +70 -0
  45. package/tutorial/src/init.js +66 -0
  46. package/tutorial/src/url.js +25 -0
  47. package/tutorial/style.css +211 -0
  48. package/yarn-error.log +1049 -0
  49. package/LICENSE +0 -29
  50. package/dist/plugin/wavesurfer.cursor.js +0 -418
  51. package/dist/plugin/wavesurfer.cursor.js.map +0 -1
  52. package/dist/plugin/wavesurfer.cursor.min.js +0 -7
  53. package/dist/plugin/wavesurfer.cursor.min.js.map +0 -1
  54. package/dist/plugin/wavesurfer.elan.js +0 -381
  55. package/dist/plugin/wavesurfer.elan.js.map +0 -1
  56. package/dist/plugin/wavesurfer.elan.min.js +0 -7
  57. package/dist/plugin/wavesurfer.elan.min.js.map +0 -1
  58. package/dist/plugin/wavesurfer.markers.js +0 -520
  59. package/dist/plugin/wavesurfer.markers.js.map +0 -1
  60. package/dist/plugin/wavesurfer.markers.min.js +0 -7
  61. package/dist/plugin/wavesurfer.markers.min.js.map +0 -1
  62. package/dist/plugin/wavesurfer.mediasession.js +0 -181
  63. package/dist/plugin/wavesurfer.mediasession.js.map +0 -1
  64. package/dist/plugin/wavesurfer.mediasession.min.js +0 -7
  65. package/dist/plugin/wavesurfer.mediasession.min.js.map +0 -1
  66. package/dist/plugin/wavesurfer.microphone.js +0 -466
  67. package/dist/plugin/wavesurfer.microphone.js.map +0 -1
  68. package/dist/plugin/wavesurfer.microphone.min.js +0 -7
  69. package/dist/plugin/wavesurfer.microphone.min.js.map +0 -1
  70. package/dist/plugin/wavesurfer.minimap.js +0 -440
  71. package/dist/plugin/wavesurfer.minimap.js.map +0 -1
  72. package/dist/plugin/wavesurfer.minimap.min.js +0 -7
  73. package/dist/plugin/wavesurfer.minimap.min.js.map +0 -1
  74. package/dist/plugin/wavesurfer.playhead.js +0 -300
  75. package/dist/plugin/wavesurfer.playhead.js.map +0 -1
  76. package/dist/plugin/wavesurfer.playhead.min.js +0 -7
  77. package/dist/plugin/wavesurfer.playhead.min.js.map +0 -1
  78. package/dist/plugin/wavesurfer.regions.js +0 -1335
  79. package/dist/plugin/wavesurfer.regions.js.map +0 -1
  80. package/dist/plugin/wavesurfer.regions.min.js +0 -7
  81. package/dist/plugin/wavesurfer.regions.min.js.map +0 -1
  82. package/dist/plugin/wavesurfer.spectrogram.js +0 -736
  83. package/dist/plugin/wavesurfer.spectrogram.js.map +0 -1
  84. package/dist/plugin/wavesurfer.spectrogram.min.js +0 -7
  85. package/dist/plugin/wavesurfer.spectrogram.min.js.map +0 -1
  86. package/dist/plugin/wavesurfer.timeline.js +0 -649
  87. package/dist/plugin/wavesurfer.timeline.js.map +0 -1
  88. package/dist/plugin/wavesurfer.timeline.min.js +0 -7
  89. package/dist/plugin/wavesurfer.timeline.min.js.map +0 -1
  90. package/dist/wavesurfer-html-init.js +0 -381
  91. package/dist/wavesurfer-html-init.js.map +0 -1
  92. package/dist/wavesurfer-html-init.min.js +0 -7
  93. package/dist/wavesurfer-html-init.min.js.map +0 -1
  94. package/dist/wavesurfer.js +0 -6145
  95. package/dist/wavesurfer.js.map +0 -1
  96. package/dist/wavesurfer.min.js +0 -7
  97. package/dist/wavesurfer.min.js.map +0 -1
  98. package/src/drawer.canvasentry.js +0 -427
  99. package/src/drawer.js +0 -413
  100. package/src/drawer.multicanvas.js +0 -617
  101. package/src/html-init.js +0 -241
  102. package/src/mediaelement-webaudio.js +0 -77
  103. package/src/mediaelement.js +0 -443
  104. package/src/peakcache.js +0 -127
  105. package/src/plugin/cursor/index.js +0 -350
  106. package/src/plugin/elan/index.js +0 -307
  107. package/src/plugin/markers/index.js +0 -436
  108. package/src/plugin/mediasession/index.js +0 -94
  109. package/src/plugin/microphone/index.js +0 -415
  110. package/src/plugin/minimap/index.js +0 -403
  111. package/src/plugin/playhead/index.js +0 -226
  112. package/src/plugin/regions/index.js +0 -478
  113. package/src/plugin/regions/region.js +0 -875
  114. package/src/plugin/spectrogram/fft.js +0 -222
  115. package/src/plugin/spectrogram/index.js +0 -522
  116. package/src/plugin/timeline/index.js +0 -600
  117. package/src/util/absMax.js +0 -16
  118. package/src/util/clamp.js +0 -11
  119. package/src/util/fetch.js +0 -222
  120. package/src/util/frame.js +0 -13
  121. package/src/util/get-id.js +0 -22
  122. package/src/util/index.js +0 -14
  123. package/src/util/max.js +0 -16
  124. package/src/util/min.js +0 -16
  125. package/src/util/observer.js +0 -144
  126. package/src/util/orientation.js +0 -98
  127. package/src/util/prevent-click.js +0 -19
  128. package/src/util/request-animation-frame.js +0 -15
  129. package/src/util/silence-mode.js +0 -42
  130. package/src/util/style.js +0 -16
  131. package/src/wavesurfer.js +0 -1797
  132. package/src/webaudio.js +0 -779
@@ -1,736 +0,0 @@
1
- /*!
2
- * wavesurfer.js spectrogram plugin 6.5.1 (2023-03-12)
3
- * https://wavesurfer-js.org
4
- * @license BSD-3-Clause
5
- */
6
- (function webpackUniversalModuleDefinition(root, factory) {
7
- if(typeof exports === 'object' && typeof module === 'object')
8
- module.exports = factory();
9
- else if(typeof define === 'function' && define.amd)
10
- define("WaveSurfer", [], factory);
11
- else if(typeof exports === 'object')
12
- exports["WaveSurfer"] = factory();
13
- else
14
- root["WaveSurfer"] = root["WaveSurfer"] || {}, root["WaveSurfer"]["spectrogram"] = factory();
15
- })(self, () => {
16
- return /******/ (() => { // webpackBootstrap
17
- /******/ "use strict";
18
- /******/ var __webpack_modules__ = ({
19
-
20
- /***/ "./src/plugin/spectrogram/fft.js":
21
- /*!***************************************!*\
22
- !*** ./src/plugin/spectrogram/fft.js ***!
23
- \***************************************/
24
- /***/ ((module, exports) => {
25
-
26
-
27
-
28
- Object.defineProperty(exports, "__esModule", ({
29
- value: true
30
- }));
31
- exports["default"] = FFT;
32
- /* eslint-disable complexity, no-redeclare, no-var, one-var */
33
-
34
- /**
35
- * Calculate FFT - Based on https://github.com/corbanbrook/dsp.js
36
- *
37
- * @param {Number} bufferSize Buffer size
38
- * @param {Number} sampleRate Sample rate
39
- * @param {Function} windowFunc Window function
40
- * @param {Number} alpha Alpha channel
41
- */
42
- function FFT(bufferSize, sampleRate, windowFunc, alpha) {
43
- this.bufferSize = bufferSize;
44
- this.sampleRate = sampleRate;
45
- this.bandwidth = 2 / bufferSize * (sampleRate / 2);
46
- this.sinTable = new Float32Array(bufferSize);
47
- this.cosTable = new Float32Array(bufferSize);
48
- this.windowValues = new Float32Array(bufferSize);
49
- this.reverseTable = new Uint32Array(bufferSize);
50
- this.peakBand = 0;
51
- this.peak = 0;
52
- var i;
53
- switch (windowFunc) {
54
- case 'bartlett':
55
- for (i = 0; i < bufferSize; i++) {
56
- this.windowValues[i] = 2 / (bufferSize - 1) * ((bufferSize - 1) / 2 - Math.abs(i - (bufferSize - 1) / 2));
57
- }
58
- break;
59
- case 'bartlettHann':
60
- for (i = 0; i < bufferSize; i++) {
61
- this.windowValues[i] = 0.62 - 0.48 * Math.abs(i / (bufferSize - 1) - 0.5) - 0.38 * Math.cos(Math.PI * 2 * i / (bufferSize - 1));
62
- }
63
- break;
64
- case 'blackman':
65
- alpha = alpha || 0.16;
66
- for (i = 0; i < bufferSize; i++) {
67
- 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));
68
- }
69
- break;
70
- case 'cosine':
71
- for (i = 0; i < bufferSize; i++) {
72
- this.windowValues[i] = Math.cos(Math.PI * i / (bufferSize - 1) - Math.PI / 2);
73
- }
74
- break;
75
- case 'gauss':
76
- alpha = alpha || 0.25;
77
- for (i = 0; i < bufferSize; i++) {
78
- this.windowValues[i] = Math.pow(Math.E, -0.5 * Math.pow((i - (bufferSize - 1) / 2) / (alpha * (bufferSize - 1) / 2), 2));
79
- }
80
- break;
81
- case 'hamming':
82
- for (i = 0; i < bufferSize; i++) {
83
- this.windowValues[i] = 0.54 - 0.46 * Math.cos(Math.PI * 2 * i / (bufferSize - 1));
84
- }
85
- break;
86
- case 'hann':
87
- case undefined:
88
- for (i = 0; i < bufferSize; i++) {
89
- this.windowValues[i] = 0.5 * (1 - Math.cos(Math.PI * 2 * i / (bufferSize - 1)));
90
- }
91
- break;
92
- case 'lanczoz':
93
- for (i = 0; i < bufferSize; i++) {
94
- this.windowValues[i] = Math.sin(Math.PI * (2 * i / (bufferSize - 1) - 1)) / (Math.PI * (2 * i / (bufferSize - 1) - 1));
95
- }
96
- break;
97
- case 'rectangular':
98
- for (i = 0; i < bufferSize; i++) {
99
- this.windowValues[i] = 1;
100
- }
101
- break;
102
- case 'triangular':
103
- for (i = 0; i < bufferSize; i++) {
104
- this.windowValues[i] = 2 / bufferSize * (bufferSize / 2 - Math.abs(i - (bufferSize - 1) / 2));
105
- }
106
- break;
107
- default:
108
- throw Error("No such window function '" + windowFunc + "'");
109
- }
110
- var limit = 1;
111
- var bit = bufferSize >> 1;
112
- var i;
113
- while (limit < bufferSize) {
114
- for (i = 0; i < limit; i++) {
115
- this.reverseTable[i + limit] = this.reverseTable[i] + bit;
116
- }
117
- limit = limit << 1;
118
- bit = bit >> 1;
119
- }
120
- for (i = 0; i < bufferSize; i++) {
121
- this.sinTable[i] = Math.sin(-Math.PI / i);
122
- this.cosTable[i] = Math.cos(-Math.PI / i);
123
- }
124
- this.calculateSpectrum = function (buffer) {
125
- // Locally scope variables for speed up
126
- var bufferSize = this.bufferSize,
127
- cosTable = this.cosTable,
128
- sinTable = this.sinTable,
129
- reverseTable = this.reverseTable,
130
- real = new Float32Array(bufferSize),
131
- imag = new Float32Array(bufferSize),
132
- bSi = 2 / this.bufferSize,
133
- sqrt = Math.sqrt,
134
- rval,
135
- ival,
136
- mag,
137
- spectrum = new Float32Array(bufferSize / 2);
138
- var k = Math.floor(Math.log(bufferSize) / Math.LN2);
139
- if (Math.pow(2, k) !== bufferSize) {
140
- throw 'Invalid buffer size, must be a power of 2.';
141
- }
142
- if (bufferSize !== buffer.length) {
143
- throw 'Supplied buffer is not the same size as defined FFT. FFT Size: ' + bufferSize + ' Buffer Size: ' + buffer.length;
144
- }
145
- var halfSize = 1,
146
- phaseShiftStepReal,
147
- phaseShiftStepImag,
148
- currentPhaseShiftReal,
149
- currentPhaseShiftImag,
150
- off,
151
- tr,
152
- ti,
153
- tmpReal;
154
- for (var i = 0; i < bufferSize; i++) {
155
- real[i] = buffer[reverseTable[i]] * this.windowValues[reverseTable[i]];
156
- imag[i] = 0;
157
- }
158
- while (halfSize < bufferSize) {
159
- phaseShiftStepReal = cosTable[halfSize];
160
- phaseShiftStepImag = sinTable[halfSize];
161
- currentPhaseShiftReal = 1;
162
- currentPhaseShiftImag = 0;
163
- for (var fftStep = 0; fftStep < halfSize; fftStep++) {
164
- var i = fftStep;
165
- while (i < bufferSize) {
166
- off = i + halfSize;
167
- tr = currentPhaseShiftReal * real[off] - currentPhaseShiftImag * imag[off];
168
- ti = currentPhaseShiftReal * imag[off] + currentPhaseShiftImag * real[off];
169
- real[off] = real[i] - tr;
170
- imag[off] = imag[i] - ti;
171
- real[i] += tr;
172
- imag[i] += ti;
173
- i += halfSize << 1;
174
- }
175
- tmpReal = currentPhaseShiftReal;
176
- currentPhaseShiftReal = tmpReal * phaseShiftStepReal - currentPhaseShiftImag * phaseShiftStepImag;
177
- currentPhaseShiftImag = tmpReal * phaseShiftStepImag + currentPhaseShiftImag * phaseShiftStepReal;
178
- }
179
- halfSize = halfSize << 1;
180
- }
181
- for (var i = 0, N = bufferSize / 2; i < N; i++) {
182
- rval = real[i];
183
- ival = imag[i];
184
- mag = bSi * sqrt(rval * rval + ival * ival);
185
- if (mag > this.peak) {
186
- this.peakBand = i;
187
- this.peak = mag;
188
- }
189
- spectrum[i] = mag;
190
- }
191
- return spectrum;
192
- };
193
- }
194
- module.exports = exports.default;
195
-
196
- /***/ }),
197
-
198
- /***/ "./src/plugin/spectrogram/index.js":
199
- /*!*****************************************!*\
200
- !*** ./src/plugin/spectrogram/index.js ***!
201
- \*****************************************/
202
- /***/ ((module, exports, __webpack_require__) => {
203
-
204
-
205
-
206
- Object.defineProperty(exports, "__esModule", ({
207
- value: true
208
- }));
209
- exports["default"] = void 0;
210
- var _fft = _interopRequireDefault(__webpack_require__(/*! ./fft */ "./src/plugin/spectrogram/fft.js"));
211
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
212
- function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
213
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
214
- 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, _toPropertyKey(descriptor.key), descriptor); } }
215
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
216
- function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
217
- function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
218
- /**
219
- * @typedef {Object} SpectrogramPluginParams
220
- * @property {string|HTMLElement} container Selector of element or element in
221
- * which to render
222
- * @property {number} fftSamples=512 Number of samples to fetch to FFT. Must be
223
- * a power of 2.
224
- * @property {boolean} splitChannels=false Render with separate spectrograms for
225
- * the channels of the audio
226
- * @property {number} height=fftSamples/2 Height of the spectrogram view in CSS
227
- * pixels
228
- * @property {boolean} labels Set to true to display frequency labels.
229
- * @property {number} noverlap Size of the overlapping window. Must be <
230
- * fftSamples. Auto deduced from canvas size by default.
231
- * @property {string} windowFunc='hann' The window function to be used. One of
232
- * these: `'bartlett'`, `'bartlettHann'`, `'blackman'`, `'cosine'`, `'gauss'`,
233
- * `'hamming'`, `'hann'`, `'lanczoz'`, `'rectangular'`, `'triangular'`
234
- * @property {?number} alpha Some window functions have this extra value.
235
- * (Between 0 and 1)
236
- * @property {number} pixelRatio=wavesurfer.params.pixelRatio to control the
237
- * size of the spectrogram in relation with its canvas. 1 = Draw on the whole
238
- * canvas. 2 = Draw on a quarter (1/2 the length and 1/2 the width)
239
- * @property {number} frequencyMin=0 Min frequency to scale spectrogram.
240
- * @property {number} frequencyMax=12000 Max frequency to scale spectrogram.
241
- * Set this to samplerate/2 to draw whole range of spectrogram.
242
- * @property {?boolean} deferInit Set to true to manually call
243
- * `initPlugin('spectrogram')`
244
- * @property {?number[][]} colorMap A 256 long array of 4-element arrays.
245
- * Each entry should contain a float between 0 and 1 and specify
246
- * r, g, b, and alpha.
247
- */
248
- /**
249
- * Render a spectrogram visualisation of the audio.
250
- *
251
- * @implements {PluginClass}
252
- * @extends {Observer}
253
- * @example
254
- * // es6
255
- * import SpectrogramPlugin from 'wavesurfer.spectrogram.js';
256
- *
257
- * // commonjs
258
- * var SpectrogramPlugin = require('wavesurfer.spectrogram.js');
259
- *
260
- * // if you are using <script> tags
261
- * var SpectrogramPlugin = window.WaveSurfer.spectrogram;
262
- *
263
- * // ... initialising wavesurfer with the plugin
264
- * var wavesurfer = WaveSurfer.create({
265
- * // wavesurfer options ...
266
- * plugins: [
267
- * SpectrogramPlugin.create({
268
- * // plugin options ...
269
- * })
270
- * ]
271
- * });
272
- */
273
- var SpectrogramPlugin = /*#__PURE__*/function () {
274
- function SpectrogramPlugin(params, ws) {
275
- var _this = this;
276
- _classCallCheck(this, SpectrogramPlugin);
277
- this.params = params;
278
- this.wavesurfer = ws;
279
- this.util = ws.util;
280
- this.frequenciesDataUrl = params.frequenciesDataUrl;
281
- this._onScroll = function (e) {
282
- _this.updateScroll(e);
283
- };
284
- this._onRender = function () {
285
- _this.render();
286
- };
287
- this._onWrapperClick = function (e) {
288
- _this._wrapperClickHandler(e);
289
- };
290
- this._onReady = function () {
291
- var drawer = _this.drawer = ws.drawer;
292
- _this.container = 'string' == typeof params.container ? document.querySelector(params.container) : params.container;
293
- if (!_this.container) {
294
- throw Error('No container for WaveSurfer spectrogram');
295
- }
296
- if (params.colorMap) {
297
- if (params.colorMap.length < 256) {
298
- throw new Error('Colormap must contain 256 elements');
299
- }
300
- for (var i = 0; i < params.colorMap.length; i++) {
301
- var cmEntry = params.colorMap[i];
302
- if (cmEntry.length !== 4) {
303
- throw new Error('ColorMap entries must contain 4 values');
304
- }
305
- }
306
- _this.colorMap = params.colorMap;
307
- } else {
308
- _this.colorMap = [];
309
- for (var _i = 0; _i < 256; _i++) {
310
- var val = (255 - _i) / 256;
311
- _this.colorMap.push([val, val, val, 1]);
312
- }
313
- }
314
- _this.width = drawer.width;
315
- _this.pixelRatio = _this.params.pixelRatio || ws.params.pixelRatio;
316
- _this.fftSamples = _this.params.fftSamples || ws.params.fftSamples || 512;
317
- _this.height = _this.params.height || _this.fftSamples / 2;
318
- _this.noverlap = params.noverlap;
319
- _this.windowFunc = params.windowFunc;
320
- _this.alpha = params.alpha;
321
- _this.splitChannels = params.splitChannels;
322
- _this.channels = _this.splitChannels ? ws.backend.buffer.numberOfChannels : 1;
323
-
324
- // Getting file's original samplerate is difficult(#1248).
325
- // So set 12kHz default to render like wavesurfer.js 5.x.
326
- _this.frequencyMin = params.frequencyMin || 0;
327
- _this.frequencyMax = params.frequencyMax || 12000;
328
- _this.createWrapper();
329
- _this.createCanvas();
330
- _this.render();
331
- drawer.wrapper.addEventListener('scroll', _this._onScroll);
332
- ws.on('redraw', _this._onRender);
333
- };
334
- }
335
- _createClass(SpectrogramPlugin, [{
336
- key: "init",
337
- value: function init() {
338
- // Check if wavesurfer is ready
339
- if (this.wavesurfer.isReady) {
340
- this._onReady();
341
- } else {
342
- this.wavesurfer.once('ready', this._onReady);
343
- }
344
- }
345
- }, {
346
- key: "destroy",
347
- value: function destroy() {
348
- this.unAll();
349
- this.wavesurfer.un('ready', this._onReady);
350
- this.wavesurfer.un('redraw', this._onRender);
351
- this.drawer && this.drawer.wrapper.removeEventListener('scroll', this._onScroll);
352
- this.wavesurfer = null;
353
- this.util = null;
354
- this.params = null;
355
- if (this.wrapper) {
356
- this.wrapper.removeEventListener('click', this._onWrapperClick);
357
- this.wrapper.parentNode.removeChild(this.wrapper);
358
- this.wrapper = null;
359
- }
360
- }
361
- }, {
362
- key: "createWrapper",
363
- value: function createWrapper() {
364
- var prevSpectrogram = this.container.querySelector('spectrogram');
365
- if (prevSpectrogram) {
366
- this.container.removeChild(prevSpectrogram);
367
- }
368
- var wsParams = this.wavesurfer.params;
369
- this.wrapper = document.createElement('spectrogram');
370
- // if labels are active
371
- if (this.params.labels) {
372
- var labelsEl = this.labelsEl = document.createElement('canvas');
373
- labelsEl.classList.add('spec-labels');
374
- this.drawer.style(labelsEl, {
375
- position: 'absolute',
376
- zIndex: 9,
377
- height: "".concat(this.height * this.channels, "px"),
378
- width: "55px"
379
- });
380
- this.wrapper.appendChild(labelsEl);
381
- this.loadLabels('rgba(68,68,68,0.5)', '12px', '10px', '', '#fff', '#f7f7f7', 'center', '#specLabels');
382
- }
383
- this.drawer.style(this.wrapper, {
384
- display: 'block',
385
- position: 'relative',
386
- userSelect: 'none',
387
- webkitUserSelect: 'none',
388
- height: "".concat(this.height * this.channels, "px")
389
- });
390
- if (wsParams.fillParent || wsParams.scrollParent) {
391
- this.drawer.style(this.wrapper, {
392
- width: '100%',
393
- overflowX: 'hidden',
394
- overflowY: 'hidden'
395
- });
396
- }
397
- this.container.appendChild(this.wrapper);
398
- this.wrapper.addEventListener('click', this._onWrapperClick);
399
- }
400
- }, {
401
- key: "_wrapperClickHandler",
402
- value: function _wrapperClickHandler(event) {
403
- event.preventDefault();
404
- var relX = 'offsetX' in event ? event.offsetX : event.layerX;
405
- this.fireEvent('click', relX / this.width || 0);
406
- }
407
- }, {
408
- key: "createCanvas",
409
- value: function createCanvas() {
410
- var canvas = this.canvas = this.wrapper.appendChild(document.createElement('canvas'));
411
- this.spectrCc = canvas.getContext('2d');
412
- this.util.style(canvas, {
413
- position: 'absolute',
414
- zIndex: 4
415
- });
416
- }
417
- }, {
418
- key: "render",
419
- value: function render() {
420
- this.updateCanvasStyle();
421
- if (this.frequenciesDataUrl) {
422
- this.loadFrequenciesData(this.frequenciesDataUrl);
423
- } else {
424
- this.getFrequencies(this.drawSpectrogram);
425
- }
426
- }
427
- }, {
428
- key: "updateCanvasStyle",
429
- value: function updateCanvasStyle() {
430
- var width = Math.round(this.width / this.pixelRatio) + 'px';
431
- this.canvas.width = this.width;
432
- this.canvas.height = this.fftSamples / 2 * this.channels;
433
- this.canvas.style.width = width;
434
- this.canvas.style.height = this.height + 'px';
435
- }
436
- }, {
437
- key: "drawSpectrogram",
438
- value: function drawSpectrogram(frequenciesData, my) {
439
- if (!isNaN(frequenciesData[0][0])) {
440
- // data is 1ch [sample, freq] format
441
- // to [channel, sample, freq] format
442
- frequenciesData = [frequenciesData];
443
- }
444
- var spectrCc = my.spectrCc;
445
- var height = my.fftSamples / 2;
446
- var width = my.width;
447
- var freqFrom = my.buffer.sampleRate / 2;
448
- var freqMin = my.frequencyMin;
449
- var freqMax = my.frequencyMax;
450
- if (!spectrCc) {
451
- return;
452
- }
453
- var _loop = function _loop(c) {
454
- // for each channel
455
- var pixels = my.resample(frequenciesData[c]);
456
- var imageData = new ImageData(width, height);
457
- for (var i = 0; i < pixels.length; i++) {
458
- for (var j = 0; j < pixels[i].length; j++) {
459
- var colorMap = my.colorMap[pixels[i][j]];
460
- var redIndex = ((height - j) * width + i) * 4;
461
- imageData.data[redIndex] = colorMap[0] * 255;
462
- imageData.data[redIndex + 1] = colorMap[1] * 255;
463
- imageData.data[redIndex + 2] = colorMap[2] * 255;
464
- imageData.data[redIndex + 3] = colorMap[3] * 255;
465
- }
466
- }
467
-
468
- // scale and stack spectrograms
469
- createImageBitmap(imageData).then(function (renderer) {
470
- return spectrCc.drawImage(renderer, 0, height * (1 - freqMax / freqFrom),
471
- // source x, y
472
- width, height * (freqMax - freqMin) / freqFrom,
473
- // source width, height
474
- 0, height * c,
475
- // destination x, y
476
- width, height // destination width, height
477
- );
478
- });
479
- };
480
- for (var c = 0; c < frequenciesData.length; c++) {
481
- _loop(c);
482
- }
483
- }
484
- }, {
485
- key: "getFrequencies",
486
- value: function getFrequencies(callback) {
487
- var fftSamples = this.fftSamples;
488
- var buffer = this.buffer = this.wavesurfer.backend.buffer;
489
- var channels = this.channels;
490
- if (!buffer) {
491
- this.fireEvent('error', 'Web Audio buffer is not available');
492
- return;
493
- }
494
-
495
- // This may differ from file samplerate. Browser resamples audio.
496
- var sampleRate = buffer.sampleRate;
497
- var frequencies = [];
498
- var noverlap = this.noverlap;
499
- if (!noverlap) {
500
- var uniqueSamplesPerPx = buffer.length / this.canvas.width;
501
- noverlap = Math.max(0, Math.round(fftSamples - uniqueSamplesPerPx));
502
- }
503
- var fft = new _fft.default(fftSamples, sampleRate, this.windowFunc, this.alpha);
504
- for (var c = 0; c < channels; c++) {
505
- // for each channel
506
- var channelData = buffer.getChannelData(c);
507
- var channelFreq = [];
508
- var currentOffset = 0;
509
- while (currentOffset + fftSamples < channelData.length) {
510
- var segment = channelData.slice(currentOffset, currentOffset + fftSamples);
511
- var spectrum = fft.calculateSpectrum(segment);
512
- var array = new Uint8Array(fftSamples / 2);
513
- var j = void 0;
514
- for (j = 0; j < fftSamples / 2; j++) {
515
- array[j] = Math.max(-255, Math.log10(spectrum[j]) * 45);
516
- }
517
- channelFreq.push(array);
518
- // channelFreq: [sample, freq]
519
-
520
- currentOffset += fftSamples - noverlap;
521
- }
522
- frequencies.push(channelFreq);
523
- // frequencies: [channel, sample, freq]
524
- }
525
-
526
- callback(frequencies, this);
527
- }
528
- }, {
529
- key: "loadFrequenciesData",
530
- value: function loadFrequenciesData(url) {
531
- var _this2 = this;
532
- var request = this.util.fetchFile({
533
- url: url
534
- });
535
- request.on('success', function (data) {
536
- return _this2.drawSpectrogram(JSON.parse(data), _this2);
537
- });
538
- request.on('error', function (e) {
539
- return _this2.fireEvent('error', e);
540
- });
541
- return request;
542
- }
543
- }, {
544
- key: "freqType",
545
- value: function freqType(freq) {
546
- return freq >= 1000 ? (freq / 1000).toFixed(1) : Math.round(freq);
547
- }
548
- }, {
549
- key: "unitType",
550
- value: function unitType(freq) {
551
- return freq >= 1000 ? 'KHz' : 'Hz';
552
- }
553
- }, {
554
- key: "loadLabels",
555
- value: function loadLabels(bgFill, fontSizeFreq, fontSizeUnit, fontType, textColorFreq, textColorUnit, textAlign, container) {
556
- var frequenciesHeight = this.height;
557
- bgFill = bgFill || 'rgba(68,68,68,0)';
558
- fontSizeFreq = fontSizeFreq || '12px';
559
- fontSizeUnit = fontSizeUnit || '10px';
560
- fontType = fontType || 'Helvetica';
561
- textColorFreq = textColorFreq || '#fff';
562
- textColorUnit = textColorUnit || '#fff';
563
- textAlign = textAlign || 'center';
564
- container = container || '#specLabels';
565
- var bgWidth = 55;
566
- var getMaxY = frequenciesHeight || 512;
567
- var labelIndex = 5 * (getMaxY / 256);
568
- var freqStart = this.frequencyMin;
569
- var step = (this.frequencyMax - freqStart) / labelIndex;
570
-
571
- // prepare canvas element for labels
572
- var ctx = this.labelsEl.getContext('2d');
573
- var dispScale = window.devicePixelRatio;
574
- this.labelsEl.height = this.height * this.channels * dispScale;
575
- this.labelsEl.width = bgWidth * dispScale;
576
- ctx.scale(dispScale, dispScale);
577
- if (!ctx) {
578
- return;
579
- }
580
- for (var c = 0; c < this.channels; c++) {
581
- // for each channel
582
- // fill background
583
- ctx.fillStyle = bgFill;
584
- ctx.fillRect(0, c * getMaxY, bgWidth, (1 + c) * getMaxY);
585
- ctx.fill();
586
- var i = void 0;
587
-
588
- // render labels
589
- for (i = 0; i <= labelIndex; i++) {
590
- ctx.textAlign = textAlign;
591
- ctx.textBaseline = 'middle';
592
- var freq = freqStart + step * i;
593
- var label = this.freqType(freq);
594
- var units = this.unitType(freq);
595
- var yLabelOffset = 2;
596
- var x = 16;
597
- var y = void 0;
598
- if (i == 0) {
599
- y = (1 + c) * getMaxY + i - 10;
600
- // unit label
601
- ctx.fillStyle = textColorUnit;
602
- ctx.font = fontSizeUnit + ' ' + fontType;
603
- ctx.fillText(units, x + 24, y);
604
- // freq label
605
- ctx.fillStyle = textColorFreq;
606
- ctx.font = fontSizeFreq + ' ' + fontType;
607
- ctx.fillText(label, x, y);
608
- } else {
609
- y = (1 + c) * getMaxY - i * 50 + yLabelOffset;
610
- // unit label
611
- ctx.fillStyle = textColorUnit;
612
- ctx.font = fontSizeUnit + ' ' + fontType;
613
- ctx.fillText(units, x + 24, y);
614
- // freq label
615
- ctx.fillStyle = textColorFreq;
616
- ctx.font = fontSizeFreq + ' ' + fontType;
617
- ctx.fillText(label, x, y);
618
- }
619
- }
620
- }
621
- }
622
- }, {
623
- key: "updateScroll",
624
- value: function updateScroll(e) {
625
- if (this.wrapper) {
626
- this.wrapper.scrollLeft = e.target.scrollLeft;
627
- }
628
- }
629
- }, {
630
- key: "resample",
631
- value: function resample(oldMatrix) {
632
- var columnsNumber = this.width;
633
- var newMatrix = [];
634
- var oldPiece = 1 / oldMatrix.length;
635
- var newPiece = 1 / columnsNumber;
636
- var i;
637
- for (i = 0; i < columnsNumber; i++) {
638
- var column = new Array(oldMatrix[0].length);
639
- var j = void 0;
640
- for (j = 0; j < oldMatrix.length; j++) {
641
- var oldStart = j * oldPiece;
642
- var oldEnd = oldStart + oldPiece;
643
- var newStart = i * newPiece;
644
- var newEnd = newStart + newPiece;
645
- 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));
646
- var k = void 0;
647
- /* eslint-disable max-depth */
648
- if (overlap > 0) {
649
- for (k = 0; k < oldMatrix[0].length; k++) {
650
- if (column[k] == null) {
651
- column[k] = 0;
652
- }
653
- column[k] += overlap / newPiece * oldMatrix[j][k];
654
- }
655
- }
656
- /* eslint-enable max-depth */
657
- }
658
-
659
- var intColumn = new Uint8Array(oldMatrix[0].length);
660
- var m = void 0;
661
- for (m = 0; m < oldMatrix[0].length; m++) {
662
- intColumn[m] = column[m];
663
- }
664
- newMatrix.push(intColumn);
665
- }
666
- return newMatrix;
667
- }
668
- }], [{
669
- key: "create",
670
- value:
671
- /**
672
- * Spectrogram plugin definition factory
673
- *
674
- * This function must be used to create a plugin definition which can be
675
- * used by wavesurfer to correctly instantiate the plugin.
676
- *
677
- * @param {SpectrogramPluginParams} params Parameters used to initialise the plugin
678
- * @return {PluginDefinition} An object representing the plugin.
679
- */
680
- function create(params) {
681
- return {
682
- name: 'spectrogram',
683
- deferInit: params && params.deferInit ? params.deferInit : false,
684
- params: params,
685
- staticProps: {
686
- FFT: _fft.default
687
- },
688
- instance: SpectrogramPlugin
689
- };
690
- }
691
- }]);
692
- return SpectrogramPlugin;
693
- }();
694
- exports["default"] = SpectrogramPlugin;
695
- module.exports = exports.default;
696
-
697
- /***/ })
698
-
699
- /******/ });
700
- /************************************************************************/
701
- /******/ // The module cache
702
- /******/ var __webpack_module_cache__ = {};
703
- /******/
704
- /******/ // The require function
705
- /******/ function __webpack_require__(moduleId) {
706
- /******/ // Check if module is in cache
707
- /******/ var cachedModule = __webpack_module_cache__[moduleId];
708
- /******/ if (cachedModule !== undefined) {
709
- /******/ return cachedModule.exports;
710
- /******/ }
711
- /******/ // Create a new module (and put it into the cache)
712
- /******/ var module = __webpack_module_cache__[moduleId] = {
713
- /******/ // no module.id needed
714
- /******/ // no module.loaded needed
715
- /******/ exports: {}
716
- /******/ };
717
- /******/
718
- /******/ // Execute the module function
719
- /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
720
- /******/
721
- /******/ // Return the exports of the module
722
- /******/ return module.exports;
723
- /******/ }
724
- /******/
725
- /************************************************************************/
726
- /******/
727
- /******/ // startup
728
- /******/ // Load entry module and return exports
729
- /******/ // This entry module is referenced by other modules so it can't be inlined
730
- /******/ var __webpack_exports__ = __webpack_require__("./src/plugin/spectrogram/index.js");
731
- /******/
732
- /******/ return __webpack_exports__;
733
- /******/ })()
734
- ;
735
- });
736
- //# sourceMappingURL=wavesurfer.spectrogram.js.map