From 491461e354ed142196773f64ccb2e5e46137863d Mon Sep 17 00:00:00 2001 From: Miika Alonen Date: Mon, 11 Dec 2023 02:35:54 +0200 Subject: [PATCH] Documented arpeggios and updated zifferjs --- package.json | 2 +- src/classes/AbstractEvents.ts | 1 + src/classes/ZPlayer.ts | 12 +-- .../patterns/ziffers/ziffers_basics.ts | 78 +++++++++---------- .../patterns/ziffers/ziffers_syncing.ts | 43 ++++++++++ yarn.lock | 8 +- 6 files changed, 94 insertions(+), 50 deletions(-) diff --git a/package.json b/package.json index d84b47b..39000ec 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "tone": "^14.8.49", "unique-names-generator": "^4.7.1", "vite-plugin-markdown": "^2.1.0", - "zifferjs": "^0.0.48", + "zifferjs": "^0.0.50", "zyklus": "^0.1.4", "zzfx": "^1.2.0" } diff --git a/src/classes/AbstractEvents.ts b/src/classes/AbstractEvents.ts index 7fe450e..8fc2365 100644 --- a/src/classes/AbstractEvents.ts +++ b/src/classes/AbstractEvents.ts @@ -391,6 +391,7 @@ export abstract class AudibleEvent extends AbstractEvent { }; public invert = (howMany: number = 0) => { + if(howMany === 0) return this; if (this.values.note) { let notes = [...this.values.note]; notes = howMany < 0 ? [...notes].reverse() : notes; diff --git a/src/classes/ZPlayer.ts b/src/classes/ZPlayer.ts index 15317d6..9792bcc 100644 --- a/src/classes/ZPlayer.ts +++ b/src/classes/ZPlayer.ts @@ -270,18 +270,18 @@ export class Player extends AbstractEvent { return this; } - octaCycle(tonnetz: TonnetzSpaces = [3, 4, 5]) { - if (this.atTheBeginning()) this.ziffers.octaCycle(tonnetz); + octaCycle(tonnetz: TonnetzSpaces = [3, 4, 5], repeats: number = 4) { + if (this.atTheBeginning()) this.ziffers.octaCycle(tonnetz, repeats); return this; } - hexaCycle(tonnetz: TonnetzSpaces = [3, 4, 5]) { - if (this.atTheBeginning()) this.ziffers.hexaCycle(tonnetz); + hexaCycle(tonnetz: TonnetzSpaces = [3, 4, 5], repeats: number = 3) { + if (this.atTheBeginning()) this.ziffers.hexaCycle(tonnetz, repeats); return this; } - enneaCycle(tonnetz: TonnetzSpaces = [3, 4, 5]) { - if (this.atTheBeginning()) this.ziffers.enneaCycle(tonnetz); + enneaCycle(tonnetz: TonnetzSpaces = [3, 4, 5], repeats: number = 3) { + if (this.atTheBeginning()) this.ziffers.enneaCycle(tonnetz, repeats); return this; } diff --git a/src/documentation/patterns/ziffers/ziffers_basics.ts b/src/documentation/patterns/ziffers/ziffers_basics.ts index 0eacf5e..ecb2d96 100644 --- a/src/documentation/patterns/ziffers/ziffers_basics.ts +++ b/src/documentation/patterns/ziffers/ziffers_basics.ts @@ -125,6 +125,26 @@ z1('w [0 [5 [3 7]]] h [0 4]') false, )} +## Rests + +${makeExample( + "Rest and octaves", + ` +z1('q 0 ^ e0 r _ 0 _ r 4 ^4 4') +.sound('sine').scale("godian").out() +`, + true, +)} + +${makeExample( + "Rests with durations", + ` + z1('q 0 4 e^r 3 e3 0.5^r h4 1/4^r e 5 r 0.125^r 0') + .sound('sine').scale("aeryptian").out() + `, + true, +)} + ## Chords Chords can be build by grouping pitches or using roman numeral notation, or by using named chords. @@ -198,40 +218,38 @@ z1('w [0 [5 [3 7]]] h [0 4]') `, )} -## Synchronization +## Arpeggios -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. - -Numbered methods are synced automatically to **z0** method if it exsists. Syncing can also be done manually by using either the wait method, which will always wait for the current pattern to finish before starting the next cycle, or the sync method will only wait for the synced pattern to finish on the first time. +Chords can be arpeggiated using the @-character within the ziffers notation or by using arpeggio method. ${makeExample( - "Automatic sync to z0", + "Arpeggio using the mini-notation", ` -z0('w 0 8').sound('peri').out() -z1('e 0 4 5 9').sound('bell').out() -`, - true, + z1("(i v vi%-3 iv%-2)@(s 0 2 0 1 2 1 0 2)") + .sound("sine").out() + `, )} ${makeExample( - "Sync with wait", + "Arpeggio from named chords with durations", ` -z1('w 0 5').sound('pluck').release(0.1).sustain(0.25).out() -z2('q 6 3').wait(z1).sound('sine').release(0.16).sustain(0.55).out() -`, - true, +z1("_ Gm7 ^ C9 D7 Gm7") + .arpeggio("e 0 2 q 3 e 1 2") + .sound("sine").out() + `, )} ${makeExample( - "Sync on first run", + "Arpeggio from roman chords with inversions", ` - z1('w __ 0 5 9 3').sound('bin').out() - z2('q __ 4 2 e 6 3 q 6').sync(z1).sound('east').out() -`, - true, + z1("i v%-1 vi%-1 iv%-2") + .arpeggio(0,2,1,2) + .noteLength(0.125) + .sound("sine").out() + `, )} -## Examples +## Chaining - Basic notation @@ -253,31 +271,13 @@ z1('0 1 2 3 4').key('G3').scale('minor').sound('sine').often(n => n.pitch+=3).ra )} ${makeExample( - "Simple options", + "Alternative way for inputting options", ` z1('0 3 2 4',{key: 'D3', scale: 'minor pentatonic'}).sound('sine').out() `, true, )} -${makeExample( - "Rest and octaves", - ` -z1('q 0 ^ e0 r _ 0 _ r 4 ^4 4') -.sound('sine').scale("godian").out() -`, - true, -)} - -${makeExample( - "Rests with durations", - ` - z1('q 0 4 e^r 3 e3 0.5^r h4 1/4^r e 5 r 0.125^r 0') - .sound('sine').scale("aeryptian").out() - `, - true, -)} - ## String prototypes You can also use string prototypes as an alternative syntax for creating Ziffers patterns diff --git a/src/documentation/patterns/ziffers/ziffers_syncing.ts b/src/documentation/patterns/ziffers/ziffers_syncing.ts index e69de29..84fb8d3 100644 --- a/src/documentation/patterns/ziffers/ziffers_syncing.ts +++ b/src/documentation/patterns/ziffers/ziffers_syncing.ts @@ -0,0 +1,43 @@ +import { type Editor } from "../../../main"; +import { makeExampleFactory } from "../../../Documentation"; + +export const ziffers_syncing = (application: Editor): string => { + const makeExample = makeExampleFactory(application); + return ` + # 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. + + Numbered methods are synced automatically to **z0** method if it exsists. Syncing can also be done manually by using either the wait method, which will always wait for the current pattern to finish before starting the next cycle, or the sync method will only wait for the synced pattern to finish on the first time. + + ${makeExample( + "Automatic sync to z0", + ` + z0('w 0 8').sound('peri').out() + z1('e 0 4 5 9').sound('bell').out() + `, + true, + )} + + ${makeExample( + "Sync with wait", + ` + z1('w 0 5').sound('pluck').release(0.1).sustain(0.25).out() + z2('q 6 3').wait(z1).sound('sine').release(0.16).sustain(0.55).out() + `, + 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, + )} + +`; +}; + + diff --git a/yarn.lock b/yarn.lock index 7eb57e5..c1c3280 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4028,10 +4028,10 @@ yaml@^2.1.1: resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.1.tgz#02fe0975d23cd441242aa7204e09fc28ac2ac33b" integrity sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ== -zifferjs@^0.0.48: - version "0.0.48" - resolved "https://registry.yarnpkg.com/zifferjs/-/zifferjs-0.0.48.tgz#af61ce6c5d58c05a2573310c0afbf55557d05196" - integrity sha512-DqPCOO0/RKyWlugz37eia0JOkbrVbkMtpM8k+XdtQ+MCY2zdklrd5K4g9lqD/TEhA7AUGvR9fdtTbjtuvXvRMg== +zifferjs@^0.0.50: + version "0.0.50" + resolved "https://registry.yarnpkg.com/zifferjs/-/zifferjs-0.0.50.tgz#5e8c31ba3aed00d23f9add3c7d21cfe1dc2b92bf" + integrity sha512-tXFqu5RfYVK5Epc1evf0OZdeX6hMKcbHSh5ZPO/XFfSBCMnnabAGde3M6eZk3SDcB6vhVt2OyiF91tYi3SSpbw== zyklus@^0.1.4: version "0.1.4"