Updating the entire documentation

This commit is contained in:
2023-09-17 00:47:50 +02:00
parent d9f98bad74
commit cde3b6eb89
14 changed files with 287 additions and 307 deletions

View File

@ -6,7 +6,7 @@ declare global {
add(amount: number): number[]; add(amount: number): number[];
sub(amount: number): number[]; sub(amount: number): number[];
mult(amount: number): number[]; mult(amount: number): number[];
division(amount: number): number[]; div(amount: number): number[];
palindrome(): T[]; palindrome(): T[];
random(index: number): T; random(index: number): T;
rand(index: number): T; rand(index: number): T;
@ -74,7 +74,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
return this.map((x: number) => x * amount); return this.map((x: number) => x * amount);
}; };
Array.prototype.division = function (amount: number): number[] { Array.prototype.div = function (amount: number): number[] {
/** /**
* @param amount - The value to divide each element in the array by. * @param amount - The value to divide each element in the array by.
* @returns New array with divided values. Throws if division by zero. * @returns New array with divided values. Throws if division by zero.

View File

@ -34,8 +34,8 @@ Stopping **Hydra** is simple:
${makeExample( ${makeExample(
"Stopping Hydra", "Stopping Hydra",
` `
mod(4) :: stop_hydra() // this one beat(4) :: stop_hydra() // this one
mod(4) :: app.hydra.hush() // or this one beat(4) :: app.hydra.hush() // or this one
`, `,
true true
)} )}

View File

@ -16,7 +16,7 @@ All functions from the sound object can be used to modify the event, for example
${makeExample( ${makeExample(
"Modifying sound events with probabilities", "Modifying sound events with probabilities",
` `
mod(.5) && sound('numbers') beat(.5) && sound('numbers')
.odds(1/4, s => s.speed(irand(1,4))) .odds(1/4, s => s.speed(irand(1,4)))
.rarely(s => s.crush(3)) .rarely(s => s.crush(3))
.out() .out()
@ -27,7 +27,7 @@ ${makeExample(
"Chance to change to a different note", "Chance to change to a different note",
` `
rhythm(.5, 3, 8) && sound('pluck').note(38).out() rhythm(.5, 3, 8) && sound('pluck').note(38).out()
mod(.5) && sound('pluck').note(60) beat(.5) && sound('pluck').note(60)
.often(s => s.note(57)) .often(s => s.note(57))
.sometimes(s => s.note(64).n(irand(1,4))) .sometimes(s => s.note(64).n(irand(1,4)))
.note(62) .note(62)
@ -41,7 +41,7 @@ All the functions from the MIDI object can be used to modify the event with prob
${makeExample( ${makeExample(
"Modifying midi events with probabilities", "Modifying midi events with probabilities",
`mod(.5) && midi(60).channel(1) `beat(.5) && midi(60).channel(1)
.odds(1/4, n => n.channel(2)) .odds(1/4, n => n.channel(2))
.often(n => n.note+=4) .often(n => n.note+=4)
.sometimes(s => s.velocity(irand(50,100))) .sometimes(s => s.velocity(irand(50,100)))
@ -63,7 +63,7 @@ ${makeExample(
"Ziffer player using a sound chain and probabilities!", "Ziffer player using a sound chain and probabilities!",
` `
z1('s 0 5 7 0 3 7 0 2 7 0 1 7 0 1 6 5 4 3 2') z1('s 0 5 7 0 3 7 0 2 7 0 1 7 0 1 6 5 4 3 2')
.octave([0, 1].div(2) - 1) .octave([0, 1].beat(2) - 1)
.scale('pentatonic').sound('pluck') .scale('pentatonic').sound('pluck')
.odds(1/4, n => n.delay(0.5).delayt(0.25)) .odds(1/4, n => n.delay(0.5).delayt(0.25))
.odds(1/2, n => n.speed(0.5)) .odds(1/2, n => n.speed(0.5))

View File

@ -34,12 +34,12 @@ ${makeExample(
"Shortening your if conditions", "Shortening your if conditions",
` `
// The && symbol (overriden by :: in Topos) is very often used for conditions! // The && symbol (overriden by :: in Topos) is very often used for conditions!
mod(.75) :: snd('linnhats').n([1,4,5].beat()).out() beat(.75) :: snd('linnhats').n([1,4,5].beat()).out()
mod(1) :: snd('bd').out() beat(1) :: snd('bd').out()
//if (true) && log('very true') //if (true) && log('very true')
// These two lines are the same: // These two lines are the same:
// mod(1) && snd('bd').out() // beat(1) && snd('bd').out()
//// mod(1) :: snd('bd').out() //// beat(1) :: snd('bd').out()
`, `,
true true
@ -49,7 +49,7 @@ ${makeExample(
"More complex conditions using ?", "More complex conditions using ?",
` `
// The ? symbol can be used to write a if/true/false condition // The ? symbol can be used to write a if/true/false condition
mod(4) ? snd('kick').out() : mod(2)::snd('snare').out() beat(4) ? snd('kick').out() : beat(2) :: snd('snare').out()
// (true) ? log('very true') : log('very false') // (true) ? log('very true') : log('very false')
`, `,
false false
@ -60,14 +60,12 @@ ${makeExample(
"Using not and other short symbols", "Using not and other short symbols",
` `
// The ! symbol can be used to reverse a condition // The ! symbol can be used to reverse a condition
mod(4) ? snd('kick').out() : mod(2)::snd('snare').out() beat(4) ? snd('kick').out() : beat(2) :: snd('snare').out()
!mod(2) :: mod(0.5)::snd('clap').out() !beat(2) :: beat(0.5) :: snd('clap').out()
`, `,
false false
)} )}
## About crashes and bugs ## About crashes and bugs
Things will crash, that's also part of the show. You will learn progressively to avoid mistakes and to write safer code. Do not hesitate to kill the page or to stop the transport if you feel overwhelmed by an algorithm blowing up. There are no safeties in place to save you. This is to ensure that you have all the available possible room to write bespoke code and experiment with your ideas through code. Things will crash, that's also part of the show. You will learn progressively to avoid mistakes and to write safer code. Do not hesitate to kill the page or to stop the transport if you feel overwhelmed by an algorithm blowing up. There are no safeties in place to save you. This is to ensure that you have all the available possible room to write bespoke code and experiment with your ideas through code.

View File

@ -15,8 +15,8 @@ The basic function to play a sound is... <ic>sound(name: string)</ic> (you can a
${makeExample( ${makeExample(
"Playing sounds is easy", "Playing sounds is easy",
` `
mod(1) && sound('bd').out() beat(1) && sound('bd').out()
mod(0.5) && sound('hh').out() beat(0.5) && sound('hh').out()
`, `,
true true
)} )}
@ -31,8 +31,8 @@ Let's make it slightly more complex:
${makeExample( ${makeExample(
"Adding some effects", "Adding some effects",
` `
mod(1) && sound('bd').coarse(0.25).room(0.5).orbit(2).out(); beat(1) && sound('bd').coarse(0.25).room(0.5).orbit(2).out();
mod(0.5) && sound('hh').delay(0.25).delaytime(0.125).out(); beat(0.5) && sound('hh').delay(0.25).delaytime(0.125).out();
`, `,
true true
)} )}
@ -51,7 +51,7 @@ Let's pause for a moment to explain what we just wrote. There are many things to
${makeExample( ${makeExample(
'"Composing" a sound or making a sound chain', '"Composing" a sound or making a sound chain',
` `
mod(1) :: sound('pad') beat(1) :: sound('pad')
.begin(rand(0, 0.4)) .begin(rand(0, 0.4))
.freq([50,52].beat()) .freq([50,52].beat())
.size(0.9) .size(0.9)
@ -85,7 +85,7 @@ The <ic>.n(number)</ic> method can be used to pick a sample from the currently s
${makeExample( ${makeExample(
"Picking a sample", "Picking a sample",
` `
mod(1) && sound('kick').n([1,2,3,4,5,6,7,8].pick()).out() beat(1) && sound('kick').n([1,2,3,4,5,6,7,8].pick()).out()
`, `,
true true
)} )}
@ -96,7 +96,7 @@ ${makeExample(
"Picking a sample... with your mouse!", "Picking a sample... with your mouse!",
` `
// Move your mouse to change the sample being used! // Move your mouse to change the sample being used!
mod(.25) && sound('numbers').n(Math.floor(mouseX())).out()`, beat(.25) && sound('numbers').n(Math.floor(mouseX())).out()`,
true true
)} )}
@ -108,7 +108,7 @@ As we said earlier, the <ic>sound('sample_name')</ic> function can be chained to
${makeExample( ${makeExample(
"Learning through repetition", "Learning through repetition",
` `
mod(0.5) && sound('hh') beat(0.5) && sound('hh')
.sometimes(s=>s.speed([1,5,10].pick())) .sometimes(s=>s.speed([1,5,10].pick()))
.room(0.5) .room(0.5)
.cutoff(usine(2) * 5000) .cutoff(usine(2) * 5000)
@ -129,7 +129,7 @@ There is a special method to choose the _orbit_ that your sound is going to use:
| Method | Alias | Description | | Method | Alias | Description |
|----------|-------|------------------------------------------------------------| |----------|-------|------------------------------------------------------------|
| orbit | | Orbit number | | orbit | | Orbit number |
## Amplitude ## Amplitude
@ -145,7 +145,7 @@ Simple controls over the amplitude (volume) of a given sound.
${makeExample( ${makeExample(
"Velocity manipulated by a counter", "Velocity manipulated by a counter",
` `
mod(.5)::snd('cp').vel($(1)%10 / 10).out()`, beat(.5)::snd('cp').vel($(1)%10 / 10).out()`,
true true
)} )}
@ -165,10 +165,10 @@ Note that the **sustain** value is not a duration but an amplitude value (how lo
${makeExample( ${makeExample(
"Simple synthesizer", "Simple synthesizer",
` `
mod(4)::sound('sawtooth').note(50).decay(0.5).sustain(0.5).release(2).gain(0.25).out(); beat(4)::sound('sawtooth').note(50).decay(0.5).sustain(0.5).release(2).gain(0.25).out();
mod(2)::sound('sawtooth').note(50+7).decay(0.5).sustain(0.6).release(2).gain(0.25).out(); beat(2)::sound('sawtooth').note(50+7).decay(0.5).sustain(0.6).release(2).gain(0.25).out();
mod(1)::sound('sawtooth').note(50+12).decay(0.5).sustain(0.7).release(2).gain(0.25).out(); beat(1)::sound('sawtooth').note(50+12).decay(0.5).sustain(0.7).release(2).gain(0.25).out();
mod(.25)::sound('sawtooth').note([50,57,62].pick() + [12, 24, 0].div(2)) beat(.25)::sound('sawtooth').note([50,57,62].pick() + [12, 24, 0].beat(2))
.cutoff(5000).sustain(0.5).release(0.1).gain(0.25).out() .cutoff(5000).sustain(0.5).release(0.1).gain(0.25).out()
`, `,
true true
@ -192,9 +192,9 @@ ${makeExample(
"Complex sampling duties", "Complex sampling duties",
` `
// Using some of the modifiers described above :) // Using some of the modifiers described above :)
mod(.5)::snd('pad').begin(0.2) beat(.5)::snd('pad').begin(0.2)
.speed([1, 0.9, 0.8].div(4)) .speed([1, 0.9, 0.8].beat(4))
.n([0, 0, 2, 4].div(4)).pan(usine(.5)) .n([0, 0, 2, 4].beat(4)).pan(usine(.5))
.end(rand(0.3,0.8)) .end(rand(0.3,0.8))
.room(0.8).size(0.5) .room(0.8).size(0.5)
.clip(1).out() .clip(1).out()
@ -220,7 +220,7 @@ There are three basic filters: a _lowpass_, _highpass_ and _bandpass_ filters wi
${makeExample( ${makeExample(
"Filter sweep using a low frequency oscillator", "Filter sweep using a low frequency oscillator",
` `
mod(.5) && snd('sawtooth') beat(.5) && snd('sawtooth')
.cutoff([2000,500].pick() + usine(.5) * 4000) .cutoff([2000,500].pick() + usine(.5) * 4000)
.resonance(0.9).freq([100,150].pick()) .resonance(0.9).freq([100,150].pick())
.out() .out()
@ -240,7 +240,7 @@ A basic reverberator that you can use to give some depth to your sounds. This si
${makeExample( ${makeExample(
"Clapping in the cavern", "Clapping in the cavern",
` `
mod(2)::snd('cp').room(1).size(0.9).out() beat(2)::snd('cp').room(1).size(0.9).out()
`, `,
true true
)}; )};
@ -259,9 +259,9 @@ A good sounding delay unit that can go into feedback territory. Use it without m
${makeExample( ${makeExample(
"Who doesn't like delay?", "Who doesn't like delay?",
` `
mod(2)::snd('cp').delay(0.5).delaytime(0.75).delayfb(0.8).out() beat(2)::snd('cp').delay(0.5).delaytime(0.75).delayfb(0.8).out()
mod(4)::snd('snare').out() beat(4)::snd('snare').out()
mod(1)::snd('kick').out() beat(1)::snd('kick').out()
`, `,
true true
)}; )};
@ -278,8 +278,8 @@ mod(1)::snd('kick').out()
${makeExample( ${makeExample(
"Crunch... crunch... crunch!", "Crunch... crunch... crunch!",
` `
mod(.5)::snd('pad').coarse($(1) % 16).clip(.5).out(); // Comment me beat(.5)::snd('pad').coarse($(1) % 16).clip(.5).out(); // Comment me
mod(.5)::snd('pad').crush([16, 8, 4].div(2)).clip(.5).out() beat(.5)::snd('pad').crush([16, 8, 4].beat(2)).clip(.5).out()
`, `,
true true
)}; )};

View File

@ -86,7 +86,7 @@ You can control scripts programatically. This is the core concept of Topos after
${makeExample( ${makeExample(
"Calling a script! The most important feature!", "Calling a script! The most important feature!",
` `
mod(1) :: script(1) beat(1) :: script(1)
`, `,
true true
)} )}
@ -94,7 +94,7 @@ mod(1) :: script(1)
${makeExample( ${makeExample(
"Calling mutliple scripts at the same time.", "Calling mutliple scripts at the same time.",
` `
mod(1) :: script(1, 3, 5) beat(1) :: script(1, 3, 5)
`, `,
false false
)} )}
@ -111,7 +111,7 @@ You can get the current position of the mouse on the screen by using the followi
${makeExample( ${makeExample(
"FM Synthesizer controlled using the mouse", "FM Synthesizer controlled using the mouse",
` `
mod(.25) :: sound('sine') beat(.25) :: sound('sine')
.fmi(mouseX() / 100) .fmi(mouseX() / 100)
.fmh(mouseY() / 100) .fmh(mouseY() / 100)
.vel(0.2) .vel(0.2)
@ -129,7 +129,7 @@ Current mouse position can also be used to generate notes:
${makeExample( ${makeExample(
"The same synthesizer, with note control!", "The same synthesizer, with note control!",
` `
mod(.25) :: sound('sine') beat(.25) :: sound('sine')
.fmi(mouseX() / 100) .fmi(mouseX() / 100)
.note(noteX()) .note(noteX())
.fmh(mouseY() / 100) .fmh(mouseY() / 100)
@ -148,7 +148,7 @@ Low Frequency Oscillators (_LFOs_) are an important piece in any digital audio w
${makeExample( ${makeExample(
"Modulating the speed of a sample player using a sine LFO", "Modulating the speed of a sample player using a sine LFO",
`mod(.25) && snd('cp').speed(1 + usine(0.25) * 2).out()`, `beat(.25) && snd('cp').speed(1 + usine(0.25) * 2).out()`,
true true
)}; )};
@ -158,7 +158,7 @@ ${makeExample(
${makeExample( ${makeExample(
"Modulating the speed of a sample player using a triangle LFO", "Modulating the speed of a sample player using a triangle LFO",
`mod(.25) && snd('cp').speed(1 + utriangle(0.25) * 2).out()`, `beat(.25) && snd('cp').speed(1 + utriangle(0.25) * 2).out()`,
true true
)} )}
@ -168,7 +168,7 @@ ${makeExample(
${makeExample( ${makeExample(
"Modulating the speed of a sample player using a saw LFO", "Modulating the speed of a sample player using a saw LFO",
`mod(.25) && snd('cp').speed(1 + usaw(0.25) * 2).out()`, `beat(.25) && snd('cp').speed(1 + usaw(0.25) * 2).out()`,
true true
)} )}
@ -177,7 +177,7 @@ ${makeExample(
${makeExample( ${makeExample(
"Modulating the speed of a sample player using a square LFO", "Modulating the speed of a sample player using a square LFO",
`mod(.25) && snd('cp').speed(1 + usquare(0.25, 0, 0.25) * 2).out()`, `beat(.25) && snd('cp').speed(1 + usquare(0.25, 0, 0.25) * 2).out()`,
true true
)}; )};
@ -185,7 +185,7 @@ ${makeExample(
${makeExample( ${makeExample(
"Modulating the speed of a sample player using noise", "Modulating the speed of a sample player using noise",
`mod(.25) && snd('cp').speed(1 + noise() * 2).out()`, `beat(.25) && snd('cp').speed(1 + noise() * 2).out()`,
true true
)}; )};
@ -254,8 +254,8 @@ ${makeExample(
${makeExample( ${makeExample(
"Using chance with other operators", "Using chance with other operators",
` `
frequently() :: mod(1) :: sound('kick').out(); frequently() :: beat(1) :: sound('kick').out();
often() :: mod(0.5) :: sound('hh').out(); often() :: beat(0.5) :: sound('hh').out();
sometimes() :: onbeat(1,3) :: sound('snare').out(); sometimes() :: onbeat(1,3) :: sound('snare').out();
`, `,
true true
@ -264,12 +264,12 @@ ${makeExample(
${makeExample( ${makeExample(
"Using chance with chaining", "Using chance with chaining",
` `
mod(0.5) && sound("bd") beat(0.5) && sound("bd")
.freq(100) .freq(100)
.sometimes(s=>s.crush(2.5)) .sometimes(s=>s.crush(2.5))
.out() .out()
mod(0.5) && sound('arp').freq(100) beat(0.5) && sound('arp').freq(100)
.sometimes(n=>n.freq(200).delay(0.5)) .sometimes(n=>n.freq(200).delay(0.5))
.rarely(n=>n.freq(300).delay(2.5)) .rarely(n=>n.freq(300).delay(2.5))
.almostNever(n=>n.freq(400)) .almostNever(n=>n.freq(400))
@ -293,8 +293,8 @@ ${makeExample(
"Phased woodblocks", "Phased woodblocks",
` `
// Some very low-budget version of phase music // Some very low-budget version of phase music
mod(.5) :: delay(usine(.125) * 80, () => sound('east').out()) beat(.5) :: delay(usine(.125) * 80, () => sound('east').out())
mod(.5) :: delay(50, () => sound('east').out()) beat(.5) :: delay(50, () => sound('east').out())
`, `,
true true
)} )}
@ -304,8 +304,8 @@ mod(.5) :: delay(50, () => sound('east').out())
${makeExample( ${makeExample(
"Another woodblock texture", "Another woodblock texture",
` `
mod(1) :: delayr(50, 4, () => sound('east').speed([0.5,.25].beat()).out()) beat(1) :: delayr(50, 4, () => sound('east').speed([0.5,.25].beat()).out())
div(2) :: mod(2) :: delayr(150, 4, () => sound('east').speed([0.5,.25].beat() * 4).out()) flip(2) :: beat(2) :: delayr(150, 4, () => sound('east').speed([0.5,.25].beat() * 4).out())
`, `,
true true
)}; )};

View File

@ -23,7 +23,7 @@ const completionDatabase: CompletionDatabase = {
name: "delayr", name: "delayr",
category: "time", category: "time",
description: "Delay a function <i>n</i> times by <i>t</i> ms", description: "Delay a function <i>n</i> times by <i>t</i> ms",
example: "delayr(50, 3, () => mod(1) :: log('delayed'))", example: "delayr(50, 3, () => beat(1) :: log('delayed'))",
}, },
toss: { toss: {
name: "toss", name: "toss",
@ -115,12 +115,12 @@ const completionDatabase: CompletionDatabase = {
description: "Log a value in the console", description: "Log a value in the console",
example: "log('Hello, world')", example: "log('Hello, world')",
}, },
div: { flip: {
name: "div", name: "flip",
category: "patterns", category: "patterns",
description: description:
"Returns next value every <i>n</i> beats or true and false alternatively", "Returns true and false alternatively or next value every <i>n</i> beats (arrays)",
example: "div(4, 50) // 2 beats of true, 2 beats of false, 50/50.", example: "flip(4, 50) // 2 beats of true, 2 beats of false, 50/50.",
}, },
n: { n: {
name: "n", name: "n",
@ -192,7 +192,7 @@ const completionDatabase: CompletionDatabase = {
name: "coarse", name: "coarse",
category: "synthesis", category: "synthesis",
description: "Artificial sample-rate lowering", description: "Artificial sample-rate lowering",
example: "mod(.5)::snd('pad').coarse($(1) % 16).clip(.5).out();", example: "beat(.5)::snd('pad').coarse($(1) % 16).clip(.5).out();",
}, },
crush: { crush: {
name: "crush", name: "crush",
@ -335,17 +335,17 @@ const completionDatabase: CompletionDatabase = {
example: example:
"oncount([1,2,3], 4) // true on beats 1, 2 and 3 in a 4 beats period", "oncount([1,2,3], 4) // true on beats 1, 2 and 3 in a 4 beats period",
}, },
mod: { beat: {
name: "mod", name: "beat",
category: "rhythm", category: "rhythm",
description: "return true every <i>n</i> pulsations.", description: "return true every <i>n</i> beats.",
example: "mod(1) :: log(rand(1,5))", example: "beat(1) :: log(rand(1,5))",
}, },
modp: { pulse: {
name: "modp", name: "pulse",
category: "rhythm", category: "rhythm",
description: "return true every <i>n</i> ticks.", description: "return true every <i>n</i> pulses.",
example: "modp(8) :: log(rand(1,5))", example: "pulse(8) :: log(rand(1,5))",
}, },
euclid: { euclid: {
name: "euclid", name: "euclid",
@ -399,61 +399,61 @@ const completionDatabase: CompletionDatabase = {
name: "odds", name: "odds",
category: "randomness", category: "randomness",
description: "Return true with a probability of <i>n</i> %", description: "Return true with a probability of <i>n</i> %",
example: "odds(1/2) // 50% probability" example: "odds(1/2) // 50% probability",
}, },
never: { never: {
name: "never", name: "never",
category: "randomness", category: "randomness",
description: "Return false", description: "Return false",
example: "never() // false" example: "never() // false",
}, },
almostNever: { almostNever: {
name: "almostNever", name: "almostNever",
category: "randomness", category: "randomness",
description: "Return true with a probability of 2.5%", description: "Return true with a probability of 2.5%",
example: "almostNever() // 2.5% chance" example: "almostNever() // 2.5% chance",
}, },
rarely: { rarely: {
name: "rarely", name: "rarely",
category: "randomness", category: "randomness",
description: "Return true with a probability of 10%", description: "Return true with a probability of 10%",
example: "rarely() // 10% chance" example: "rarely() // 10% chance",
}, },
scarcely: { scarcely: {
name: "scarcely", name: "scarcely",
category: "randomness", category: "randomness",
description: "Return true with a probability of 25%", description: "Return true with a probability of 25%",
example: "scarcely() // 25% chance" example: "scarcely() // 25% chance",
}, },
sometimes: { sometimes: {
name: "sometimes", name: "sometimes",
category: "randomness", category: "randomness",
description: "Return true with a probability of 50%", description: "Return true with a probability of 50%",
example: "sometimes() // 50% chance" example: "sometimes() // 50% chance",
}, },
often: { often: {
name: "often", name: "often",
category: "randomness", category: "randomness",
description: "Return true with a probability of 75%", description: "Return true with a probability of 75%",
example: "often() // 75% chance" example: "often() // 75% chance",
}, },
frequently: { frequently: {
name: "frequently", name: "frequently",
category: "randomness", category: "randomness",
description: "Return true with a probability of 90%", description: "Return true with a probability of 90%",
example: "frequently() // chance" example: "frequently() // chance",
}, },
almostAlways: { almostAlways: {
name: "almostAlways", name: "almostAlways",
category: "randomness", category: "randomness",
description: "Return true with a probability of 98.5%", description: "Return true with a probability of 98.5%",
example: "almostAlways() // 98.5% chance" example: "almostAlways() // 98.5% chance",
}, },
always: { always: {
name: "always", name: "always",
category: "randomness", category: "randomness",
description: "Return true", description: "Return true",
example: "always() // true" example: "always() // true",
}, },
sound: { sound: {
name: "sound", name: "sound",
@ -484,7 +484,7 @@ const completionDatabase: CompletionDatabase = {
name: "script", name: "script",
category: "core", category: "core",
description: "Execute one or more local scripts", description: "Execute one or more local scripts",
example: "mod(1) :: script(1)", example: "beat(1) :: script(1)",
}, },
clear_script: { clear_script: {
name: "clear_script", name: "clear_script",
@ -514,14 +514,14 @@ const completionDatabase: CompletionDatabase = {
name: "divbar", name: "divbar",
category: "time", category: "time",
description: description:
"works just like <i>div</i> but at the level of bars instead of beats", "works just like <i>flip</i> but at the level of bars instead of beats",
example: "divbar(2)::mod(1)::snd('kick').out()", example: "divbar(2)::beat(1)::snd('kick').out()",
}, },
onbar: { onbar: {
name: "onbar", name: "onbar",
category: "time", category: "time",
description: "return true when targetted bar(s) is/are reached in period", description: "return true when targetted bar(s) is/are reached in period",
example: "onbar(4, 4)::mod(.5)::snd('hh').out();", example: "onbar(4, 4)::beat(.5)::snd('hh').out();",
}, },
begin: { begin: {
name: "begin", name: "begin",
@ -629,7 +629,7 @@ const completionDatabase: CompletionDatabase = {
name: "speak", name: "speak",
category: "synthesis", category: "synthesis",
description: "Text to speech synthesizer", description: "Text to speech synthesizer",
example: "mod(2) :: speak('Topos!','fr',irand(0,5))", example: "beat(2) :: speak('Topos!','fr',irand(0,5))",
}, },
midi_outputs: { midi_outputs: {
name: "midi_outputs", name: "midi_outputs",
@ -775,11 +775,11 @@ const completionDatabase: CompletionDatabase = {
description: "Multiply each element of the given array by a value", description: "Multiply each element of the given array by a value",
example: "[0,1,2,3].mul(2)", example: "[0,1,2,3].mul(2)",
}, },
division: { div: {
name: "div", name: "div",
category: "patterns", category: "patterns",
description: "Divide each element of the given array by a value", description: "Divide each element of the given array by a value",
example: "[0,1,2,3].division(2)", example: "[0,1,2,3].div(2)",
}, },
scale: { scale: {
name: "scale", name: "scale",

View File

@ -35,8 +35,8 @@ Every Topos session is composed of several small scripts. A set of scripts is ca
${makeExample( ${makeExample(
"To take the most out of Topos...", "To take the most out of Topos...",
`// Write your code in multiple scripts. Use all the code buffers! `// Write your code in multiple scripts. Use all the code buffers!
mod(1) :: script(1) beat(1) :: script(1)
div(4) :: mod(.5) :: script(2) flip(4) :: beat(.5) :: script(2)
`, `,
true true
)} )}
@ -44,8 +44,8 @@ div(4) :: mod(.5) :: script(2)
${makeExample( ${makeExample(
"Script execution can become musical too!", "Script execution can become musical too!",
`// You can play your scripts... algorithmically. `// You can play your scripts... algorithmically.
mod(1) :: script([1,3,5].pick()) beat(1) :: script([1,3,5].pick())
div(4) :: mod([.5, .25].div(16)) :: script([5,6,7,8].loop($(2))) flip(4) :: beat([.5, .25].beat(16)) :: script([5,6,7,8].loop($(2)))
`, `,
false false
)} )}

View File

@ -16,17 +16,16 @@ ${makeExample(
bpm(110) bpm(110)
mod(0.125) && sound('sawtooth') beat(0.125) && sound('sawtooth')
.note([60, 62, 63, 67, 70].div(.125) + .note([60, 62, 63, 67, 70].beat(.125) +
[-12,0,12].beat() + [0, 0, 5, 7].bar()) [-12,0,12].beat() + [0, 0, 5, 7].bar())
.sustain(0.1).fmi(0.25).fmh(2).room(0.9) .sustain(0.1).fmi(0.25).fmh(2).room(0.9)
.gain(0.75).cutoff(500 + usine(8) * [500, 1000, 2000].bar()) .gain(0.75).cutoff(500 + usine(8) * [500, 1000, 2000].bar())
.delay(0.5).delayt(0.25).delayfb(0.25) .delay(0.5).delayt(0.25).delayfb(0.25)
.out(); .out();
mod(1) && snd('kick').out(); beat(1) && snd('kick').out();
mod(2) && snd('snare').out(); beat(2) && snd('snare').out();
mod(.5) && snd('hat').out(); beat(.5) && snd('hat').out();
`, `,
true true
)} )}
@ -39,16 +38,16 @@ Topos is an _algorithmic_ sequencer. Topos uses small algorithms to represent mu
${makeExample( ${makeExample(
"Small algorithms for direct musical expression", "Small algorithms for direct musical expression",
` `
mod(1) :: sound(['kick', 'hat', 'snare', 'hat'].div(1)).out() beat(1) :: sound(['kick', 'hat', 'snare', 'hat'].beat(1)).out()
mod(.5) :: sound('jvbass').note(35 + [0,12].beat()).out() beat(.5) :: sound('jvbass').note(35 + [0,12].beat()).out()
mod([0.5, 0.25, 1, 2].div(1)) :: sound('east') beat([0.5, 0.25, 1, 2].beat(1)) :: sound('east')
.room(.5).size(0.5).n(irand(1,5)).out()`, .room(.5).size(0.5).n(irand(1,5)).out()`,
false false
)} )}
${makeExample( ${makeExample(
"Computer music should be immediate and intuitive", "Computer music should be immediate and intuitive",
`mod(.5)::snd('sine') `beat(.5)::snd('sine')
.delay(0.5).delayt(0.25).delayfb(0.7) .delay(0.5).delayt(0.25).delayfb(0.7)
.room(0.8).size(0.8) .room(0.8).size(0.8)
.freq(mouseX()).out()`, .freq(mouseX()).out()`,
@ -58,9 +57,9 @@ ${makeExample(
${makeExample( ${makeExample(
"Making the web less dreadful, one beep at at time", "Making the web less dreadful, one beep at at time",
` `
mod(.5) :: sound('sid').n($(2)).out() beat(.5) :: sound('sid').n($(2)).out()
mod(.25) :: sound('sid').note( beat(.25) :: sound('sid').note(
[34, 36, 41].div(.25) + [[0,-24].pick(),12].beat()) [34, 36, 41].beat(.25) + [[0,-24].pick(),12].beat())
.room(0.9).size(0.9).n(4).out()`, .room(0.9).size(0.9).n(4).out()`,
false false
)} )}

View File

@ -81,10 +81,10 @@ ${makeExample(
"Playing some piano", "Playing some piano",
` `
bpm(80) // Setting a default BPM bpm(80) // Setting a default BPM
mod(.5) && midi(36 + seqbeat(0,12)).sustain(0.02).out() beat(.5) && midi(36 + [0,12].beat()).sustain(0.02).out()
mod(.25) && midi([64, 76].pick()).sustain(0.05).out() beat(.25) && midi([64, 76].pick()).sustain(0.05).out()
mod(.75) && midi(seqbeat(64, 67, 69)).sustain(0.05).out() beat(.75) && midi([64, 67, 69].beat()).sustain(0.05).out()
sometimes() && mod(.25) && midi(seqbeat(64, 67, 69) + 24).sustain(0.05).out() beat(.25) && midi([64, 67, 69].beat() + 24).sustain(0.05).out()
`, `,
true true
)} )}
@ -133,7 +133,7 @@ sysex(0x90, 0x40, 0x7f)
${makeExample( ${makeExample(
"Tic, tac, tic, tac...", "Tic, tac, tic, tac...",
` `
mod(.25) && midi_clock() // Sending clock to MIDI device from the global buffer beat(.25) && midi_clock() // Sending clock to MIDI device from the global buffer
`, `,
true true
)} )}

View File

@ -12,30 +12,30 @@ Music really comes to life when you start playing with algorithmic patterns. The
JavaScript is using [Arrays](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) as a data structure for lists. Topos is extending them with custom methods that allow you to enter softly into a universe of musical patterns. These methods can often be chained to compose a more complex expression: <ic>[1, 2, 3].repeatOdd(5).palindrome().beat()</ic>. JavaScript is using [Arrays](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) as a data structure for lists. Topos is extending them with custom methods that allow you to enter softly into a universe of musical patterns. These methods can often be chained to compose a more complex expression: <ic>[1, 2, 3].repeatOdd(5).palindrome().beat()</ic>.
- <ic>div(division: number)</ic>: this method will return the next value in the list every _n_ pulses. By default, <ic>1</ic> equals to one beat but integer and floating point number values are supported as well. This method is extremely powerful and can be used for many different purposes. Check out the examples. - <ic>beat(division: number)</ic>: this method will return the next value in the list every _n_ pulses. By default, <ic>1</ic> equals to one beat but integer and floating point number values are supported as well. This method is extremely powerful and can be used for many different purposes. Check out the examples.
${makeExample( ${makeExample(
"Light drumming", "Light drumming",
` `
// Every bar, use a different rhythm // Every bar, use a different rhythm
mod([1, 0.75].div(4)) :: sound('cp').out() beat([1, 0.75].beat(4)) :: sound('cp').out()
mod([0.5, 1].div(4)) :: sound('kick').out() beat([0.5, 1].beat(4)) :: sound('kick').out()
mod(2)::snd('snare').shape(.5).out() beat(2)::snd('snare').shape(.5).out()
`, `,
true true
)} )}
${makeExample( ${makeExample(
"Using div to create arpeggios", "Using beat to create arpeggios",
` `
// Arpeggio using pulse divisions // Arpeggio using pulse divisions
mod([.5, .25].div(2)) :: sound('sine') beat([.5, .25].div(2)) :: sound('sine')
.hcutoff(400) .hcutoff(400)
.fmi([1,2].div(8)) .fmi([1,2].beat(8))
.fmh([0.5,0.25,1].div(2)) .fmh([0.5,0.25,1].beat(2))
.note([50,53,57].div(.25) + [12,24].div(2)) .note([50,53,57].beat(.25) + [12,24].beat(2))
.sustain([0.25, 0.5].div(8)) .sustain([0.25, 0.5].beat(8))
.room(0.9).size(0.5) .room(0.9).size(0.5)
.delay(0.25).delayt([0.5,0.25].div(16)) .delay(0.25).delayt([0.5,0.25].beat(16))
.delayfb(0.5) .delayfb(0.5)
.out() .out()
`, `,
@ -44,48 +44,44 @@ mod([.5, .25].div(2)) :: sound('sine')
${makeExample( ${makeExample(
"Cool ambiance", "Cool ambiance",
` `
mod(.5) :: snd(['kick', 'hat'].div(4)).out() beat(.5) :: snd(['kick', 'hat'].beat(4)).out()
mod([2,4].div(2)) :: snd('shaker').delay(.5).delayfb(.75).delayt(0.125).out() beat([2,4].beat(2)) :: snd('shaker').delay(.5).delayfb(.75).delayt(0.125).out()
div(2)::mod(1)::snd('clap').out() flip(2)::beat(1)::snd('clap').out()
div(4)::mod(2)::snd('pad').n(2).shape(.5).orbit(2).room(0.9).size(0.9).release(0.5).out() flip(4)::beat(2)::snd('pad').n(2).shape(.5).orbit(2).room(0.9).size(0.9).release(0.5).out()
`, `,
false false
)} )}
- <ic>beat()</ic>: returns the index of the list corresponding to current beat (with wrapping). This allows you to return a different value for each beat.
- <ic>pulse()</ic>: returns the index of the list corresponding to the current pulse (with wrapping). This method will return a different value for each pulse. - <ic>pulse()</ic>: returns the index of the list corresponding to the current pulse (with wrapping). This method will return a different value for each pulse.
- <ic>bar()</ic>: returns the index of the list corresponding to the current bar (with wrapping). This method will return a different value for each bar. - <ic>bar()</ic>: returns the index of the list corresponding to the current bar (with wrapping). This method will return a different value for each bar.
${makeExample( ${makeExample(
"A simple drumbeat in no time!", "A simple drumbeat in no time!",
` `
mod(1)::sound(['kick', 'hat', 'snare', 'hat'].beat()).out() beat(1)::sound(['kick', 'hat', 'snare', 'hat'].beat()).out()
mod(1.5)::sound(['jvbass', 'clap'].beat()).out() beat(1.5)::sound(['jvbass', 'clap'].beat()).out()
`, `,
true true
)} )}
${makeExample( ${makeExample(
"Using beat, pulse and bar in the same code", "Using beat, pulse and bar in the same code",
`mod(2)::snd('snare').out() `beat(2)::snd('snare').out()
mod([1, 0.5].beat()) :: sound(['bass3'].bar()) beat([1, 0.5].beat()) :: sound(['bass3'].bar())
.freq(100).n([12, 14].bar()) .freq(100).n([12, 14].bar())
.speed([1,2,3].pulse()) .speed([1,2,3].pulse())
.out() .out()
` `
)} )}
- <ic>palindrome()</ic>: Concatenates a list with the same list in reverse. - <ic>palindrome()</ic>: Concatenates a list with the same list in reverse.
${makeExample( ${makeExample(
"Palindrome filter sweep", "Palindrome filter sweep",
` `
mod([1,.5,.25].beat()) :: snd('sine') beat([1,.5,.25].beat()) :: snd('sine')
.freq([100,200,300].div(0.25)) .freq([100,200,300].beat(0.25))
.fmi([1,2,3].palindrome().div(0.5)) .fmi([1,2,3].palindrome().beat(0.5))
.fmh([4, 8].palindrome().beat()) .fmh([4, 8].palindrome().beat())
.cutoff([500,1000,2000,4000].palindrome().beat()) .cutoff([500,1000,2000,4000].palindrome().beat())
.sustain(0.1) .sustain(0.1)
@ -94,7 +90,6 @@ mod([1,.5,.25].beat()) :: snd('sine')
true true
)} )}
- <ic>random(index: number)</ic>: pick a random element in the given list. - <ic>random(index: number)</ic>: pick a random element in the given list.
- <ic>rand(index: number)</ic>: shorter alias for the same method. - <ic>rand(index: number)</ic>: shorter alias for the same method.
- <ic>pick()</ic>: pick a random element in the list. - <ic>pick()</ic>: pick a random element in the list.
@ -103,8 +98,8 @@ mod([1,.5,.25].beat()) :: snd('sine')
${makeExample( ${makeExample(
"Sipping some gasoline at the robot bar", "Sipping some gasoline at the robot bar",
` `
mod(1)::snd('kick').shape(0.5).out() beat(1)::snd('kick').shape(0.5).out()
mod([.5, 1].random() / 2) :: snd( beat([.5, 1].random() / 2) :: snd(
['amencutup', 'synth2'].random()) ['amencutup', 'synth2'].random())
.n(irand(4,10)) .n(irand(4,10))
.cutoff(2000) .cutoff(2000)
@ -116,9 +111,7 @@ mod([.5, 1].random() / 2) :: snd(
${makeExample( ${makeExample(
"Generate a list of random numbers", "Generate a list of random numbers",
` `beat(0.5) && sound('arp').freq([].gen(300,600,10).div(3)).out()`,
mod(0.5) && sound('arp').freq([].gen(300,600,10).div(3)).out()
`,
true true
)} )}
@ -128,7 +121,7 @@ ${makeExample(
"Amen break suffering from data loss", "Amen break suffering from data loss",
` `
// Tweak the value to degrade this amen break even more! // Tweak the value to degrade this amen break even more!
mod(.25)::snd('amencutup').n([1,2,3,4,5,6,7,8,9].degrade(20).loop($(1))).out() beat(.25)::snd('amencutup').n([1,2,3,4,5,6,7,8,9].degrade(20).loop($(1))).out()
`, `,
true true
)} )}
@ -141,7 +134,7 @@ ${makeExample(
"Repeating samples a given number of times", "Repeating samples a given number of times",
` `
// Please take this repeat number down a bit! // Please take this repeat number down a bit!
mod(.25)::sound('amencutup').n([1,2,3,4,5,6,7,8].repeatAll(4).beat()).out() beat(.25)::sound('amencutup').n([1,2,3,4,5,6,7,8].repeatAll(4).beat()).out()
`, `,
true true
)} )}
@ -151,7 +144,7 @@ mod(.25)::sound('amencutup').n([1,2,3,4,5,6,7,8].repeatAll(4).beat()).out()
${makeExample( ${makeExample(
"Don't you know how to count up to 5?", "Don't you know how to count up to 5?",
` `
mod(1) :: sound('numbers').n([1,2,3,4,5].loop($(3, 10, 2))).out() beat(1) :: sound('numbers').n([1,2,3,4,5].loop($(3, 10, 2))).out()
`, `,
true true
)} )}
@ -161,7 +154,7 @@ mod(1) :: sound('numbers').n([1,2,3,4,5].loop($(3, 10, 2))).out()
${makeExample( ${makeExample(
"Shuffling a list for extra randomness", "Shuffling a list for extra randomness",
` `
mod(1) :: sound('numbers').n([1,2,3,4,5].shuffle().loop($(1)).out() beat(1) :: sound('numbers').n([1,2,3,4,5].shuffle().loop($(1)).out()
`, `,
true true
)} )}
@ -171,7 +164,7 @@ mod(1) :: sound('numbers').n([1,2,3,4,5].shuffle().loop($(1)).out()
${makeExample( ${makeExample(
"To make things more complex... here you go", "To make things more complex... here you go",
` `
mod(.5) :: snd('sine') beat(.5) :: snd('sine')
.freq([100, 150, 200, 250, ,300, 400] .freq([100, 150, 200, 250, ,300, 400]
.rotate([1,2,3].bar()) // The list of frequencies is rotating .rotate([1,2,3].bar()) // The list of frequencies is rotating
.beat()) // while being indexed over! .beat()) // while being indexed over!
@ -187,7 +180,7 @@ ${makeExample(
"Demonstrative filtering. Final list is [100, 200]", "Demonstrative filtering. Final list is [100, 200]",
` `
// Remove unique and 100 will repeat four times! // Remove unique and 100 will repeat four times!
mod(1)::snd('sine').sustain(0.1).freq([100,100,100,100,200].unique().beat()).out() beat(1)::snd('sine').sustain(0.1).freq([100,100,100,100,200].unique().beat()).out()
`, `,
true true
)} )}
@ -199,9 +192,5 @@ mod(1)::snd('sine').sustain(0.1).freq([100,100,100,100,200].unique().beat()).out
${makeExample("Simple addition", `[1, 2 ,3].add(2).beat()`, true)} ${makeExample("Simple addition", `[1, 2 ,3].add(2).beat()`, true)}
## Simple patterns
- <ic>divseq(div: number, ...values:any[])</ic>
`; `;
}; };

View File

@ -19,7 +19,7 @@ The <ic>sound</ic> function can take the name of a synthesizer as first argument
${makeExample( ${makeExample(
"Simple synthesizer voice with filter", "Simple synthesizer voice with filter",
` `
mod(.5) && snd('sawtooth') beat(.5) && snd('sawtooth')
.cutoff([2000,500].pick() + usine(.5) * 4000) .cutoff([2000,500].pick() + usine(.5) * 4000)
.resonance(0.9).freq([100,150].pick()) .resonance(0.9).freq([100,150].pick())
.out() .out()
@ -30,10 +30,9 @@ mod(.5) && snd('sawtooth')
${makeExample( ${makeExample(
"Listening to the different waveforms from the sweetest to the harshest", "Listening to the different waveforms from the sweetest to the harshest",
` `
mod(.5) && snd(['sine', 'triangle', 'sawtooth', 'square'].beat()).freq(100).out() beat(.5) && snd(['sine', 'triangle', 'sawtooth', 'square'].beat()).freq(100).out()
.freq(50) .freq(50)
.out() .out()`,
`,
false false
)} )}
@ -41,11 +40,11 @@ mod(.5) && snd(['sine', 'triangle', 'sawtooth', 'square'].beat()).freq(100).out(
${makeExample( ${makeExample(
"Blessed by the square wave", "Blessed by the square wave",
` `
mod(4) :: [100,101].forEach((freq) => sound('square').freq(freq).sustain(0.1).out()) beat(4) :: [100,101].forEach((freq) => sound('square').freq(freq).sustain(0.1).out())
mod(.5) :: [100,101].forEach((freq) => sound('square').freq(freq*2).sustain(0.01).out()) beat(.5) :: [100,101].forEach((freq) => sound('square').freq(freq*2).sustain(0.01).out())
mod([.5, .75, 2].beat()) :: [100,101].forEach((freq) => sound('square') beat([.5, .75, 2].beat()) :: [100,101].forEach((freq) => sound('square')
.freq(freq*4 + usquare(2) * 200).sustain(0.125).out()) .freq(freq*4 + usquare(2) * 200).sustain(0.125).out())
mod(.25) :: sound('square').freq(100*[1,2,4,8].beat()).sustain(0.1).out()`, beat(.25) :: sound('square').freq(100*[1,2,4,8].beat()).sustain(0.1).out()`,
false false
)} )}
@ -53,7 +52,7 @@ mod(.25) :: sound('square').freq(100*[1,2,4,8].beat()).sustain(0.1).out()`,
${makeExample( ${makeExample(
"Ghost carillon", "Ghost carillon",
` `
mod(1/8)::sound('sine') beat(1/8)::sound('sine')
.velocity(rand(0.0, 1.0)) .velocity(rand(0.0, 1.0))
.delay(0.75).delayt(.5) .delay(0.75).delayt(.5)
.sustain(0.4) .sustain(0.4)
@ -76,9 +75,9 @@ The same basic waveforms can take additional methods to switch to a basic two op
${makeExample( ${makeExample(
"80s nostalgia", "80s nostalgia",
` `
mod(.25) && snd('sine') beat(.25) && snd('sine')
.fmi([1,2,4,8].pick()) .fmi([1,2,4,8].pick())
.fmh([1,2,4,8].div(8)) .fmh([1,2,4,8].beat(8))
.freq([100,150].pick()) .freq([100,150].pick())
.sustain(0.1) .sustain(0.1)
.out() .out()
@ -89,9 +88,9 @@ mod(.25) && snd('sine')
${makeExample( ${makeExample(
"Giving some love to weird ratios", "Giving some love to weird ratios",
` `
mod([.5, .25].bar()) :: sound('sine').fm('2.2183:3.18293').sustain(0.05).out() beat([.5, .25].bar()) :: sound('sine').fm('2.2183:3.18293').sustain(0.05).out()
mod([4].bar()) :: sound('sine').fm('5.2183:4.5').sustain(0.05).out() beat([4].bar()) :: sound('sine').fm('5.2183:4.5').sustain(0.05).out()
mod(.5) :: sound('sine') beat(.5) :: sound('sine')
.fmh([1, 1.75].beat()) .fmh([1, 1.75].beat())
.fmi($(1) % 30).orbit(2).room(0.5).out()`, .fmi($(1) % 30).orbit(2).room(0.5).out()`,
false false
@ -101,7 +100,7 @@ mod(.5) :: sound('sine')
${makeExample( ${makeExample(
"Some peace and serenity", "Some peace and serenity",
` `
mod(0.25) :: sound('sine') beat(0.25) :: sound('sine')
.note([60, 67, 70, 72, 77].beat() - [0,12].bar()) .note([60, 67, 70, 72, 77].beat() - [0,12].bar())
.attack(0.2).release(0.5).gain(0.25) .attack(0.2).release(0.5).gain(0.25)
.room(0.9).size(0.8).sustain(0.5) .room(0.9).size(0.8).sustain(0.5)
@ -123,10 +122,10 @@ There is also a more advanced set of parameters you can use to control the envel
${makeExample( ${makeExample(
"FM Synthesis with envelope control", "FM Synthesis with envelope control",
` `
mod(.5) :: sound('sine') beat(.5) :: sound('sine')
.note([50,53,55,57].div(.5) - 12) .note([50,53,55,57].beat(.5) - 12)
.fmi(0.5 + usine(.25) * 1.5) .fmi(0.5 + usine(.25) * 1.5)
.fmh([2,4].div(.125)) .fmh([2,4].beat(.125))
.fmwave('triangle') .fmwave('triangle')
.fmsus(0).fmdec(0.2).out() .fmsus(0).fmdec(0.2).out()
`, `,
@ -142,16 +141,16 @@ ZZfX can be triggered by picking a default ZZfX waveform in the following list:
${makeExample( ${makeExample(
"Picking a waveform", "Picking a waveform",
` `
mod(.5) :: sound(['z_sine', 'z_triangle', 'z_sawtooth', 'z_tan', 'z_noise'].beat()).out() beat(.5) :: sound(['z_sine', 'z_triangle', 'z_sawtooth', 'z_tan', 'z_noise'].beat()).out()
`, `,
true true
)} )}
${makeExample( ${makeExample(
"Minimalist chiptune", "Minimalist chiptune",
` `
mod(.5) :: sound('z_triangle') beat(.5) :: sound('z_triangle')
.note([60, 67, 72, 63, 65, 70].div(.5)) .note([60, 67, 72, 63, 65, 70].beat(.5))
.zrand(0).curve([1,2,3,4].div(1)) .zrand(0).curve([1,2,3,4].beat(1))
.slide(0.01).tremolo(12) .slide(0.01).tremolo(12)
.noise([0,0.5].beat()) .noise([0,0.5].beat())
.decay(0.3).sustain(0) .decay(0.3).sustain(0)
@ -187,7 +186,7 @@ It comes with a set of parameters that can be used to tweak the sound. Don't und
${makeExample( ${makeExample(
"Chaotic Noise source", "Chaotic Noise source",
` `
mod(.25) :: sound('z_tan') beat(.25) :: sound('z_tan')
.note(40).noise(rand(0.0, 1.0)) .note(40).noise(rand(0.0, 1.0))
.pitchJump(84).pitchJumpTime(rand(0.0, 1.0)) .pitchJump(84).pitchJumpTime(rand(0.0, 1.0))
.zcrush([0,1,2,3,4].beat()) .zcrush([0,1,2,3,4].beat())
@ -201,7 +200,7 @@ mod(.25) :: sound('z_tan')
${makeExample( ${makeExample(
"What is happening to me?", "What is happening to me?",
` `
mod(1) :: snd('zzfx').zzfx([ beat(1) :: snd('zzfx').zzfx([
[4.77,,25,,.15,.2,3,.21,,2.4,,,,,,,.23,.35], [4.77,,25,,.15,.2,3,.21,,2.4,,,,,,,.23,.35],
[1.12,,97,.11,.16,.01,4,.77,,,30,.17,,,-1.9,,.01,.67,.2] [1.12,,97,.11,.16,.01,4,.77,,,30,.17,,,-1.9,,.01,.67,.2]
].beat()).out() ].beat()).out()
@ -211,9 +210,9 @@ mod(1) :: snd('zzfx').zzfx([
${makeExample( ${makeExample(
"Les voitures dans le futur", "Les voitures dans le futur",
` `
mod(1) :: sound(['z_triangle', 'z_sine'].pick()) beat(1) :: sound(['z_triangle', 'z_sine'].pick())
.note([60,63,72,75].pick()).tremolo(16) .note([60,63,72,75].pick()).tremolo(16)
.zmod([0, 1/2, 1/8].division(2).pick()) .zmod([0, 1/2, 1/8].div(2).pick())
.attack(0.5).release(0.5).sustain(2).delay(0.8) .attack(0.5).release(0.5).sustain(2).delay(0.8)
.room(0.9).size(0.9) .room(0.9).size(0.9)
.delayt(0.75).delayfb(0.5).out() .delayt(0.75).delayfb(0.5).out()
@ -226,7 +225,7 @@ ${makeExample(
"Designing a sound on the ZzFX website", "Designing a sound on the ZzFX website",
` `
mod(2) :: sound('zzfx').zzfx([3.62,,452,.16,.1,.21,,2.5,,,403,.05,.29,,,,.17,.34,.22,.68]).out() beat(2) :: sound('zzfx').zzfx([3.62,,452,.16,.1,.21,,2.5,,,403,.05,.29,,,,.17,.34,.22,.68]).out()
`, `,
true true
)} )}
@ -246,7 +245,7 @@ Topos can also speak using the [Web Speech API](https://developer.mozilla.org/en
${makeExample( ${makeExample(
"Hello world!", "Hello world!",
` `
mod(4) :: speak("Hello world!") beat(4) :: speak("Hello world!")
`, `,
true true
)} )}
@ -254,7 +253,7 @@ mod(4) :: speak("Hello world!")
${makeExample( ${makeExample(
"Different voices", "Different voices",
` `
mod(2) :: speak("Topos!","fr",irand(0,5)) beat(2) :: speak("Topos!","fr",irand(0,5))
`, `,
true true
)} )}
@ -278,7 +277,7 @@ ${makeExample(
const object = ["happy","sad","tired"].pick() const object = ["happy","sad","tired"].pick()
const sentence = subject+" "+verb+" "+" "+object const sentence = subject+" "+verb+" "+" "+object
mod(6) :: sentence.pitch(0).rate(0).voice([0,2].pick()).speak() beat(6) :: sentence.pitch(0).rate(0).voice([0,2].pick()).speak()
`, `,
true true
)} )}

View File

@ -20,13 +20,13 @@ To change the tempo, use the <ic>bpm(number)</ic> function. The transport is con
Let's study two very simple rhythmic functions, <ic>mod(n: ...number[])</ic> and <ic>onbeat(...n:number[])</ic>. They are both easy to understand and powerful enough to get you to play your first rhythms. Let's study two very simple rhythmic functions, <ic>mod(n: ...number[])</ic> and <ic>onbeat(...n:number[])</ic>. They are both easy to understand and powerful enough to get you to play your first rhythms.
- <ic>mod(...n: number[])</ic>: this function will return true every _n_ pulsations. The value <ic>1</ic> will return <ic>true</ic> at the beginning of each beat. Floating point numbers like <ic>0.5</ic> or <ic>0.25</ic> are also accepted. Multiple values can be passed to <ic>mod</ic> to generate more complex rhythms. - <ic>beat(...n: number[])</ic>: this function will return true every _n_ pulsations. The value <ic>1</ic> will return <ic>true</ic> at the beginning of each beat. Floating point numbers like <ic>0.5</ic> or <ic>0.25</ic> are also accepted. Multiple values can be passed to <ic>beat</ic> to generate more complex rhythms.
${makeExample( ${makeExample(
"Using different mod values", "Using different mod values",
` `
// This code is alternating between different mod values // This code is alternating between different mod values
mod([1,1/2,1/4,1/8].div(2)) :: sound('bd').n(0).out() beat([1,1/2,1/4,1/8].beat(2)) :: sound('bd').n(0).out()
`, `,
true true
)} )}
@ -35,32 +35,32 @@ ${makeExample(
"Some sort of ringtone", "Some sort of ringtone",
` `
let blip = (freq) => {return sound('sine').sustain(0.1).freq(freq)}; let blip = (freq) => {return sound('sine').sustain(0.1).freq(freq)};
mod(1) :: blip(200).out(); beat(1) :: blip(200).out();
mod(1/3) :: blip(400).out(); beat(1/3) :: blip(400).out();
div(3) :: mod(1/6) :: blip(800).out(); flip(3) :: beat(1/6) :: blip(800).out();
mod([1,0.75].div(2)) :: blip([50, 100].div(2)).out(); beat([1,0.75].beat(2)) :: blip([50, 100].beat(2)).out();
`, `,
false false
)} )}
- <ic>modp(...n: number[])</ic>: extreme version of the <ic>mod</ic> function. Instead of being normalised, this function is returning a modulo of real pulses! It can be used to break out of ratios and play with real clock pulses for unexpected results. - <ic>pulse(...n: number[])</ic>: extreme version of the <ic>beat</ic> function. Instead of returning true for every beat, this function is returning true every _n_ clock ticks! It can be used to generate very unexpected results or to sequence by using your arithmetic ninja skills.
${makeExample( ${makeExample(
"Intriguing rhythms", "Intriguing rhythms",
` `
modp(36) :: snd('east') pulse(36) :: snd('east')
.n([2,4].div(1)).out() .n([2,4].beat(1)).out()
modp([12, 36].div(4)) :: snd('east') pulse([12, 36].beat(4)) :: snd('east')
.n([2,4].add(5).div(1)).out() .n([2,4].add(5).beat(1)).out()
`, `,
true true
)} )}
${makeExample( ${makeExample(
"modp is the OG rhythmic function in Topos", "pulse is the OG rhythmic function in Topos",
` `
modp([48, 24, 16].div(4)) :: sound('linnhats').out() pulse([48, 24, 16].beat(4)) :: sound('linnhats').out()
mod(1)::snd('bd').out() pulse(1)::snd('bd').out()
`, `,
false false
)}; )};
@ -82,7 +82,7 @@ ${makeExample(
` `
onbeat(0.5, 1.5, 2, 3, 3.75)::snd('kick').n(2).out() onbeat(0.5, 1.5, 2, 3, 3.75)::snd('kick').n(2).out()
onbeat(2, [1.5, 3].pick(), 4)::snd('snare').n(7).out() onbeat(2, [1.5, 3].pick(), 4)::snd('snare').n(7).out()
mod([.25, 1/8].div(1.5))::snd('hat').n(2) beat([.25, 1/8].beat(1.5))::snd('hat').n(2)
.gain(rand(0.4, 0.7)) .gain(rand(0.4, 0.7))
.pan(usine()).out() .pan(usine()).out()
`, `,
@ -106,10 +106,10 @@ ${makeExample(
"Using oncount to create rhythms with a custom meter", "Using oncount to create rhythms with a custom meter",
` `
bpm(200) bpm(200)
oncount([1,5,9,13],16) :: sound('bd').gain(1.0).out() oncount([1, 5, 9, 13],16) :: sound('bd').gain(1.0).out()
oncount([5,6,13],16) :: sound('cp').gain(0.9).out() oncount([5, 6, 13],16) :: sound('cp').gain(0.9).out()
oncount([2,3,3.5,6,7,10,15],16) :: sound('hh').n(8).gain(0.8).out() oncount([2, 3, 3. 5, 6, 7, 10, 15],16) :: sound('hh').n(8).gain(0.8).out()
oncount([1,4,5,8,9,10,11,12,13,14,15,16],16) :: oncount([1, 4, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16],16) ::
sound('hh').out() sound('hh').out()
`, `,
true true
@ -124,8 +124,8 @@ We included a bunch of popular rhythm generators in Topos such as the euclidian
${makeExample( ${makeExample(
"Classic euclidian club music patterns", "Classic euclidian club music patterns",
` `
mod(.5) && euclid($(1), 5, 8) && snd('kick').out() beat(.5) && euclid($(1), 5, 8) && snd('kick').out()
mod(.5) && euclid($(2), 2, 8) && snd('sd').out() beat(.5) && euclid($(2), 2, 8) && snd('sd').out()
`, `,
true true
)} )}
@ -134,9 +134,9 @@ ${makeExample(
"And now for more interesting rhythmic constructions", "And now for more interesting rhythmic constructions",
` `
bpm(145); // Setting a faster BPM bpm(145); // Setting a faster BPM
mod(.5) && euclid($(1), 5, 8) :: sound('bd').out() beat(.5) && euclid($(1), 5, 8) :: sound('bd').out()
mod(.5) && euclid($(2), [1,0].div(8), 8) :: sound('sd').out() beat(.5) && euclid($(2), [1,0].beat(8), 8) :: sound('sd').out()
mod(.5) && euclid($(6), [6,7].div(8), 8) :: sound('hh').out() beat(.5) && euclid($(6), [6,7].beat(8), 8) :: sound('hh').out()
`, `,
false false
)} )}
@ -144,10 +144,10 @@ mod(.5) && euclid($(6), [6,7].div(8), 8) :: sound('hh').out()
${makeExample( ${makeExample(
"Adding more rhythmic density", "Adding more rhythmic density",
` `
mod(.5) && euclid($(1), 5, 9) && snd('kick').out() beat(.5) && euclid($(1), 5, 9) && snd('kick').out()
mod(.5) && euclid($(2), 2, 3, 1) && snd('east').end(0.5).n(5).out() beat(.5) && euclid($(2), 2, 3, 1) && snd('east').end(0.5).n(5).out()
mod(.5) && euclid($(3), 6, 9, 1) && snd('east').end(0.5).n(5).freq(200).out() beat(.5) && euclid($(3), 6, 9, 1) && snd('east').end(0.5).n(5).freq(200).out()
mod(.25) && euclid($(4), 7, 9, 1) && snd('hh').out() beat(.25) && euclid($(4), 7, 9, 1) && snd('hh').out()
`, `,
false false
)} )}
@ -179,16 +179,14 @@ rhythm(speed, 7, 12) :: snd('east').n(9).out()
true true
)} )}
- <ic>bin(iterator: number, n: number): boolean</ic>: a binary rhythm generator. It transforms the given number into its binary representation (_e.g_ <ic>34</ic> becomes <ic>100010</ic>). It then returns a boolean value based on the iterator in order to generate a rhythm. - <ic>bin(iterator: number, n: number): boolean</ic>: a binary rhythm generator. It transforms the given number into its binary representation (_e.g_ <ic>34</ic> becomes <ic>100010</ic>). It then returns a boolean value based on the iterator in order to generate a rhythm.
- <ic>binrhythm(divisor: number, n: number): boolean: boolean</ic>: iterator-less version of the binary rhythm generator. - <ic>binrhythm(divisor: number, n: number): boolean: boolean</ic>: iterator-less version of the binary rhythm generator.
${makeExample( ${makeExample(
"Change the integers for a surprise rhythm!", "Change the integers for a surprise rhythm!",
` `
mod(.5) && bin($(1), 34) && snd('kick').out() beat(.5) && bin($(1), 34) && snd('kick').out()
mod(.5) && bin($(2), 48) && snd('sd').out() beat(.5) && bin($(2), 48) && snd('sd').out()
`, `,
true true
)} )}
@ -205,8 +203,8 @@ binrhythm(.5, 18) && snd('sd').out()
${makeExample( ${makeExample(
"Calling 911", "Calling 911",
` `
mod(.5) && bin($(1), 911) && snd('subroc3d').n($(2)).delay(0.5).delayt(0.25).end(0.5).out() beat(.5) && bin($(1), 911) && snd('subroc3d').n($(2)).delay(0.5).delayt(0.25).end(0.5).out()
mod(.5) && sound('less').n(irand(1, 10)).out() beat(.5) && sound('less').n(irand(1, 10)).out()
`, `,
false false
)} )}
@ -214,9 +212,9 @@ mod(.5) && sound('less').n(irand(1, 10)).out()
${makeExample( ${makeExample(
"Playing around with simple numbers", "Playing around with simple numbers",
` `
mod(.5) && bin($(1), [123, 456, 789].div(4)) beat(.5) && bin($(1), [123, 456, 789].beat(4))
&& snd('tabla').n($(2)).delay(0.5).delayt(0.25).out() && snd('tabla').n($(2)).delay(0.5).delayt(0.25).out()
mod(1) && sound('kick').shape(0.5).out() beat(1) && sound('kick').shape(0.5).out()
`, `,
false false
)} )}
@ -226,9 +224,9 @@ If you don't find it spicy enough, you can add some more probabilities to your r
${makeExample( ${makeExample(
"Probablistic drums in one line!", "Probablistic drums in one line!",
` `
prob(60)::mod(.5) && euclid($(1), 5, 8) && snd('kick').out() prob(60)::beat(.5) && euclid($(1), 5, 8) && snd('kick').out()
prob(60)::mod(.5) && euclid($(2), 3, 8) && snd('sd').out() prob(60)::beat(.5) && euclid($(2), 3, 8) && snd('sd').out()
prob(80)::mod(.5) && sound('hh').out() prob(80)::beat(.5) && sound('hh').out()
`, `,
true true
)} )}
@ -244,16 +242,16 @@ ${makeExample(
"Jumping back and forth in time", "Jumping back and forth in time",
` `
// Obscure Shenanigans - Bubobubobubo // Obscure Shenanigans - Bubobubobubo
mod([1/4,1/8,1/16].div(8)):: sound('sine') beat([1/4,1/8,1/16].beat(8)):: sound('sine')
.freq([100,50].div(16) + 50 * ($(1)%10)) .freq([100,50].beat(16) + 50 * ($(1)%10))
.gain(0.5).room(0.9).size(0.9) .gain(0.5).room(0.9).size(0.9)
.sustain(0.1).out() .sustain(0.1).out()
mod(1) :: sound('kick').out() beat(1) :: sound('kick').out()
mod(2) :: sound('dr').n(5).out() beat(2) :: sound('dr').n(5).out()
div(3) :: mod([.25,.5].div(.5)) :: sound('dr') div(3) :: beat([.25,.5].beat(.5)) :: sound('dr')
.n([8,9].pick()).gain([.8,.5,.25,.1,.0].div(.25)).out() .n([8,9].pick()).gain([.8,.5,.25,.1,.0].beat(.25)).out()
// Time is elastic now! // Time is elastic now!
mod(.25) :: warp([12, 48, 24, 1, 120, 30].pick()) beat(.25) :: warp([12, 48, 24, 1, 120, 30].pick())
`, `,
true true
)} )}
@ -264,18 +262,18 @@ ${makeExample(
"Jumping back and forth with beats", "Jumping back and forth with beats",
` `
// Resonance bliss - Bubobubobubo // Resonance bliss - Bubobubobubo
mod(.25)::snd('arpy') beat(.25)::snd('arpy')
.note(30 + [0,3,7,10].beat()) .note(30 + [0,3,7,10].beat())
.cutoff(usine(.5) * 5000).resonance(10).gain(0.3) .cutoff(usine(.5) * 5000).resonance(10).gain(0.3)
.end(0.8).room(0.9).size(0.9).n(0).out(); .end(0.8).room(0.9).size(0.9).n(0).out();
mod([.25,.125].div(2))::snd('arpy') beat([.25,.125].beat(2))::snd('arpy')
.note(30 + [0,3,7,10].beat()) .note(30 + [0,3,7,10].beat())
.cutoff(usine(.5) * 5000).resonance(20).gain(0.3) .cutoff(usine(.5) * 5000).resonance(20).gain(0.3)
.end(0.8).room(0.9).size(0.9).n(3).out(); .end(0.8).room(0.9).size(0.9).n(3).out();
mod(.5) :: snd('arpy').note( beat(.5) :: snd('arpy').note(
[30, 33, 35].repeatAll(4).div(1) - [12,0].div(0.5)).out() [30, 33, 35].repeatAll(4).beat(1) - [12,0].beat(0.5)).out()
// Comment me to stop warping! // Comment me to stop warping!
mod(1) :: beat_warp([2,4,5,10,11].pick()) beat(1) :: beat_warp([2,4,5,10,11].pick())
`, `,
true true
)} )}
@ -284,13 +282,13 @@ mod(1) :: beat_warp([2,4,5,10,11].pick())
Now you know how to play some basic rhythmic music but you are a bit stuck in a one-bar long loop. Let's see how we can think about time flowing on longer periods. The functions you are going to learn now are _very fundamental_ and all the fun comes from mastering them. **Read and experiment a lot with the following examples**. Now you know how to play some basic rhythmic music but you are a bit stuck in a one-bar long loop. Let's see how we can think about time flowing on longer periods. The functions you are going to learn now are _very fundamental_ and all the fun comes from mastering them. **Read and experiment a lot with the following examples**.
- <ic>div(n: number, ratio: number = 50)</ic>: the <ic>div</ic> method is a temporal switch. If the value <ic>2</ic> is given, the function will return <ic>true</ic> for two beats and <ic>false</ic> for two beats. There are multiple ways to use it effectively. You can pass an integer or a floating point number. - <ic>flip(n: number, ratio: number = 50)</ic>: the <ic>flip</ic> method is a temporal switch. If the value <ic>2</ic> is given, the function will return <ic>true</ic> for two beats and <ic>false</ic> for two beats. There are multiple ways to use it effectively. You can pass an integer or a floating point number.
- <ic>ratio: number = 50</ic>: this argument is ratio expressed in %. It determines how much of the period should be true or false. A ratio of <ic>75</ic> means that 75% of the period will be true. A ratio of <ic>25</ic> means that 25% of the period will be true. - <ic>ratio: number = 50</ic>: this argument is ratio expressed in %. It determines how much of the period should be true or false. A ratio of <ic>75</ic> means that 75% of the period will be true. A ratio of <ic>25</ic> means that 25% of the period will be true.
${makeExample( ${makeExample(
"Two beats of silence, two beats of playing", "Two beats of silence, two beats of playing",
` `
div(4) :: mod(1) :: snd('kick').out() flip(4) :: beat(1) :: snd('kick').out()
`, `,
true true
)} )}
@ -298,9 +296,9 @@ div(4) :: mod(1) :: snd('kick').out()
${makeExample( ${makeExample(
"Clapping on the edge", "Clapping on the edge",
` `
div(2.5, 10) :: mod(.25) :: snd('cp').out() flip(2.5, 10) :: beat(.25) :: snd('cp').out()
div(2.5, 75) :: mod(.25) :: snd('click').speed(2).end(0.2).out() flip(2.5, 75) :: beat(.25) :: snd('click').speed(2).end(0.2).out()
div(2.5) :: mod(.5) :: snd('bd').out() flip(2.5) :: mod(.5) :: snd('bd').out()
`, `,
false false
)} )}
@ -308,35 +306,35 @@ div(2.5) :: mod(.5) :: snd('bd').out()
${makeExample( ${makeExample(
"Good old true and false", "Good old true and false",
` `
if (div(4, 75)) { if (flip(4, 75)) {
mod(1) :: snd('kick').out() beat(1) :: snd('kick').out()
} else { } else {
mod(.5) :: snd('snare').out() beat(.5) :: snd('snare').out()
} }
`, `,
true true
)} )}
<ic>div</ic> is extremely powerful and is used internally for a lot of other Topos functions. You can also use it to think about **longer durations** spanning over multiple bars. <ic>flip</ic> is extremely powerful and is used internally for a lot of other Topos functions. You can also use it to think about **longer durations** spanning over multiple bars.
${makeExample( ${makeExample(
"Clunky algorithmic rap music", "Clunky algorithmic rap music",
` `
// Rap God VS Lil Wild -- Adel Faure // Rap God VS Lil Wild -- Adel Faure
if (div(16)) { if (flip(16)) {
// Playing this part for two bars // Playing this part for two bars
mod(1.5)::snd('kick').out() beat(1.5)::snd('kick').out()
mod(2)::snd('snare').out() beat(2)::snd('snare').out()
mod(.5)::snd('hh').out() beat(.5)::snd('hh').out()
} else { } else {
// Now adding some birds and tablas // Now adding some birds and tablas
mod(1.5)::snd('kick').out() beat(1.5)::snd('kick').out()
mod(2)::snd('snare').out() beat(2)::snd('snare').out()
mod(.5)::snd('hh').out() beat(.5)::snd('hh').out()
mod(.5)::snd('tabla').speed([1,2].pick()).end(0.5).out() beat(.5)::snd('tabla').speed([1,2].pick()).end(0.5).out()
mod(2.34)::snd('birds').n(irand(1,10)) beat(2.34)::snd('birds').n(irand(1,10))
.delay(0.5).delaytime(0.5).delayfb(0.25).out() .delay(0.5).delaytime(0.5).delayfb(0.25).out()
mod(.5)::snd('diphone').end(0.5).n([1,2,3,4].pick()).out() beat(.5)::snd('diphone').end(0.5).n([1,2,3,4].pick()).out()
} }
`, `,
true true
@ -347,7 +345,7 @@ You can use it everywhere to spice things up, including as a method parameter pi
${makeExample( ${makeExample(
"div is great for parameter variation", "div is great for parameter variation",
` `
mod(.5)::snd(div(4) ? 'kick' : 'hat').out() beat(.5)::snd(flip(4) ? 'kick' : 'hat').out()
`, `,
true true
)} )}
@ -357,8 +355,8 @@ mod(.5)::snd(div(4) ? 'kick' : 'hat').out()
${makeExample( ${makeExample(
"Thinking music over bars", "Thinking music over bars",
` `
divbar(2)::mod(1)::snd('kick').out() divbar(2)::beat(1)::snd('kick').out()
divbar(3)::mod(.5)::snd('hat').out() divbar(3)::beat(.5)::snd('hat').out()
`, `,
true true
)} )}
@ -366,8 +364,8 @@ ${makeExample(
"Alternating over four bars", "Alternating over four bars",
` `
divbar(2) divbar(2)
? mod(.5) && snd(['kick', 'hh'].div(1)).out() ? beat(.5) && snd(['kick', 'hh'].beat(1)).out()
: mod(.5) && snd(['east', 'snare'].div(1)).out() : beat(.5) && snd(['east', 'snare'].beat(1)).out()
`, `,
false false
)}; )};
@ -379,13 +377,13 @@ ${makeExample(
"Using onbar for filler drums", "Using onbar for filler drums",
` `
// Only play on the fourth bar of a four bar cycle. // Only play on the fourth bar of a four bar cycle.
onbar(4, 4)::mod(.5)::snd('hh').out(); onbar(4, 4)::beat(.5)::snd('hh').out();
// Here comes a longer version using JavaScript normal control flow // Here comes a longer version using JavaScript normal control flow
if (onbar([4, 1], 3)) { if (onbar([4, 1], 3)) {
mod(1)::snd('kick').out(); beat(1)::snd('kick').out();
} else { } else {
mod(.5)::snd('sd').out(); beat(.5)::snd('sd').out();
} }
`, `,
true true
@ -401,13 +399,13 @@ To make a beat, you need a certain number of time grains or **pulses**. The **pu
Every script can access the current time by using the following functions: Every script can access the current time by using the following functions:
- <ic>bar(n: number)</ic>: returns the current bar since the origin of time. - <ic>cbar(n: number)</ic>: returns the current bar since the origin of time.
- <ic>beat(n: number)</ic>: returns the current beat since the beginning of the bar. - <ic>cbeat(n: number)</ic>: returns the current beat since the beginning of the bar.
- <ic>ebeat()</ic>: returns the current beat since the origin of time (counting from 1). - <ic>ebeat()</ic>: returns the current beat since the origin of time (counting from 1).
- <ic>pulse()</ic>: returns the current bar since the origin of the beat. - <ic>cpulse()</ic>: returns the current bar since the origin of the beat.
- <ic>ppqn()</ic>: returns the current **PPQN** (see above). - <ic>ppqn()</ic>: returns the current **PPQN** (see above).
@ -420,14 +418,14 @@ These values are **extremely useful** to craft more complex syntax or to write m
${makeExample( ${makeExample(
"Manual mode: using time primitives!", "Manual mode: using time primitives!",
` `
if((bar() % 4) > 1) { if((cbar() % 4) > 1) {
mod(1) && sound('kick').out() beat(1) && sound('kick').out()
rarely() && mod(.5) && sound('sd').out() rarely() && beat(.5) && sound('sd').out()
mod(.5) && sound('jvbass').freq(500).out() beat(.5) && sound('jvbass').freq(500).out()
} else { } else {
mod(.5) && sound('hh').out() beat(.5) && sound('hh').out()
mod(.75) && sound('cp').out() beat(.75) && sound('cp').out()
mod(.5) && sound('jvbass').freq(250).out() beat(.5) && sound('jvbass').freq(250).out()
} }
`, `,
true true

View File

@ -42,7 +42,7 @@ z1('s 0 1 2 3 4 5 6 7 8 9').sound('pluck').release(0.1).sustain(0.25).out()
${makeExample( ${makeExample(
"Escaped pitches using curly brackets", "Escaped pitches using curly brackets",
` `
let pattern = div(4) ? z1('s _ _ 0 0 {9 11}') : z1('s _ 0 0 {10 12}'); let pattern = flip(4) ? z1('s _ _ 0 0 {9 11}') : z1('s _ 0 0 {10 12}');
pattern.sound('pluck').sustain(0.1).room(0.9).out(); pattern.sound('pluck').sustain(0.1).room(0.9).out();
`, `,
false false
@ -51,7 +51,7 @@ pattern.sound('pluck').sustain(0.1).room(0.9).out();
${makeExample( ${makeExample(
"Durations using letters and floating point numbers", "Durations using letters and floating point numbers",
` `
div(8) ? z1('s 0 e 1 q 2 h 3 w 4').sound('sine').scale("locrian").out() flip(8) ? z1('s 0 e 1 q 2 h 3 w 4').sound('sine').scale("locrian").out()
: z1('0.125 0 0.25 2').sound('sine').scale("locrian").out() : z1('0.125 0 0.25 2').sound('sine').scale("locrian").out()
`, `,
false false
@ -61,8 +61,8 @@ ${makeExample(
"Disco was invented thanks to Ziffers", "Disco was invented thanks to Ziffers",
` `
z1('e _ _ 0 ^ 0 _ 0 ^ 0').sound('jvbass').out() z1('e _ _ 0 ^ 0 _ 0 ^ 0').sound('jvbass').out()
mod(1)::snd('bd').out(); mod(2)::snd('sd').out() beat(1)::snd('bd').out(); beat(2)::snd('sd').out()
mod(3) :: snd('cp').room(0.5).size(0.5).orbit(2).out() beat(3) :: snd('cp').room(0.5).size(0.5).orbit(2).out()
`, `,
false false
)} )}
@ -131,7 +131,7 @@ ${makeExample(
"Transposing chords", "Transposing chords",
` `
z1('q Fmaj Amin Dmin Cmaj Cdim') z1('q Fmaj Amin Dmin Cmaj Cdim')
.key(["F3","E3","D3","E3"].div(3)) .key(["F3","E3","D3","E3"].beat(3))
.sound('sawtooth').out() .sound('sawtooth').out()
` `
)} )}
@ -161,7 +161,7 @@ z1("s (0,8) 0 0 (0,5) 0 0").sound('sine')
.scale('minor').fmi(2).fmh(2).room(0.5) .scale('minor').fmi(2).fmh(2).room(0.5)
.size(0.5).sustain(0.1) .delay(0.5) .size(0.5).sustain(0.1) .delay(0.5)
.delay(0.125).delayfb(0.25).out(); .delay(0.125).delayfb(0.25).out();
mod(.5) :: snd(['kick', 'hat'].div(.5)).out() beat(.5) :: snd(['kick', 'hat'].beat(.5)).out()
`, `,
true true
)} )}
@ -172,17 +172,17 @@ Ziffers supports all the keys and scales. Keys can be defined by using [scientif
| Scale name | Intervals | | Scale name | Intervals |
|------------|------------------------| |------------|------------------------|
| Lydian | <ic>2221221</ic> | | Lydian | <ic>2221221</ic> |
| Mixolydian | <ic>2212212</ic> | | Mixolydian | <ic>2212212</ic> |
| Aeolian  | <ic>2122122</ic> | | Aeolian | <ic>2122122</ic> |
| Locrian | <ic>1221222</ic> | | Locrian | <ic>1221222</ic> |
| Ionian | <ic>2212221</ic> | | Ionian | <ic>2212221</ic> |
| Dorian | <ic>2122212</ic> | | Dorian | <ic>2122212</ic> |
| Phrygian | <ic>1222122</ic> | | Phrygian | <ic>1222122</ic> |
| Soryllic | <ic>11122122</ic>| | Soryllic | <ic>11122122</ic>|
| Modimic | <ic>412122</ic> | | Modimic | <ic>412122</ic> |
| Ionalian   | <ic>1312122</ic> | | Ionalian | <ic>1312122</ic> |
| ... | And it goes on for **1490** scales | | ... | And it goes on for **1490** scales |
${makeExample( ${makeExample(
"What the hell is the Modimic scale?", "What the hell is the Modimic scale?",
@ -191,7 +191,7 @@ z1("s (0,8) 0 0 (0,5) 0 0").sound('sine')
.scale('modimic').fmi(2).fmh(2).room(0.5) .scale('modimic').fmi(2).fmh(2).room(0.5)
.size(0.5).sustain(0.1) .delay(0.5) .size(0.5).sustain(0.1) .delay(0.5)
.delay(0.125).delayfb(0.25).out(); .delay(0.125).delayfb(0.25).out();
mod(.5) :: snd(['kick', 'hat'].div(.5)).out() beat(.5) :: snd(['kick', 'hat'].beat(.5)).out()
`, `,
true true
)} )}
@ -205,16 +205,16 @@ You can also use more traditional <a href="https://ianring.com/musictheory/scale
| Scale name | Intervals | | Scale name | Intervals |
|------------|------------------------| |------------|------------------------|
| Major | <ic>2212221</ic> | | Major | <ic>2212221</ic> |
| Minor | <ic>2122122</ic> | | Minor | <ic>2122122</ic> |
| Minor pentatonic  | <ic>32232</ic> | | Minor pentatonic | <ic>32232</ic> |
| Harmonic minor | <ic>2122131</ic>| | Harmonic minor | <ic>2122131</ic>|
| Harmonic major | <ic>2212131</ic>| | Harmonic major | <ic>2212131</ic>|
| Melodic minor | <ic>2122221</ic>| | Melodic minor | <ic>2122221</ic>|
| Melodic major | <ic>2212122</ic>| | Melodic major | <ic>2212122</ic>|
| Whole | <ic>222222</ic> | | Whole | <ic>222222</ic> |
| Blues minor | <ic>321132</ic> | | Blues minor | <ic>321132</ic> |
| Blues major | <ic>211323</ic> | | Blues major | <ic>211323</ic> |
${makeExample( ${makeExample(
@ -224,7 +224,7 @@ z1("s (0,8) 0 0 (0,5) 0 0").sound('sine')
.scale('blues minor').fmi(2).fmh(2).room(0.5) .scale('blues minor').fmi(2).fmh(2).room(0.5)
.size(0.5).sustain(0.25).delay(0.25) .size(0.5).sustain(0.25).delay(0.25)
.delay(0.25).delayfb(0.5).out(); .delay(0.25).delayfb(0.5).out();
mod(1, 1.75) :: snd(['kick', 'hat'].div(1)).out() beat(1, 1.75) :: snd(['kick', 'hat'].beat(1)).out()
`, `,
true true
)} )}
@ -242,7 +242,7 @@ z1("s ^ (0,8) 0 0 _ (0,5) 0 0").sound('sine')
.scale('17/16 9/8 6/5 5/4 4/3 11/8 3/2 13/8 5/3 7/4 15/8 2/1').fmi(2).fmh(2).room(0.5) .scale('17/16 9/8 6/5 5/4 4/3 11/8 3/2 13/8 5/3 7/4 15/8 2/1').fmi(2).fmh(2).room(0.5)
.size(0.5).sustain(0.15).delay(0.1) .size(0.5).sustain(0.15).delay(0.1)
.delay(0.25).delayfb(0.5).out(); .delay(0.25).delayfb(0.5).out();
mod(1, 1.75) :: snd(['kick', 'hat'].div(1)).out() beat(1, 1.75) :: snd(['kick', 'hat'].beat(1)).out()
`, `,
true true
)} )}
@ -258,7 +258,7 @@ ${makeExample(
` `
z0('w 0 8').sound('peri').out() z0('w 0 8').sound('peri').out()
z1('e 0 4 5 9').sound('bell').out() z1('e 0 4 5 9').sound('bell').out()
`, `,
true true
)} )}
@ -267,7 +267,7 @@ ${makeExample(
` `
z1('w 0 5').sound('pluck').release(0.1).sustain(0.25).out() 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() z2('q 6 3').wait(z1).sound('sine').release(0.16).sustain(0.55).out()
`, `,
true true
)} )}
@ -276,13 +276,10 @@ ${makeExample(
` `
z1('w __ 0 5 9 3').sound('bin').out() z1('w __ 0 5 9 3').sound('bin').out()
z2('q __ 4 2 e 6 3 q 6').sync(z1).sound('east').out() z2('q __ 4 2 e 6 3 q 6').sync(z1).sound('east').out()
`, `,
true true
)} )}
## Examples ## Examples
- Basic notation - Basic notation