tone 14.8.32 → 14.8.36
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/Tone/core/clock/TickSource.test.ts +52 -0
- package/Tone/core/clock/TickSource.ts +70 -9
- package/Tone/core/type/Frequency.ts +8 -8
- package/Tone/effect/Chorus.test.ts +11 -8
- package/Tone/instrument/NoiseSynth.ts +56 -17
- package/Tone/source/Source.ts +84 -27
- package/Tone/source/buffer/Player.test.ts +98 -49
- package/Tone/source/buffer/Player.ts +45 -21
- package/Tone/version.ts +1 -1
- package/build/Tone.js +1 -1
- package/build/Tone.js.map +1 -1
- package/build/esm/core/clock/TickSource.d.ts +8 -0
- package/build/esm/core/clock/TickSource.js +49 -7
- package/build/esm/core/clock/TickSource.js.map +1 -1
- package/build/esm/core/type/Frequency.js +8 -8
- package/build/esm/core/type/Frequency.js.map +1 -1
- package/build/esm/instrument/NoiseSynth.d.ts +10 -0
- package/build/esm/instrument/NoiseSynth.js +14 -2
- package/build/esm/instrument/NoiseSynth.js.map +1 -1
- package/build/esm/source/Source.js +27 -14
- package/build/esm/source/Source.js.map +1 -1
- package/build/esm/source/buffer/Player.d.ts +2 -1
- package/build/esm/source/buffer/Player.js +19 -11
- package/build/esm/source/buffer/Player.js.map +1 -1
- package/build/esm/version.js +1 -1
- package/docs/tone.json +1 -1
- package/package.json +26 -26
|
@@ -8,7 +8,6 @@ import { getContext } from "Tone/core/Global";
|
|
|
8
8
|
import { Player } from "./Player";
|
|
9
9
|
|
|
10
10
|
describe("Player", () => {
|
|
11
|
-
|
|
12
11
|
const buffer = new ToneAudioBuffer();
|
|
13
12
|
|
|
14
13
|
beforeEach(() => {
|
|
@@ -20,15 +19,18 @@ describe("Player", () => {
|
|
|
20
19
|
SourceTests(Player, buffer);
|
|
21
20
|
|
|
22
21
|
it("matches a file", () => {
|
|
23
|
-
return CompareToFile(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
return CompareToFile(
|
|
23
|
+
() => {
|
|
24
|
+
const player = new Player(buffer).toDestination();
|
|
25
|
+
player.start(0.1).stop(0.2);
|
|
26
|
+
player.playbackRate = 2;
|
|
27
|
+
},
|
|
28
|
+
"player.wav",
|
|
29
|
+
0.005
|
|
30
|
+
);
|
|
28
31
|
});
|
|
29
32
|
|
|
30
33
|
context("Constructor", () => {
|
|
31
|
-
|
|
32
34
|
it("can be constructed with a Tone.Buffer", () => {
|
|
33
35
|
const player = new Player(buffer);
|
|
34
36
|
expect(player.buffer.get()).to.equal(buffer.get());
|
|
@@ -60,7 +62,6 @@ describe("Player", () => {
|
|
|
60
62
|
});
|
|
61
63
|
|
|
62
64
|
context("onstop", () => {
|
|
63
|
-
|
|
64
65
|
it("invokes the onstop method when the player is explicitly stopped", () => {
|
|
65
66
|
let wasInvoked = false;
|
|
66
67
|
return Offline(() => {
|
|
@@ -105,7 +106,6 @@ describe("Player", () => {
|
|
|
105
106
|
});
|
|
106
107
|
|
|
107
108
|
context("Loading", () => {
|
|
108
|
-
|
|
109
109
|
it("loads a url which was passed in", (done) => {
|
|
110
110
|
const player = new Player("./audio/sine.wav", () => {
|
|
111
111
|
expect(player.loaded).to.be.true;
|
|
@@ -131,12 +131,12 @@ describe("Player", () => {
|
|
|
131
131
|
|
|
132
132
|
it("invokes onerror if no url", (done) => {
|
|
133
133
|
const source = new Player({
|
|
134
|
-
url: "./nosuchfile.wav",
|
|
134
|
+
url: "./nosuchfile.wav",
|
|
135
135
|
onerror(e) {
|
|
136
136
|
expect(e).to.be.instanceOf(Error);
|
|
137
137
|
source.dispose();
|
|
138
138
|
done();
|
|
139
|
-
}
|
|
139
|
+
},
|
|
140
140
|
});
|
|
141
141
|
});
|
|
142
142
|
|
|
@@ -152,11 +152,9 @@ describe("Player", () => {
|
|
|
152
152
|
url: "./audio/sine.wav",
|
|
153
153
|
});
|
|
154
154
|
});
|
|
155
|
-
|
|
156
155
|
});
|
|
157
156
|
|
|
158
157
|
context("Reverse", () => {
|
|
159
|
-
|
|
160
158
|
it("can get/set reverse", () => {
|
|
161
159
|
const player = new Player();
|
|
162
160
|
player.reverse = true;
|
|
@@ -166,7 +164,9 @@ describe("Player", () => {
|
|
|
166
164
|
|
|
167
165
|
it("can be played in reverse", () => {
|
|
168
166
|
const shorterBuffer = buffer.slice(0, buffer.duration / 2);
|
|
169
|
-
const audioBuffer = (
|
|
167
|
+
const audioBuffer = (
|
|
168
|
+
shorterBuffer.get() as AudioBuffer
|
|
169
|
+
).getChannelData(0);
|
|
170
170
|
const lastSample = audioBuffer[audioBuffer.length - 1];
|
|
171
171
|
expect(lastSample).to.not.equal(0);
|
|
172
172
|
return Offline(() => {
|
|
@@ -180,11 +180,9 @@ describe("Player", () => {
|
|
|
180
180
|
expect(firstSample).to.equal(lastSample);
|
|
181
181
|
});
|
|
182
182
|
});
|
|
183
|
-
|
|
184
183
|
});
|
|
185
184
|
|
|
186
185
|
context("Looping", () => {
|
|
187
|
-
|
|
188
186
|
beforeEach(() => {
|
|
189
187
|
return buffer.load("./audio/short_sine.wav");
|
|
190
188
|
});
|
|
@@ -243,7 +241,7 @@ describe("Player", () => {
|
|
|
243
241
|
player.toDestination();
|
|
244
242
|
player.start(0);
|
|
245
243
|
player.loop = true;
|
|
246
|
-
}, buffer.duration * 1.5).then(buff => {
|
|
244
|
+
}, buffer.duration * 1.5).then((buff) => {
|
|
247
245
|
expect(buff.getRmsAtTime(0)).to.be.above(0);
|
|
248
246
|
expect(buff.getRmsAtTime(buffer.duration * 0.5)).to.be.above(0);
|
|
249
247
|
expect(buff.getRmsAtTime(buffer.duration)).to.be.above(0);
|
|
@@ -252,7 +250,8 @@ describe("Player", () => {
|
|
|
252
250
|
});
|
|
253
251
|
|
|
254
252
|
it("offset is the loopStart when set to loop", () => {
|
|
255
|
-
const testSample =
|
|
253
|
+
const testSample =
|
|
254
|
+
buffer.toArray(0)[Math.floor(0.1 * getContext().sampleRate)];
|
|
256
255
|
return Offline(() => {
|
|
257
256
|
const player = new Player(buffer);
|
|
258
257
|
player.loopStart = 0.1;
|
|
@@ -271,10 +270,10 @@ describe("Player", () => {
|
|
|
271
270
|
player.loop = true;
|
|
272
271
|
player.toDestination();
|
|
273
272
|
player.start(0, 0, playDur);
|
|
274
|
-
}, buffer.duration * 2).then(buff => {
|
|
273
|
+
}, buffer.duration * 2).then((buff) => {
|
|
275
274
|
for (let time = 0; time < buffer.duration * 2; time += 0.1) {
|
|
276
275
|
const val = buff.getRmsAtTime(time);
|
|
277
|
-
if (time <
|
|
276
|
+
if (time < playDur - 0.01) {
|
|
278
277
|
expect(val).to.be.greaterThan(0);
|
|
279
278
|
} else if (time > playDur) {
|
|
280
279
|
expect(val).to.equal(0);
|
|
@@ -286,9 +285,11 @@ describe("Player", () => {
|
|
|
286
285
|
it("correctly compensates if the offset is greater than the loopEnd", () => {
|
|
287
286
|
return Offline(() => {
|
|
288
287
|
// make a ramp between 0-1
|
|
289
|
-
const ramp = new Float32Array(
|
|
288
|
+
const ramp = new Float32Array(
|
|
289
|
+
Math.floor(getContext().sampleRate * 0.3)
|
|
290
|
+
);
|
|
290
291
|
for (let i = 0; i < ramp.length; i++) {
|
|
291
|
-
ramp[i] = (i /
|
|
292
|
+
ramp[i] = (i / ramp.length) * 0.3;
|
|
292
293
|
}
|
|
293
294
|
const buff = ToneAudioBuffer.fromArray(ramp);
|
|
294
295
|
const player = new Player(buff).toDestination();
|
|
@@ -306,7 +307,6 @@ describe("Player", () => {
|
|
|
306
307
|
});
|
|
307
308
|
});
|
|
308
309
|
});
|
|
309
|
-
|
|
310
310
|
});
|
|
311
311
|
|
|
312
312
|
context("PlaybackRate", () => {
|
|
@@ -344,7 +344,6 @@ describe("Player", () => {
|
|
|
344
344
|
});
|
|
345
345
|
|
|
346
346
|
context("Get/Set", () => {
|
|
347
|
-
|
|
348
347
|
it("can be set with an options object", () => {
|
|
349
348
|
const player = new Player();
|
|
350
349
|
expect(player.loop).to.be.false;
|
|
@@ -399,13 +398,12 @@ describe("Player", () => {
|
|
|
399
398
|
expect(player.playbackRate).to.equal(0.5);
|
|
400
399
|
player.dispose();
|
|
401
400
|
});
|
|
402
|
-
|
|
403
401
|
});
|
|
404
402
|
|
|
405
403
|
context("Start Scheduling", () => {
|
|
406
|
-
|
|
407
404
|
it("can be start with an offset", () => {
|
|
408
|
-
const testSample =
|
|
405
|
+
const testSample =
|
|
406
|
+
buffer.toArray(0)[Math.floor(0.1 * getContext().sampleRate)];
|
|
409
407
|
return Offline(() => {
|
|
410
408
|
const player = new Player(buffer.get());
|
|
411
409
|
player.toDestination();
|
|
@@ -418,9 +416,11 @@ describe("Player", () => {
|
|
|
418
416
|
it("is stopped and restarted when start is called twice", () => {
|
|
419
417
|
return Offline(() => {
|
|
420
418
|
// make a ramp between 0-1
|
|
421
|
-
const ramp = new Float32Array(
|
|
419
|
+
const ramp = new Float32Array(
|
|
420
|
+
Math.floor(getContext().sampleRate * 0.3)
|
|
421
|
+
);
|
|
422
422
|
for (let i = 0; i < ramp.length; i++) {
|
|
423
|
-
ramp[i] =
|
|
423
|
+
ramp[i] = i / (ramp.length - 1);
|
|
424
424
|
}
|
|
425
425
|
const buff = new ToneAudioBuffer().fromArray(ramp);
|
|
426
426
|
const player = new Player(buff).toDestination();
|
|
@@ -442,9 +442,11 @@ describe("Player", () => {
|
|
|
442
442
|
|
|
443
443
|
it("can seek to a position at the given time", () => {
|
|
444
444
|
return Offline(() => {
|
|
445
|
-
const ramp = new Float32Array(
|
|
445
|
+
const ramp = new Float32Array(
|
|
446
|
+
Math.floor(getContext().sampleRate * 0.3)
|
|
447
|
+
);
|
|
446
448
|
for (let i = 0; i < ramp.length; i++) {
|
|
447
|
-
ramp[i] = (i /
|
|
449
|
+
ramp[i] = (i / ramp.length) * 0.3;
|
|
448
450
|
}
|
|
449
451
|
const buff = new ToneAudioBuffer().fromArray(ramp);
|
|
450
452
|
const player = new Player(buff).toDestination();
|
|
@@ -466,7 +468,7 @@ describe("Player", () => {
|
|
|
466
468
|
const player = new Player(buffer);
|
|
467
469
|
player.toDestination();
|
|
468
470
|
player.start(0).stop(0.1);
|
|
469
|
-
return time => {
|
|
471
|
+
return (time) => {
|
|
470
472
|
whenBetween(time, 0.1, Infinity, () => {
|
|
471
473
|
expect(player.state).to.equal("stopped");
|
|
472
474
|
});
|
|
@@ -475,9 +477,13 @@ describe("Player", () => {
|
|
|
475
477
|
});
|
|
476
478
|
};
|
|
477
479
|
}, 0.3).then((buff) => {
|
|
478
|
-
buff.forEachBetween(
|
|
479
|
-
|
|
480
|
-
|
|
480
|
+
buff.forEachBetween(
|
|
481
|
+
(sample) => {
|
|
482
|
+
expect(sample).to.equal(0);
|
|
483
|
+
},
|
|
484
|
+
0.11,
|
|
485
|
+
0.15
|
|
486
|
+
);
|
|
481
487
|
});
|
|
482
488
|
});
|
|
483
489
|
|
|
@@ -495,7 +501,10 @@ describe("Player", () => {
|
|
|
495
501
|
return Offline(() => {
|
|
496
502
|
const player = new Player(buffer);
|
|
497
503
|
player.toDestination();
|
|
498
|
-
player
|
|
504
|
+
player
|
|
505
|
+
.start(0, 0, 0.05)
|
|
506
|
+
.start(0.1, 0, 0.05)
|
|
507
|
+
.start(0.2, 0, 0.05);
|
|
499
508
|
player.stop(0.1);
|
|
500
509
|
}, 0.3).then((buff) => {
|
|
501
510
|
expect(buff.getTimeOfLastSound()).to.be.closeTo(0.1, 0.02);
|
|
@@ -518,7 +527,7 @@ describe("Player", () => {
|
|
|
518
527
|
const player = new Player(buffer);
|
|
519
528
|
player.toDestination();
|
|
520
529
|
player.start(0, 0, 0.1);
|
|
521
|
-
return time => {
|
|
530
|
+
return (time) => {
|
|
522
531
|
whenBetween(time, 0.1, Infinity, () => {
|
|
523
532
|
expect(player.state).to.equal("stopped");
|
|
524
533
|
});
|
|
@@ -549,17 +558,42 @@ describe("Player", () => {
|
|
|
549
558
|
|
|
550
559
|
it("plays synced to the Transport", () => {
|
|
551
560
|
return Offline(({ transport }) => {
|
|
552
|
-
const player = new Player(buffer)
|
|
561
|
+
const player = new Player(buffer)
|
|
562
|
+
.sync()
|
|
563
|
+
.start(0)
|
|
564
|
+
.toDestination();
|
|
553
565
|
transport.start(0);
|
|
554
566
|
}, 0.05).then((buff) => {
|
|
555
567
|
expect(buff.isSilent()).to.be.false;
|
|
556
568
|
});
|
|
557
569
|
});
|
|
558
570
|
|
|
571
|
+
it("does not play twice when the offset is very small", () => {
|
|
572
|
+
// addresses #999 and #944
|
|
573
|
+
return CompareToFile(
|
|
574
|
+
() => {
|
|
575
|
+
const player = new Player(buffer).toDestination();
|
|
576
|
+
player.sync().start(0);
|
|
577
|
+
getContext().transport.bpm.value = 125;
|
|
578
|
+
getContext().transport.setLoopPoints(0, "1:0:0");
|
|
579
|
+
getContext().transport.loop = true;
|
|
580
|
+
getContext().transport.start(0);
|
|
581
|
+
},
|
|
582
|
+
"playerSyncLoop.wav",
|
|
583
|
+
0.01
|
|
584
|
+
);
|
|
585
|
+
});
|
|
586
|
+
|
|
559
587
|
it("offsets correctly when started by the Transport", () => {
|
|
560
|
-
const testSample =
|
|
588
|
+
const testSample =
|
|
589
|
+
buffer.toArray(0)[
|
|
590
|
+
Math.floor(0.13125 * getContext().sampleRate)
|
|
591
|
+
];
|
|
561
592
|
return Offline(({ transport }) => {
|
|
562
|
-
const player = new Player(buffer)
|
|
593
|
+
const player = new Player(buffer)
|
|
594
|
+
.sync()
|
|
595
|
+
.start(0, 0.1)
|
|
596
|
+
.toDestination();
|
|
563
597
|
transport.start(0, 0.03125);
|
|
564
598
|
}, 0.05).then((buff) => {
|
|
565
599
|
expect(buff.toArray()[0][0]).to.equal(testSample);
|
|
@@ -569,9 +603,11 @@ describe("Player", () => {
|
|
|
569
603
|
it("starts at the correct position when Transport is offset and playbackRate is not 1", () => {
|
|
570
604
|
return Offline(({ transport }) => {
|
|
571
605
|
// make a ramp between 0-1
|
|
572
|
-
const ramp = new Float32Array(
|
|
606
|
+
const ramp = new Float32Array(
|
|
607
|
+
Math.floor(getContext().sampleRate * 0.3)
|
|
608
|
+
);
|
|
573
609
|
for (let i = 0; i < ramp.length; i++) {
|
|
574
|
-
ramp[i] =
|
|
610
|
+
ramp[i] = i / ramp.length;
|
|
575
611
|
}
|
|
576
612
|
const buff = ToneAudioBuffer.fromArray(ramp);
|
|
577
613
|
const player = new Player(buff).toDestination();
|
|
@@ -586,9 +622,11 @@ describe("Player", () => {
|
|
|
586
622
|
|
|
587
623
|
it("starts with an offset when synced and started after Transport is running", () => {
|
|
588
624
|
return Offline(({ transport }) => {
|
|
589
|
-
const ramp = new Float32Array(
|
|
625
|
+
const ramp = new Float32Array(
|
|
626
|
+
Math.floor(getContext().sampleRate * 0.3)
|
|
627
|
+
);
|
|
590
628
|
for (let i = 0; i < ramp.length; i++) {
|
|
591
|
-
ramp[i] = (i /
|
|
629
|
+
ramp[i] = (i / ramp.length) * 0.3;
|
|
592
630
|
}
|
|
593
631
|
const buff = new ToneAudioBuffer().fromArray(ramp);
|
|
594
632
|
const player = new Player(buff).toDestination();
|
|
@@ -606,9 +644,11 @@ describe("Player", () => {
|
|
|
606
644
|
|
|
607
645
|
it("can pass in an offset when synced and started after Transport is running", () => {
|
|
608
646
|
return Offline(({ transport }) => {
|
|
609
|
-
const ramp = new Float32Array(
|
|
647
|
+
const ramp = new Float32Array(
|
|
648
|
+
Math.floor(getContext().sampleRate * 0.3)
|
|
649
|
+
);
|
|
610
650
|
for (let i = 0; i < ramp.length; i++) {
|
|
611
|
-
ramp[i] = (i /
|
|
651
|
+
ramp[i] = (i / ramp.length) * 0.3;
|
|
612
652
|
}
|
|
613
653
|
const buff = new ToneAudioBuffer().fromArray(ramp);
|
|
614
654
|
const player = new Player(buff).toDestination();
|
|
@@ -630,12 +670,18 @@ describe("Player", () => {
|
|
|
630
670
|
it("fades in and out correctly", () => {
|
|
631
671
|
let duration = 0.5;
|
|
632
672
|
return Offline(() => {
|
|
633
|
-
const onesArray = new Float32Array(
|
|
673
|
+
const onesArray = new Float32Array(
|
|
674
|
+
getContext().sampleRate * duration
|
|
675
|
+
);
|
|
634
676
|
onesArray.forEach((sample, index) => {
|
|
635
677
|
onesArray[index] = 1;
|
|
636
678
|
});
|
|
637
679
|
const onesBuffer = ToneAudioBuffer.fromArray(onesArray);
|
|
638
|
-
const player = new Player({
|
|
680
|
+
const player = new Player({
|
|
681
|
+
url: onesBuffer,
|
|
682
|
+
fadeOut: 0.1,
|
|
683
|
+
fadeIn: 0.1,
|
|
684
|
+
}).toDestination();
|
|
639
685
|
player.start(0);
|
|
640
686
|
}, 0.6).then((buff) => {
|
|
641
687
|
expect(buff.getRmsAtTime(0)).to.be.closeTo(0, 0.1);
|
|
@@ -643,7 +689,10 @@ describe("Player", () => {
|
|
|
643
689
|
expect(buff.getRmsAtTime(0.1)).to.be.closeTo(1, 0.1);
|
|
644
690
|
duration -= 0.1;
|
|
645
691
|
expect(buff.getRmsAtTime(duration)).to.be.closeTo(1, 0.1);
|
|
646
|
-
expect(buff.getRmsAtTime(duration + 0.05)).to.be.closeTo(
|
|
692
|
+
expect(buff.getRmsAtTime(duration + 0.05)).to.be.closeTo(
|
|
693
|
+
0.5,
|
|
694
|
+
0.1
|
|
695
|
+
);
|
|
647
696
|
expect(buff.getRmsAtTime(duration + 0.1)).to.be.closeTo(0, 0.1);
|
|
648
697
|
});
|
|
649
698
|
});
|
|
@@ -31,7 +31,6 @@ export interface PlayerOptions extends SourceOptions {
|
|
|
31
31
|
* @category Source
|
|
32
32
|
*/
|
|
33
33
|
export class Player extends Source<PlayerOptions> {
|
|
34
|
-
|
|
35
34
|
readonly name: string = "Player";
|
|
36
35
|
|
|
37
36
|
/**
|
|
@@ -86,12 +85,22 @@ export class Player extends Source<PlayerOptions> {
|
|
|
86
85
|
* @param url Either the AudioBuffer or the url from which to load the AudioBuffer
|
|
87
86
|
* @param onload The function to invoke when the buffer is loaded.
|
|
88
87
|
*/
|
|
89
|
-
constructor(
|
|
88
|
+
constructor(
|
|
89
|
+
url?: string | AudioBuffer | ToneAudioBuffer,
|
|
90
|
+
onload?: () => void
|
|
91
|
+
);
|
|
90
92
|
constructor(options?: Partial<PlayerOptions>);
|
|
91
93
|
constructor() {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
94
|
+
super(
|
|
95
|
+
optionsFromArguments(Player.getDefaults(), arguments, [
|
|
96
|
+
"url",
|
|
97
|
+
"onload",
|
|
98
|
+
])
|
|
99
|
+
);
|
|
100
|
+
const options = optionsFromArguments(Player.getDefaults(), arguments, [
|
|
101
|
+
"url",
|
|
102
|
+
"onload",
|
|
103
|
+
]);
|
|
95
104
|
|
|
96
105
|
this._buffer = new ToneAudioBuffer({
|
|
97
106
|
onload: this._onload.bind(this, options.onload),
|
|
@@ -157,8 +166,11 @@ export class Player extends Source<PlayerOptions> {
|
|
|
157
166
|
|
|
158
167
|
// delete the source from the active sources
|
|
159
168
|
this._activeSources.delete(source);
|
|
160
|
-
if (
|
|
161
|
-
this.
|
|
169
|
+
if (
|
|
170
|
+
this._activeSources.size === 0 &&
|
|
171
|
+
!this._synced &&
|
|
172
|
+
this._state.getValueAtTime(this.now()) === "started"
|
|
173
|
+
) {
|
|
162
174
|
// remove the 'implicitEnd' event and replace with an explicit end
|
|
163
175
|
this._state.cancel(this.now());
|
|
164
176
|
this._state.setStateAtTime("stopped", this.now());
|
|
@@ -196,7 +208,10 @@ export class Player extends Source<PlayerOptions> {
|
|
|
196
208
|
|
|
197
209
|
// compute the duration which is either the passed in duration of the buffer.duration - offset
|
|
198
210
|
const origDuration = duration;
|
|
199
|
-
duration = defaultArg(
|
|
211
|
+
duration = defaultArg(
|
|
212
|
+
duration,
|
|
213
|
+
Math.max(this._buffer.duration - computedOffset, 0)
|
|
214
|
+
);
|
|
200
215
|
let computedDuration = this.toSeconds(duration);
|
|
201
216
|
|
|
202
217
|
// scale it by the playback rate
|
|
@@ -223,9 +238,13 @@ export class Player extends Source<PlayerOptions> {
|
|
|
223
238
|
// cancel the previous stop
|
|
224
239
|
this._state.cancel(startTime + computedDuration);
|
|
225
240
|
// if it's not looping, set the state change at the end of the sample
|
|
226
|
-
this._state.setStateAtTime(
|
|
227
|
-
|
|
228
|
-
|
|
241
|
+
this._state.setStateAtTime(
|
|
242
|
+
"stopped",
|
|
243
|
+
startTime + computedDuration,
|
|
244
|
+
{
|
|
245
|
+
implicitEnd: true,
|
|
246
|
+
}
|
|
247
|
+
);
|
|
229
248
|
}
|
|
230
249
|
|
|
231
250
|
// add it to the array of active sources
|
|
@@ -236,7 +255,11 @@ export class Player extends Source<PlayerOptions> {
|
|
|
236
255
|
source.start(startTime, computedOffset);
|
|
237
256
|
} else {
|
|
238
257
|
// subtract the fade out time
|
|
239
|
-
source.start(
|
|
258
|
+
source.start(
|
|
259
|
+
startTime,
|
|
260
|
+
computedOffset,
|
|
261
|
+
computedDuration - this.toSeconds(this.fadeOut)
|
|
262
|
+
);
|
|
240
263
|
}
|
|
241
264
|
}
|
|
242
265
|
|
|
@@ -245,14 +268,14 @@ export class Player extends Source<PlayerOptions> {
|
|
|
245
268
|
*/
|
|
246
269
|
protected _stop(time?: Time): void {
|
|
247
270
|
const computedTime = this.toSeconds(time);
|
|
248
|
-
this._activeSources.forEach(source => source.stop(computedTime));
|
|
271
|
+
this._activeSources.forEach((source) => source.stop(computedTime));
|
|
249
272
|
}
|
|
250
273
|
|
|
251
274
|
/**
|
|
252
275
|
* Stop and then restart the player from the beginning (or offset)
|
|
253
276
|
* @param time When the player should start.
|
|
254
277
|
* @param offset The offset from the beginning of the sample to start at.
|
|
255
|
-
* @param duration How long the sample should play. If no duration is given,
|
|
278
|
+
* @param duration How long the sample should play. If no duration is given,
|
|
256
279
|
* it will default to the full length of the sample (minus any offset)
|
|
257
280
|
*/
|
|
258
281
|
restart(time?: Seconds, offset?: Time, duration?: Time): this {
|
|
@@ -318,7 +341,7 @@ export class Player extends Source<PlayerOptions> {
|
|
|
318
341
|
assertRange(this.toSeconds(loopStart), 0, this.buffer.duration);
|
|
319
342
|
}
|
|
320
343
|
// get the current source
|
|
321
|
-
this._activeSources.forEach(source => {
|
|
344
|
+
this._activeSources.forEach((source) => {
|
|
322
345
|
source.loopStart = loopStart;
|
|
323
346
|
});
|
|
324
347
|
}
|
|
@@ -335,7 +358,7 @@ export class Player extends Source<PlayerOptions> {
|
|
|
335
358
|
assertRange(this.toSeconds(loopEnd), 0, this.buffer.duration);
|
|
336
359
|
}
|
|
337
360
|
// get the current source
|
|
338
|
-
this._activeSources.forEach(source => {
|
|
361
|
+
this._activeSources.forEach((source) => {
|
|
339
362
|
source.loopEnd = loopEnd;
|
|
340
363
|
});
|
|
341
364
|
}
|
|
@@ -367,7 +390,7 @@ export class Player extends Source<PlayerOptions> {
|
|
|
367
390
|
}
|
|
368
391
|
this._loop = loop;
|
|
369
392
|
// set the loop of all of the sources
|
|
370
|
-
this._activeSources.forEach(source => {
|
|
393
|
+
this._activeSources.forEach((source) => {
|
|
371
394
|
source.loop = loop;
|
|
372
395
|
});
|
|
373
396
|
if (loop) {
|
|
@@ -399,17 +422,18 @@ export class Player extends Source<PlayerOptions> {
|
|
|
399
422
|
const stopEvent = this._state.getNextState("stopped", now);
|
|
400
423
|
if (stopEvent && stopEvent.implicitEnd) {
|
|
401
424
|
this._state.cancel(stopEvent.time);
|
|
402
|
-
this._activeSources.forEach(source => source.cancelStop());
|
|
425
|
+
this._activeSources.forEach((source) => source.cancelStop());
|
|
403
426
|
}
|
|
404
427
|
|
|
405
428
|
// set all the sources
|
|
406
|
-
this._activeSources.forEach(source => {
|
|
429
|
+
this._activeSources.forEach((source) => {
|
|
407
430
|
source.playbackRate.setValueAtTime(rate, now);
|
|
408
431
|
});
|
|
409
432
|
}
|
|
410
433
|
|
|
411
434
|
/**
|
|
412
|
-
* If the buffer should be reversed
|
|
435
|
+
* If the buffer should be reversed. Note that this sets the underlying [[ToneAudioBuffer.reverse]], so
|
|
436
|
+
* if multiple players are pointing at the same ToneAudioBuffer, they will all be reversed.
|
|
413
437
|
* @example
|
|
414
438
|
* const player = new Tone.Player("https://tonejs.github.io/audio/berklee/chime_1.mp3").toDestination();
|
|
415
439
|
* player.autostart = true;
|
|
@@ -432,7 +456,7 @@ export class Player extends Source<PlayerOptions> {
|
|
|
432
456
|
dispose(): this {
|
|
433
457
|
super.dispose();
|
|
434
458
|
// disconnect all of the players
|
|
435
|
-
this._activeSources.forEach(source => source.dispose());
|
|
459
|
+
this._activeSources.forEach((source) => source.dispose());
|
|
436
460
|
this._activeSources.clear();
|
|
437
461
|
this._buffer.dispose();
|
|
438
462
|
return this;
|
package/Tone/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version: string = "14.8.
|
|
1
|
+
export const version: string = "14.8.36";
|