tone 15.5.20 → 15.5.22

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 (43) hide show
  1. package/Tone/core/Global.test.ts +19 -0
  2. package/Tone/core/Global.ts +11 -32
  3. package/Tone/core/clock/TickSource.ts +1 -1
  4. package/Tone/core/clock/Transport.ts +1 -1
  5. package/Tone/core/context/GlobalContext.ts +34 -0
  6. package/Tone/core/context/OfflineContext.ts +1 -1
  7. package/Tone/core/context/ToneAudioBuffer.ts +1 -1
  8. package/Tone/core/type/Frequency.test.ts +11 -3
  9. package/Tone/core/type/Frequency.ts +27 -13
  10. package/Tone/core/type/Midi.test.ts +1 -0
  11. package/Tone/core/type/TimeBase.ts +17 -6
  12. package/Tone/core/worklet/ToneAudioWorklet.ts +6 -5
  13. package/Tone/signal/SyncedSignal.ts +1 -1
  14. package/Tone/source/OneShotSource.ts +1 -1
  15. package/Tone/source/buffer/Player.ts +3 -2
  16. package/Tone/version.ts +1 -1
  17. package/build/Tone.js +1 -1
  18. package/build/Tone.js.map +1 -1
  19. package/build/esm/core/Global.d.ts +2 -5
  20. package/build/esm/core/Global.js +8 -26
  21. package/build/esm/core/Global.js.map +1 -1
  22. package/build/esm/core/clock/TickSource.js.map +1 -1
  23. package/build/esm/core/clock/Transport.js +1 -1
  24. package/build/esm/core/clock/Transport.js.map +1 -1
  25. package/build/esm/core/context/GlobalContext.d.ts +15 -0
  26. package/build/esm/core/context/GlobalContext.js +30 -0
  27. package/build/esm/core/context/GlobalContext.js.map +1 -0
  28. package/build/esm/core/context/OfflineContext.js +1 -1
  29. package/build/esm/core/context/OfflineContext.js.map +1 -1
  30. package/build/esm/core/context/ToneAudioBuffer.js +1 -1
  31. package/build/esm/core/context/ToneAudioBuffer.js.map +1 -1
  32. package/build/esm/core/type/Frequency.js +9 -7
  33. package/build/esm/core/type/Frequency.js.map +1 -1
  34. package/build/esm/core/type/TimeBase.d.ts +2 -2
  35. package/build/esm/core/type/TimeBase.js +1 -1
  36. package/build/esm/core/type/TimeBase.js.map +1 -1
  37. package/build/esm/core/worklet/ToneAudioWorklet.js +1 -3
  38. package/build/esm/core/worklet/ToneAudioWorklet.js.map +1 -1
  39. package/build/esm/source/OneShotSource.js +1 -1
  40. package/build/esm/source/OneShotSource.js.map +1 -1
  41. package/build/esm/source/buffer/Player.js.map +1 -1
  42. package/build/esm/version.js +1 -1
  43. package/package.json +1 -1
@@ -0,0 +1,19 @@
1
+ import { expect } from "chai";
2
+
3
+ import { Context } from "./context/Context.js";
4
+ import { getContext, setContext } from "./Global.js";
5
+
6
+ describe("Global", () => {
7
+ it("can setContext with disposeOld = true", () => {
8
+ const origContext = getContext();
9
+ const toneContext = new Context();
10
+
11
+ setContext(toneContext);
12
+ expect(getContext()).to.equal(toneContext);
13
+
14
+ setContext(origContext, true);
15
+
16
+ expect(getContext()).to.equal(origContext);
17
+ expect(toneContext.disposed).to.be.true;
18
+ });
19
+ });
@@ -1,39 +1,18 @@
1
1
  import { version } from "../version.js";
2
- import {
3
- AnyAudioContext,
4
- hasAudioContext,
5
- theWindow,
6
- } from "./context/AudioContext.js";
2
+ import { AnyAudioContext, theWindow } from "./context/AudioContext.js";
7
3
  import { BaseContext } from "./context/BaseContext.js";
