diff --git a/packages/webaudio/webaudio.mjs b/packages/webaudio/webaudio.mjs index dff958e4..d94f264f 100644 --- a/packages/webaudio/webaudio.mjs +++ b/packages/webaudio/webaudio.mjs @@ -238,10 +238,10 @@ function effectSend(input, effect, wet) { export const webaudioOutput = async (hap, deadline, hapDuration) => { try { const ac = getAudioContext(); - if (isNote(hap.value)) { + /* if (isNote(hap.value)) { // supports primitive hap values that look like notes hap.value = { note: hap.value }; - } + } */ if (typeof hap.value !== 'object') { throw new Error( `hap.value ${hap.value} is not supported by webaudio output. Hint: append .note() or .s() to the end`, diff --git a/tutorial/tutorial.mdx b/tutorial/tutorial.mdx index 87432132..ce90569a 100644 --- a/tutorial/tutorial.mdx +++ b/tutorial/tutorial.mdx @@ -54,13 +54,98 @@ s("bd,[~ ],hh(3,4)") // drums
+# Playing Pitches + +Pitches are an essential building block for music. In Strudel, there are 3 different options to express a pitch: + +- `note`: letter notation +- `n`: number notation +- `freq`: frequency notation + +## note + +Notes are notated with the note letter, followed by the octave number. You can notate flats with `b` and sharps with `#`. + + + +By the way, you can edit the contents of the player, and press "update" to hear your change! +You can also press "play" on the next player without needing to stop the last one. + +## n + +If you don't like notes, you can also use numbers with `n` instead: + + + +These numbers are interpreted as so called midi numbers, where adjacent whole numbers are 1 semitone apart. +You could also write decimal numbers to get microtonal pitches: + + + +## freq + +To get maximum freedom, you can also use `freq` to directly control the frequency: + + + +In this example, we play A3 (220Hz), C#4 natural (275Hz), E4 (330Hz) and A4 (440Hz). + +
+ +# Playing Sounds + +Instead of pitches, we can also play sounds with `s`: + + + +Similarly, we can also use `s` to change the sound of our pitches: + + + +Try changing the sound to `square`, `triangle` or `sine`! + +We will go into the defails of sounds and synths [later](http://localhost:3000/tutorial/#web-audio-output). + +
+ +# Syntax + +So far, we've seen the following syntax: + +``` +xxx("foo").yyy("bar") +``` + +Generally, `xxx` and `yyy` are called functions, while `foo` and `bar` are called function arguments. +So far, we've used the functions to declare which aspect of the sound we want to control, and their arguments for the actual data. +The `yyy` function is called a chained function, because it is appended with a dot. + +Strudel makes heavy use of chained functions. Here is a more extreme example: + + + +The `//` is a line comment, resulting in the `delay` function being ignored. +It is a handy way to quickly turn stuff on and off. Try uncommenting this line by deleting `//`! + +The good news is, that this covers 99% of the JavaScript syntax needed for Strudel! + +Let's now look at the way we can express rhythms.. + +
+ # Mini Notation Similar to Tidal Cycles, Strudel has an embedded mini language that is designed to write rhythmic patterns in a short manner. Before diving deeper into the details, here is a flavor of how the mini language looks like: The snippet above is enclosed in backticks (`), which allows you to write multi-line strings. You can also use double quotes (") for single line mini notation. -## Notes - -Notes are notated with the note letter, followed by the octave number. You can notate flats with `b` and sharps with `#`. - - - -Here, the same note is played over and over again, once a second. This one second is the default length of one so called "cycle". - -By the way, you can edit the contents of the player, and press "update" to hear your change! -You can also press "play" on the next player without needing to stop the last one. - ## Sequences We can play more notes by separating them with spaces: - + Here, those four notes are squashed into one cycle, so each note is a quarter second long. +Try adding or removing notes and notice how the tempo changes! ## Division We can slow the sequence down by enclosing it in brackets and dividing it by a number: - + The division by two means that the sequence will be played over the course of two cycles. You can also use decimal numbers for any tempo you like. @@ -118,11 +193,11 @@ You can also use decimal numbers for any tempo you like. Using angle brackets, we can define the sequence length based on the number of children: -"`} /> +")`} /> The above snippet is the same as: - + The advantage of the angle brackets, is that we can add more children without needing to change the number at the end. @@ -130,7 +205,7 @@ The advantage of the angle brackets, is that we can add more children without ne Contrary to division, a sequence can be sped up by multiplying it by a number: - + The multiplication by 2 here means that the sequence will play twice a cycle. @@ -138,29 +213,29 @@ The multiplication by 2 here means that the sequence will play twice a cycle. To create more interesting rhythms, you can nest sequences with brackets, like this: - + ## Rests The "~" represents a rest: - + ## Parallel Using commas, we can play chords: - + To play multiple chords in a sequence, we have to wrap them in brackets: -"`} /> +")`} /> ## Elongation With the "@" symbol, we can specify temporal "weight" of a sequence child: -"`} /> +")`} /> Here, the first chord has a weight of 2, making it twice the length of the other chords. The default weight is 1. @@ -168,7 +243,7 @@ Here, the first chord has a weight of 2, making it twice the length of the other Using "!" we can repeat without speeding up: -"`} /> +")`} /> In essence, the `x!n` is like a shortcut for `[x*n]@n`. @@ -181,7 +256,7 @@ The third (optional) parameter controls the starting position for distributing t One popular Euclidian rhythm (going by various names, such as "Pop Clave") is "(3,8,1)" or simply "(3,8)", resulting in a rhythmical structure of "x ~ ~ x ~ ~ x ~" (3 beats over 8 segments, starting on position 1). - +
@@ -381,17 +456,26 @@ Internally, the mini notation will expand to use the actual functional JavaScrip Notes are automatically available as variables: - + An important difference to the mini notation: For sharp notes, the letter "s" is used instead of "#", because JavaScript does not support "#" in a variable name. The above is the same as: - + Using strings, you can also use "#". +## Alternative Syntax + +In the above example, we are nesting a function inside a function, which makes reading the parens a little more difficult. +To avoid getting to many nested parens, there is an alternative syntax to add a type to a pattern: + + + +You can use this with any function that declares a type, just make sure to leave the parens empty! + ## Pattern Factories The following functions will return a pattern.