tone 15.5.60 → 15.5.62

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.
@@ -103,6 +103,29 @@ describe("ToneAudioBuffer", () => {
103
103
  });
104
104
  });
105
105
 
106
+ it("preserves the onload of an unloaded buffer it wraps", async () => {
107
+ let originalCalled = false;
108
+ const inner = new ToneAudioBuffer({
109
+ onload(): void {
110
+ originalCalled = true;
111
+ },
112
+ url: testFile,
113
+ });
114
+ let outerCalled = false;
115
+ const outer = new ToneAudioBuffer({
116
+ onload(): void {
117
+ outerCalled = true;
118
+ },
119
+ url: inner,
120
+ });
121
+ await ToneAudioBuffer.loaded();
122
+ expect(originalCalled).to.equal(true);
123
+ expect(outerCalled).to.equal(true);
124
+ expect(outer.get()).to.equal(inner.get());
125
+ inner.dispose();
126
+ outer.dispose();
127
+ });
128
+
106
129
  it("takes Tone.ToneAudioBuffer in the set method", (done) => {
107
130
  const buffer = new ToneAudioBuffer({
108
131
  url: testFile,
@@ -99,8 +99,11 @@ export class ToneAudioBuffer extends Tone {
99
99
  if (buffer.loaded) {
100
100
  this._buffer = buffer.get();
101
101
  } else {
102
- // otherwise when its loaded, invoke it's callback
102
+ // Chain so a wrapper does not replace the buffer's own onload.
103
+ // An early note constructs that wrapper before the fetch finishes.
104
+ const previousOnload = buffer.onload;
103
105
  buffer.onload = () => {
106
+ previousOnload.call(buffer, buffer);
104
107
  this.set(buffer);
105
108
  this.onload(this);
106
109
  };
@@ -160,6 +160,25 @@ describe("Sampler", () => {
160
160
  );
161
161
  });
162
162
 
163
+ it("invokes onload when triggerAttack runs before the buffer loads", async () => {
164
+ let loaded = false;
165
+ const sampler = new Sampler({
166
+ onload(): void {
167
+ loaded = true;
168
+ },
169
+ urls: {
170
+ A4: "./test/audio/sine.wav",
171
+ },
172
+ });
173
+ expect(() => {
174
+ sampler.triggerAttack("A4");
175
+ }).throws(Error, /not loaded/);
176
+ await ToneAudioBuffer.loaded();
177
+ expect(loaded).to.be.true;
178
+ expect(sampler.loaded).to.be.true;
179
+ sampler.dispose();
180
+ });
181
+
163
182
  it("can pass in a callback and baseUrl", (done) => {
164
183
  const sampler = new Sampler(
165
184
  {
@@ -9,6 +9,7 @@ import { Offline } from "../../../test/helper/Offline.js";
9
9
  import { OscillatorTests } from "../../../test/helper/OscillatorTests.js";
10
10
  import { OutputAudio } from "../../../test/helper/OutputAudio.js";
11
11
  import { SourceTests } from "../../../test/helper/SourceTests.js";
12
+ import { OfflineContext } from "../../core/context/OfflineContext.js";
12
13
  import { Signal } from "../../signal/Signal.js";
13
14
  import { Oscillator } from "./Oscillator.js";
14
15
  import { ToneOscillatorType } from "./OscillatorInterface.js";
@@ -111,14 +112,103 @@ describe("Oscillator", () => {
111
112
  }
112
113
  });
113
114
  });
115
+ });
116
+
117
+ context("Periodic Wave Cache", () => {
118
+ beforeEach(() => {
119
+ // @ts-ignore
120
+ Oscillator._periodicWaveCache = [];
121
+ });
114
122
 
115
123
  it("can go past the cache max size of 100", () => {
116
124
  const osc = new Oscillator();
117
125
  for (let i = 0; i < 110; i++) {
118
126
  osc.phase = i;
119
127
  }
128
+ // @ts-ignore
129
+ expect(Oscillator._periodicWaveCache.length).to.equal(100);
120
130
  osc.dispose();
121
131
  });
132
+
133
+ it("caches periodic waves by sample rate", () => {
134
+ const createWave = sinon.spy(
135
+ OfflineContext.prototype,
136
+ "createPeriodicWave"
137
+ );
138
+ const context44k = new OfflineContext(1, 0.01, 44100);
139
+ const context48k = new OfflineContext(1, 0.01, 48000);
140
+
141
+ const osc1 = new Oscillator({
142
+ context: context44k,
143
+ phase: 90,
144
+ });
145
+ const osc2 = new Oscillator({
146
+ context: context44k,
147
+ phase: 90,
148
+ });
149
+ expect(createWave).to.have.been.calledOnce;
150
+
151
+ const osc3 = new Oscillator({
152
+ context: context48k,
153
+ phase: 90,
154
+ });
155
+ expect(createWave).to.have.been.calledTwice;
156
+
157
+ const osc4 = new Oscillator({
158
+ context: context48k,
159
+ phase: 90,
160
+ });
161
+ expect(createWave).to.have.been.calledTwice;
162
+
163
+ osc1.dispose();
164
+ osc2.dispose();
165
+ osc3.dispose();
166
+ osc4.dispose();
167
+ context44k.dispose();
168
+ context48k.dispose();
169
+ });
170
+
171
+ it("caches custom waveforms by sample rate", () => {
172
+ const createWave = sinon.spy(
173
+ OfflineContext.prototype,
174
+ "createPeriodicWave"
175
+ );
176
+ const context44k = new OfflineContext(1, 0.01, 44100);
177
+ const context48k = new OfflineContext(1, 0.01, 48000);
178
+
179
+ const osc1 = new Oscillator({
180
+ context: context44k,
181
+ partials: [1, 2, 3],
182
+ type: "custom",
183
+ });
184
+ const osc2 = new Oscillator({
185
+ context: context44k,
186
+ partials: [1, 2, 3],
187
+ type: "custom",
188
+ });
189
+ expect(createWave).to.have.been.calledOnce;
190
+
191
+ const osc3 = new Oscillator({
192
+ context: context48k,
193
+ partials: [1, 2, 3],
194
+ type: "custom",
195
+ });
196
+ expect(createWave).to.have.been.calledTwice;
197
+
198
+ const osc4 = new Oscillator({
199
+ context: context48k,
200
+ partials: [1, 2, 3],
201
+ type: "custom",
202
+ });
203
+ expect(createWave).to.have.been.calledTwice;
204
+
205
+ osc1.dispose();
206
+ osc2.dispose();
207
+ osc3.dispose();
208
+ osc4.dispose();
209
+ context44k.dispose();
210
+ context48k.dispose();
211
+ });
122
212
  });
123
213
 
124
214
  context("Type", () => {
@@ -230,6 +230,7 @@ export class Oscillator
230
230
  phase: number;
231
231
  type: string;
232
232
  partialCount: number;
233
+ sampleRate: number;
233
234
  real: Float32Array;
234
235
  imag: Float32Array;
235
236
  wave: PeriodicWave;
@@ -252,6 +253,7 @@ export class Oscillator
252
253
  const oscProps = Oscillator._periodicWaveCache.find(
253
254
  (description) => {
254
255
  return (
256
+ description.sampleRate === this.context.sampleRate &&
255
257
  description.phase === this._phase &&
256
258
  deepEquals(description.partials, this._partials)
257
259
  );
@@ -262,6 +264,7 @@ export class Oscillator
262
264
  const oscProps = Oscillator._periodicWaveCache.find(
263
265
  (description) => {
264
266
  return (
267
+ description.sampleRate === this.context.sampleRate &&
265
268
  description.type === this._type &&
266
269
  description.phase === this._phase
267
270
  );
@@ -315,6 +318,7 @@ export class Oscillator
315
318
  partialCount: this._partialCount,
316
319
  partials: this._partials,
317
320
  phase: this._phase,
321
+ sampleRate: this.context.sampleRate,
318
322
  real,
319
323
  type: this._type,
320
324
  wave: this._wave,
package/Tone/version.ts CHANGED
@@ -1 +1 @@
1
- export const version: string = "15.5.60";
1
+ export const version: string = "15.5.62";