wavesurfer.js 6.5.1 → 7.0.0-alpha.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/.eslintrc.json +24 -0
- package/.prettierrc +8 -0
- package/README.md +26 -117
- package/dist/base-plugin.d.ts +10 -0
- package/dist/base-plugin.js +13 -0
- package/dist/decoder.d.ts +10 -0
- package/dist/decoder.js +43 -0
- package/dist/event-emitter.d.ts +11 -0
- package/dist/event-emitter.js +21 -0
- package/dist/fetcher.d.ts +4 -0
- package/dist/fetcher.js +17 -0
- package/dist/index.d.ts +92 -0
- package/dist/index.js +166 -0
- package/dist/player-webaudio.d.ts +8 -0
- package/dist/player-webaudio.js +31 -0
- package/dist/player.d.ts +16 -0
- package/dist/player.js +40 -0
- package/dist/plugins/regions.d.ts +48 -0
- package/dist/plugins/regions.js +183 -0
- package/dist/renderer.d.ts +34 -0
- package/dist/renderer.js +193 -0
- package/dist/timer.d.ts +10 -0
- package/dist/timer.js +17 -0
- package/examples/audio.ogg +0 -0
- package/examples/bars.js +19 -0
- package/examples/basic.js +8 -0
- package/examples/gradient.js +28 -0
- package/examples/regions.js +63 -0
- package/examples/video.js +19 -0
- package/examples/webaudio.js +14 -0
- package/package.json +19 -99
- package/src/base-plugin.ts +20 -0
- package/src/decoder.ts +41 -0
- package/src/event-emitter.ts +35 -0
- package/src/fetcher.ts +7 -0
- package/src/index.ts +252 -0
- package/src/player-webaudio.ts +34 -0
- package/src/player.ts +50 -0
- package/src/plugins/regions.ts +240 -0
- package/src/renderer.ts +250 -0
- package/src/timer.ts +27 -0
- package/tsconfig.json +105 -0
- package/tutorial/index.html +47 -0
- package/tutorial/src/editor.js +70 -0
- package/tutorial/src/init.js +66 -0
- package/tutorial/src/url.js +25 -0
- package/tutorial/style.css +211 -0
- package/yarn-error.log +1049 -0
- package/LICENSE +0 -29
- package/dist/plugin/wavesurfer.cursor.js +0 -418
- package/dist/plugin/wavesurfer.cursor.js.map +0 -1
- package/dist/plugin/wavesurfer.cursor.min.js +0 -7
- package/dist/plugin/wavesurfer.cursor.min.js.map +0 -1
- package/dist/plugin/wavesurfer.elan.js +0 -381
- package/dist/plugin/wavesurfer.elan.js.map +0 -1
- package/dist/plugin/wavesurfer.elan.min.js +0 -7
- package/dist/plugin/wavesurfer.elan.min.js.map +0 -1
- package/dist/plugin/wavesurfer.markers.js +0 -520
- package/dist/plugin/wavesurfer.markers.js.map +0 -1
- package/dist/plugin/wavesurfer.markers.min.js +0 -7
- package/dist/plugin/wavesurfer.markers.min.js.map +0 -1
- package/dist/plugin/wavesurfer.mediasession.js +0 -181
- package/dist/plugin/wavesurfer.mediasession.js.map +0 -1
- package/dist/plugin/wavesurfer.mediasession.min.js +0 -7
- package/dist/plugin/wavesurfer.mediasession.min.js.map +0 -1
- package/dist/plugin/wavesurfer.microphone.js +0 -466
- package/dist/plugin/wavesurfer.microphone.js.map +0 -1
- package/dist/plugin/wavesurfer.microphone.min.js +0 -7
- package/dist/plugin/wavesurfer.microphone.min.js.map +0 -1
- package/dist/plugin/wavesurfer.minimap.js +0 -440
- package/dist/plugin/wavesurfer.minimap.js.map +0 -1
- package/dist/plugin/wavesurfer.minimap.min.js +0 -7
- package/dist/plugin/wavesurfer.minimap.min.js.map +0 -1
- package/dist/plugin/wavesurfer.playhead.js +0 -300
- package/dist/plugin/wavesurfer.playhead.js.map +0 -1
- package/dist/plugin/wavesurfer.playhead.min.js +0 -7
- package/dist/plugin/wavesurfer.playhead.min.js.map +0 -1
- package/dist/plugin/wavesurfer.regions.js +0 -1335
- package/dist/plugin/wavesurfer.regions.js.map +0 -1
- package/dist/plugin/wavesurfer.regions.min.js +0 -7
- package/dist/plugin/wavesurfer.regions.min.js.map +0 -1
- package/dist/plugin/wavesurfer.spectrogram.js +0 -736
- package/dist/plugin/wavesurfer.spectrogram.js.map +0 -1
- package/dist/plugin/wavesurfer.spectrogram.min.js +0 -7
- package/dist/plugin/wavesurfer.spectrogram.min.js.map +0 -1
- package/dist/plugin/wavesurfer.timeline.js +0 -649
- package/dist/plugin/wavesurfer.timeline.js.map +0 -1
- package/dist/plugin/wavesurfer.timeline.min.js +0 -7
- package/dist/plugin/wavesurfer.timeline.min.js.map +0 -1
- package/dist/wavesurfer-html-init.js +0 -381
- package/dist/wavesurfer-html-init.js.map +0 -1
- package/dist/wavesurfer-html-init.min.js +0 -7
- package/dist/wavesurfer-html-init.min.js.map +0 -1
- package/dist/wavesurfer.js +0 -6145
- package/dist/wavesurfer.js.map +0 -1
- package/dist/wavesurfer.min.js +0 -7
- package/dist/wavesurfer.min.js.map +0 -1
- package/src/drawer.canvasentry.js +0 -427
- package/src/drawer.js +0 -413
- package/src/drawer.multicanvas.js +0 -617
- package/src/html-init.js +0 -241
- package/src/mediaelement-webaudio.js +0 -77
- package/src/mediaelement.js +0 -443
- package/src/peakcache.js +0 -127
- package/src/plugin/cursor/index.js +0 -350
- package/src/plugin/elan/index.js +0 -307
- package/src/plugin/markers/index.js +0 -436
- package/src/plugin/mediasession/index.js +0 -94
- package/src/plugin/microphone/index.js +0 -415
- package/src/plugin/minimap/index.js +0 -403
- package/src/plugin/playhead/index.js +0 -226
- package/src/plugin/regions/index.js +0 -478
- package/src/plugin/regions/region.js +0 -875
- package/src/plugin/spectrogram/fft.js +0 -222
- package/src/plugin/spectrogram/index.js +0 -522
- package/src/plugin/timeline/index.js +0 -600
- package/src/util/absMax.js +0 -16
- package/src/util/clamp.js +0 -11
- package/src/util/fetch.js +0 -222
- package/src/util/frame.js +0 -13
- package/src/util/get-id.js +0 -22
- package/src/util/index.js +0 -14
- package/src/util/max.js +0 -16
- package/src/util/min.js +0 -16
- package/src/util/observer.js +0 -144
- package/src/util/orientation.js +0 -98
- package/src/util/prevent-click.js +0 -19
- package/src/util/request-animation-frame.js +0 -15
- package/src/util/silence-mode.js +0 -42
- package/src/util/style.js +0 -16
- package/src/wavesurfer.js +0 -1797
- package/src/webaudio.js +0 -779
|
@@ -1,617 +0,0 @@
|
|
|
1
|
-
import Drawer from './drawer';
|
|
2
|
-
import * as util from './util';
|
|
3
|
-
import CanvasEntry from './drawer.canvasentry';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* MultiCanvas renderer for wavesurfer. Is currently the default and sole
|
|
7
|
-
* builtin renderer.
|
|
8
|
-
*
|
|
9
|
-
* A `MultiCanvas` consists of one or more `CanvasEntry` instances, depending
|
|
10
|
-
* on the zoom level.
|
|
11
|
-
*/
|
|
12
|
-
export default class MultiCanvas extends Drawer {
|
|
13
|
-
/**
|
|
14
|
-
* @param {HTMLElement} container The container node of the wavesurfer instance
|
|
15
|
-
* @param {WavesurferParams} params The wavesurfer initialisation options
|
|
16
|
-
*/
|
|
17
|
-
constructor(container, params) {
|
|
18
|
-
super(container, params);
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* @type {number}
|
|
22
|
-
*/
|
|
23
|
-
this.maxCanvasWidth = params.maxCanvasWidth;
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* @type {number}
|
|
27
|
-
*/
|
|
28
|
-
this.maxCanvasElementWidth = Math.round(
|
|
29
|
-
params.maxCanvasWidth / params.pixelRatio
|
|
30
|
-
);
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Whether or not the progress wave is rendered. If the `waveColor`
|
|
34
|
-
* and `progressColor` are the same color it is not.
|
|
35
|
-
*
|
|
36
|
-
* @type {boolean}
|
|
37
|
-
*/
|
|
38
|
-
this.hasProgressCanvas = params.waveColor != params.progressColor;
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* @type {number}
|
|
42
|
-
*/
|
|
43
|
-
this.halfPixel = 0.5 / params.pixelRatio;
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* List of `CanvasEntry` instances.
|
|
47
|
-
*
|
|
48
|
-
* @type {Array}
|
|
49
|
-
*/
|
|
50
|
-
this.canvases = [];
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* @type {HTMLElement}
|
|
54
|
-
*/
|
|
55
|
-
this.progressWave = null;
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Class used to generate entries.
|
|
59
|
-
*
|
|
60
|
-
* @type {function}
|
|
61
|
-
*/
|
|
62
|
-
this.EntryClass = CanvasEntry;
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Canvas 2d context attributes.
|
|
66
|
-
*
|
|
67
|
-
* @type {object}
|
|
68
|
-
*/
|
|
69
|
-
this.canvasContextAttributes = params.drawingContextAttributes;
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Overlap added between entries to prevent vertical white stripes
|
|
73
|
-
* between `canvas` elements.
|
|
74
|
-
*
|
|
75
|
-
* @type {number}
|
|
76
|
-
*/
|
|
77
|
-
this.overlap = 2 * Math.ceil(params.pixelRatio / 2);
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* The radius of the wave bars. Makes bars rounded
|
|
81
|
-
*
|
|
82
|
-
* @type {number}
|
|
83
|
-
*/
|
|
84
|
-
this.barRadius = params.barRadius || 0;
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Whether to render the waveform vertically. Defaults to false.
|
|
88
|
-
*
|
|
89
|
-
* @type {boolean}
|
|
90
|
-
*/
|
|
91
|
-
this.vertical = params.vertical;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Initialize the drawer
|
|
96
|
-
*/
|
|
97
|
-
init() {
|
|
98
|
-
this.createWrapper();
|
|
99
|
-
this.createElements();
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Create the canvas elements and style them
|
|
104
|
-
*
|
|
105
|
-
*/
|
|
106
|
-
createElements() {
|
|
107
|
-
this.progressWave = util.withOrientation(
|
|
108
|
-
this.wrapper.appendChild(document.createElement('wave')),
|
|
109
|
-
this.params.vertical
|
|
110
|
-
);
|
|
111
|
-
this.style(this.progressWave, {
|
|
112
|
-
position: 'absolute',
|
|
113
|
-
zIndex: 3,
|
|
114
|
-
left: 0,
|
|
115
|
-
top: 0,
|
|
116
|
-
bottom: 0,
|
|
117
|
-
overflow: 'hidden',
|
|
118
|
-
width: '0',
|
|
119
|
-
display: 'none',
|
|
120
|
-
boxSizing: 'border-box',
|
|
121
|
-
borderRightStyle: 'solid',
|
|
122
|
-
pointerEvents: 'none'
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
this.addCanvas();
|
|
126
|
-
this.updateCursor();
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Update cursor style
|
|
131
|
-
*/
|
|
132
|
-
updateCursor() {
|
|
133
|
-
this.style(this.progressWave, {
|
|
134
|
-
borderRightWidth: this.params.cursorWidth + 'px',
|
|
135
|
-
borderRightColor: this.params.cursorColor
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Adjust to the updated size by adding or removing canvases
|
|
141
|
-
*/
|
|
142
|
-
updateSize() {
|
|
143
|
-
const totalWidth = Math.round(this.width / this.params.pixelRatio);
|
|
144
|
-
const requiredCanvases = Math.ceil(
|
|
145
|
-
totalWidth / (this.maxCanvasElementWidth + this.overlap)
|
|
146
|
-
);
|
|
147
|
-
|
|
148
|
-
// add required canvases
|
|
149
|
-
while (this.canvases.length < requiredCanvases) {
|
|
150
|
-
this.addCanvas();
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// remove older existing canvases, if any
|
|
154
|
-
while (this.canvases.length > requiredCanvases) {
|
|
155
|
-
this.removeCanvas();
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
let canvasWidth = this.maxCanvasWidth + this.overlap;
|
|
159
|
-
const lastCanvas = this.canvases.length - 1;
|
|
160
|
-
this.canvases.forEach((entry, i) => {
|
|
161
|
-
if (i == lastCanvas) {
|
|
162
|
-
canvasWidth = this.width - this.maxCanvasWidth * lastCanvas;
|
|
163
|
-
}
|
|
164
|
-
this.updateDimensions(entry, canvasWidth, this.height);
|
|
165
|
-
|
|
166
|
-
entry.clearWave();
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* Add a canvas to the canvas list
|
|
172
|
-
*
|
|
173
|
-
*/
|
|
174
|
-
addCanvas() {
|
|
175
|
-
const entry = new this.EntryClass();
|
|
176
|
-
entry.canvasContextAttributes = this.canvasContextAttributes;
|
|
177
|
-
entry.hasProgressCanvas = this.hasProgressCanvas;
|
|
178
|
-
entry.halfPixel = this.halfPixel;
|
|
179
|
-
const leftOffset = this.maxCanvasElementWidth * this.canvases.length;
|
|
180
|
-
|
|
181
|
-
// wave
|
|
182
|
-
let wave = util.withOrientation(
|
|
183
|
-
this.wrapper.appendChild(document.createElement('canvas')),
|
|
184
|
-
this.params.vertical
|
|
185
|
-
);
|
|
186
|
-
this.style(wave, {
|
|
187
|
-
position: 'absolute',
|
|
188
|
-
zIndex: 2,
|
|
189
|
-
left: leftOffset + 'px',
|
|
190
|
-
top: 0,
|
|
191
|
-
bottom: 0,
|
|
192
|
-
height: '100%',
|
|
193
|
-
pointerEvents: 'none'
|
|
194
|
-
});
|
|
195
|
-
entry.initWave(wave);
|
|
196
|
-
|
|
197
|
-
// progress
|
|
198
|
-
if (this.hasProgressCanvas) {
|
|
199
|
-
let progress = util.withOrientation(
|
|
200
|
-
this.progressWave.appendChild(document.createElement('canvas')),
|
|
201
|
-
this.params.vertical
|
|
202
|
-
);
|
|
203
|
-
this.style(progress, {
|
|
204
|
-
position: 'absolute',
|
|
205
|
-
left: leftOffset + 'px',
|
|
206
|
-
top: 0,
|
|
207
|
-
bottom: 0,
|
|
208
|
-
height: '100%'
|
|
209
|
-
});
|
|
210
|
-
entry.initProgress(progress);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
this.canvases.push(entry);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* Pop single canvas from the list
|
|
218
|
-
*
|
|
219
|
-
*/
|
|
220
|
-
removeCanvas() {
|
|
221
|
-
let lastEntry = this.canvases[this.canvases.length - 1];
|
|
222
|
-
|
|
223
|
-
// wave
|
|
224
|
-
lastEntry.wave.parentElement.removeChild(lastEntry.wave.domElement);
|
|
225
|
-
|
|
226
|
-
// progress
|
|
227
|
-
if (this.hasProgressCanvas) {
|
|
228
|
-
lastEntry.progress.parentElement.removeChild(lastEntry.progress.domElement);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
// cleanup
|
|
232
|
-
if (lastEntry) {
|
|
233
|
-
lastEntry.destroy();
|
|
234
|
-
lastEntry = null;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
this.canvases.pop();
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
/**
|
|
241
|
-
* Update the dimensions of a canvas element
|
|
242
|
-
*
|
|
243
|
-
* @param {CanvasEntry} entry Target entry
|
|
244
|
-
* @param {number} width The new width of the element
|
|
245
|
-
* @param {number} height The new height of the element
|
|
246
|
-
*/
|
|
247
|
-
updateDimensions(entry, width, height) {
|
|
248
|
-
const elementWidth = Math.round(width / this.params.pixelRatio);
|
|
249
|
-
const totalWidth = Math.round(this.width / this.params.pixelRatio);
|
|
250
|
-
|
|
251
|
-
// update canvas dimensions
|
|
252
|
-
entry.updateDimensions(elementWidth, totalWidth, width, height);
|
|
253
|
-
|
|
254
|
-
// style element
|
|
255
|
-
this.style(this.progressWave, { display: 'block' });
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
* Clear the whole multi-canvas
|
|
260
|
-
*/
|
|
261
|
-
clearWave() {
|
|
262
|
-
util.frame(() => {
|
|
263
|
-
this.canvases.forEach(entry => entry.clearWave());
|
|
264
|
-
})();
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
/**
|
|
268
|
-
* Draw a waveform with bars
|
|
269
|
-
*
|
|
270
|
-
* @param {number[]|Number.<Array[]>} peaks Can also be an array of arrays
|
|
271
|
-
* for split channel rendering
|
|
272
|
-
* @param {number} channelIndex The index of the current channel. Normally
|
|
273
|
-
* should be 0. Must be an integer.
|
|
274
|
-
* @param {number} start The x-offset of the beginning of the area that
|
|
275
|
-
* should be rendered
|
|
276
|
-
* @param {number} end The x-offset of the end of the area that should be
|
|
277
|
-
* rendered
|
|
278
|
-
* @returns {void}
|
|
279
|
-
*/
|
|
280
|
-
drawBars(peaks, channelIndex, start, end) {
|
|
281
|
-
return this.prepareDraw(
|
|
282
|
-
peaks,
|
|
283
|
-
channelIndex,
|
|
284
|
-
start,
|
|
285
|
-
end,
|
|
286
|
-
({ absmax, hasMinVals, height, offsetY, halfH, peaks, channelIndex: ch }) => {
|
|
287
|
-
// if drawBars was called within ws.empty we don't pass a start and
|
|
288
|
-
// don't want anything to happen
|
|
289
|
-
if (start === undefined) {
|
|
290
|
-
return;
|
|
291
|
-
}
|
|
292
|
-
// Skip every other value if there are negatives.
|
|
293
|
-
const peakIndexScale = hasMinVals ? 2 : 1;
|
|
294
|
-
const length = peaks.length / peakIndexScale;
|
|
295
|
-
const bar = this.params.barWidth * this.params.pixelRatio;
|
|
296
|
-
const gap =
|
|
297
|
-
this.params.barGap === null
|
|
298
|
-
? Math.max(this.params.pixelRatio, ~~(bar / 2))
|
|
299
|
-
: Math.max(
|
|
300
|
-
this.params.pixelRatio,
|
|
301
|
-
this.params.barGap * this.params.pixelRatio
|
|
302
|
-
);
|
|
303
|
-
const step = bar + gap;
|
|
304
|
-
|
|
305
|
-
const scale = length / this.width;
|
|
306
|
-
const first = start;
|
|
307
|
-
const last = end;
|
|
308
|
-
let peakIndex = first;
|
|
309
|
-
for (peakIndex; peakIndex < last; peakIndex += step) {
|
|
310
|
-
|
|
311
|
-
// search for the highest peak in the range this bar falls into
|
|
312
|
-
let peak = 0;
|
|
313
|
-
let peakIndexRange = Math.floor(peakIndex * scale) * peakIndexScale; // start index
|
|
314
|
-
const peakIndexEnd = Math.floor((peakIndex + step) * scale) * peakIndexScale;
|
|
315
|
-
do { // do..while makes sure at least one peak is always evaluated
|
|
316
|
-
const newPeak = Math.abs(peaks[peakIndexRange]); // for arrays starting with negative values
|
|
317
|
-
if (newPeak > peak) {
|
|
318
|
-
peak = newPeak; // higher
|
|
319
|
-
}
|
|
320
|
-
peakIndexRange += peakIndexScale; // skip every other value for negatives
|
|
321
|
-
} while (peakIndexRange < peakIndexEnd);
|
|
322
|
-
|
|
323
|
-
// calculate the height of this bar according to the highest peak found
|
|
324
|
-
let h = Math.round((peak / absmax) * halfH);
|
|
325
|
-
|
|
326
|
-
// raise the bar height to the specified minimum height
|
|
327
|
-
// Math.max is used to replace any value smaller than barMinHeight (not just 0) with barMinHeight
|
|
328
|
-
if (this.params.barMinHeight) {
|
|
329
|
-
h = Math.max(h, this.params.barMinHeight);
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
this.fillRect(
|
|
333
|
-
peakIndex + this.halfPixel,
|
|
334
|
-
halfH - h + offsetY,
|
|
335
|
-
bar + this.halfPixel,
|
|
336
|
-
h * 2,
|
|
337
|
-
this.barRadius,
|
|
338
|
-
ch
|
|
339
|
-
);
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
);
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
/**
|
|
346
|
-
* Draw a waveform
|
|
347
|
-
*
|
|
348
|
-
* @param {number[]|Number.<Array[]>} peaks Can also be an array of arrays
|
|
349
|
-
* for split channel rendering
|
|
350
|
-
* @param {number} channelIndex The index of the current channel. Normally
|
|
351
|
-
* should be 0
|
|
352
|
-
* @param {number?} start The x-offset of the beginning of the area that
|
|
353
|
-
* should be rendered (If this isn't set only a flat line is rendered)
|
|
354
|
-
* @param {number?} end The x-offset of the end of the area that should be
|
|
355
|
-
* rendered
|
|
356
|
-
* @returns {void}
|
|
357
|
-
*/
|
|
358
|
-
drawWave(peaks, channelIndex, start, end) {
|
|
359
|
-
return this.prepareDraw(
|
|
360
|
-
peaks,
|
|
361
|
-
channelIndex,
|
|
362
|
-
start,
|
|
363
|
-
end,
|
|
364
|
-
({ absmax, hasMinVals, height, offsetY, halfH, peaks, channelIndex }) => {
|
|
365
|
-
if (!hasMinVals) {
|
|
366
|
-
const reflectedPeaks = [];
|
|
367
|
-
const len = peaks.length;
|
|
368
|
-
let i = 0;
|
|
369
|
-
for (i; i < len; i++) {
|
|
370
|
-
reflectedPeaks[2 * i] = peaks[i];
|
|
371
|
-
reflectedPeaks[2 * i + 1] = -peaks[i];
|
|
372
|
-
}
|
|
373
|
-
peaks = reflectedPeaks;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
// if drawWave was called within ws.empty we don't pass a start and
|
|
377
|
-
// end and simply want a flat line
|
|
378
|
-
if (start !== undefined) {
|
|
379
|
-
this.drawLine(peaks, absmax, halfH, offsetY, start, end, channelIndex);
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
// always draw a median line
|
|
383
|
-
this.fillRect(
|
|
384
|
-
0,
|
|
385
|
-
halfH + offsetY - this.halfPixel,
|
|
386
|
-
this.width,
|
|
387
|
-
this.halfPixel,
|
|
388
|
-
this.barRadius,
|
|
389
|
-
channelIndex
|
|
390
|
-
);
|
|
391
|
-
}
|
|
392
|
-
);
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
/**
|
|
396
|
-
* Tell the canvas entries to render their portion of the waveform
|
|
397
|
-
*
|
|
398
|
-
* @param {number[]} peaks Peaks data
|
|
399
|
-
* @param {number} absmax Maximum peak value (absolute)
|
|
400
|
-
* @param {number} halfH Half the height of the waveform
|
|
401
|
-
* @param {number} offsetY Offset to the top
|
|
402
|
-
* @param {number} start The x-offset of the beginning of the area that
|
|
403
|
-
* should be rendered
|
|
404
|
-
* @param {number} end The x-offset of the end of the area that
|
|
405
|
-
* should be rendered
|
|
406
|
-
* @param {channelIndex} channelIndex The channel index of the line drawn
|
|
407
|
-
*/
|
|
408
|
-
drawLine(peaks, absmax, halfH, offsetY, start, end, channelIndex) {
|
|
409
|
-
const { waveColor, progressColor } = this.params.splitChannelsOptions.channelColors[channelIndex] || {};
|
|
410
|
-
this.canvases.forEach((entry, i) => {
|
|
411
|
-
this.setFillStyles(entry, waveColor, progressColor);
|
|
412
|
-
this.applyCanvasTransforms(entry, this.params.vertical);
|
|
413
|
-
entry.drawLines(peaks, absmax, halfH, offsetY, start, end);
|
|
414
|
-
});
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
/**
|
|
418
|
-
* Draw a rectangle on the multi-canvas
|
|
419
|
-
*
|
|
420
|
-
* @param {number} x X-position of the rectangle
|
|
421
|
-
* @param {number} y Y-position of the rectangle
|
|
422
|
-
* @param {number} width Width of the rectangle
|
|
423
|
-
* @param {number} height Height of the rectangle
|
|
424
|
-
* @param {number} radius Radius of the rectangle
|
|
425
|
-
* @param {channelIndex} channelIndex The channel index of the bar drawn
|
|
426
|
-
*/
|
|
427
|
-
fillRect(x, y, width, height, radius, channelIndex) {
|
|
428
|
-
const startCanvas = Math.floor(x / this.maxCanvasWidth);
|
|
429
|
-
const endCanvas = Math.min(
|
|
430
|
-
Math.ceil((x + width) / this.maxCanvasWidth) + 1,
|
|
431
|
-
this.canvases.length
|
|
432
|
-
);
|
|
433
|
-
let i = startCanvas;
|
|
434
|
-
for (i; i < endCanvas; i++) {
|
|
435
|
-
const entry = this.canvases[i];
|
|
436
|
-
const leftOffset = i * this.maxCanvasWidth;
|
|
437
|
-
|
|
438
|
-
const intersection = {
|
|
439
|
-
x1: Math.max(x, i * this.maxCanvasWidth),
|
|
440
|
-
y1: y,
|
|
441
|
-
x2: Math.min(
|
|
442
|
-
x + width,
|
|
443
|
-
i * this.maxCanvasWidth + entry.wave.width
|
|
444
|
-
),
|
|
445
|
-
y2: y + height
|
|
446
|
-
};
|
|
447
|
-
|
|
448
|
-
if (intersection.x1 < intersection.x2) {
|
|
449
|
-
const { waveColor, progressColor } = this.params.splitChannelsOptions.channelColors[channelIndex] || {};
|
|
450
|
-
this.setFillStyles(entry, waveColor, progressColor);
|
|
451
|
-
this.applyCanvasTransforms(entry, this.params.vertical);
|
|
452
|
-
|
|
453
|
-
entry.fillRects(
|
|
454
|
-
intersection.x1 - leftOffset,
|
|
455
|
-
intersection.y1,
|
|
456
|
-
intersection.x2 - intersection.x1,
|
|
457
|
-
intersection.y2 - intersection.y1,
|
|
458
|
-
radius
|
|
459
|
-
);
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
/**
|
|
465
|
-
* Returns whether to hide the channel from being drawn based on params.
|
|
466
|
-
*
|
|
467
|
-
* @param {number} channelIndex The index of the current channel.
|
|
468
|
-
* @returns {bool} True to hide the channel, false to draw.
|
|
469
|
-
*/
|
|
470
|
-
hideChannel(channelIndex) {
|
|
471
|
-
return this.params.splitChannels && this.params.splitChannelsOptions.filterChannels.includes(channelIndex);
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
/**
|
|
475
|
-
* Performs preparation tasks and calculations which are shared by `drawBars`
|
|
476
|
-
* and `drawWave`
|
|
477
|
-
*
|
|
478
|
-
* @param {number[]|Number.<Array[]>} peaks Can also be an array of arrays for
|
|
479
|
-
* split channel rendering
|
|
480
|
-
* @param {number} channelIndex The index of the current channel. Normally
|
|
481
|
-
* should be 0
|
|
482
|
-
* @param {number?} start The x-offset of the beginning of the area that
|
|
483
|
-
* should be rendered. If this isn't set only a flat line is rendered
|
|
484
|
-
* @param {number?} end The x-offset of the end of the area that should be
|
|
485
|
-
* rendered
|
|
486
|
-
* @param {function} fn The render function to call, e.g. `drawWave`
|
|
487
|
-
* @param {number} drawIndex The index of the current channel after filtering.
|
|
488
|
-
* @param {number?} normalizedMax Maximum modulation value across channels for use with relativeNormalization. Ignored when undefined
|
|
489
|
-
* @returns {void}
|
|
490
|
-
*/
|
|
491
|
-
prepareDraw(peaks, channelIndex, start, end, fn, drawIndex, normalizedMax) {
|
|
492
|
-
return util.frame(() => {
|
|
493
|
-
// Split channels and call this function with the channelIndex set
|
|
494
|
-
if (peaks[0] instanceof Array) {
|
|
495
|
-
const channels = peaks;
|
|
496
|
-
|
|
497
|
-
if (this.params.splitChannels) {
|
|
498
|
-
const filteredChannels = channels.filter((c, i) => !this.hideChannel(i));
|
|
499
|
-
if (!this.params.splitChannelsOptions.overlay) {
|
|
500
|
-
this.setHeight(
|
|
501
|
-
Math.max(filteredChannels.length, 1) *
|
|
502
|
-
this.params.height *
|
|
503
|
-
this.params.pixelRatio
|
|
504
|
-
);
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
let overallAbsMax;
|
|
508
|
-
if (this.params.splitChannelsOptions && this.params.splitChannelsOptions.relativeNormalization) {
|
|
509
|
-
// calculate maximum peak across channels to use for normalization
|
|
510
|
-
overallAbsMax = util.max(channels.map((channelPeaks => util.absMax(channelPeaks))));
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
return channels.forEach((channelPeaks, i) =>
|
|
515
|
-
this.prepareDraw(channelPeaks, i, start, end, fn, filteredChannels.indexOf(channelPeaks), overallAbsMax)
|
|
516
|
-
);
|
|
517
|
-
}
|
|
518
|
-
peaks = channels[0];
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
// Return and do not draw channel peaks if hidden.
|
|
522
|
-
if (this.hideChannel(channelIndex)) {
|
|
523
|
-
return;
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
// calculate maximum modulation value, either from the barHeight
|
|
527
|
-
// parameter or if normalize=true from the largest value in the peak
|
|
528
|
-
// set
|
|
529
|
-
let absmax = 1 / this.params.barHeight;
|
|
530
|
-
if (this.params.normalize) {
|
|
531
|
-
absmax = normalizedMax === undefined ? util.absMax(peaks) : normalizedMax;
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
// Bar wave draws the bottom only as a reflection of the top,
|
|
535
|
-
// so we don't need negative values
|
|
536
|
-
const hasMinVals = [].some.call(peaks, val => val < 0);
|
|
537
|
-
const height = this.params.height * this.params.pixelRatio;
|
|
538
|
-
const halfH = height / 2;
|
|
539
|
-
|
|
540
|
-
let offsetY = height * drawIndex || 0;
|
|
541
|
-
|
|
542
|
-
// Override offsetY if overlay is true
|
|
543
|
-
if (this.params.splitChannelsOptions && this.params.splitChannelsOptions.overlay) {
|
|
544
|
-
offsetY = 0;
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
return fn({
|
|
548
|
-
absmax: absmax,
|
|
549
|
-
hasMinVals: hasMinVals,
|
|
550
|
-
height: height,
|
|
551
|
-
offsetY: offsetY,
|
|
552
|
-
halfH: halfH,
|
|
553
|
-
peaks: peaks,
|
|
554
|
-
channelIndex: channelIndex
|
|
555
|
-
});
|
|
556
|
-
})();
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
/**
|
|
560
|
-
* Set the fill styles for a certain entry (wave and progress)
|
|
561
|
-
*
|
|
562
|
-
* @param {CanvasEntry} entry Target entry
|
|
563
|
-
* @param {string} waveColor Wave color to draw this entry
|
|
564
|
-
* @param {string} progressColor Progress color to draw this entry
|
|
565
|
-
*/
|
|
566
|
-
setFillStyles(entry, waveColor = this.params.waveColor, progressColor = this.params.progressColor) {
|
|
567
|
-
entry.setFillStyles(waveColor, progressColor);
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
/**
|
|
571
|
-
* Set the canvas transforms for a certain entry (wave and progress)
|
|
572
|
-
*
|
|
573
|
-
* @param {CanvasEntry} entry Target entry
|
|
574
|
-
* @param {boolean} vertical Whether to render the waveform vertically
|
|
575
|
-
*/
|
|
576
|
-
applyCanvasTransforms(entry, vertical = false) {
|
|
577
|
-
entry.applyCanvasTransforms(vertical);
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
/**
|
|
581
|
-
* Return image data of the multi-canvas
|
|
582
|
-
*
|
|
583
|
-
* When using a `type` of `'blob'`, this will return a `Promise`.
|
|
584
|
-
*
|
|
585
|
-
* @param {string} format='image/png' An optional value of a format type.
|
|
586
|
-
* @param {number} quality=0.92 An optional value between 0 and 1.
|
|
587
|
-
* @param {string} type='dataURL' Either 'dataURL' or 'blob'.
|
|
588
|
-
* @return {string|string[]|Promise} When using the default `'dataURL'`
|
|
589
|
-
* `type` this returns a single data URL or an array of data URLs,
|
|
590
|
-
* one for each canvas. When using the `'blob'` `type` this returns a
|
|
591
|
-
* `Promise` that resolves with an array of `Blob` instances, one for each
|
|
592
|
-
* canvas.
|
|
593
|
-
*/
|
|
594
|
-
getImage(format, quality, type) {
|
|
595
|
-
if (type === 'blob') {
|
|
596
|
-
return Promise.all(
|
|
597
|
-
this.canvases.map(entry => {
|
|
598
|
-
return entry.getImage(format, quality, type);
|
|
599
|
-
})
|
|
600
|
-
);
|
|
601
|
-
} else if (type === 'dataURL') {
|
|
602
|
-
let images = this.canvases.map(entry =>
|
|
603
|
-
entry.getImage(format, quality, type)
|
|
604
|
-
);
|
|
605
|
-
return images.length > 1 ? images : images[0];
|
|
606
|
-
}
|
|
607
|
-
}
|
|
608
|
-
|
|
609
|
-
/**
|
|
610
|
-
* Render the new progress
|
|
611
|
-
*
|
|
612
|
-
* @param {number} position X-offset of progress position in pixels
|
|
613
|
-
*/
|
|
614
|
-
updateProgress(position) {
|
|
615
|
-
this.style(this.progressWave, { width: position + 'px' });
|
|
616
|
-
}
|
|
617
|
-
}
|