@checksub_team/peaks_timeline 1.4.34 → 1.4.35

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/peaks.js CHANGED
@@ -12938,6 +12938,16 @@ exports.default = _default;
12938
12938
 
12939
12939
  /**
12940
12940
  * ArrayBuffer adapter consumes binary waveform data.
12941
+ * It is used as a data abstraction layer by `WaveformData`.
12942
+ *
12943
+ * This is supposed to be the fastest adapter ever:
12944
+ * * **Pros**: working directly in memory, everything is done by reference
12945
+ * (including the offsetting)
12946
+ * * **Cons**: binary data are hardly readable without data format knowledge
12947
+ * (and this is why this adapter exists).
12948
+ *
12949
+ * @param {ArrayBuffer} buffer
12950
+ * @constructor
12941
12951
  */
12942
12952
 
12943
12953
  function WaveformDataArrayBufferAdapter(buffer) {
@@ -12947,14 +12957,19 @@ function WaveformDataArrayBufferAdapter(buffer) {
12947
12957
 
12948
12958
  /**
12949
12959
  * Detects if a set of data is suitable for the ArrayBuffer adapter.
12960
+ * It is used internally by `WaveformData.create` so you should not bother using it.
12961
+ *
12962
+ * @static
12963
+ * @param {Mixed} data
12964
+ * @returns {boolean}
12950
12965
  */
12951
12966
 
12952
12967
  WaveformDataArrayBufferAdapter.isCompatible = function isCompatible(data) {
12953
- var isCompatible = data && typeof data === "object" && "byteLength" in data;
12968
+ const isCompatible = data && typeof data === "object" && "byteLength" in data;
12954
12969
 
12955
12970
  if (isCompatible) {
12956
- var view = new DataView(data);
12957
- var version = view.getInt32(0, true);
12971
+ const view = new DataView(data);
12972
+ const version = view.getInt32(0, true);
12958
12973
 
12959
12974
  if (version !== 1 && version !== 2) {
12960
12975
  throw new TypeError("This waveform data version not supported.");
@@ -12964,10 +12979,15 @@ WaveformDataArrayBufferAdapter.isCompatible = function isCompatible(data) {
12964
12979
  return isCompatible;
12965
12980
  };
12966
12981
 
12967
- WaveformDataArrayBufferAdapter.prototype = {
12982
+ /**
12983
+ * @namespace WaveformDataArrayBufferAdapter
12984
+ */
12968
12985
 
12986
+ WaveformDataArrayBufferAdapter.prototype = {
12969
12987
  /**
12970
12988
  * Returns the data format version number.
12989
+ *
12990
+ * @return {Integer} Version number of the consumed data format.
12971
12991
  */
12972
12992
 
12973
12993
  get version() {
@@ -12986,6 +13006,8 @@ WaveformDataArrayBufferAdapter.isCompatible = function isCompatible(data) {
12986
13006
 
12987
13007
  /**
12988
13008
  * Returns the number of channels.
13009
+ *
13010
+ * @return {Integer} Number of channels.
12989
13011
  */
12990
13012
 
12991
13013
  get channels() {
@@ -12999,6 +13021,8 @@ WaveformDataArrayBufferAdapter.isCompatible = function isCompatible(data) {
12999
13021
 
13000
13022
  /**
13001
13023
  * Returns the number of samples per second.
13024
+ *
13025
+ * @return {Integer} Number of samples per second.
13002
13026
  */
13003
13027
 
13004
13028
  get sample_rate() {
@@ -13007,6 +13031,8 @@ WaveformDataArrayBufferAdapter.isCompatible = function isCompatible(data) {
13007
13031
 
13008
13032
  /**
13009
13033
  * Returns the scale (number of samples per pixel).
13034
+ *
13035
+ * @return {Integer} Number of samples per pixel.
13010
13036
  */
13011
13037
 
13012
13038
  get scale() {
@@ -13015,6 +13041,8 @@ WaveformDataArrayBufferAdapter.isCompatible = function isCompatible(data) {
13015
13041
 
13016
13042
  /**
13017
13043
  * Returns the length of the waveform data (number of data points).
13044
+ *
13045
+ * @return {Integer} Length of the waveform data.
13018
13046
  */
13019
13047
 
13020
13048
  get length() {
@@ -13022,7 +13050,10 @@ WaveformDataArrayBufferAdapter.isCompatible = function isCompatible(data) {
13022
13050
  },
13023
13051
 
13024
13052
  /**
13025
- * Returns a waveform data value at a specific offset.
13053
+ * Returns a value at a specific offset.
13054
+ *
13055
+ * @param {Integer} index
13056
+ * @return {Integer} waveform value
13026
13057
  */
13027
13058
 
13028
13059
  at: function at_sample(index) {
@@ -13032,6 +13063,9 @@ WaveformDataArrayBufferAdapter.isCompatible = function isCompatible(data) {
13032
13063
  /**
13033
13064
  * Returns a new ArrayBuffer with the concatenated waveform.
13034
13065
  * All waveforms must have identical metadata (version, channels, etc)
13066
+ *
13067
+ * @param {...WaveformDataArrayBufferAdapter} otherAdapters One or more adapters to concatenate
13068
+ * @return {ArrayBuffer} concatenated ArrayBuffer
13035
13069
  */
13036
13070
 
13037
13071
  concatBuffers: function() {
@@ -13121,9 +13155,10 @@ WaveformDataObjectAdapter.isCompatible = function isCompatible(data) {
13121
13155
  */
13122
13156
 
13123
13157
  WaveformDataObjectAdapter.prototype = {
13124
-
13125
13158
  /**
13126
13159
  * Returns the data format version number.
13160
+ *
13161
+ * @return {Integer} Version number of the consumed data format.
13127
13162
  */
13128
13163
 
13129
13164
  get version() {
@@ -13140,6 +13175,8 @@ WaveformDataObjectAdapter.prototype = {
13140
13175
 
13141
13176
  /**
13142
13177
  * Returns the number of channels.
13178
+ *
13179
+ * @return {Integer} Number of channels.
13143
13180
  */
13144
13181
 
13145
13182
  get channels() {
@@ -13148,6 +13185,8 @@ WaveformDataObjectAdapter.prototype = {
13148
13185
 
13149
13186
  /**
13150
13187
  * Returns the number of samples per second.
13188
+ *
13189
+ * @return {Integer} Number of samples per second.
13151
13190
  */
13152
13191
 
13153
13192
  get sample_rate() {
@@ -13156,6 +13195,8 @@ WaveformDataObjectAdapter.prototype = {
13156
13195
 
13157
13196
  /**
13158
13197
  * Returns the scale (number of samples per pixel).
13198
+ *
13199
+ * @return {Integer} Number of samples per pixel.
13159
13200
  */
13160
13201
 
13161
13202
  get scale() {
@@ -13164,6 +13205,8 @@ WaveformDataObjectAdapter.prototype = {
13164
13205
 
13165
13206
  /**
13166
13207
  * Returns the length of the waveform data (number of data points).
13208
+ *
13209
+ * @return {Integer} Length of the waveform data.
13167
13210
  */
13168
13211
 
13169
13212
  get length() {
@@ -13171,11 +13214,14 @@ WaveformDataObjectAdapter.prototype = {
13171
13214
  },
13172
13215
 
13173
13216
  /**
13174
- * Returns a waveform data value at a specific offset.
13217
+ * Returns a value at a specific offset.
13218
+ *
13219
+ * @param {Integer} index
13220
+ * @return {number} waveform value
13175
13221
  */
13176
13222
 
13177
13223
  at: function at_sample(index) {
13178
- var data = this._data.data;
13224
+ const data = this._data.data;
13179
13225
 
13180
13226
  if (index >= 0 && index < data.length) {
13181
13227
  return data[index];
@@ -13188,6 +13234,9 @@ WaveformDataObjectAdapter.prototype = {
13188
13234
  /**
13189
13235
  * Returns a new data object with the concatenated waveform.
13190
13236
  * Both waveforms must have identical metadata (version, channels, etc)
13237
+ *
13238
+ * @param {...WaveformDataObjectAdapter} otherAdapters One or more adapters
13239
+ * @return {Mixed} combined waveform data
13191
13240
  */
13192
13241
 
13193
13242
  concatBuffers: function() {
@@ -13212,166 +13261,165 @@ module.exports = WaveformDataObjectAdapter;
13212
13261
 
13213
13262
  var WaveformData = _dereq_("../core");
13214
13263
  var InlineWorker = _dereq_("inline-worker");
13215
- var MainThreadWorker = _dereq_("../util/main-thread-worker");
13216
13264
 
13217
- function processWorker(workerArgs, callback) {
13218
- var WaveformWorker = workerArgs.disable_worker ? MainThreadWorker : InlineWorker;
13265
+ /**
13266
+ * This callback is executed once the audio has been decoded by the browser and
13267
+ * resampled by waveform-data.
13268
+ *
13269
+ * @callback onAudioResampled
13270
+ * @param {Error?}
13271
+ * @param {WaveformData} waveform_data Waveform instance of the browser decoded audio
13272
+ * @param {AudioBuffer} audio_buffer Decoded audio buffer
13273
+ */
13219
13274
 
13220
- var worker = new WaveformWorker(function() {
13221
- var INT8_MAX = 127;
13222
- var INT8_MIN = -128;
13275
+ /**
13276
+ * AudioBuffer-based WaveformData generator
13277
+ *
13278
+ * Adapted from BlockFile::CalcSummary in Audacity, with permission.
13279
+ * @see https://code.google.com/p/audacity/source/browse/audacity-src/trunk/src/BlockFile.cpp
13280
+ *
13281
+ * @param {Object.<{scale: Number, amplitude_scale: Number, split_channels: Boolean}>} options
13282
+ * @param {onAudioResampled} callback
13283
+ * @returns {Function.<AudioBuffer>}
13284
+ */
13223
13285
 
13224
- function calculateWaveformDataLength(audio_sample_count, scale) {
13225
- var data_length = Math.floor(audio_sample_count / scale);
13286
+ function getAudioDecoder(options, callback) {
13287
+ return function onAudioDecoded(audio_buffer) {
13288
+ var worker = new InlineWorker(function() {
13289
+ var INT8_MAX = 127;
13290
+ var INT8_MIN = -128;
13226
13291
 
13227
- var samples_remaining = audio_sample_count - (data_length * scale);
13292
+ function calculateWaveformDataLength(audio_sample_count, scale) {
13293
+ var data_length = Math.floor(audio_sample_count / scale);
13228
13294
 
13229
- if (samples_remaining > 0) {
13230
- data_length++;
13231
- }
13295
+ var samples_remaining = audio_sample_count - (data_length * scale);
13232
13296
 
13233
- return data_length;
13234
- }
13297
+ if (samples_remaining > 0) {
13298
+ data_length++;
13299
+ }
13235
13300
 
13236
- this.addEventListener("message", function listener(evt) {
13237
- if (!evt.data.audio_buffer) {
13238
- return;
13301
+ return data_length;
13239
13302
  }
13240
13303
 
13241
- var scale = evt.data.scale;
13242
- var amplitude_scale = evt.data.amplitude_scale;
13243
- var split_channels = evt.data.split_channels;
13244
- var audio_buffer = evt.data.audio_buffer;
13245
-
13246
- var channels = audio_buffer.channels;
13247
- var output_channels = split_channels ? channels.length : 1;
13248
- var version = output_channels === 1 ? 1 : 2;
13249
- var header_size = version === 1 ? 20 : 24;
13250
- var data_length = calculateWaveformDataLength(audio_buffer.length, scale);
13251
- var total_size = header_size + data_length * 2 * output_channels;
13252
- var data_object = new DataView(new ArrayBuffer(total_size));
13253
-
13254
- var scale_counter = 0;
13255
- var buffer_length = audio_buffer.length;
13256
- var offset = header_size;
13257
- var channel, i;
13258
-
13259
- var min_value = new Array(output_channels);
13260
- var max_value = new Array(output_channels);
13261
-
13262
- for (channel = 0; channel < output_channels; channel++) {
13263
- min_value[channel] = Infinity;
13264
- max_value[channel] = -Infinity;
13265
- }
13304
+ this.addEventListener("message", function(evt) {
13305
+ var scale = evt.data.scale;
13306
+ var amplitude_scale = evt.data.amplitude_scale;
13307
+ var split_channels = evt.data.split_channels;
13308
+ var audio_buffer = evt.data.audio_buffer;
13266
13309
 
13267
- data_object.setInt32(0, version, true); // Version
13268
- data_object.setUint32(4, 1, true); // Is 8 bit?
13269
- data_object.setInt32(8, audio_buffer.sampleRate, true); // Sample rate
13270
- data_object.setInt32(12, scale, true); // Scale
13271
- data_object.setInt32(16, data_length, true); // Length
13310
+ var channels = audio_buffer.channels;
13311
+ var output_channels = split_channels ? channels.length : 1;
13312
+ var version = output_channels === 1 ? 1 : 2;
13313
+ var header_size = version === 1 ? 20 : 24;
13314
+ var data_length = calculateWaveformDataLength(audio_buffer.length, scale);
13315
+ var total_size = header_size + data_length * 2 * output_channels;
13316
+ var data_object = new DataView(new ArrayBuffer(total_size));
13272
13317
 
13273
- if (version === 2) {
13274
- data_object.setInt32(20, output_channels, true);
13275
- }
13318
+ var min_value = new Array(output_channels);
13319
+ var max_value = new Array(output_channels);
13276
13320
 
13277
- for (i = 0; i < buffer_length; i++) {
13278
- var sample = 0;
13321
+ for (let channel = 0; channel < output_channels; channel++) {
13322
+ min_value[channel] = Infinity;
13323
+ max_value[channel] = -Infinity;
13324
+ }
13279
13325
 
13280
- if (output_channels === 1) {
13281
- for (channel = 0; channel < channels.length; ++channel) {
13282
- sample += channels[channel][i];
13283
- }
13326
+ var scale_counter = 0;
13327
+ var buffer_length = audio_buffer.length;
13328
+ var offset = header_size;
13329
+ var channel, i;
13330
+
13331
+ data_object.setInt32(0, version, true); // Version
13332
+ data_object.setUint32(4, 1, true); // Is 8 bit?
13333
+ data_object.setInt32(8, audio_buffer.sampleRate, true); // Sample rate
13334
+ data_object.setInt32(12, scale, true); // Scale
13335
+ data_object.setInt32(16, data_length, true); // Length
13284
13336
 
13285
- sample = Math.floor(INT8_MAX * sample * amplitude_scale / channels.length);
13337
+ if (version === 2) {
13338
+ data_object.setInt32(20, output_channels, true);
13339
+ }
13286
13340
 
13287
- if (sample < min_value[0]) {
13288
- min_value[0] = sample;
13341
+ for (i = 0; i < buffer_length; i++) {
13342
+ var sample = 0;
13289
13343
 
13290
- if (min_value[0] < INT8_MIN) {
13291
- min_value[0] = INT8_MIN;
13344
+ if (output_channels === 1) {
13345
+ for (channel = 0; channel < channels.length; ++channel) {
13346
+ sample += channels[channel][i];
13292
13347
  }
13293
- }
13294
13348
 
13295
- if (sample > max_value[0]) {
13296
- max_value[0] = sample;
13349
+ sample = Math.floor(INT8_MAX * sample * amplitude_scale / channels.length);
13350
+
13351
+ if (sample < min_value[0]) {
13352
+ min_value[0] = sample;
13297
13353
 
13298
- if (max_value[0] > INT8_MAX) {
13299
- max_value[0] = INT8_MAX;
13354
+ if (min_value[0] < INT8_MIN) {
13355
+ min_value[0] = INT8_MIN;
13356
+ }
13300
13357
  }
13301
- }
13302
- }
13303
- else {
13304
- for (channel = 0; channel < output_channels; ++channel) {
13305
- sample = Math.floor(INT8_MAX * channels[channel][i] * amplitude_scale);
13306
13358
 
13307
- if (sample < min_value[channel]) {
13308
- min_value[channel] = sample;
13359
+ if (sample > max_value[0]) {
13360
+ max_value[0] = sample;
13309
13361
 
13310
- if (min_value[channel] < INT8_MIN) {
13311
- min_value[channel] = INT8_MIN;
13362
+ if (max_value[0] > INT8_MAX) {
13363
+ max_value[0] = INT8_MAX;
13312
13364
  }
13313
13365
  }
13366
+ }
13367
+ else {
13368
+ for (channel = 0; channel < output_channels; ++channel) {
13369
+ sample = Math.floor(INT8_MAX * channels[channel][i] * amplitude_scale);
13314
13370
 
13315
- if (sample > max_value[channel]) {
13316
- max_value[channel] = sample;
13371
+ if (sample < min_value[channel]) {
13372
+ min_value[channel] = sample;
13317
13373
 
13318
- if (max_value[channel] > INT8_MAX) {
13319
- max_value[channel] = INT8_MAX;
13374
+ if (min_value[channel] < INT8_MIN) {
13375
+ min_value[channel] = INT8_MIN;
13376
+ }
13320
13377
  }
13378
+
13379
+ if (sample > max_value[channel]) {
13380
+ max_value[channel] = sample;
13381
+
13382
+ if (max_value[channel] > INT8_MAX) {
13383
+ max_value[channel] = INT8_MAX;
13384
+ }
13385
+ }
13386
+ }
13387
+ }
13388
+
13389
+ if (++scale_counter === scale) {
13390
+ for (channel = 0; channel < output_channels; channel++) {
13391
+ data_object.setInt8(offset++, min_value[channel]);
13392
+ data_object.setInt8(offset++, max_value[channel]);
13393
+
13394
+ min_value[channel] = Infinity;
13395
+ max_value[channel] = -Infinity;
13321
13396
  }
13397
+
13398
+ scale_counter = 0;
13322
13399
  }
13323
13400
  }
13324
13401
 
13325
- if (++scale_counter === scale) {
13402
+ if (scale_counter > 0) {
13326
13403
  for (channel = 0; channel < output_channels; channel++) {
13327
13404
  data_object.setInt8(offset++, min_value[channel]);
13328
13405
  data_object.setInt8(offset++, max_value[channel]);
13329
-
13330
- min_value[channel] = Infinity;
13331
- max_value[channel] = -Infinity;
13332
13406
  }
13333
-
13334
- scale_counter = 0;
13335
- }
13336
- }
13337
-
13338
- if (scale_counter > 0) {
13339
- for (channel = 0; channel < output_channels; channel++) {
13340
- data_object.setInt8(offset++, min_value[channel]);
13341
- data_object.setInt8(offset++, max_value[channel]);
13342
13407
  }
13343
- }
13344
13408
 
13345
- this.postMessage(data_object);
13346
- this.removeEventListener("message", listener);
13347
- this.close();
13409
+ this.postMessage(data_object);
13410
+ });
13348
13411
  });
13349
- });
13350
-
13351
- worker.addEventListener("message", function listener(evt) {
13352
- if (evt.data.audio_buffer) {
13353
- return;
13354
- }
13355
-
13356
- callback(evt.data);
13357
-
13358
- // We're only sending a single message to each listener, so
13359
- // remove the callback afterwards to avoid leaks.
13360
- worker.removeEventListener("message", listener);
13361
- });
13362
13412
 
13363
- worker.postMessage(workerArgs);
13364
- }
13413
+ worker.addEventListener("message", function(evt) {
13414
+ var data_object = evt.data;
13365
13415
 
13366
- /**
13367
- * AudioBuffer-based WaveformData generator
13368
- *
13369
- * Adapted from BlockFile::CalcSummary in Audacity, with permission.
13370
- * See https://code.google.com/p/audacity/source/browse/audacity-src/trunk/src/BlockFile.cpp
13371
- */
13416
+ callback(
13417
+ null,
13418
+ new WaveformData(data_object.buffer),
13419
+ audio_buffer
13420
+ );
13421
+ });
13372
13422
 
13373
- function getAudioDecoder(options, callback) {
13374
- return function onAudioDecoded(audio_buffer) {
13375
13423
  // Construct a simple object with the necessary AudioBuffer data,
13376
13424
  // as we cannot send an AudioBuffer to a Web Worker.
13377
13425
  var audio_buffer_obj = {
@@ -13385,38 +13433,35 @@ function getAudioDecoder(options, callback) {
13385
13433
  audio_buffer_obj.channels[channel] = audio_buffer.getChannelData(channel);
13386
13434
  }
13387
13435
 
13388
- var worker_args = {
13436
+ worker.postMessage({
13389
13437
  scale: options.scale,
13390
13438
  amplitude_scale: options.amplitude_scale,
13391
13439
  split_channels: options.split_channels,
13392
- audio_buffer: audio_buffer_obj,
13393
- disable_worker: options.disable_worker
13394
- };
13395
-
13396
- processWorker(worker_args, function(data_object) {
13397
- callback(null, new WaveformData(data_object.buffer), audio_buffer);
13440
+ audio_buffer: audio_buffer_obj
13398
13441
  });
13399
13442
  };
13400
13443
  }
13401
13444
 
13402
13445
  module.exports = getAudioDecoder;
13403
13446
 
13404
- },{"../core":83,"../util/main-thread-worker":84,"inline-worker":3}],80:[function(_dereq_,module,exports){
13447
+ },{"../core":83,"inline-worker":3}],80:[function(_dereq_,module,exports){
13405
13448
  "use strict";
13406
13449
 
13407
13450
  var defaultOptions = {
13408
13451
  scale: 512,
13409
13452
  amplitude_scale: 1.0,
13410
- split_channels: false,
13411
- disable_worker: false
13453
+ split_channels: false
13412
13454
  };
13413
13455
 
13414
13456
  function getOptions(options) {
13457
+ if (Object.prototype.hasOwnProperty.call(options, "scale_adjuster")) {
13458
+ throw new Error("Please rename the 'scale_adjuster' option to 'amplitude_scale'");
13459
+ }
13460
+
13415
13461
  var opts = {
13416
13462
  scale: options.scale || defaultOptions.scale,
13417
13463
  amplitude_scale: options.amplitude_scale || defaultOptions.amplitude_scale,
13418
- split_channels: options.split_channels || defaultOptions.split_channels,
13419
- disable_worker: options.disable_worker || defaultOptions.disable_worker
13464
+ split_channels: options.split_channels || defaultOptions.split_channels
13420
13465
  };
13421
13466
 
13422
13467
  return opts;
@@ -13458,7 +13503,39 @@ function createFromAudioBuffer(audioBuffer, options, callback) {
13458
13503
  }
13459
13504
 
13460
13505
  /**
13461
- * Creates a WaveformData instance from audio.
13506
+ * Creates a working WaveformData based on binary audio data.
13507
+ *
13508
+ * This is still quite experimental and the result will mostly depend on the
13509
+ * level of browser support.
13510
+ *
13511
+ * ```javascript
13512
+ * const xhr = new XMLHttpRequest();
13513
+ * const audioContext = new AudioContext();
13514
+ *
13515
+ * // URL of a CORS MP3/Ogg file
13516
+ * xhr.open('GET', 'https://example.com/audio/track.ogg');
13517
+ * xhr.responseType = 'arraybuffer';
13518
+ *
13519
+ * xhr.addEventListener('load', function(progressEvent) {
13520
+ * WaveformData.createFromAudio(audioContext, progressEvent.target.response,
13521
+ * function(err, waveform) {
13522
+ * if (err) {
13523
+ * console.error(err);
13524
+ * return;
13525
+ * }
13526
+ *
13527
+ * console.log(waveform.duration);
13528
+ * });
13529
+ * });
13530
+ *
13531
+ * xhr.send();
13532
+ * ```
13533
+ *
13534
+ * @todo Use `SourceBuffer.appendBuffer` and `ProgressEvent` to stream the decoding?
13535
+ * @param {AudioContext|webkitAudioContext} audio_context
13536
+ * @param {ArrayBuffer} audio_data
13537
+ * @param {callback} what to do once the decoding is done
13538
+ * @constructor
13462
13539
  */
13463
13540
 
13464
13541
  function createFromAudio(options, callback) {
@@ -13471,10 +13548,7 @@ function createFromAudio(options, callback) {
13471
13548
  return createFromAudioBuffer(options.audio_buffer, opts, callback);
13472
13549
  }
13473
13550
  else {
13474
- throw new TypeError(
13475
- // eslint-disable-next-line
13476
- "WaveformData.createFromAudio(): Pass either an AudioContext and ArrayBuffer, or an AudioBuffer object"
13477
- );
13551
+ throw new TypeError("Please pass either an AudioContext and ArrayBuffer, or an AudioBuffer object");
13478
13552
  }
13479
13553
  }
13480
13554
 
@@ -13485,6 +13559,10 @@ module.exports = createFromAudio;
13485
13559
 
13486
13560
  /**
13487
13561
  * Provides access to the waveform data for a single audio channel.
13562
+ *
13563
+ * @param {WaveformData} waveformData Waveform data.
13564
+ * @param {Number} channelIndex Channel number.
13565
+ * @constructor
13488
13566
  */
13489
13567
 
13490
13568
  function WaveformDataChannel(waveformData, channelIndex) {
@@ -13493,27 +13571,58 @@ function WaveformDataChannel(waveformData, channelIndex) {
13493
13571
  }
13494
13572
 
13495
13573
  /**
13496
- * Returns the waveform minimum at the given index position.
13574
+ * Returns a min value for a specific offset.
13575
+ *
13576
+ * ```javascript
13577
+ * var waveform = WaveformData.create({ ... });
13578
+ * var channel = waveform.channel(0);
13579
+ *
13580
+ * console.log(channel.min_sample(10)); // -> -12
13581
+ * ```
13582
+ *
13583
+ * @api
13584
+ * @param {Integer} offset
13585
+ * @return {Number} Offset min value
13497
13586
  */
13498
13587
 
13499
13588
  WaveformDataChannel.prototype.min_sample = function(index) {
13500
- var offset = (index * this._waveformData.channels + this._channelIndex) * 2;
13589
+ const offset = (index * this._waveformData.channels + this._channelIndex) * 2;
13501
13590
 
13502
13591
  return this._waveformData._adapter.at(offset);
13503
13592
  };
13504
13593
 
13505
13594
  /**
13506
- * Returns the waveform maximum at the given index position.
13595
+ * Returns a max value for a specific offset.
13596
+ *
13597
+ * ```javascript
13598
+ * var waveform = WaveformData.create({ ... });
13599
+ * var channel = waveform.channel(0);
13600
+ *
13601
+ * console.log(channel.max_sample(10)); // -> 12
13602
+ * ```
13603
+ *
13604
+ * @api
13605
+ * @param {Integer} offset
13606
+ * @return {Number} Offset max value
13507
13607
  */
13508
13608
 
13509
13609
  WaveformDataChannel.prototype.max_sample = function(index) {
13510
- var offset = (index * this._waveformData.channels + this._channelIndex) * 2 + 1;
13610
+ const offset = (index * this._waveformData.channels + this._channelIndex) * 2 + 1;
13511
13611
 
13512
13612
  return this._waveformData._adapter.at(offset);
13513
13613
  };
13514
13614
 
13515
13615
  /**
13516
- * Returns all the waveform minimum values as an array.
13616
+ * Returns all the min values within the current offset.
13617
+ *
13618
+ * ```javascript
13619
+ * var waveform = WaveformData.create({ ... });
13620
+ * var channel = waveform.channel(0);
13621
+ *
13622
+ * console.log(channel.min_array()); // -> [-7, -5, -10]
13623
+ * ```
13624
+ *
13625
+ * @return {Array.<Integer>} Min values contained in the offset.
13517
13626
  */
13518
13627
 
13519
13628
  WaveformDataChannel.prototype.min_array = function() {
@@ -13525,7 +13634,16 @@ WaveformDataChannel.prototype.min_array = function() {
13525
13634
  };
13526
13635
 
13527
13636
  /**
13528
- * Returns all the waveform maximum values as an array.
13637
+ * Returns all the max values within the current offset.
13638
+ *
13639
+ * ```javascript
13640
+ * var waveform = WaveformData.create({ ... });
13641
+ * var channel = waveform.channel(0);
13642
+ *
13643
+ * console.log(channel.max_array()); // -> [9, 6, 11]
13644
+ * ```
13645
+ *
13646
+ * @return {Array.<Integer>} Max values contained in the offset.
13529
13647
  */
13530
13648
 
13531
13649
  WaveformDataChannel.prototype.max_array = function() {
@@ -13551,7 +13669,32 @@ var adapters = [
13551
13669
  ];
13552
13670
 
13553
13671
  /**
13554
- * Provides access to waveform data.
13672
+ * Facade to iterate on audio waveform response.
13673
+ *
13674
+ * ```javascript
13675
+ * var waveform = new WaveformData({ ... });
13676
+ *
13677
+ * var json_waveform = new WaveformData(xhr.responseText);
13678
+ *
13679
+ * var arraybuff_waveform = new WaveformData(
13680
+ * getArrayBufferData()
13681
+ * );
13682
+ * ```
13683
+ *
13684
+ * ## Offsets
13685
+ *
13686
+ * An **offset** is a non-destructive way to iterate on a subset of data.
13687
+ *
13688
+ * It is the easiest way to **navigate** through data without having to deal
13689
+ * with complex calculations. Simply iterate over the data to display them.
13690
+ *
13691
+ * *Notice*: the default offset is the entire set of data.
13692
+ *
13693
+ * @param {String|ArrayBuffer|Object} data Waveform data,
13694
+ * to be consumed by the related adapter.
13695
+ * @param {WaveformData.adapter|Function} adapter Backend adapter used to manage
13696
+ * access to the data.
13697
+ * @constructor
13555
13698
  */
13556
13699
 
13557
13700
  function WaveformData(data) {
@@ -13561,19 +13704,45 @@ function WaveformData(data) {
13561
13704
 
13562
13705
  this._channels = [];
13563
13706
 
13564
- for (var channel = 0; channel < this.channels; channel++) {
13707
+ for (let channel = 0; channel < this.channels; channel++) {
13565
13708
  this._channels[channel] = new WaveformDataChannel(this, channel);
13566
13709
  }
13567
13710
  }
13568
13711
 
13569
13712
  /**
13570
- * Creates and returns a WaveformData instance from the given waveform data.
13713
+ * Creates an instance of WaveformData by guessing the adapter from the
13714
+ * data type. It can also accept an XMLHttpRequest response.
13715
+ *
13716
+ * ```javascript
13717
+ * var xhr = new XMLHttpRequest();
13718
+ * xhr.open("GET", "http://example.com/waveforms/track.dat");
13719
+ * xhr.responseType = "arraybuffer";
13720
+ *
13721
+ * xhr.addEventListener("load", function onResponse(progressEvent) {
13722
+ * var waveform = WaveformData.create(progressEvent.target);
13723
+ *
13724
+ * console.log(waveform.duration);
13725
+ * });
13726
+ *
13727
+ * xhr.send();
13728
+ * ```
13729
+ *
13730
+ * @static
13731
+ * @throws TypeError
13732
+ * @param {Object} data
13733
+ * @return {WaveformData}
13571
13734
  */
13572
13735
 
13573
13736
  WaveformData.create = function create(data) {
13574
13737
  return new WaveformData(data);
13575
13738
  };
13576
13739
 
13740
+ /**
13741
+ * Public API for the Waveform Data manager.
13742
+ *
13743
+ * @namespace WaveformData
13744
+ */
13745
+
13577
13746
  WaveformData.prototype = {
13578
13747
 
13579
13748
  _getAdapter: function(data) {
@@ -13587,23 +13756,47 @@ WaveformData.prototype = {
13587
13756
  });
13588
13757
 
13589
13758
  if (Adapter === null) {
13590
- throw new TypeError(
13591
- "WaveformData.create(): Could not detect a WaveformData adapter from the input"
13592
- );
13759
+ throw new TypeError("Could not detect a WaveformData adapter from the input.");
13593
13760
  }
13594
13761
 
13595
13762
  return Adapter;
13596
13763
  },
13597
13764
 
13598
13765
  /**
13599
- * Creates and returns a new WaveformData object with resampled data.
13600
- * Use this method to create waveform data at different zoom levels.
13766
+ * Creates a new WaveformData object with resampled data.
13767
+ * Returns a rescaled waveform, to either fit the waveform to a specific
13768
+ * width, or to a specific zoom level.
13769
+ *
13770
+ * **Note**: You may specify either the *width* or the *scale*, but not both.
13771
+ * The `scale` will be deduced from the `width` you want to fit the data into.
13601
13772
  *
13602
13773
  * Adapted from Sequence::GetWaveDisplay in Audacity, with permission.
13603
- * https://code.google.com/p/audacity/source/browse/audacity-src/trunk/src/Sequence.cpp
13774
+ *
13775
+ * ```javascript
13776
+ * var waveform = WaveformData.create({ ... });
13777
+ * // ...
13778
+ *
13779
+ * // fitting the data in a 500px wide canvas
13780
+ * var resampled_waveform = waveform.resample({ width: 500 });
13781
+ *
13782
+ * console.log(resampled_waveform.min.length); // -> 500
13783
+ *
13784
+ * // zooming out on a 3 times less precise scale
13785
+ * var resampled_waveform = waveform.resample({ scale: waveform.scale * 3 });
13786
+ * ```
13787
+ *
13788
+ * @see https://code.google.com/p/audacity/source/browse/audacity-src/trunk/src/Sequence.cpp
13789
+ * @param {Number|{width: Number, scale: Number}} options Either a constraint width or a constraint sample rate
13790
+ * @return {WaveformData} New resampled object
13604
13791
  */
13605
13792
 
13606
13793
  resample: function(options) {
13794
+ if (typeof options === "number") {
13795
+ options = {
13796
+ width: options
13797
+ };
13798
+ }
13799
+
13607
13800
  options.input_index = typeof options.input_index === "number" ? options.input_index : null;
13608
13801
  options.output_index = typeof options.output_index === "number" ? options.output_index : null;
13609
13802
  options.scale = typeof options.scale === "number" ? options.scale : null;
@@ -13612,63 +13805,48 @@ WaveformData.prototype = {
13612
13805
  var is_partial_resampling = Boolean(options.input_index) || Boolean(options.output_index);
13613
13806
 
13614
13807
  if (options.input_index != null && (options.input_index < 0)) {
13615
- throw new RangeError(
13616
- "WaveformData.resample(): input_index should be a positive integer value"
13617
- );
13808
+ throw new RangeError("options.input_index should be a positive integer value. [" + options.input_index + "]");
13618
13809
  }
13619
13810
 
13620
13811
  if (options.output_index != null && (options.output_index < 0)) {
13621
- throw new RangeError(
13622
- "WaveformData.resample(): output_index should be a positive integer value"
13623
- );
13812
+ throw new RangeError("options.output_index should be a positive integer value. [" + options.output_index + "]");
13624
13813
  }
13625
13814
 
13626
13815
  if (options.width != null && (options.width <= 0)) {
13627
- throw new RangeError("WaveformData.resample(): width should be a positive integer value");
13816
+ throw new RangeError("options.width should be a strictly positive integer value. [" + options.width + "]");
13628
13817
  }
13629
13818
 
13630
13819
  if (options.scale != null && (options.scale <= 0)) {
13631
- throw new RangeError("WaveformData.resample(): scale should be a positive integer value");
13820
+ throw new RangeError("options.scale should be a strictly positive integer value. [" + options.scale + "]");
13632
13821
  }
13633
13822
 
13634
13823
  if (!options.scale && !options.width) {
13635
- throw new Error("WaveformData.resample(): Missing scale or width option");
13824
+ throw new RangeError("You should provide either a resampling scale or a width in pixel the data should fit in.");
13636
13825
  }
13637
13826
 
13638
- if (is_partial_resampling) {
13639
- if (options.width === null ||
13640
- options.scale === null ||
13641
- options.input_index === null ||
13642
- options.output_index === null) {
13643
- throw new Error(
13644
- "WaveformData.resample(): Missing width, scale, input_index, or output_index option"
13645
- );
13646
- }
13827
+ var definedPartialOptionsCount = ["width", "scale", "output_index", "input_index"].reduce(function(count, key) {
13828
+ return count + (options[key] === null ? 0 : 1);
13829
+ }, 0);
13830
+
13831
+ if (is_partial_resampling && definedPartialOptionsCount !== 4) {
13832
+ throw new Error("Some partial resampling options are missing. You provided " + definedPartialOptionsCount + " of them over 4.");
13647
13833
  }
13648
13834
 
13649
13835
  var output_data = [];
13650
- // Scale we want to reach
13651
- var samples_per_pixel = options.scale ||
13652
- Math.floor(this.duration * this.sample_rate / options.width);
13836
+ var samples_per_pixel = options.scale || Math.floor(this.duration * this.sample_rate / options.width); // scale we want to reach
13653
13837
  var scale = this.scale; // scale we are coming from
13654
13838
  var channel_count = 2 * this.channels;
13655
13839
 
13656
- // The amount of data we want to resample i.e. final zoom want to resample
13657
- // all data but for intermediate zoom we want to resample subset
13658
- var input_buffer_size = this.length;
13659
- // Is this start point? or is this the index at current scale?
13660
- var input_index = options.input_index || 0;
13661
- // Is this end point? or is this the index at scale we want to be?
13662
- var output_index = options.output_index || 0;
13840
+ var input_buffer_size = this.length; // the amount of data we want to resample i.e. final zoom want to resample all data but for intermediate zoom we want to resample subset
13841
+ var input_index = options.input_index || 0; // is this start point? or is this the index at current scale
13842
+ var output_index = options.output_index || 0; // is this end point? or is this the index at scale we want to be?
13663
13843
 
13664
13844
  var channels = this.channels;
13665
13845
 
13666
13846
  var min = new Array(channels);
13667
13847
  var max = new Array(channels);
13668
13848
 
13669
- var channel;
13670
-
13671
- for (channel = 0; channel < channels; ++channel) {
13849
+ for (let channel = 0; channel < channels; ++channel) {
13672
13850
  if (input_buffer_size > 0) {
13673
13851
  min[channel] = this.channel(channel).min_sample(input_index);
13674
13852
  max[channel] = this.channel(channel).max_sample(input_index);
@@ -13683,9 +13861,7 @@ WaveformData.prototype = {
13683
13861
  var max_value = 127;
13684
13862
 
13685
13863
  if (samples_per_pixel < scale) {
13686
- throw new Error(
13687
- "WaveformData.resample(): Zoom level " + samples_per_pixel + " too low, minimum: " + scale
13688
- );
13864
+ throw new Error("Zoom level " + samples_per_pixel + " too low, minimum: " + scale);
13689
13865
  }
13690
13866
 
13691
13867
  var where, prev_where, stop, value, last_input_index;
@@ -13694,11 +13870,15 @@ WaveformData.prototype = {
13694
13870
  return Math.floor(x * samples_per_pixel);
13695
13871
  }
13696
13872
 
13873
+ function add_sample(min, max) {
13874
+ output_data.push(min, max);
13875
+ }
13876
+
13697
13877
  while (input_index < input_buffer_size) {
13698
13878
  while (Math.floor(sample_at_pixel(output_index) / scale) <= input_index) {
13699
13879
  if (output_index > 0) {
13700
- for (channel = 0; channel < channels; ++channel) {
13701
- output_data.push(min[channel], max[channel]);
13880
+ for (let channel = 0; channel < channels; ++channel) {
13881
+ add_sample(min[channel], max[channel]);
13702
13882
  }
13703
13883
  }
13704
13884
 
@@ -13710,7 +13890,7 @@ WaveformData.prototype = {
13710
13890
  prev_where = sample_at_pixel(output_index - 1);
13711
13891
 
13712
13892
  if (where !== prev_where) {
13713
- for (channel = 0; channel < channels; ++channel) {
13893
+ for (let channel = 0; channel < channels; ++channel) {
13714
13894
  min[channel] = max_value;
13715
13895
  max[channel] = min_value;
13716
13896
  }
@@ -13725,7 +13905,7 @@ WaveformData.prototype = {
13725
13905
  }
13726
13906
 
13727
13907
  while (input_index < stop) {
13728
- for (channel = 0; channel < channels; ++channel) {
13908
+ for (let channel = 0; channel < channels; ++channel) {
13729
13909
  value = this.channel(channel).min_sample(input_index);
13730
13910
 
13731
13911
  if (value < min[channel]) {
@@ -13750,14 +13930,14 @@ WaveformData.prototype = {
13750
13930
  if (is_partial_resampling) {
13751
13931
  if ((output_data.length / channel_count) > options.width &&
13752
13932
  input_index !== last_input_index) {
13753
- for (channel = 0; channel < channels; ++channel) {
13754
- output_data.push(min[channel], max[channel]);
13933
+ for (let channel = 0; channel < channels; ++channel) {
13934
+ add_sample(min[channel], max[channel]);
13755
13935
  }
13756
13936
  }
13757
13937
  }
13758
13938
  else if (input_index !== last_input_index) {
13759
- for (channel = 0; channel < channels; ++channel) {
13760
- output_data.push(min[channel], max[channel]);
13939
+ for (let channel = 0; channel < channels; ++channel) {
13940
+ add_sample(min[channel], max[channel]);
13761
13941
  }
13762
13942
  }
13763
13943
 
@@ -13773,9 +13953,11 @@ WaveformData.prototype = {
13773
13953
  },
13774
13954
 
13775
13955
  /**
13776
- * Concatenates with one or more other waveforms, returning a new WaveformData object.
13956
+ * Return a new WaveformData instance with the concatenated result of multiple waveforms.
13957
+ *
13958
+ * @param {...WaveformData} otherWaveforms One or more waveform instances to concatenate
13959
+ * @return {WaveformData} New concatenated object
13777
13960
  */
13778
-
13779
13961
  concat: function() {
13780
13962
  var self = this;
13781
13963
  var otherWaveforms = Array.prototype.slice.call(arguments);
@@ -13787,7 +13969,7 @@ WaveformData.prototype = {
13787
13969
  self.scale !== otherWaveform.scale ||
13788
13970
  Object.getPrototypeOf(self._adapter) !== Object.getPrototypeOf(otherWaveform._adapter) ||
13789
13971
  self._adapter.version !== otherWaveform._adapter.version) {
13790
- throw new Error("WaveformData.concat(): Waveforms are incompatible");
13972
+ throw new Error("Waveforms are incompatible");
13791
13973
  }
13792
13974
  });
13793
13975
 
@@ -13802,6 +13984,12 @@ WaveformData.prototype = {
13802
13984
 
13803
13985
  /**
13804
13986
  * Return the unpacked values for a particular offset.
13987
+ *
13988
+ * @param {Integer} start
13989
+ * @param {Integer} length
13990
+ * @param {Integer} correction The step to skip for each iteration
13991
+ * (as the response body is [min, max, min, max...])
13992
+ * @return {Array.<Integer>}
13805
13993
  */
13806
13994
 
13807
13995
  _offsetValues: function getOffsetValues(start, length, correction) {
@@ -13820,6 +14008,14 @@ WaveformData.prototype = {
13820
14008
 
13821
14009
  /**
13822
14010
  * Returns the length of the waveform, in pixels.
14011
+ *
14012
+ * ```javascript
14013
+ * var waveform = WaveformData.create({ ... });
14014
+ * console.log(waveform.length); // -> 600
14015
+ * ```
14016
+ *
14017
+ * @api
14018
+ * @return {Integer} Length of the waveform, in pixels.
13823
14019
  */
13824
14020
 
13825
14021
  get length() {
@@ -13836,6 +14032,14 @@ WaveformData.prototype = {
13836
14032
 
13837
14033
  /**
13838
14034
  * Returns the (approximate) duration of the audio file, in seconds.
14035
+ *
14036
+ * ```javascript
14037
+ * var waveform = WaveformData.create({ ... });
14038
+ * console.log(waveform.duration); // -> 10.33333333333
14039
+ * ```
14040
+ *
14041
+ * @api
14042
+ * @return {number} Duration of the audio waveform, in seconds.
13839
14043
  */
13840
14044
 
13841
14045
  get duration() {
@@ -13843,7 +14047,16 @@ WaveformData.prototype = {
13843
14047
  },
13844
14048
 
13845
14049
  /**
13846
- * Returns the number of pixels per second.
14050
+ * Return the number of pixels per second.
14051
+ *
14052
+ * ```javascript
14053
+ * var waveform = WaveformData.create({ ... });
14054
+ *
14055
+ * console.log(waveform.pixels_per_second); // -> 93.75
14056
+ * ```
14057
+ *
14058
+ * @api
14059
+ * @return {number} Number of pixels per second.
13847
14060
  */
13848
14061
 
13849
14062
  get pixels_per_second() {
@@ -13851,7 +14064,15 @@ WaveformData.prototype = {
13851
14064
  },
13852
14065
 
13853
14066
  /**
13854
- * Returns the amount of time represented by a single pixel, in seconds.
14067
+ * Return the amount of time represented by a single pixel.
14068
+ *
14069
+ * ```javascript
14070
+ * var waveform = WaveformData.create({ ... });
14071
+ *
14072
+ * console.log(waveform.seconds_per_pixel); // -> 0.010666666666666666
14073
+ * ```
14074
+ *
14075
+ * @return {number} Amount of time (in seconds) contained in a pixel.
13855
14076
  */
13856
14077
 
13857
14078
  get seconds_per_pixel() {
@@ -13860,6 +14081,14 @@ WaveformData.prototype = {
13860
14081
 
13861
14082
  /**
13862
14083
  * Returns the number of waveform channels.
14084
+ *
14085
+ * ```javascript
14086
+ * var waveform = WaveformData.create({ ... });
14087
+ * console.log(waveform.channels); // -> 1
14088
+ * ```
14089
+ *
14090
+ * @api
14091
+ * @return {number} Number of channels.
13863
14092
  */
13864
14093
 
13865
14094
  get channels() {
@@ -13868,6 +14097,16 @@ WaveformData.prototype = {
13868
14097
 
13869
14098
  /**
13870
14099
  * Returns a waveform channel.
14100
+ *
14101
+ * ```javascript
14102
+ * var waveform = WaveformData.create({ ... });
14103
+ * var channel = waveform.channel(0);
14104
+ * console.log(channel.min_sample(0)); // -> 1
14105
+ * ```
14106
+ *
14107
+ * @api
14108
+ * @param {Number} Channel index.
14109
+ * @return {WaveformDataChannel} Waveform channel.
13871
14110
  */
13872
14111
 
13873
14112
  channel: function(index) {
@@ -13880,7 +14119,9 @@ WaveformData.prototype = {
13880
14119
  },
13881
14120
 
13882
14121
  /**
13883
- * Returns the number of audio samples per second.
14122
+ * Returns the number of samples per second.
14123
+ *
14124
+ * @return {Integer} Number of samples per second.
13884
14125
  */
13885
14126
 
13886
14127
  get sample_rate() {
@@ -13888,7 +14129,9 @@ WaveformData.prototype = {
13888
14129
  },
13889
14130
 
13890
14131
  /**
13891
- * Returns the number of audio samples per pixel.
14132
+ * Returns the scale (number of samples per pixel).
14133
+ *
14134
+ * @return {Integer} Number of samples per pixel.
13892
14135
  */
13893
14136
 
13894
14137
  get scale() {
@@ -13896,7 +14139,10 @@ WaveformData.prototype = {
13896
14139
  },
13897
14140
 
13898
14141
  /**
13899
- * Returns the waveform data index position for a given time.
14142
+ * Returns the pixel location for a given time.
14143
+ *
14144
+ * @param {number} time
14145
+ * @return {integer} Index location for a specific time.
13900
14146
  */
13901
14147
 
13902
14148
  at_time: function at_time(time) {
@@ -13904,36 +14150,14 @@ WaveformData.prototype = {
13904
14150
  },
13905
14151
 
13906
14152
  /**
13907
- * Returns the time in seconds for a given index.
14153
+ * Returns the time in seconds for a given index
14154
+ *
14155
+ * @param {Integer} index
14156
+ * @return {number}
13908
14157
  */
13909
14158
 
13910
14159
  time: function time(index) {
13911
14160
  return index * this.scale / this.sample_rate;
13912
- },
13913
-
13914
- /**
13915
- * Returns an object containing the waveform data.
13916
- */
13917
-
13918
- toJSON: function() {
13919
- const waveform = {
13920
- version: 2,
13921
- channels: this.channels,
13922
- sample_rate: this.sample_rate,
13923
- samples_per_pixel: this.scale,
13924
- bits: this.bits,
13925
- length: this.length,
13926
- data: []
13927
- };
13928
-
13929
- for (var i = 0; i < this.length; i++) {
13930
- for (var channel = 0; channel < this.channels; channel++) {
13931
- waveform.data.push(this.channel(channel).min_sample(i));
13932
- waveform.data.push(this.channel(channel).max_sample(i));
13933
- }
13934
- }
13935
-
13936
- return waveform;
13937
14161
  }
13938
14162
  };
13939
14163
 
@@ -13942,54 +14166,13 @@ module.exports = WaveformData;
13942
14166
  },{"./adapters/arraybuffer":77,"./adapters/object":78,"./channel":82}],84:[function(_dereq_,module,exports){
13943
14167
  "use strict";
13944
14168
 
13945
- function MainThreadWorker(func) {
13946
- this._listeners = {};
13947
-
13948
- func.call(this);
13949
- }
13950
-
13951
- MainThreadWorker.prototype.addEventListener = function(event, listener) {
13952
- if (!this._listeners[event]) {
13953
- this._listeners[event] = [];
13954
- }
13955
-
13956
- this._listeners[event].push(listener);
13957
- };
13958
-
13959
- MainThreadWorker.prototype.removeEventListener = function(event, listener) {
13960
- if (this._listeners[event]) {
13961
- this._listeners[event] = this._listeners[event].filter(function(item) {
13962
- return item !== listener;
13963
- });
13964
- }
13965
- };
13966
-
13967
- MainThreadWorker.prototype.postMessage = function(data) {
13968
- var event = { data: data };
13969
-
13970
- var listeners = this._listeners.message;
13971
-
13972
- for (var i = 0; i < listeners.length; i++) {
13973
- listeners[i].call(this, event);
13974
- }
13975
- };
13976
-
13977
- MainThreadWorker.prototype.close = function() {
13978
- this._listeners = {};
13979
- };
13980
-
13981
- module.exports = MainThreadWorker;
13982
-
13983
- },{}],85:[function(_dereq_,module,exports){
13984
- "use strict";
13985
-
13986
14169
  var WaveformData = _dereq_("./lib/core");
13987
14170
 
13988
14171
  WaveformData.createFromAudio = _dereq_("./lib/builders/webaudio");
13989
14172
 
13990
14173
  module.exports = WaveformData;
13991
14174
 
13992
- },{"./lib/builders/webaudio":81,"./lib/core":83}],86:[function(_dereq_,module,exports){
14175
+ },{"./lib/builders/webaudio":81,"./lib/core":83}],85:[function(_dereq_,module,exports){
13993
14176
  module.exports = function (Data) {
13994
14177
  'use strict';
13995
14178
  function DataRetriever(peaks) {
@@ -14039,7 +14222,7 @@ module.exports = function (Data) {
14039
14222
  };
14040
14223
  return DataRetriever;
14041
14224
  }(_dereq_('./data'));
14042
- },{"./data":87}],87:[function(_dereq_,module,exports){
14225
+ },{"./data":86}],86:[function(_dereq_,module,exports){
14043
14226
  module.exports = function () {
14044
14227
  'use strict';
14045
14228
  function Data(type, content) {
@@ -14071,7 +14254,7 @@ module.exports = function () {
14071
14254
  };
14072
14255
  return Data;
14073
14256
  }();
14074
- },{}],88:[function(_dereq_,module,exports){
14257
+ },{}],87:[function(_dereq_,module,exports){
14075
14258
  module.exports = function (Utils, Konva) {
14076
14259
  'use strict';
14077
14260
  function DefaultSegmentMarker(options) {
@@ -14155,7 +14338,7 @@ module.exports = function (Utils, Konva) {
14155
14338
  };
14156
14339
  return DefaultSegmentMarker;
14157
14340
  }(_dereq_('./utils'), _dereq_('konva'));
14158
- },{"./utils":111,"konva":43}],89:[function(_dereq_,module,exports){
14341
+ },{"./utils":110,"konva":43}],88:[function(_dereq_,module,exports){
14159
14342
  module.exports = function () {
14160
14343
  'use strict';
14161
14344
  function Invoker() {
@@ -14204,7 +14387,7 @@ module.exports = function () {
14204
14387
  };
14205
14388
  return Invoker;
14206
14389
  }();
14207
- },{}],90:[function(_dereq_,module,exports){
14390
+ },{}],89:[function(_dereq_,module,exports){
14208
14391
  module.exports = function () {
14209
14392
  'use strict';
14210
14393
  var nodes = [
@@ -14287,7 +14470,7 @@ module.exports = function () {
14287
14470
  };
14288
14471
  return KeyboardHandler;
14289
14472
  }();
14290
- },{}],91:[function(_dereq_,module,exports){
14473
+ },{}],90:[function(_dereq_,module,exports){
14291
14474
  module.exports = function (Konva, Utils) {
14292
14475
  'use strict';
14293
14476
  function LineIndicator(peaks, view, container) {
@@ -14320,22 +14503,57 @@ module.exports = function (Konva, Utils) {
14320
14503
  if (this._peaks.options.enableLineIndicatorContextMenu) {
14321
14504
  this._createContextMenu();
14322
14505
  }
14506
+ this.ICON_SIZE = 18;
14507
+ this._volumeSVGPath = 'M0 6.00001V12H4L9 17V1.00001L4 6.00001H0ZM13.5 9.00001C13.5 7.23001 12.48 5.71001 11 4.97001V13.02C12.48 12.29 13.5 10.77 13.5 9.00001ZM11 0.230011V2.29001C13.89 3.15001 16 5.83001 16 9.00001C16 12.17 13.89 14.85 11 15.71V17.77C15.01 16.86 18 13.28 18 9.00001C18 4.72001 15.01 1.14001 11 0.230011Z';
14508
+ this._noVolumeSVGPath = 'M13.5 9C13.5 7.23 12.48 5.71 11 4.97V7.18L13.45 9.63C13.48 9.43 13.5 9.22 13.5 9ZM16 9C16 9.94 15.8 10.82 15.46 11.64L16.97 13.15C17.63 11.91 18 10.5 18 9C18 4.72 15.01 1.14 11 0.23V2.29C13.89 3.15 16 5.83 16 9ZM1.27 0L0 1.27L4.73 6H0V12H4L9 17V10.27L13.25 14.52C12.58 15.04 11.83 15.45 11 15.7V17.76C12.38 17.45 13.63 16.81 14.69 15.95L16.73 18L18 16.73L9 7.73L1.27 0ZM9 1L6.91 3.09L9 5.18V1Z';
14509
+ this._peaks.on('lineIndicator.setType', this._onSetType.bind(this));
14510
+ this._types = [
14511
+ 'default',
14512
+ 'volume',
14513
+ 'noVolume'
14514
+ ];
14323
14515
  }
14516
+ LineIndicator.prototype._onSetType = function (lineId, type) {
14517
+ this.removeIndicator(lineId, true);
14518
+ type = this._types.includes(type) ? type : 'default';
14519
+ var indicator = this._createIndicator(this._indicators[lineId].line, type);
14520
+ this._layer.add(indicator);
14521
+ this._indicators[lineId].indicator = indicator;
14522
+ this._indicators[lineId].type = type;
14523
+ this.draw();
14524
+ };
14324
14525
  LineIndicator.prototype._showMenu = function (menu) {
14325
14526
  menu.style.display = 'block';
14326
14527
  var containerRect = this._stage.container().getBoundingClientRect();
14327
14528
  menu.style.top = containerRect.top + this._stage.getPointerPosition().y - menu.offsetHeight + 'px';
14328
14529
  menu.style.left = containerRect.left + this._stage.getPointerPosition().x + 6 + 'px';
14329
14530
  };
14330
- LineIndicator.prototype._createIndicator = function (line) {
14331
- var indicator = new Konva.Circle({
14332
- x: this._width / 2,
14333
- y: line.getY() + line.lineHeight() / 2,
14334
- radius: this._indicatorRadius,
14335
- fill: this._peaks.options.lineIndicatorColor,
14336
- strokeWidth: 0,
14337
- lineId: line.getId()
14338
- });
14531
+ LineIndicator.prototype._createIndicator = function (line, type) {
14532
+ var indicator;
14533
+ type = typeof type !== 'undefined' ? type : 'default';
14534
+ if (type === 'default') {
14535
+ indicator = new Konva.Circle({
14536
+ x: this._width / 2,
14537
+ y: line.getY() + line.lineHeight() / 2,
14538
+ radius: this._indicatorRadius,
14539
+ fill: this._peaks.options.lineIndicatorColor,
14540
+ strokeWidth: 0,
14541
+ lineId: line.getId()
14542
+ });
14543
+ } else {
14544
+ var scaleFactor = this._width / 2 / this.ICON_SIZE;
14545
+ indicator = new Konva.Path({
14546
+ x: this._width / 4,
14547
+ y: line.getY() + line.lineHeight() / 2 - this._width / 4,
14548
+ data: type === 'volume' ? this._volumeSVGPath : this._noVolumeSVGPath,
14549
+ fill: this._peaks.options.lineIndicatorColor,
14550
+ scale: {
14551
+ x: scaleFactor,
14552
+ y: scaleFactor
14553
+ },
14554
+ lineId: line.getId()
14555
+ });
14556
+ }
14339
14557
  var self = this;
14340
14558
  indicator.on('mouseover', function () {
14341
14559
  indicator.fill(self._peaks.options.lineIndicatorSelected);
@@ -14345,6 +14563,9 @@ module.exports = function (Konva, Utils) {
14345
14563
  indicator.fill(self._peaks.options.lineIndicatorColor);
14346
14564
  indicator.draw();
14347
14565
  });
14566
+ indicator.on('click', function (e) {
14567
+ self._peaks.emit('lineIndicator.click', self._indicators[line.getId()], e.evt.button);
14568
+ });
14348
14569
  return indicator;
14349
14570
  };
14350
14571
  LineIndicator.prototype.addIndicator = function (line) {
@@ -14353,7 +14574,8 @@ module.exports = function (Konva, Utils) {
14353
14574
  this._layer.add(indicator);
14354
14575
  this._indicators[line.getId()] = {
14355
14576
  indicator: indicator,
14356
- line: line
14577
+ line: line,
14578
+ type: 'default'
14357
14579
  };
14358
14580
  }
14359
14581
  };
@@ -14369,15 +14591,18 @@ module.exports = function (Konva, Utils) {
14369
14591
  }
14370
14592
  }
14371
14593
  };
14594
+ LineIndicator.prototype.getPixelsFromCenter = function (lineId) {
14595
+ return this._indicators[lineId].type === 'default' ? 0 : this._width / 4;
14596
+ };
14372
14597
  LineIndicator.prototype.updateIndicator = function (lineId) {
14373
14598
  if (this._indicators[lineId]) {
14374
14599
  var y = this._indicators[lineId].line.getY() + this._indicators[lineId].line.lineHeight() / 2;
14375
14600
  if (y + this._indicatorRadius > 0 && y - this._indicatorRadius < this._height) {
14376
14601
  if (!this._indicators[lineId].indicator) {
14377
- this._indicators[lineId].indicator = this._createIndicator(this._indicators[lineId].line);
14602
+ this._indicators[lineId].indicator = this._createIndicator(this._indicators[lineId].line, this._indicators[lineId].type);
14378
14603
  this._layer.add(this._indicators[lineId].indicator);
14379
14604
  } else {
14380
- this._indicators[lineId].indicator.y(y);
14605
+ this._indicators[lineId].indicator.y(y - this.getPixelsFromCenter(lineId));
14381
14606
  }
14382
14607
  } else {
14383
14608
  this.removeIndicator(lineId, true);
@@ -14508,7 +14733,7 @@ module.exports = function (Konva, Utils) {
14508
14733
  };
14509
14734
  return LineIndicator;
14510
14735
  }(_dereq_('konva'), _dereq_('./utils'));
14511
- },{"./utils":111,"konva":43}],92:[function(_dereq_,module,exports){
14736
+ },{"./utils":110,"konva":43}],91:[function(_dereq_,module,exports){
14512
14737
  module.exports = function (Konva, Utils) {
14513
14738
  'use strict';
14514
14739
  function Line(peaks, view, y, id, position) {
@@ -14971,7 +15196,7 @@ module.exports = function (Konva, Utils) {
14971
15196
  };
14972
15197
  return Line;
14973
15198
  }(_dereq_('konva'), _dereq_('./utils'));
14974
- },{"./utils":111,"konva":43}],93:[function(_dereq_,module,exports){
15199
+ },{"./utils":110,"konva":43}],92:[function(_dereq_,module,exports){
14975
15200
  module.exports = function (SegmentsGroup, Line, LineIndicator, Utils) {
14976
15201
  'use strict';
14977
15202
  function Lines(peaks, view, layer) {
@@ -15174,6 +15399,9 @@ module.exports = function (SegmentsGroup, Line, LineIndicator, Utils) {
15174
15399
  }
15175
15400
  }
15176
15401
  };
15402
+ Lines.prototype.getLineByPosition = function (pos) {
15403
+ return this._linesByPosition[pos];
15404
+ };
15177
15405
  Lines.prototype.getLineOnPosition = function (y) {
15178
15406
  var height;
15179
15407
  var pos = [
@@ -15270,7 +15498,7 @@ module.exports = function (SegmentsGroup, Line, LineIndicator, Utils) {
15270
15498
  };
15271
15499
  return Lines;
15272
15500
  }(_dereq_('./segments-group'), _dereq_('./line'), _dereq_('./line-indicator'), _dereq_('./utils'));
15273
- },{"./line":92,"./line-indicator":91,"./segments-group":103,"./utils":111}],94:[function(_dereq_,module,exports){
15501
+ },{"./line":91,"./line-indicator":90,"./segments-group":102,"./utils":110}],93:[function(_dereq_,module,exports){
15274
15502
  module.exports = function (Colors, EventEmitter, TimelineSegments, TimelineSources, KeyboardHandler, Player, MarkerFactories, TimelineZoomView, Utils) {
15275
15503
  'use strict';
15276
15504
  function Peaks() {
@@ -15320,7 +15548,7 @@ module.exports = function (Colors, EventEmitter, TimelineSegments, TimelineSourc
15320
15548
  segmentMagnetThreshold: 15,
15321
15549
  enableVerticalScrolling: true,
15322
15550
  lineIndicatorWidth: 20,
15323
- lineIndicatorColor: 'gray',
15551
+ lineIndicatorColor: '#8A8F98',
15324
15552
  lineIndicatorSelected: '#ccc',
15325
15553
  autoScrollThreshold: 0.05,
15326
15554
  enableLineIndicatorContextMenu: true,
@@ -15459,6 +15687,10 @@ module.exports = function (Colors, EventEmitter, TimelineSegments, TimelineSourc
15459
15687
  Peaks.prototype.setCutMode = function () {
15460
15688
  this.emit('cut_mode');
15461
15689
  };
15690
+ Peaks.prototype.setIndicatorType = function (linePosition, type) {
15691
+ var lineId = this.view.getLineByPosition(linePosition).getId();
15692
+ this.emit('lineIndicator.setType', lineId, type);
15693
+ };
15462
15694
  Peaks.prototype.getVisibleSegments = function () {
15463
15695
  return this.view.getSegmentsGroup().getVisibleSegments();
15464
15696
  };
@@ -15509,7 +15741,7 @@ module.exports = function (Colors, EventEmitter, TimelineSegments, TimelineSourc
15509
15741
  };
15510
15742
  return Peaks;
15511
15743
  }(_dereq_('colors.css'), _dereq_('eventemitter2'), _dereq_('./timeline-segments'), _dereq_('./timeline-sources'), _dereq_('./keyboard-handler'), _dereq_('./player'), _dereq_('./marker-factories'), _dereq_('./timeline-zoomview'), _dereq_('./utils'));
15512
- },{"./keyboard-handler":90,"./marker-factories":95,"./player":98,"./timeline-segments":108,"./timeline-sources":109,"./timeline-zoomview":110,"./utils":111,"colors.css":1,"eventemitter2":2}],95:[function(_dereq_,module,exports){
15744
+ },{"./keyboard-handler":89,"./marker-factories":94,"./player":97,"./timeline-segments":107,"./timeline-sources":108,"./timeline-zoomview":109,"./utils":110,"colors.css":1,"eventemitter2":2}],94:[function(_dereq_,module,exports){
15513
15745
  module.exports = function (DefaultSegmentMarker, Utils, Konva) {
15514
15746
  'use strict';
15515
15747
  function createSegmentMarker(options) {
@@ -15541,7 +15773,7 @@ module.exports = function (DefaultSegmentMarker, Utils, Konva) {
15541
15773
  createSegmentLabel: createSegmentLabel
15542
15774
  };
15543
15775
  }(_dereq_('./default-segment-marker'), _dereq_('./utils'), _dereq_('konva'));
15544
- },{"./default-segment-marker":88,"./utils":111,"konva":43}],96:[function(_dereq_,module,exports){
15776
+ },{"./default-segment-marker":87,"./utils":110,"konva":43}],95:[function(_dereq_,module,exports){
15545
15777
  module.exports = function (Utils, SourceGroup, Konva) {
15546
15778
  'use strict';
15547
15779
  var TIME_X_OFFSET = 20;
@@ -15813,7 +16045,7 @@ module.exports = function (Utils, SourceGroup, Konva) {
15813
16045
  };
15814
16046
  return ModeLayer;
15815
16047
  }(_dereq_('./utils'), _dereq_('./source-group'), _dereq_('konva'));
15816
- },{"./source-group":104,"./utils":111,"konva":43}],97:[function(_dereq_,module,exports){
16048
+ },{"./source-group":103,"./utils":110,"konva":43}],96:[function(_dereq_,module,exports){
15817
16049
  module.exports = function (Konva) {
15818
16050
  'use strict';
15819
16051
  function getMarkerObject(obj) {
@@ -15909,7 +16141,7 @@ module.exports = function (Konva) {
15909
16141
  };
15910
16142
  return MouseDragHandler;
15911
16143
  }(_dereq_('konva'));
15912
- },{"konva":43}],98:[function(_dereq_,module,exports){
16144
+ },{"konva":43}],97:[function(_dereq_,module,exports){
15913
16145
  module.exports = function (Utils) {
15914
16146
  'use strict';
15915
16147
  function Player(peaks) {
@@ -15993,7 +16225,7 @@ module.exports = function (Utils) {
15993
16225
  };
15994
16226
  return Player;
15995
16227
  }(_dereq_('./utils'));
15996
- },{"./utils":111}],99:[function(_dereq_,module,exports){
16228
+ },{"./utils":110}],98:[function(_dereq_,module,exports){
15997
16229
  module.exports = function (Utils, Konva) {
15998
16230
  'use strict';
15999
16231
  var HANDLE_RADIUS = 10;
@@ -16238,7 +16470,7 @@ module.exports = function (Utils, Konva) {
16238
16470
  };
16239
16471
  return PlayheadLayer;
16240
16472
  }(_dereq_('./utils'), _dereq_('konva'));
16241
- },{"./utils":111,"konva":43}],100:[function(_dereq_,module,exports){
16473
+ },{"./utils":110,"konva":43}],99:[function(_dereq_,module,exports){
16242
16474
  module.exports = function (Konva) {
16243
16475
  'use strict';
16244
16476
  function SegmentMarker(options) {
@@ -16324,7 +16556,7 @@ module.exports = function (Konva) {
16324
16556
  };
16325
16557
  return SegmentMarker;
16326
16558
  }(_dereq_('konva'));
16327
- },{"konva":43}],101:[function(_dereq_,module,exports){
16559
+ },{"konva":43}],100:[function(_dereq_,module,exports){
16328
16560
  module.exports = function (Konva, SegmentMarker) {
16329
16561
  'use strict';
16330
16562
  var SEGMENT_WIDTH = 10;
@@ -16561,7 +16793,7 @@ module.exports = function (Konva, SegmentMarker) {
16561
16793
  };
16562
16794
  return SegmentShape;
16563
16795
  }(_dereq_('konva'), _dereq_('./segment-marker'));
16564
- },{"./segment-marker":100,"konva":43}],102:[function(_dereq_,module,exports){
16796
+ },{"./segment-marker":99,"konva":43}],101:[function(_dereq_,module,exports){
16565
16797
  module.exports = function (Utils) {
16566
16798
  'use strict';
16567
16799
  function validateSegment(peaks, options, context) {
@@ -16755,7 +16987,7 @@ module.exports = function (Utils) {
16755
16987
  };
16756
16988
  return Segment;
16757
16989
  }(_dereq_('./utils'));
16758
- },{"./utils":111}],103:[function(_dereq_,module,exports){
16990
+ },{"./utils":110}],102:[function(_dereq_,module,exports){
16759
16991
  module.exports = function (SegmentShape, Utils, Konva) {
16760
16992
  'use strict';
16761
16993
  function SegmentsGroup(peaks, view, allowEditing) {
@@ -17252,7 +17484,7 @@ module.exports = function (SegmentShape, Utils, Konva) {
17252
17484
  };
17253
17485
  return SegmentsGroup;
17254
17486
  }(_dereq_('./segment-shape'), _dereq_('./utils'), _dereq_('konva'));
17255
- },{"./segment-shape":101,"./utils":111,"konva":43}],104:[function(_dereq_,module,exports){
17487
+ },{"./segment-shape":100,"./utils":110,"konva":43}],103:[function(_dereq_,module,exports){
17256
17488
  module.exports = function (WaveformBuilder, WaveformShape, Utils, Konva) {
17257
17489
  'use strict';
17258
17490
  var SPACING_BETWEEN_PREVIEW_AND_BORDER_RATIO = 0.15;
@@ -17957,7 +18189,7 @@ module.exports = function (WaveformBuilder, WaveformShape, Utils, Konva) {
17957
18189
  };
17958
18190
  return SourceGroup;
17959
18191
  }(_dereq_('./waveform-builder'), _dereq_('./waveform-shape'), _dereq_('./utils'), _dereq_('konva'));
17960
- },{"./utils":111,"./waveform-builder":112,"./waveform-shape":113,"konva":43}],105:[function(_dereq_,module,exports){
18192
+ },{"./utils":110,"./waveform-builder":111,"./waveform-shape":112,"konva":43}],104:[function(_dereq_,module,exports){
17961
18193
  module.exports = function (Utils) {
17962
18194
  'use strict';
17963
18195
  function validateSource(peaks, options, context) {
@@ -18494,7 +18726,7 @@ module.exports = function (Utils) {
18494
18726
  };
18495
18727
  return Source;
18496
18728
  }(_dereq_('./utils'));
18497
- },{"./utils":111}],106:[function(_dereq_,module,exports){
18729
+ },{"./utils":110}],105:[function(_dereq_,module,exports){
18498
18730
  module.exports = function (SourceGroup, Lines, DataRetriever, Utils, Invoker, Konva) {
18499
18731
  'use strict';
18500
18732
  function SourcesLayer(peaks, view, allowEditing) {
@@ -18839,9 +19071,12 @@ module.exports = function (SourceGroup, Lines, DataRetriever, Utils, Invoker, Ko
18839
19071
  SourcesLayer.prototype.getLength = function () {
18840
19072
  return this._lines.linesLength();
18841
19073
  };
19074
+ SourcesLayer.prototype.getLineByPosition = function (pos) {
19075
+ return this._lines.getLineByPosition(pos);
19076
+ };
18842
19077
  return SourcesLayer;
18843
19078
  }(_dereq_('./source-group'), _dereq_('./lines'), _dereq_('./data-retriever'), _dereq_('./utils'), _dereq_('./invoker'), _dereq_('konva'));
18844
- },{"./data-retriever":86,"./invoker":89,"./lines":93,"./source-group":104,"./utils":111,"konva":43}],107:[function(_dereq_,module,exports){
19079
+ },{"./data-retriever":85,"./invoker":88,"./lines":92,"./source-group":103,"./utils":110,"konva":43}],106:[function(_dereq_,module,exports){
18845
19080
  module.exports = function (Utils, Konva) {
18846
19081
  'use strict';
18847
19082
  var LEFT_PADDING = 4;
@@ -18982,7 +19217,7 @@ module.exports = function (Utils, Konva) {
18982
19217
  };
18983
19218
  return TimelineAxis;
18984
19219
  }(_dereq_('./utils'), _dereq_('konva'));
18985
- },{"./utils":111,"konva":43}],108:[function(_dereq_,module,exports){
19220
+ },{"./utils":110,"konva":43}],107:[function(_dereq_,module,exports){
18986
19221
  module.exports = function (Colors, Segment, Utils) {
18987
19222
  'use strict';
18988
19223
  function TimelineSegments(peaks) {
@@ -19132,7 +19367,7 @@ module.exports = function (Colors, Segment, Utils) {
19132
19367
  };
19133
19368
  return TimelineSegments;
19134
19369
  }(_dereq_('colors.css'), _dereq_('./segment'), _dereq_('./utils'));
19135
- },{"./segment":102,"./utils":111,"colors.css":1}],109:[function(_dereq_,module,exports){
19370
+ },{"./segment":101,"./utils":110,"colors.css":1}],108:[function(_dereq_,module,exports){
19136
19371
  module.exports = function (Source, Utils) {
19137
19372
  'use strict';
19138
19373
  function TimelineSources(peaks) {
@@ -19299,7 +19534,7 @@ module.exports = function (Source, Utils) {
19299
19534
  };
19300
19535
  return TimelineSources;
19301
19536
  }(_dereq_('./source'), _dereq_('./utils'));
19302
- },{"./source":105,"./utils":111}],110:[function(_dereq_,module,exports){
19537
+ },{"./source":104,"./utils":110}],109:[function(_dereq_,module,exports){
19303
19538
  module.exports = function (MouseDragHandler, PlayheadLayer, SourcesLayer, ModeLayer, TimelineAxis, Utils, Konva) {
19304
19539
  'use strict';
19305
19540
  function TimelineZoomView(container, peaks) {
@@ -19710,6 +19945,9 @@ module.exports = function (MouseDragHandler, PlayheadLayer, SourcesLayer, ModeLa
19710
19945
  TimelineZoomView.prototype.getEndTime = function () {
19711
19946
  return this.pixelsToTime(this._frameOffset + this._width);
19712
19947
  };
19948
+ TimelineZoomView.prototype.getLineByPosition = function (pos) {
19949
+ return this._sourcesLayer.getLineByPosition(pos);
19950
+ };
19713
19951
  TimelineZoomView.prototype.setStartTime = function (time) {
19714
19952
  if (time < 0) {
19715
19953
  time = 0;
@@ -19848,7 +20086,7 @@ module.exports = function (MouseDragHandler, PlayheadLayer, SourcesLayer, ModeLa
19848
20086
  };
19849
20087
  return TimelineZoomView;
19850
20088
  }(_dereq_('./mouse-drag-handler'), _dereq_('./playhead-layer'), _dereq_('./sources-layer'), _dereq_('./mode-layer'), _dereq_('./timeline-axis'), _dereq_('./utils'), _dereq_('konva'));
19851
- },{"./mode-layer":96,"./mouse-drag-handler":97,"./playhead-layer":99,"./sources-layer":106,"./timeline-axis":107,"./utils":111,"konva":43}],111:[function(_dereq_,module,exports){
20089
+ },{"./mode-layer":95,"./mouse-drag-handler":96,"./playhead-layer":98,"./sources-layer":105,"./timeline-axis":106,"./utils":110,"konva":43}],110:[function(_dereq_,module,exports){
19852
20090
  module.exports = function (UUID) {
19853
20091
  'use strict';
19854
20092
  if (typeof Number.isFinite !== 'function') {
@@ -20012,7 +20250,7 @@ module.exports = function (UUID) {
20012
20250
  }
20013
20251
  };
20014
20252
  }(_dereq_('uuid'));
20015
- },{"uuid":62}],112:[function(_dereq_,module,exports){
20253
+ },{"uuid":62}],111:[function(_dereq_,module,exports){
20016
20254
  module.exports = function (WaveformData, Utils) {
20017
20255
  'use strict';
20018
20256
  var isXhr2 = 'withCredentials' in new XMLHttpRequest();
@@ -20204,7 +20442,7 @@ module.exports = function (WaveformData, Utils) {
20204
20442
  };
20205
20443
  return WaveformBuilder;
20206
20444
  }(_dereq_('waveform-data'), _dereq_('./utils'));
20207
- },{"./utils":111,"waveform-data":85}],113:[function(_dereq_,module,exports){
20445
+ },{"./utils":110,"waveform-data":84}],112:[function(_dereq_,module,exports){
20208
20446
  module.exports = function (Utils, Konva) {
20209
20447
  'use strict';
20210
20448
  function scaleY(amplitude, height, scale) {
@@ -20297,6 +20535,6 @@ module.exports = function (Utils, Konva) {
20297
20535
  };
20298
20536
  return WaveformShape;
20299
20537
  }(_dereq_('./utils'), _dereq_('konva'));
20300
- },{"./utils":111,"konva":43}]},{},[94])(94)
20538
+ },{"./utils":110,"konva":43}]},{},[93])(93)
20301
20539
  });
20302
20540
  //# sourceMappingURL=peaks.js.map