mirror of
https://github.com/Tonejs/Tone.js
synced 2024-11-16 00:27:58 +00:00
adding additional option to StateTimeline.add
enables more strict typing of returned object
This commit is contained in:
parent
f6f2e78574
commit
9306e5188c
3 changed files with 23 additions and 29 deletions
|
@ -1,24 +1,18 @@
|
|||
// import "../type/Type";
|
||||
import { Timeline, TimelineEvent } from "./Timeline";
|
||||
|
||||
export type PlaybackState = "started" | "stopped" | "paused";
|
||||
export type BasicPlaybackState = "started" | "stopped";
|
||||
export type PlaybackState = BasicPlaybackState | "paused";
|
||||
|
||||
export interface StateTimelineEvent extends TimelineEvent {
|
||||
state: PlaybackState;
|
||||
duration?: Seconds;
|
||||
offset?: Seconds;
|
||||
/**
|
||||
* Either the buffer is explicitly scheduled to end using the stop method,
|
||||
* or it's implicitly ended when the buffer is over.
|
||||
*/
|
||||
implicitEnd?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* A Timeline State. Provides the methods: `setStateAtTime("state", time)` and `getValueAtTime(time)`
|
||||
* @param initial The initial state of the StateTimeline. Defaults to `undefined`
|
||||
*/
|
||||
export class StateTimeline extends Timeline<StateTimelineEvent> {
|
||||
export class StateTimeline<AdditionalOptions extends {} = {}> extends Timeline<StateTimelineEvent & AdditionalOptions> {
|
||||
|
||||
/**
|
||||
* The initial state
|
||||
|
@ -47,16 +41,17 @@ export class StateTimeline extends Timeline<StateTimelineEvent> {
|
|||
|
||||
/**
|
||||
* Add a state to the timeline.
|
||||
* @param state The name of the state to set.
|
||||
* @param time The time to query.
|
||||
* @param state The name of the state to set.
|
||||
* @param time The time to query.
|
||||
* @param options Any additional options that are needed in the timeline.
|
||||
*/
|
||||
setStateAtTime(state: PlaybackState, time: Seconds): this {
|
||||
setStateAtTime(state: PlaybackState, time: Seconds, options?: AdditionalOptions): this {
|
||||
// all state changes need to be >= the previous state time
|
||||
// TODO throw error if time < the previous event time
|
||||
this.add({
|
||||
this.add(Object.assign({}, options, {
|
||||
state,
|
||||
time,
|
||||
});
|
||||
}));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -66,7 +61,7 @@ export class StateTimeline extends Timeline<StateTimelineEvent> {
|
|||
* @param time When to check before
|
||||
* @return The event with the given state before the time
|
||||
*/
|
||||
getLastState(state: PlaybackState, time: number): StateTimelineEvent | undefined {
|
||||
getLastState(state: PlaybackState, time: number): StateTimelineEvent & AdditionalOptions | undefined {
|
||||
// time = this.toSeconds(time);
|
||||
const index = this._search(time);
|
||||
for (let i = index; i >= 0; i--) {
|
||||
|
@ -83,7 +78,7 @@ export class StateTimeline extends Timeline<StateTimelineEvent> {
|
|||
* @param time When to check from
|
||||
* @return The event with the given state after the time
|
||||
*/
|
||||
getNextState(state: PlaybackState, time: number): StateTimelineEvent | undefined {
|
||||
getNextState(state: PlaybackState, time: number): StateTimelineEvent & AdditionalOptions | undefined {
|
||||
// time = this.toSeconds(time);
|
||||
const index = this._search(time);
|
||||
if (index !== -1) {
|
||||
|
|
|
@ -3,7 +3,7 @@ import { ToneWithContext, ToneWithContextOptions } from "../core/context/ToneWit
|
|||
import { TicksClass } from "../core/type/Ticks";
|
||||
import { defaultArg, optionsFromArguments } from "../core/util/Defaults";
|
||||
import { noOp } from "../core/util/Interface";
|
||||
import { PlaybackState, StateTimeline } from "../core/util/StateTimeline";
|
||||
import { BasicPlaybackState, StateTimeline } from "../core/util/StateTimeline";
|
||||
import { isBoolean, isDefined, isNumber } from "../core/util/TypeCheck";
|
||||
|
||||
type ToneEventCallback = (time: Seconds, value: any) => void;
|
||||
|
@ -71,7 +71,7 @@ export class ToneEvent extends ToneWithContext<ToneEventOptions> {
|
|||
/**
|
||||
* Tracks the scheduled events
|
||||
*/
|
||||
private _state: StateTimeline = new StateTimeline("stopped");
|
||||
private _state: StateTimeline<{id: number}> = new StateTimeline("stopped");
|
||||
|
||||
/**
|
||||
* The playback speed of the note. A speed of 1
|
||||
|
@ -143,7 +143,7 @@ export class ToneEvent extends ToneWithContext<ToneEventOptions> {
|
|||
this._state.forEachFrom(after, event => {
|
||||
let duration;
|
||||
if (event.state === "started") {
|
||||
if (isDefined(event.id)) {
|
||||
if (event.id !== -1) {
|
||||
this.context.transport.clear(event.id);
|
||||
}
|
||||
const startTick = event.time + Math.round(this.startOffset / this._playbackRate);
|
||||
|
@ -158,7 +158,7 @@ export class ToneEvent extends ToneWithContext<ToneEventOptions> {
|
|||
}
|
||||
if (duration !== Infinity) {
|
||||
// schedule a stop since it's finite duration
|
||||
this._state.setStateAtTime("stopped", startTick + duration + 1);
|
||||
this._state.setStateAtTime("stopped", startTick + duration + 1, { id : -1 });
|
||||
duration = new TicksClass(this.context, duration);
|
||||
}
|
||||
const interval = new TicksClass(this.context, this._getLoopDuration());
|
||||
|
@ -174,8 +174,8 @@ export class ToneEvent extends ToneWithContext<ToneEventOptions> {
|
|||
/**
|
||||
* Returns the playback state of the note, either "started" or "stopped".
|
||||
*/
|
||||
get state(): PlaybackState {
|
||||
return this._state.getValueAtTime(this.context.transport.ticks);
|
||||
get state(): BasicPlaybackState {
|
||||
return this._state.getValueAtTime(this.context.transport.ticks) as BasicPlaybackState;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -221,7 +221,7 @@ export class ToneEvent extends ToneWithContext<ToneEventOptions> {
|
|||
time = this.toTicks(time);
|
||||
if (this._state.getValueAtTime(time) === "stopped") {
|
||||
this._state.add({
|
||||
id : undefined,
|
||||
id : -1,
|
||||
state : "started",
|
||||
time,
|
||||
});
|
||||
|
@ -238,7 +238,7 @@ export class ToneEvent extends ToneWithContext<ToneEventOptions> {
|
|||
this.cancel(time);
|
||||
time = this.toTicks(time);
|
||||
if (this._state.getValueAtTime(time) === "started") {
|
||||
this._state.setStateAtTime("stopped", time);
|
||||
this._state.setStateAtTime("stopped", time, { id: -1 });
|
||||
const previousEvent = this._state.getBefore(time);
|
||||
let reschedulTime = time;
|
||||
if (previousEvent !== null) {
|
||||
|
@ -257,7 +257,7 @@ export class ToneEvent extends ToneWithContext<ToneEventOptions> {
|
|||
time = defaultArg(time, -Infinity);
|
||||
time = this.toTicks(time);
|
||||
this._state.forEachFrom(time, event => {
|
||||
this.context.transport.clear(event.id as number);
|
||||
this.context.transport.clear(event.id);
|
||||
});
|
||||
this._state.cancel(time);
|
||||
return this;
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { StateTimelineEvent } from "Tone/core/util/StateTimeline";
|
||||
import { ToneAudioBuffer } from "../../core/context/ToneAudioBuffer";
|
||||
import { defaultArg, optionsFromArguments } from "../../core/util/Defaults";
|
||||
import { noOp } from "../../core/util/Interface";
|
||||
|
@ -220,9 +219,9 @@ export class Player extends Source<PlayerOptions> {
|
|||
// set the looping properties
|
||||
if (!this._loop && !this._synced) {
|
||||
// if it's not looping, set the state change at the end of the sample
|
||||
this._state.setStateAtTime("stopped", startTime + computedDuration);
|
||||
// mark that ending as an implicit ending
|
||||
(this._state.get(startTime + computedDuration) as StateTimelineEvent).implicitEnd = true;
|
||||
this._state.setStateAtTime("stopped", startTime + computedDuration, {
|
||||
implicitEnd: true,
|
||||
});
|
||||
}
|
||||
|
||||
// add it to the array of active sources
|
||||
|
|
Loading…
Reference in a new issue