tone 15.2.0 → 15.2.2
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/component/analysis/Follower.test.ts +38 -42
- package/Tone/component/channel/Channel.test.ts +3 -4
- package/Tone/component/channel/Merge.test.ts +5 -6
- package/Tone/component/channel/MidSideSplit.test.ts +21 -25
- package/Tone/component/channel/Mono.test.ts +18 -20
- package/Tone/component/channel/PanVol.test.ts +3 -4
- package/Tone/component/channel/Panner.test.ts +28 -32
- package/Tone/component/channel/Recorder.ts +1 -1
- package/Tone/component/channel/Volume.test.ts +9 -12
- package/Tone/component/dynamics/Gate.test.ts +10 -14
- package/Tone/component/envelope/AmplitudeEnvelope.test.ts +7 -9
- package/Tone/component/envelope/Envelope.test.ts +347 -384
- package/Tone/component/filter/BiquadFilter.test.ts +5 -6
- package/Tone/component/filter/Convolver.test.ts +6 -9
- package/Tone/component/filter/FeedbackCombFilter.test.ts +14 -16
- package/Tone/component/filter/Filter.test.ts +5 -6
- package/Tone/component/filter/LowpassCombFilter.test.ts +15 -17
- package/Tone/core/clock/Clock.test.ts +12 -15
- package/Tone/core/clock/TickSignal.test.ts +18 -21
- package/Tone/core/clock/Transport.test.ts +133 -162
- package/Tone/core/clock/TransportEvent.test.ts +3 -4
- package/Tone/core/clock/TransportRepeatEvent.test.ts +6 -6
- package/Tone/core/context/Context.test.ts +8 -10
- package/Tone/core/context/Context.ts +8 -4
- package/Tone/core/context/Destination.test.ts +3 -4
- package/Tone/core/context/Offline.test.ts +23 -41
- package/Tone/core/context/OfflineContext.test.ts +20 -22
- package/Tone/core/context/Param.test.ts +33 -40
- package/Tone/core/context/ToneAudioBuffer.test.ts +3 -10
- package/Tone/core/context/ToneAudioBuffers.test.ts +9 -13
- package/Tone/core/worklet/ToneAudioWorklet.ts +3 -1
- package/Tone/effect/AutoFilter.test.ts +10 -12
- package/Tone/effect/AutoPanner.test.ts +10 -12
- package/Tone/effect/Chorus.test.ts +10 -14
- package/Tone/effect/FrequencyShifter.test.ts +6 -7
- package/Tone/effect/Reverb.test.ts +12 -15
- package/Tone/effect/Tremolo.test.ts +10 -12
- package/Tone/event/Loop.test.ts +29 -36
- package/Tone/event/Part.test.ts +152 -180
- package/Tone/event/Pattern.test.ts +16 -20
- package/Tone/event/Sequence.test.ts +86 -101
- package/Tone/event/ToneEvent.test.ts +60 -70
- package/Tone/instrument/MonoSynth.test.ts +3 -4
- package/Tone/instrument/PolySynth.test.ts +62 -74
- package/Tone/instrument/Sampler.test.ts +39 -48
- package/Tone/instrument/Synth.test.ts +40 -47
- package/Tone/signal/AudioToGain.test.ts +4 -5
- package/Tone/signal/Signal.test.ts +120 -143
- package/Tone/signal/SyncedSignal.test.ts +108 -122
- package/Tone/signal/ToneConstantSource.test.ts +21 -25
- package/Tone/signal/WaveShaper.test.ts +5 -6
- package/Tone/source/Source.test.ts +42 -48
- package/Tone/source/buffer/GrainPlayer.test.ts +29 -35
- package/Tone/source/buffer/Player.test.ts +162 -191
- package/Tone/source/buffer/Players.test.ts +44 -50
- package/Tone/source/buffer/ToneBufferSource.test.ts +176 -211
- package/Tone/source/oscillator/LFO.test.ts +49 -61
- package/Tone/source/oscillator/Oscillator.test.ts +24 -28
- package/Tone/source/oscillator/PulseOscillator.test.ts +36 -40
- package/Tone/source/oscillator/ToneOscillatorNode.test.ts +25 -29
- package/Tone/version.ts +1 -1
- package/build/Tone.js +1 -1
- package/build/Tone.js.map +1 -1
- package/build/esm/component/channel/Recorder.js.map +1 -1
- package/build/esm/core/context/Context.js +6 -3
- package/build/esm/core/context/Context.js.map +1 -1
- package/build/esm/core/worklet/ToneAudioWorklet.js.map +1 -1
- package/build/esm/version.js +1 -1
- package/package.json +1 -1
|
@@ -65,8 +65,8 @@ describe("ToneEvent", () => {
|
|
|
65
65
|
});
|
|
66
66
|
});
|
|
67
67
|
|
|
68
|
-
it("can set get a the values as an object", () => {
|
|
69
|
-
|
|
68
|
+
it("can set get a the values as an object", async () => {
|
|
69
|
+
await Offline(() => {
|
|
70
70
|
const callback = noOp;
|
|
71
71
|
const note = new ToneEvent({
|
|
72
72
|
callback,
|
|
@@ -82,8 +82,8 @@ describe("ToneEvent", () => {
|
|
|
82
82
|
});
|
|
83
83
|
|
|
84
84
|
context("ToneEvent callback", () => {
|
|
85
|
-
it("does not invoke get invoked until started", () => {
|
|
86
|
-
|
|
85
|
+
it("does not invoke get invoked until started", async () => {
|
|
86
|
+
await Offline(({ transport }) => {
|
|
87
87
|
const event = new ToneEvent(() => {
|
|
88
88
|
throw new Error("shouldn't call this callback");
|
|
89
89
|
}, "C4");
|
|
@@ -91,22 +91,21 @@ describe("ToneEvent", () => {
|
|
|
91
91
|
}, 0.3);
|
|
92
92
|
});
|
|
93
93
|
|
|
94
|
-
it("is invoked after it's started", () => {
|
|
94
|
+
it("is invoked after it's started", async () => {
|
|
95
95
|
let invoked = false;
|
|
96
|
-
|
|
96
|
+
await Offline(({ transport }) => {
|
|
97
97
|
const note = new ToneEvent(() => {
|
|
98
98
|
note.dispose();
|
|
99
99
|
invoked = true;
|
|
100
100
|
}, "C4").start(0);
|
|
101
101
|
transport.start();
|
|
102
|
-
}, 0.3)
|
|
103
|
-
|
|
104
|
-
});
|
|
102
|
+
}, 0.3);
|
|
103
|
+
expect(invoked).to.be.true;
|
|
105
104
|
});
|
|
106
105
|
|
|
107
|
-
it("passes in the scheduled time to the callback", () => {
|
|
106
|
+
it("passes in the scheduled time to the callback", async () => {
|
|
108
107
|
let invoked = false;
|
|
109
|
-
|
|
108
|
+
await Offline(({ transport }) => {
|
|
110
109
|
const now = 0.1;
|
|
111
110
|
const note = new ToneEvent((time) => {
|
|
112
111
|
expect(time).to.be.a("number");
|
|
@@ -116,14 +115,13 @@ describe("ToneEvent", () => {
|
|
|
116
115
|
});
|
|
117
116
|
note.start(0.3);
|
|
118
117
|
transport.start(now);
|
|
119
|
-
}, 0.5)
|
|
120
|
-
|
|
121
|
-
});
|
|
118
|
+
}, 0.5);
|
|
119
|
+
expect(invoked).to.be.true;
|
|
122
120
|
});
|
|
123
121
|
|
|
124
|
-
it("passes in the value to the callback", () => {
|
|
122
|
+
it("passes in the value to the callback", async () => {
|
|
125
123
|
let invoked = false;
|
|
126
|
-
|
|
124
|
+
await Offline(({ transport }) => {
|
|
127
125
|
const note = new ToneEvent((time, thing) => {
|
|
128
126
|
expect(time).to.be.a("number");
|
|
129
127
|
expect(thing).to.equal("thing");
|
|
@@ -131,9 +129,8 @@ describe("ToneEvent", () => {
|
|
|
131
129
|
invoked = true;
|
|
132
130
|
}, "thing").start();
|
|
133
131
|
transport.start();
|
|
134
|
-
}, 0.3)
|
|
135
|
-
|
|
136
|
-
});
|
|
132
|
+
}, 0.3);
|
|
133
|
+
expect(invoked).to.be.true;
|
|
137
134
|
});
|
|
138
135
|
|
|
139
136
|
it("can mute the callback", () => {
|
|
@@ -196,8 +193,8 @@ describe("ToneEvent", () => {
|
|
|
196
193
|
}, 1);
|
|
197
194
|
});
|
|
198
195
|
|
|
199
|
-
it("can be cancelled", () => {
|
|
200
|
-
|
|
196
|
+
it("can be cancelled", async () => {
|
|
197
|
+
await Offline(({ transport }) => {
|
|
201
198
|
const note = new ToneEvent().start(0);
|
|
202
199
|
expect(note.state).to.equal("started");
|
|
203
200
|
transport.start();
|
|
@@ -227,9 +224,9 @@ describe("ToneEvent", () => {
|
|
|
227
224
|
});
|
|
228
225
|
|
|
229
226
|
context("Looping", () => {
|
|
230
|
-
it("can be set to loop", () => {
|
|
227
|
+
it("can be set to loop", async () => {
|
|
231
228
|
let callCount = 0;
|
|
232
|
-
|
|
229
|
+
await Offline(({ transport }) => {
|
|
233
230
|
new ToneEvent({
|
|
234
231
|
callback(): void {
|
|
235
232
|
callCount++;
|
|
@@ -238,13 +235,12 @@ describe("ToneEvent", () => {
|
|
|
238
235
|
loopEnd: 0.25,
|
|
239
236
|
}).start(0);
|
|
240
237
|
transport.start(0);
|
|
241
|
-
}, 0.8)
|
|
242
|
-
|
|
243
|
-
});
|
|
238
|
+
}, 0.8);
|
|
239
|
+
expect(callCount).to.equal(4);
|
|
244
240
|
});
|
|
245
241
|
|
|
246
|
-
it("can be set to loop at a specific interval", () => {
|
|
247
|
-
|
|
242
|
+
it("can be set to loop at a specific interval", async () => {
|
|
243
|
+
await Offline(({ transport }) => {
|
|
248
244
|
let lastCall;
|
|
249
245
|
new ToneEvent({
|
|
250
246
|
callback(time): void {
|
|
@@ -279,9 +275,9 @@ describe("ToneEvent", () => {
|
|
|
279
275
|
}, 0.8);
|
|
280
276
|
});
|
|
281
277
|
|
|
282
|
-
it("can loop a specific number of times", () => {
|
|
278
|
+
it("can loop a specific number of times", async () => {
|
|
283
279
|
let callCount = 0;
|
|
284
|
-
|
|
280
|
+
await Offline(({ transport }) => {
|
|
285
281
|
new ToneEvent({
|
|
286
282
|
loop: 3,
|
|
287
283
|
loopEnd: 0.125,
|
|
@@ -290,14 +286,13 @@ describe("ToneEvent", () => {
|
|
|
290
286
|
},
|
|
291
287
|
}).start(0);
|
|
292
288
|
transport.start();
|
|
293
|
-
}, 0.8)
|
|
294
|
-
|
|
295
|
-
});
|
|
289
|
+
}, 0.8);
|
|
290
|
+
expect(callCount).to.equal(3);
|
|
296
291
|
});
|
|
297
292
|
|
|
298
|
-
it("plays once when loop is 1", () => {
|
|
293
|
+
it("plays once when loop is 1", async () => {
|
|
299
294
|
let callCount = 0;
|
|
300
|
-
|
|
295
|
+
await Offline(({ transport }) => {
|
|
301
296
|
new ToneEvent({
|
|
302
297
|
loop: 1,
|
|
303
298
|
loopEnd: 0.125,
|
|
@@ -306,14 +301,13 @@ describe("ToneEvent", () => {
|
|
|
306
301
|
},
|
|
307
302
|
}).start(0);
|
|
308
303
|
transport.start();
|
|
309
|
-
}, 0.8)
|
|
310
|
-
|
|
311
|
-
});
|
|
304
|
+
}, 0.8);
|
|
305
|
+
expect(callCount).to.equal(1);
|
|
312
306
|
});
|
|
313
307
|
|
|
314
|
-
it("plays once when loop is 0", () => {
|
|
308
|
+
it("plays once when loop is 0", async () => {
|
|
315
309
|
let callCount = 0;
|
|
316
|
-
|
|
310
|
+
await Offline(({ transport }) => {
|
|
317
311
|
new ToneEvent({
|
|
318
312
|
loop: 0,
|
|
319
313
|
loopEnd: 0.125,
|
|
@@ -322,14 +316,13 @@ describe("ToneEvent", () => {
|
|
|
322
316
|
},
|
|
323
317
|
}).start(0);
|
|
324
318
|
transport.start();
|
|
325
|
-
}, 0.8)
|
|
326
|
-
|
|
327
|
-
});
|
|
319
|
+
}, 0.8);
|
|
320
|
+
expect(callCount).to.equal(1);
|
|
328
321
|
});
|
|
329
322
|
|
|
330
|
-
it("plays once when loop is false", () => {
|
|
323
|
+
it("plays once when loop is false", async () => {
|
|
331
324
|
let callCount = 0;
|
|
332
|
-
|
|
325
|
+
await Offline(({ transport }) => {
|
|
333
326
|
new ToneEvent({
|
|
334
327
|
loop: false,
|
|
335
328
|
loopEnd: 0.125,
|
|
@@ -338,18 +331,16 @@ describe("ToneEvent", () => {
|
|
|
338
331
|
},
|
|
339
332
|
}).start(0);
|
|
340
333
|
transport.start();
|
|
341
|
-
}, 0.8)
|
|
342
|
-
|
|
343
|
-
});
|
|
334
|
+
}, 0.8);
|
|
335
|
+
expect(callCount).to.equal(1);
|
|
344
336
|
});
|
|
345
337
|
|
|
346
|
-
it("can be started and stopped multiple times", () => {
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
let eventTimeIndex = 0;
|
|
338
|
+
it("can be started and stopped multiple times", async () => {
|
|
339
|
+
const eventTimes = [
|
|
340
|
+
0.3, 0.39, 0.9, 0.99, 1.3, 1.39, 1.48, 1.57, 1.66, 1.75, 1.84,
|
|
341
|
+
];
|
|
342
|
+
let eventTimeIndex = 0;
|
|
343
|
+
await Offline(({ transport }) => {
|
|
353
344
|
new ToneEvent({
|
|
354
345
|
loop: true,
|
|
355
346
|
loopEnd: 0.09,
|
|
@@ -370,9 +361,9 @@ describe("ToneEvent", () => {
|
|
|
370
361
|
}, 2);
|
|
371
362
|
});
|
|
372
363
|
|
|
373
|
-
it("loops the correct amount of times when the event is started in the transport's past", () => {
|
|
364
|
+
it("loops the correct amount of times when the event is started in the transport's past", async () => {
|
|
374
365
|
let callCount = 0;
|
|
375
|
-
|
|
366
|
+
await Offline(({ transport }) => {
|
|
376
367
|
const note = new ToneEvent({
|
|
377
368
|
loop: 3,
|
|
378
369
|
loopEnd: 0.2,
|
|
@@ -388,13 +379,12 @@ describe("ToneEvent", () => {
|
|
|
388
379
|
note.start(0);
|
|
389
380
|
}
|
|
390
381
|
};
|
|
391
|
-
}, 1)
|
|
392
|
-
|
|
393
|
-
});
|
|
382
|
+
}, 1);
|
|
383
|
+
expect(callCount).to.equal(2);
|
|
394
384
|
});
|
|
395
385
|
|
|
396
|
-
it("reports the progress of the loop", () => {
|
|
397
|
-
|
|
386
|
+
it("reports the progress of the loop", async () => {
|
|
387
|
+
await Offline(({ transport }) => {
|
|
398
388
|
const note = new ToneEvent({
|
|
399
389
|
loop: true,
|
|
400
390
|
loopEnd: 1,
|
|
@@ -408,8 +398,8 @@ describe("ToneEvent", () => {
|
|
|
408
398
|
}, 0.8);
|
|
409
399
|
});
|
|
410
400
|
|
|
411
|
-
it("progress is 0 when not looping", () => {
|
|
412
|
-
Offline(({ transport }) => {
|
|
401
|
+
it("progress is 0 when not looping", async () => {
|
|
402
|
+
await Offline(({ transport }) => {
|
|
413
403
|
const note = new ToneEvent({
|
|
414
404
|
loop: false,
|
|
415
405
|
loopEnd: 0.25,
|
|
@@ -423,8 +413,8 @@ describe("ToneEvent", () => {
|
|
|
423
413
|
});
|
|
424
414
|
|
|
425
415
|
context("playbackRate and humanize", () => {
|
|
426
|
-
it("can adjust the playbackRate", () => {
|
|
427
|
-
|
|
416
|
+
it("can adjust the playbackRate", async () => {
|
|
417
|
+
await Offline(({ transport }) => {
|
|
428
418
|
let lastCall;
|
|
429
419
|
new ToneEvent({
|
|
430
420
|
loop: true,
|
|
@@ -441,8 +431,8 @@ describe("ToneEvent", () => {
|
|
|
441
431
|
}, 0.7);
|
|
442
432
|
});
|
|
443
433
|
|
|
444
|
-
it("can adjust the playbackRate after starting", () => {
|
|
445
|
-
|
|
434
|
+
it("can adjust the playbackRate after starting", async () => {
|
|
435
|
+
await Offline(({ transport }) => {
|
|
446
436
|
let lastCall;
|
|
447
437
|
const note = new ToneEvent({
|
|
448
438
|
loop: true,
|
|
@@ -461,8 +451,8 @@ describe("ToneEvent", () => {
|
|
|
461
451
|
}, 1.2);
|
|
462
452
|
});
|
|
463
453
|
|
|
464
|
-
it("can humanize the callback by some amount", () => {
|
|
465
|
-
|
|
454
|
+
it("can humanize the callback by some amount", async () => {
|
|
455
|
+
await Offline(({ transport }) => {
|
|
466
456
|
let lastCall;
|
|
467
457
|
const note = new ToneEvent({
|
|
468
458
|
humanize: 0.05,
|
|
@@ -71,7 +71,7 @@ describe("MonoSynth", () => {
|
|
|
71
71
|
});
|
|
72
72
|
|
|
73
73
|
it("is silent after triggerAttack if sustain is 0", async () => {
|
|
74
|
-
|
|
74
|
+
const buffer = await Offline(() => {
|
|
75
75
|
const synth = new MonoSynth({
|
|
76
76
|
envelope: {
|
|
77
77
|
attack: 0.1,
|
|
@@ -80,9 +80,8 @@ describe("MonoSynth", () => {
|
|
|
80
80
|
},
|
|
81
81
|
}).toDestination();
|
|
82
82
|
synth.triggerAttack("C4", 0);
|
|
83
|
-
}, 0.5)
|
|
84
|
-
|
|
85
|
-
});
|
|
83
|
+
}, 0.5);
|
|
84
|
+
expect(buffer.getTimeOfLastSound()).to.be.closeTo(0.2, 0.01);
|
|
86
85
|
});
|
|
87
86
|
});
|
|
88
87
|
});
|
|
@@ -76,29 +76,28 @@ describe("PolySynth", () => {
|
|
|
76
76
|
});
|
|
77
77
|
|
|
78
78
|
context("Playing Notes", () => {
|
|
79
|
-
it("triggerAttackRelease can take an array of durations", () => {
|
|
80
|
-
|
|
79
|
+
it("triggerAttackRelease can take an array of durations", async () => {
|
|
80
|
+
await OutputAudio(() => {
|
|
81
81
|
const polySynth = new PolySynth();
|
|
82
82
|
polySynth.toDestination();
|
|
83
83
|
polySynth.triggerAttackRelease(["C4", "D4"], [0.1, 0.2]);
|
|
84
84
|
});
|
|
85
85
|
});
|
|
86
86
|
|
|
87
|
-
it("triggerAttack and triggerRelease can be invoked without arrays", () => {
|
|
88
|
-
|
|
87
|
+
it("triggerAttack and triggerRelease can be invoked without arrays", async () => {
|
|
88
|
+
const buffer = await Offline(() => {
|
|
89
89
|
const polySynth = new PolySynth();
|
|
90
90
|
polySynth.set({ envelope: { release: 0.1 } });
|
|
91
91
|
polySynth.toDestination();
|
|
92
92
|
polySynth.triggerAttack("C4", 0);
|
|
93
93
|
polySynth.triggerRelease("C4", 0.1);
|
|
94
|
-
}, 0.3)
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
});
|
|
94
|
+
}, 0.3);
|
|
95
|
+
expect(buffer.getTimeOfFirstSound()).to.be.closeTo(0, 0.01);
|
|
96
|
+
expect(buffer.getValueAtTime(0.2)).to.be.closeTo(0, 0.01);
|
|
98
97
|
});
|
|
99
98
|
|
|
100
|
-
it("can stop all of the currently playing sounds", () => {
|
|
101
|
-
|
|
99
|
+
it("can stop all of the currently playing sounds", async () => {
|
|
100
|
+
const buffer = await Offline(() => {
|
|
102
101
|
const polySynth = new PolySynth();
|
|
103
102
|
polySynth.set({ envelope: { release: 0.1 } });
|
|
104
103
|
polySynth.toDestination();
|
|
@@ -106,33 +105,30 @@ describe("PolySynth", () => {
|
|
|
106
105
|
return atTime(0.1, () => {
|
|
107
106
|
polySynth.releaseAll();
|
|
108
107
|
});
|
|
109
|
-
}, 0.3)
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
});
|
|
108
|
+
}, 0.3);
|
|
109
|
+
expect(buffer.getTimeOfFirstSound()).to.be.closeTo(0, 0.01);
|
|
110
|
+
expect(buffer.getTimeOfLastSound()).to.be.closeTo(0.2, 0.01);
|
|
113
111
|
});
|
|
114
112
|
|
|
115
|
-
it("is silent before being triggered", () => {
|
|
116
|
-
|
|
113
|
+
it("is silent before being triggered", async () => {
|
|
114
|
+
const buffer = await Offline(() => {
|
|
117
115
|
const polySynth = new PolySynth();
|
|
118
116
|
polySynth.toDestination();
|
|
119
|
-
}).then((buffer) => {
|
|
120
|
-
expect(buffer.isSilent()).to.be.true;
|
|
121
117
|
});
|
|
118
|
+
expect(buffer.isSilent()).to.be.true;
|
|
122
119
|
});
|
|
123
120
|
|
|
124
|
-
it("can be scheduled to start in the future", () => {
|
|
125
|
-
|
|
121
|
+
it("can be scheduled to start in the future", async () => {
|
|
122
|
+
const buffer = await Offline(() => {
|
|
126
123
|
const polySynth = new PolySynth();
|
|
127
124
|
polySynth.toDestination();
|
|
128
125
|
polySynth.triggerAttack("C4", 0.1);
|
|
129
|
-
}, 0.3)
|
|
130
|
-
|
|
131
|
-
});
|
|
126
|
+
}, 0.3);
|
|
127
|
+
expect(buffer.getTimeOfFirstSound()).to.be.closeTo(0.1, 0.01);
|
|
132
128
|
});
|
|
133
129
|
|
|
134
|
-
it("can stop all sounds scheduled to start in the future when disposed", () => {
|
|
135
|
-
|
|
130
|
+
it("can stop all sounds scheduled to start in the future when disposed", async () => {
|
|
131
|
+
const buffer = await Offline(() => {
|
|
136
132
|
const polySynth = new PolySynth();
|
|
137
133
|
polySynth.set({ envelope: { release: 0.1 } });
|
|
138
134
|
polySynth.toDestination();
|
|
@@ -140,13 +136,12 @@ describe("PolySynth", () => {
|
|
|
140
136
|
return atTime(0.1, () => {
|
|
141
137
|
polySynth.dispose();
|
|
142
138
|
});
|
|
143
|
-
}, 0.3)
|
|
144
|
-
|
|
145
|
-
});
|
|
139
|
+
}, 0.3);
|
|
140
|
+
expect(buffer.isSilent()).to.be.true;
|
|
146
141
|
});
|
|
147
142
|
|
|
148
|
-
it("disposes voices when they are no longer used", () => {
|
|
149
|
-
|
|
143
|
+
it("disposes voices when they are no longer used", async () => {
|
|
144
|
+
await Offline(() => {
|
|
150
145
|
const polySynth = new PolySynth(Synth, {
|
|
151
146
|
envelope: {
|
|
152
147
|
release: 0.1,
|
|
@@ -181,8 +176,8 @@ describe("PolySynth", () => {
|
|
|
181
176
|
});
|
|
182
177
|
});
|
|
183
178
|
|
|
184
|
-
it("reports the active notes", () => {
|
|
185
|
-
|
|
179
|
+
it("reports the active notes", async () => {
|
|
180
|
+
await Offline(() => {
|
|
186
181
|
const polySynth = new PolySynth();
|
|
187
182
|
polySynth.set({ envelope: { release: 0.1 } });
|
|
188
183
|
polySynth.toDestination();
|
|
@@ -222,9 +217,9 @@ describe("PolySynth", () => {
|
|
|
222
217
|
}, 1);
|
|
223
218
|
});
|
|
224
219
|
|
|
225
|
-
it("can trigger another attack before the release has ended", () => {
|
|
220
|
+
it("can trigger another attack before the release has ended", async () => {
|
|
226
221
|
// compute the end time
|
|
227
|
-
|
|
222
|
+
const buffer = await Offline(() => {
|
|
228
223
|
const synth = new PolySynth(Synth, {
|
|
229
224
|
envelope: {
|
|
230
225
|
release: 0.1,
|
|
@@ -235,14 +230,13 @@ describe("PolySynth", () => {
|
|
|
235
230
|
synth.triggerRelease("C4", 0.1);
|
|
236
231
|
synth.triggerAttack("C4", 0.15);
|
|
237
232
|
synth.triggerRelease("C4", 0.2);
|
|
238
|
-
}, 1)
|
|
239
|
-
|
|
240
|
-
});
|
|
233
|
+
}, 1);
|
|
234
|
+
expect(buffer.getTimeOfLastSound()).to.be.closeTo(0.3, 0.01);
|
|
241
235
|
});
|
|
242
236
|
|
|
243
|
-
it("can trigger another attack right after the release has ended", () => {
|
|
237
|
+
it("can trigger another attack right after the release has ended", async () => {
|
|
244
238
|
// compute the end time
|
|
245
|
-
|
|
239
|
+
const buffer = await Offline(() => {
|
|
246
240
|
const synth = new PolySynth(Synth, {
|
|
247
241
|
envelope: {
|
|
248
242
|
release: 0.1,
|
|
@@ -256,15 +250,14 @@ describe("PolySynth", () => {
|
|
|
256
250
|
return atTime(0.41, () => {
|
|
257
251
|
expect(synth.activeVoices).to.equal(0);
|
|
258
252
|
});
|
|
259
|
-
}, 1)
|
|
260
|
-
|
|
261
|
-
});
|
|
253
|
+
}, 1);
|
|
254
|
+
expect(buffer.getTimeOfLastSound()).to.be.closeTo(0.4, 0.01);
|
|
262
255
|
});
|
|
263
256
|
});
|
|
264
257
|
|
|
265
258
|
context("Transport sync", () => {
|
|
266
|
-
it("can be synced to the transport", () => {
|
|
267
|
-
|
|
259
|
+
it("can be synced to the transport", async () => {
|
|
260
|
+
const buffer = await Offline(({ transport }) => {
|
|
268
261
|
const polySynth = new PolySynth(Synth, {
|
|
269
262
|
envelope: {
|
|
270
263
|
release: 0.1,
|
|
@@ -274,24 +267,22 @@ describe("PolySynth", () => {
|
|
|
274
267
|
polySynth.triggerAttackRelease("C4", 0.1, 0.1);
|
|
275
268
|
polySynth.triggerAttackRelease("E4", 0.1, 0.3);
|
|
276
269
|
transport.start(0.1);
|
|
277
|
-
}, 0.8)
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
});
|
|
270
|
+
}, 0.8);
|
|
271
|
+
expect(buffer.getTimeOfFirstSound()).to.be.closeTo(0.2, 0.01);
|
|
272
|
+
expect(buffer.getTimeOfLastSound()).to.be.closeTo(0.6, 0.01);
|
|
281
273
|
});
|
|
282
274
|
|
|
283
|
-
it("is silent until the transport is started", () => {
|
|
284
|
-
|
|
275
|
+
it("is silent until the transport is started", async () => {
|
|
276
|
+
const buffer = await Offline(({ transport }) => {
|
|
285
277
|
const synth = new PolySynth(Synth).sync().toDestination();
|
|
286
278
|
synth.triggerAttackRelease("C4", 0.5);
|
|
287
279
|
transport.start(0.5);
|
|
288
|
-
}, 1)
|
|
289
|
-
|
|
290
|
-
});
|
|
280
|
+
}, 1);
|
|
281
|
+
expect(buffer.getTimeOfFirstSound()).is.closeTo(0.5, 0.1);
|
|
291
282
|
});
|
|
292
283
|
|
|
293
|
-
it("stops when the transport is stopped", () => {
|
|
294
|
-
|
|
284
|
+
it("stops when the transport is stopped", async () => {
|
|
285
|
+
const buffer = await Offline(({ transport }) => {
|
|
295
286
|
const synth = new PolySynth(Synth, {
|
|
296
287
|
envelope: {
|
|
297
288
|
release: 0,
|
|
@@ -301,13 +292,12 @@ describe("PolySynth", () => {
|
|
|
301
292
|
.toDestination();
|
|
302
293
|
synth.triggerAttackRelease("C4", 0.5);
|
|
303
294
|
transport.start(0.5).stop(1);
|
|
304
|
-
}, 1.5)
|
|
305
|
-
|
|
306
|
-
});
|
|
295
|
+
}, 1.5);
|
|
296
|
+
expect(buffer.getTimeOfLastSound()).is.closeTo(1, 0.1);
|
|
307
297
|
});
|
|
308
298
|
|
|
309
|
-
it("goes silent at the loop boundary", () => {
|
|
310
|
-
|
|
299
|
+
it("goes silent at the loop boundary", async () => {
|
|
300
|
+
const buffer = await Offline(({ transport }) => {
|
|
311
301
|
const synth = new PolySynth(Synth, {
|
|
312
302
|
envelope: {
|
|
313
303
|
release: 0,
|
|
@@ -319,16 +309,15 @@ describe("PolySynth", () => {
|
|
|
319
309
|
transport.loopEnd = 1;
|
|
320
310
|
transport.loop = true;
|
|
321
311
|
transport.start();
|
|
322
|
-
}, 2)
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
});
|
|
312
|
+
}, 2);
|
|
313
|
+
expect(buffer.getRmsAtTime(0)).to.be.closeTo(0, 0.05);
|
|
314
|
+
expect(buffer.getRmsAtTime(0.6)).to.be.closeTo(0.2, 0.05);
|
|
315
|
+
expect(buffer.getRmsAtTime(1.1)).to.be.closeTo(0, 0.05);
|
|
316
|
+
expect(buffer.getRmsAtTime(1.6)).to.be.closeTo(0.2, 0.05);
|
|
328
317
|
});
|
|
329
318
|
|
|
330
|
-
it("can unsync", () => {
|
|
331
|
-
|
|
319
|
+
it("can unsync", async () => {
|
|
320
|
+
const buffer = await Offline(({ transport }) => {
|
|
332
321
|
const synth = new PolySynth(Synth, {
|
|
333
322
|
envelope: {
|
|
334
323
|
sustain: 1,
|
|
@@ -340,12 +329,11 @@ describe("PolySynth", () => {
|
|
|
340
329
|
.unsync();
|
|
341
330
|
synth.triggerAttackRelease("C4", 1, 0.5);
|
|
342
331
|
transport.start().stop(1);
|
|
343
|
-
}, 2)
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
});
|
|
332
|
+
}, 2);
|
|
333
|
+
expect(buffer.getRmsAtTime(0)).to.be.closeTo(0, 0.05);
|
|
334
|
+
expect(buffer.getRmsAtTime(0.6)).to.be.closeTo(0.6, 0.05);
|
|
335
|
+
expect(buffer.getRmsAtTime(1.4)).to.be.closeTo(0.6, 0.05);
|
|
336
|
+
expect(buffer.getRmsAtTime(1.6)).to.be.closeTo(0, 0.05);
|
|
349
337
|
});
|
|
350
338
|
});
|
|
351
339
|
|