wavesurfer.js 6.5.1 → 6.6.0
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.
- package/README.md +16 -2
- package/dist/plugin/wavesurfer.cursor.js +1 -1
- package/dist/plugin/wavesurfer.cursor.min.js +1 -1
- package/dist/plugin/wavesurfer.elan.js +1 -1
- package/dist/plugin/wavesurfer.elan.min.js +1 -1
- package/dist/plugin/wavesurfer.markers.js +1 -1
- package/dist/plugin/wavesurfer.markers.min.js +1 -1
- package/dist/plugin/wavesurfer.mediasession.js +1 -1
- package/dist/plugin/wavesurfer.mediasession.min.js +1 -1
- package/dist/plugin/wavesurfer.microphone.js +1 -1
- package/dist/plugin/wavesurfer.microphone.min.js +1 -1
- package/dist/plugin/wavesurfer.minimap.js +1 -1
- package/dist/plugin/wavesurfer.minimap.min.js +1 -1
- package/dist/plugin/wavesurfer.playhead.js +1 -1
- package/dist/plugin/wavesurfer.playhead.min.js +1 -1
- package/dist/plugin/wavesurfer.regions.js +1 -1
- package/dist/plugin/wavesurfer.regions.min.js +1 -1
- package/dist/plugin/wavesurfer.spectrogram.js +128 -34
- package/dist/plugin/wavesurfer.spectrogram.js.map +1 -1
- package/dist/plugin/wavesurfer.spectrogram.min.js +2 -2
- package/dist/plugin/wavesurfer.spectrogram.min.js.map +1 -1
- package/dist/plugin/wavesurfer.timeline.js +1 -1
- package/dist/plugin/wavesurfer.timeline.min.js +1 -1
- package/dist/wavesurfer-html-init.js +1 -1
- package/dist/wavesurfer-html-init.min.js +1 -1
- package/dist/wavesurfer.js +160 -6
- package/dist/wavesurfer.js.map +1 -1
- package/dist/wavesurfer.min.js +2 -2
- package/dist/wavesurfer.min.js.map +1 -1
- package/package.json +4 -3
- package/src/drawer.canvasentry.js +43 -0
- package/src/drawer.js +0 -4
- package/src/drawer.multicanvas.js +71 -1
- package/src/plugin/spectrogram/index.js +121 -30
- package/src/wavesurfer.js +33 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wavesurfer.js",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.6.0",
|
|
4
4
|
"description": "Interactive navigable audio visualization using Web Audio and Canvas",
|
|
5
5
|
"main": "dist/wavesurfer.js",
|
|
6
6
|
"directories": {
|
|
@@ -31,11 +31,12 @@
|
|
|
31
31
|
"test": "karma start karma.conf.js",
|
|
32
32
|
"test:chrome": "karma start karma.conf.js --browsers=Chrome --single-run=false",
|
|
33
33
|
"prepublishOnly": "not-in-install && npm run build || in-install",
|
|
34
|
-
"prepare": "npm run build"
|
|
34
|
+
"prepare": "npm run build",
|
|
35
|
+
"release": "./scripts/release.sh"
|
|
35
36
|
},
|
|
36
37
|
"repository": {
|
|
37
38
|
"type": "git",
|
|
38
|
-
"url": "git
|
|
39
|
+
"url": "git@github.com:wavesurfer-js/wavesurfer.js.git"
|
|
39
40
|
},
|
|
40
41
|
"publishConfig": {
|
|
41
42
|
"registry": "https://registry.npmjs.org"
|
|
@@ -66,6 +66,11 @@ export default class CanvasEntry {
|
|
|
66
66
|
* @type {object}
|
|
67
67
|
*/
|
|
68
68
|
this.canvasContextAttributes = {};
|
|
69
|
+
/**
|
|
70
|
+
* The Timeout id used to track this canvas entry.
|
|
71
|
+
*/
|
|
72
|
+
this.drawTimeout = null;
|
|
73
|
+
|
|
69
74
|
}
|
|
70
75
|
|
|
71
76
|
/**
|
|
@@ -125,21 +130,27 @@ export default class CanvasEntry {
|
|
|
125
130
|
*/
|
|
126
131
|
clearWave() {
|
|
127
132
|
// wave
|
|
133
|
+
this.waveCtx.save();
|
|
134
|
+
this.waveCtx.setTransform(1, 0, 0, 1, 0, 0);
|
|
128
135
|
this.waveCtx.clearRect(
|
|
129
136
|
0,
|
|
130
137
|
0,
|
|
131
138
|
this.waveCtx.canvas.width,
|
|
132
139
|
this.waveCtx.canvas.height
|
|
133
140
|
);
|
|
141
|
+
this.waveCtx.restore();
|
|
134
142
|
|
|
135
143
|
// progress
|
|
136
144
|
if (this.hasProgressCanvas) {
|
|
145
|
+
this.progressCtx.save();
|
|
146
|
+
this.progressCtx.setTransform(1, 0, 0, 1, 0, 0);
|
|
137
147
|
this.progressCtx.clearRect(
|
|
138
148
|
0,
|
|
139
149
|
0,
|
|
140
150
|
this.progressCtx.canvas.width,
|
|
141
151
|
this.progressCtx.canvas.height
|
|
142
152
|
);
|
|
153
|
+
this.progressCtx.restore();
|
|
143
154
|
}
|
|
144
155
|
}
|
|
145
156
|
|
|
@@ -424,4 +435,36 @@ export default class CanvasEntry {
|
|
|
424
435
|
return this.wave.toDataURL(format, quality);
|
|
425
436
|
}
|
|
426
437
|
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Stretches existing canvas
|
|
441
|
+
* @param {Number} newTotalWidth total width of wave in pixels
|
|
442
|
+
*/
|
|
443
|
+
stretchCanvas(newTotalWidth) {
|
|
444
|
+
//Calculate the start and width of this canvas
|
|
445
|
+
let start = Math.round(this.start * newTotalWidth);
|
|
446
|
+
let width = Math.round(this.end * newTotalWidth - start);
|
|
447
|
+
|
|
448
|
+
//Stretch canvas
|
|
449
|
+
let elementSize = { width: width + 'px' };
|
|
450
|
+
let elementStart = {left: start + 'px'};
|
|
451
|
+
style(this.wave, elementSize);
|
|
452
|
+
style(this.wave, elementStart);
|
|
453
|
+
if (this.hasProgressCanvas) {
|
|
454
|
+
style(this.progress, elementSize);
|
|
455
|
+
style(this.progress, elementStart);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Set the left offset of the canvas
|
|
461
|
+
* @param {Number} position in px for the canvas to start
|
|
462
|
+
*/
|
|
463
|
+
setLeft(position) {
|
|
464
|
+
let elementStart = {left: position + 'px'};
|
|
465
|
+
style(this.wave, elementStart);
|
|
466
|
+
if (this.hasProgressCanvas) {
|
|
467
|
+
style(this.progress, elementStart);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
427
470
|
}
|
package/src/drawer.js
CHANGED
|
@@ -272,10 +272,6 @@ export default class Drawer extends util.Observer {
|
|
|
272
272
|
* @return {boolean} Whether the width of the container was updated or not
|
|
273
273
|
*/
|
|
274
274
|
setWidth(width) {
|
|
275
|
-
if (this.width == width) {
|
|
276
|
-
return false;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
275
|
this.width = width;
|
|
280
276
|
|
|
281
277
|
if (this.params.fillParent || this.params.scrollParent) {
|
|
@@ -89,6 +89,14 @@ export default class MultiCanvas extends Drawer {
|
|
|
89
89
|
* @type {boolean}
|
|
90
90
|
*/
|
|
91
91
|
this.vertical = params.vertical;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Whether to use the optimsized zoom rendering
|
|
95
|
+
* Automatically toggles to true if stretchCanvases() function is called
|
|
96
|
+
*
|
|
97
|
+
* @type {boolean}
|
|
98
|
+
*/
|
|
99
|
+
this.optimiseZoom = false;
|
|
92
100
|
}
|
|
93
101
|
|
|
94
102
|
/**
|
|
@@ -157,10 +165,16 @@ export default class MultiCanvas extends Drawer {
|
|
|
157
165
|
|
|
158
166
|
let canvasWidth = this.maxCanvasWidth + this.overlap;
|
|
159
167
|
const lastCanvas = this.canvases.length - 1;
|
|
168
|
+
let leftOffset = 0;
|
|
160
169
|
this.canvases.forEach((entry, i) => {
|
|
161
170
|
if (i == lastCanvas) {
|
|
162
171
|
canvasWidth = this.width - this.maxCanvasWidth * lastCanvas;
|
|
163
172
|
}
|
|
173
|
+
|
|
174
|
+
//Set left offset and add to next entry
|
|
175
|
+
entry.setLeft(leftOffset);
|
|
176
|
+
leftOffset += canvasWidth / this.params.pixelRatio;
|
|
177
|
+
|
|
164
178
|
this.updateDimensions(entry, canvasWidth, this.height);
|
|
165
179
|
|
|
166
180
|
entry.clearWave();
|
|
@@ -410,7 +424,39 @@ export default class MultiCanvas extends Drawer {
|
|
|
410
424
|
this.canvases.forEach((entry, i) => {
|
|
411
425
|
this.setFillStyles(entry, waveColor, progressColor);
|
|
412
426
|
this.applyCanvasTransforms(entry, this.params.vertical);
|
|
413
|
-
|
|
427
|
+
|
|
428
|
+
if (this.optimiseZoom) {
|
|
429
|
+
//Optimising zoom functionality
|
|
430
|
+
//If there's a wrapper, optimise for the view
|
|
431
|
+
let priority = 0;
|
|
432
|
+
if (this.wrapper) {
|
|
433
|
+
let canvasRect = entry.wave.getBoundingClientRect();
|
|
434
|
+
let wrapperRect = this.wrapper.getBoundingClientRect();
|
|
435
|
+
|
|
436
|
+
//Determine whether canvas is in viewframe or not and assign priority
|
|
437
|
+
if (Math.floor(canvasRect['left']) > Math.ceil(wrapperRect['right'])) {
|
|
438
|
+
//Canvas is to the right of view window
|
|
439
|
+
let distance = canvasRect['left'] - wrapperRect['right'];
|
|
440
|
+
priority = Math.ceil(distance / wrapperRect['width']);
|
|
441
|
+
} else if (Math.ceil(canvasRect['right']) < Math.floor(wrapperRect['left'])) {
|
|
442
|
+
//Canvas is to the left of the view window
|
|
443
|
+
let distance = wrapperRect['left'] - canvasRect['right'];
|
|
444
|
+
priority = Math.ceil(distance / wrapperRect['width']);
|
|
445
|
+
}
|
|
446
|
+
} else {
|
|
447
|
+
//Everything is equal priority
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
//This staggers the drawing of canvases so they don't all draw at once
|
|
451
|
+
entry.clearWave();
|
|
452
|
+
clearTimeout(entry.drawTimeout);
|
|
453
|
+
entry.drawTimeout = setTimeout(function(){
|
|
454
|
+
entry.drawLines(peaks, absmax, halfH, offsetY, start, end);
|
|
455
|
+
entry.drawTimeout = null;
|
|
456
|
+
}, 25 * priority);
|
|
457
|
+
} else {
|
|
458
|
+
entry.drawLines(peaks, absmax, halfH, offsetY, start, end);
|
|
459
|
+
}
|
|
414
460
|
});
|
|
415
461
|
}
|
|
416
462
|
|
|
@@ -606,6 +652,30 @@ export default class MultiCanvas extends Drawer {
|
|
|
606
652
|
}
|
|
607
653
|
}
|
|
608
654
|
|
|
655
|
+
/**
|
|
656
|
+
* Stretches the canvases to mimic zoom without recalculation
|
|
657
|
+
*
|
|
658
|
+
* @param {Number} desiredWidth new width of the wave display
|
|
659
|
+
* @param {Number} progress Value between 0 and 1 for wave progress
|
|
660
|
+
*/
|
|
661
|
+
stretchCanvases(desiredWidth, progress) {
|
|
662
|
+
if (!this.optimiseZoom) {
|
|
663
|
+
//Enable optimsed zooming
|
|
664
|
+
this.optimiseZoom = true;
|
|
665
|
+
}
|
|
666
|
+
let totalCanvasWidth = Math.round(desiredWidth / this.params.pixelRatio);
|
|
667
|
+
this.width = desiredWidth;
|
|
668
|
+
|
|
669
|
+
for (let i = 0; i < this.canvases.length; i++) {
|
|
670
|
+
this.canvases[i].stretchCanvas(totalCanvasWidth);
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
//Update progress
|
|
674
|
+
let progressPos = progress * totalCanvasWidth;
|
|
675
|
+
this.updateProgress(progressPos);
|
|
676
|
+
this.recenterOnPosition(progressPos, true);
|
|
677
|
+
}
|
|
678
|
+
|
|
609
679
|
/**
|
|
610
680
|
* Render the new progress
|
|
611
681
|
*
|
|
@@ -92,6 +92,9 @@ export default class SpectrogramPlugin {
|
|
|
92
92
|
this._onRender = () => {
|
|
93
93
|
this.render();
|
|
94
94
|
};
|
|
95
|
+
this._onZoom = () => {
|
|
96
|
+
this.stretchCanvases();
|
|
97
|
+
};
|
|
95
98
|
this._onWrapperClick = e => {
|
|
96
99
|
this._wrapperClickHandler(e);
|
|
97
100
|
};
|
|
@@ -136,6 +139,9 @@ export default class SpectrogramPlugin {
|
|
|
136
139
|
this.alpha = params.alpha;
|
|
137
140
|
this.splitChannels = params.splitChannels;
|
|
138
141
|
this.channels = this.splitChannels ? ws.backend.buffer.numberOfChannels : 1;
|
|
142
|
+
this.canvases = [];
|
|
143
|
+
this.canvasesTimeouts = [];
|
|
144
|
+
this.scrollLeftTracker = 0; //Tracks the desired scrollLeft value
|
|
139
145
|
|
|
140
146
|
// Getting file's original samplerate is difficult(#1248).
|
|
141
147
|
// So set 12kHz default to render like wavesurfer.js 5.x.
|
|
@@ -143,10 +149,11 @@ export default class SpectrogramPlugin {
|
|
|
143
149
|
this.frequencyMax = params.frequencyMax || 12000;
|
|
144
150
|
|
|
145
151
|
this.createWrapper();
|
|
146
|
-
this.
|
|
152
|
+
this.addCanvas();
|
|
147
153
|
this.render();
|
|
148
154
|
|
|
149
155
|
drawer.wrapper.addEventListener('scroll', this._onScroll);
|
|
156
|
+
ws.on('zoom', this._onZoom);
|
|
150
157
|
ws.on('redraw', this._onRender);
|
|
151
158
|
};
|
|
152
159
|
}
|
|
@@ -231,17 +238,49 @@ export default class SpectrogramPlugin {
|
|
|
231
238
|
this.fireEvent('click', relX / this.width || 0);
|
|
232
239
|
}
|
|
233
240
|
|
|
234
|
-
|
|
235
|
-
|
|
241
|
+
/**
|
|
242
|
+
* Add a canvas to this.canvases
|
|
243
|
+
*/
|
|
244
|
+
addCanvas() {
|
|
245
|
+
const canvas = (this.wrapper.appendChild(
|
|
236
246
|
document.createElement('canvas')
|
|
237
247
|
));
|
|
238
248
|
|
|
239
|
-
this.spectrCc = canvas.getContext('2d');
|
|
240
|
-
|
|
241
249
|
this.util.style(canvas, {
|
|
242
250
|
position: 'absolute',
|
|
243
251
|
zIndex: 4
|
|
244
252
|
});
|
|
253
|
+
|
|
254
|
+
this.canvases.push(canvas);
|
|
255
|
+
this.canvasesTimeouts.push(null);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Remove a canvas from this.canvases
|
|
260
|
+
*/
|
|
261
|
+
removeCanvas() {
|
|
262
|
+
//Stop drawing (if drawing)
|
|
263
|
+
clearTimeout(this.canvasesTimeouts[this.canvasesTimeouts.length - 1]);
|
|
264
|
+
|
|
265
|
+
let lastEntry = this.canvases[this.canvases.length - 1];
|
|
266
|
+
lastEntry.parentElement.removeChild(lastEntry);
|
|
267
|
+
|
|
268
|
+
this.canvases.pop();
|
|
269
|
+
this.canvasesTimeouts.pop();
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Ensure the correct number of canvases for the size of the spectrogram
|
|
274
|
+
*/
|
|
275
|
+
updateCanvases() {
|
|
276
|
+
let canvasesRequired = Math.ceil(this.width / 4000);
|
|
277
|
+
|
|
278
|
+
while (this.canvases.length < canvasesRequired) {
|
|
279
|
+
this.addCanvas();
|
|
280
|
+
}
|
|
281
|
+
while (this.canvases.length > canvasesRequired) {
|
|
282
|
+
this.removeCanvas();
|
|
283
|
+
}
|
|
245
284
|
}
|
|
246
285
|
|
|
247
286
|
render() {
|
|
@@ -255,11 +294,14 @@ export default class SpectrogramPlugin {
|
|
|
255
294
|
}
|
|
256
295
|
|
|
257
296
|
updateCanvasStyle() {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
297
|
+
this.updateCanvases();
|
|
298
|
+
//width per canvas
|
|
299
|
+
for (let i = 0; i < this.canvases.length; i++) {
|
|
300
|
+
this.canvases[i].width = Math.round(this.width / this.canvases.length);
|
|
301
|
+
this.canvases[i].height = this.fftSamples / 2 * this.channels;
|
|
302
|
+
this.canvases[i].style.width = Math.round(this.canvases[i].width / this.pixelRatio) + 'px';
|
|
303
|
+
this.canvases[i].style.height = this.height + 'px';
|
|
304
|
+
}
|
|
263
305
|
}
|
|
264
306
|
|
|
265
307
|
drawSpectrogram(frequenciesData, my) {
|
|
@@ -268,25 +310,61 @@ export default class SpectrogramPlugin {
|
|
|
268
310
|
frequenciesData = [frequenciesData];
|
|
269
311
|
}
|
|
270
312
|
|
|
271
|
-
|
|
313
|
+
my.updateCanvasStyle();
|
|
314
|
+
|
|
315
|
+
//Stop canvases still being drawn
|
|
316
|
+
for (let i = 0; i < my.canvasesTimeouts.length; i++) {
|
|
317
|
+
clearTimeout(my.canvasesTimeouts[i]);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
const view = [my.scrollLeftTracker, my.scrollLeftTracker + my.wrapper.clientWidth];
|
|
321
|
+
|
|
322
|
+
for (let canvasNum = 0; canvasNum < my.canvases.length; canvasNum++) {
|
|
323
|
+
const canvasLeft = canvasNum * Math.floor(my.width / my.canvases.length / my.pixelRatio);
|
|
324
|
+
const canvasRight = (canvasNum + 1) * Math.floor(my.width / my.canvases.length / my.pixelRatio);
|
|
325
|
+
const canvasBound = [canvasLeft, canvasRight];
|
|
326
|
+
my.canvases[canvasNum].style['left'] = canvasLeft + 'px';
|
|
327
|
+
|
|
328
|
+
//Optimise drawing for the view
|
|
329
|
+
let priority = 0;
|
|
330
|
+
if (canvasBound[0] > view[1]) {
|
|
331
|
+
//Canvas is to the right of view window
|
|
332
|
+
let distance = canvasBound[0] - view[1];
|
|
333
|
+
priority = Math.ceil(distance / (view[1] - view[0]));
|
|
334
|
+
} else if (canvasBound[1] < view[0]) {
|
|
335
|
+
//Canvas is to the left of the view window
|
|
336
|
+
let distance = view[0] - canvasBound[1];
|
|
337
|
+
priority = Math.ceil(distance / (view[1] - view[0]));
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
//delay = 25ms * number of viewport widths away the canvas is
|
|
341
|
+
my.canvasesTimeouts[canvasNum] = setTimeout(my.drawToCanvas, 25 * priority, frequenciesData, my, canvasNum);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Draw spectrogram channel to a specific canvas
|
|
347
|
+
* @param {[Number, Number, Number]} frequenciesData spectrogram data in [channel, sample, freq] format
|
|
348
|
+
* @param {SpectrogramPlugin} my variable with 'this' in it
|
|
349
|
+
* @param {Number} canvasNum Canvas to draw to
|
|
350
|
+
*/
|
|
351
|
+
drawToCanvas(frequenciesData, my, canvasNum) {
|
|
272
352
|
const height = my.fftSamples / 2;
|
|
273
|
-
const width = my.width;
|
|
274
353
|
const freqFrom = my.buffer.sampleRate / 2;
|
|
275
354
|
const freqMin = my.frequencyMin;
|
|
276
355
|
const freqMax = my.frequencyMax;
|
|
277
356
|
|
|
278
|
-
|
|
279
|
-
return;
|
|
280
|
-
}
|
|
357
|
+
for (let channel = 0; channel < frequenciesData.length; channel++) {
|
|
281
358
|
|
|
282
|
-
|
|
283
|
-
const
|
|
284
|
-
const
|
|
359
|
+
//Get pixels from frequency data and apply to image
|
|
360
|
+
const relevantFreqs = frequenciesData[channel].slice(canvasNum * Math.round(frequenciesData[channel].length / my.canvases.length), (canvasNum + 1) * Math.round(frequenciesData[channel].length / my.canvases.length));
|
|
361
|
+
const pixels = my.resample(relevantFreqs);
|
|
362
|
+
const imageData = new ImageData(pixels.length, height);
|
|
285
363
|
|
|
286
364
|
for (let i = 0; i < pixels.length; i++) {
|
|
287
365
|
for (let j = 0; j < pixels[i].length; j++) {
|
|
288
366
|
const colorMap = my.colorMap[pixels[i][j]];
|
|
289
|
-
const redIndex = ((height - j) * width + i) * 4;
|
|
367
|
+
const redIndex = ((height - j) * imageData.width + i) * 4;
|
|
290
368
|
imageData.data[redIndex] = colorMap[0] * 255;
|
|
291
369
|
imageData.data[redIndex + 1] = colorMap[1] * 255;
|
|
292
370
|
imageData.data[redIndex + 2] = colorMap[2] * 255;
|
|
@@ -294,16 +372,20 @@ export default class SpectrogramPlugin {
|
|
|
294
372
|
}
|
|
295
373
|
}
|
|
296
374
|
|
|
297
|
-
//
|
|
298
|
-
createImageBitmap(imageData).then(renderer =>
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
375
|
+
//Draw image to canvas
|
|
376
|
+
createImageBitmap(imageData).then(renderer => {
|
|
377
|
+
if (my.canvases[canvasNum]) { //Check canvas still exists after creating image
|
|
378
|
+
my.canvases[canvasNum].getContext('2d').drawImage(renderer,
|
|
379
|
+
0, height * (1 - freqMax / freqFrom), // source x, y
|
|
380
|
+
imageData.width, height * (freqMax - freqMin) / freqFrom, // source width, height
|
|
381
|
+
0, height * channel, // destination x, y
|
|
382
|
+
my.canvases[canvasNum].width, height // destination width, height
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
});
|
|
306
386
|
}
|
|
387
|
+
//Drawing is finished
|
|
388
|
+
my.canvasesTimeouts[canvasNum] = null;
|
|
307
389
|
}
|
|
308
390
|
|
|
309
391
|
getFrequencies(callback) {
|
|
@@ -322,7 +404,7 @@ export default class SpectrogramPlugin {
|
|
|
322
404
|
|
|
323
405
|
let noverlap = this.noverlap;
|
|
324
406
|
if (!noverlap) {
|
|
325
|
-
const uniqueSamplesPerPx = buffer.length / this.
|
|
407
|
+
const uniqueSamplesPerPx = buffer.length / this.width;
|
|
326
408
|
noverlap = Math.max(0, Math.round(fftSamples - uniqueSamplesPerPx));
|
|
327
409
|
}
|
|
328
410
|
|
|
@@ -461,12 +543,13 @@ export default class SpectrogramPlugin {
|
|
|
461
543
|
|
|
462
544
|
updateScroll(e) {
|
|
463
545
|
if (this.wrapper) {
|
|
546
|
+
this.scrollLeftTracker = e.target.scrollLeft;
|
|
464
547
|
this.wrapper.scrollLeft = e.target.scrollLeft;
|
|
465
548
|
}
|
|
466
549
|
}
|
|
467
550
|
|
|
468
551
|
resample(oldMatrix) {
|
|
469
|
-
const columnsNumber =
|
|
552
|
+
const columnsNumber = oldMatrix.length;
|
|
470
553
|
const newMatrix = [];
|
|
471
554
|
|
|
472
555
|
const oldPiece = 1 / oldMatrix.length;
|
|
@@ -519,4 +602,12 @@ export default class SpectrogramPlugin {
|
|
|
519
602
|
|
|
520
603
|
return newMatrix;
|
|
521
604
|
}
|
|
605
|
+
|
|
606
|
+
stretchCanvases() {
|
|
607
|
+
for (let i = 0; i < this.canvases.length; i++) {
|
|
608
|
+
this.canvases[i].style.width = Math.round(this.drawer.width / this.canvases.length / this.pixelRatio) + 'px';
|
|
609
|
+
const canvasLeft = i * Math.floor(this.drawer.width / this.canvases.length / this.pixelRatio);
|
|
610
|
+
this.canvases[i].style['left'] = canvasLeft + 'px';
|
|
611
|
+
}
|
|
612
|
+
}
|
|
522
613
|
}
|
package/src/wavesurfer.js
CHANGED
|
@@ -1275,6 +1275,21 @@ export default class WaveSurfer extends util.Observer {
|
|
|
1275
1275
|
this.drawBuffer();
|
|
1276
1276
|
}
|
|
1277
1277
|
|
|
1278
|
+
/**
|
|
1279
|
+
* Calls getPeaks() and drawPeaks()
|
|
1280
|
+
* @param {WaveSurfer} wavesurfer the Wavesurfer to get/draw peaks from/to
|
|
1281
|
+
* @param {number} width The width of the area that should be drawn
|
|
1282
|
+
* @param {number} start The x-offset of the beginning of the area that
|
|
1283
|
+
* should be rendered
|
|
1284
|
+
* @param {number} end The x-offset of the end of the area that should be
|
|
1285
|
+
* rendered
|
|
1286
|
+
*/
|
|
1287
|
+
getAndDrawPeaks(wavesurfer, width, start, end) {
|
|
1288
|
+
let peaks;
|
|
1289
|
+
peaks = wavesurfer.backend.getPeaks(width, start, end);
|
|
1290
|
+
wavesurfer.drawer.drawPeaks(peaks, width, start, end);
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1278
1293
|
/**
|
|
1279
1294
|
* Get the correct peaks for current wave view-port and render wave
|
|
1280
1295
|
*
|
|
@@ -1356,6 +1371,24 @@ export default class WaveSurfer extends util.Observer {
|
|
|
1356
1371
|
this.fireEvent('zoom', pxPerSec);
|
|
1357
1372
|
}
|
|
1358
1373
|
|
|
1374
|
+
/**
|
|
1375
|
+
* Call this function while moving the zoom slider to stretch the canvases
|
|
1376
|
+
* of the wave without recalculating
|
|
1377
|
+
*
|
|
1378
|
+
* @param {Number} pxPerSec value returned from the zoom slider
|
|
1379
|
+
*/
|
|
1380
|
+
zooming(pxPerSec) {
|
|
1381
|
+
//Calculate the new width, this cannot be smaller than the parent container width
|
|
1382
|
+
let desiredWidth = Math.round(this.getDuration() * pxPerSec * this.params.pixelRatio);
|
|
1383
|
+
let parentWidth = this.drawer.getWidth();
|
|
1384
|
+
desiredWidth = Math.max(parentWidth, desiredWidth);
|
|
1385
|
+
|
|
1386
|
+
//Stretch canvases
|
|
1387
|
+
this.drawer.stretchCanvases(desiredWidth, this.backend.getPlayedPercents());
|
|
1388
|
+
|
|
1389
|
+
this.fireEvent('zoom', pxPerSec);
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1359
1392
|
/**
|
|
1360
1393
|
* Decode buffer and load
|
|
1361
1394
|
*
|