2024-05-03 18:31:14 +00:00
|
|
|
import { Loop, LoopOptions } from "./Loop.js";
|
|
|
|
import { PatternGenerator, PatternName } from "./PatternGenerator.js";
|
|
|
|
import { ToneEventCallback } from "./ToneEvent.js";
|
|
|
|
import { optionsFromArguments } from "../core/util/Defaults.js";
|
|
|
|
import { Seconds } from "../core/type/Units.js";
|
|
|
|
import { noOp } from "../core/util/Interface.js";
|
2019-11-07 19:39:28 +00:00
|
|
|
|
|
|
|
export interface PatternOptions<ValueType> extends LoopOptions {
|
|
|
|
pattern: PatternName;
|
|
|
|
values: ValueType[];
|
|
|
|
callback: (time: Seconds, value?: ValueType) => void;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Pattern arpeggiates between the given notes
|
2024-05-03 18:31:14 +00:00
|
|
|
* in a number of patterns.
|
2019-11-07 19:39:28 +00:00
|
|
|
* @example
|
2020-04-17 02:24:18 +00:00
|
|
|
* const pattern = new Tone.Pattern((time, note) => {
|
2019-11-07 19:39:28 +00:00
|
|
|
* // the order of the notes passed in depends on the pattern
|
|
|
|
* }, ["C2", "D4", "E5", "A6"], "upDown");
|
2019-12-15 21:02:29 +00:00
|
|
|
* @category Event
|
2019-11-07 19:39:28 +00:00
|
|
|
*/
|
|
|
|
export class Pattern<ValueType> extends Loop<PatternOptions<ValueType>> {
|
|
|
|
readonly name: string = "Pattern";
|
2020-04-17 02:24:18 +00:00
|
|
|
|
2019-11-07 19:39:28 +00:00
|
|
|
/**
|
|
|
|
* The pattern generator function
|
|
|
|
*/
|
2022-01-05 05:12:40 +00:00
|
|
|
private _pattern: Iterator<number>;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The current index
|
|
|
|
*/
|
2024-05-03 18:31:14 +00:00
|
|
|
private _index?: number;
|
2019-11-07 19:39:28 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The current value
|
|
|
|
*/
|
2024-05-03 18:31:14 +00:00
|
|
|
private _value?: ValueType;
|
2019-11-07 19:39:28 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Hold the pattern type
|
|
|
|
*/
|
|
|
|
private _type: PatternName;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Hold the values
|
|
|
|
*/
|
|
|
|
private _values: ValueType[];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The callback to be invoked at a regular interval
|
|
|
|
*/
|
|
|
|
callback: (time: Seconds, value?: ValueType) => void;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param callback The callback to invoke with the event.
|
|
|
|
* @param values The values to arpeggiate over.
|
|
|
|
* @param pattern The name of the pattern
|
|
|
|
*/
|
|
|
|
constructor(
|
|
|
|
callback?: ToneEventCallback<ValueType>,
|
|
|
|
values?: ValueType[],
|
2024-05-03 18:31:14 +00:00
|
|
|
pattern?: PatternName
|
2019-11-07 19:39:28 +00:00
|
|
|
);
|
|
|
|
constructor(options?: Partial<PatternOptions<ValueType>>);
|
|
|
|
constructor() {
|
2024-05-03 18:31:14 +00:00
|
|
|
super(
|
|
|
|
optionsFromArguments(Pattern.getDefaults(), arguments, [
|
|
|
|
"callback",
|
|
|
|
"values",
|
|
|
|
"pattern",
|
|
|
|
])
|
|
|
|
);
|
|
|
|
const options = optionsFromArguments(Pattern.getDefaults(), arguments, [
|
|
|
|
"callback",
|
|
|
|
"values",
|
|
|
|
"pattern",
|
|
|
|
]);
|
2019-11-07 19:39:28 +00:00
|
|
|
|
|
|
|
this.callback = options.callback;
|
|
|
|
this._values = options.values;
|
2024-05-03 18:31:14 +00:00
|
|
|
this._pattern = PatternGenerator(
|
|
|
|
options.values.length,
|
|
|
|
options.pattern
|
|
|
|
);
|
2019-11-07 19:39:28 +00:00
|
|
|
this._type = options.pattern;
|
|
|
|
}
|
|
|
|
|
|
|
|
static getDefaults(): PatternOptions<any> {
|
|
|
|
return Object.assign(Loop.getDefaults(), {
|
2021-10-13 22:38:30 +00:00
|
|
|
pattern: "up" as const,
|
2019-11-07 19:39:28 +00:00
|
|
|
values: [],
|
|
|
|
callback: noOp,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Internal function called when the notes should be called
|
|
|
|
*/
|
|
|
|
protected _tick(time: Seconds): void {
|
2022-01-05 05:12:40 +00:00
|
|
|
const index = this._pattern.next() as IteratorResult<ValueType>;
|
|
|
|
this._index = index.value;
|
|
|
|
this._value = this._values[index.value];
|
2019-11-07 19:39:28 +00:00
|
|
|
this.callback(time, this._value);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The array of events.
|
|
|
|
*/
|
|
|
|
get values(): ValueType[] {
|
|
|
|
return this._values;
|
|
|
|
}
|
|
|
|
set values(val) {
|
|
|
|
this._values = val;
|
|
|
|
// reset the pattern
|
|
|
|
this.pattern = this._type;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The current value of the pattern.
|
|
|
|
*/
|
|
|
|
get value(): ValueType | undefined {
|
|
|
|
return this._value;
|
|
|
|
}
|
|
|
|
|
2022-01-05 05:12:40 +00:00
|
|
|
/**
|
|
|
|
* The current index of the pattern.
|
|
|
|
*/
|
2024-05-03 18:31:14 +00:00
|
|
|
get index(): number | undefined {
|
2022-01-05 05:12:40 +00:00
|
|
|
return this._index;
|
|
|
|
}
|
|
|
|
|
2019-11-07 19:39:28 +00:00
|
|
|
/**
|
2024-05-03 18:31:14 +00:00
|
|
|
* The pattern type.
|
2019-11-07 19:39:28 +00:00
|
|
|
*/
|
|
|
|
get pattern(): PatternName {
|
|
|
|
return this._type;
|
|
|
|
}
|
|
|
|
set pattern(pattern) {
|
|
|
|
this._type = pattern;
|
2022-01-05 05:12:40 +00:00
|
|
|
this._pattern = PatternGenerator(this._values.length, this._type);
|
2019-11-07 19:39:28 +00:00
|
|
|
}
|
|
|
|
}
|