From 15a293b49a48fdb995be26302d282f85aad3c6b4 Mon Sep 17 00:00:00 2001 From: Raphael Forment Date: Fri, 6 Oct 2023 14:44:29 +0200 Subject: [PATCH] Rebalancing documentation, will figure the rest later --- index.html | 3 + src/Documentation.ts | 6 + src/documentation/functions.ts | 210 ----------------------------- src/documentation/lfos.ts | 58 ++++++++ src/documentation/probabilities.ts | 98 ++++++++++++++ src/documentation/variables.ts | 80 +++++++++++ src/main.ts | 3 + 7 files changed, 248 insertions(+), 210 deletions(-) create mode 100644 src/documentation/lfos.ts create mode 100644 src/documentation/probabilities.ts create mode 100644 src/documentation/variables.ts diff --git a/index.html b/index.html index 3b4f2e3..370f4d1 100644 --- a/index.html +++ b/index.html @@ -146,6 +146,9 @@

Learning

Patterns

Patterns

+

Variables

+

LFOs

+

Probabilities

Chaining

Functions

Ziffers

diff --git a/src/Documentation.ts b/src/Documentation.ts index c3d30fb..6a35fbf 100644 --- a/src/Documentation.ts +++ b/src/Documentation.ts @@ -12,6 +12,9 @@ import { sound } from "./documentation/engine"; import { shortcuts } from "./documentation/keyboard"; import { patterns } from "./documentation/patterns"; import { functions } from "./documentation/functions"; +import { variables } from "./documentation/variables"; +import { probabilities } from "./documentation/probabilities"; +import { lfos } from "./documentation/lfos"; import { ziffers } from "./documentation/ziffers"; import { reference } from "./documentation/reference"; import { synths } from "./documentation/synths"; @@ -64,6 +67,9 @@ export const documentation_factory = (application: Editor) => { patterns: patterns(application), ziffers: ziffers(application), midi: midi(application), + lfos: lfos(application), + variables: variables(application), + probabilities: probabilities(application), functions: functions(application), reference: reference(), shortcuts: shortcuts(), diff --git a/src/documentation/functions.ts b/src/documentation/functions.ts index f14a6c5..7315424 100644 --- a/src/documentation/functions.ts +++ b/src/documentation/functions.ts @@ -6,75 +6,6 @@ export const functions = (application: Editor): string => { return ` # Functions -## Global Shared Variables - -By default, each script is independant from each other. Scripts live in their own bubble and you cannot get or set variables affecting a script from any other script. **However**, everybody knows that global variables are cool and should be used everywhere. This is an incredibely powerful tool to use for radically altering a composition in a few lines of code. - -- variable(a: number | string, b?: any): if only one argument is provided, the value of the variable will be returned through its name, denoted by the first argument. If a second argument is used, it will be saved as a global variable under the name of the first argument. - - delete_variable(name: string): deletes a global variable from storage. - - clear_variables(): clear **ALL** variables. **This is a destructive operation**! - -**Note:** since this example is running in the documentation, we cannot take advantage of the multiple scripts paradigm. Try to send a variable from the global file to the local file n°6. - -${makeExample( - "Setting a global variable", - ` -v('my_cool_variable', 2) -`, - true - )} - -${makeExample( - "Getting that variable back and printing!", - ` -// Note that we just use one argument -log(v('my_cool_variable')) -`, - false - )} - - -## Counter and iterators - -You will often need to use iterators and/or counters to index over data structures (getting a note from a list of notes, etc...). There are functions ready to be used for this. Each script also comes with its own iterator that you can access using the i variable. **Note:** the script iteration count is **not** resetted between sessions. It will continue to increase the more you play, even if you just picked up an old project. - -- counter(name: number | string, limit?: number, step?: number): reads the value of the counter name. You can also call this function using the dollar symbol: $. - - limit?: counter upper limit before wrapping up. - - step?: incrementor. If step is 2, the iterator will go: 0, 2, 4, 6, etc... - -- drunk(n?: number): returns the value of the internal drunk walk counter. This iterator will sometimes go up, sometimes go down. It comes with companion functions that you can use to finetune its behavior. - - drunk_max(max: number): sets the maximum value. - - drunk_min(min: number): sets the minimum value. - - drunk_wrap(wrap: boolean): whether to wrap the drunk walk to 0 once the upper limit is reached or not. - -**Note:** Counters also come with a secret syntax. They can be called with the **$** symbol! - -${makeExample( - "Iterating over a list of samples using a counter", - ` -rhythm(.25, 6, 8) :: sound('dr').n($(1)).end(.25).out() -`, - true - )} - -${makeExample( - "Using a more complex counter", - ` -// Limit is 20, step is 5 -rhythm(.25, 6, 8) :: sound('dr').n($(1, 20, 5)).end(.25).out() -`, - false - )} - -${makeExample( - "Calling the drunk mechanism", - ` -// Limit is 20, step is 5 -rhythm(.25, 6, 8) :: sound('dr').n(drunk()).end(.25).out() -`, - false - )} - ## Scripts You can control scripts programatically. This is the core concept of Topos after all! @@ -99,147 +30,6 @@ beat(1) :: script(1, 3, 5) false )} - - -## Low Frequency Oscillators - -Low Frequency Oscillators (_LFOs_) are an important piece in any digital audio workstation or synthesizer. Topos implements some basic waveforms you can play with to automatically modulate your paremeters. - -- sine(freq: number = 1, offset: number= 0): number: returns a sinusoïdal oscillation between -1 and 1. -- usine(freq: number = 1, offset: number= 0): number: returns a sinusoïdal oscillation between 0 and 1. The u stands for _unipolar_. - -${makeExample( - "Modulating the speed of a sample player using a sine LFO", - `beat(.25) && snd('cp').speed(1 + usine(0.25) * 2).out()`, - true - )}; - -- triangle(freq: number = 1, offset: number= 0): number: returns a triangle oscillation between -1 and 1. -- utriangle(freq: number = 1, offset: number= 0): number: returns a triangle oscillation between 0 and 1. The u stands for _unipolar_. - - -${makeExample( - "Modulating the speed of a sample player using a triangle LFO", - `beat(.25) && snd('cp').speed(1 + utriangle(0.25) * 2).out()`, - true - )} - -- saw(freq: number = 1, offset: number= 0): number: returns a sawtooth-like oscillation between -1 and 1. -- usaw(freq: number = 1, offset: number= 0): number: returns a sawtooth-like oscillation between 0 and 1. The u stands for _unipolar_. - - -${makeExample( - "Modulating the speed of a sample player using a saw LFO", - `beat(.25) && snd('cp').speed(1 + usaw(0.25) * 2).out()`, - true - )} - -- square(freq: number = 1, offset: number= 0, duty: number = .5): number: returns a square wave oscillation between -1 and 1. You can also control the duty cycle using the duty parameter. -- usquare(freq: number = 1, offset: number= 0, duty: number = .5): number: returns a square wave oscillation between 0 and 1. The u stands for _unipolar_. You can also control the duty cycle using the duty parameter. - -${makeExample( - "Modulating the speed of a sample player using a square LFO", - `beat(.25) && snd('cp').speed(1 + usquare(0.25, 0, 0.25) * 2).out()`, - true - )}; - -- noise(): returns a random value between -1 and 1. - -${makeExample( - "Modulating the speed of a sample player using noise", - `beat(.25) && snd('cp').speed(1 + noise() * 2).out()`, - true - )}; - -## Probabilities - -There are some simple functions to play with probabilities. - -- rand(min: number, max:number): returns a random number between min and max. Shorthand _r()_. -- irand(min: number, max:number): returns a random integer between min and max. Shorthands _ir()_ or _rI()_. - -${makeExample( - "Bleep bloop, what were you expecting?", - ` -rhythm(0.125, 10, 16) :: sound('sid').n(4).note(50 + irand(50, 62) % 8).out() -`, - true - )} - - -- prob(p: number): return true _p_% of time, false in other cases. -- toss(): throwing a coin. Head (true) or tails (false). - - -${makeExample( - "The Teletype experience!", - ` -prob(50) :: script(1); -prob(60) :: script(2); -prob(80) :: script(toss() ? script(3) : script(4)) -`, - true - )} - -- seed(val: number|string): sets the seed of the random number generator. You can use a number or a string. The same seed will always return the same sequence of random numbers. - - -## Chance operators - -Chance operators returning a boolean value are also available. They are super important because they also exist for another mechanism called **chaining**. Checkout the **Chaining** page to learn how to use them in different contexts! - -By default chance operators will be evaluated 48 times within a beat. You can change this value by providing a number of beats as an argument. Default value is 1. Change operators can also be used to randomly apply other operators. - -- odds(n: number, beats?: number): returns true for every n (odds) (eg. 1/4 = 0.25) in given number of beats -- never(beats?: number): returns false. Can be handy when switching between different probabilities -- almostNever(beats?: number): returns true 0.1% of the time in given number of beats -- rarely(beats?: number): returns true 1% of the time in given number of beats -- scarcely(beats?: number): returns true 10% of the time in given number of beats -- sometimes(beats?: number): returns true 50% of the time in given number of beats -- often(beats?: number): returns true 75% of the time in given number of beats -- frequently(beats?: number): returns true 90% of the time in given number of beats -- almostAlways(beats?: number): returns true 99% of the time in given number of beats -- always(beats?: number): returns true. Can be handy when switching between different probabilities - -Examples: - -${makeExample( - "Using chance operators", - ` - rarely() :: sound('hh').out(); // Rarely 48 times is still a lot - rarely(4) :: sound('bd').out(); // Rarely in 4 beats is bit less - rarely(8) :: sound('east').out(); // Rarely in 8 beats is even less - `, - true - )} - -${makeExample( - "Using chance with other operators", - ` - frequently() :: beat(1) :: sound('kick').out(); - often() :: beat(0.5) :: sound('hh').out(); - sometimes() :: onbeat(1,3) :: sound('snare').out(); - `, - true - )} - -${makeExample( - "Using chance with chaining", - ` - beat(0.5) && sound("bd") - .freq(100) - .sometimes(s=>s.crush(2.5)) - .out() - - beat(0.5) && sound('arp').freq(100) - .sometimes(n=>n.freq(200).delay(0.5)) - .rarely(n=>n.freq(300).delay(2.5)) - .almostNever(n=>n.freq(400)) - .out() - `, - true - )} - ## Math functions - max(...values: number[]): number: returns the maximum value of a list of numbers. diff --git a/src/documentation/lfos.ts b/src/documentation/lfos.ts new file mode 100644 index 0000000..356c452 --- /dev/null +++ b/src/documentation/lfos.ts @@ -0,0 +1,58 @@ +import { type Editor } from "../main"; +import { makeExampleFactory } from "../Documentation"; + +export const lfos = (application: Editor): string => { + const makeExample = makeExampleFactory(application); + return ` +# Low Frequency Oscillators + +Low Frequency Oscillators (_LFOs_) are an important piece in any digital audio workstation or synthesizer. Topos implements some basic waveforms you can play with to automatically modulate your paremeters. + +- sine(freq: number = 1, offset: number= 0): number: returns a sinusoïdal oscillation between -1 and 1. +- usine(freq: number = 1, offset: number= 0): number: returns a sinusoïdal oscillation between 0 and 1. The u stands for _unipolar_. + +${makeExample( + "Modulating the speed of a sample player using a sine LFO", + `beat(.25) && snd('cp').speed(1 + usine(0.25) * 2).out()`, + true + )}; + +- triangle(freq: number = 1, offset: number= 0): number: returns a triangle oscillation between -1 and 1. +- utriangle(freq: number = 1, offset: number= 0): number: returns a triangle oscillation between 0 and 1. The u stands for _unipolar_. + +${makeExample( + "Modulating the speed of a sample player using a triangle LFO", + `beat(.25) && snd('cp').speed(1 + utriangle(0.25) * 2).out()`, + true + )} + +- saw(freq: number = 1, offset: number= 0): number: returns a sawtooth-like oscillation between -1 and 1. +- usaw(freq: number = 1, offset: number= 0): number: returns a sawtooth-like oscillation between 0 and 1. The u stands for _unipolar_. + +${makeExample( + "Modulating the speed of a sample player using a saw LFO", + `beat(.25) && snd('cp').speed(1 + usaw(0.25) * 2).out()`, + true + )} + +- square(freq: number = 1, offset: number= 0, duty: number = .5): number: returns a square wave oscillation between -1 and 1. You can also control the duty cycle using the duty parameter. +- usquare(freq: number = 1, offset: number= 0, duty: number = .5): number: returns a square wave oscillation between 0 and 1. The u stands for _unipolar_. You can also control the duty cycle using the duty parameter. + +${makeExample( + "Modulating the speed of a sample player using a square LFO", + `beat(.25) && snd('cp').speed(1 + usquare(0.25, 0, 0.25) * 2).out()`, + true + )}; + +- noise(): returns a random value between -1 and 1. + +${makeExample( + "Modulating the speed of a sample player using noise", + `beat(.25) && snd('cp').speed(1 + noise() * 2).out()`, + true + )}; + +` +} + + diff --git a/src/documentation/probabilities.ts b/src/documentation/probabilities.ts new file mode 100644 index 0000000..14dae0a --- /dev/null +++ b/src/documentation/probabilities.ts @@ -0,0 +1,98 @@ +import { type Editor } from "../main"; +import { makeExampleFactory } from "../Documentation"; + +export const probabilities = (application: Editor): string => { + const makeExample = makeExampleFactory(application); + return ` + +# Probabilities + +There are some simple functions to play with probabilities. + +- rand(min: number, max:number): returns a random number between min and max. Shorthand _r()_. +- irand(min: number, max:number): returns a random integer between min and max. Shorthands _ir()_ or _rI()_. + +${makeExample( + "Bleep bloop, what were you expecting?", + ` +rhythm(0.125, 10, 16) :: sound('sid').n(4).note(50 + irand(50, 62) % 8).out() +`, + true + )} + + +- prob(p: number): return true _p_% of time, false in other cases. +- toss(): throwing a coin. Head (true) or tails (false). + + +${makeExample( + "The Teletype experience!", + ` +prob(50) :: script(1); +prob(60) :: script(2); +prob(80) :: script(toss() ? script(3) : script(4)) +`, + true + )} + +- seed(val: number|string): sets the seed of the random number generator. You can use a number or a string. The same seed will always return the same sequence of random numbers. + + +## Chance operators + +Chance operators returning a boolean value are also available. They are super important because they also exist for another mechanism called **chaining**. Checkout the **Chaining** page to learn how to use them in different contexts! + +By default chance operators will be evaluated 48 times within a beat. You can change this value by providing a number of beats as an argument. Default value is 1. Change operators can also be used to randomly apply other operators. + +- odds(n: number, beats?: number): returns true for every n (odds) (eg. 1/4 = 0.25) in given number of beats +- never(beats?: number): returns false. Can be handy when switching between different probabilities +- almostNever(beats?: number): returns true 0.1% of the time in given number of beats +- rarely(beats?: number): returns true 1% of the time in given number of beats +- scarcely(beats?: number): returns true 10% of the time in given number of beats +- sometimes(beats?: number): returns true 50% of the time in given number of beats +- often(beats?: number): returns true 75% of the time in given number of beats +- frequently(beats?: number): returns true 90% of the time in given number of beats +- almostAlways(beats?: number): returns true 99% of the time in given number of beats +- always(beats?: number): returns true. Can be handy when switching between different probabilities + +Examples: + +${makeExample( + "Using chance operators", + ` + rarely() :: sound('hh').out(); // Rarely 48 times is still a lot + rarely(4) :: sound('bd').out(); // Rarely in 4 beats is bit less + rarely(8) :: sound('east').out(); // Rarely in 8 beats is even less + `, + true + )} + +${makeExample( + "Using chance with other operators", + ` + frequently() :: beat(1) :: sound('kick').out(); + often() :: beat(0.5) :: sound('hh').out(); + sometimes() :: onbeat(1,3) :: sound('snare').out(); + `, + false + )} + +${makeExample( + "Using chance with chaining", + ` + beat(0.5) && sound("bd") + .freq(100) + .sometimes(s=>s.crush(2.5)) + .out() + + beat(0.5) && sound('arp').freq(100) + .sometimes(n=>n.freq(200).delay(0.5)) + .rarely(n=>n.freq(300).delay(2.5)) + .almostNever(n=>n.freq(400)) + .out() + `, + false + )} +` +} + diff --git a/src/documentation/variables.ts b/src/documentation/variables.ts new file mode 100644 index 0000000..59d7ff9 --- /dev/null +++ b/src/documentation/variables.ts @@ -0,0 +1,80 @@ +import { type Editor } from "../main"; +import { makeExampleFactory } from "../Documentation"; + +export const variables = (application: Editor): string => { + const makeExample = makeExampleFactory(application); + return ` + +# Variables + +By default, each script is independant from each other. Scripts live in their own bubble and you cannot get or set variables affecting a script from any other script. **However**, everybody knows that global variables are cool and should be used everywhere. This is an incredibely powerful tool to use for radically altering a composition in a few lines of code. + +- variable(a: number | string, b?: any): if only one argument is provided, the value of the variable will be returned through its name, denoted by the first argument. If a second argument is used, it will be saved as a global variable under the name of the first argument. + - delete_variable(name: string): deletes a global variable from storage. + - clear_variables(): clear **ALL** variables. **This is a destructive operation**! + +**Note:** since this example is running in the documentation, we cannot take advantage of the multiple scripts paradigm. Try to send a variable from the global file to the local file n°6. + +${makeExample( + "Setting a global variable", + ` +v('my_cool_variable', 2) +`, + true + )} + +${makeExample( + "Getting that variable back and printing!", + ` +// Note that we just use one argument +log(v('my_cool_variable')) +`, + false + )} + + +## Counter and iterators + +You will often need to use iterators and/or counters to index over data structures (getting a note from a list of notes, etc...). There are functions ready to be used for this. Each script also comes with its own iterator that you can access using the i variable. **Note:** the script iteration count is **not** resetted between sessions. It will continue to increase the more you play, even if you just picked up an old project. + +- counter(name: number | string, limit?: number, step?: number): reads the value of the counter name. You can also call this function using the dollar symbol: $. + - limit?: counter upper limit before wrapping up. + - step?: incrementor. If step is 2, the iterator will go: 0, 2, 4, 6, etc... + +- drunk(n?: number): returns the value of the internal drunk walk counter. This iterator will sometimes go up, sometimes go down. It comes with companion functions that you can use to finetune its behavior. + - drunk_max(max: number): sets the maximum value. + - drunk_min(min: number): sets the minimum value. + - drunk_wrap(wrap: boolean): whether to wrap the drunk walk to 0 once the upper limit is reached or not. + +**Note:** Counters also come with a secret syntax. They can be called with the **$** symbol! + +${makeExample( + "Iterating over a list of samples using a counter", + ` +rhythm(.25, 6, 8) :: sound('dr').n($(1)).end(.25).out() +`, + true + )} + +${makeExample( + "Using a more complex counter", + ` +// Limit is 20, step is 5 +rhythm(.25, 6, 8) :: sound('dr').n($(1, 20, 5)).end(.25).out() +`, + false + )} + +${makeExample( + "Calling the drunk mechanism", + ` +// Limit is 20, step is 5 +rhythm(.25, 6, 8) :: sound('dr').n(drunk()).end(.25).out() +`, + false + )} + + + +` +} diff --git a/src/main.ts b/src/main.ts index aa87386..442f45c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -838,6 +838,9 @@ export class Editor { "ziffers", "midi", "functions", + "lfos", + "probabilities", + "variables", // "reference", "shortcuts", "about",