UNPKG

shimi

Version:

A JS framework for building complex MIDI applications

203 lines (202 loc) 9.78 kB
import TimeSig from './TimeSig'; import PropertyTracker from './PropertyTracker'; import { ClockChildFinishedEvent, IClockChild } from './Clock'; import { IMetronome, MetronomeBase } from './Metronome'; import ShimiEvent, { ShimiEventData } from './ShimiEvent'; /** * The Flexinome, much like the Metronome, is an implementation of the IMetronome interface, and is used for converting millisecond updates in time, into beat updates in time. * * The Flexinome differs from the Metronome though, in that it fully embraces the IMetronome's concept of separating quarter notes from beats, allowing a lot of flexibility in how bars can be divided up, with some beats stretching out to last longer than others. * * This means that if you had a 4 beat clip, it could be played infinitely many ways, just by passing it into a ClipPlayer that's linked to a Flexinome, and altering the time signature that it's using. * * To better understand how this works, please take a look at the [IMetronome](https://jamescoyle1989.github.io/shimi/interfaces/IMetronome.html) and [TimeSig](https://jamescoyle1989.github.io/shimi/classes/TimeSig.html) documentation. * * @category Timing */ export default class Flexinome extends MetronomeBase implements IMetronome, IClockChild { /** Returns the name of this type. This can be used rather than instanceof which is sometimes unreliable. */ get typeName(): string; private _tempo; /** Get the current flexinome tempo. */ get tempo(): number; /** Set the current flexinome tempo. */ set tempo(value: number); private _tempoMultiplier; /** * Get the tempo multiplier. This allows defining the tempo in terms of other duration values than just quarter notes. For example, if `tempo == 120`: * * `tempoMultiplier == 1` means ♩ = 120 * * `tempoMultiplier == 0.5` means ♪ = 120 * * `tempoMultiplier == 1.5` means ♩. = 120 * * The default value is 1. */ get tempoMultiplier(): number; /** * Set the tempo multiplier. This allows defining the tempo in terms of other duration values than just quarter notes. For example, if `tempo == 120`: * * `tempoMultiplier == 1` means ♩ = 120 * * `tempoMultiplier == 0.5` means ♪ = 120 * * `tempoMultiplier == 1.5` means ♩. = 120 * * Valid values are technically all positive numbers, though in reality only numbers that correspond to common musical note durations make sense. */ set tempoMultiplier(value: number); /** Provides a way of identifying flexinomes so they can be easily retrieved later */ get ref(): string; set ref(value: string); private _ref; private _timeSig; /** Get the current flexinome time signature. */ get timeSig(): TimeSig; /** * Set the flexinome time signature. * * **Note:** This doesn't actually change the time signature straight away, but instead stores it so that the time signature changes on the start of the next bar. */ set timeSig(value: TimeSig); private _totalQuarterNote; /** * How many quarter notes have passed in total since the flexinome started. * * This just returns `totalQuarterNoteTracker.value`. */ get totalQuarterNote(): number; /** Records the difference in total quarter notes passed, enabling inspection of the total quarter note change from one update cycle to the next. */ get totalQuarterNoteTracker(): PropertyTracker<number>; private _totalBeat; /** * How many beats have passed in total since the flexinome started. * * This just returns `totalBeatTracker.value`. */ get totalBeat(): number; /** Records the difference in total beats passed, enabling inspection of the total beat change from one update cycle to the next. */ get totalBeatTracker(): PropertyTracker<number>; private _bar; /** * Records what bar the flexinome is currently on. * * This just returns `barTracker.value`. */ get bar(): number; /** Records the bar number in the previous update vs the current one. */ get barTracker(): PropertyTracker<number>; private _barQuarterNote; /** * Records how many quarter notes have passed within the current bar * * This just returns `barQuarterNoteTracker.value`. */ get barQuarterNote(): number; /** Records the difference in bar quarter note values, enabling inspection of the quarter note within the current bar from one update cycle to the next. */ get barQuarterNoteTracker(): PropertyTracker<number>; private _barBeat; /** * Records how many beats have passed within the current bar. * * This just returns `barBeatTracker.value`. */ get barBeat(): number; /** Records the difference in bar beat values, enabling inspection of the beat within the current bar from one update cycle to the next. */ get barBeatTracker(): PropertyTracker<number>; private _enabled; /** Gets whether the flexinome is currently enabled to run. */ get enabled(): boolean; /** Sets whether the flexinome is currently enabled to run. */ set enabled(value: boolean); /** Returns true if the Flexinome has been instructed to stop everything by the `finish()` method. */ get isFinished(): boolean; private _isFinished; /** This event fires when the Flexinome finishes. */ get finished(): ClockChildFinishedEvent; private _finished; /** * @param tempo The tempo to run the flexinome at. * @param timeSig The time signature for the flexinome to use. If not provided then the flexinome defaults to common time (4/4). */ constructor(tempo: number, timeSig?: TimeSig); /** * This takes in a beat and returns true if the flexinome is currently at it, or has only just passed it in the bar within the last update cycle. * @param beat The beat to test if we've recently passed. * @returns */ atBarBeat(beat: number): boolean; /** * This takes a quarter note and returns true if the flexinome is currently at it, or has only just passed it in the bar within the last update cycle. * @param quarterNote The quarter note to test if we've recently passed. * @returns */ atBarQuarterNote(quarterNote: number): boolean; /** * This takes in a beat division and checks if the metronome is currently at some multiple of that division within the current bar, returning what multiple of the division we're currently at. * For example: atBarBeatMultiple(0.5) returns 0 if we're at beat 0, 1 if we're at beat 0.5, 2 if we're at beat 1, etc. If not at a multiple of the division, then -1 is returned. * @param division The beat division to check if the metronome is at a multiple of. */ atBarBeatMultiple(division: number): number; /** * This takes in a quarter note division and checks if the metronome is currently at some multiple of that division within the current bar, returning what multiple of the division we're currently at. * For example: atBarQuarterNoteMultiple(0.5) returns 0 if we're at QN 0, 1 if we're at QN 0.5, 2 if we're at QN 1, etc. If not at a multiple of the division, then -1 is returned. * @param division The beat division to check if the metronome is at a multiple of. */ atBarQuarterNoteMultiple(division: number): number; /** * This method is intended to be called by a clock to provide regular updates. It should be called by consumers of the library. * @param msDelta How many milliseconds have passed since the last update cycle. * @returns */ update(msDelta: number): boolean; /** * This method is exposed primarily for the TickReceiver, so it can get a metronome to update, using its own calculation of how many quarter notes to update by. * * This method should not be called by consumers of the library. * @param qnDelta The number of quarter notes to update the metronome by. * @returns */ updateFromQuarterNoteDelta(qnDelta: number): boolean; /** Calling this tells the flexinome to stop whatever it's doing and that it will no longer be used. */ finish(): void; /** * Provides a way for setting the ref through a chained function call. For example: * * ``` * clock.addChild(new Flexinome(120, TimeSig.commonTime).withRef('metronome')); * ``` * * @param ref The ref to set on the object. * @returns The calling object. */ withRef(ref: string): IClockChild; /** * This method allows for setting the metronome to a specific position. * * Note though, that the bar-related values are calculated under the assumption that the metronome's current time signature is the one that it always has. * @param totalQuarterNote The new position, as measured in quarter notes. */ setSongPosition(totalQuarterNote: number): void; /** * Event that fires whenever the metronome is directed to move to a new position. */ get positionChanged(): ShimiEvent<ShimiEventData<IMetronome>, IMetronome>; private _positionChanged; /** * Event that fires when the metronome is first started */ get started(): ShimiEvent<ShimiEventData<IMetronome>, IMetronome>; private _started; /** * Event that fires when the metronome is allowed to resume running (enabled = true) */ get continued(): ShimiEvent<ShimiEventData<IMetronome>, IMetronome>; private _continued; /** * Event that fires when the metronome is instructed to stop running (enabled = false) */ get stopped(): ShimiEvent<ShimiEventData<IMetronome>, IMetronome>; private _stopped; }