tone 14.8.29 → 14.8.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/Tone/component/dynamics/Limiter.ts +1 -1
  2. package/Tone/component/envelope/Envelope.ts +2 -2
  3. package/Tone/component/filter/FeedbackCombFilter.ts +2 -2
  4. package/Tone/core/clock/TickSource.ts +1 -1
  5. package/Tone/core/clock/Transport.test.ts +15 -0
  6. package/Tone/core/clock/Transport.ts +93 -30
  7. package/Tone/core/context/ToneWithContext.ts +2 -0
  8. package/Tone/core/type/Frequency.ts +8 -8
  9. package/Tone/core/util/Debug.ts +37 -4
  10. package/Tone/core/util/StateTimeline.ts +1 -1
  11. package/Tone/effect/AutoFilter.ts +1 -1
  12. package/Tone/effect/Chebyshev.ts +1 -1
  13. package/Tone/effect/Chorus.test.ts +11 -8
  14. package/Tone/effect/Chorus.ts +1 -1
  15. package/Tone/effect/MidSideEffect.ts +2 -2
  16. package/Tone/effect/StereoEffect.ts +2 -2
  17. package/Tone/effect/Tremolo.ts +1 -1
  18. package/Tone/effect/Vibrato.ts +1 -1
  19. package/Tone/event/Pattern.ts +1 -1
  20. package/Tone/instrument/Instrument.ts +13 -0
  21. package/Tone/instrument/NoiseSynth.ts +56 -17
  22. package/Tone/instrument/PolySynth.test.ts +81 -18
  23. package/Tone/instrument/PolySynth.ts +11 -1
  24. package/Tone/instrument/Sampler.test.ts +0 -1
  25. package/Tone/instrument/Sampler.ts +1 -1
  26. package/Tone/instrument/Synth.test.ts +63 -0
  27. package/Tone/source/oscillator/PWMOscillator.ts +1 -1
  28. package/Tone/source/oscillator/PulseOscillator.ts +1 -1
  29. package/Tone/version.ts +1 -1
  30. package/build/Tone.js +1 -1
  31. package/build/Tone.js.map +1 -1
  32. package/build/esm/component/dynamics/Limiter.js +0 -1
  33. package/build/esm/component/dynamics/Limiter.js.map +1 -1
  34. package/build/esm/component/envelope/Envelope.js.map +1 -1
  35. package/build/esm/component/filter/FeedbackCombFilter.js +0 -2
  36. package/build/esm/component/filter/FeedbackCombFilter.js.map +1 -1
  37. package/build/esm/core/clock/TickSource.js.map +1 -1
  38. package/build/esm/core/clock/Transport.js +17 -11
  39. package/build/esm/core/clock/Transport.js.map +1 -1
  40. package/build/esm/core/context/ToneWithContext.js +2 -0
  41. package/build/esm/core/context/ToneWithContext.js.map +1 -1
  42. package/build/esm/core/type/Frequency.js +8 -8
  43. package/build/esm/core/type/Frequency.js.map +1 -1
  44. package/build/esm/core/util/Debug.d.ts +9 -1
  45. package/build/esm/core/util/Debug.js +22 -1
  46. package/build/esm/core/util/Debug.js.map +1 -1
  47. package/build/esm/core/util/StateTimeline.d.ts +1 -1
  48. package/build/esm/core/util/StateTimeline.js.map +1 -1
  49. package/build/esm/effect/AutoFilter.js.map +1 -1
  50. package/build/esm/effect/Chebyshev.js.map +1 -1
  51. package/build/esm/effect/Chorus.js.map +1 -1
  52. package/build/esm/effect/Tremolo.js.map +1 -1
  53. package/build/esm/effect/Vibrato.js.map +1 -1
  54. package/build/esm/event/Pattern.js.map +1 -1
  55. package/build/esm/instrument/Instrument.d.ts +4 -0
  56. package/build/esm/instrument/Instrument.js +10 -0
  57. package/build/esm/instrument/Instrument.js.map +1 -1
  58. package/build/esm/instrument/NoiseSynth.d.ts +10 -0
  59. package/build/esm/instrument/NoiseSynth.js +14 -2
  60. package/build/esm/instrument/NoiseSynth.js.map +1 -1
  61. package/build/esm/instrument/PolySynth.d.ts +4 -0
  62. package/build/esm/instrument/PolySynth.js +8 -0
  63. package/build/esm/instrument/PolySynth.js.map +1 -1
  64. package/build/esm/instrument/Sampler.js.map +1 -1
  65. package/build/esm/source/oscillator/PulseOscillator.js.map +1 -1
  66. package/build/esm/version.js +1 -1
  67. package/docs/tone.json +1 -1
  68. package/package.json +32 -30
