Merge branch 'main' of github.com:Bubobubobubobubo/Topos
This commit is contained in:
@ -22,14 +22,14 @@ const samples_to_markdown = (application: Editor) => {
|
||||
|
||||
// Adding new examples for each sample folder!
|
||||
const codeId = `sampleExample${i}`;
|
||||
application.api.codeExamples[codeId] = `mod(.5) :: sound("${keys[i]}").n(irand(1,100)).end(1).out()`;
|
||||
application.api.codeExamples[codeId] = `sound("${keys[i]}").n(irand(1, 5)).end(1).out()`;
|
||||
// @ts-ignore
|
||||
const howMany = samples[keys[i]].data.samples.length;
|
||||
|
||||
markdownList += `
|
||||
<button
|
||||
class="hover:bg-neutral-500 inline px-4 py-2 bg-neutral-700 text-orange-300 text-2xl"
|
||||
onclick="app.api._playDocExample(app.api.codeExamples['${codeId}'])"
|
||||
class="hover:bg-neutral-500 inline px-4 py-2 bg-neutral-700 text-orange-300 text-xl"
|
||||
onclick="app.api._playDocExampleOnce(app.api.codeExamples['${codeId}'])"
|
||||
>
|
||||
${keys[i]}
|
||||
<b class="text-white">(${howMany})</b>
|
||||
@ -82,11 +82,21 @@ Welcome to the Topos documentation. These pages are offering you an introduction
|
||||
|
||||
${makeExample(
|
||||
"Welcome! Eval to get started", `
|
||||
mod([1/4,1/8,1/16].div(8)):: sound('sine')
|
||||
.freq([100,50].div(16) + 50 * ($(1)%10))
|
||||
.gain(0.5).room(0.9).size(0.9)
|
||||
.sustain(0.1).out()
|
||||
mod(1) :: sound('kick').out()`,
|
||||
|
||||
|
||||
bpm(110)
|
||||
mod(0.125) && sound('sawtooth')
|
||||
.note([60, 62, 63, 67, 70].div(.125) +
|
||||
[-12,0,12].beat() + [0, 0, 5, 7].bar())
|
||||
.sustain(0.1).fmi(0.25).fmh(2).room(0.9)
|
||||
.gain(0.75).cutoff(500 + usine(8) * [500, 1000, 2000].bar())
|
||||
.delay(0.5).delayt(0.25).delayfb(0.25)
|
||||
.out();
|
||||
mod(1) && snd('kick').out();
|
||||
mod(2) && snd('snare').out();
|
||||
mod(.5) && snd('hat').out();
|
||||
|
||||
`,
|
||||
true
|
||||
)}
|
||||
|
||||
@ -97,7 +107,11 @@ Topos is an _algorithmic_ sequencer. Topos uses small algorithms to represent mu
|
||||
|
||||
${makeExample(
|
||||
"Small algorithms for direct musical expression",
|
||||
`mod(1) :: sound(['kick', 'hat', 'snare', 'hat'].div(1)).out()`,
|
||||
`
|
||||
mod(1) :: sound(['kick', 'hat', 'snare', 'hat'].div(1)).out()
|
||||
mod(.5) :: sound('jvbass').note(35 + [0,12].beat()).out()
|
||||
mod([0.5, 0.25, 1, 2].div(1)) :: sound('east')
|
||||
.room(.5).size(0.5).n(irand(1,5)).out()`,
|
||||
false
|
||||
)}
|
||||
|
||||
@ -112,7 +126,11 @@ ${makeExample(
|
||||
|
||||
${makeExample(
|
||||
"Making the web less dreadful, one beep at at time",
|
||||
`mod(.5) :: sound(['sid', 'crow', 'zap'].pick()).n($(1) % 10).out()`,
|
||||
`
|
||||
mod(.5) :: sound('sid').n($(2)).out()
|
||||
mod(.25) :: sound('sid').note(
|
||||
[34, 36, 41].div(.25) + [[0,-24].pick(),12].beat())
|
||||
.room(0.9).size(0.9).n(4).out()`,
|
||||
false
|
||||
)}
|
||||
|
||||
@ -127,39 +145,32 @@ Press ${key_shortcut(
|
||||
)}. You are now making music:
|
||||
|
||||
${makeExample(
|
||||
"Drums and arpeggios",
|
||||
"Obscure shenanigans",
|
||||
`
|
||||
bpm(80)
|
||||
mod(0.25) && sound('sawtooth')
|
||||
.note(seqbar(
|
||||
[60, 67, 63].pick() - 12, [60, 67, 63].pick() - 12,
|
||||
[60, 67, 63].pick() - 12 + 5, [60, 67, 63].pick() - 12 + 5,
|
||||
[60, 67, 63].pick() - 12 + 7, [60, 67, 63].pick() - 12 + 7) + (sometimes() ? 24 : 12)
|
||||
)
|
||||
.sustain(0.1).fmi(8).fmh(4).room(0.9)
|
||||
.gain(0.75).cutoff(500 + usine(8) * 10000)
|
||||
.delay(0.5).delaytime(bpm() / 60 / 4 / 3)
|
||||
.delayfeedback(0.25)
|
||||
.out();
|
||||
mod(1) && snd('kick').out();
|
||||
mod(2) && snd('snare').out();
|
||||
mod(.5) && snd('hat').out();
|
||||
`,
|
||||
mod([1/4,1/8,1/16].div(8)):: sound('sine')
|
||||
.freq([100,50].div(16) + 50 * ($(1)%10))
|
||||
.gain(0.5).room(0.9).size(0.9)
|
||||
.sustain(0.1).out()
|
||||
mod(1) :: sound('kick').out()
|
||||
mod(2) :: sound('dr').n(5).out()
|
||||
div(3) :: mod([.25,.5].div(.5)) :: sound('dr')
|
||||
.n([8,9].pick()).gain([.8,.5,.25,.1,.0].div(.25)).out()`,
|
||||
true
|
||||
)}
|
||||
|
||||
${makeExample(
|
||||
"Resonant madness",
|
||||
`mod(.5)::snd('synth2')
|
||||
.freq([50,50*1.25,50*1.5,50*1.75].div(8) / 2)
|
||||
.cutoff(usine(.5) * 5000).resonance(15).end(0.8).room(0.9).size(0.9).n(7).out();
|
||||
mod(.25)::snd('synth2')
|
||||
.freq([50,50*1.25,50*1.5,50*1.75].div(.5))
|
||||
.cutoff(usine(.5) * 5000).resonance(15)
|
||||
.end(0.2).room(0.9).size(0.9).n(14).out()
|
||||
mod(1)::snd('kick').out()
|
||||
mod(2)::snd('snare').shape(0.5).out()
|
||||
mod(.75)::snd('hat').shape(0.4).out()`,
|
||||
`
|
||||
mod(.25)::snd('arpy')
|
||||
.note(30 + [0,3,7,10].beat())
|
||||
.cutoff(usine(.5) * 5000).resonance(10).gain(0.3)
|
||||
.end(0.8).room(0.9).size(0.9).n(0).out();
|
||||
mod([.25,.125].div(2))::snd('arpy')
|
||||
.note(30 + [0,3,7,10].beat())
|
||||
.cutoff(usine(.5) * 5000).resonance(20).gain(0.3)
|
||||
.end(0.8).room(0.9).size(0.9).n(3).out();
|
||||
mod(.5) :: snd('arpy').note(
|
||||
[30, 33, 35].repeatAll(4).div(1) - [12,0].div(0.5)).out()`,
|
||||
false
|
||||
)}
|
||||
`;
|
||||
@ -253,15 +264,17 @@ Let's study two very simple rhythmic functions, <icode>mod(n: ...number[])</icod
|
||||
|
||||
${makeExample(
|
||||
"Using different mod values",
|
||||
`// This code is alternating between different mod values
|
||||
mod([1,1/2,1/4,1/8,1/16].div(4)) :: sound('kick').out()
|
||||
`
|
||||
// This code is alternating between different mod values
|
||||
mod([1,1/2,1/4,1/8].div(2)) :: sound('bd').n(0).out()
|
||||
`,
|
||||
true
|
||||
)}
|
||||
|
||||
${makeExample(
|
||||
"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();
|
||||
mod(1/3) :: blip(400).out();
|
||||
div(3) :: mod(1/6) :: blip(800).out();
|
||||
@ -269,12 +282,33 @@ mod([1,0.75].div(2)) :: blip([50, 100].div(2)).out();
|
||||
`,
|
||||
false
|
||||
)}
|
||||
|
||||
|
||||
|
||||
- <icode>modp(...n: number[])</icode>: extreme version of the <icode>mod</icode> 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.
|
||||
|
||||
${makeExample(
|
||||
"Intriguing rhythms",
|
||||
`
|
||||
modp(36) :: snd('east')
|
||||
.n([2,4].div(1)).out()
|
||||
modp([12, 36].div(4)) :: snd('east')
|
||||
.n([2,4].add(5).div(1)).out()
|
||||
`,
|
||||
true
|
||||
)}
|
||||
${makeExample(
|
||||
"modp is the OG rhythmic function in Topos",
|
||||
`
|
||||
modp([48, 24, 16].div(4)) :: sound('linnhats').out()
|
||||
mod(1)::snd('bd').out()
|
||||
`, false)};
|
||||
|
||||
- <icode>onbeat(...n: number[])</icode>: By default, the bar is set in <icode>4/4</icode> with four beats per bar. The <icode>onbeat</icode> function allows you to lock on to a specific beat to execute some code. It can accept multiple arguments. It's usage is very straightforward and not hard to understand. You can pass integers or floating point numbers.
|
||||
|
||||
${makeExample(
|
||||
"Some simple yet detailed rhythms",
|
||||
`onbeat(1,2,3,4)::snd('kick').out() // Bassdrum on each beat
|
||||
`
|
||||
onbeat(1,2,3,4)::snd('kick').out() // Bassdrum on each beat
|
||||
onbeat(2,4)::snd('snare').out() // Snare on acccentuated beats
|
||||
onbeat(1.5,2.5,3.5, 3.75)::snd('hat').out() // Cool high-hats
|
||||
`,
|
||||
@ -283,7 +317,8 @@ onbeat(1.5,2.5,3.5, 3.75)::snd('hat').out() // Cool high-hats
|
||||
|
||||
${makeExample(
|
||||
"Let's do something more complex",
|
||||
`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()
|
||||
mod([.25, 1/8].div(1.5))::snd('hat').n(2)
|
||||
.gain(rand(0.4, 0.7))
|
||||
@ -311,8 +346,10 @@ mod(.5) && euclid($(2), 2, 8) && snd('sd').out()
|
||||
${makeExample(
|
||||
"And now for more interesting rhythmic constructions",
|
||||
`
|
||||
mod(.5) && euclid($(1), 5, 9) && snd('kick').out()
|
||||
mod(.5) && euclid($(2), 2, 3, 1) && snd('pluck').end(0.5).n(5).out()
|
||||
bpm(145); // Setting a faster BPM
|
||||
mod(.5) && euclid($(1), 5, 8) :: sound('bd').out()
|
||||
mod(.5) && euclid($(2), [1,0].div(8), 8) :: sound('sd').out()
|
||||
mod(.5) && euclid($(6), [6,7].div(8), 8) :: sound('hh').out()
|
||||
`,
|
||||
false
|
||||
)}
|
||||
@ -321,15 +358,29 @@ ${makeExample(
|
||||
"Adding more rhythmic density",
|
||||
`
|
||||
mod(.5) && euclid($(1), 5, 9) && snd('kick').out()
|
||||
mod(.5) && euclid($(2), 2, 3, 1) && snd('pluck').end(0.5).n(5).out()
|
||||
mod(.5) && euclid($(3), 6, 9, 1) && snd('pluck').end(0.5).n(5).freq(200).out()
|
||||
mod(.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()
|
||||
mod(.25) && euclid($(4), 7, 9, 1) && snd('hh').out()
|
||||
`,
|
||||
false
|
||||
)}
|
||||
|
||||
|
||||
|
||||
- <icode>rhythm(divisor: number, pulses: number, length: number, rotate: number): boolean</icode>: generates <icode>true</icode> or <icode>false</icode> values from an euclidian rhythm sequence. This is another version of <icode>euclid</icode> that does not take an iterator.
|
||||
${makeExample(
|
||||
"rhythm is a beginner friendly rhythmic function!",
|
||||
`
|
||||
let speed = [0.5, 0.25].div(8);
|
||||
rhythm(speed, 5, 12) :: snd('east').n(2).out()
|
||||
rhythm(speed, 2, 12) :: snd('east').out()
|
||||
rhythm(speed, 3, 12) :: snd('east').n(4).out()
|
||||
rhythm(speed, 7, 12) :: snd('east').n(9).out()
|
||||
`,
|
||||
true
|
||||
)}
|
||||
|
||||
|
||||
|
||||
- <icode>bin(iterator: number, n: number): boolean</icode>: a binary rhythm generator. It transforms the given number into its binary representation (_e.g_ <icode>34</icode> becomes <icode>100010</icode>). It then returns a boolean value based on the iterator in order to generate a rhythm.
|
||||
|
||||
${makeExample(
|
||||
@ -343,15 +394,17 @@ mod(.5) && bin($(2), 48) && snd('sd').out()
|
||||
|
||||
${makeExample(
|
||||
"Calling 911",
|
||||
`mod(.5) && bin($(1), 911) && snd('pluck').n(4).delay(0.5).delayt(0.25).out()
|
||||
mod(1) && sound('kick').shape(0.5).out()
|
||||
`
|
||||
mod(.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()
|
||||
`,
|
||||
false
|
||||
)}
|
||||
|
||||
${makeExample(
|
||||
"Playing around with simple numbers",
|
||||
`mod(.5) && bin($(1), [123, 456, 789].div(4))
|
||||
`
|
||||
mod(.5) && bin($(1), [123, 456, 789].div(4))
|
||||
&& snd('tabla').n($(2)).delay(0.5).delayt(0.25).out()
|
||||
mod(1) && sound('kick').shape(0.5).out()
|
||||
`,
|
||||
@ -424,7 +477,8 @@ mod(.5)::snd(div(2) ? 'kick' : 'hat').out()
|
||||
|
||||
${makeExample(
|
||||
"div is great for pretty much everything",
|
||||
`div([1, .5].beat()) :: mod(.25) :: sound('shaker').out();
|
||||
`
|
||||
div([1, .5].beat()) :: mod(.25) :: sound('shaker').out();
|
||||
div([4, .5].beat()) :: mod(.25) :: sound('shaker').speed(2).out();
|
||||
div([1, 2].beat()) :: mod(1.75) :: sound('snare').out();
|
||||
div(4) :: mod(.5) :: sound('tom').out()
|
||||
@ -446,9 +500,16 @@ divbar(3)::mod(.5)::snd('hat').out()
|
||||
`,
|
||||
true
|
||||
)}
|
||||
${makeExample(
|
||||
"Alternating over four bars",
|
||||
`
|
||||
divbar(2)
|
||||
? mod(.5) && snd(['kick', 'hh'].div(1)).out()
|
||||
: mod(.5) && snd(['east', 'snare'].div(1)).out()
|
||||
`, false)};
|
||||
|
||||
|
||||
- <icode>onbar(n: number, ...bar: number[])</icode>: The first argument, <icode>n</icode>, is used to divide the time in a period of <icode>n</icode> consecutive bars. The following arguments are bar numbers to play on. For example, <icode>onbar(5, 1, 4)</icode> will return <icode>true</icode> on bar <icode>1</icode> and <icode>4</icode> but return <icode>false</icode> the rest of the time. You can easily divide time that way.
|
||||
|
||||
- <icode>onbar(bars: number | number[], n: number)</icode>: The second argument, <icode>n</icode>, is used to divide the time in a period of <icode>n</icode> consecutive bars. The first argument should be a bar number or a list of bar numbers to play on. For example, <icode>onbar([1, 4], 5)</icode> will return <icode>true</icode> on bar <icode>1</icode> and <icode>4</icode> but return <icode>false</icode> the rest of the time. You can easily divide time that way.
|
||||
|
||||
${makeExample(
|
||||
"Using onbar for filler drums",
|
||||
@ -457,7 +518,7 @@ ${makeExample(
|
||||
onbar(4, 4)::mod(.5)::snd('hh').out();
|
||||
|
||||
// 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();
|
||||
} else {
|
||||
mod(.5)::snd('sd').out();
|
||||
@ -465,7 +526,7 @@ if (onbar(4, 1, 3)) {
|
||||
`,
|
||||
true
|
||||
)}
|
||||
|
||||
|
||||
## What are pulses?
|
||||
|
||||
To make a beat, you need a certain number of time grains or **pulses**. The **pulse** is also known as the [PPQN](https://en.wikipedia.org/wiki/Pulses_per_quarter_note). By default, Topos is using a _pulses per quarter note_ of 48. You can change it by using the <icode>ppqn(number)</icode> function. It means that the lowest possible rhythmic value is 1/48 of a quarter note. That's plenty of time already.
|
||||
@ -606,7 +667,8 @@ The basic function to play a sound is... <icode>sound(name: string)</icode> (you
|
||||
|
||||
${makeExample(
|
||||
"Playing sounds is easy",
|
||||
`mod(1) && sound('bd').out()
|
||||
`
|
||||
mod(1) && sound('bd').out()
|
||||
mod(0.5) && sound('hh').out()
|
||||
`,
|
||||
true
|
||||
@ -621,7 +683,8 @@ Let's make it slightly more complex:
|
||||
|
||||
${makeExample(
|
||||
"Adding some effects",
|
||||
`mod(1) && sound('bd').coarse(0.25).out();
|
||||
`
|
||||
mod(1) && sound('bd').coarse(0.25).room(0.5).orbit(2).out();
|
||||
mod(0.5) && sound('hh').delay(0.25).delaytime(0.125).out();
|
||||
`,
|
||||
true
|
||||
@ -640,12 +703,14 @@ Let's pause for a moment to explain what we just wrote. There are many things to
|
||||
|
||||
${makeExample(
|
||||
'"Composing" a sound or making a sound chain',
|
||||
`mod(1) :: sound('pad')
|
||||
`
|
||||
mod(1) :: sound('pad')
|
||||
.begin(rand(0, 0.4))
|
||||
.freq([50,52].beat())
|
||||
.size(0.9)
|
||||
.room(0.9)
|
||||
.pan(sine()).release(2).out()`,
|
||||
.velocity(0.25)
|
||||
.pan(usine()).release(2).out()`,
|
||||
true
|
||||
)}
|
||||
|
||||
@ -672,7 +737,9 @@ When you type <icode>kick</icode> in the <icode>sound('kick').out()</icode> expr
|
||||
The <icode>.n(number)</icode> method can be used to pick a sample from the currently selected sample folder. For instance, the following script will play a random sample from the _kick_ folder:
|
||||
${makeExample(
|
||||
"Picking a sample",
|
||||
`mod(1) && sound('kick').n([1,2,3,4,5,6,7,8].pick()).out()`,
|
||||
`
|
||||
mod(1) && sound('kick').n([1,2,3,4,5,6,7,8].pick()).out()
|
||||
`,
|
||||
true
|
||||
)}
|
||||
|
||||
@ -680,7 +747,8 @@ Don't worry about the number. If it gets too big, it will be automatically wrapp
|
||||
|
||||
${makeExample(
|
||||
"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()`,
|
||||
true
|
||||
)}
|
||||
@ -692,11 +760,12 @@ mod(.25) && sound('numbers').n(Math.floor(mouseX())).out()`,
|
||||
As we said earlier, the <icode>sound('sample_name')</icode> function can be chained to _specify_ a sound more. For instance, you can add a filter and some effects to your high-hat:
|
||||
${makeExample(
|
||||
"Learning through repetition",
|
||||
`mod(0.5) && sound('hh')
|
||||
.sometimes(s=>s.speed([1,5,10].pick()))
|
||||
.room(0.5)
|
||||
.cutoff(usine(2) * 5000)
|
||||
.out()`,
|
||||
`
|
||||
mod(0.5) && sound('hh')
|
||||
.sometimes(s=>s.speed([1,5,10].pick()))
|
||||
.room(0.5)
|
||||
.cutoff(usine(2) * 5000)
|
||||
.out()`,
|
||||
true
|
||||
)}
|
||||
|
||||
@ -748,11 +817,11 @@ Note that the **sustain** value is not a duration but an amplitude value (how lo
|
||||
${makeExample(
|
||||
"Simple synthesizer",
|
||||
`
|
||||
mod(4)::sound('sawtooth').note(50).decay(0.5).sustain(0.5).release(2).out();
|
||||
mod(2)::sound('sawtooth').note(50+7).decay(0.5).sustain(0.6).release(2).out();
|
||||
mod(1)::sound('sawtooth').note(50+12).decay(0.5).sustain(0.7).release(2).out();
|
||||
mod(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();
|
||||
mod(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))
|
||||
.cutoff(5000).sustain(0.5).release(0.1).out()
|
||||
.cutoff(5000).sustain(0.5).release(0.1).gain(0.25).out()
|
||||
`,
|
||||
true
|
||||
)};
|
||||
@ -804,9 +873,9 @@ ${makeExample(
|
||||
"Filter sweep using a low frequency oscillator",
|
||||
`
|
||||
mod(.5) && snd('sawtooth')
|
||||
.cutoff([2000,500].pick() + usine(.5) * 4000)
|
||||
.resonance(0.9).freq([100,150].pick())
|
||||
.out()
|
||||
.cutoff([2000,500].pick() + usine(.5) * 4000)
|
||||
.resonance(0.9).freq([100,150].pick())
|
||||
.out()
|
||||
`,
|
||||
true
|
||||
)};
|
||||
@ -895,7 +964,8 @@ JavaScript is using [Arrays](https://developer.mozilla.org/en-US/docs/Web/JavaSc
|
||||
|
||||
${makeExample(
|
||||
"Light drumming",
|
||||
`// Every bar, use a different rhythm
|
||||
`
|
||||
// Every bar, use a different rhythm
|
||||
mod([1, 0.75].div(4)) :: sound('cp').out()
|
||||
mod([0.5, 1].div(4)) :: sound('kick').out()
|
||||
mod(2)::snd('snare').shape(.5).out()
|
||||
@ -904,7 +974,8 @@ mod(2)::snd('snare').shape(.5).out()
|
||||
)}
|
||||
${makeExample(
|
||||
"Using div to create arpeggios",
|
||||
`// Arpeggio using pulse divisions
|
||||
`
|
||||
// Arpeggio using pulse divisions
|
||||
mod([.5, .25].div(2)) :: sound('sine')
|
||||
.hcutoff(400)
|
||||
.fmi([1,2].div(8))
|
||||
@ -920,7 +991,8 @@ mod([.5, .25].div(2)) :: sound('sine')
|
||||
)}
|
||||
${makeExample(
|
||||
"Cool ambiance",
|
||||
`mod(.5) :: snd(['kick', 'hat'].div(4)).out()
|
||||
`
|
||||
mod(.5) :: snd(['kick', 'hat'].div(4)).out()
|
||||
mod([2,4].div(2)) :: snd('shaker').delay(.5).delayfb(.75).delayt(0.125).out()
|
||||
div(2)::mod(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()
|
||||
@ -936,7 +1008,8 @@ div(4)::mod(2)::snd('pad').n(2).shape(.5).orbit(2).room(0.9).size(0.9).release(0
|
||||
|
||||
${makeExample(
|
||||
"A simple drumbeat in no time!",
|
||||
`mod(1)::sound(['kick', 'hat', 'snare', 'hat'].beat()).out()
|
||||
`
|
||||
mod(1)::sound(['kick', 'hat', 'snare', 'hat'].beat()).out()
|
||||
mod(1.5)::sound(['jvbass', 'clap'].beat()).out()
|
||||
`,
|
||||
true
|
||||
@ -957,7 +1030,8 @@ mod([1, 0.5].beat()) :: sound(['bass3'].bar())
|
||||
|
||||
${makeExample(
|
||||
"Palindrome filter sweep",
|
||||
`mod([1,.5,.25].beat()) :: snd('sine')
|
||||
`
|
||||
mod([1,.5,.25].beat()) :: snd('sine')
|
||||
.freq([100,200,300].div(0.25))
|
||||
.fmi([1,2,3].palindrome().div(0.5))
|
||||
.fmh([4, 8].palindrome().beat())
|
||||
@ -976,7 +1050,8 @@ ${makeExample(
|
||||
|
||||
${makeExample(
|
||||
"Sipping some gasoline at the robot bar",
|
||||
`mod(1)::snd('kick').shape(0.5).out()
|
||||
`
|
||||
mod(1)::snd('kick').shape(0.5).out()
|
||||
mod([.5, 1].random() / 2) :: snd(
|
||||
['amencutup', 'synth2'].random())
|
||||
.n(irand(4,10))
|
||||
@ -991,7 +1066,8 @@ mod([.5, 1].random() / 2) :: snd(
|
||||
|
||||
${makeExample(
|
||||
"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()
|
||||
`,
|
||||
true
|
||||
@ -1003,7 +1079,8 @@ mod(.25)::snd('amencutup').n([1,2,3,4,5,6,7,8,9].degrade(20).loop($(1))).out()
|
||||
|
||||
${makeExample(
|
||||
"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()
|
||||
`,
|
||||
true
|
||||
@ -1013,7 +1090,9 @@ mod(.25)::sound('amencutup').n([1,2,3,4,5,6,7,8].repeatAll(4).beat()).out()
|
||||
|
||||
${makeExample(
|
||||
"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()`,
|
||||
`
|
||||
mod(1) :: sound('numbers').n([1,2,3,4,5].loop($(3, 10, 2))).out()
|
||||
`,
|
||||
true
|
||||
)}
|
||||
|
||||
@ -1021,7 +1100,8 @@ ${makeExample(
|
||||
|
||||
${makeExample(
|
||||
"Shuffling a list for extra randomness",
|
||||
`mod(1) :: sound('numbers').n([1,2,3,4,5].shuffle().loop($(1)).out()
|
||||
`
|
||||
mod(1) :: sound('numbers').n([1,2,3,4,5].shuffle().loop($(1)).out()
|
||||
`,
|
||||
true
|
||||
)}
|
||||
@ -1030,10 +1110,11 @@ ${makeExample(
|
||||
|
||||
${makeExample(
|
||||
"To make things more complex... here you go",
|
||||
`mod(.5) :: snd('sine')
|
||||
`
|
||||
mod(.5) :: snd('sine')
|
||||
.freq([100, 150, 200, 250, ,300, 400]
|
||||
.rotate([1,2,3].bar()) // The list of frequencies is rotating
|
||||
.beat()) // while being indexed over!
|
||||
.rotate([1,2,3].bar()) // The list of frequencies is rotating
|
||||
.beat()) // while being indexed over!
|
||||
.sustain(0.1)
|
||||
.out()
|
||||
`,
|
||||
@ -1044,12 +1125,23 @@ ${makeExample(
|
||||
|
||||
${makeExample(
|
||||
"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()
|
||||
`,
|
||||
true
|
||||
)}
|
||||
|
||||
- <icode>add()</icode>: add a given amount to every list element.
|
||||
- <icode>sub()</icode>: add a given amount to every list element.
|
||||
- <icode>mult()</icode>: add a given amount to every list element.
|
||||
- <icode>division()</icode>: add a given amount to every list element. The method is named <icode>division</icode> because obviously <icode>div</icode> is already taken.
|
||||
|
||||
${makeExample(
|
||||
"Simple addition",
|
||||
`[1, 2 ,3].add(2).beat()`,
|
||||
true
|
||||
)}
|
||||
|
||||
## Simple patterns
|
||||
|
||||
@ -1248,7 +1340,8 @@ The <icode>sound</icode> function can take the name of a synthesizer as first ar
|
||||
|
||||
${makeExample(
|
||||
"Simple synthesizer voice with filter",
|
||||
`mod(.5) && snd('sawtooth')
|
||||
`
|
||||
mod(.5) && snd('sawtooth')
|
||||
.cutoff([2000,500].pick() + usine(.5) * 4000)
|
||||
.resonance(0.9).freq([100,150].pick())
|
||||
.out()
|
||||
@ -1258,8 +1351,9 @@ ${makeExample(
|
||||
|
||||
${makeExample(
|
||||
"Listening to the different waveforms from the sweetest to the harshest",
|
||||
`mod(.5) && snd(['sine', 'triangle', 'sawtooth', 'square'].beat()).freq(100).out()
|
||||
.freq(50)
|
||||
`
|
||||
mod(.5) && snd(['sine', 'triangle', 'sawtooth', 'square'].beat()).freq(100).out()
|
||||
.freq(50)
|
||||
.out()
|
||||
`,
|
||||
false
|
||||
@ -1268,7 +1362,8 @@ ${makeExample(
|
||||
|
||||
${makeExample(
|
||||
"Blessed by the square wave",
|
||||
`mod(4) :: [100,101].forEach((freq) => sound('square').freq(freq).sustain(0.1).out())
|
||||
`
|
||||
mod(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())
|
||||
mod([.5, .75, 2].beat()) :: [100,101].forEach((freq) => sound('square')
|
||||
.freq(freq*4 + usquare(2) * 200).sustain(0.125).out())
|
||||
@ -1279,11 +1374,14 @@ mod(.25) :: sound('square').freq(100*[1,2,4,8].beat()).sustain(0.1).out()`,
|
||||
|
||||
${makeExample(
|
||||
"Ghost carillon",
|
||||
`mod(1/8)::sound('sine')
|
||||
`
|
||||
mod(1/8)::sound('sine')
|
||||
.velocity(rand(0.0, 1.0))
|
||||
.delay(0.75).delayt(.5)
|
||||
.sustain(0.4)
|
||||
.cutoff(2000)
|
||||
.freq(mouseX())
|
||||
.gain(0.25)
|
||||
.out()`,
|
||||
false
|
||||
)}
|
||||
@ -1298,7 +1396,8 @@ The same basic waveforms can take additional methods to switch to a basic two op
|
||||
|
||||
${makeExample(
|
||||
"80s nostalgia",
|
||||
`mod(.25) && snd('sine')
|
||||
`
|
||||
mod(.25) && snd('sine')
|
||||
.fmi([1,2,4,8].pick())
|
||||
.fmh([1,2,4,8].div(8))
|
||||
.freq([100,150].pick())
|
||||
@ -1310,7 +1409,8 @@ ${makeExample(
|
||||
|
||||
${makeExample(
|
||||
"Giving some love to weird ratios",
|
||||
`mod([.5, .25].bar()) :: sound('sine').fm('2.2183:3.18293').sustain(0.05).out()
|
||||
`
|
||||
mod([.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()
|
||||
mod(.5) :: sound('sine')
|
||||
.fmh([1, 1.75].beat())
|
||||
@ -1321,9 +1421,10 @@ mod(.5) :: sound('sine')
|
||||
|
||||
${makeExample(
|
||||
"Some peace and serenity",
|
||||
`mod(0.25) :: sound('sine')
|
||||
.note([60, 67, 70, 72, 77].beat())
|
||||
.attack(0.2).release(0.5).gain(0.5)
|
||||
`
|
||||
mod(0.25) :: sound('sine')
|
||||
.note([60, 67, 70, 72, 77].beat() - [0,12].bar())
|
||||
.attack(0.2).release(0.5).gain(0.25)
|
||||
.room(0.9).size(0.8).sustain(0.5)
|
||||
.fmi(Math.floor(usine(.25) * 10))
|
||||
.cutoff(1500).delay(0.5).delayt(0.125)
|
||||
@ -1383,16 +1484,23 @@ There are some techniques that Topos players are using to keep their JavaScript
|
||||
|
||||
${makeExample(
|
||||
"Shortening your if conditions",
|
||||
`// The && symbol (overriden by :: in Topos) is very often used for conditions!
|
||||
mod(.75) :: snd('zap').out()
|
||||
`
|
||||
// The && symbol (overriden by :: in Topos) is very often used for conditions!
|
||||
mod(.75) :: snd('linnhats').n([1,4,5].beat()).out()
|
||||
mod(1) :: snd('bd').out()
|
||||
//if (true) && log('very true')
|
||||
// These two lines are the same:
|
||||
// mod(1) && snd('bd').out()
|
||||
//// mod(1) :: snd('bd').out()
|
||||
|
||||
`,
|
||||
true
|
||||
)}
|
||||
|
||||
${makeExample(
|
||||
"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()
|
||||
// (true) ? log('very true') : log('very false')
|
||||
`,
|
||||
@ -1402,7 +1510,8 @@ mod(4) ? snd('kick').out() : mod(2)::snd('snare').out()
|
||||
|
||||
${makeExample(
|
||||
"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()
|
||||
!mod(2) :: mod(0.5)::snd('clap').out()
|
||||
`,
|
||||
@ -1477,36 +1586,38 @@ Low Frequency Oscillators (_LFOs_) are an important piece in any digital audio w
|
||||
- <icode>sine(freq: number = 1, offset: number= 0): number</icode>: returns a sinusoïdal oscillation between <icode>-1</icode> and <icode>1</icode>.
|
||||
- <icode>usine(freq: number = 1, offset: number= 0): number</icode>: returns a sinusoïdal oscillation between <icode>0</icode> and <icode>1</icode>. The <icode>u</icode> stands for _unipolar_.
|
||||
|
||||
\`\`\`javascript
|
||||
mod(.25) && snd('cp').speed(1 + usine(0.25) * 2).out()
|
||||
\`\`\`
|
||||
|
||||
${makeExample(
|
||||
"Modulating the speed of a sample player using a sine LFO",
|
||||
`mod(.25) && snd('cp').speed(1 + usine(0.25) * 2).out()`, true)};
|
||||
|
||||
- <icode>triangle(freq: number = 1, offset: number= 0): number</icode>: returns a triangle oscillation between <icode>-1</icode> and <icode>1</icode>.
|
||||
- <icode>utriangle(freq: number = 1, offset: number= 0): number</icode>: returns a triangle oscillation between <icode>0</icode> and <icode>1</icode>. The <icode>u</icode> stands for _unipolar_.
|
||||
|
||||
\`\`\`javascript
|
||||
mod(.25) && snd('cp').speed(1 + utriangle(0.25) * 2).out()
|
||||
\`\`\`
|
||||
|
||||
${makeExample(
|
||||
"Modulating the speed of a sample player using a triangle LFO",
|
||||
`mod(.25) && snd('cp').speed(1 + utriangle(0.25) * 2).out()`, true)}
|
||||
|
||||
- <icode>saw(freq: number = 1, offset: number= 0): number</icode>: returns a sawtooth-like oscillation between <icode>-1</icode> and <icode>1</icode>.
|
||||
- <icode>usaw(freq: number = 1, offset: number= 0): number</icode>: returns a sawtooth-like oscillation between <icode>0</icode> and <icode>1</icode>. The <icode>u</icode> stands for _unipolar_.
|
||||
|
||||
\`\`\`javascript
|
||||
mod(.25) && snd('cp').speed(1 + usaw(0.25) * 2).out()
|
||||
\`\`\`
|
||||
|
||||
${makeExample(
|
||||
"Modulating the speed of a sample player using a saw LFO",
|
||||
`mod(.25) && snd('cp').speed(1 + usaw(0.25) * 2).out()`, true)}
|
||||
|
||||
- <icode>square(freq: number = 1, offset: number= 0, duty: number = .5): number</icode>: returns a square wave oscillation between <icode>-1</icode> and <icode>1</icode>. You can also control the duty cycle using the <icode>duty</icode> parameter.
|
||||
- <icode>usquare(freq: number = 1, offset: number= 0, duty: number = .5): number</icode>: returns a square wave oscillation between <icode>0</icode> and <icode>1</icode>. The <icode>u</icode> stands for _unipolar_. You can also control the duty cycle using the <icode>duty</icode> parameter.
|
||||
|
||||
\`\`\`javascript
|
||||
mod(.25) && snd('cp').speed(1 + usquare(0.25, 0, 0.25) * 2).out()
|
||||
\`\`\`
|
||||
${makeExample(
|
||||
"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()`,true)};
|
||||
|
||||
- <icode>noise()</icode>: returns a random value between -1 and 1.
|
||||
|
||||
\`\`\`javascript
|
||||
mod(.25) && snd('cp').speed(1 + noise() * 2).out()
|
||||
\`\`\`
|
||||
${makeExample(
|
||||
"Modulating the speed of a sample player using noise",
|
||||
`mod(.25) && snd('cp').speed(1 + noise() * 2).out()`, true)};
|
||||
|
||||
## Probabilities
|
||||
|
||||
|
||||
Reference in New Issue
Block a user