diff --git a/src/API.ts b/src/API.ts
index 423922f..633ef95 100644
--- a/src/API.ts
+++ b/src/API.ts
@@ -745,7 +745,7 @@ export class UserAPI {
if (id !== "" && zid !== "z0") {
// Sync named patterns to z0 by default
- player.sync("z0");
+ player.sync("z0", false);
}
return player;
diff --git a/src/classes/ZPlayer.ts b/src/classes/ZPlayer.ts
index e8bfcec..674e338 100644
--- a/src/classes/ZPlayer.ts
+++ b/src/classes/ZPlayer.ts
@@ -17,6 +17,7 @@ export class Player extends AbstractEvent {
startCallTime: number = 0;
lastCallTime: number = 0;
waitTime = 0;
+ cueName: string|undefined = undefined;
played: boolean = false;
current!: Pitch | Chord | ZRest;
retro: boolean = false;
@@ -133,6 +134,7 @@ export class Player extends AbstractEvent {
const timeToPlayNext =
this.current &&
+ this.waitTime >= 0 &&
this.pulseToSecond(this.origin()) >=
this.pulseToSecond(this.lastCallTime) +
this.pulseToSecond(this.current.duration * 4 * this.app.clock.ppqn) &&
@@ -158,8 +160,19 @@ export class Player extends AbstractEvent {
return areWeThereYet;
};
+ checkCue() {
+ if(this.ziffers.atLast()) {
+ if(this.cueName && this.app.api.cueTimes[this.cueName]) {
+ delete this.app.api.cueTimes[this.cueName];
+ this.cueName = undefined;
+ this.waitTime = -1;
+ }
+ }
+ }
+
sound(name?: string | string[] | SoundParams | SoundParams[]) {
if (this.areWeThereYet()) {
+ this.checkCue();
const event = this.next() as Pitch | Chord | ZRest;
const noteLengthInSeconds = this.app.clock.convertPulseToSecond(
event.duration * 4 * this.app.clock.ppqn,
@@ -214,6 +227,7 @@ export class Player extends AbstractEvent {
midi(value: number | undefined = undefined) {
if (this.areWeThereYet()) {
+ this.checkCue();
const event = this.next() as Pitch | Chord | ZRest;
const obj = event.getExisting(
"note",
@@ -316,14 +330,28 @@ export class Player extends AbstractEvent {
return this;
}
- wait(value: number | string | Function) {
-
+ listen(value: string) {
if(typeof value === "string") {
const cueTime = this.app.api.cueTimes[value];
+ this.cueName = value;
if(cueTime && this.app.clock.pulses_since_origin <= cueTime) {
this.waitTime = cueTime;
} else {
- this.waitTime = -1;
+ this.waitTime = -1;
+ }
+ return this;
+ }
+ }
+
+ wait(value: number | string | Function) {
+
+ if(typeof value === "string") {
+ const cueTime = this.app.api.cueTimes[value];
+ this.cueName = value;
+ if(cueTime && this.app.clock.pulses_since_origin <= cueTime) {
+ this.waitTime = cueTime;
+ } else if(this.atTheBeginning()){
+ this.waitTime = -1;
}
return this;
}
@@ -343,12 +371,24 @@ export class Player extends AbstractEvent {
return this;
}
- sync(value: string | Function) {
+ sync(value: string | Function, manualSync: boolean = true) {
+
+ if(typeof value === "string") {
+ if(manualSync) {
+ const cueTime = this.app.api.cueTimes[value];
+ if(cueTime) {
+ this.waitTime = cueTime;
+ } else {
+ this.waitTime = -1;
+ }
+ }
+ return this;
+ }
+
if (this.atTheBeginning() && this.notStarted()) {
const origin = this.app.clock.pulses_since_origin;
- const syncId = typeof value === "function" ? value.name : value;
if (origin > 0) {
- const syncPattern = this.app.api.patternCache.get(syncId) as Player;
+ const syncPattern = this.app.api.patternCache.get(value.name) as Player;
if (syncPattern) {
const syncPatternDuration = syncPattern.ziffers.duration;
const syncPatternStart = syncPattern.startCallTime;
diff --git a/src/documentation/patterns/ziffers/ziffers_syncing.ts b/src/documentation/patterns/ziffers/ziffers_syncing.ts
index 933052c..70b3003 100644
--- a/src/documentation/patterns/ziffers/ziffers_syncing.ts
+++ b/src/documentation/patterns/ziffers/ziffers_syncing.ts
@@ -6,31 +6,50 @@ export const ziffers_syncing = (application: Editor): string => {
return `
# Synchronization
-Ziffers patterns can be synced to any event using cue(name: string)) and wait(name: string) or by using sync(name: Function) and wait(name: Function) methods from the ziffers patterns.
+Ziffers patterns can be synced to any event by using **cue**, **sync**, **wait** and **listen** methods.
## Sync with cue
-The cue(name: string) methods can be used to send cue messages for ziffers patterns. The wait(name: string) method is used to wait for the cue message to start the pattern.
+The cue(name: string) methods can be used to send cue messages for ziffers patterns. The wait(name: string) method is used to wait for the cue message to be received before starting the next cycle.
${makeExample(
- "Sending cue from event",
+ "Sending cue from event and wait",
`
beat(4.0) :: sound("bd").cue("foo").out();
- z1("q 0 3 e 2 1 2 1").wait("foo").sound("sine").out();
+ z1("e 0 3 2 1 2 1").wait("foo").sound("sine").out();
`,
true,
)}
+The sync(name: string) method is used to sync the ziffers pattern to the cue message.
+
${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();
+ register('christmas', n=>n.room(0.25).size(2).speed([0.5, 0.25, 0.125])
+ .delay(0.5).delayt(1/3).delayfb(0.5).bpf(200+usine(1/3)*500).out())
+ onbar(1) :: cue("bar")
+ onbar(2) :: cue('baz')
+ z1("<0.25 0.125> 0 4 2 -2").sync("bar").sound("ST40:25").christmas()
+ z2("<0.25 0.125> 0 6 4 -4").sync("baz").sound("ST40:25").christmas()
`,
true,
)}
+The listen(name: string) method can be used to listen for the cue messages and play one event from the pattern for every cue.
+
+ ${makeExample(
+ "Delayed start using individual cue",
+ `
+ beat(1.0) :: cue("boom")
+
+ z1("bd ").listen("boom")
+ .sound().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 noteLength(number) method.