mirror of
https://github.com/eliasstepanik/strudel-docker.git
synced 2026-01-13 14:48:36 +00:00
373 lines
7.9 KiB
Plaintext
373 lines
7.9 KiB
Plaintext
---
|
|
title: First Notes
|
|
layout: ../../layouts/MainLayout.astro
|
|
---
|
|
|
|
import { MiniRepl } from '@src/docs/MiniRepl';
|
|
import { midi2note } from '@strudel/core';
|
|
import Box from '@components/Box.astro';
|
|
import QA from '@components/QA';
|
|
|
|
# First Notes
|
|
|
|
Let's look at how we can play notes
|
|
|
|
## numbers and notes
|
|
|
|
**play notes with numbers**
|
|
|
|
<MiniRepl
|
|
client:visible
|
|
tune={`note("48 52 55 59").sound("piano")`}
|
|
claviature
|
|
claviatureLabels={Object.fromEntries(
|
|
Array(49)
|
|
.fill()
|
|
.map((_, i) => [midi2note(i + 36), i + 36]),
|
|
)}
|
|
/>
|
|
|
|
<Box>
|
|
|
|
Try out different numbers!
|
|
|
|
Try decimal numbers, like 55.5
|
|
|
|
</Box>
|
|
|
|
**play notes with letters**
|
|
|
|
<MiniRepl
|
|
client:visible
|
|
tune={`note("c e g b").sound("piano")`}
|
|
claviature
|
|
claviatureLabels={Object.fromEntries(['c3', 'd3', 'e3', 'f3', 'g3', 'a3', 'b3'].map((n) => [n, n.split('')[0]]))}
|
|
/>
|
|
|
|
<Box>
|
|
|
|
Try out different letters (a - g).
|
|
|
|
Can you find melodies that are actual words? Hint: ☕ 😉 ⚪
|
|
|
|
</Box>
|
|
|
|
**add flats or sharps to play the black keys**
|
|
|
|
<MiniRepl
|
|
client:visible
|
|
tune={`note("db eb gb ab bb").sound("piano")`}
|
|
claviature
|
|
claviatureLabels={Object.fromEntries(
|
|
['db3', 'eb3', 'gb3', 'ab3', 'bb3'].map((n) => [n, n.split('').slice(0, 2).join('')]),
|
|
)}
|
|
/>
|
|
|
|
<MiniRepl
|
|
client:visible
|
|
tune={`note("c# d# f# g# a#").sound("piano")`}
|
|
claviature
|
|
claviatureLabels={Object.fromEntries(
|
|
['c#3', 'd#3', 'f#3', 'g#3', 'a#3'].map((n) => [n, n.split('').slice(0, 2).join('')]),
|
|
)}
|
|
/>
|
|
|
|
**play notes with letters in different octaves**
|
|
|
|
<MiniRepl
|
|
client:visible
|
|
tune={`note("c2 e3 g4 b5").sound("piano")`}
|
|
claviature
|
|
claviatureLabels={Object.fromEntries(
|
|
Array(49)
|
|
.fill()
|
|
.map((_, i) => [midi2note(i + 36), midi2note(i + 36)]),
|
|
)}
|
|
/>
|
|
|
|
<Box>
|
|
|
|
Try out different octaves (1-8)
|
|
|
|
</Box>
|
|
|
|
If you are not comfortable with the note letter system, it should be easier to use numbers instead.
|
|
Most of the examples below will use numbers for that reason.
|
|
We will also look at ways to make it easier to play the right notes later.
|
|
|
|
## changing the sound
|
|
|
|
Just like with unpitched sounds, we can change the sound of our notes with `sound`:
|
|
|
|
<MiniRepl client:visible tune={`note("36 43, 52 59 62 64").sound("piano")`} />
|
|
|
|
{/* c2 g2, e3 b3 d4 e4 */}
|
|
|
|
<Box>
|
|
|
|
Try out different sounds:
|
|
|
|
- gm_electric_guitar_muted
|
|
- gm_acoustic_bass
|
|
- gm_voice_oohs
|
|
- gm_blown_bottle
|
|
- sawtooth
|
|
- square
|
|
- triangle
|
|
- how about bd, sd or hh?
|
|
- remove `.sound('...')` completely
|
|
|
|
</Box>
|
|
|
|
**switch between sounds**
|
|
|
|
<MiniRepl
|
|
client:visible
|
|
tune={`note("48 67 63 [62, 58]")
|
|
.sound("piano gm_electric_guitar_muted")`}
|
|
/>
|
|
|
|
**stack multiple sounds**
|
|
|
|
<MiniRepl
|
|
client:visible
|
|
tune={`note("48 67 63 [62, 58]")
|
|
.sound("piano, gm_electric_guitar_muted")`}
|
|
/>
|
|
|
|
<Box>
|
|
|
|
The `note` and `sound` patterns are combined!
|
|
|
|
We will see more ways to combine patterns later..
|
|
|
|
</Box>
|
|
|
|
## Longer Sequences
|
|
|
|
**Divide sequences with `/` to slow them down**
|
|
|
|
{/* [c2 bb1 f2 eb2] */}
|
|
|
|
<MiniRepl client:visible tune={`note("[36 34 41 39]/4").sound("gm_acoustic_bass")`} punchcard />
|
|
|
|
<Box>
|
|
|
|
The `/4` plays the sequence in brackets over 4 cycles (=4s).
|
|
|
|
So each of the 4 notes is 1s long.
|
|
|
|
Try adding more notes inside the brackets and notice how it gets faster.
|
|
|
|
</Box>
|
|
|
|
Because it is so common to just play one thing per cycle, you can..
|
|
|
|
**Play one per cycle with \< \>**
|
|
|
|
<MiniRepl client:visible tune={`note("<36 34 41 39>").sound("gm_acoustic_bass")`} punchcard />
|
|
|
|
<Box>
|
|
|
|
Try adding more notes inside the brackets and notice how it does **not** get faster.
|
|
|
|
</Box>
|
|
|
|
**Play one sequence per cycle**
|
|
|
|
{/* <[c2 c3]*4 [bb1 bb2]*4 [f2 f3]*4 [eb2 eb3]*4>/2 */}
|
|
|
|
<MiniRepl
|
|
client:visible
|
|
tune={`note("<[36 48]*4 [34 46]*4 [41 53]*4 [39 51]*4>/2")
|
|
.sound("gm_acoustic_bass")`}
|
|
punchcard
|
|
/>
|
|
|
|
**Alternate between multiple things**
|
|
|
|
<MiniRepl
|
|
client:visible
|
|
tune={`note("60 <63 62 65 63>")
|
|
.sound("gm_xylophone")`}
|
|
punchcard
|
|
/>
|
|
|
|
This is also useful for unpitched sounds:
|
|
|
|
<MiniRepl
|
|
client:visible
|
|
tune={`sound("bd*2, ~ <sd cp>, [~ hh]*2")
|
|
.bank("RolandTR909")`}
|
|
punchcard
|
|
/>
|
|
|
|
## Scales
|
|
|
|
Finding the right notes can be difficult.. Scales are here to help:
|
|
|
|
<MiniRepl
|
|
client:visible
|
|
tune={`n("0 2 4 <[6,8] [7,9]>")
|
|
.scale("C:minor").sound("piano")`}
|
|
punchcard
|
|
/>
|
|
|
|
<Box>
|
|
|
|
Try out different numbers. Any number should sound good!
|
|
|
|
Try out different scales:
|
|
|
|
- C:major
|
|
- A2:minor
|
|
- D:dorian
|
|
- G:mixolydian
|
|
- A2:minor:pentatonic
|
|
- F:major:pentatonic
|
|
|
|
</Box>
|
|
|
|
**automate scales**
|
|
|
|
Just like anything, we can automate the scale with a pattern:
|
|
|
|
<MiniRepl
|
|
client:visible
|
|
tune={`n("<0 -3>, 2 4 <[6,8] [7,9]>")
|
|
.scale("<C:major D:mixolydian>/4")
|
|
.sound("piano")`}
|
|
punchcard
|
|
/>
|
|
|
|
<Box>
|
|
|
|
If you have no idea what these scale mean, don't worry.
|
|
These are just labels for different sets of notes that go well together.
|
|
|
|
Take your time and you'll find scales you like!
|
|
|
|
</Box>
|
|
|
|
## Repeat & Elongate
|
|
|
|
**Elongate with @**
|
|
|
|
<MiniRepl client:visible tune={`note("c@3 eb").sound("gm_acoustic_bass")`} punchcard />
|
|
|
|
<Box>
|
|
|
|
Not using `@` is like using `@1`. In the above example, c is 3 units long and eb is 1 unit long.
|
|
|
|
Try changing that number!
|
|
|
|
</Box>
|
|
|
|
**Elongate within sub-sequences**
|
|
|
|
<MiniRepl
|
|
client:visible
|
|
tune={`n("<[4@2 4] [5@2 5] [6@2 6] [5@2 5]>*2")
|
|
.scale("<C2:mixolydian F2:mixolydian>/4")
|
|
.sound("gm_acoustic_bass")`}
|
|
punchcard
|
|
/>
|
|
|
|
<Box>
|
|
|
|
This groove is called a `shuffle`.
|
|
Each beat has two notes, where the first is twice as long as the second.
|
|
This is also sometimes called triplet swing. You'll often find it in blues and jazz.
|
|
|
|
</Box>
|
|
|
|
**Replicate**
|
|
|
|
<MiniRepl client:visible tune={`note("c!2 [eb,<g a bb a>]").sound("piano")`} punchcard />
|
|
|
|
<Box>
|
|
|
|
Try switching between `!`, `*` and `@`
|
|
|
|
What's the difference?
|
|
|
|
</Box>
|
|
|
|
## Recap
|
|
|
|
Let's recap what we've learned in this chapter:
|
|
|
|
| Concept | Syntax | Example |
|
|
| --------- | ------ | -------------------------------------------------------- |
|
|
| Slow down | \/ | <MiniRepl client:visible tune={`note("[c a f e]/2")`} /> |
|
|
| Alternate | \<\> | <MiniRepl client:visible tune={`note("c <e g>")`} /> |
|
|
| Elongate | @ | <MiniRepl client:visible tune={`note("c@3 e")`} /> |
|
|
| Replicate | ! | <MiniRepl client:visible tune={`note("c!3 e")`} /> |
|
|
|
|
New functions:
|
|
|
|
| Name | Description | Example |
|
|
| ----- | ----------------------------------- | --------------------------------------------------------------------------------- |
|
|
| note | set pitch as number or letter | <MiniRepl client:visible tune={`note("b g e c").sound("piano")`} /> |
|
|
| scale | interpret `n` as scale degree | <MiniRepl client:visible tune={`n("6 4 2 0").scale("C:minor").sound("piano")`} /> |
|
|
| stack | play patterns in parallel (read on) | <MiniRepl client:visible tune={`stack(s("bd sd"),note("c eb g"))`} /> |
|
|
|
|
## Examples
|
|
|
|
**Classy Bassline**
|
|
|
|
<MiniRepl
|
|
client:visible
|
|
tune={`note("<[c2 c3]*4 [bb1 bb2]*4 [f2 f3]*4 [eb2 eb3]*4>/2")
|
|
.sound("gm_synth_bass_1")
|
|
.lpf(800) // <-- we'll learn about this soon`}
|
|
/>
|
|
|
|
**Classy Melody**
|
|
|
|
<MiniRepl
|
|
client:visible
|
|
tune={`n(\`<
|
|
[~ 0] 2 [0 2] [~ 2]
|
|
[~ 0] 1 [0 1] [~ 1]
|
|
[~ 0] 3 [0 3] [~ 3]
|
|
[~ 0] 2 [0 2] [~ 2]
|
|
>*2\`).scale("C4:minor")
|
|
.sound("gm_synth_strings_1")`}
|
|
/>
|
|
|
|
**Classy Drums**
|
|
|
|
<MiniRepl
|
|
client:visible
|
|
tune={`sound("bd*2, ~ <sd cp>, [~ hh]*2")
|
|
.bank("RolandTR909")`}
|
|
/>
|
|
|
|
**If there just was a way to play all the above at the same time.......**
|
|
|
|
<Box>
|
|
|
|
It's called `stack` 😙
|
|
|
|
</Box>
|
|
|
|
<MiniRepl
|
|
client:visible
|
|
tune={`stack(
|
|
note("<[c2 c3]*4 [bb1 bb2]*4 [f2 f3]*4 [eb2 eb3]*4>/2")
|
|
.sound("gm_synth_bass_1").lpf(800),
|
|
n(\`<
|
|
[~ 0] 2 [0 2] [~ 2]
|
|
[~ 0] 1 [0 1] [~ 1]
|
|
[~ 0] 3 [0 3] [~ 3]
|
|
[~ 0] 2 [0 2] [~ 2]
|
|
>*2\`).scale("C4:minor")
|
|
.sound("gm_synth_strings_1"),
|
|
sound("bd*2, ~ <sd cp>, [~ hh]*2")
|
|
.bank("RolandTR909")
|
|
)`}
|
|
/>
|
|
|
|
This is starting to sound like actual music! We have sounds, we have notes, now the last piece of the puzzle is missing: [effects](/workshop/first-effects)
|