Skip to content

Commit 84fc4ea

Browse files
committed
Added slice method
See #84
1 parent fe7bb04 commit 84fc4ea

3 files changed

Lines changed: 189 additions & 2 deletions

File tree

doc/API.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
* [.channel](#waveformDatachannelindex)
1717
* [.resample](#waveformDataresampleoptions)
1818
* [.concat](#waveformDataconcatwaveforms)
19+
* [.slice](#waveformDatasliceoptions)
1920
* [.toJSON](#waveformDatatojson)
2021
* [.toArrayBuffer](#waveformDatatoarraybuffer)
2122
* [WaveformDataChannel](#waveformdatachannel)
@@ -468,6 +469,38 @@ console.log(wave3.length); // -> 100
468469
console.log(combinedResult.length); // -> 900
469470
```
470471

472+
### waveformData.slice(options)
473+
474+
Returns a subset of the waveform data between a given start and end point.
475+
476+
#### Arguments
477+
478+
| Name | Type |
479+
| --------- | ------------------------------------ |
480+
| `options` | An object containing either `startIndex` and `endIndex` values, which give the start and end indexes in the waveform data, or `startTime` and `endTime`, which give the start and end times (in seconds) |
481+
482+
#### Example
483+
484+
Return the waveform between index 100 and index 200:
485+
486+
```javascript
487+
const waveform = WaveformData.create(buffer);
488+
489+
const slice = waveform.slice({ startIndex: 100, endIndex: 200 });
490+
491+
console.log(slice.length); // -> 100
492+
```
493+
494+
Return the waveform between 1.0 and 2.0 seconds:
495+
496+
```javascript
497+
const waveform = WaveformData.create(buffer);
498+
499+
const slice = waveform.slice({ startTime: 1.0, endTime: 2.0 });
500+
501+
console.log(slice.length); // -> 86
502+
```
503+
471504
## waveformData.toJSON()
472505

473506
Returns an object containing the waveform data.

src/waveform-data.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,70 @@ WaveformData.prototype = {
423423
return totalBuffer;
424424
},
425425

426+
slice: function(options) {
427+
var startIndex = 0;
428+
var endIndex = 0;
429+
430+
if (options.startIndex != null && options.endIndex != null) {
431+
startIndex = options.startIndex;
432+
endIndex = options.endIndex;
433+
}
434+
else if (options.startTime != null && options.endTime != null) {
435+
startIndex = this.at_time(options.startTime);
436+
endIndex = this.at_time(options.endTime);
437+
}
438+
439+
if (startIndex < 0) {
440+
throw new RangeError("startIndex or startTime must not be negative");
441+
}
442+
443+
if (endIndex < 0) {
444+
throw new RangeError("endIndex or endTime must not be negative");
445+
}
446+
447+
if (startIndex > this.length) {
448+
startIndex = this.length;
449+
}
450+
451+
if (endIndex > this.length) {
452+
endIndex = this.length;
453+
}
454+
455+
if (startIndex > endIndex) {
456+
startIndex = endIndex;
457+
}
458+
459+
var length = endIndex - startIndex;
460+
461+
var header_size = 24; // Version 2
462+
var bytes_per_sample = this.bits === 8 ? 1 : 2;
463+
var total_size = header_size
464+
+ length * 2 * this.channels * bytes_per_sample;
465+
466+
var output_data = new ArrayBuffer(total_size);
467+
var output_dataview = new DataView(output_data);
468+
469+
output_dataview.setInt32(0, 2, true); // Version
470+
output_dataview.setUint32(4, this.bits === 8, true); // Is 8 bit?
471+
output_dataview.setInt32(8, this.sample_rate, true);
472+
output_dataview.setInt32(12, this.scale, true);
473+
output_dataview.setInt32(16, length, true);
474+
output_dataview.setInt32(20, this.channels, true);
475+
476+
for (var i = 0; i < length * this.channels * 2; i++) {
477+
var sample = this._at(startIndex * this.channels * 2 + i);
478+
479+
if (this.bits === 8) {
480+
output_dataview.setInt8(header_size + i, sample);
481+
}
482+
else {
483+
output_dataview.setInt16(header_size + i * 2, sample, true);
484+
}
485+
}
486+
487+
return new WaveformData(output_data);
488+
},
489+
426490
/**
427491
* Returns the data format version number.
428492
*/

test/unit/waveform-data.js

Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ export default function waveformDataTests(WaveformData) {
5555
context("with " + bits + "-bit " + format + " data", function() {
5656
beforeEach(function() {
5757
const data = format === "binary" ? getBinaryData({ channels: 1, bits: bits })
58-
: getJSONData({ channels: 1, bits: bits });
58+
: getJSONData({ channels: 1, bits: bits });
5959

6060
instance = WaveformData.create(data);
6161
});
@@ -284,6 +284,96 @@ export default function waveformDataTests(WaveformData) {
284284
expect(result.duration).to.equal(expectations.duration * 3);
285285
});
286286
});
287+
288+
describe(".slice()", function() {
289+
context("with valid startIndex and endIndex", function() {
290+
it("should return a subset of the waveform", function() {
291+
var extract = instance.slice({ startIndex: 1, endIndex: 4 });
292+
293+
expect(extract.length).to.equal(3);
294+
expect(extract.channels).to.equal(instance.channels);
295+
expect(extract.bits).to.equal(instance.bits);
296+
expect(extract.channel(0).min_array()).to.deep.equal([-10, 0, -5]);
297+
expect(extract.channel(0).max_array()).to.deep.equal([10, 0, 7]);
298+
});
299+
});
300+
301+
context("with endIndex beyond the length of the waveform", function() {
302+
it("should limit to the end of the waveform", function() {
303+
var extract = instance.slice({ startIndex: 1, endIndex: 12 });
304+
305+
expect(extract.length).to.equal(9);
306+
expect(extract.channels).to.equal(instance.channels);
307+
expect(extract.bits).to.equal(instance.bits);
308+
expect(extract.channel(0).min_array()).to.deep.equal([-10, 0, -5, -5, 0, 0, 0, 0, -2]);
309+
expect(extract.channel(0).max_array()).to.deep.equal([10, 0, 7, 7, 0, 0, 0, 0, 2]);
310+
});
311+
});
312+
313+
context("with startIndex equal to endIndex", function() {
314+
it("should return a zero length waveform", function() {
315+
var extract = instance.slice({ startIndex: 1, endIndex: 1 });
316+
317+
expect(extract.length).to.equal(0);
318+
expect(extract.channels).to.equal(instance.channels);
319+
expect(extract.bits).to.equal(instance.bits);
320+
expect(extract.channel(0).min_array()).to.deep.equal([]);
321+
expect(extract.channel(0).max_array()).to.deep.equal([]);
322+
});
323+
});
324+
325+
context("with startIndex greater than endIndex", function() {
326+
it("should return a zero length waveform", function() {
327+
var extract = instance.slice({ startIndex: 1, endIndex: 1 });
328+
329+
expect(extract.length).to.equal(0);
330+
expect(extract.channels).to.equal(instance.channels);
331+
expect(extract.bits).to.equal(instance.bits);
332+
expect(extract.channel(0).min_array()).to.deep.equal([]);
333+
expect(extract.channel(0).max_array()).to.deep.equal([]);
334+
});
335+
});
336+
337+
context("with startIndex and endIndex beyond the length of the waveform", function() {
338+
it("should return a zero length waveform", function() {
339+
var extract = instance.slice({ startIndex: 10, endIndex: 12 });
340+
341+
expect(extract.length).to.equal(0);
342+
expect(extract.channels).to.equal(instance.channels);
343+
expect(extract.bits).to.equal(instance.bits);
344+
expect(extract.channel(0).min_array()).to.deep.equal([]);
345+
expect(extract.channel(0).max_array()).to.deep.equal([]);
346+
});
347+
});
348+
349+
context("with negative startIndex", function() {
350+
it("should throw RangeError", function() {
351+
expect(function() {
352+
instance.slice({ startIndex: -1, endIndex: 4 });
353+
}).to.throw(RangeError);
354+
});
355+
});
356+
357+
context("with negative endIndex", function() {
358+
it("should throw RangeError", function() {
359+
expect(function() {
360+
instance.slice({ startIndex: 1, endIndex: -1 });
361+
}).to.throw(RangeError);
362+
});
363+
});
364+
365+
context("with valid startTime and endTime", function() {
366+
it("should return a subset of the waveform", function() {
367+
var extract = instance.slice({ startTime: instance.time(1), endTime: instance.time(4) });
368+
369+
expect(extract.length).to.equal(3);
370+
expect(extract.channels).to.equal(instance.channels);
371+
expect(extract.bits).to.equal(instance.bits);
372+
expect(extract.channel(0).min_array()).to.deep.equal([-10, 0, -5]);
373+
expect(extract.channel(0).max_array()).to.deep.equal([10, 0, 7]);
374+
});
375+
});
376+
});
287377
});
288378
});
289379
});
@@ -295,7 +385,7 @@ export default function waveformDataTests(WaveformData) {
295385
context("with " + bits + "-bit " + format + " data", function() {
296386
beforeEach(function() {
297387
const data = format === "binary" ? getBinaryData({ channels: 2, bits: bits })
298-
: getJSONData({ channels: 2, bits: bits });
388+
: getJSONData({ channels: 2, bits: bits });
299389

300390
instance = WaveformData.create(data);
301391
});

0 commit comments

Comments
 (0)