mirror of
https://github.com/Tonejs/Tone.js
synced 2024-12-27 12:03:12 +00:00
feat: latencyHint is now set in constructor
BREAK: the latencyHint can only be set in the constructor, no longer settable after construction addresses #658
This commit is contained in:
parent
368a7f43cb
commit
ba8e82b1ca
6 changed files with 30 additions and 87 deletions
|
@ -9,8 +9,8 @@ import { isDefined } from "../util/TypeCheck";
|
|||
/**
|
||||
* Create a new AudioContext
|
||||
*/
|
||||
export function createAudioContext(): AudioContext {
|
||||
return new stdAudioContext() as unknown as AudioContext;
|
||||
export function createAudioContext(options?: AudioContextOptions): AudioContext {
|
||||
return new stdAudioContext(options) as unknown as AudioContext;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -8,7 +8,7 @@ type Transport = import("../clock/Transport").Transport;
|
|||
type Listener = import("./Listener").Listener;
|
||||
type BaseAudioContextSubset = import("./Context").BaseAudioContextSubset;
|
||||
|
||||
export type ContextLatencyHint = AudioContextLatencyCategory | "fastest";
|
||||
export type ContextLatencyHint = AudioContextLatencyCategory;
|
||||
|
||||
export abstract class BaseContext extends Emitter<"statechange" | "tick"> implements BaseAudioContextSubset {
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ describe("Context", () => {
|
|||
expect(ctx.createDelay()).to.be.have.property("delayTime");
|
||||
expect(ctx).to.have.property("createConstantSource");
|
||||
ctx.dispose();
|
||||
return ctx.close();
|
||||
});
|
||||
|
||||
if (ONLINE_TESTING) {
|
||||
|
@ -61,25 +62,28 @@ describe("Context", () => {
|
|||
expect(ctx.rawContext).has.property("destination");
|
||||
expect(ctx.rawContext).has.property("sampleRate");
|
||||
ctx.dispose();
|
||||
return ctx.close();
|
||||
});
|
||||
|
||||
it("can be constructed with an options object", () => {
|
||||
const ctx = new Context({
|
||||
clockSource: "timeout",
|
||||
latencyHint: "fastest",
|
||||
latencyHint: "playback",
|
||||
lookAhead: 0.2,
|
||||
});
|
||||
expect(ctx.lookAhead).to.equal(0.2);
|
||||
expect(ctx.latencyHint).to.equal("fastest");
|
||||
expect(ctx.latencyHint).to.equal("playback");
|
||||
expect(ctx.clockSource).to.equal("timeout");
|
||||
ctx.dispose();
|
||||
return ctx.close();
|
||||
});
|
||||
|
||||
|
||||
it("returns 'now' and 'immediate' time", () => {
|
||||
const ctx = new Context();
|
||||
expect(ctx.now()).to.be.a("number");
|
||||
expect(ctx.immediate()).to.be.a("number");
|
||||
ctx.dispose();
|
||||
return ctx.close();
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -296,60 +300,6 @@ describe("Context", () => {
|
|||
});
|
||||
});
|
||||
|
||||
// context("Tone", () => {
|
||||
|
||||
// it("has a context", () => {
|
||||
// expect(Tone.context).to.exist;
|
||||
// expect(Tone.context).to.be.instanceOf(Context);
|
||||
// });
|
||||
|
||||
// it("can set a new context", () => {
|
||||
// const originalContext = Tone.context;
|
||||
// Tone.context = new Context();
|
||||
// return Tone.context.dispose().then(() => {
|
||||
// Tone.context = originalContext;
|
||||
// });
|
||||
// });
|
||||
|
||||
// it("has a consistent context after offline rendering", () => {
|
||||
// const initialContext = Tone.context;
|
||||
// const initialTransport = Tone.Transport;
|
||||
// return Offline(() => { }).then(() => {
|
||||
// expect(Tone.context).to.equal(initialContext);
|
||||
// expect(Tone.Transport).to.equal(initialTransport);
|
||||
// });
|
||||
// });
|
||||
|
||||
// it("invokes the resume promise", () => {
|
||||
// return Tone.context.resume();
|
||||
// });
|
||||
|
||||
// it("invokes init when a new context is set", done => {
|
||||
// this.timeout(200);
|
||||
// const initFn = function(context) {
|
||||
// expect(Tone.context).to.equal(context);
|
||||
// Context.off("init", initFn);
|
||||
// done();
|
||||
// };
|
||||
// Context.on("init", initFn);
|
||||
// Tone.context = new Context();
|
||||
// });
|
||||
|
||||
// it("invokes close when a context is disposed", done => {
|
||||
// this.timeout(200);
|
||||
// const closeFn = function(context) {
|
||||
// expect(context).to.be.instanceOf(Context);
|
||||
// Context.off("close", closeFn);
|
||||
// // set a new context
|
||||
// Tone.context = new Context();
|
||||
// done();
|
||||
// };
|
||||
// Context.on("close", closeFn);
|
||||
// Tone.context.dispose();
|
||||
// });
|
||||
|
||||
// });
|
||||
|
||||
context("get/set", () => {
|
||||
|
||||
let ctx;
|
||||
|
@ -373,19 +323,6 @@ describe("Context", () => {
|
|||
expect(ctx.updateInterval).to.equal(0.05);
|
||||
});
|
||||
|
||||
it("can set the latencyHint", () => {
|
||||
ctx.latencyHint = "fastest";
|
||||
expect(ctx.latencyHint).to.equal("fastest");
|
||||
expect(ctx.lookAhead).to.be.closeTo(0.01, 0.05);
|
||||
expect(ctx.updateInterval).to.be.closeTo(0.01, 0.05);
|
||||
// test all other latency hints
|
||||
const latencyHints = ["interactive", "playback", "balanced", 0.2];
|
||||
latencyHints.forEach(hint => {
|
||||
ctx.latencyHint = hint;
|
||||
expect(ctx.latencyHint).to.equal(hint);
|
||||
});
|
||||
});
|
||||
|
||||
it("gets a constant signal", () => {
|
||||
return ConstantOutput(context => {
|
||||
const bufferSrc = context.getConstant(1);
|
||||
|
|
|
@ -65,7 +65,7 @@ export class Context extends BaseContext {
|
|||
/**
|
||||
* The default latency hint
|
||||
*/
|
||||
private _latencyHint: ContextLatencyHint | Seconds;
|
||||
private _latencyHint!: ContextLatencyHint | Seconds;
|
||||
|
||||
/**
|
||||
* An object containing all of the constants AudioBufferSourceNodes
|
||||
|
@ -121,10 +121,10 @@ export class Context extends BaseContext {
|
|||
if (options.context) {
|
||||
this._context = options.context;
|
||||
} else {
|
||||
this._context = createAudioContext();
|
||||
this._context = createAudioContext({
|
||||
latencyHint: options.latencyHint,
|
||||
});
|
||||
}
|
||||
this._latencyHint = options.latencyHint;
|
||||
this.lookAhead = options.lookAhead;
|
||||
|
||||
this._ticker = new Ticker(this.emit.bind(this, "tick"), options.clockSource, options.updateInterval);
|
||||
this.on("tick", this._timeoutLoop.bind(this));
|
||||
|
@ -133,6 +133,9 @@ export class Context extends BaseContext {
|
|||
this._context.onstatechange = () => {
|
||||
this.emit("statechange", this.state);
|
||||
};
|
||||
|
||||
this._setLatencyHint(options.latencyHint);
|
||||
this.lookAhead = options.lookAhead;
|
||||
}
|
||||
|
||||
static getDefaults(): ContextOptions {
|
||||
|
@ -375,13 +378,19 @@ export class Context extends BaseContext {
|
|||
* "playback" (prioritizes sustained playback), "balanced" (balances
|
||||
* latency and performance), and "fastest" (lowest latency, might glitch more often).
|
||||
* @example
|
||||
* // set the latencyHint to prioritize smooth playback at the expensive of latency
|
||||
* Tone.context.latencyHint = "playback";
|
||||
* // prioritize sustained playback
|
||||
* const context = new Tone.Context({ latencyHint: "playback" });
|
||||
* // set this context as the global Context
|
||||
* Tone.setContext(context);
|
||||
*/
|
||||
get latencyHint(): ContextLatencyHint | Seconds {
|
||||
return this._latencyHint;
|
||||
}
|
||||
set latencyHint(hint: ContextLatencyHint | Seconds) {
|
||||
|
||||
/**
|
||||
* Update the lookAhead and updateInterval based on the latencyHint
|
||||
*/
|
||||
private _setLatencyHint(hint: ContextLatencyHint | Seconds): void {
|
||||
let lookAheadValue = 0;
|
||||
this._latencyHint = hint;
|
||||
if (isString(hint)) {
|
||||
|
@ -390,14 +399,11 @@ export class Context extends BaseContext {
|
|||
lookAheadValue = 0.1;
|
||||
break;
|
||||
case "playback":
|
||||
lookAheadValue = 0.8;
|
||||
lookAheadValue = 0.5;
|
||||
break;
|
||||
case "balanced":
|
||||
lookAheadValue = 0.25;
|
||||
break;
|
||||
case "fastest":
|
||||
lookAheadValue = 0.01;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.lookAhead = lookAheadValue;
|
||||
|
@ -405,7 +411,7 @@ export class Context extends BaseContext {
|
|||
}
|
||||
|
||||
/**
|
||||
* The unwrapped AudioContext.
|
||||
* The unwrapped AudioContext or OfflineAudioContext
|
||||
*/
|
||||
get rawContext(): AnyAudioContext {
|
||||
return this._context;
|
||||
|
|
2
package-lock.json
generated
2
package-lock.json
generated
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "tone",
|
||||
"version": "14.6.0",
|
||||
"version": "14.7.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "tone",
|
||||
"version": "14.6.0",
|
||||
"version": "14.7.0",
|
||||
"description": "A Web Audio framework for making interactive music in the browser.",
|
||||
"main": "build/Tone.js",
|
||||
"module": "build/esm/index.js",
|
||||
|
|
Loading…
Reference in a new issue