@@ -4,7 +4,10 @@ import { omitFromObject, optionsFromArguments } from "../core/util/Defaults";
4
4
  import { RecursivePartial } from "../core/util/Interface";
5
5
  import { Noise, NoiseOptions } from "../source/Noise";
6
6
  import { Instrument, InstrumentOptions } from "./Instrument";
7
- import { ToneAudioNode, ToneAudioNodeOptions } from "../core/context/ToneAudioNode";
7
+ import {
8
+ ToneAudioNode,
9
+ ToneAudioNodeOptions,
10
+ } from "../core/context/ToneAudioNode";
8
11
  import { Envelope, EnvelopeOptions } from "../component/envelope/Envelope";
9
12
  import { Source } from "../source/Source";
10
13
 
@@ -14,7 +17,7 @@ export interface NoiseSynthOptions extends InstrumentOptions {
14
17
  }
15
18
 
16
19
  /**
17
- * Tone.NoiseSynth is composed of [[Noise]] through an [[AmplitudeEnvelope]].
20
+ * Tone.NoiseSynth is composed of [[Noise]] through an [[AmplitudeEnvelope]].
18
21
  * ```
19
22
  * +-------+ +-------------------+
20
23
  * | Noise +>--> AmplitudeEnvelope +>--> Output
@@ -26,7 +29,6 @@ export interface NoiseSynthOptions extends InstrumentOptions {
26
29
  * @category Instrument
27
30
  */
