UNPKG

tone

Version:

A Web Audio framework for making interactive music in the browser.

332 lines (331 loc) 12 kB
import { TimeClass } from "../../core/type/Time.js"; import { PlaybackState } from "../../core/util/StateTimeline.js"; import { Signal } from "../../signal/Signal.js"; import { ToneWithContext, ToneWithContextOptions } from "../context/ToneWithContext.js"; import { TransportTimeClass } from "../type/TransportTime.js"; import { BarsBeatsSixteenths, BPM, NormalRange, Seconds, Subdivision, Ticks, Time, TimeSignature, TransportTime } from "../type/Units.js"; import { Emitter } from "../util/Emitter.js"; import { TickParam } from "./TickParam.js"; interface TransportOptions extends ToneWithContextOptions { bpm: BPM; swing: NormalRange; swingSubdivision: Subdivision; timeSignature: number; loopStart: Time; loopEnd: Time; ppq: number; } type TransportEventNames = "start" | "stop" | "pause" | "loop" | "loopEnd" | "loopStart" | "ticks"; type TransportCallback = (time: Seconds) => void; /** * Transport for timing musical events. * Supports tempo curves and time changes. Unlike browser-based timing (setInterval, requestAnimationFrame) * Transport timing events pass in the exact time of the scheduled event * in the argument of the callback function. Pass that time value to the object * you're scheduling. <br><br> * A single transport is created for you when the library is initialized. * <br><br> * The transport emits the events: "start", "stop", "pause", and "loop" which are * called with the time of that event as the argument. * * @example * const osc = new Tone.Oscillator().toDestination(); * // repeated event every 8th note * Tone.getTransport().scheduleRepeat((time) => { * // use the callback time to schedule events * osc.start(time).stop(time + 0.1); * }, "8n"); * // transport must be started before it starts invoking events * Tone.getTransport().start(); * @category Core */ export declare class TransportClass extends ToneWithContext<TransportOptions> implements Emitter<TransportEventNames> { readonly name: string; /** * If the transport loops or not. */ private _loop; /** * The loop start position in ticks */ private _loopStart; /** * The loop end position in ticks */ private _loopEnd; /** * Pulses per quarter is the number of ticks per quarter note. */ private _ppq; /** * watches the main oscillator for timing ticks * initially starts at 120bpm */ private _clock; /** * The Beats Per Minute of the Transport. * @example * const osc = new Tone.Oscillator().toDestination(); * Tone.getTransport().bpm.value = 80; * // start/stop the oscillator every quarter note * Tone.getTransport().scheduleRepeat(time => { * osc.start(time).stop(time + 0.1); * }, "4n"); * Tone.getTransport().start(); * // ramp the bpm to 120 over 10 seconds * Tone.getTransport().bpm.rampTo(120, 10); */ bpm: TickParam<"bpm">; /** * The time signature, or more accurately the numerator * of the time signature over a denominator of 4. */ private _timeSignature; /** * All the events in an object to keep track by ID */ private _scheduledEvents; /** * The scheduled events. */ private _timeline; /** * Repeated events */ private _repeatedEvents; /** * All of the synced Signals */ private _syncedSignals; /** * The subdivision of the swing */ private _swingTicks; /** * The swing amount */ private _swingAmount; constructor(options?: Partial<TransportOptions>); static getDefaults(): TransportOptions; /** * called on every tick * @param tickTime clock relative tick time */ private _processTick; /** * Schedule an event along the timeline. * @param callback The callback to be invoked at the time. * @param time The time to invoke the callback at. * @return The id of the event which can be used for canceling the event. * @example * // schedule an event on the 16th measure * Tone.getTransport().schedule((time) => { * // invoked on measure 16 * console.log("measure 16!"); * }, "16:0:0"); */ schedule(callback: TransportCallback, time: TransportTime | TransportTimeClass): number; /** * Schedule a repeated event along the timeline. The event will fire * at the `interval` starting at the `startTime` and for the specified * `duration`. * @param callback The callback to invoke. * @param interval The duration between successive callbacks. Must be a positive number. * @param startTime When along the timeline the events should start being invoked. * @param duration How long the event should repeat. * @return The ID of the scheduled event. Use this to cancel the event. * @example * const osc = new Tone.Oscillator().toDestination().start(); * // a callback invoked every eighth note after the first measure * Tone.getTransport().scheduleRepeat((time) => { * osc.start(time).stop(time + 0.1); * }, "8n", "1m"); */ scheduleRepeat(callback: TransportCallback, interval: Time | TimeClass, startTime?: TransportTime | TransportTimeClass, duration?: Time): number; /** * Schedule an event that will be removed after it is invoked. * @param callback The callback to invoke once. * @param time The time the callback should be invoked. * @returns The ID of the scheduled event. */ scheduleOnce(callback: TransportCallback, time: TransportTime | TransportTimeClass): number; /** * Clear the passed in event id from the timeline * @param eventId The id of the event. */ clear(eventId: number): this; /** * Add an event to the correct timeline. Keep track of the * timeline it was added to. * @returns the event id which was just added */ private _addEvent; /** * Remove scheduled events from the timeline after * the given time. Repeated events will be removed * if their startTime is after the given time * @param after Clear all events after this time. */ cancel(after?: TransportTime): this; /** * Bind start/stop/pause events from the clock and emit them. */ private _bindClockEvents; /** * Returns the playback state of the source, either "started", "stopped", or "paused" */ get state(): PlaybackState; /** * Start the transport and all sources synced to the transport. * @param time The time when the transport should start. * @param offset The timeline offset to start the transport. * @example * // start the transport in one second starting at beginning of the 5th measure. * Tone.getTransport().start("+1", "4:0:0"); */ start(time?: Time, offset?: TransportTime): this; /** * Stop the transport and all sources synced to the transport. * @param time The time when the transport should stop. * @example * Tone.getTransport().stop(); */ stop(time?: Time): this; /** * Pause the transport and all sources synced to the transport. */ pause(time?: Time): this; /** * Toggle the current state of the transport. If it is * started, it will stop it, otherwise it will start the Transport. * @param time The time of the event */ toggle(time?: Time): this; /** * The time signature as just the numerator over 4. * For example 4/4 would be just 4 and 6/8 would be 3. * @example * // common time * Tone.getTransport().timeSignature = 4; * // 7/8 * Tone.getTransport().timeSignature = [7, 8]; * // this will be reduced to a single number * Tone.getTransport().timeSignature; // returns 3.5 */ get timeSignature(): TimeSignature; set timeSignature(timeSig: TimeSignature); /** * When the Transport.loop = true, this is the starting position of the loop. */ get loopStart(): Time; set loopStart(startPosition: Time); /** * When the Transport.loop = true, this is the ending position of the loop. */ get loopEnd(): Time; set loopEnd(endPosition: Time); /** * If the transport loops or not. */ get loop(): boolean; set loop(loop: boolean); /** * Set the loop start and stop at the same time. * @example * // loop over the first measure * Tone.getTransport().setLoopPoints(0, "1m"); * Tone.getTransport().loop = true; */ setLoopPoints(startPosition: TransportTime, endPosition: TransportTime): this; /** * The swing value. Between 0-1 where 1 equal to the note + half the subdivision. */ get swing(): NormalRange; set swing(amount: NormalRange); /** * Set the subdivision which the swing will be applied to. * The default value is an 8th note. Value must be less * than a quarter note. */ get swingSubdivision(): Subdivision; set swingSubdivision(subdivision: Subdivision); /** * The Transport's position in Bars:Beats:Sixteenths. * Setting the value will jump to that position right away. */ get position(): BarsBeatsSixteenths | Time; set position(progress: Time); /** * The Transport's position in seconds. * Setting the value will jump to that position right away. */ get seconds(): Seconds; set seconds(s: Seconds); /** * The Transport's loop position as a normalized value. Always * returns 0 if the Transport.loop = false. */ get progress(): NormalRange; /** * The Transport's current tick position. */ get ticks(): Ticks; set ticks(t: Ticks); /** * Get the clock's ticks at the given time. * @param time When to get the tick value * @return The tick value at the given time. */ getTicksAtTime(time?: Time): Ticks; /** * Return the elapsed seconds at the given time. * @param time When to get the elapsed seconds * @return The number of elapsed seconds */ getSecondsAtTime(time: Time): Seconds; /** * Pulses Per Quarter note. This is the smallest resolution * the Transport timing supports. This should be set once * on initialization and not set again. Changing this value * after other objects have been created can cause problems. */ get PPQ(): number; set PPQ(ppq: number); /** * Returns the time aligned to the next subdivision * of the Transport. If the Transport is not started, * it will return 0. * Note: this will not work precisely during tempo ramps. * @param subdivision The subdivision to quantize to * @return The context time of the next subdivision. * @example * // the transport must be started, otherwise returns 0 * Tone.getTransport().start(); * Tone.getTransport().nextSubdivision("4n"); */ nextSubdivision(subdivision?: Time): Seconds; /** * Attaches the signal to the tempo control signal so that * any changes in the tempo will change the signal in the same * ratio. * * @param signal * @param ratio Optionally pass in the ratio between the two signals. * Otherwise it will be computed based on their current values. */ syncSignal(signal: Signal<any>, ratio?: number): this; /** * Unsyncs a previously synced signal from the transport's control. * @see {@link syncSignal}. */ unsyncSignal(signal: Signal<any>): this; /** * Clean up. */ dispose(): this; on: (event: TransportEventNames, callback: (...args: any[]) => void) => this; once: (event: TransportEventNames, callback: (...args: any[]) => void) => this; off: (event: TransportEventNames, callback?: ((...args: any[]) => void) | undefined) => this; emit: (event: any, ...args: any[]) => this; } export {};