docs: control params

This commit is contained in:
Felix Roos 2023-01-09 23:27:30 +01:00
parent 69ecb7b54f
commit b695e090cd
4 changed files with 134 additions and 36 deletions

View File

@ -59,7 +59,7 @@ export const SIDEBAR: Sidebar = {
{ text: 'Introduction', link: 'functions/intro' }, { text: 'Introduction', link: 'functions/intro' },
{ text: 'Pattern Constructors', link: 'learn/factories' }, { text: 'Pattern Constructors', link: 'learn/factories' },
{ text: 'Time Modifiers', link: 'learn/time-modifiers' }, { text: 'Time Modifiers', link: 'learn/time-modifiers' },
{ text: 'Value Modifiers', link: 'functions/value-modifiers' }, { text: 'Control Parameters', link: 'functions/value-modifiers' },
{ text: 'Signals', link: 'learn/signals' }, { text: 'Signals', link: 'learn/signals' },
{ text: 'Conditional Modifiers', link: 'learn/conditional-modifiers' }, { text: 'Conditional Modifiers', link: 'learn/conditional-modifiers' },
{ text: 'Tonal Modifiers', link: 'learn/tonal' }, { text: 'Tonal Modifiers', link: 'learn/tonal' },

View File

@ -1,61 +1,154 @@
--- ---
title: Value Modifiers title: Control Parameters
layout: ../../layouts/MainLayout.astro layout: ../../layouts/MainLayout.astro
--- ---
import { MiniRepl } from '../../docs/MiniRepl'; import { MiniRepl } from '../../docs/MiniRepl';
import { JsDoc } from '../../docs/JsDoc'; import { JsDoc } from '../../docs/JsDoc';
# Value Modifiers # Control Parameters
## Notes Besides functions that control time, we saw earlier that functions like `note` and `cutoff` control different parameters (short params) of an event.
Let's now look more closely at how these `param(eter) functions` work.
Notes are automatically available as variables: # Parameter Functions
<MiniRepl client:only="react" tune={`note(seq(d4, fs4, a4)) // note("d4 f#4 a4")`} /> A very powerful feature of tidal patterns is that each parameter can be controlled independently:
An important difference to the mini notation: <MiniRepl
For sharp notes, the letter "s" is used instead of "#", because JavaScript does not support "#" in a variable name. client:only="react"
tune={`note("c a f e")
.cutoff("<500 1000 2000 [4000 8000]>")
.gain(.8)
.s('sawtooth')
.log()`}
/>
The above is the same as: In this example, the parameters `note`, `cutoff`, `gain` and `s` are controlled independently by either patterns or plain values (numbers / text).
After pressing play, we can observe the time and parameter values of each event (hap) in the output created by `.log()`.
<MiniRepl client:only="react" tune={`note(seq('d4', 'f#4', 'a4'))`} /> ## Plain vs Parameterized Values
Using strings, you can also use "#". Patterns that are not wrapped inside a param function will contain unlabeled `plain values`:
## Alternative Syntax <MiniRepl client:only="react" tune={`"<c e g>".log()`} />
In the above example, we are nesting a function inside a function, which makes reading the parens a little more difficult. This will not generate any sound output, because Strudel could only guess which param is meant by these letters.
To avoid getting to many nested parens, there is an alternative syntax to add a type to a pattern:
<MiniRepl client:only="react" tune={`seq(d4, fs4, a4).note()`} /> Now compare that to the version wrapped in `note`:
<MiniRepl client:only="react" tune={`note("<c e g>").log()`} />
Now it is clear that these letters are meant to be played as notes.
Under the hood, the `note` function (as well as all other param functions)
will wrap each plain value in an object. If the note function did not exist, we would need to write:
<MiniRepl client:only="react" tune={`cat({note:'c'},{note:'e'},{note:'g'}).log()`} />
This will have the same output, though it is rather unwieldy to read and write.
## Wrapping Parameter Functions
To avoid too much nesting, param functions can also be chained like this:
<MiniRepl client:only="react" tune={`cat('c', 'e', 'g').note().log()`} />
This is equivalent to `note(cat('c','e','g')).log()`.
You can use this with any function that declares a type (like `n`, `s`, `note`, `freq` etc), just make sure to leave the parens empty! You can use this with any function that declares a type (like `n`, `s`, `note`, `freq` etc), just make sure to leave the parens empty!
## Pattern.add ## Plain Value Modification
Patterns of plain values can be modified with any of the following operators:
<MiniRepl client:only="react" tune={`"50 60 70".add("<0 1 2>").log()`} />
Here, the add function modifies the numbers on the left.
Again, there is no output because these numbers have no meaning without a param.
## Param Value Modification
To modify a parameter value, you can either:
- Use the operator on the plain value pattern, inside the param function:
<MiniRepl client:only="react" tune={`note("50 60 70".add("<0 1 2>")).room(.1).log()`} />
- Similarly, use the operator on the plain value pattern and wrap it later:
<MiniRepl client:only="react" tune={`"50 60 70".add("<0 1 2>").note().room(.1).log()`} />
- Specify which param should be modified inside the operator function:
<MiniRepl client:only="react" tune={`note("50 60 70").room(.1).add(note("<0 1 2>")).log()`} />
- Modify _all_ numeral params:
<MiniRepl client:only="react" tune={`note("50 60 70").room(.1).add("<0 1 2>").log()`} />
Which of these 3 ways to use strongly depends on the context!
Note that the order of chaining param functions also matters!
In the last example, the `room` value would not have changed if it was applied later:
<MiniRepl client:only="react" tune={`note("50 60 70").add("<0 1 2>").room(.1).log()`} />
This shows how the execution of the chained functions goes from left to right.
In this case, the `.add` will only modify what's on the left side.
# Operators
This group of functions allows to modify the value of events.
## add
<JsDoc client:idle name="Pattern.add" h={0} /> <JsDoc client:idle name="Pattern.add" h={0} />
## Pattern.sub ## sub
<JsDoc client:idle name="Pattern.sub" h={0} /> <JsDoc client:idle name="Pattern.sub" h={0} />
## Pattern.mul ## mul
<JsDoc client:idle name="Pattern.mul" h={0} /> <JsDoc client:idle name="Pattern.mul" h={0} />
## Pattern.div ## div
<JsDoc client:idle name="Pattern.div" h={0} /> <JsDoc client:idle name="Pattern.div" h={0} />
## Pattern.round ## round
<JsDoc client:idle name="Pattern.round" h={0} /> <JsDoc client:idle name="Pattern.round" h={0} />
## Pattern.apply ## floor
<JsDoc client:idle name="Pattern.apply" h={0} /> <JsDoc client:idle name="Pattern.floor" h={0} />
## Pattern.range ## ceil
<JsDoc client:idle name="Pattern.ceil" h={0} />
## range
<JsDoc client:idle name="Pattern.range" h={0} /> <JsDoc client:idle name="Pattern.range" h={0} />
# Custom Parameters
You can also create your own parameters:
<MiniRepl
client:only="react"
tune={`let x = createParam('x')
x(sine.range(0, 200))
`}
/>
Multiple params can also be created in a more consice way, using `createParams`:
<MiniRepl
client:only="react"
tune={`let { x, y } = createParams('x', 'y');
x(sine.range(0, 200)).y(cosine.range(0, 200));
`}
/>
Note that these params will not do anything until you give them meaning in your custom output!

View File

@ -20,6 +20,7 @@ These are the equivalents used by the Mini Notation:
| `timeCat([3,x],[2,y])` | `"x@2 y@2"` | | `timeCat([3,x],[2,y])` | `"x@2 y@2"` |
| `polymeter([a, b, c], [x, y])` | `"{a b c, x y}"` | | `polymeter([a, b, c], [x, y])` | `"{a b c, x y}"` |
| `polymeterSteps(2, x, y, z)` | `"{x y z}%2"` | | `polymeterSteps(2, x, y, z)` | `"{x y z}%2"` |
| `silence` | `"~"` |
## cat ## cat
@ -56,3 +57,7 @@ As a chained function:
## polymeterSteps ## polymeterSteps
<JsDoc client:idle name="polymeterSteps" h={0} /> <JsDoc client:idle name="polymeterSteps" h={0} />
## silence
<JsDoc client:idle name="silence" h={0} />

View File

@ -56,54 +56,54 @@ These methods add random behavior to your Patterns.
<JsDoc client:idle name="chooseCycles" h={0} /> <JsDoc client:idle name="chooseCycles" h={0} />
## Pattern.degradeBy ## degradeBy
<JsDoc client:idle name="Pattern.degradeBy" h={0} /> <JsDoc client:idle name="Pattern.degradeBy" h={0} />
## Pattern.degrade ## degrade
<JsDoc client:idle name="Pattern.degrade" h={0} /> <JsDoc client:idle name="Pattern.degrade" h={0} />
## Pattern.undegradeBy ## undegradeBy
<JsDoc client:idle name="Pattern.undegradeBy" h={0} /> <JsDoc client:idle name="Pattern.undegradeBy" h={0} />
## Pattern.sometimesBy ## sometimesBy
<JsDoc client:idle name="Pattern.sometimesBy" h={0} /> <JsDoc client:idle name="Pattern.sometimesBy" h={0} />
## Pattern.sometimes ## sometimes
<JsDoc client:idle name="Pattern.sometimes" h={0} /> <JsDoc client:idle name="Pattern.sometimes" h={0} />
## Pattern.someCyclesBy ## someCyclesBy
<JsDoc client:idle name="Pattern.someCyclesBy" h={0} /> <JsDoc client:idle name="Pattern.someCyclesBy" h={0} />
## Pattern.someCycles ## someCycles
<JsDoc client:idle name="Pattern.someCycles" h={0} /> <JsDoc client:idle name="Pattern.someCycles" h={0} />
## Pattern.often ## often
<JsDoc client:idle name="Pattern.often" h={0} /> <JsDoc client:idle name="Pattern.often" h={0} />
## Pattern.rarely ## rarely
<JsDoc client:idle name="Pattern.rarely" h={0} /> <JsDoc client:idle name="Pattern.rarely" h={0} />
## Pattern.almostNever ## almostNever
<JsDoc client:idle name="Pattern.almostNever" h={0} /> <JsDoc client:idle name="Pattern.almostNever" h={0} />
## Pattern.almostAlways ## almostAlways
<JsDoc client:idle name="Pattern.almostAlways" h={0} /> <JsDoc client:idle name="Pattern.almostAlways" h={0} />
## Pattern.never ## never
<JsDoc client:idle name="Pattern.never" h={0} /> <JsDoc client:idle name="Pattern.never" h={0} />
## Pattern.always ## always
<JsDoc client:idle name="Pattern.always" h={0} /> <JsDoc client:idle name="Pattern.always" h={0} />