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.
- 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
package/src/mediaelement.js
DELETED
|
@@ -1,443 +0,0 @@
|
|
|
1
|
-
import WebAudio from './webaudio';
|
|
2
|
-
import * as util from './util';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* MediaElement backend
|
|
6
|
-
*/
|
|
7
|
-
export default class MediaElement extends WebAudio {
|
|
8
|
-
/**
|
|
9
|
-
* Construct the backend
|
|
10
|
-
*
|
|
11
|
-
* @param {WavesurferParams} params Wavesurfer parameters
|
|
12
|
-
*/
|
|
13
|
-
constructor(params) {
|
|
14
|
-
super(params);
|
|
15
|
-
/** @private */
|
|
16
|
-
this.params = params;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Initially a dummy media element to catch errors. Once `_load` is
|
|
20
|
-
* called, this will contain the actual `HTMLMediaElement`.
|
|
21
|
-
* @private
|
|
22
|
-
*/
|
|
23
|
-
this.media = {
|
|
24
|
-
currentTime: 0,
|
|
25
|
-
duration: 0,
|
|
26
|
-
paused: true,
|
|
27
|
-
playbackRate: 1,
|
|
28
|
-
play() {},
|
|
29
|
-
pause() {},
|
|
30
|
-
volume: 0
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
/** @private */
|
|
34
|
-
this.mediaType = params.mediaType.toLowerCase();
|
|
35
|
-
/** @private */
|
|
36
|
-
this.elementPosition = params.elementPosition;
|
|
37
|
-
/** @private */
|
|
38
|
-
this.peaks = null;
|
|
39
|
-
/** @private */
|
|
40
|
-
this.playbackRate = 1;
|
|
41
|
-
/** @private */
|
|
42
|
-
this.volume = 1;
|
|
43
|
-
/** @private */
|
|
44
|
-
this.isMuted = false;
|
|
45
|
-
/** @private */
|
|
46
|
-
this.buffer = null;
|
|
47
|
-
/** @private */
|
|
48
|
-
this.onPlayEnd = null;
|
|
49
|
-
/** @private */
|
|
50
|
-
this.mediaListeners = {};
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Initialise the backend, called in `wavesurfer.createBackend()`
|
|
55
|
-
*/
|
|
56
|
-
init() {
|
|
57
|
-
this.setPlaybackRate(this.params.audioRate);
|
|
58
|
-
this.createTimer();
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Attach event listeners to media element.
|
|
63
|
-
*/
|
|
64
|
-
_setupMediaListeners() {
|
|
65
|
-
this.mediaListeners.error = () => {
|
|
66
|
-
this.fireEvent('error', 'Error loading media element');
|
|
67
|
-
};
|
|
68
|
-
this.mediaListeners.waiting = () => {
|
|
69
|
-
this.fireEvent('waiting');
|
|
70
|
-
};
|
|
71
|
-
this.mediaListeners.canplay = () => {
|
|
72
|
-
this.fireEvent('canplay');
|
|
73
|
-
};
|
|
74
|
-
this.mediaListeners.ended = () => {
|
|
75
|
-
this.fireEvent('finish');
|
|
76
|
-
};
|
|
77
|
-
// listen to and relay play, pause and seeked events to enable
|
|
78
|
-
// playback control from the external media element
|
|
79
|
-
this.mediaListeners.play = () => {
|
|
80
|
-
this.fireEvent('play');
|
|
81
|
-
};
|
|
82
|
-
this.mediaListeners.pause = () => {
|
|
83
|
-
this.fireEvent('pause');
|
|
84
|
-
};
|
|
85
|
-
this.mediaListeners.seeked = event => {
|
|
86
|
-
this.fireEvent('seek');
|
|
87
|
-
};
|
|
88
|
-
this.mediaListeners.volumechange = event => {
|
|
89
|
-
this.isMuted = this.media.muted;
|
|
90
|
-
if (this.isMuted) {
|
|
91
|
-
this.volume = 0;
|
|
92
|
-
} else {
|
|
93
|
-
this.volume = this.media.volume;
|
|
94
|
-
}
|
|
95
|
-
this.fireEvent('volume');
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
// reset event listeners
|
|
99
|
-
Object.keys(this.mediaListeners).forEach(id => {
|
|
100
|
-
this.media.removeEventListener(id, this.mediaListeners[id]);
|
|
101
|
-
this.media.addEventListener(id, this.mediaListeners[id]);
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Create a timer to provide a more precise `audioprocess` event.
|
|
107
|
-
*/
|
|
108
|
-
createTimer() {
|
|
109
|
-
const onAudioProcess = () => {
|
|
110
|
-
if (this.isPaused()) {
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
this.fireEvent('audioprocess', this.getCurrentTime());
|
|
114
|
-
|
|
115
|
-
// Call again in the next frame
|
|
116
|
-
util.frame(onAudioProcess)();
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
this.on('play', onAudioProcess);
|
|
120
|
-
|
|
121
|
-
// Update the progress one more time to prevent it from being stuck in
|
|
122
|
-
// case of lower framerates
|
|
123
|
-
this.on('pause', () => {
|
|
124
|
-
this.fireEvent('audioprocess', this.getCurrentTime());
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Create media element with url as its source,
|
|
130
|
-
* and append to container element.
|
|
131
|
-
*
|
|
132
|
-
* @param {string} url Path to media file
|
|
133
|
-
* @param {HTMLElement} container HTML element
|
|
134
|
-
* @param {number[]|Number.<Array[]>} peaks Array of peak data
|
|
135
|
-
* @param {string} preload HTML 5 preload attribute value
|
|
136
|
-
* @throws Will throw an error if the `url` argument is not a valid media
|
|
137
|
-
* element.
|
|
138
|
-
*/
|
|
139
|
-
load(url, container, peaks, preload) {
|
|
140
|
-
const media = document.createElement(this.mediaType);
|
|
141
|
-
media.controls = this.params.mediaControls;
|
|
142
|
-
media.autoplay = this.params.autoplay || false;
|
|
143
|
-
media.preload = preload == null ? 'auto' : preload;
|
|
144
|
-
media.src = url;
|
|
145
|
-
media.style.width = '100%';
|
|
146
|
-
|
|
147
|
-
const prevMedia = container.querySelector(this.mediaType);
|
|
148
|
-
if (prevMedia) {
|
|
149
|
-
container.removeChild(prevMedia);
|
|
150
|
-
}
|
|
151
|
-
container.appendChild(media);
|
|
152
|
-
|
|
153
|
-
this._load(media, peaks, preload);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Load existing media element.
|
|
158
|
-
*
|
|
159
|
-
* @param {HTMLMediaElement} elt HTML5 Audio or Video element
|
|
160
|
-
* @param {number[]|Number.<Array[]>} peaks Array of peak data
|
|
161
|
-
*/
|
|
162
|
-
loadElt(elt, peaks) {
|
|
163
|
-
elt.controls = this.params.mediaControls;
|
|
164
|
-
elt.autoplay = this.params.autoplay || false;
|
|
165
|
-
|
|
166
|
-
this._load(elt, peaks, elt.preload);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* Method called by both `load` (from url)
|
|
171
|
-
* and `loadElt` (existing media element) methods.
|
|
172
|
-
*
|
|
173
|
-
* @param {HTMLMediaElement} media HTML5 Audio or Video element
|
|
174
|
-
* @param {number[]|Number.<Array[]>} peaks Array of peak data
|
|
175
|
-
* @param {string} preload HTML 5 preload attribute value
|
|
176
|
-
* @throws Will throw an error if the `media` argument is not a valid media
|
|
177
|
-
* element.
|
|
178
|
-
* @private
|
|
179
|
-
*/
|
|
180
|
-
_load(media, peaks, preload) {
|
|
181
|
-
// verify media element is valid
|
|
182
|
-
if (
|
|
183
|
-
!(media instanceof HTMLMediaElement) ||
|
|
184
|
-
typeof media.addEventListener === 'undefined'
|
|
185
|
-
) {
|
|
186
|
-
throw new Error('media parameter is not a valid media element');
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// load must be called manually on iOS, otherwise peaks won't draw
|
|
190
|
-
// until a user interaction triggers load --> 'ready' event
|
|
191
|
-
//
|
|
192
|
-
// note that we avoid calling media.load here when given peaks and preload == 'none'
|
|
193
|
-
// as this almost always triggers some browser fetch of the media.
|
|
194
|
-
if (typeof media.load == 'function' && !(peaks && preload == 'none')) {
|
|
195
|
-
// Resets the media element and restarts the media resource. Any
|
|
196
|
-
// pending events are discarded. How much media data is fetched is
|
|
197
|
-
// still affected by the preload attribute.
|
|
198
|
-
media.load();
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
this.media = media;
|
|
202
|
-
this._setupMediaListeners();
|
|
203
|
-
this.peaks = peaks;
|
|
204
|
-
this.onPlayEnd = null;
|
|
205
|
-
this.buffer = null;
|
|
206
|
-
this.isMuted = media.muted;
|
|
207
|
-
this.setPlaybackRate(this.playbackRate);
|
|
208
|
-
this.setVolume(this.volume);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
* Used by `wavesurfer.isPlaying()` and `wavesurfer.playPause()`
|
|
213
|
-
*
|
|
214
|
-
* @return {boolean} Media paused or not
|
|
215
|
-
*/
|
|
216
|
-
isPaused() {
|
|
217
|
-
return !this.media || this.media.paused;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Used by `wavesurfer.getDuration()`
|
|
222
|
-
*
|
|
223
|
-
* @return {number} Duration
|
|
224
|
-
*/
|
|
225
|
-
getDuration() {
|
|
226
|
-
if (this.explicitDuration) {
|
|
227
|
-
return this.explicitDuration;
|
|
228
|
-
}
|
|
229
|
-
let duration = (this.buffer || this.media).duration;
|
|
230
|
-
if (duration >= Infinity) {
|
|
231
|
-
// streaming audio
|
|
232
|
-
duration = this.media.seekable.end(0);
|
|
233
|
-
}
|
|
234
|
-
return duration;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
/**
|
|
238
|
-
* Returns the current time in seconds relative to the audio-clip's
|
|
239
|
-
* duration.
|
|
240
|
-
*
|
|
241
|
-
* @return {number} Current time
|
|
242
|
-
*/
|
|
243
|
-
getCurrentTime() {
|
|
244
|
-
return this.media && this.media.currentTime;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
/**
|
|
248
|
-
* Get the position from 0 to 1
|
|
249
|
-
*
|
|
250
|
-
* @return {number} Current position
|
|
251
|
-
*/
|
|
252
|
-
getPlayedPercents() {
|
|
253
|
-
return this.getCurrentTime() / this.getDuration() || 0;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
/**
|
|
257
|
-
* Get the audio source playback rate.
|
|
258
|
-
*
|
|
259
|
-
* @return {number} Playback rate
|
|
260
|
-
*/
|
|
261
|
-
getPlaybackRate() {
|
|
262
|
-
return this.playbackRate || this.media.playbackRate;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* Set the audio source playback rate.
|
|
267
|
-
*
|
|
268
|
-
* @param {number} value Playback rate
|
|
269
|
-
*/
|
|
270
|
-
setPlaybackRate(value) {
|
|
271
|
-
this.playbackRate = value || 1;
|
|
272
|
-
this.media.playbackRate = this.playbackRate;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
/**
|
|
276
|
-
* Used by `wavesurfer.seekTo()`
|
|
277
|
-
*
|
|
278
|
-
* @param {number} start Position to start at in seconds
|
|
279
|
-
*/
|
|
280
|
-
seekTo(start) {
|
|
281
|
-
if (start != null && !isNaN(start)) {
|
|
282
|
-
this.media.currentTime = start;
|
|
283
|
-
}
|
|
284
|
-
this.clearPlayEnd();
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
/**
|
|
288
|
-
* Plays the loaded audio region.
|
|
289
|
-
*
|
|
290
|
-
* @param {number} start Start offset in seconds, relative to the beginning
|
|
291
|
-
* of a clip.
|
|
292
|
-
* @param {number} end When to stop, relative to the beginning of a clip.
|
|
293
|
-
* @emits MediaElement#play
|
|
294
|
-
* @return {Promise} Result
|
|
295
|
-
*/
|
|
296
|
-
play(start, end) {
|
|
297
|
-
this.seekTo(start);
|
|
298
|
-
const promise = this.media.play();
|
|
299
|
-
end && this.setPlayEnd(end);
|
|
300
|
-
|
|
301
|
-
return promise;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
/**
|
|
305
|
-
* Pauses the loaded audio.
|
|
306
|
-
*
|
|
307
|
-
* @emits MediaElement#pause
|
|
308
|
-
* @return {Promise} Result
|
|
309
|
-
*/
|
|
310
|
-
pause() {
|
|
311
|
-
let promise;
|
|
312
|
-
|
|
313
|
-
if (this.media) {
|
|
314
|
-
promise = this.media.pause();
|
|
315
|
-
}
|
|
316
|
-
this.clearPlayEnd();
|
|
317
|
-
|
|
318
|
-
return promise;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
/**
|
|
322
|
-
* Set the play end
|
|
323
|
-
*
|
|
324
|
-
* @param {number} end Where to end
|
|
325
|
-
*/
|
|
326
|
-
setPlayEnd(end) {
|
|
327
|
-
this.clearPlayEnd();
|
|
328
|
-
|
|
329
|
-
this._onPlayEnd = time => {
|
|
330
|
-
if (time >= end) {
|
|
331
|
-
this.pause();
|
|
332
|
-
this.seekTo(end);
|
|
333
|
-
}
|
|
334
|
-
};
|
|
335
|
-
this.on('audioprocess', this._onPlayEnd);
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
/** @private */
|
|
339
|
-
clearPlayEnd() {
|
|
340
|
-
if (this._onPlayEnd) {
|
|
341
|
-
this.un('audioprocess', this._onPlayEnd);
|
|
342
|
-
this._onPlayEnd = null;
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
/**
|
|
347
|
-
* Compute the max and min value of the waveform when broken into
|
|
348
|
-
* <length> subranges.
|
|
349
|
-
*
|
|
350
|
-
* @param {number} length How many subranges to break the waveform into.
|
|
351
|
-
* @param {number} first First sample in the required range.
|
|
352
|
-
* @param {number} last Last sample in the required range.
|
|
353
|
-
* @return {number[]|Number.<Array[]>} Array of 2*<length> peaks or array of
|
|
354
|
-
* arrays of peaks consisting of (max, min) values for each subrange.
|
|
355
|
-
*/
|
|
356
|
-
getPeaks(length, first, last) {
|
|
357
|
-
if (this.buffer) {
|
|
358
|
-
return super.getPeaks(length, first, last);
|
|
359
|
-
}
|
|
360
|
-
return this.peaks || [];
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
/**
|
|
364
|
-
* Set the sink id for the media player
|
|
365
|
-
*
|
|
366
|
-
* @param {string} deviceId String value representing audio device id.
|
|
367
|
-
* @returns {Promise} A Promise that resolves to `undefined` when there
|
|
368
|
-
* are no errors.
|
|
369
|
-
*/
|
|
370
|
-
setSinkId(deviceId) {
|
|
371
|
-
if (deviceId) {
|
|
372
|
-
if (!this.media.setSinkId) {
|
|
373
|
-
return Promise.reject(
|
|
374
|
-
new Error('setSinkId is not supported in your browser')
|
|
375
|
-
);
|
|
376
|
-
}
|
|
377
|
-
return this.media.setSinkId(deviceId);
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
return Promise.reject(new Error('Invalid deviceId: ' + deviceId));
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
/**
|
|
384
|
-
* Get the current volume
|
|
385
|
-
*
|
|
386
|
-
* @return {number} value A floating point value between 0 and 1.
|
|
387
|
-
*/
|
|
388
|
-
getVolume() {
|
|
389
|
-
return this.volume;
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
/**
|
|
393
|
-
* Set the audio volume
|
|
394
|
-
*
|
|
395
|
-
* @param {number} value A floating point value between 0 and 1.
|
|
396
|
-
*/
|
|
397
|
-
setVolume(value) {
|
|
398
|
-
this.volume = value;
|
|
399
|
-
// no need to change when it's already at that volume
|
|
400
|
-
if (this.media.volume !== this.volume) {
|
|
401
|
-
this.media.volume = this.volume;
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
/**
|
|
406
|
-
* Enable or disable muted audio
|
|
407
|
-
*
|
|
408
|
-
* @since 4.0.0
|
|
409
|
-
* @param {boolean} muted Specify `true` to mute audio.
|
|
410
|
-
*/
|
|
411
|
-
setMute(muted) {
|
|
412
|
-
// This causes a volume change to be emitted too through the
|
|
413
|
-
// volumechange event listener.
|
|
414
|
-
this.isMuted = this.media.muted = muted;
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
/**
|
|
418
|
-
* This is called when wavesurfer is destroyed
|
|
419
|
-
*
|
|
420
|
-
*/
|
|
421
|
-
destroy() {
|
|
422
|
-
this.pause();
|
|
423
|
-
this.unAll();
|
|
424
|
-
this.destroyed = true;
|
|
425
|
-
|
|
426
|
-
// cleanup media event listeners
|
|
427
|
-
Object.keys(this.mediaListeners).forEach(id => {
|
|
428
|
-
if (this.media) {
|
|
429
|
-
this.media.removeEventListener(id, this.mediaListeners[id]);
|
|
430
|
-
}
|
|
431
|
-
});
|
|
432
|
-
|
|
433
|
-
if (
|
|
434
|
-
this.params.removeMediaElementOnDestroy &&
|
|
435
|
-
this.media &&
|
|
436
|
-
this.media.parentNode
|
|
437
|
-
) {
|
|
438
|
-
this.media.parentNode.removeChild(this.media);
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
this.media = null;
|
|
442
|
-
}
|
|
443
|
-
}
|
package/src/peakcache.js
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Caches the decoded peaks data to improve rendering speed for large audio
|
|
3
|
-
*
|
|
4
|
-
* Is used if the option parameter `partialRender` is set to `true`
|
|
5
|
-
*/
|
|
6
|
-
export default class PeakCache {
|
|
7
|
-
/**
|
|
8
|
-
* Instantiate cache
|
|
9
|
-
*/
|
|
10
|
-
constructor() {
|
|
11
|
-
this.clearPeakCache();
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Empty the cache
|
|
16
|
-
*/
|
|
17
|
-
clearPeakCache() {
|
|
18
|
-
/**
|
|
19
|
-
* Flat array with entries that are always in pairs to mark the
|
|
20
|
-
* beginning and end of each subrange. This is a convenience so we can
|
|
21
|
-
* iterate over the pairs for easy set difference operations.
|
|
22
|
-
* @private
|
|
23
|
-
*/
|
|
24
|
-
this.peakCacheRanges = [];
|
|
25
|
-
/**
|
|
26
|
-
* Length of the entire cachable region, used for resetting the cache
|
|
27
|
-
* when this changes (zoom events, for instance).
|
|
28
|
-
* @private
|
|
29
|
-
*/
|
|
30
|
-
this.peakCacheLength = -1;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Add a range of peaks to the cache
|
|
35
|
-
*
|
|
36
|
-
* @param {number} length The length of the range
|
|
37
|
-
* @param {number} start The x offset of the start of the range
|
|
38
|
-
* @param {number} end The x offset of the end of the range
|
|
39
|
-
* @return {Number.<Array[]>} Array with arrays of numbers
|
|
40
|
-
*/
|
|
41
|
-
addRangeToPeakCache(length, start, end) {
|
|
42
|
-
if (length != this.peakCacheLength) {
|
|
43
|
-
this.clearPeakCache();
|
|
44
|
-
this.peakCacheLength = length;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// Return ranges that weren't in the cache before the call.
|
|
48
|
-
let uncachedRanges = [];
|
|
49
|
-
let i = 0;
|
|
50
|
-
// Skip ranges before the current start.
|
|
51
|
-
while (
|
|
52
|
-
i < this.peakCacheRanges.length &&
|
|
53
|
-
this.peakCacheRanges[i] < start
|
|
54
|
-
) {
|
|
55
|
-
i++;
|
|
56
|
-
}
|
|
57
|
-
// If |i| is even, |start| falls after an existing range. Otherwise,
|
|
58
|
-
// |start| falls between an existing range, and the uncached region
|
|
59
|
-
// starts when we encounter the next node in |peakCacheRanges| or
|
|
60
|
-
// |end|, whichever comes first.
|
|
61
|
-
if (i % 2 == 0) {
|
|
62
|
-
uncachedRanges.push(start);
|
|
63
|
-
}
|
|
64
|
-
while (
|
|
65
|
-
i < this.peakCacheRanges.length &&
|
|
66
|
-
this.peakCacheRanges[i] <= end
|
|
67
|
-
) {
|
|
68
|
-
uncachedRanges.push(this.peakCacheRanges[i]);
|
|
69
|
-
i++;
|
|
70
|
-
}
|
|
71
|
-
// If |i| is even, |end| is after all existing ranges.
|
|
72
|
-
if (i % 2 == 0) {
|
|
73
|
-
uncachedRanges.push(end);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Filter out the 0-length ranges.
|
|
77
|
-
uncachedRanges = uncachedRanges.filter((item, pos, arr) => {
|
|
78
|
-
if (pos == 0) {
|
|
79
|
-
return item != arr[pos + 1];
|
|
80
|
-
} else if (pos == arr.length - 1) {
|
|
81
|
-
return item != arr[pos - 1];
|
|
82
|
-
}
|
|
83
|
-
return item != arr[pos - 1] && item != arr[pos + 1];
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
// Merge the two ranges together, uncachedRanges will either contain
|
|
87
|
-
// wholly new points, or duplicates of points in peakCacheRanges. If
|
|
88
|
-
// duplicates are detected, remove both and extend the range.
|
|
89
|
-
this.peakCacheRanges = this.peakCacheRanges.concat(uncachedRanges);
|
|
90
|
-
this.peakCacheRanges = this.peakCacheRanges
|
|
91
|
-
.sort((a, b) => a - b)
|
|
92
|
-
.filter((item, pos, arr) => {
|
|
93
|
-
if (pos == 0) {
|
|
94
|
-
return item != arr[pos + 1];
|
|
95
|
-
} else if (pos == arr.length - 1) {
|
|
96
|
-
return item != arr[pos - 1];
|
|
97
|
-
}
|
|
98
|
-
return item != arr[pos - 1] && item != arr[pos + 1];
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
// Push the uncached ranges into an array of arrays for ease of
|
|
102
|
-
// iteration in the functions that call this.
|
|
103
|
-
const uncachedRangePairs = [];
|
|
104
|
-
for (i = 0; i < uncachedRanges.length; i += 2) {
|
|
105
|
-
uncachedRangePairs.push([uncachedRanges[i], uncachedRanges[i + 1]]);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
return uncachedRangePairs;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* For testing
|
|
113
|
-
*
|
|
114
|
-
* @return {Number.<Array[]>} Array with arrays of numbers
|
|
115
|
-
*/
|
|
116
|
-
getCacheRanges() {
|
|
117
|
-
const peakCacheRangePairs = [];
|
|
118
|
-
let i;
|
|
119
|
-
for (i = 0; i < this.peakCacheRanges.length; i += 2) {
|
|
120
|
-
peakCacheRangePairs.push([
|
|
121
|
-
this.peakCacheRanges[i],
|
|
122
|
-
this.peakCacheRanges[i + 1]
|
|
123
|
-
]);
|
|
124
|
-
}
|
|
125
|
-
return peakCacheRangePairs;
|
|
126
|
-
}
|
|
127
|
-
}
|