wavesurfer.js 5.2.0 → 6.0.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.
Files changed (58) hide show
  1. package/CHANGES.md +22 -0
  2. package/README.md +10 -0
  3. package/dist/plugin/wavesurfer.cursor.js +52 -50
  4. package/dist/plugin/wavesurfer.cursor.js.map +1 -1
  5. package/dist/plugin/wavesurfer.cursor.min.js +2 -2
  6. package/dist/plugin/wavesurfer.cursor.min.js.map +1 -1
  7. package/dist/plugin/wavesurfer.elan.js +9 -6
  8. package/dist/plugin/wavesurfer.elan.js.map +1 -1
  9. package/dist/plugin/wavesurfer.elan.min.js +2 -2
  10. package/dist/plugin/wavesurfer.elan.min.js.map +1 -1
  11. package/dist/plugin/wavesurfer.markers.js +141 -25
  12. package/dist/plugin/wavesurfer.markers.js.map +1 -1
  13. package/dist/plugin/wavesurfer.markers.min.js +2 -2
  14. package/dist/plugin/wavesurfer.markers.min.js.map +1 -1
  15. package/dist/plugin/wavesurfer.mediasession.js +5 -5
  16. package/dist/plugin/wavesurfer.mediasession.min.js +2 -2
  17. package/dist/plugin/wavesurfer.mediasession.min.js.map +1 -1
  18. package/dist/plugin/wavesurfer.microphone.js +4 -4
  19. package/dist/plugin/wavesurfer.microphone.min.js +2 -2
  20. package/dist/plugin/wavesurfer.microphone.min.js.map +1 -1
  21. package/dist/plugin/wavesurfer.minimap.js +25 -22
  22. package/dist/plugin/wavesurfer.minimap.js.map +1 -1
  23. package/dist/plugin/wavesurfer.minimap.min.js +2 -2
  24. package/dist/plugin/wavesurfer.minimap.min.js.map +1 -1
  25. package/dist/plugin/wavesurfer.playhead.js +4 -4
  26. package/dist/plugin/wavesurfer.playhead.min.js +2 -2
  27. package/dist/plugin/wavesurfer.playhead.min.js.map +1 -1
  28. package/dist/plugin/wavesurfer.regions.js +53 -16
  29. package/dist/plugin/wavesurfer.regions.js.map +1 -1
  30. package/dist/plugin/wavesurfer.regions.min.js +2 -2
  31. package/dist/plugin/wavesurfer.regions.min.js.map +1 -1
  32. package/dist/plugin/wavesurfer.spectrogram.js +70 -57
  33. package/dist/plugin/wavesurfer.spectrogram.js.map +1 -1
  34. package/dist/plugin/wavesurfer.spectrogram.min.js +2 -2
  35. package/dist/plugin/wavesurfer.spectrogram.min.js.map +1 -1
  36. package/dist/plugin/wavesurfer.timeline.js +39 -44
  37. package/dist/plugin/wavesurfer.timeline.js.map +1 -1
  38. package/dist/plugin/wavesurfer.timeline.min.js +2 -2
  39. package/dist/plugin/wavesurfer.timeline.min.js.map +1 -1
  40. package/dist/wavesurfer-html-init.js +5 -5
  41. package/dist/wavesurfer-html-init.min.js +2 -2
  42. package/dist/wavesurfer-html-init.min.js.map +1 -1
  43. package/dist/wavesurfer.js +209 -121
  44. package/dist/wavesurfer.js.map +1 -1
  45. package/dist/wavesurfer.min.js +2 -2
  46. package/dist/wavesurfer.min.js.map +1 -1
  47. package/package.json +23 -23
  48. package/src/drawer.canvasentry.js +30 -6
  49. package/src/drawer.js +1 -0
  50. package/src/drawer.multicanvas.js +19 -8
  51. package/src/mediaelement.js +1 -1
  52. package/src/plugin/cursor/index.js +68 -70
  53. package/src/plugin/markers/index.js +112 -23
  54. package/src/plugin/minimap/index.js +24 -21
  55. package/src/plugin/regions/index.js +30 -3
  56. package/src/plugin/regions/region.js +13 -4
  57. package/src/plugin/spectrogram/index.js +65 -50
  58. package/src/wavesurfer.js +31 -10