8
4
  import { Context } from "./context/Context.js";
9
- import { DummyContext } from "./context/DummyContext.js";
5
+ import {
6
+ getContext,
7
+ setContext as _setContext,
8
+ } from "./context/GlobalContext.js";
10
9
  import { OfflineContext } from "./context/OfflineContext.js";
11
10
  import {
12
11
  isAudioContext,
13
12
  isOfflineAudioContext,
14
13
  } from "./util/AdvancedTypeCheck.js";
15
14
 
16
- /**
17
- * This dummy context is used to avoid throwing immediate errors when importing in Node.js
18
- */
19
- const dummyContext = new DummyContext();
20
-
21
- /**
22
- * The global audio context which is getable and assignable through
23
- * getContext and setContext
24
- */
25
- let globalContext: BaseContext = dummyContext;
26
-
27
- /**
28
- * Returns the default system-wide {@link Context}
29
- * @category Core
30
- */
31
- export function getContext(): BaseContext {
32
- if (globalContext === dummyContext && hasAudioContext) {
33
- setContext(new Context());
34
- }
35
- return globalContext;
36
- }
15
+ export { getContext };
37
16
 
38
17
  /**
39
18
  * Set the default audio context
@@ -46,15 +25,15 @@ export function setContext(
46
25
  disposeOld = false
47
26
  ): void {
48
27
  if (disposeOld) {
49
- globalContext.dispose();
28
+ getContext().dispose();
50
29
  }
51
30
 
52
31
  if (isAudioContext(context)) {
53
- globalContext = new Context(context);
32
+ _setContext(new Context(context));
54
33
  } else if (isOfflineAudioContext(context)) {
55
- globalContext = new OfflineContext(context);
34
+ _setContext(new OfflineContext(context));
56
35
  } else {
57
- globalContext = context;
36
+ _setContext(context);
58
37
  }
59
38
  }
60
39
 
@@ -72,7 +51,7 @@ export function setContext(
72
51
  * @category Core
73
52
  */
74
53
  export function start(): Promise<void> {
75
- return globalContext.resume();
54
+ return getContext().resume();
76
55
  }
77
56
 
78
57
  /**
@@ -444,7 +444,7 @@ export class TickSource<
444
444
  Math.round(this.getTicksAtTime(nextTickTime))
445
445
  );
446
446
  } catch (e) {
447
- error = e;
447
+ error = e as Error;
448
448
  break;
449
449
  }
450
450
  nextTickTime += this.frequency.getDurationOfTicks(
@@ -236,7 +236,7 @@ export class TransportInstance
236
236
  * called on every tick
237
237
  * @param tickTime clock relative tick time
238
238
  */
