Documented syncing and updated zifferjs
This commit is contained in:
@ -87,6 +87,7 @@ export class UserAPI {
|
||||
public currentSeed: string | undefined = undefined;
|
||||
public localSeeds = new Map<string, Function>();
|
||||
public patternCache = new LRUCache({ max: 1000, ttl: 1000 * 60 * 5 });
|
||||
public cueTimes: { [key: string]: number } = {};
|
||||
private errorTimeoutID: number = 0;
|
||||
private printTimeoutID: number = 0;
|
||||
public MidiConnection: MidiConnection;
|
||||
@ -2176,4 +2177,10 @@ export class UserAPI {
|
||||
*/
|
||||
this.app.clock.time_signature = [numerator, denominator];
|
||||
};
|
||||
|
||||
public cue = (functionName: string|Function): void => {
|
||||
functionName = typeof functionName === "function" ? functionName.name : functionName;
|
||||
this.cueTimes[functionName] = this.app.clock.pulses_since_origin;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@ -34,8 +34,8 @@ import { ziffers_basics } from "./documentation/patterns/ziffers/ziffers_basics"
|
||||
import { ziffers_scales } from "./documentation/patterns/ziffers/ziffers_scales";
|
||||
import { ziffers_rhythm } from "./documentation/patterns/ziffers/ziffers_rhythm";
|
||||
import { ziffers_algorithmic } from "./documentation/patterns/ziffers/ziffers_algorithmic";
|
||||
|
||||
import { ziffers_tonnetz } from "./documentation/patterns/ziffers/ziffers_tonnetz";
|
||||
import { ziffers_syncing } from "./documentation/patterns/ziffers/ziffers_syncing";
|
||||
|
||||
import { synths } from "./documentation/learning/audio_engine/synths";
|
||||
|
||||
@ -102,6 +102,7 @@ export const documentation_factory = (application: Editor) => {
|
||||
ziffers_algorithmic: ziffers_algorithmic(application),
|
||||
ziffers_rhythm: ziffers_rhythm(application),
|
||||
ziffers_tonnetz: ziffers_tonnetz(application),
|
||||
ziffers_syncing: ziffers_syncing(application),
|
||||
midi: midi(application),
|
||||
osc: osc(application),
|
||||
lfos: lfos(application),
|
||||
|
||||
@ -508,6 +508,7 @@ export const installInterfaceLogic = (app: Editor) => {
|
||||
"ziffers_rhythm",
|
||||
"ziffers_algorithmic",
|
||||
"ziffers_tonnetz",
|
||||
"ziffers_syncing",
|
||||
"midi",
|
||||
"osc",
|
||||
"functions",
|
||||
|
||||
@ -442,4 +442,9 @@ export abstract class AudibleEvent extends AbstractEvent {
|
||||
update = (): void => {
|
||||
// Overwrite in subclasses
|
||||
};
|
||||
|
||||
cue = (functionName: string|Function): this => {
|
||||
this.app.api.cue(functionName);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@ -127,8 +127,9 @@ export class Player extends AbstractEvent {
|
||||
|
||||
const patternIsStarting =
|
||||
this.notStarted() &&
|
||||
(this.pulse() === 0 || this.origin() >= this.nextBeatInTicks()) &&
|
||||
this.origin() >= this.waitTime;
|
||||
this.waitTime >= 0 &&
|
||||
this.origin() >= this.waitTime &&
|
||||
(this.pulse() === 0 || this.origin() >= this.nextBeatInTicks());
|
||||
|
||||
const timeToPlayNext =
|
||||
this.current &&
|
||||
@ -315,16 +316,30 @@ export class Player extends AbstractEvent {
|
||||
return this;
|
||||
}
|
||||
|
||||
wait(value: number | Function) {
|
||||
wait(value: number | string | Function) {
|
||||
|
||||
if(typeof value === "string") {
|
||||
const cueTime = this.app.api.cueTimes[value];
|
||||
if(cueTime && this.app.clock.pulses_since_origin <= cueTime) {
|
||||
this.waitTime = cueTime;
|
||||
} else {
|
||||
this.waitTime = -1;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
if (this.atTheBeginning()) {
|
||||
if (typeof value === "function") {
|
||||
const refPat = this.app.api.patternCache.get(value.name) as Player;
|
||||
if (refPat) this.waitTime = refPat.nextEndTime();
|
||||
return this;
|
||||
} else if(typeof value === "number") {
|
||||
this.waitTime =
|
||||
this.origin() + Math.ceil(value * 4 * this.app.clock.ppqn);
|
||||
return this;
|
||||
}
|
||||
this.waitTime =
|
||||
this.origin() + Math.ceil(value * 4 * this.app.clock.ppqn);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@ -4,11 +4,53 @@ import { makeExampleFactory } from "../../../Documentation";
|
||||
export const ziffers_syncing = (application: Editor): string => {
|
||||
const makeExample = makeExampleFactory(application);
|
||||
return `
|
||||
# Synchronization
|
||||
# Synchronization
|
||||
|
||||
Ziffers numbered methods **(z0-z16)** can be used to parse and play patterns. Each method is individually cached and can be used to play multiple patterns simultaneously. By default, each Ziffers expression can have a different duration. This system is thus necessary to make everything fit together in a loop-based environment like Topos.
|
||||
Ziffers patterns can be synced to any event using <ic>cue(name: string))</ic> and <ic>wait(name: string)</ic> or by using <ic>sync(name: Function)</ic> and <ic>wait(name: Function)</ic> methods from the ziffers patterns.
|
||||
|
||||
## Sync with cue
|
||||
|
||||
The <ic>cue(name: string)</ic> methods can be used to send cue messages for ziffers patterns. The <ic>wait(name: string)</ic> method is used to wait for the cue message to start the pattern.
|
||||
|
||||
${makeExample(
|
||||
"Sending cue from event",
|
||||
`
|
||||
beat(4.0) :: sound("bd").cue("foo").out();
|
||||
z1("q 0 3 e 2 1 2 1").wait("foo").sound("sine").out();
|
||||
`,
|
||||
true,
|
||||
)}
|
||||
|
||||
${makeExample(
|
||||
"Delayed start using individual cue",
|
||||
`
|
||||
onbar(3) :: cue("bar")
|
||||
z1("0 4 2 -2").wait("bar")
|
||||
.sound("ST40:3").stretch([2,1,3,.1].beat(0.5)).out();
|
||||
`,
|
||||
true,
|
||||
)}
|
||||
|
||||
## Sync with beat
|
||||
|
||||
Patterns can also be synced using beat and setting the note length of events to zero using **z** duration character or <ic>noteLength(number)</ic> method.
|
||||
|
||||
${makeExample(
|
||||
"Syncing with beat",
|
||||
`
|
||||
beat(.5) :: z1("<bd sn:3> hh:5").noteLength(0)
|
||||
.sound().out()
|
||||
|
||||
Numbered methods are synced automatically to **z0** method if it exsists. Syncing can also be done manually by using either the <ic>wait</ic> method, which will always wait for the current pattern to finish before starting the next cycle, or the <ic>sync</ic> method will only wait for the synced pattern to finish on the first time.
|
||||
beat([2.0,0.5,1.5].bar(1)) ::
|
||||
z2("z _ 0 0 <2 1>").sound("bass:5")
|
||||
.dur(0.5).out()
|
||||
`,
|
||||
true,
|
||||
)}
|
||||
|
||||
## Automatic sync for ziffers patterns
|
||||
|
||||
Numbered methods **(z0-z16)** are synced automatically to **z0** method if it exsists. Syncing can also be done manually by using either the <ic>wait</ic> method, which will always wait for the current pattern to finish before starting the next cycle, or the <ic>sync</ic> method will only wait for the synced pattern to finish on the first time.
|
||||
|
||||
${makeExample(
|
||||
"Automatic sync to z0",
|
||||
@ -18,6 +60,23 @@ export const ziffers_syncing = (application: Editor): string => {
|
||||
`,
|
||||
true,
|
||||
)}
|
||||
|
||||
## Syncing patterns to each other
|
||||
|
||||
Patterns can also be synced together using the <ic>sync(name: Function)</ic> method. This will sync the pattern to the start of the referenced pattern. Copy this example and first run z1 and then z2 at random position.
|
||||
|
||||
${makeExample(
|
||||
"Sync on first run",
|
||||
`
|
||||
z1('w __ 0 5 9 3').sound('bin').out()
|
||||
z2('q __ 4 2 e 6 3 q 6').sync(z1).sound('east').out()
|
||||
`,
|
||||
true,
|
||||
)}
|
||||
|
||||
## Sync with wait
|
||||
|
||||
Syncing can also be done using <ic>wait(name: Function)</ic> method. This will wait for the referenced pattern to finish before starting the next cycle.
|
||||
|
||||
${makeExample(
|
||||
"Sync with wait",
|
||||
@ -27,15 +86,6 @@ export const ziffers_syncing = (application: Editor): string => {
|
||||
`,
|
||||
true,
|
||||
)}
|
||||
|
||||
${makeExample(
|
||||
"Sync on first run",
|
||||
`
|
||||
z1('w __ 0 5 9 3').sound('bin').out()
|
||||
z2('q __ 4 2 e 6 3 q 6').sync(z1).sound('east').out()
|
||||
`,
|
||||
true,
|
||||
)}
|
||||
|
||||
`;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user