@@ -96,16 +96,7 @@ export default class MinimapPlugin {
96
96
  this.drawer = new ws.Drawer(this.params.container, this.params);
97
97
  this.wavesurfer = ws;
98
98
  this.util = ws.util;
99
- /**
100
- * Minimap needs to listen for the `ready` and `waveform-ready` events
101
- * to work with the `MediaElement` backend. The moment the `ready` event
102
- * is called is different (and peaks would not load).
103
- *
104
- * @type {string}
105
- * @see https://github.com/katspaugh/wavesurfer.js/issues/736
106
- */
107
- this.renderEvent =
108
- ws.params.backend === 'MediaElement' ? 'waveform-ready' : 'ready';
99
+ this.renderEvent = 'redraw';
109
100
  this.overviewRegion = null;
110
101
  this.regionsPlugin = this.wavesurfer[this.params.regionsPluginName];
111
102
 
@@ -144,7 +135,8 @@ export default class MinimapPlugin {
144
135
  // event listeners for the overview region
145
136
  this._onScroll = e => {
146
137
  if (!this.draggingOverview) {
147
- this.moveOverviewRegion(e.target.scrollLeft / this.ratio);
138
+ const orientedTarget = this.util.withOrientation(e.target, this.wavesurfer.params.vertical);
139
+ this.moveOverviewRegion(orientedTarget.scrollLeft / this.ratio);
148
140
  }
149
141
  };
150
142
  this._onMouseover = e => {
@@ -245,8 +237,13 @@ export default class MinimapPlugin {
245
237
  createElements() {
246
238
  this.drawer.createElements();
247
239
  if (this.params.showOverview) {
248
- this.overviewRegion = this.util.style(
249
- document.createElement('overview'),
240
+ this.overviewRegion = this.util.withOrientation(
241
+ this.drawer.wrapper.appendChild(document.createElement('overview')),
242
+ this.wavesurfer.params.vertical
243
+ );
244
+
245
+ this.util.style(
246
+ this.overviewRegion,
250
247
  {
251
248
  top: 0,
252
249
  bottom: 0,
@@ -262,7 +259,6 @@ export default class MinimapPlugin {
262
259
  opacity: this.params.overviewOpacity
263
260
  }
264
261
  );
265
- this.drawer.wrapper.appendChild(this.overviewRegion);
266
262
  }
267
263
  }
268
264
 
@@ -307,24 +303,27 @@ export default class MinimapPlugin {
307
303
  }
308
304
 
309
305
  if (this.params.showOverview) {
310
- this.overviewRegion.addEventListener('mousedown', event => {
306
+ this.overviewRegion.domElement.addEventListener('mousedown', e => {
307
+ const event = this.util.withOrientation(e, this.wavesurfer.params.vertical);
311
308
  this.draggingOverview = true;
312
309
  relativePositionX = event.layerX;
313
310
  positionMouseDown.clientX = event.clientX;
314
311
  positionMouseDown.clientY = event.clientY;
315
312
  });
316
313
 
317
- this.drawer.wrapper.addEventListener('mousemove', event => {
314
+ this.drawer.wrapper.addEventListener('mousemove', e => {
318
315
  if (this.draggingOverview) {
316
+ const event = this.util.withOrientation(e, this.wavesurfer.params.vertical);
319
317
  this.moveOverviewRegion(
320
318
  event.clientX -
321
- this.drawer.container.getBoundingClientRect().left -
322
- relativePositionX
319
+ this.drawer.container.getBoundingClientRect().left -
320
+ relativePositionX
323
321
  );
324
322
  }
325
323
  });
326
324
 
327
- this.drawer.wrapper.addEventListener('mouseup', event => {
325
+ this.drawer.wrapper.addEventListener('mouseup', e => {
326
+ const event = this.util.withOrientation(e, this.wavesurfer.params.vertical);
328
327
  if (
329
328
  positionMouseDown.clientX - event.clientX === 0 &&
330
329
  positionMouseDown.clientX - event.clientX === 0
@@ -356,7 +355,9 @@ export default class MinimapPlugin {
356
355
  this.moveOverviewRegion(
357
356
  this.wavesurfer.drawer.wrapper.scrollLeft / this.ratio
358
357
  );
359
- this.overviewRegion.style.width = this.overviewWidth + 'px';
358
+ this.util.style(this.overviewRegion, {
359
+ width: this.overviewWidth + 'px'
360
+ });
360
361
  }
361
362
  }
362
363
 
@@ -372,7 +373,9 @@ export default class MinimapPlugin {
372
373
  this.overviewPosition =
373
374
  this.drawer.container.offsetWidth - this.overviewWidth;
374
375
  }
375
- this.overviewRegion.style.left = this.overviewPosition + 'px';
376
+ this.util.style(this.overviewRegion, {
377
+ left: this.overviewPosition + 'px'
378
+ });
376
379
  if (this.draggingOverview) {
377
380
  this.wavesurfer.drawer.wrapper.scrollLeft =
378
381
  this.overviewPosition * this.ratio;
@@ -129,15 +129,14 @@ export default class RegionsPlugin {
129
129
  this.wavesurfer.Region = Region;
130
130
 
131
131
  // By default, scroll the container if the user drags a region
132
- // within 5% of its edge
132
+ // within 5% (based on its initial size) of its edge
133
133
  const scrollWidthProportion = 0.05;
134
134
  this._onBackendCreated = () => {
135
135
  this.wrapper = this.wavesurfer.drawer.wrapper;
136
136
  this.orientation = this.wavesurfer.drawer.orientation;
137
+ this.defaultEdgeScrollWidth = this.wrapper.clientWidth * scrollWidthProportion;
137
138
  if (this.params.regions) {
138
139
  this.params.regions.forEach(region => {
139
- region.edgeScrollWidth = this.params.edgeScrollWidth ||
140
- this.wrapper.clientWidth * scrollWidthProportion;
141
140
  this.add(region);
142
141
  });
143
142
  }
@@ -171,6 +170,11 @@ export default class RegionsPlugin {
171
170
  destroy() {
172
171
  this.wavesurfer.un('ready', this._onReady);
173
172
  this.wavesurfer.un('backend-created', this._onBackendCreated);
173
+ // Disabling `region-removed' because destroying the plugin calls
174
+ // the Region.remove() method that is also used to remove regions based
175
+ // on user input. This can cause confusion since teardown is not a
176
+ // user event, but would emit `region-removed` as if it was.
177
+ this.wavesurfer.setDisabledEventEmissions(['region-removed']);
174
178
  this.disableDragSelection();
175
179
  this.clear();
176
180
  }
@@ -197,6 +201,16 @@ export default class RegionsPlugin {
197
201
  return null;
198
202
  }
199
203
 
204
+ params = {
205
+ edgeScrollWidth: this.params.edgeScrollWidth || this.defaultEdgeScrollWidth,
206
+ ...params
207
+ };
208
+
209
+ // Take formatTimeCallback from plugin params if not already set
210
+ if (!params.formatTimeCallback && this.params.formatTimeCallback) {
211
+ params = {...params, formatTimeCallback: this.params.formatTimeCallback};
212
+ }
213
+
200
214
  if (!params.minLength && this.regionsMinLength) {
201
215
  params = {...params, minLength: this.regionsMinLength};
202
216
  }
@@ -284,6 +298,19 @@ export default class RegionsPlugin {
284
298
  this.vertical
285
299
  );
286
300
 
301
+ // set the region channel index based on the clicked area
302
+ if (this.wavesurfer.params.splitChannels) {
303
+ const y = (e.touches ? e.touches[0].clientY : e.clientY) - wrapperRect.top;
304
+ const channelCount = this.wavesurfer.backend.buffer != null ? this.wavesurfer.backend.buffer.numberOfChannels : 1;
305
+ const channelHeight = this.wrapper.clientHeight / channelCount;
306
+ const channelIdx = Math.floor(y / channelHeight);
307
+ params.channelIdx = channelIdx;
308
+ const channelColors = this.wavesurfer.params.splitChannelsOptions.channelColors[channelIdx];
309
+ if (channelColors && channelColors.dragColor) {
310
+ params.color = channelColors.dragColor;
311
+ }
312
+ }
313
+
287
314
  drag = true;
288
315
  start = this.wavesurfer.drawer.handleEvent(e, true);
289
316
  region = null;
@@ -62,6 +62,7 @@ export class Region {
62
62
  // select channel ID to set region
63
63
  let channelIdx =
64
64
  params.channelIdx == null ? -1 : parseInt(params.channelIdx);
65
+ this.channelIdx = channelIdx;
65
66
  this.regionHeight = '100%';
66
67
  this.marginTop = '0px';
67
68
 
@@ -190,7 +191,7 @@ export class Region {
190
191
 
191
192
  this.style(this.element, {
192
193
  position: 'absolute',
193
- zIndex: 2,
194
+ zIndex: 3,
194
195
  height: this.regionHeight,
195
196
  top: this.marginTop
196
197
  });
@@ -749,16 +750,20 @@ export class Region {
749
750
  const duration = this.wavesurfer.getDuration();
750
751
  const eventParams = {
751
752
  action: 'resize',
752
- direction: direction === 'start' ? 'right' : 'left'
753
+ direction: direction === 'start' ? 'left' : 'right'
753
754
  };
754
755
 
755
756
  if (direction === 'start') {
756
757
  // Check if changing the start by the given delta would result in the region being smaller than minLength
757
- // Ignore cases where we are making the region wider rather than shrinking it
758
758
  if (delta > 0 && this.end - (this.start + delta) < this.minLength) {
759
759
  delta = this.end - this.minLength - this.start;
760
760
  }
761
761
 
762
+ // Check if changing the start by the given delta would result in the region being larger than maxLength
763
+ if (delta < 0 && this.end - (this.start + delta) > this.maxLength) {
764
+ delta = this.end - this.start - this.maxLength;
765
+ }
766
+
762
767
  if (delta < 0 && (this.start + delta) < 0) {
763
768
  delta = this.start * -1;
764
769
  }
@@ -769,11 +774,15 @@ export class Region {
769
774
  }, eventParams);
770
775
  } else {
771
776
  // Check if changing the end by the given delta would result in the region being smaller than minLength
772
- // Ignore cases where we are making the region wider rather than shrinking it
773
777
  if (delta < 0 && this.end + delta - this.start < this.minLength) {
774
778
  delta = this.start + this.minLength - this.end;
775
779
  }
776
780
 
781
+ // Check if changing the end by the given delta would result in the region being larger than maxLength
782
+ if (delta > 0 && this.end + delta - this.start > this.maxLength) {
783
+ delta = this.maxLength - (this.end - this.start);
784
+ }
785
+
777
786
  if (delta > 0 && (this.end + delta) > duration) {
778
787
  delta = duration - this.end;
779
788
  }
@@ -8,6 +8,8 @@ import FFT from './fft';
8
8
  * which to render
9
9
  * @property {number} fftSamples=512 Number of samples to fetch to FFT. Must be
10
10
  * a power of 2.
11
+ * @property {boolean} splitChannels=false Render with separate spectrograms for
12
+ * the channels of the audio
11
13
  * @property {boolean} labels Set to true to display frequency labels.
12
14
  * @property {number} noverlap Size of the overlapping window. Must be <
13
15
  * fftSamples. Auto deduced from canvas size by default.
@@ -127,6 +129,8 @@ export default class SpectrogramPlugin {
127
129
  this.noverlap = params.noverlap;
128
130
  this.windowFunc = params.windowFunc;
129
131
  this.alpha = params.alpha;
132
+ this.splitChannels = params.splitChannels;
133
+ this.channels = this.splitChannels ? ws.backend.buffer.numberOfChannels : 1;
130
134
 
131
135
  this.createWrapper();
132
136
  this.createCanvas();
@@ -176,7 +180,7 @@ export default class SpectrogramPlugin {
176
180
  left: 0,
177
181
  position: 'absolute',
178
182
  zIndex: 9,
179
- height: `${this.height / this.pixelRatio}px`,
183
+ height: `${this.height * this.channels / this.pixelRatio}px`,
180
184
  width: `${55 / this.pixelRatio}px`
181
185
  });
182
186
  this.wrapper.appendChild(labelsEl);
@@ -197,7 +201,7 @@ export default class SpectrogramPlugin {
197
201
  position: 'relative',
198
202
  userSelect: 'none',
199
203
  webkitUserSelect: 'none',
200
- height: `${this.height / this.pixelRatio}px`
204
+ height: `${this.height * this.channels / this.pixelRatio}px`
201
205
  });
202
206
 
203
207
  if (wsParams.fillParent || wsParams.scrollParent) {
@@ -244,57 +248,58 @@ export default class SpectrogramPlugin {
244
248
  updateCanvasStyle() {
245
249
  const width = Math.round(this.width / this.pixelRatio) + 'px';
246
250
  this.canvas.width = this.width;
247
- this.canvas.height = this.height;
251
+ this.canvas.height = this.height * this.channels;
248
252
  this.canvas.style.width = width;
249
253
  }
250
254
 
251
255
  drawSpectrogram(frequenciesData, my) {
256
+ if (!isNaN(frequenciesData[0][0])) { // data is 1ch [sample, freq] format
257
+ // to [channel, sample, freq] format
258
+ frequenciesData = [frequenciesData];
259
+ }
260
+
252
261
  const spectrCc = my.spectrCc;
253
262
  const height = my.height;
254
263
  const width = my.width;
255
- const pixels = my.resample(frequenciesData);
256
- const heightFactor = my.buffer ? 2 / my.buffer.numberOfChannels : 1;
257
- if (spectrCc) {
264
+
265
+ if (!spectrCc) {
266
+ return;
267
+ }
268
+
269
+ for (let c = 0; c < frequenciesData.length; c++) { // for each channel
270
+ const pixels = my.resample(frequenciesData[c]);
258
271
  const imageData = spectrCc.createImageData(width, height);
259
- let i;
260
- let j;
261
- let k;
262
272
 
263
- for (i = 0; i < pixels.length; i++) {
264
- for (j = 0; j < pixels[i].length; j++) {
273
+ for (let i = 0; i < pixels.length; i++) {
274
+ for (let j = 0; j < pixels[i].length; j++) {
265
275
  const colorMap = my.colorMap[pixels[i][j]];
266
- /* eslint-disable max-depth */
267
- for (k = 0; k < heightFactor; k++) {
268
- let y = height - j * heightFactor;
269
- if (heightFactor === 2 && k === 1) {
270
- y--;
271
- }
272
- const redIndex = y * (width * 4) + i * 4;
273
- imageData.data[redIndex] = colorMap[0] * 255;
274
- imageData.data[redIndex + 1] = colorMap[1] * 255;
275
- imageData.data[redIndex + 2] = colorMap[2] * 255;
276
- imageData.data[redIndex + 3] = colorMap[3] * 255;
277
- }
278
- /* eslint-enable max-depth */
276
+ const redIndex = ((height - j) * width + i) * 4;
277
+ imageData.data[redIndex] = colorMap[0] * 255;
278
+ imageData.data[redIndex + 1] = colorMap[1] * 255;
279
+ imageData.data[redIndex + 2] = colorMap[2] * 255;
280
+ imageData.data[redIndex + 3] = colorMap[3] * 255;
279
281
  }
280
282
  }
281
- spectrCc.putImageData(imageData, 0, 0);
283
+
284
+ // stack spectrograms
285
+ spectrCc.putImageData(imageData, 0, height * c);
282
286
  }
283
287
  }
284
288
 
285
289
  getFrequencies(callback) {
286
290
  const fftSamples = this.fftSamples;
287
291
  const buffer = (this.buffer = this.wavesurfer.backend.buffer);
288
- const channelOne = buffer.getChannelData(0);
289
- const bufferLength = buffer.length;
290
- const sampleRate = buffer.sampleRate;
291
- const frequencies = [];
292
+ const channels = this.channels;
292
293
 
293
294
  if (!buffer) {
294
295
  this.fireEvent('error', 'Web Audio buffer is not available');
295
296
  return;
296
297
  }
297
298
 
299
+ // This may differ from file samplerate. Browser resamples audio.
300
+ const sampleRate = buffer.sampleRate;
301
+ const frequencies = [];
302
+
298
303
  let noverlap = this.noverlap;
299
304
  if (!noverlap) {
300
305
  const uniqueSamplesPerPx = buffer.length / this.canvas.width;
@@ -307,24 +312,30 @@ export default class SpectrogramPlugin {
307
312
  this.windowFunc,
308
313
  this.alpha
309
314
  );
310
- const maxSlicesCount = Math.floor(
311
- bufferLength / (fftSamples - noverlap)
312
- );
313
- let currentOffset = 0;
314
315
 
315
- while (currentOffset + fftSamples < channelOne.length) {
316
- const segment = channelOne.slice(
317
- currentOffset,
318
- currentOffset + fftSamples
319
- );
320
- const spectrum = fft.calculateSpectrum(segment);
321
- const array = new Uint8Array(fftSamples / 2);
322
- let j;
323
- for (j = 0; j < fftSamples / 2; j++) {
324
- array[j] = Math.max(-255, Math.log10(spectrum[j]) * 45);
316
+ for (let c = 0; c < channels; c++) { // for each channel
317
+ const channelData = buffer.getChannelData(c);
318
+ const channelFreq = [];
319
+ let currentOffset = 0;
320
+
321
+ while (currentOffset + fftSamples < channelData.length) {
322
+ const segment = channelData.slice(
323
+ currentOffset,
324
+ currentOffset + fftSamples
325
+ );
326
+ const spectrum = fft.calculateSpectrum(segment);
327
+ const array = new Uint8Array(fftSamples / 2);
328
+ let j;
329
+ for (j = 0; j < fftSamples / 2; j++) {
330
+ array[j] = Math.max(-255, Math.log10(spectrum[j]) * 45);
331
+ }
332
+ channelFreq.push(array);
333
+ // channelFreq: [sample, freq]
334
+
335
+ currentOffset += fftSamples - noverlap;
325
336
  }
326
- frequencies.push(array);
327
- currentOffset += fftSamples - noverlap;
337
+ frequencies.push(channelFreq);
338
+ // frequencies: [channel, sample, freq]
328
339
  }
329
340
  callback(frequencies, this);
330
341
  }
@@ -377,13 +388,17 @@ export default class SpectrogramPlugin {
377
388
 
378
389
  // prepare canvas element for labels
379
390
  const ctx = this.labelsEl.getContext('2d');
380
- this.labelsEl.height = this.height;
391
+ this.labelsEl.height = this.height * this.channels;
381
392
  this.labelsEl.width = bgWidth;
382
393
 
383
- if (ctx) {
394
+ if (!ctx) {
395
+ return;
396
+ }
397
+
398
+ for (let c = 0; c < this.channels; c++) { // for each channel
384
399
  // fill background
385
400
  ctx.fillStyle = bgFill;
386
- ctx.fillRect(0, 0, bgWidth, getMaxY);
401
+ ctx.fillRect(0, c * getMaxY, bgWidth, (1 + c) * getMaxY);
387
402
  ctx.fill();
388
403
  let i;
389
404
 
@@ -403,7 +418,7 @@ export default class SpectrogramPlugin {
403
418
  let y;
404
419
 
405
420
  if (i == 0) {
406
- y = getMaxY + i - 10;
421
+ y = (1 + c) * getMaxY + i - 10;
407
422
  // unit label
408
423
  ctx.fillStyle = textColorUnit;
409
424
  ctx.font = fontSizeUnit + ' ' + fontType;
@@ -413,7 +428,7 @@ export default class SpectrogramPlugin {
413
428
  ctx.font = fontSizeFreq + ' ' + fontType;
414
429
  ctx.fillText(label, x, y);
415
430
  } else {
416
- y = getMaxY - i * 50 + yLabelOffset;
431
+ y = (1 + c) * getMaxY - i * 50 + yLabelOffset;
417
432
  // unit label
418
433
  ctx.fillStyle = textColorUnit;
419
434
  ctx.font = fontSizeUnit + ' ' + fontType;
package/src/wavesurfer.js CHANGED
@@ -69,6 +69,8 @@ import MediaElementWebAudio from './mediaelement-webaudio';
69
69
  * pixels.
70
70
  * @property {boolean} hideScrollbar=false Whether to hide the horizontal
71
71
  * scrollbar when one would normally be shown.
72
+ * @property {boolean} hideCursor=false Whether to hide the mouse cursor
73
+ * when one would normally be shown by default.
72
74
  * @property {boolean} ignoreSilenceMode=false If true, ignores device silence mode
73
75
  * when using the `WebAudio` backend.
74
76
  * @property {boolean} interact=true Whether the mouse interaction will be
@@ -270,6 +272,7 @@ export default class WaveSurfer extends util.Observer {
270
272
  forceDecode: false,
271
273
  height: 128,
272
274
  hideScrollbar: false,
275
+ hideCursor: false,
273
276
  ignoreSilenceMode: false,
274
277
  interact: true,
275
278
  loopSelection: true,
@@ -1125,40 +1128,58 @@ export default class WaveSurfer extends util.Observer {
1125
1128
  /**
1126
1129
  * Get the fill color of the waveform after the cursor.
1127
1130
  *
1128
- * @return {string} A CSS color string.
1131
+ * @param {?number} channelIdx Optional index of the channel to get its wave color if splitChannels is true
1132
+ * @return {string|object} A CSS color string, or an array of CSS color strings.
1129
1133
  */
1130
- getWaveColor() {
1134
+ getWaveColor(channelIdx = null) {
1135
+ if (this.params.splitChannelsOptions.channelColors[channelIdx]) {
1136
+ return this.params.splitChannelsOptions.channelColors[channelIdx].waveColor;
1137
+ }
1131
1138
  return this.params.waveColor;
1132
1139
  }
1133
1140
 
1134
1141
  /**
1135
1142
  * Set the fill color of the waveform after the cursor.
1136
1143
  *
1137
- * @param {string} color A CSS color string.
1144
+ * @param {string|object} color A CSS color string, or an array of CSS color strings.
1145
+ * @param {?number} channelIdx Optional index of the channel to set its wave color if splitChannels is true
1138
1146
  * @example wavesurfer.setWaveColor('#ddd');
1139
1147
  */
1140
- setWaveColor(color) {
1141
- this.params.waveColor = color;
1148
+ setWaveColor(color, channelIdx = null) {
1149
+ if (this.params.splitChannelsOptions.channelColors[channelIdx]) {
1150
+ this.params.splitChannelsOptions.channelColors[channelIdx].waveColor = color;
1151
+ } else {
1152
+ this.params.waveColor = color;
1153
+ }
1142
1154
  this.drawBuffer();
1143
1155
  }
1144
1156
 
1145
1157
  /**
1146
1158
  * Get the fill color of the waveform behind the cursor.
1147
1159
  *
1148
- * @return {string} A CSS color string.
1160
+ * @param {?number} channelIdx Optional index of the channel to get its progress color if splitChannels is true
1161
+ * @return {string|object} A CSS color string, or an array of CSS color strings.
1149
1162
  */
1150
- getProgressColor() {
1163
+ getProgressColor(channelIdx = null) {
1164
+ if (this.params.splitChannelsOptions.channelColors[channelIdx]) {
1165
+ return this.params.splitChannelsOptions.channelColors[channelIdx].progressColor;
1166
+ }
1151
1167
  return this.params.progressColor;
1152
1168
  }
1153
1169
 
1154
1170
  /**
1155
1171
  * Set the fill color of the waveform behind the cursor.
1156
1172
  *
1157
- * @param {string} color A CSS color string.
1173
+ * @param {string|object} color A CSS color string, or an array of CSS color strings.
1174
+ * @param {?number} channelIdx Optional index of the channel to set its progress color if splitChannels is true
1158
1175
  * @example wavesurfer.setProgressColor('#400');
1159
1176
  */
1160
- setProgressColor(color) {
1161
- this.params.progressColor = color;
1177
+ setProgressColor(color, channelIdx) {
1178
+ if (this.params.splitChannelsOptions.channelColors[channelIdx]) {
1179
+ this.params.splitChannelsOptions.channelColors[channelIdx].progressColor = color;
1180
+ } else {
1181
+ this.params.progressColor = color;
1182
+ }
1162
1183
  this.drawBuffer();
1163
1184
  }
1164
1185