From b8f991eddbbbf6f21ba5716b8d067bade8868078 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Tue, 20 Dec 2022 20:42:42 +0100 Subject: [PATCH] simplify writing mdx files --- website/src/components/strudel/MiniRepl.jsx | 42 ++-- website/src/layouts/MainLayout.astro | 7 +- website/src/pages/tutorial/index.astro | 7 - .../tutorial.mdx => pages/tutorial/index.mdx} | 236 ++++++++++-------- website/src/styles/index.css | 2 + 5 files changed, 162 insertions(+), 132 deletions(-) delete mode 100644 website/src/pages/tutorial/index.astro rename website/src/{components/tutorial.mdx => pages/tutorial/index.mdx} (75%) diff --git a/website/src/components/strudel/MiniRepl.jsx b/website/src/components/strudel/MiniRepl.jsx index ee32e0db..64b2a377 100644 --- a/website/src/components/strudel/MiniRepl.jsx +++ b/website/src/components/strudel/MiniRepl.jsx @@ -1,25 +1,35 @@ import { evalScope, controls } from '@strudel.cycles/core'; -import { MiniRepl as _MiniRepl } from '@strudel.cycles/react'; import { samples } from '@strudel.cycles/webaudio'; +import { useEffect, useState } from 'react'; -fetch('https://strudel.tidalcycles.org/EmuSP12.json') - .then((res) => res.json()) - .then((json) => samples(json, 'https://strudel.tidalcycles.org/EmuSP12/')); +if (typeof window !== 'undefined') { + fetch('https://strudel.tidalcycles.org/EmuSP12.json') + .then((res) => res.json()) + .then((json) => samples(json, 'https://strudel.tidalcycles.org/EmuSP12/')); -evalScope( - controls, - import('@strudel.cycles/core'), - // import('@strudel.cycles/tone'), - import('@strudel.cycles/tonal'), - import('@strudel.cycles/mini'), - import('@strudel.cycles/midi'), - import('@strudel.cycles/xen'), - import('@strudel.cycles/webaudio'), - import('@strudel.cycles/osc'), -); + evalScope( + controls, + import('@strudel.cycles/core'), + // import('@strudel.cycles/tone'), + import('@strudel.cycles/tonal'), + import('@strudel.cycles/mini'), + import('@strudel.cycles/midi'), + import('@strudel.cycles/xen'), + import('@strudel.cycles/webaudio'), + import('@strudel.cycles/osc'), + ); +} // prebake(); export function MiniRepl({ tune }) { - return <_MiniRepl tune={tune} hideOutsideView={true} />; + const [Repl, setRepl] = useState(); + useEffect(() => { + // we have to load this package on the client + // because codemirror throws an error on the server + import('@strudel.cycles/react').then((res) => { + setRepl(() => res.MiniRepl); + }); + }, []); + return Repl ? :
{tune}
; } diff --git a/website/src/layouts/MainLayout.astro b/website/src/layouts/MainLayout.astro index e25f1a8e..5d62e6a4 100644 --- a/website/src/layouts/MainLayout.astro +++ b/website/src/layouts/MainLayout.astro @@ -36,11 +36,14 @@ const githubEditUrl = `${CONFIG.GITHUB_EDIT_URL}/${currentFile}`;
-
+ +
-
+ diff --git a/website/src/pages/tutorial/index.astro b/website/src/pages/tutorial/index.astro deleted file mode 100644 index 8b3f57e8..00000000 --- a/website/src/pages/tutorial/index.astro +++ /dev/null @@ -1,7 +0,0 @@ ---- -import { Content } from '../../components/tutorial.mdx'; -import MiniRepl from '../../components/strudel/MiniRepl.astro'; -import JsDoc from '../../components/strudel/JsDoc.astro'; ---- - - diff --git a/website/src/components/tutorial.mdx b/website/src/pages/tutorial/index.mdx similarity index 75% rename from website/src/components/tutorial.mdx rename to website/src/pages/tutorial/index.mdx index 12e3d42e..dd4d3b75 100644 --- a/website/src/components/tutorial.mdx +++ b/website/src/pages/tutorial/index.mdx @@ -1,9 +1,12 @@ --- title: What is Strudel? description: Strudel Tutorial -layout: ../layouts/MainLayout.astro +layout: ../../layouts/MainLayout.astro --- +import { MiniRepl } from '../../components/strudel/MiniRepl'; +import { JsDoc } from '../../components/strudel/JsDoc'; + # What is Strudel? With Strudel, you can expressively write dynamic music pieces. @@ -20,6 +23,7 @@ The best place to actually make music with Strudel is the [Strudel REPL](https:/ To get a taste of what Strudel can do, check out this track: + 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. @@ -77,18 +81,18 @@ You can also press "play" on the next player without needing to stop the last on 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). @@ -98,11 +102,11 @@ In this example, we play A3 (220Hz), C#4 natural (275Hz), E4 (330Hz) and A4 (440 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`! @@ -125,6 +129,7 @@ The `yyy` function is called a chained function, because it is appended with a d Strudel makes heavy use of chained functions. Here is a more extreme example: + 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! @@ -186,7 +192,7 @@ Try adding or removing notes and notice how the tempo changes! 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. @@ -195,11 +201,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. @@ -207,7 +213,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. @@ -215,29 +221,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. @@ -245,7 +251,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`. @@ -258,7 +264,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,0)" or simply "(3,8)", resulting in a rhythmical structure of "x ~ ~ x ~ ~ x ~" (3 beats over 8 segments, starting on position 1). - +
@@ -271,14 +277,14 @@ Let's take a closer look at how we can control synths, sounds and effects. So far, all the mini notation examples all used the same sound, which is kind of boring. We can change the sound, using the `s` function: ->").s('sawtooth')`} /> +>").s('sawtooth')`} /> Here, we are wrapping our notes inside `note` and set the sound using `s`, connected by a dot. Those functions are only 2 of many ways to alter the properties, or _params_ of a sound. The power of patterns allows us to sequence any _param_ independently: ->").s("")`} /> +>").s("")`} /> Now we not only pattern the notes, but the sound as well! `sawtooth` `square` and `triangle` are the basic waveforms available in `s`. @@ -288,6 +294,7 @@ Now we not only pattern the notes, but the sound as well! You can control the envelope of a synth using the `attack`, `decay`, `sustain` and `release` functions: >").s('sawtooth') .attack(.1).decay(.1).sustain(.2).release(.1)`} /> @@ -296,7 +303,7 @@ You can control the envelope of a synth using the `attack`, `decay`, `sustain` a Besides Synths, `s` can also play back samples: - + To know which sounds are available, open the [default sample map](https://strudel.tidalcycles.org/EmuSP12.json) @@ -305,6 +312,7 @@ To know which sounds are available, open the [default sample map](https://strude You can load your own sample map like this: ")`} For pitched sounds, you can use `note`, just like with synths: @2").s('gtr').clip(1) If we have 2 samples with different base pitches, we can make them in tune by specifying the pitch like this: + ### Pattern.end - + ### Pattern.loopAt - + ### Pattern.chop - + ## Audio Effects @@ -431,55 +446,55 @@ Wether you're using a synth or a sample, you can apply these effects: ### gain - + ### velocity - + ### cutoff - + ### resonance - + ### hcutoff - + ### hresonance - + ### bandf - + ### bandq - + ### vowel - + ### pan - + ### coarse - + ### shape - + ### crush - +
@@ -490,11 +505,11 @@ Internally, the mini notation will expand to use the actual functional JavaScrip For example, this Pattern in Mini Notation: - + is equivalent to this Pattern without Mini Notation: - + Similarly, there is an equivalent function for every aspect of the mini notation. @@ -506,6 +521,7 @@ to fit better for the larger context, while mini notation is more practical for While the Mini Notation is a powerful way to write rhythms shortly, it also has its limits. Take this example: + 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 "#". @@ -535,7 +551,7 @@ Using strings, you can also use "#". 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 (like `n`, `s`, `note`, `freq` etc), just make sure to leave the parens empty! @@ -545,25 +561,26 @@ The following functions will return a pattern. ### cat - + ### seq - + ### stack - + ### timeCat - + ## Combining Patterns You can freely mix JS patterns, mini patterns and values! For example, this pattern: ")`} /> +")`} /> While mini notation is almost always shorter, it only has a handful of modifiers: \* / ! @. When using JS patterns, there is a lot more you can do. @@ -596,131 +614,131 @@ The following functions modify a pattern temporal structure in some way. ### Pattern.slow - + ### Pattern.fast - + ### Pattern.early - + ### Pattern.late - + ### Pattern.legato - + ### Pattern.struct - + ### Pattern.euclid - + ### Pattern.euclidLegato - + ### Pattern.rev - + ### Pattern.iter - + ### Pattern.iterBack - + ## Conditional Modifiers ### Pattern.every - + ### Pattern.when - + ## Accumulation Modifiers ### Pattern.stack - + ### Pattern.superimpose - + ### Pattern.layer - + ### Pattern.off - + ### Pattern.echo - + ### Pattern.echoWith - + ## Concat Modifiers ### Pattern.seq - + ### Pattern.cat - + ## Value Modifiers ### Pattern.add - + ### Pattern.sub - + ### Pattern.mul - + ### Pattern.div - + ### Pattern.round - + ### Pattern.apply - + ### Pattern.range - + ### Pattern.chunk - + ### Pattern.chunkBack - + ## Continuous Signals @@ -729,23 +747,23 @@ They can provide streams of numbers that can be sampled at discrete points in ti ### saw - + ### sine - + ### cosine - + ### tri - + ### square - + ### Ranges from -1 to 1 @@ -753,15 +771,15 @@ There is also `saw2`, `sine2`, `cosine2`, `tri2` and `square2` which have a rang ### rand - + ### perlin - + ### irand - + ## Random Modifiers @@ -769,59 +787,59 @@ These methods add random behavior to your Patterns. ### chooseCycles - + ### Pattern.degradeBy - + ### Pattern.degrade - + ### Pattern.undegradeBy - + ### Pattern.sometimesBy - + ### Pattern.sometimes - + ### Pattern.someCyclesBy - + ### Pattern.someCycles - + ### Pattern.often - + ### Pattern.rarely - + ### Pattern.almostNever - + ### Pattern.almostAlways - + ### Pattern.never - + ### Pattern.always - +

@@ -834,19 +852,20 @@ The Tonal API, uses [tonaljs](https://github.com/tonaljs/tonal) to provide helpe Transposes all notes to the given number of semitones: -".slow(2)).note()`} /> +".slow(2)).note()`} /> This method gets really exciting when we use it with a pattern as above. Instead of numbers, scientific interval notation can be used as well: -".slow(2)).note()`} /> +".slow(2)).note()`} /> ### scale(name) Turns numbers into notes in the scale (zero indexed). Also sets scale for other scale operations, like scaleTranpose. ") @@ -871,17 +891,18 @@ Transposes notes inside the scale by the number of steps: Turns chord symbols into voicings, using the smoothest voice leading possible: -".voicings('lefthand'), "").note()`} /> +".voicings('lefthand'), "").note()`} /> ### rootNotes(octave = 2) Turns chord symbols into root notes of chords in given octave. -".rootNotes(3).note()`} /> +".rootNotes(3).note()`} /> Together with layer, struct and voicings, this can be used to create a basic backing track: ".layer( x => x.voicings('lefthand').struct("~ x").note(), x => x.rootNotes(2).note().s('sawtooth').cutoff(800) @@ -901,6 +922,7 @@ Either connect a midi device or use the IAC Driver (Mac) or Midi Through Port (L If no outputName is given, it uses the first midi output it finds. ".voicings('lefthand'), "") .midi()`} /> @@ -931,13 +953,13 @@ Now you're all set! ...or test it here: - + If you now hear sound, congratulations! If not, you can get help on the [#strudel channel in the TidalCycles discord](https://discord.com/invite/HGEdXmRkzT). ### Pattern.osc - + ## Superdirt Params diff --git a/website/src/styles/index.css b/website/src/styles/index.css index 4e4707a6..0892024b 100644 --- a/website/src/styles/index.css +++ b/website/src/styles/index.css @@ -1,3 +1,5 @@ +@import '@strudel.cycles/react/dist/style.css'; + .cm-gutters { display: none !important; }