28
31
  export class NoiseSynth extends Instrument<NoiseSynthOptions> {
29
-
30
32
  readonly name = "NoiseSynth";
31
33
 
32
34
  /**
@@ -39,17 +41,30 @@ export class NoiseSynth extends Instrument<NoiseSynthOptions> {
39
41
  */
40
42
  readonly envelope: AmplitudeEnvelope;
41
43
 
42
- constructor(options?: RecursivePartial<NoiseSynthOptions>)
44
+ constructor(options?: RecursivePartial<NoiseSynthOptions>);
43
45
  constructor() {
44
46
  super(optionsFromArguments(NoiseSynth.getDefaults(), arguments));
45
- const options = optionsFromArguments(NoiseSynth.getDefaults(), arguments);
46
- this.noise = new Noise(Object.assign({
47
- context: this.context,
48
- }, options.noise));
47
+ const options = optionsFromArguments(
48
+ NoiseSynth.getDefaults(),
49
+ arguments
50
+ );
51
+ this.noise = new Noise(
52
+ Object.assign(
53
+ {
54
+ context: this.context,
55
+ },
56
+ options.noise
57
+ )
58
+ );
49
59
 
50
- this.envelope = new AmplitudeEnvelope(Object.assign({
51
- context: this.context,
52
- }, options.envelope));
60
+ this.envelope = new AmplitudeEnvelope(
61
+ Object.assign(
62
+ {
63
+ context: this.context,
64
+ },
65
+ options.envelope
66
+ )
67
+ );
53
68
 
54
69
  // connect the noise to the output
55
70
  this.noise.chain(this.envelope, this.output);
@@ -58,17 +73,23 @@ export class NoiseSynth extends Instrument<NoiseSynthOptions> {
58
73
  static getDefaults(): NoiseSynthOptions {
59
74
  return Object.assign(Instrument.getDefaults(), {
60
75
  envelope: Object.assign(
61
- omitFromObject(Envelope.getDefaults(), Object.keys(ToneAudioNode.getDefaults())),
76
+ omitFromObject(
77
+ Envelope.getDefaults(),
78
+ Object.keys(ToneAudioNode.getDefaults())
79
+ ),
62
80
  {
63
81
  decay: 0.1,
64
82
  sustain: 0.0,
65
- },
83
+ }
66
84
  ),
67
85
  noise: Object.assign(
68
- omitFromObject(Noise.getDefaults(), Object.keys(Source.getDefaults())),
86
+ omitFromObject(
87
+ Noise.getDefaults(),
88
+ Object.keys(Source.getDefaults())
89
+ ),
69
90
  {
70
91
  type: "white",
71
- },
92
+ }
72
93
  ),
73
94
  });
74
95
  }
@@ -87,7 +108,11 @@ export class NoiseSynth extends Instrument<NoiseSynthOptions> {
87
108
  // start the noise
88
109
  this.noise.start(time);
89
110
  if (this.envelope.sustain === 0) {
90
- this.noise.stop(time + this.toSeconds(this.envelope.attack) + this.toSeconds(this.envelope.decay));
111
+ this.noise.stop(
112
+ time +
113
+ this.toSeconds(this.envelope.attack) +
114
+ this.toSeconds(this.envelope.decay)
115
+ );
91
116
  }
92
117
  return this;
93
118
  }
@@ -110,7 +135,21 @@ export class NoiseSynth extends Instrument<NoiseSynthOptions> {
110
135
  return this;
111
136
  }
112
137
 
113
- triggerAttackRelease(duration: Time, time?: Time, velocity: NormalRange = 1): this {
138
+ /**
139
+ * Trigger the attack and then the release after the duration.
140
+ * @param duration The amount of time to hold the note for
141
+ * @param time The time the note should start
142
+ * @param velocity The volume of the note (0-1)
143
+ * @example
144
+ * const noiseSynth = new Tone.NoiseSynth().toDestination();
145
+ * // hold the note for 0.5 seconds
146
+ * noiseSynth.triggerAttackRelease(0.5);
147
+ */
148
+ triggerAttackRelease(
149
+ duration: Time,
150
+ time?: Time,
151
+ velocity: NormalRange = 1
152
+ ): this {
114
153
  time = this.toSeconds(time);
115
154
  duration = this.toSeconds(duration);
116
155
  this.triggerAttack(time, velocity);
@@ -135,23 +135,6 @@ describe("PolySynth", () => {
135
135
  });
136
136
  });
137
137
 
138
- it("can be synced to the transport", () => {
139
- return Offline(({ transport }) => {
140
- const polySynth = new PolySynth(Synth, {
141
- envelope: {
142
- release: 0.1,
143
- },
144
- }).sync();
145
- polySynth.toDestination();
146
- polySynth.triggerAttackRelease("C4", 0.1, 0.1);
147
- polySynth.triggerAttackRelease("E4", 0.1, 0.3);
148
- transport.start(0.1);
149
- }, 0.8).then((buffer) => {
150
- expect(buffer.getTimeOfFirstSound()).to.be.closeTo(0.2, 0.01);
151
- expect(buffer.getTimeOfLastSound()).to.be.closeTo(0.6, 0.01);
152
- });
153
- });
154
-
155
138
  it("disposes voices when they are no longer used", () => {
156
139
  return Offline(() => {
157
140
  const polySynth = new PolySynth(Synth, {
@@ -266,6 +249,86 @@ describe("PolySynth", () => {
266
249
 
267
250
  });
268
251
 
252
+ context("Transport sync", () => {
253
+ it("can be synced to the transport", () => {
254
+ return Offline(({ transport }) => {
255
+ const polySynth = new PolySynth(Synth, {
256
+ envelope: {
257
+ release: 0.1,
258
+ },
259
+ }).sync();
260
+ polySynth.toDestination();
261
+ polySynth.triggerAttackRelease("C4", 0.1, 0.1);
262
+ polySynth.triggerAttackRelease("E4", 0.1, 0.3);
263
+ transport.start(0.1);
264
+ }, 0.8).then((buffer) => {
265
+ expect(buffer.getTimeOfFirstSound()).to.be.closeTo(0.2, 0.01);
266
+ expect(buffer.getTimeOfLastSound()).to.be.closeTo(0.6, 0.01);
267
+ });
268
+ });
269
+
270
+ it("is silent until the transport is started", () => {
271
+ return Offline(({ transport }) => {
272
+ const synth = new PolySynth(Synth).sync().toDestination();
273
+ synth.triggerAttackRelease("C4", 0.5);
274
+ transport.start(0.5);
275
+ }, 1).then((buffer) => {
276
+ expect(buffer.getTimeOfFirstSound()).is.closeTo(0.5, 0.1);
277
+ });
278
+ });
279
+
280
+ it("stops when the transport is stopped", () => {
281
+ return Offline(({ transport }) => {
282
+ const synth = new PolySynth(Synth, {
283
+ envelope: {
284
+ release: 0
285
+ }
286
+ }).sync().toDestination();
287
+ synth.triggerAttackRelease("C4", 0.5);
288
+ transport.start(0.5).stop(1);
289
+ }, 1.5).then((buffer) => {
290
+ expect(buffer.getTimeOfLastSound()).is.closeTo(1, 0.1);
291
+ });
292
+ });
293
+
294
+ it("goes silent at the loop boundary", () => {
295
+ return Offline(({ transport }) => {
296
+ const synth = new PolySynth(Synth, {
297
+ envelope: {
298
+ release: 0
299
+ }
300
+ }).sync().toDestination();
301
+ synth.triggerAttackRelease("C4", 0.8, 0.5);
302
+ transport.loopEnd = 1;
303
+ transport.loop = true;
304
+ transport.start();
305
+ }, 2).then((buffer) => {
306
+ expect(buffer.getRmsAtTime(0)).to.be.closeTo(0, 0.05);
307
+ expect(buffer.getRmsAtTime(0.6)).to.be.closeTo(0.2, 0.05);
308
+ expect(buffer.getRmsAtTime(1.1)).to.be.closeTo(0, 0.05);
309
+ expect(buffer.getRmsAtTime(1.6)).to.be.closeTo(0.2, 0.05);
310
+ });
311
+ });
312
+
313
+ it("can unsync", () => {
314
+ return Offline(({ transport }) => {
315
+ const synth = new PolySynth(Synth, {
316
+ envelope: {
317
+ sustain: 1,
318
+ release: 0
319
+ }
320
+ }).sync().toDestination().unsync();
321
+ synth.triggerAttackRelease("C4", 1, 0.5);
322
+ transport.start().stop(1);
323
+ }, 2).then((buffer) => {
324
+ expect(buffer.getRmsAtTime(0)).to.be.closeTo(0, 0.05);
325
+ expect(buffer.getRmsAtTime(0.6)).to.be.closeTo(0.6, 0.05);
326
+ expect(buffer.getRmsAtTime(1.4)).to.be.closeTo(0.6, 0.05);
327
+ expect(buffer.getRmsAtTime(1.6)).to.be.closeTo(0, 0.05);
328
+ });
329
+ });
330
+ });
331
+
269
332
  context("API", () => {
270
333
 
271
334
  it("can be constructed with an options object", () => {
@@ -282,7 +345,7 @@ describe("PolySynth", () => {
282
345
  expect(() => {
283
346
  // @ts-ignore
284
347
  new PolySynth(PluckSynth);
285
- }).throws(Error)
348
+ }).throws(Error);
286
349
  });
287
350
 
288
351
  it("can pass in the volume", () => {
@@ -341,10 +341,20 @@ export class PolySynth<Voice extends Monophonic<any> = Synth> extends Instrument
341
341
  if (this._syncState()) {
342
342
  this._syncMethod("triggerAttack", 1);
343
343
  this._syncMethod("triggerRelease", 1);
344
+
345
+ // make sure that the sound doesn't play after its been stopped
346
+ this.context.transport.on("stop", this._syncedRelease);
347
+ this.context.transport.on("pause", this._syncedRelease);
348
+ this.context.transport.on("loopEnd", this._syncedRelease);
344
349
  }
345
350
  return this;
346
351
  }
347
352
 
353
+ /**
354
+ * The release which is scheduled to the timeline.
355
+ */
356
+ protected _syncedRelease = (time: number) => this.releaseAll(time);
357
+
348
358
  /**
349
359
  * Set a member/attribute of the voices
350
360
  * @example
@@ -382,7 +392,7 @@ export class PolySynth<Voice extends Monophonic<any> = Synth> extends Instrument
382
392
  });
383
393
  return this;
384
394
  }
385
-
395
+
386
396
  dispose(): this {
387
397
  super.dispose();
388
398
  this._dummyVoice.dispose();
@@ -1,4 +1,3 @@
1
- /* eslint-disable @typescript-eslint/camelcase */
2
1
  import { expect } from "chai";
3
2
  import { BasicTests } from "test/helper/Basic";
4
3
  import { CompareToFile } from "test/helper/CompareToFile";
@@ -138,7 +138,7 @@ export class Sampler extends Instrument<SamplerOptions> {
138
138
  return Object.assign(Instrument.getDefaults(), {
139
139
  attack: 0,
140
140
  baseUrl: "",
141
- curve: "exponential" as "exponential",
141
+ curve: "exponential" as const,
142
142
  onload: noOp,
143
143
  onerror: noOp,
144
144
  release: 0.1,
@@ -106,6 +106,69 @@ describe("Synth", () => {
106
106
  });
107
107
  });
108
108
 
109
+ context("Transport sync", () => {
110
+ it("is silent until the transport is started", () => {
111
+ return Offline(({ transport }) => {
112
+ const synth = new Synth().sync().toDestination();
113
+ synth.triggerAttackRelease("C4", 0.5);
114
+ transport.start(0.5);
115
+ }, 1).then((buffer) => {
116
+ expect(buffer.getTimeOfFirstSound()).is.closeTo(0.5, 0.1);
117
+ });
118
+ });
119
+
120
+ it("stops when the transport is stopped", () => {
121
+ return Offline(({ transport }) => {
122
+ const synth = new Synth({
123
+ envelope: {
124
+ release: 0
125
+ }
126
+ }).sync().toDestination();
127
+ synth.triggerAttackRelease("C4", 0.5);
128
+ transport.start(0.5).stop(1);
129
+ }, 1.5).then((buffer) => {
130
+ expect(buffer.getTimeOfLastSound()).is.closeTo(1, 0.1);
131
+ });
132
+ });
133
+
134
+ it("goes silent at the loop boundary", () => {
135
+ return Offline(({ transport }) => {
136
+ const synth = new Synth({
137
+ envelope: {
138
+ release: 0
139
+ }
140
+ }).sync().toDestination();
141
+ synth.triggerAttackRelease("C4", 0.8, 0.5);
142
+ transport.loopEnd = 1;
143
+ transport.loop = true;
144
+ transport.start();
145
+ }, 2).then((buffer) => {
146
+ expect(buffer.getRmsAtTime(0)).to.be.closeTo(0, 0.05);
147
+ expect(buffer.getRmsAtTime(0.6)).to.be.closeTo(0.2, 0.05);
148
+ expect(buffer.getRmsAtTime(1.1)).to.be.closeTo(0, 0.05);
149
+ expect(buffer.getRmsAtTime(1.6)).to.be.closeTo(0.2, 0.05);
150
+ });
151
+ });
152
+
153
+ it("can unsync", () => {
154
+ return Offline(({ transport }) => {
155
+ const synth = new Synth({
156
+ envelope: {
157
+ sustain: 1,
158
+ release: 0
159
+ }
160
+ }).sync().toDestination().unsync();
161
+ synth.triggerAttackRelease("C4", 1, 0.5);
162
+ transport.start().stop(1);
163
+ }, 2).then((buffer) => {
164
+ expect(buffer.getRmsAtTime(0)).to.be.closeTo(0, 0.05);
165
+ expect(buffer.getRmsAtTime(0.6)).to.be.closeTo(0.6, 0.05);
166
+ expect(buffer.getRmsAtTime(1.4)).to.be.closeTo(0.6, 0.05);
167
+ expect(buffer.getRmsAtTime(1.6)).to.be.closeTo(0, 0.05);
168
+ });
169
+ });
170
+ });
171
+
109
172
  context("Portamento", () => {
110
173
  it("can play notes with a portamento", () => {
111
174
  return Offline(() => {
@@ -106,7 +106,7 @@ export class PWMOscillator extends Source<PWMOscillatorOptions> implements ToneO
106
106
  frequency: 440,
107
107
  modulationFrequency: 0.4,
108
108
  phase: 0,
109
- type: "pwm" as "pwm",
109
+ type: "pwm" as const,
110
110
  });
111
111
  }
112
112
  /**
@@ -128,7 +128,7 @@ export class PulseOscillator extends Source<PulseOscillatorOptions> implements T
128
128
  detune: 0,
129
129
  frequency: 440,
130
130
  phase: 0,
131
- type: "pulse" as "pulse",
131
+ type: "pulse" as const,
132
132
  width: 0.2,
133
133
  });
134
134
  }
package/Tone/version.ts CHANGED
@@ -1 +1 @@
1
- export const version: string = "14.8.29";
1
+ export const version: string = "14.8.33";