mirror of
https://github.com/eliasstepanik/strudel.git
synced 2026-01-11 13:48:40 +00:00
tutorial updates
This commit is contained in:
parent
823115c4ec
commit
858f4f74b3
4
package-lock.json
generated
4
package-lock.json
generated
@ -12273,7 +12273,6 @@
|
||||
"version": "0.5.0",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@strudel.cycles/core": "^0.5.0",
|
||||
"acorn": "^8.8.1",
|
||||
"escodegen": "^2.0.0",
|
||||
"estree-walker": "^3.0.1"
|
||||
@ -12302,7 +12301,6 @@
|
||||
"version": "0.5.0",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@strudel.cycles/core": "^0.5.0",
|
||||
"WebDirt": "github:dktr0/WebDirt"
|
||||
}
|
||||
},
|
||||
@ -13884,7 +13882,6 @@
|
||||
"@strudel.cycles/transpiler": {
|
||||
"version": "file:packages/transpiler",
|
||||
"requires": {
|
||||
"@strudel.cycles/core": "^0.5.0",
|
||||
"acorn": "^8.8.1",
|
||||
"escodegen": "^2.0.0",
|
||||
"estree-walker": "^3.0.1"
|
||||
@ -13904,7 +13901,6 @@
|
||||
"@strudel.cycles/webdirt": {
|
||||
"version": "file:packages/webdirt",
|
||||
"requires": {
|
||||
"@strudel.cycles/core": "^0.5.0",
|
||||
"WebDirt": "github:dktr0/WebDirt"
|
||||
}
|
||||
},
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
"test-ui": "vitest --ui",
|
||||
"test-coverage": "vitest --coverage",
|
||||
"bootstrap": "lerna bootstrap",
|
||||
"setup": "npm i && npm run bootstrap && cd website && npm i",
|
||||
"setup": "npm i && npm run jsdoc-json && npm run bootstrap && cd website && npm i",
|
||||
"snapshot": "vitest run -u --silent",
|
||||
"repl": "cd website && npm run dev",
|
||||
"osc": "cd packages/osc && npm run server",
|
||||
|
||||
@ -45,12 +45,17 @@ export const SIDEBAR: Sidebar = {
|
||||
en: {
|
||||
Tutorial: [
|
||||
{ text: 'Getting Started', link: 'learn/getting-started' },
|
||||
{ text: 'Mini Notation', link: 'learn/mini-notation' },
|
||||
{ text: 'Synths, Samples & FX', link: 'learn/synths-samples-effects' },
|
||||
{ text: 'Notes', link: 'learn/notes' },
|
||||
{ text: 'Sounds', link: 'learn/sounds' },
|
||||
{ text: 'Coding syntax', link: 'learn/code' },
|
||||
{ text: 'Mini-notation', link: 'learn/mini-notation' },
|
||||
{ text: 'Samples', link: 'learn/samples' },
|
||||
{ text: 'Synths', link: 'learn/synths' },
|
||||
{ text: 'Audio effects', link: 'learn/effects' },
|
||||
{ text: 'Functions', link: 'learn/functions' },
|
||||
{ text: 'Signals', link: 'learn/signals' },
|
||||
{ text: 'Tonal', link: 'learn/tonal' },
|
||||
{ text: 'Outputs', link: 'learn/outputs' },
|
||||
{ text: 'MIDI & OSC', link: 'learn/input-output' },
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
81
website/src/pages/learn/code.mdx
Normal file
81
website/src/pages/learn/code.mdx
Normal file
@ -0,0 +1,81 @@
|
||||
---
|
||||
title: Coding syntax
|
||||
description: Strudel Tutorial - Coding syntax
|
||||
layout: ../../layouts/MainLayout.astro
|
||||
---
|
||||
|
||||
import { MiniRepl } from '../../docs/MiniRepl';
|
||||
import { JsDoc } from '../../docs/JsDoc';
|
||||
|
||||
# Strudel Code
|
||||
|
||||
Now that we have played some notes using different sounds, let's take a step back and look how we actually achieved this using _code_.
|
||||
|
||||
Let's look at this simple example again. What do we notice?
|
||||
|
||||
<MiniRepl client:idle tune={`freq("220 275 330 440").s("sine")`} />
|
||||
|
||||
- We have a word `freq` which is followed by some brackets `()` with some words/letters/numbers inside, surrounded by quotes `"a3 c#4 e4 a4"`.
|
||||
- Then we have a dot `.` followed by another similar piece of code `s("sawtooth")`.
|
||||
- We can also see these texts are _highlighted_ using colours: word `freq` is purple, the brackets `()` are grey, and the content inside the `""` are green.
|
||||
|
||||
What happens if we try to 'break' this pattern in different ways?
|
||||
|
||||
<MiniRepl client:idle tune={`freq(220 275 330 440).s(sine)`} />
|
||||
|
||||
<MiniRepl client:idle tune={`freq("220 275 330 440")s("sine")`} />
|
||||
|
||||
<MiniRepl client:idle tune={`freq["220 275 330 440"].s{"sine"}`} />
|
||||
|
||||
Ok, none of these seem to work...
|
||||
|
||||
<MiniRepl client:idle tune={`s("sine").freq("220 275 330 440")`} />
|
||||
|
||||
This one does work, but now we can't hear the four different events and frequencies anymore.
|
||||
|
||||
So what is going on here?
|
||||
|
||||
# Functions, arguments and chaining
|
||||
|
||||
So far, we've seen the following syntax:
|
||||
|
||||
```
|
||||
xxx("foo").yyy("bar")
|
||||
```
|
||||
|
||||
Generally, `xxx` and `yyy` are called [_functions_](https://en.wikipedia.org/wiki/Function_(computer_programming)), while `foo` and `bar` are called function [_arguments_ or _parameters_](https://en.wikipedia.org/wiki/Parameter_(computer_programming)).
|
||||
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](https://en.wikipedia.org/wiki/Method_chaining), because it is appended with a dot (`.`).
|
||||
|
||||
Generally, the idea with chaining is that code such as `a("this").b("that").c("other")` allows `a`, `b` and `c` functions to happen in a specified order, without needing to write them as three separate lines of code.
|
||||
You can think of this as being similar to chaining audio effects together using guitar pedals or digital audio effects.
|
||||
|
||||
Strudel makes heavy use of chained functions. Here is a more sophisticated example:
|
||||
|
||||
<MiniRepl client:idle
|
||||
tune={`note("a3 c#4 e4 a4")
|
||||
.s("sawtooth")
|
||||
.cutoff(500)
|
||||
//.delay(0.5)
|
||||
.room(0.5)`}
|
||||
/>
|
||||
|
||||
# Comments
|
||||
|
||||
The `//` in the example above is a line comment, resulting in the `delay` function being ignored.
|
||||
It is a handy way to quickly turn code on and off.
|
||||
Try uncommenting this line by deleting `//` and refreshing the pattern.
|
||||
You can also use the keyboard shortcut `cmd-/` to toggle comments on and off.
|
||||
|
||||
# Strings
|
||||
|
||||
Ok, so what about the content inside the quotes (e.g. `"a3 c#4 e4 a4"`)?
|
||||
In JavaScript, as in most programming languages, this content is referred to as being a [_string_](https://en.wikipedia.org/wiki/String_(computer_science)).
|
||||
A string is simply a sequence of individual characters.
|
||||
In TidalCycles, strings are used to write _patterns_ using the mini-notation, and you may hear the phrase _pattern string_ from time to time.
|
||||
|
||||
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](/learn/mini-notation)...
|
||||
|
||||
<br/>
|
||||
65
website/src/pages/learn/effects.mdx
Normal file
65
website/src/pages/learn/effects.mdx
Normal file
@ -0,0 +1,65 @@
|
||||
---
|
||||
title: Audio effects
|
||||
description: Strudel Tutorial - Audio effects
|
||||
layout: ../../layouts/MainLayout.astro
|
||||
---
|
||||
|
||||
import { MiniRepl } from '../../docs/MiniRepl';
|
||||
import { JsDoc } from '../../docs/JsDoc';
|
||||
|
||||
# Audio Effects
|
||||
|
||||
Wether you're using a synth or a sample, you can apply any of the following built-in audio effects.
|
||||
As you might suspect, the effects can be chained together, and they accept a pattern string as their argument.
|
||||
|
||||
# bandf
|
||||
|
||||
<JsDoc client:idle name="bandf" h={0} />
|
||||
|
||||
# bandq
|
||||
|
||||
<JsDoc client:idle name="bandq" h={0} />
|
||||
|
||||
# coarse
|
||||
|
||||
<JsDoc client:idle name="coarse" h={0} />
|
||||
|
||||
# crush
|
||||
|
||||
<JsDoc client:idle name="crush" h={0} />
|
||||
|
||||
# cutoff
|
||||
|
||||
<JsDoc client:idle name="cutoff" h={0} />
|
||||
|
||||
# gain
|
||||
|
||||
<JsDoc client:idle name="gain" h={0} />
|
||||
|
||||
# hcutoff
|
||||
|
||||
<JsDoc client:idle name="hcutoff" h={0} />
|
||||
|
||||
# hresonance
|
||||
|
||||
<JsDoc client:idle name="hresonance" h={0} />
|
||||
|
||||
# pan
|
||||
|
||||
<JsDoc client:idle name="pan" h={0} />
|
||||
|
||||
# resonance
|
||||
|
||||
<JsDoc client:idle name="resonance" h={0} />
|
||||
|
||||
# shape
|
||||
|
||||
<JsDoc client:idle name="shape" h={0} />
|
||||
|
||||
# velocity
|
||||
|
||||
<JsDoc client:idle name="velocity" h={0} />
|
||||
|
||||
# vowel
|
||||
|
||||
<JsDoc client:idle name="vowel" h={0} />
|
||||
@ -1,26 +1,49 @@
|
||||
---
|
||||
title: Getting Started
|
||||
description: Strudel Tutorial
|
||||
description: Strudel Tutorial - Getting Started
|
||||
layout: ../../layouts/MainLayout.astro
|
||||
---
|
||||
|
||||
import { MiniRepl } from '../../docs/MiniRepl';
|
||||
import { JsDoc } from '../../docs/JsDoc';
|
||||
|
||||
# Welcome
|
||||
|
||||
Welcome to the Strudel documentation pages!
|
||||
|
||||
|
||||
These pages will introduce you to [Strudel](https://strudel.tidalcycles.org/), a web-based [live coding](https://github.com/toplap/awesome-livecoding/) environment that implements the [Tidal Cycles](https://tidalcycles.org) algorithmic pattern language.
|
||||
|
||||
# What is Strudel?
|
||||
|
||||
[Strudel](https://strudel.tidalcycles.org/) is a version of [Tidal Cycles](https://tidalcycles.org) written in [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript), initiated by [Alex McLean](https://slab.org) and [Felix Roos](https://github.com/felixroos) in 2022.
|
||||
Tidal Cycles, also known as Tidal, is a language for [algorithmic pattern](https://algorithmicpattern.org), and though it is most commonly used for [making music](https://tidalcycles.org/docs/showcase), it can be used for any kind of pattern making activity, including [weaving](https://www.youtube.com/watch?v=TfEmEsusXjU).
|
||||
|
||||
Tidal was first implemented as a library written in the [Haskell](https://www.haskell.org/) functional programming language, and by itself it does not make any sound.
|
||||
To make sound, it has to be connected to a sound engine, and by default this is a [SuperCollider](https://supercollider.github.io/) plugin called [SuperDirt](https://github.com/musikinformatik/SuperDirt/).
|
||||
As such, it can be difficult for first-time users to install both Tidal Cycles and SuperDirt, as there are many small details to get right.
|
||||
Strudel however runs directly in your web browser, does not require any custom software installation, and can make sound all by itself.
|
||||
|
||||
# Strudel REPL and MiniREPL
|
||||
|
||||
The main place to actually make music with Strudel is the [Strudel REPL](https://strudel.tidalcycles.org/) ([what is a REPL?](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop)), but in these pages you will also encounter interactive "MiniREPLs" where you can listen to and edit Strudel patterns.
|
||||
Try clicking the play icon below:
|
||||
|
||||
<MiniRepl client:idle tune={`s("bd sn")`}/>
|
||||
|
||||
Then edit the text so it reads `s("bd sn cp hh")` and click the refresh icon.
|
||||
Congratulations, you have now live coded your first Strudel pattern!
|
||||
|
||||
With Strudel, you can expressively write dynamic music pieces.
|
||||
It aims to be [Tidal Cycles](https://tidalcycles.org/) for JavaScript (started by the same author).
|
||||
|
||||
You don't need to know JavaScript or Tidal Cycles to make music with Strudel.
|
||||
|
||||
This interactive tutorial will guide you through the basics of Strudel.
|
||||
|
||||
The best place to actually make music with Strudel is the [Strudel REPL](https://strudel.tidalcycles.org/).
|
||||
# Show me some demos!
|
||||
|
||||
## Show me a Demo
|
||||
To see and hear what Strudel can do, visit the [Strudel REPL](https://strudel.tidalcycles.org/) and click the Shuffle icon in the top menu bar.
|
||||
You can get a feel for Strudel by browsing and editing these examples and clicking the Refresh icon to update.
|
||||
|
||||
To get a taste of what Strudel can do, check out this track:
|
||||
Alternatively, you can get a taste of what Strudel can do by clicking play on this track:
|
||||
|
||||
<MiniRepl
|
||||
client:idle
|
||||
@ -53,93 +76,15 @@ s("bd,[~ <sd!3 sd(3,4,2)>],hh(3,4)") // drums
|
||||
.slow(3/2)`}
|
||||
/>
|
||||
|
||||
## Disclaimer
|
||||
# Strudel is a work in progress 🚧
|
||||
|
||||
- This project is still in its experimental state. In the future, parts of it might change significantly.
|
||||
- This tutorial is far from complete.
|
||||
Please note that this project is still in its experimental state.
|
||||
In the future, parts of it might change significantly.
|
||||
This tutorial is also far from complete.
|
||||
You can contribute to it clicking 'Edit this page' in the top right, or by visiting the [Strudel GitHub page](https://github.com/tidalcycles/strudel/).
|
||||
|
||||
# Playing Pitches
|
||||
# What's next?
|
||||
|
||||
Pitches are an essential building block for music. In Strudel, there are 3 different options to express a pitch:
|
||||
Head on over to the [Notes](/learn/notes) page.
|
||||
|
||||
- `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 `#`.
|
||||
|
||||
<MiniRepl client:only="react" tune={`note("a3 c#4 e4 a4")`} />
|
||||
|
||||
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:
|
||||
|
||||
<MiniRepl client:only="react" tune={`n("57 61 64 69")`} />
|
||||
|
||||
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:
|
||||
|
||||
<MiniRepl client:only="react" tune={`n("74.5 75 75.5 76")`} />
|
||||
|
||||
## freq
|
||||
|
||||
To get maximum freedom, you can also use `freq` to directly control the frequency:
|
||||
|
||||
<MiniRepl client:only="react" tune={`freq("220 275 330 440")`} />
|
||||
|
||||
In this example, we play A3 (220Hz), C#4 natural (275Hz), E4 (330Hz) and A4 (440Hz).
|
||||
|
||||
<br />
|
||||
|
||||
# Playing Sounds
|
||||
|
||||
Instead of pitches, we can also play sounds with `s`:
|
||||
|
||||
<MiniRepl client:only="react" tune={`s("bd hh sd hh")`} />
|
||||
|
||||
Similarly, we can also use `s` to change the sound of our pitches:
|
||||
|
||||
<MiniRepl client:only="react" tune={`note("a3 c#4 e4 a4").s("sawtooth")`} />
|
||||
|
||||
Try changing the sound to `square`, `triangle` or `sine`!
|
||||
|
||||
We will go into the defails of sounds and synths [later](/learn/synths-samples-effects).
|
||||
|
||||
<br />
|
||||
|
||||
# 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:
|
||||
|
||||
<MiniRepl
|
||||
client:idle
|
||||
tune={`note("a3 c#4 e4 a4")
|
||||
.s("sawtooth")
|
||||
.cutoff(500)
|
||||
//.delay(0.5)
|
||||
.room(0.5)`}
|
||||
/>
|
||||
|
||||
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..
|
||||
|
||||
<br />
|
||||
<br/>
|
||||
@ -7,16 +7,16 @@ layout: ../../layouts/MainLayout.astro
|
||||
import { MiniRepl } from '../../docs/MiniRepl';
|
||||
import { JsDoc } from '../../docs/JsDoc';
|
||||
|
||||
# Alternative Outputs
|
||||
# MIDI and OSC
|
||||
|
||||
The default audio output of Strudel uses the Web Audio API.
|
||||
It is also possible to use strudel with MIDI and OSC / Superdirt instead.
|
||||
The default audio output of Strudel uses the [Web Audio API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API).
|
||||
It is also possible to use Strudel with MIDI and OSC / [SuperDirt](https://github.com/musikinformatik/SuperDirt/) instead.
|
||||
|
||||
# MIDI API
|
||||
|
||||
Strudel also supports midi via [webmidi](https://npmjs.com/package/webmidi).
|
||||
|
||||
### midi(outputName?)
|
||||
## midi(outputName?)
|
||||
|
||||
Either connect a midi device or use the IAC Driver (Mac) or Midi Through Port (Linux) for internal midi messages.
|
||||
If no outputName is given, it uses the first midi output it finds.
|
||||
@ -29,14 +29,14 @@ If no outputName is given, it uses the first midi output it finds.
|
||||
|
||||
In the console, you will see a log of the available MIDI devices as soon as you run the code, e.g. `Midi connected! Using "Midi Through Port-0".`
|
||||
|
||||
# Superdirt API
|
||||
# SuperDirt API
|
||||
|
||||
In mainline tidal, the actual sound is generated via Superdirt, which runs inside Supercollider.
|
||||
Strudel also supports using Superdirt as a backend, although it requires some developer tooling to run.
|
||||
In mainline tidal, the actual sound is generated via [SuperDirt](https://github.com/musikinformatik/SuperDirt/), which runs inside SuperCollider.
|
||||
Strudel also supports using [SuperDirt](https://github.com/musikinformatik/SuperDirt/) as a backend, although it requires some developer tooling to run.
|
||||
|
||||
## Prequisites
|
||||
|
||||
Getting Superdirt to work with Strudel, you need to
|
||||
Getting [SuperDirt](https://github.com/musikinformatik/SuperDirt/) to work with Strudel, you need to
|
||||
|
||||
1. install SuperCollider + sc3 plugins, see [Tidal Docs](https://tidalcycles.org/docs/) (Install Tidal) for more info.
|
||||
2. install [node.js](https://nodejs.org/en/)
|
||||
@ -61,10 +61,12 @@ If you now hear sound, congratulations! If not, you can get help on the [#strude
|
||||
|
||||
<JsDoc client:idle name="Pattern.osc" h={0} />
|
||||
|
||||
## Superdirt Params
|
||||
## SuperDirt Params
|
||||
|
||||
The following functions can be used with superdirt:
|
||||
The following functions can be used with [SuperDirt](https://github.com/musikinformatik/SuperDirt/):
|
||||
|
||||
`s n note freq channel orbit cutoff resonance hcutoff hresonance bandf bandq djf vowel cut begin end loop fadeTime speed unitA gain amp accelerate crush coarse delay lock leslie lrate lsize pan panspan pansplay room size dry shape squiz waveloss attack decay octave detune tremolodepth`
|
||||
|
||||
Please refer to [Tidal Docs](https://tidalcycles.org/) for more info.
|
||||
|
||||
<br/>
|
||||
@ -6,10 +6,13 @@ layout: ../../layouts/MainLayout.astro
|
||||
import { MiniRepl } from '../../docs/MiniRepl';
|
||||
import { JsDoc } from '../../docs/JsDoc';
|
||||
|
||||
# Mini Notation
|
||||
# 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:
|
||||
Similar to [Haskell Tidal Cycles](https://tidalcycles.org/docs/), Strudel has an "embedded mini-notation" (also called a [domain-specific language, or DSL](https://en.wikipedia.org/wiki/Domain-specific_language)) that is designed for writing rhythmic patterns using little amounts of text.
|
||||
If you've seen any Tidal code before, you may have noticed the mini-notation and wondered what it's all about.
|
||||
It's one of the main features of Tidal, and although it might look like a strange way to notate music and other patterns, you will soon see how powerful it can be.
|
||||
|
||||
Before diving deeper into the details, here is a flavour of how the mini-notation looks like:
|
||||
|
||||
<MiniRepl
|
||||
client:idle
|
||||
@ -36,92 +39,197 @@ Before diving deeper into the details, here is a flavor of how the mini language
|
||||
]/16\`)`}
|
||||
/>
|
||||
|
||||
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.
|
||||
Note that the snippet above is enclosed in backticks (`), which allows you to write multi-line strings.
|
||||
|
||||
## Sequences
|
||||
You can also use regular double quotes (`"`) for single line mini-notation, as we have done already.
|
||||
|
||||
# Sequences of events in a cycle
|
||||
|
||||
We can play more notes by separating them with spaces:
|
||||
|
||||
<MiniRepl client:only="react" tune={`note("e5 b4 d5 c5")`} />
|
||||
<MiniRepl client:idle tune={`note("e5 b4 d5 c5")`} />
|
||||
|
||||
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
|
||||
<MiniRepl client:idle tune={`note("e5 b4 d5 c5 e5 b4 d5 c5")`} />
|
||||
|
||||
We can slow the sequence down by enclosing it in brackets and dividing it by a number:
|
||||
Note that the overall duration of time does not change, and instead each note length descreases.
|
||||
This is a key idea, as it illustrates the 'Cycle' in TidalCycles!
|
||||
|
||||
<MiniRepl client:only="react" tune={`note("[e5 b4 d5 c5]/2")`} />
|
||||
Each space-separated note in this sequence is an _event_.
|
||||
The time duration of each event is based on the speed or tempo of the cycle, and how many events are present.
|
||||
Taking the two examples above, we have four and eight events respectively, and since they have the same cycle duration, they each have to fit their events inside the same amount of time.
|
||||
|
||||
This is perhaps counter-intuitive if you are used to adding notes in a sequencer or piano roll and the overall length increasing.
|
||||
But, it will begin to make sense as we go through more elements of mini-notation.
|
||||
|
||||
# Division
|
||||
|
||||
We can slow the sequence down by enclosing it in brackets and dividing it by a number (`/2`):
|
||||
|
||||
<MiniRepl client:idle tune={`note("[e5 b4 d5 c5]/2")`} />
|
||||
|
||||
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.
|
||||
You can also use decimal numbers for any tempo you like (`/2.75`).
|
||||
|
||||
## Angle Brackets
|
||||
<MiniRepl client:idle tune={`note("[e5 b4 d5 c5]/2.75")`} />
|
||||
|
||||
Using angle brackets, we can define the sequence length based on the number of children:
|
||||
# Angle Brackets
|
||||
|
||||
<MiniRepl client:only="react" tune={`note("<e5 b4 d5 c5>")`} />
|
||||
Using angle brackets `<>`, we can define the sequence length based on the number of events:
|
||||
|
||||
<MiniRepl client:idle tune={`note("<e5 b4 d5 c5>")`} />
|
||||
|
||||
The above snippet is the same as:
|
||||
|
||||
<MiniRepl client:only="react" tune={`note("[e5 b4 d5 c5]/4")`} />
|
||||
<MiniRepl client:idle tune={`note("[e5 b4 d5 c5]/4")`} />
|
||||
|
||||
The advantage of the angle brackets, is that we can add more children without needing to change the number at the end.
|
||||
The advantage of the angle brackets, is that we can add more events without needing to change the number at the end.
|
||||
|
||||
## Multiplication
|
||||
<MiniRepl client:idle tune={`note("<e5 b4 d5 c5 e5>")`} />
|
||||
|
||||
Contrary to division, a sequence can be sped up by multiplying it by a number:
|
||||
<MiniRepl client:idle tune={`note("<e5 b4 d5 c5 e5 b4>")`} />
|
||||
|
||||
<MiniRepl client:only="react" tune={`note("[e5 b4 d5 c5]*2")`} />
|
||||
This is more similar to traditional music sequencers and piano rolls, where adding a note increases the perceived overall duration.
|
||||
|
||||
The multiplication by 2 here means that the sequence will play twice a cycle.
|
||||
# Multiplication
|
||||
|
||||
## Bracket Nesting
|
||||
Contrary to division, a sequence can be sped up by multiplying it by a number using the asterisk symbol (`*`):
|
||||
|
||||
To create more interesting rhythms, you can nest sequences with brackets, like this:
|
||||
<MiniRepl client:idle tune={`note("[e5 b4 d5 c5]*2")`} />
|
||||
|
||||
<MiniRepl client:only="react" tune={`note("e5 [b4 c5] d5 [c5 b4]")`} />
|
||||
The multiplication by two here means that the sequence will play twice a cycle.
|
||||
|
||||
## Rests
|
||||
As with divisions, multiplications can be decimal (`*2.75`):
|
||||
|
||||
The "~" represents a rest:
|
||||
<MiniRepl client:idle tune={`note("[e5 b4 d5 c5]*2.75")`} />
|
||||
|
||||
<MiniRepl client:only="react" tune={`note("[b4 [~ c5] d5 e5]")`} />
|
||||
Actually, this is not true, but this will be [fixed](https://github.com/tidalcycles/strudel/issues/314) :)
|
||||
|
||||
## Parallel
|
||||
# Subdividing time with bracket nesting
|
||||
|
||||
Using commas, we can play chords:
|
||||
To create more interesting rhythms, you can _nest_ or _enclose_ sequences (put sequences inside sequences) with brackets `[]`, like this:
|
||||
|
||||
<MiniRepl client:only="react" tune={`note("g3,b3,e4")`} />
|
||||
Compare the difference between the following:
|
||||
|
||||
To play multiple chords in a sequence, we have to wrap them in brackets:
|
||||
<MiniRepl client:idle tune={`note("e5 b4 c5 d5 c5 b4")`} />
|
||||
<MiniRepl client:idle tune={`note("e5 [b4 c5] d5 c5 b4")`} />
|
||||
<MiniRepl client:idle tune={`note("e5 [b4 c5] d5 [c5 b4]")`} />
|
||||
<MiniRepl client:idle tune={`note("e5 [b4 c5] d5 [c5 b4 d5 e5]")`} />
|
||||
<MiniRepl client:idle tune={`note("e5 [b4 c5] d5 [c5 b4 [d5 e5]]")`} />
|
||||
|
||||
<MiniRepl client:only="react" tune={`note("<[g3,b3,e4] [a3,c3,e4] [b3,d3,f#4] [b3,e4,g4]>")`} />
|
||||
What's going on here? When we nest/enclose multiple events inside brackets (`[]`), their duration becomes the length of one event in the outer sequence.
|
||||
|
||||
## Elongation
|
||||
This is a very simple change to make, but it has profound consequences.
|
||||
Remember what we said earlier about how the cycles in tidal stay the same length, and the individual event lengths are divided up in this cycle?
|
||||
Well, what this means is that in TidalCycles, not only can you divide time any way you want, and you can also subdivide time any way you want!
|
||||
|
||||
# Rests
|
||||
|
||||
The "~" represents a rest, and will create silence between other events:
|
||||
|
||||
<MiniRepl client:idle tune={`note("[b4 [~ c5] d5 e5]")`} />
|
||||
|
||||
# Parallel / polyphony
|
||||
|
||||
Using commas, we can play chords.
|
||||
The following are the same:
|
||||
|
||||
<MiniRepl client:idle tune={`note("[g3,b3,e4]")`} />
|
||||
<MiniRepl client:idle tune={`note("g3,b3,e4")`} />
|
||||
|
||||
But to play multiple chords in a sequence, we have to wrap them in brackets:
|
||||
|
||||
<MiniRepl client:idle tune={`note("<[g3,b3,e4] [a3,c3,e4] [b3,d3,f#4] [b3,e4,g4]>")`} />
|
||||
|
||||
# Elongation
|
||||
|
||||
With the "@" symbol, we can specify temporal "weight" of a sequence child:
|
||||
|
||||
<MiniRepl client:only="react" tune={`note("<[g3,b3,e4]@2 [a3,c3,e4] [b3,d3,f#4]>")`} />
|
||||
<MiniRepl client:idle tune={`note("<[g3,b3,e4]@2 [a3,c3,e4] [b3,d3,f#4]>")`} />
|
||||
|
||||
Here, the first chord has a weight of 2, making it twice the length of the other chords. The default weight is 1.
|
||||
|
||||
## Replication
|
||||
# Replication
|
||||
|
||||
Using "!" we can repeat without speeding up:
|
||||
|
||||
<MiniRepl client:only="react" tune={`note("<[g3,b3,e4]!2 [a3,c3,e4] [b3,d3,f#4]>")`} />
|
||||
<MiniRepl client:idle tune={`note("<[g3,b3,e4]!2 [a3,c3,e4] [b3,d3,f#4]>")`} />
|
||||
|
||||
In essence, the `x!n` is like a shortcut for `[x*n]@n`.
|
||||
|
||||
## Euclidian
|
||||
# Mini-notation review
|
||||
|
||||
Using round brackets, we can create rhythmical sub-divisions based on three parameters: beats, segments and offset.
|
||||
The first parameter controls how may beats will be played.
|
||||
The second parameter controls the total amount of segments the beats will be distributed over.
|
||||
The third (optional) parameter controls the starting position for distributing the beats.
|
||||
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).
|
||||
To recap what we've learned so far, compare the following patterns:
|
||||
|
||||
<MiniRepl client:only="react" tune={`note("e5(2,8) b4(3,8) d5(2,8) c5(3,8)").slow(4)`} />
|
||||
<MiniRepl client:idle tune={`note("<g3 b3 e4 [a3,c3,e4] [b3,d3,f#4]>")`} />
|
||||
<MiniRepl client:idle tune={`note("<[g3,b3,e4] [a3,c3,e4] [b3,d3,f#4]>")`} />
|
||||
<MiniRepl client:idle tune={`note("<[g3,b3,e4]/2 [a3,c3,e4] [b3,d3,f#4]>")`} />
|
||||
<MiniRepl client:idle tune={`note("<[g3,b3,e4]*2 [a3,c3,e4] [b3,d3,f#4]>")`} />
|
||||
<MiniRepl client:idle tune={`note("<[g3,b3,e4] _ [a3,c3,e4] [b3,d3,f#4]>")`} />
|
||||
<MiniRepl client:idle tune={`note("<[g3,b3,e4]@2 [a3,c3,e4] [b3,d3,f#4]>")`} />
|
||||
<MiniRepl client:idle tune={`note("<[g3,b3,e4]!2 [a3,c3,e4] [b3,d3,f#4]>")`} />
|
||||
|
||||
# Euclidian rhythms
|
||||
|
||||
Using round brackets after an event, we can create rhythmical sub-divisions based on three parameters: `beats`, `segments` and `offset`.
|
||||
This algorithm can be found in many different types of music software, and is often referred to as a [Euclidean rhythm](https://en.wikipedia.org/wiki/Euclidean_rhythm) sequencer, after computer scientist Godfriend Toussaint.
|
||||
Why is it interesting? Well, consider the following simple example:
|
||||
|
||||
<MiniRepl client:idle tune={`s("bd(3,8,0)")`} />
|
||||
|
||||
Sound familiar?
|
||||
This is a popular Euclidian rhythm going by various names, such as "Pop Clave".
|
||||
These rhythms can be found in all musical cultures, and the Euclidian rhythm algorithm allows us to express them extremely easily.
|
||||
Writing this rhythm out in full require describing:
|
||||
|
||||
<MiniRepl client:idle tune={`s("bd ~ ~ bd ~ ~ bd ~")`} />
|
||||
|
||||
But using the Euclidian rhythm notation, we only need to express "3 beats over 8 segments, starting on position 1".
|
||||
|
||||
This makes it easy to write patterns with interesting rhythmic structures and variations that still sound familiar:
|
||||
|
||||
<MiniRepl client:idle tune={`note("e5(2,8) b4(3,8) d5(2,8) c5(3,8)").slow(4)`} />
|
||||
|
||||
Note that since the example above does not use the third `offset` parameter, it can be written simply as `"(3,8)"`.
|
||||
|
||||
<MiniRepl client:idle tune={`s("bd(3,8)")`} />
|
||||
|
||||
Let's look at those three parameters in detail.
|
||||
|
||||
## Beats
|
||||
|
||||
`beats`: the first parameter controls how may beats will be played.
|
||||
Compare these:
|
||||
|
||||
<MiniRepl client:idle tune={`s("bd(2,8)")`} />
|
||||
<MiniRepl client:idle tune={`s("bd(5,8)")`} />
|
||||
<MiniRepl client:idle tune={`s("bd(7,8)")`} />
|
||||
|
||||
## Segments
|
||||
|
||||
`segments`: the second parameter controls the total amount of segments the beats will be distributed over:
|
||||
|
||||
<MiniRepl client:idle tune={`s("bd(3,4)")`} />
|
||||
<MiniRepl client:idle tune={`s("bd(3,8)")`} />
|
||||
<MiniRepl client:idle tune={`s("bd(3,13)")`} />
|
||||
|
||||
## Offsets
|
||||
|
||||
`offset`: the third (optional) parameter controls the starting position for distributing the beats.
|
||||
We need a secondary rhythm to hear the difference:
|
||||
|
||||
<MiniRepl client:idle tune={`s("bd(3,8,0), hh cp")`} />
|
||||
<MiniRepl client:idle tune={`s("bd(3,8,3), hh cp")`} />
|
||||
<MiniRepl client:idle tune={`s("bd(3,8,5), hh cp")`} />
|
||||
|
||||
# Mini-notation exercise
|
||||
|
||||
The most fun thing about the mini-notation, is that everything you have just learned can be combined in various ways!
|
||||
|
||||
Starting with this one `n`, can you make a _pattern string_ that uses every single mini-notation element above?
|
||||
|
||||
<MiniRepl client:idle tune={`n("60")`} />
|
||||
|
||||
<br/>
|
||||
|
||||
88
website/src/pages/learn/notes.mdx
Normal file
88
website/src/pages/learn/notes.mdx
Normal file
@ -0,0 +1,88 @@
|
||||
---
|
||||
title: Notes
|
||||
description: Strudel Tutorial - Notes
|
||||
layout: ../../layouts/MainLayout.astro
|
||||
---
|
||||
|
||||
import { MiniRepl } from '../../docs/MiniRepl';
|
||||
import { JsDoc } from '../../docs/JsDoc';
|
||||
|
||||
# Notes
|
||||
|
||||
Pitches are an essential building block for music.
|
||||
In Strudel, there are three different ways to express a pitch, `note`, `n` and `freq`.
|
||||
Here's the same pattern written in three different ways:
|
||||
|
||||
- `note`: letter notation, good for those who are familiar with western music theory:
|
||||
<MiniRepl client:idle tune={`note("a3 c#4 e4 a4")`} />
|
||||
|
||||
- `n`: number notation, good for those who want to use recognisable pitches, but don't care about music theory:
|
||||
<MiniRepl client:idle tune={`n("57 61 64 69")`} />
|
||||
|
||||
- `freq`: frequency notation, good for those who want to go beyond standardised tuning systems:
|
||||
<MiniRepl client:idle tune={`freq("220 275 330 440")`} />
|
||||
|
||||
Let's look at `note`, `n` and `freq` in more detail...
|
||||
|
||||
# `note`
|
||||
|
||||
Notes are notated with the note letter, followed by the octave number. You can notate flats with `b` and sharps with `#`.
|
||||
|
||||
<MiniRepl client:idle tune={`note("a3 c#4 e4 a4")`} />
|
||||
|
||||
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 prefer, you can also use numbers with `n` instead:
|
||||
|
||||
<MiniRepl client:idle tune={`n("57 61 64 69")`} />
|
||||
|
||||
These numbers are interpreted as so called [MIDI numbers](https://www.inspiredacoustics.com/en/MIDI_note_numbers_and_center_frequencies), where adjacent whole numbers are one 'semitone' apart.
|
||||
|
||||
You could also write decimal numbers to get 'microtonal' pitches (in between the black and white piano notes):
|
||||
|
||||
<MiniRepl client:idle tune={`n("74.5 75 75.5 76")`} />
|
||||
|
||||
# `freq`
|
||||
|
||||
To get maximum freedom, you can also use `freq` to directly control the frequency:
|
||||
|
||||
<MiniRepl client:idle tune={`freq("220 275 330 440")`} />
|
||||
|
||||
## Hearing and frequency
|
||||
|
||||
In the above example, we play A3 (220Hz), C#4 natural (275Hz), E4 (330Hz) and A4 (440Hz), mirroring our previous examples.
|
||||
|
||||
But can you hear the difference between these individual frequencies?
|
||||
|
||||
<MiniRepl client:idle tune={`freq("220 221 223 224")`} />
|
||||
|
||||
How about these?
|
||||
|
||||
<MiniRepl client:idle tune={`freq("2020 2021 2023 2024")`} />
|
||||
|
||||
The higher we go up...
|
||||
|
||||
<MiniRepl client:idle tune={`freq("5020 5021 5023 5024")`} />
|
||||
|
||||
The less distance we can hear between the frequencies!
|
||||
|
||||
<MiniRepl client:idle tune={`freq("10020 10021 10023 10024")`} />
|
||||
|
||||
Why is this? [Human hearing operates logarithmically](https://www.audiocheck.net/soundtests_nonlinear.php).
|
||||
|
||||
# From notes to sounds
|
||||
|
||||
In this page, when we played a pattern of notes like this:
|
||||
|
||||
<MiniRepl client:idle tune={`note("a3 c#4 e4 a4")`} />
|
||||
|
||||
We heard a simple synthesised sound, in fact we heard a [square wave oscillator](https://en.wikipedia.org/wiki/Square_wave).
|
||||
|
||||
This is the default synthesiser used by Strudel, but how do we then make different sounds in Strudel?
|
||||
|
||||
Let's find out in the next page on [Sounds](/learn/sounds).
|
||||
|
||||
<br/>
|
||||
215
website/src/pages/learn/samples.mdx
Normal file
215
website/src/pages/learn/samples.mdx
Normal file
@ -0,0 +1,215 @@
|
||||
---
|
||||
title: Notes
|
||||
description: Strudel Tutorial - Notes
|
||||
layout: ../../layouts/MainLayout.astro
|
||||
---
|
||||
|
||||
import { MiniRepl } from '../../docs/MiniRepl';
|
||||
import { JsDoc } from '../../docs/JsDoc';
|
||||
|
||||
# Samples
|
||||
|
||||
# Default Sample Map
|
||||
|
||||
As we have seen, `s` can play back audio samples:
|
||||
|
||||
<MiniRepl client:idle client:idle tune={`s("bd sd,hh*8,misc/2")`} />
|
||||
|
||||
These sounds come from Strudels in-built default "sample map".
|
||||
To know which sounds are available, open the [default sample map](https://strudel.tidalcycles.org/EmuSP12.json).
|
||||
|
||||
# Custom Sample Maps
|
||||
|
||||
You can load your own sample map using the `samples` function.
|
||||
In this example we create a map using sounds from the default sample map:
|
||||
|
||||
<MiniRepl client:idle
|
||||
tune={`samples({
|
||||
bd: 'bd/BT0AADA.wav',
|
||||
sd: 'sd/rytm-01-classic.wav',
|
||||
hh: 'hh27/000_hh27closedhh.wav',
|
||||
}, 'https://raw.githubusercontent.com/tidalcycles/Dirt-Samples/master/');
|
||||
s("bd sd,hh*8")`}
|
||||
/>
|
||||
|
||||
When you load your own samples, you can choose the names that you will then refer to in your pattern string inside the `s` function.
|
||||
Compare with this example which uses the same samples, but with different names.
|
||||
|
||||
<MiniRepl client:idle
|
||||
tune={`samples({
|
||||
bassdrum: 'bd/BT0AADA.wav',
|
||||
snaredrum: 'sd/rytm-01-classic.wav',
|
||||
hihat: 'hh27/000_hh27closedhh.wav',
|
||||
}, 'https://raw.githubusercontent.com/tidalcycles/Dirt-Samples/master/');
|
||||
s("bassdrum snaredrum, hihat*8")`}
|
||||
/>
|
||||
|
||||
Here we have changed the "map" to include longer sample names.
|
||||
|
||||
# Loading Custom Samples
|
||||
|
||||
The `samples` function has two arguments:
|
||||
- A [JavaScript object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object) that maps sound names to audio file paths.
|
||||
- A base URL that comes before each path describing where the sample folder can be found online.
|
||||
- Make sure your base URL ends with a slash, while your sample paths do **not** begin with one!
|
||||
|
||||
To see how this looks in practice, compare the [DirtSamples GitHub repo](https://github.com/tidalcycles/Dirt-Samples) with the previous sample map example.
|
||||
|
||||
Because GitHub is a popular place for uploading open source samples, it has its own shortcut:
|
||||
|
||||
<MiniRepl client:idle
|
||||
tune={`samples({
|
||||
bd: 'bd/BT0AADA.wav',
|
||||
sd: 'sd/rytm-01-classic.wav',
|
||||
hh: 'hh27/000_hh27closedhh.wav',
|
||||
}, 'github:tidalcycles/Dirt-Samples/master/');
|
||||
s("bd sd,hh*8")`}
|
||||
/>
|
||||
|
||||
The format is `github:user/repo/branch/`.
|
||||
|
||||
Let's see another example, this time based on the following GitHub repo: https://github.com/jarmitage/jarmitage.github.io.
|
||||
We can see there are some guitar samples inside the `/samples` folder, so let's try to load them:
|
||||
|
||||
<MiniRepl client:idle
|
||||
tune={`samples({
|
||||
g0: 'samples/guitar/guitar_0.wav',
|
||||
g1: 'samples/guitar/guitar_1.wav',
|
||||
g2: 'samples/guitar/guitar_2.wav',
|
||||
g3: 'samples/guitar/guitar_3.wav',
|
||||
g4: 'samples/guitar/guitar_4.wav'
|
||||
}, 'github:jarmitage/jarmitage.github.io/master/');
|
||||
s("[g0 g1 g2 g3 g4]/5")`}
|
||||
/>
|
||||
|
||||
# Loading Multiple Samples per Sound
|
||||
|
||||
It is also possible, to declare multiple files for one sound, using the array notation:
|
||||
|
||||
<MiniRepl client:idle
|
||||
tune={`samples({
|
||||
bd: ['bd/BT0AADA.wav','bd/BT0AAD0.wav'],
|
||||
sd: ['sd/rytm-01-classic.wav','sd/rytm-00-hard.wav'],
|
||||
hh: ['hh27/000_hh27closedhh.wav','hh/000_hh3closedhh.wav'],
|
||||
}, 'github:tidalcycles/Dirt-Samples/master/');
|
||||
s("<bd:0 bd:1>,~ <sd:0 sd:1>,[hh:0 hh:1]*2")`}
|
||||
/>
|
||||
|
||||
The `:0` `:1` etc. are the indices of the array.
|
||||
The sample number can also be set using `n`:
|
||||
|
||||
<MiniRepl client:idle
|
||||
tune={`samples({
|
||||
bd: ['bd/BT0AADA.wav','bd/BT0AAD0.wav'],
|
||||
sd: ['sd/rytm-01-classic.wav','sd/rytm-00-hard.wav'],
|
||||
hh: ['hh27/000_hh27closedhh.wav','hh/000_hh3closedhh.wav'],
|
||||
}, 'github:tidalcycles/Dirt-Samples/master/');
|
||||
s("bd,~ sd,hh*4").n("<0 1>")`}
|
||||
/>
|
||||
|
||||
In that case, we might load our guitar sample map a different way:
|
||||
|
||||
<MiniRepl client:idle
|
||||
tune={`samples({
|
||||
guitar: [
|
||||
'samples/guitar/guitar_0.wav',
|
||||
'samples/guitar/guitar_1.wav',
|
||||
'samples/guitar/guitar_2.wav',
|
||||
'samples/guitar/guitar_3.wav',
|
||||
'samples/guitar/guitar_4.wav'
|
||||
]
|
||||
}, 'github:jarmitage/jarmitage.github.io/master/');
|
||||
s("[guitar:0 guitar:1 guitar:2 guitar:3 guitar:4]/5")`}
|
||||
/>
|
||||
|
||||
And as above, we can choose the sample number using `n` for even more flexibility:
|
||||
|
||||
<MiniRepl client:idle
|
||||
tune={`samples({
|
||||
guitar: [
|
||||
'samples/guitar/guitar_0.wav',
|
||||
'samples/guitar/guitar_1.wav',
|
||||
'samples/guitar/guitar_2.wav',
|
||||
'samples/guitar/guitar_3.wav',
|
||||
'samples/guitar/guitar_4.wav'
|
||||
]
|
||||
}, 'github:jarmitage/jarmitage.github.io/master/');
|
||||
n("<0 1 2 3 4>").s("guitar")`}
|
||||
/>
|
||||
|
||||
# Pitched Sounds
|
||||
|
||||
For pitched sounds, you can use `note`, just like with synths:
|
||||
|
||||
<MiniRepl client:idle
|
||||
tune={`samples({
|
||||
'gtr': 'gtr/0001_cleanC.wav',
|
||||
}, 'github:tidalcycles/Dirt-Samples/master/');
|
||||
note("g3 [bb3 c4] <g4 f4 eb4 f3>@2").s('gtr').gain(.5)`}
|
||||
/>
|
||||
|
||||
Here, the guitar samples will overlap, because they always play till the end.
|
||||
If we want them to behave more like a synth, we can add `clip(1)`:
|
||||
|
||||
<MiniRepl client:idle
|
||||
tune={`samples({
|
||||
'gtr': 'gtr/0001_cleanC.wav',
|
||||
}, 'github:tidalcycles/Dirt-Samples/master/');
|
||||
note("g3 [bb3 c4] <g4 f4 eb4 f3>@2").s('gtr').clip(1)
|
||||
.gain(.5)`}
|
||||
/>
|
||||
|
||||
# Base Pitch
|
||||
|
||||
If we have 2 samples with different base pitches, we can make them in tune by specifying the pitch like this:
|
||||
|
||||
<MiniRepl client:idle
|
||||
tune={`samples({
|
||||
'gtr': 'gtr/0001_cleanC.wav',
|
||||
'moog': { 'g3': 'moog/005_Mighty%20Moog%20G3.wav' },
|
||||
}, 'github:tidalcycles/Dirt-Samples/master/');
|
||||
note("g3 [bb3 c4] <g4 f4 eb4 f3>@2").s("gtr,moog").clip(1)
|
||||
.gain(.5)`}
|
||||
/>
|
||||
|
||||
If a sample has no pitch set, `c3` is the default.
|
||||
|
||||
We can also declare different samples for different regions of the keyboard:
|
||||
|
||||
<MiniRepl client:idle
|
||||
tune={`samples({
|
||||
'moog': {
|
||||
'g2': 'moog/004_Mighty%20Moog%20G2.wav',
|
||||
'g3': 'moog/005_Mighty%20Moog%20G3.wav',
|
||||
'g4': 'moog/006_Mighty%20Moog%20G4.wav',
|
||||
}}, 'github:tidalcycles/Dirt-Samples/master/');
|
||||
note("g2!2 <bb2 c3>!2, <c4@3 [<eb4 bb3> g4 f4]>")
|
||||
.s('moog').clip(1)
|
||||
.gain(.5)`}
|
||||
/>
|
||||
|
||||
The sampler will always pick the closest matching sample for the current note!
|
||||
|
||||
# Sampler Effects
|
||||
|
||||
Below are four different examples of sampler "effects" which are functions that can be used to change the behaviour of sample playback.
|
||||
Note that most of what you've learned already about Tidal mini-notation can be used with these functions too.
|
||||
Almost everything in Tidal can be patterned using strings!
|
||||
|
||||
### `begin`
|
||||
|
||||
<JsDoc client:idle name="Pattern.begin" h={0} />
|
||||
|
||||
### `end`
|
||||
|
||||
<JsDoc client:idle name="Pattern.end" h={0} />
|
||||
|
||||
### `loopAt`
|
||||
|
||||
<JsDoc client:idle name="Pattern.loopAt" h={0} />
|
||||
|
||||
### `chop`
|
||||
|
||||
<JsDoc client:idle name="Pattern.chop" h={0} />
|
||||
|
||||
<br/>
|
||||
40
website/src/pages/learn/sounds.mdx
Normal file
40
website/src/pages/learn/sounds.mdx
Normal file
@ -0,0 +1,40 @@
|
||||
---
|
||||
title: Sounds
|
||||
description: Strudel Tutorial - Sounds
|
||||
layout: ../../layouts/MainLayout.astro
|
||||
---
|
||||
|
||||
import { MiniRepl } from '../../docs/MiniRepl';
|
||||
import { JsDoc } from '../../docs/JsDoc';
|
||||
|
||||
# Sounds
|
||||
|
||||
We can play sounds with `s`, in two different ways:
|
||||
- `s` can trigger audio samples, where a sound file is loaded in the background and played back:
|
||||
<MiniRepl client:idle tune={`s("bd hh sd hh")`} />
|
||||
- `s` can trigger audio synthesisers, which are synthesised in real-time using code also running in the background:
|
||||
<MiniRepl client:idle tune={`s("sawtooth square triangle sine")`} />
|
||||
|
||||
You can learn more about both of these approaches in the pages [Synths](/learn/synths) and [Samples](/learn/samples).
|
||||
|
||||
# Combining notes and sounds
|
||||
|
||||
In both of the above cases, we are no longer directly controlling the `note`/`n`/`freq` of the sound heard via `s`, as we were in the [Notes](/strudel/notes) page.
|
||||
|
||||
So how can we both control the sound and the pitch? We can _combine_ `note`/`n`/`freq` with `s` to change the sound of our pitches:
|
||||
|
||||
<MiniRepl client:idle tune={`note("a3 c#4 e4 a4").s("sawtooth")`} />
|
||||
|
||||
<MiniRepl client:idle tune={`n("57 61 64 69").s("triangle")`} />
|
||||
|
||||
<MiniRepl client:idle tune={`freq("220 275 330 440").s("sine")`} />
|
||||
|
||||
What about combining different notes with different sounds at the same time?
|
||||
|
||||
<MiniRepl client:idle tune={`freq("220 275 330 440 550").s("triangle sawtooth sine")`} />
|
||||
|
||||
Hmm, something interesting is going on there, related to there being five notes and three sounds.
|
||||
|
||||
Let's now take a step back and think about the Strudel [Code](/learn/code) we've been hearing so far.
|
||||
|
||||
<br/>
|
||||
@ -1,236 +0,0 @@
|
||||
---
|
||||
title: Synths, Samples & FX
|
||||
description: Strudel Tutorial
|
||||
layout: ../../layouts/MainLayout.astro
|
||||
---
|
||||
|
||||
import { MiniRepl } from '../../docs/MiniRepl';
|
||||
import { JsDoc } from '../../docs/JsDoc';
|
||||
|
||||
# Synths, Samples & Effects
|
||||
|
||||
Let's take a closer look at how we can control synths, sounds and effects.
|
||||
|
||||
## Synths
|
||||
|
||||
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:
|
||||
|
||||
<MiniRepl client:only="react" tune={`note("c2 <eb2 <g2 g1>>").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:
|
||||
|
||||
<MiniRepl client:only="react" tune={`note("c2 <eb2 <g2 g1>>").s("<sawtooth square triangle>")`} />
|
||||
|
||||
Now we not only pattern the notes, but the sound as well!
|
||||
`sawtooth` `square` and `triangle` are the basic waveforms available in `s`.
|
||||
|
||||
### Envelope
|
||||
|
||||
You can control the envelope of a synth using the `attack`, `decay`, `sustain` and `release` functions:
|
||||
|
||||
<MiniRepl
|
||||
client:idle
|
||||
tune={`note("c2 <eb2 <g2 g1>>").s('sawtooth')
|
||||
.attack(.1).decay(.1).sustain(.2).release(.1)`}
|
||||
/>
|
||||
|
||||
## Samples
|
||||
|
||||
Besides Synths, `s` can also play back samples:
|
||||
|
||||
<MiniRepl client:only="react" tune={`s("bd sd,hh*8,misc/2")`} />
|
||||
|
||||
To know which sounds are available, open the [default sample map](https://strudel.tidalcycles.org/EmuSP12.json)
|
||||
|
||||
### Custom Sample Maps
|
||||
|
||||
You can load your own sample map like this:
|
||||
|
||||
<MiniRepl
|
||||
client:idle
|
||||
tune={`samples({
|
||||
bd: 'bd/BT0AADA.wav',
|
||||
sd: 'sd/rytm-01-classic.wav',
|
||||
hh: 'hh27/000_hh27closedhh.wav',
|
||||
}, 'https://raw.githubusercontent.com/tidalcycles/Dirt-Samples/master/');
|
||||
s("bd sd,hh*8")`}
|
||||
/>
|
||||
|
||||
The `samples` function takes an object that maps sound names to audio file paths.
|
||||
The second argument is the base URL that comes before each path. Make sure your base URL ends with a slash, while your sample paths do **not** begin with one.
|
||||
|
||||
Because github is a popular choice to dump samples, there is a shortcut for that:
|
||||
|
||||
<MiniRepl
|
||||
client:idle
|
||||
tune={`samples({
|
||||
bd: 'bd/BT0AADA.wav',
|
||||
sd: 'sd/rytm-01-classic.wav',
|
||||
hh: 'hh27/000_hh27closedhh.wav',
|
||||
}, 'github:tidalcycles/Dirt-Samples/master/');
|
||||
s("bd sd,hh*8")`}
|
||||
/>
|
||||
|
||||
The format is `github:user/repo/branch/`.
|
||||
|
||||
### Multiple Samples per Sound
|
||||
|
||||
It is also possible, to declare multiple files for one sound, using the array notation:
|
||||
|
||||
<MiniRepl
|
||||
client:idle
|
||||
tune={`samples({
|
||||
bd: ['bd/BT0AADA.wav','bd/BT0AAD0.wav'],
|
||||
sd: ['sd/rytm-01-classic.wav','sd/rytm-00-hard.wav'],
|
||||
hh: ['hh27/000_hh27closedhh.wav','hh/000_hh3closedhh.wav'],
|
||||
}, 'github:tidalcycles/Dirt-Samples/master/');
|
||||
s("<bd:0 bd:1>,~ <sd:0 sd:1>,[hh:0 hh:1]*2")`}
|
||||
/>
|
||||
|
||||
The `:0` `:1` etc. are the indices of the array.
|
||||
The sample number can also be set using `n`:
|
||||
|
||||
<MiniRepl
|
||||
client:idle
|
||||
tune={`samples({
|
||||
bd: ['bd/BT0AADA.wav','bd/BT0AAD0.wav'],
|
||||
sd: ['sd/rytm-01-classic.wav','sd/rytm-00-hard.wav'],
|
||||
hh: ['hh27/000_hh27closedhh.wav','hh/000_hh3closedhh.wav'],
|
||||
}, 'github:tidalcycles/Dirt-Samples/master/');
|
||||
s("bd,~ sd,hh*4").n("<0 1>")`}
|
||||
/>
|
||||
|
||||
### Pitched Sounds
|
||||
|
||||
For pitched sounds, you can use `note`, just like with synths:
|
||||
|
||||
<MiniRepl
|
||||
client:idle
|
||||
tune={`samples({
|
||||
'gtr': 'gtr/0001_cleanC.wav',
|
||||
}, 'github:tidalcycles/Dirt-Samples/master/');
|
||||
note("g3 [bb3 c4] <g4 f4 eb4 f3>@2").s('gtr').gain(.5)`}
|
||||
/>
|
||||
|
||||
Here, the guitar samples will overlap, because they always play till the end.
|
||||
If we want them to behave more like a synth, we can add `clip(1)`:
|
||||
|
||||
<MiniRepl
|
||||
client:idle
|
||||
tune={`samples({
|
||||
'gtr': 'gtr/0001_cleanC.wav',
|
||||
}, 'github:tidalcycles/Dirt-Samples/master/');
|
||||
note("g3 [bb3 c4] <g4 f4 eb4 f3>@2").s('gtr').clip(1)
|
||||
.gain(.5)`}
|
||||
/>
|
||||
|
||||
### Base Pitch
|
||||
|
||||
If we have 2 samples with different base pitches, we can make them in tune by specifying the pitch like this:
|
||||
|
||||
<MiniRepl
|
||||
client:idle
|
||||
tune={`samples({
|
||||
'gtr': 'gtr/0001_cleanC.wav',
|
||||
'moog': { 'g3': 'moog/005_Mighty%20Moog%20G3.wav' },
|
||||
}, 'github:tidalcycles/Dirt-Samples/master/');
|
||||
note("g3 [bb3 c4] <g4 f4 eb4 f3>@2").s("gtr,moog").clip(1)
|
||||
.gain(.5)`}
|
||||
/>
|
||||
|
||||
If a sample has no pitch set, `c3` is the default.
|
||||
|
||||
We can also declare different samples for different regions of the keyboard:
|
||||
|
||||
<MiniRepl
|
||||
client:idle
|
||||
tune={`samples({
|
||||
'moog': {
|
||||
'g2': 'moog/004_Mighty%20Moog%20G2.wav',
|
||||
'g3': 'moog/005_Mighty%20Moog%20G3.wav',
|
||||
'g4': 'moog/006_Mighty%20Moog%20G4.wav',
|
||||
}}, 'github:tidalcycles/Dirt-Samples/master/');
|
||||
note("g2!2 <bb2 c3>!2, <c4@3 [<eb4 bb3> g4 f4]>")
|
||||
.s('moog').clip(1)
|
||||
.gain(.5)`}
|
||||
/>
|
||||
|
||||
The sampler will always pick the closest matching sample for the current note!
|
||||
|
||||
## Sampler Effects
|
||||
|
||||
### begin
|
||||
|
||||
<JsDoc client:idle name="Pattern.begin" h={0} />
|
||||
|
||||
### end
|
||||
|
||||
<JsDoc client:idle name="Pattern.end" h={0} />
|
||||
|
||||
### loopAt
|
||||
|
||||
<JsDoc client:idle name="Pattern.loopAt" h={0} />
|
||||
|
||||
### chop
|
||||
|
||||
<JsDoc client:idle name="Pattern.chop" h={0} />
|
||||
|
||||
## Audio Effects
|
||||
|
||||
Wether you're using a synth or a sample, you can apply these effects:
|
||||
|
||||
### gain
|
||||
|
||||
<JsDoc client:idle name="gain" h={0} />
|
||||
|
||||
### velocity
|
||||
|
||||
<JsDoc client:idle name="velocity" h={0} />
|
||||
|
||||
### cutoff
|
||||
|
||||
<JsDoc client:idle name="cutoff" h={0} />
|
||||
|
||||
### resonance
|
||||
|
||||
<JsDoc client:idle name="resonance" h={0} />
|
||||
|
||||
### hcutoff
|
||||
|
||||
<JsDoc client:idle name="hcutoff" h={0} />
|
||||
|
||||
### hresonance
|
||||
|
||||
<JsDoc client:idle name="hresonance" h={0} />
|
||||
|
||||
### bandf
|
||||
|
||||
<JsDoc client:idle name="bandf" h={0} />
|
||||
|
||||
### bandq
|
||||
|
||||
<JsDoc client:idle name="bandq" h={0} />
|
||||
|
||||
### vowel
|
||||
|
||||
<JsDoc client:idle name="vowel" h={0} />
|
||||
|
||||
### pan
|
||||
|
||||
<JsDoc client:idle name="pan" h={0} />
|
||||
|
||||
### coarse
|
||||
|
||||
<JsDoc client:idle name="coarse" h={0} />
|
||||
|
||||
### shape
|
||||
|
||||
<JsDoc client:idle name="shape" h={0} />
|
||||
|
||||
### crush
|
||||
|
||||
<JsDoc client:idle name="crush" h={0} />
|
||||
41
website/src/pages/learn/synths.mdx
Normal file
41
website/src/pages/learn/synths.mdx
Normal file
@ -0,0 +1,41 @@
|
||||
---
|
||||
title: Synths
|
||||
description: Strudel Tutorial - Synths
|
||||
layout: ../../layouts/MainLayout.astro
|
||||
---
|
||||
|
||||
import { MiniRepl } from '../../docs/MiniRepl';
|
||||
import { JsDoc } from '../../docs/JsDoc';
|
||||
|
||||
# Synths
|
||||
|
||||
For now, [samples](/learn/samples) are the main way to play with Strudel.
|
||||
In future, more powerful synthesis capabilities will be added.
|
||||
If in the meantime you want to dive deeper into audio synthesis with Tidal, you will need to [install SuperCollider and SuperDirt](https://tidalcycles.org/docs/).
|
||||
|
||||
## Playing synths with `s`
|
||||
|
||||
We can change the sound, using the `s` function:
|
||||
|
||||
<MiniRepl client:idle tune={`note("c2 <eb2 <g2 g1>>").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:
|
||||
|
||||
<MiniRepl client:idle tune={`note("c2 <eb2 <g2 g1>>").s("<sawtooth square triangle>")`} />
|
||||
|
||||
Now we not only pattern the notes, but the sound as well!
|
||||
`sawtooth` `square` and `triangle` are the basic waveforms available in `s`.
|
||||
|
||||
## Ampltude Envelope
|
||||
|
||||
You can control the envelope of a synth using the `attack`, `decay`, `sustain` and `release` functions:
|
||||
|
||||
<MiniRepl
|
||||
client:idle tune={`note("c2 <eb2 <g2 g1>>").s('sawtooth')
|
||||
.attack(.1).decay(.1).sustain(.2).release(.1)`}
|
||||
/>
|
||||
|
||||
<br/>
|
||||
@ -7,3 +7,7 @@ body {
|
||||
.cm-gutters {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
h1 {
|
||||
padding-top: 30px;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user