tone 15.1.23 → 15.2.0

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.
@@ -1,8 +1,8 @@
1
1
  import { expect } from "chai";
2
2
  import { BasicTests } from "../../test/helper/Basic.js";
3
- import { CompareToFile } from "../../test/helper/CompareToFile.js";
4
3
  import { Offline, whenBetween } from "../../test/helper/Offline.js";
5
4
  import { ToneConstantSource } from "./ToneConstantSource.js";
5
+ import { Context } from "../core/context/Context.js";
6
6
 
7
7
  describe("ToneConstantSource", () => {
8
8
  BasicTests(ToneConstantSource);
@@ -36,7 +36,7 @@ describe("ToneConstantSource", () => {
36
36
  source.stop("+0.3");
37
37
  const now = source.now();
38
38
  source.onended = () => {
39
- expect(source.now() - now).to.be.within(0.25, 0.5);
39
+ expect(source.now() - now).to.be.closeTo(0.3, 0.15);
40
40
  source.dispose();
41
41
  done();
42
42
  };
@@ -186,4 +186,65 @@ describe("ToneConstantSource", () => {
186
186
  }, 0.2);
187
187
  });
188
188
  });
189
+
190
+ context.only("Suspended AudioContext", () => {
191
+ it("does nothing when AudioContext returns to suspended", () => {
192
+ const context = new Context();
193
+ expect(context.state).to.equal("suspended");
194
+
195
+ const source = new ToneConstantSource({
196
+ context,
197
+ });
198
+
199
+ source.start(0);
200
+
201
+ context.dispose();
202
+ source.dispose();
203
+ });
204
+
205
+ it("starts when the audio context is resumed", async () => {
206
+ const context = new Context();
207
+ expect(context.state).to.equal("suspended");
208
+
209
+ const source = new ToneConstantSource({
210
+ context,
211
+ });
212
+
213
+ source.start(0);
214
+
215
+ await context.resume();
216
+
217
+ context.dispose();
218
+ source.dispose();
219
+ });
220
+
221
+ it("context can be suspended again", async () => {
222
+ const context = new Context();
223
+ expect(context.state).to.equal("suspended");
224
+
225
+ const source = new ToneConstantSource({
226
+ context,
227
+ });
228
+
229
+ source.start(0);
230
+
231
+ await context.resume();
232
+
233
+ source.stop(0.1);
234
+
235
+ await context.rawContext.suspend(0);
236
+
237
+ // wait for the context to be suspended
238
+ await new Promise<void>((resolve) =>
239
+ context.on("statechange", () => {
240
+ if (context.state === "suspended") {
241
+ resolve();
242
+ }
243
+ })
244
+ );
245
+
246
+ context.dispose();
247
+ source.dispose();
248
+ });
249
+ });
189
250
  });
@@ -29,7 +29,7 @@ export class ToneConstantSource<
29
29
  /**
30
30
  * The signal generator
31
31
  */
32
- private _source = this.context.createConstantSource();
32
+ private _source?: ConstantSourceNode;
33
33
 
34
34
  /**
35
35
  * The offset of the signal generator
@@ -49,12 +49,24 @@ export class ToneConstantSource<
49
49
  );
50
50
  super(options);
51
51
 
52
- connect(this._source, this._gainNode);
52
+ const isSuspended =
53
+ !this.context.isOffline && this.context.state !== "running";
54
+
55
+ if (!isSuspended) {
56
+ this._source = this.context.createConstantSource();
57
+ connect(this._source, this._gainNode);
58
+ } else {
59
+ this.context.on("statechange", this._contextStarted);
60
+ }
53
61
 
54
62
  this.offset = new Param({
55
63
  context: this.context,
56
64
  convert: options.convert,
57
- param: this._source.offset,
65
+ param: isSuspended
66
+ ? // placeholder param until the context is started
67
+ this.context.createGain().gain
68
+ : this._source?.offset,
69
+ swappable: isSuspended,
58
70
  units: options.units,
59
71
  value: options.offset,
60
72
  minValue: options.minValue,
@@ -70,6 +82,21 @@ export class ToneConstantSource<
70
82
  });
71
83
  }
72
84
 
85
+ /**
86
+ * Once the context is started, kick off source.
87
+ */
88
+ private readonly _contextStarted = (state: AudioContextState) => {
89
+ if (state !== "running") {
90
+ return;
91
+ }
92
+ this._source = this.context.createConstantSource();
93
+ connect(this._source, this._gainNode);
94
+ this.offset.setParam(this._source.offset);
95
+ if (this.state === "started") {
96
+ this._source.start(0);
97
+ }
98
+ };
99
+
73
100
  /**
74
101
  * Start the source node at the given time
75
102
  * @param time When to start the source
@@ -78,12 +105,15 @@ export class ToneConstantSource<
78
105
  const computedTime = this.toSeconds(time);
79
106
  this.log("start", computedTime);
80
107
  this._startGain(computedTime);
81
- this._source.start(computedTime);
108
+ this._source?.start(computedTime);
82
109
  return this;
83
110
  }
84
111
 
85
112
  protected _stopSource(time?: Seconds): void {
86
- this._source.stop(time);
113
+ if (this.state === "stopped") {
114
+ return;
115
+ }
116
+ this._source?.stop(time);
87
117
  }
88
118
 
89
119
  dispose(): this {
@@ -91,8 +121,9 @@ export class ToneConstantSource<
91
121
  if (this.state === "started") {
92
122
  this.stop();
93
123
  }
94
- this._source.disconnect();
124
+ this._source?.disconnect();
95
125
  this.offset.dispose();
126
+ this.context.off("statechange", this._contextStarted);
96
127
  return this;
97
128
  }
98
129
  }
package/Tone/version.ts CHANGED
@@ -1 +1 @@
1
- export const version: string = "15.1.23";
1
+ export const version: string = "15.2.0";