239
- private _processTick(tickTime: Seconds, ticks: Ticks): void {
239
+ private _processTick(tickTime: Seconds, ticks: Ticks = 0): void {
240
240
  // do the loop test
241
241
  if (this._loop.get(tickTime)) {
242
242
  if (ticks >= this._loopEnd) {
@@ -0,0 +1,34 @@
1
+ import { hasAudioContext } from "./AudioContext.js";
2
+ import { BaseContext } from "./BaseContext.js";
3
+ import { Context } from "./Context.js";
4
+ import { DummyContext } from "./DummyContext.js";
5
+
6
+ /**
7
+ * This dummy context is used to avoid throwing immediate errors when importing in Node.js
8
+ */
9
+ export const dummyContext: BaseContext = new DummyContext();
10
+
11
+ /**
12
+ * The global audio context which is getable and assignable through
13
+ * getContext and setContext
14
+ */
15
+ let globalContext: BaseContext = dummyContext;
16
+
17
+ /**
18
+ * Returns the default system-wide {@link Context}.
19
+ * Auto-initializes a real Context in browser environments.
20
+ */
21
+ export function getContext(): BaseContext {
22
+ if (globalContext === dummyContext && hasAudioContext) {
23
+ globalContext = new Context();
24
+ }
25
+ return globalContext;
26
+ }
27
+
28
+ /**
29
+ * Set the global context directly. Unlike the richer `setContext` in Global.ts,
30
+ * this only accepts a {@link BaseContext} — no native AudioContext wrapping.
31
+ */
32
+ export function setContext(context: BaseContext): void {
33
+ globalContext = context;
34
+ }
@@ -1,8 +1,8 @@
1
1
  import { createOfflineAudioContext } from "../context/AudioContext.js";
2
2
  import { Context } from "../context/Context.js";
3
- import { getContext, setContext } from "../Global.js";
4
3
  import { Seconds } from "../type/Units.js";
5
4
  import { isOfflineAudioContext } from "../util/AdvancedTypeCheck.js";
5
+ import { getContext, setContext } from "./GlobalContext.js";
6
6
  import { ToneAudioBuffer } from "./ToneAudioBuffer.js";
7
7
 
8
8
  /**
@@ -1,10 +1,10 @@
1
- import { getContext } from "../Global.js";
2
1
  import { Tone } from "../Tone.js";
3
2
  import { Samples, Seconds } from "../type/Units.js";
4
3
  import { assert } from "../util/Debug.js";
5
4
  import { optionsFromArguments } from "../util/Defaults.js";
6
5
  import { noOp } from "../util/Interface.js";
7
6
  import { isArray, isNumber, isString } from "../util/TypeCheck.js";
7
+ import { getContext } from "./GlobalContext.js";
8
8
 
9
9
  interface ToneAudioBufferOptions {
10
10
  url?: string | AudioBuffer | ToneAudioBuffer;
@@ -128,9 +128,17 @@ describe("FrequencyClass", () => {
128
128
  });
129
129
 
130
130
  it("evaluates transport time", () => {
131
- expect(Frequency("1:0").valueOf()).to.equal(0.5);
132
- expect(Frequency("1:4:0").valueOf()).to.equal(0.25);
133
- // expect(Frequency("2:1:0").valueOf()).to.equal(0.25);
131
+ return Offline(({ transport }) => {
132
+ transport.bpm.value = 120;
133
+ transport.timeSignature = 4;
134
+ expect(Frequency("1:0").valueOf()).to.equal(0.5);
135
+ expect(Frequency("2:0:0").valueOf()).to.equal(0.25);
136
+ expect(Frequency("1:1").valueOf()).to.be.closeTo(0.4, 0.0001);
137
+ expect(Frequency("1:0:2").valueOf()).to.be.closeTo(
138
+ 120 / (60 * 4.5),
139
+ 0.0001
140
+ );
141
+ });
134
142
  });
135
143
 
136
144
  it("evaluates midi", () => {
@@ -2,7 +2,12 @@ import { getContext } from "../Global.js";
2
2
  import { intervalToFrequencyRatio, mtof } from "./Conversions.js";
3
3
  import { ftom, getA4, setA4 } from "./Conversions.js";
4
4
  import { TimeClass } from "./Time.js";
5
- import { TimeBaseUnit, TimeExpression, TimeValue } from "./TimeBase.js";
5
+ import {
6
+ TimeBaseClass,
7
+ TimeBaseUnit,
8
+ TimeExpression,
9
+ TimeValue,
10
+ } from "./TimeBase.js";
6
11
  import {
7
12
  Frequency,
8
13
  Hertz,
@@ -51,17 +56,22 @@ export class FrequencyClass<Type extends number = Hertz> extends TimeClass<
51
56
  return Object.assign({}, super._getExpressions(), {
52
57
  midi: {
53
58
  regexp: /^(\d+(?:\.\d+)?midi)/,
54
- method(value): number {
59
+ method(this: TimeBaseClass<any, any>, value: string): number {
60
+ const numericValue = parseFloat(value);
55
61
  if (this.defaultUnits === "midi") {
56
- return value;
62
+ return numericValue;
57
63
  } else {
58
- return FrequencyClass.mtof(value);
64
+ return FrequencyClass.mtof(numericValue as MidiNote);
59
65
  }
60
66
  },
61
67
  },
62
68
  note: {
63
69
  regexp: /^([a-g]{1}(?:b|#|##|x|bb|###|#x|x#|bbb)?)(-?[0-9]+)/i,
64
- method(pitch, octave): number {
70
+ method(
71
+ this: TimeBaseClass<any, any>,
72
+ pitch: string,
73
+ octave: string
74
+ ): number {
65
75
  const index = noteToScaleIndex[pitch.toLowerCase()];
66
76
  const noteNumber = index + (parseInt(octave, 10) + 1) * 12;
67
77
  if (this.defaultUnits === "midi") {
@@ -73,20 +83,24 @@ export class FrequencyClass<Type extends number = Hertz> extends TimeClass<
73
83
  },
74
84
  tr: {
75
85
  regexp: /^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?):?(\d+(?:\.\d+)?)?/,
76
- method(m, q, s): number {
77
- let total = 1;
86
+ method(
87
+ this: TimeBaseClass<any, any>,
88
+ m: string,
89
+ q: string,
90
+ s: string
91
+ ): number {
92
+ const self = this as FrequencyClass<any>;
93
+ let totalBeats = 0;
78
94
  if (m && m !== "0") {
79
- total *= this._beatsToUnits(
80
- this._getTimeSignature() * parseFloat(m)
81
- );
95
+ totalBeats += self._getTimeSignature() * parseFloat(m);
82
96
  }
83
97
  if (q && q !== "0") {
84
- total *= this._beatsToUnits(parseFloat(q));
98
+ totalBeats += parseFloat(q);
85
99
  }
86
100
  if (s && s !== "0") {
87
- total *= this._beatsToUnits(parseFloat(s) / 4);
101
+ totalBeats += parseFloat(s) / 4;
88
102
  }
89
- return total;
103
+ return self._beatsToUnits(totalBeats);
90
104
  },
91
105
  },
92
106
  });
@@ -68,6 +68,7 @@ describe("MidiClass", () => {
68
68
 
69
69
  it("can convert from Midi", () => {
70
70
  expect(Midi(Midi(2)).valueOf()).to.equal(2);
71
+ expect(Midi(60, "midi").valueOf()).to.equal(60);
71
72
  expect(Midi(Midi("64n")).valueOf()).to.equal(24);
72
73
  expect(Midi(Midi(64, "n")).valueOf()).to.equal(24);
73
74
  });
@@ -30,13 +30,21 @@ export type TimeBaseUnit =
30
30
 
31
31
  export interface TypeFunction {
32
32
  regexp: RegExp;
33
- method: (value: string, ...args: string[]) => number;
33
+ method: (
34
+ this: TimeBaseClass<any, any>,
35
+ value: string,
36
+ ...args: string[]
37
+ ) => number;
34
38
  }
35
39
 
36
40
  export interface TimeExpression<Type extends number> {
37
41
  [key: string]: {
38
42
  regexp: RegExp;
39
- method: (value: string, ...args: string[]) => Type;
43
+ method: (
44
+ this: TimeBaseClass<any, any>,
45
+ value: string,
46
+ ...args: string[]
47
+ ) => Type;
40
48
  };
41
49
  }
42
50
 
@@ -110,7 +118,7 @@ export abstract class TimeBaseClass<
110
118
  regexp: /^(\d+)m$/i,
111
119
  },
112
120
  n: {
113
- method: (value, dot) => {
121
+ method: (value: string, dot: string) => {
114
122
  const numericValue = parseInt(value, 10);
115
123
  const scalar = dot === "." ? 1.5 : 1;
116
124
  if (numericValue === 1) {
@@ -155,7 +163,7 @@ export abstract class TimeBaseClass<
155
163
  regexp: /^(\d+)t$/i,
156
164
  },
157
165
  tr: {
158
- method: (m, q, s) => {
166
+ method: (m: string, q: string, s: string) => {
159
167
  let total = 0;
160
168
  if (m && m !== "0") {
161
169
  total += this._beatsToUnits(
@@ -213,9 +221,12 @@ export abstract class TimeBaseClass<
213
221
  const expr = this._expressions[this._units];
214
222
  const matching = this._val.toString().trim().match(expr.regexp);
215
223
  if (matching) {
216
- return expr.method.apply(this, matching.slice(1));
224
+ return expr.method.apply(
225
+ this,
226
+ matching.slice(1) as [string, ...string[]]
227
+ );
217
228
  } else {
218
- return expr.method.call(this, this._val);
229
+ return expr.method.call(this, String(this._val));
219
230
  }
220
231
  } else if (isString(this._val)) {
221
232
  return parseFloat(this._val) as Type;
@@ -6,8 +6,8 @@ import { noOp } from "../util/Interface.js";
6
6
  import { getWorkletGlobalScope } from "./WorkletGlobalScope.js";
7
7
 
8
8
  export interface ToneAudioWorkletOptions extends ToneAudioNodeOptions {
9
- workletOptions?: Partial<AudioWorkletNodeOptions>
10
- };
9
+ workletOptions?: Partial<AudioWorkletNodeOptions>;
10
+ }
11
11
  export abstract class ToneAudioWorklet<
12
12
  Options extends ToneAudioWorkletOptions,
13
13
  > extends ToneAudioNode<Options> {
@@ -65,7 +65,8 @@ export abstract class ToneAudioWorklet<
65
65
  );
66
66
 
67
67
  if (options.workletOptions) {
68
- this.workletOptions = Object.assign({},
68
+ this.workletOptions = Object.assign(
69
+ {},
69
70
  this.workletOptions,
70
71
  options.workletOptions
71
72
  );
@@ -84,8 +85,8 @@ export abstract class ToneAudioWorklet<
84
85
  name,
85
86
  this.workletOptions
86
87
  );
87
- this._worklet.onprocessorerror =
88
- this.onprocessorerror.bind(this);
88
+ this._worklet.onprocessorerror = (e) =>
89
+ this.onprocessorerror((e as ErrorEvent).message);
89
90
  this.onReady(this._worklet);
90
91
  }
91
92
  });
@@ -43,7 +43,7 @@ export class SyncedSignal<
43
43
  /**
44
44
  * Remember the callback value
45
45
  */
46
- private _syncedCallback: () => void;
46
+ private _syncedCallback: (time: Seconds) => void;
47
47
 
48
48
  /**
49
49
  * @param value Initial value of the signal
@@ -217,7 +217,7 @@ export abstract class OneShotSource<
217
217
  /**
218
218
  * Get the playback state at the given time
219
219
  */
220
- getStateAtTime = function (time: Time): BasicPlaybackState {
220
+ getStateAtTime = (time: Time): BasicPlaybackState => {
221
221
  const computedTime = this.toSeconds(time);
222
222
  if (
223
223
  this._startTime !== -1 &&
@@ -8,6 +8,7 @@ import { noOp } from "../../core/util/Interface.js";
8
8
  import { Timeline } from "../../core/util/Timeline.js";
9
9
  import { isUndef } from "../../core/util/TypeCheck.js";
10
10
  import { ToneConstantSource } from "../../signal/ToneConstantSource.js";
11
+ import { OneShotSource } from "../OneShotSource.js";
11
12
  import { Source, SourceOptions } from "../Source.js";
12
13
  import { ToneBufferSource } from "./ToneBufferSource.js";
13
14
 
@@ -231,12 +232,12 @@ export class Player extends Source<PlayerOptions> {
231
232
  /**
232
233
  * Internal callback when the buffer is done playing.
233
234
  */
234
- private _onSourceEnd(source: ToneBufferSource): void {
235
+ private _onSourceEnd(source: OneShotSource<any>): void {
235
236
  // invoke the onstop function
236
237
  this.onstop(this);
237
238
 
238
239
  // delete the source from the active sources
239
- this._activeSources.delete(source);
240
+ this._activeSources.delete(source as ToneBufferSource);
240
241
  if (
241
242
  this._activeSources.size === 0 &&
242
243
  !this._synced &&
package/Tone/version.ts CHANGED
@@ -1 +1 @@
1
- export const version: string = "15.5.20";
1
+ export const version: string = "15.5.22";