Merge branch 'main' into uzu
This commit is contained in:
commit
67bfedb317
20 changed files with 351 additions and 117 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
name: Strudel tests
|
name: Strudel tests
|
||||||
|
|
||||||
on: [push, pull_request]
|
on: [push]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
|
@ -11,13 +11,15 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
- name: apt install ztd
|
||||||
|
run: apt update && apt install -y zstd
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
with:
|
with:
|
||||||
version: 9.12.2
|
version: 9.12.2
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
# cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
- run: pnpm install
|
- run: pnpm install
|
||||||
- run: pnpm run format-check
|
- run: pnpm run format-check
|
||||||
- run: pnpm run lint
|
- run: pnpm run lint
|
||||||
|
|
|
||||||
12
packages/codemirror/themes.mjs
vendored
12
packages/codemirror/themes.mjs
vendored
|
|
@ -8,6 +8,11 @@ import CutiePi, { settings as CutiePiSettings } from './themes/CutiePi.mjs';
|
||||||
import sonicPink, { settings as sonicPinkSettings } from './themes/sonic-pink.mjs';
|
import sonicPink, { settings as sonicPinkSettings } from './themes/sonic-pink.mjs';
|
||||||
import redText, { settings as redTextSettings } from './themes/red-text.mjs';
|
import redText, { settings as redTextSettings } from './themes/red-text.mjs';
|
||||||
import greenText, { settings as greenTextSettings } from './themes/green-text.mjs';
|
import greenText, { settings as greenTextSettings } from './themes/green-text.mjs';
|
||||||
|
import archBtw, { settings as archBtwSettings } from './themes/archBtw.mjs';
|
||||||
|
import fruitDaw, { settings as fruitDawSettings } from './themes/fruitDaw.mjs';
|
||||||
|
|
||||||
|
import bluescreenlight, { settings as bluescreenlightsettings } from './themes/bluescreenlight.mjs';
|
||||||
|
|
||||||
import androidstudio, { settings as androidstudioSettings } from './themes/androidstudio.mjs';
|
import androidstudio, { settings as androidstudioSettings } from './themes/androidstudio.mjs';
|
||||||
import atomone, { settings as atomOneSettings } from './themes/atomone.mjs';
|
import atomone, { settings as atomOneSettings } from './themes/atomone.mjs';
|
||||||
import aura, { settings as auraSettings } from './themes/aura.mjs';
|
import aura, { settings as auraSettings } from './themes/aura.mjs';
|
||||||
|
|
@ -39,17 +44,20 @@ import { setTheme } from '@strudel/draw';
|
||||||
export const themes = {
|
export const themes = {
|
||||||
strudelTheme,
|
strudelTheme,
|
||||||
algoboy,
|
algoboy,
|
||||||
|
archBtw,
|
||||||
androidstudio,
|
androidstudio,
|
||||||
atomone,
|
atomone,
|
||||||
aura,
|
aura,
|
||||||
bbedit,
|
bbedit,
|
||||||
blackscreen,
|
blackscreen,
|
||||||
bluescreen,
|
bluescreen,
|
||||||
|
bluescreenlight,
|
||||||
CutiePi,
|
CutiePi,
|
||||||
darcula,
|
darcula,
|
||||||
dracula,
|
dracula,
|
||||||
duotoneDark,
|
duotoneDark,
|
||||||
eclipse,
|
eclipse,
|
||||||
|
fruitDaw,
|
||||||
githubDark,
|
githubDark,
|
||||||
githubLight,
|
githubLight,
|
||||||
greenText,
|
greenText,
|
||||||
|
|
@ -78,10 +86,12 @@ export const themes = {
|
||||||
export const settings = {
|
export const settings = {
|
||||||
strudelTheme: strudelThemeSettings,
|
strudelTheme: strudelThemeSettings,
|
||||||
bluescreen: bluescreenSettings,
|
bluescreen: bluescreenSettings,
|
||||||
|
bluescreenlight: bluescreenlightsettings,
|
||||||
blackscreen: blackscreenSettings,
|
blackscreen: blackscreenSettings,
|
||||||
whitescreen: whitescreenSettings,
|
whitescreen: whitescreenSettings,
|
||||||
teletext: teletextSettings,
|
teletext: teletextSettings,
|
||||||
algoboy: algoboySettings,
|
algoboy: algoboySettings,
|
||||||
|
archBtw: archBtwSettings,
|
||||||
androidstudio: androidstudioSettings,
|
androidstudio: androidstudioSettings,
|
||||||
atomone: atomOneSettings,
|
atomone: atomOneSettings,
|
||||||
aura: auraSettings,
|
aura: auraSettings,
|
||||||
|
|
@ -92,9 +102,11 @@ export const settings = {
|
||||||
eclipse: eclipseSettings,
|
eclipse: eclipseSettings,
|
||||||
CutiePi: CutiePiSettings,
|
CutiePi: CutiePiSettings,
|
||||||
sonicPink: sonicPinkSettings,
|
sonicPink: sonicPinkSettings,
|
||||||
|
fruitDaw: fruitDawSettings,
|
||||||
githubLight: githubLightSettings,
|
githubLight: githubLightSettings,
|
||||||
githubDark: githubDarkSettings,
|
githubDark: githubDarkSettings,
|
||||||
greenText: greenTextSettings,
|
greenText: greenTextSettings,
|
||||||
|
|
||||||
gruvboxDark: gruvboxDarkSettings,
|
gruvboxDark: gruvboxDarkSettings,
|
||||||
gruvboxLight: gruvboxLightSettings,
|
gruvboxLight: gruvboxLightSettings,
|
||||||
materialDark: materialDarkSettings,
|
materialDark: materialDarkSettings,
|
||||||
|
|
|
||||||
38
packages/codemirror/themes/archBtw.mjs
vendored
Normal file
38
packages/codemirror/themes/archBtw.mjs
vendored
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Arch Btw
|
||||||
|
* Modern terminal inspired theme
|
||||||
|
* made by Jade
|
||||||
|
*/
|
||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
const hex = ['rgb(0, 0, 0)', 'rgb(82, 208, 250)', 'rgba(113, 208, 250, .4)', 'rgba(113, 208, 250, .15)'];
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
background: hex[0],
|
||||||
|
lineBackground: 'transparent',
|
||||||
|
foreground: hex[1],
|
||||||
|
selection: hex[2],
|
||||||
|
selectionMatch: hex[0],
|
||||||
|
gutterBackground: hex[0],
|
||||||
|
gutterForeground: hex[2],
|
||||||
|
gutterBorder: 'transparent',
|
||||||
|
lineHighlight: hex[0],
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'dark',
|
||||||
|
settings,
|
||||||
|
styles: [
|
||||||
|
{
|
||||||
|
tag: [t.function(t.variableName), t.function(t.propertyName), t.url, t.processingInstruction],
|
||||||
|
color: hex[1],
|
||||||
|
},
|
||||||
|
{ tag: [t.atom, t.bool, t.special(t.variableName)], color: hex[1] },
|
||||||
|
{ tag: [t.comment, t.brace, t.bracket], color: hex[2] },
|
||||||
|
{ tag: [t.variableName, t.propertyName, t.labelName], color: hex[1] },
|
||||||
|
{ tag: [t.attributeName, t.number], color: hex[1] },
|
||||||
|
{ tag: t.keyword, color: hex[1] },
|
||||||
|
{ tag: [t.string, t.regexp, t.special(t.propertyName)], color: hex[1] },
|
||||||
|
],
|
||||||
|
});
|
||||||
37
packages/codemirror/themes/bluescreenlight.mjs
vendored
Normal file
37
packages/codemirror/themes/bluescreenlight.mjs
vendored
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* A lighter blue screen theme
|
||||||
|
* made by Jade
|
||||||
|
*/
|
||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
const hex = ['rgb(75, 130, 247)', 'rgb(47, 108, 246)', 'rgb(255, 255, 255)', 'rgba(255, 255, 255,.3)'];
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
background: hex[0],
|
||||||
|
lineBackground: 'transparent',
|
||||||
|
foreground: hex[2],
|
||||||
|
selection: hex[3],
|
||||||
|
selectionMatch: hex[0],
|
||||||
|
gutterBackground: hex[0],
|
||||||
|
gutterForeground: hex[2],
|
||||||
|
gutterBorder: 'transparent',
|
||||||
|
lineHighlight: hex[1],
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'dark',
|
||||||
|
settings,
|
||||||
|
styles: [
|
||||||
|
{
|
||||||
|
tag: [t.function(t.variableName), t.function(t.propertyName), t.url, t.processingInstruction],
|
||||||
|
color: hex[2],
|
||||||
|
},
|
||||||
|
{ tag: [t.atom, t.bool, t.special(t.variableName)], color: hex[2] },
|
||||||
|
{ tag: [t.comment, t.bracket, t.brace, t.compareOperator], color: hex[3] },
|
||||||
|
{ tag: [t.variableName, t.propertyName, t.labelName], color: hex[2] },
|
||||||
|
{ tag: [t.attributeName, t.number], color: hex[2] },
|
||||||
|
{ tag: t.keyword, color: hex[2] },
|
||||||
|
{ tag: [t.string, t.regexp, t.special(t.propertyName)], color: hex[2] },
|
||||||
|
],
|
||||||
|
});
|
||||||
50
packages/codemirror/themes/fruitDaw.mjs
vendored
Normal file
50
packages/codemirror/themes/fruitDaw.mjs
vendored
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* Fruit Daw
|
||||||
|
* made by Jade
|
||||||
|
*/
|
||||||
|
import { tags as t } from '@lezer/highlight';
|
||||||
|
import { createTheme } from './theme-helper.mjs';
|
||||||
|
|
||||||
|
const hex = [
|
||||||
|
'rgb(84, 93, 98)',
|
||||||
|
'rgb(255, 255, 255)',
|
||||||
|
'rgba(255, 255, 255, .25)',
|
||||||
|
'rgb(67, 76, 81)',
|
||||||
|
'rgb(186, 230, 115)',
|
||||||
|
'rgb(252, 184, 67)',
|
||||||
|
'rgb(124, 206, 254)',
|
||||||
|
'rgb(83, 101, 102)',
|
||||||
|
'rgba(46, 62, 72,.5)',
|
||||||
|
'rgb(94, 100, 108)',
|
||||||
|
'rgb(167, 216, 177)',
|
||||||
|
];
|
||||||
|
|
||||||
|
export const settings = {
|
||||||
|
background: hex[0],
|
||||||
|
lineBackground: 'transparent',
|
||||||
|
foreground: hex[10],
|
||||||
|
selection: hex[8],
|
||||||
|
selectionMatch: hex[0],
|
||||||
|
gutterBackground: hex[3],
|
||||||
|
gutterForeground: hex[2],
|
||||||
|
gutterBorder: 'transparent',
|
||||||
|
lineHighlight: hex[3],
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createTheme({
|
||||||
|
theme: 'dark',
|
||||||
|
settings,
|
||||||
|
styles: [
|
||||||
|
{
|
||||||
|
tag: [t.function(t.variableName), t.function(t.propertyName), t.url, t.processingInstruction],
|
||||||
|
color: hex[1],
|
||||||
|
},
|
||||||
|
{ tag: [t.bool, t.special(t.variableName)], color: hex[1] },
|
||||||
|
{ tag: [t.comment, t.brace, t.bracket], color: hex[2] },
|
||||||
|
{ tag: [t.variableName], color: hex[1] },
|
||||||
|
{ tag: [t.labelName, t.propertyName, t.self, t.atom], color: hex[5] },
|
||||||
|
{ tag: [t.attributeName, t.number], color: hex[6] },
|
||||||
|
{ tag: t.keyword, color: hex[5] },
|
||||||
|
{ tag: [t.string, t.regexp, t.special(t.propertyName)], color: hex[4] },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
@ -1984,6 +1984,7 @@ export const apply = register('apply', function (func, pat) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Plays the pattern at the given cycles per minute.
|
* Plays the pattern at the given cycles per minute.
|
||||||
|
* @deprecated
|
||||||
* @example
|
* @example
|
||||||
* s("<bd sd>,hh*2").cpm(90) // = 90 bpm
|
* s("<bd sd>,hh*2").cpm(90) // = 90 bpm
|
||||||
*/
|
*/
|
||||||
|
|
@ -2722,7 +2723,7 @@ export function stepcat(...timepats) {
|
||||||
if (timepats.length === 0) {
|
if (timepats.length === 0) {
|
||||||
return nothing;
|
return nothing;
|
||||||
}
|
}
|
||||||
const findsteps = (x) => (Array.isArray(x) ? x : [x._steps, x]);
|
const findsteps = (x) => (Array.isArray(x) ? x : [x._steps ?? 1, x]);
|
||||||
timepats = timepats.map(findsteps);
|
timepats = timepats.map(findsteps);
|
||||||
if (timepats.find((x) => x[0] === undefined)) {
|
if (timepats.find((x) => x[0] === undefined)) {
|
||||||
const times = timepats.map((a) => a[0]).filter((x) => x !== undefined);
|
const times = timepats.map((a) => a[0]).filter((x) => x !== undefined);
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,17 @@ export function repl({
|
||||||
const pause = () => scheduler.pause();
|
const pause = () => scheduler.pause();
|
||||||
const toggle = () => scheduler.toggle();
|
const toggle = () => scheduler.toggle();
|
||||||
const setCps = (cps) => scheduler.setCps(cps);
|
const setCps = (cps) => scheduler.setCps(cps);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the global tempo to the given cycles per minute
|
||||||
|
*
|
||||||
|
* @name setcpm
|
||||||
|
* @alias setCpm
|
||||||
|
* @param {number} cpm cycles per minute
|
||||||
|
* @example
|
||||||
|
* setcpm(140/4) // =140 bpm in 4/4
|
||||||
|
* $: s("bd*4,[- sd]*2").bank('tr707')
|
||||||
|
*/
|
||||||
const setCpm = (cpm) => scheduler.setCps(cpm / 60);
|
const setCpm = (cpm) => scheduler.setCps(cpm / 60);
|
||||||
|
|
||||||
// TODO - not documented as jsdoc examples as the test framework doesn't simulate enough context for `each` and `all`..
|
// TODO - not documented as jsdoc examples as the test framework doesn't simulate enough context for `each` and `all`..
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ import {
|
||||||
stackCentre,
|
stackCentre,
|
||||||
stepcat,
|
stepcat,
|
||||||
sometimes,
|
sometimes,
|
||||||
|
expand,
|
||||||
} from '../index.mjs';
|
} from '../index.mjs';
|
||||||
|
|
||||||
import { steady } from '../signal.mjs';
|
import { steady } from '../signal.mjs';
|
||||||
|
|
@ -1179,6 +1180,9 @@ describe('Pattern', () => {
|
||||||
it('calculates undefined steps as the average', () => {
|
it('calculates undefined steps as the average', () => {
|
||||||
expect(sameFirst(stepcat(pure(1), pure(2), pure(3).setSteps(undefined)), fastcat(1, 2, 3)));
|
expect(sameFirst(stepcat(pure(1), pure(2), pure(3).setSteps(undefined)), fastcat(1, 2, 3)));
|
||||||
});
|
});
|
||||||
|
it('works with auto-reified values', () => {
|
||||||
|
expect(sameFirst(stepcat(expand(3, 'bd'), 'rim'), stepcat(expand(3, 'bd'), pure('rim'))));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
describe('shrink', () => {
|
describe('shrink', () => {
|
||||||
it('can shrink', () => {
|
it('can shrink', () => {
|
||||||
|
|
|
||||||
|
|
@ -56,14 +56,15 @@ You can use button inputs to control different aspects of your music, such as ga
|
||||||
<MiniRepl
|
<MiniRepl
|
||||||
client:idle
|
client:idle
|
||||||
tune={`const gp = gamepad(0)
|
tune={`const gp = gamepad(0)
|
||||||
// Use button values to control amplitude
|
setcpm(120)
|
||||||
|
// Use button values to control amplitude
|
||||||
$: stack(
|
$: stack(
|
||||||
s("[[hh hh] oh hh oh]/2").mask(gp.tglX).bank("RolandTR909"), // X btn for HH
|
s("[[hh hh] oh hh oh]/2").mask(gp.tglX).bank("RolandTR909"), // X btn for HH
|
||||||
s("cr*1").mask(gp.Y).bank("RolandTR909"), // LB btn for CR
|
s("cr*1").mask(gp.Y).bank("RolandTR909"), // LB btn for CR
|
||||||
s("bd").mask(gp.tglA).bank("RolandTR909"), // A btn for BD
|
s("bd").mask(gp.tglA).bank("RolandTR909"), // A btn for BD
|
||||||
s("[ht - - mt - - lt - ]/2").mask(gp.tglB).bank("RolandTR909"), // B btn for Toms
|
s("[ht - - mt - - lt - ]/2").mask(gp.tglB).bank("RolandTR909"), // B btn for Toms
|
||||||
s("sd*4").mask(gp.RB).bank("RolandTR909"), // RB btn for SD
|
s("sd*4").mask(gp.RB).bank("RolandTR909"), // RB btn for SD
|
||||||
).cpm(120)
|
)
|
||||||
`}
|
`}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
@ -74,14 +75,13 @@ Analog sticks can be used for continuous control, such as pitch shifting or pann
|
||||||
<MiniRepl
|
<MiniRepl
|
||||||
client:idle
|
client:idle
|
||||||
tune={`const gp = gamepad(0)
|
tune={`const gp = gamepad(0)
|
||||||
// Use analog stick for continuous control
|
setcpm(120)
|
||||||
|
// Use analog stick for continuous control
|
||||||
$: note("c4 d3 a3 e3").sound("sawtooth")
|
$: note("c4 d3 a3 e3").sound("sawtooth")
|
||||||
.lpf(gp.x1.range(100,4000))
|
.lpf(gp.x1.range(100,4000))
|
||||||
.lpq(gp.y1.range(5,30))
|
.lpq(gp.y1.range(5,30))
|
||||||
.decay(gp.y2.range(0.1,2))
|
.decay(gp.y2.range(0.1,2))
|
||||||
.lpenv(gp.x2.range(-5,5))
|
.lpenv(gp.x2.range(-5,5))`}
|
||||||
.cpm(120)
|
|
||||||
`}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
### Button Sequences
|
### Button Sequences
|
||||||
|
|
@ -89,6 +89,7 @@ $: note("c4 d3 a3 e3").sound("sawtooth")
|
||||||
You can define button sequences to trigger specific actions, like playing a sound when a sequence is detected.
|
You can define button sequences to trigger specific actions, like playing a sound when a sequence is detected.
|
||||||
|
|
||||||
<MiniRepl client:idle tune={`const gp = gamepad(0)
|
<MiniRepl client:idle tune={`const gp = gamepad(0)
|
||||||
|
setcpm(120)
|
||||||
// Define button sequences
|
// Define button sequences
|
||||||
const HADOUKEN = [
|
const HADOUKEN = [
|
||||||
'd', // Down
|
'd', // Down
|
||||||
|
|
@ -99,7 +100,7 @@ const KONAMI = 'uuddlrlrba' //Konami Code ↑↑↓↓←→←→BA
|
||||||
|
|
||||||
// Check butto-n sequence (returns 1 while detected, 0 when not within last 1 second)
|
// Check butto-n sequence (returns 1 while detected, 0 when not within last 1 second)
|
||||||
$: s("free_hadouken -").slow(2)
|
$: s("free_hadouken -").slow(2)
|
||||||
.mask(gp.btnSequence(HADOUKEN)).room(1).cpm(120)
|
.mask(gp.btnSequence(HADOUKEN)).room(1)
|
||||||
|
|
||||||
// hadouken.wav by Syna-Max
|
// hadouken.wav by Syna-Max
|
||||||
//https://freesound.org/people/Syna-Max/sounds/67674/
|
//https://freesound.org/people/Syna-Max/sounds/67674/
|
||||||
|
|
|
||||||
|
|
@ -8450,6 +8450,35 @@ exports[`runs examples > example "seqPLoop" example index 0 1`] = `
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "setcpm" example index 0 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/4 | s:bd bank:tr707 ]",
|
||||||
|
"[ 1/4 → 1/2 | s:bd bank:tr707 ]",
|
||||||
|
"[ 1/4 → 1/2 | s:sd bank:tr707 ]",
|
||||||
|
"[ 1/2 → 3/4 | s:bd bank:tr707 ]",
|
||||||
|
"[ 3/4 → 1/1 | s:bd bank:tr707 ]",
|
||||||
|
"[ 3/4 → 1/1 | s:sd bank:tr707 ]",
|
||||||
|
"[ 1/1 → 5/4 | s:bd bank:tr707 ]",
|
||||||
|
"[ 5/4 → 3/2 | s:bd bank:tr707 ]",
|
||||||
|
"[ 5/4 → 3/2 | s:sd bank:tr707 ]",
|
||||||
|
"[ 3/2 → 7/4 | s:bd bank:tr707 ]",
|
||||||
|
"[ 7/4 → 2/1 | s:bd bank:tr707 ]",
|
||||||
|
"[ 7/4 → 2/1 | s:sd bank:tr707 ]",
|
||||||
|
"[ 2/1 → 9/4 | s:bd bank:tr707 ]",
|
||||||
|
"[ 9/4 → 5/2 | s:bd bank:tr707 ]",
|
||||||
|
"[ 9/4 → 5/2 | s:sd bank:tr707 ]",
|
||||||
|
"[ 5/2 → 11/4 | s:bd bank:tr707 ]",
|
||||||
|
"[ 11/4 → 3/1 | s:bd bank:tr707 ]",
|
||||||
|
"[ 11/4 → 3/1 | s:sd bank:tr707 ]",
|
||||||
|
"[ 3/1 → 13/4 | s:bd bank:tr707 ]",
|
||||||
|
"[ 13/4 → 7/2 | s:bd bank:tr707 ]",
|
||||||
|
"[ 13/4 → 7/2 | s:sd bank:tr707 ]",
|
||||||
|
"[ 7/2 → 15/4 | s:bd bank:tr707 ]",
|
||||||
|
"[ 15/4 → 4/1 | s:bd bank:tr707 ]",
|
||||||
|
"[ 15/4 → 4/1 | s:sd bank:tr707 ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`runs examples > example "shape" example index 0 1`] = `
|
exports[`runs examples > example "shape" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/8 | s:hh shape:0 ]",
|
"[ 0/1 → 1/8 | s:hh shape:0 ]",
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,7 @@ const toneHelpersMocked = {
|
||||||
'_pianoroll',
|
'_pianoroll',
|
||||||
'_spectrum',
|
'_spectrum',
|
||||||
'markcss',
|
'markcss',
|
||||||
|
'p',
|
||||||
].forEach((mock) => {
|
].forEach((mock) => {
|
||||||
strudel.Pattern.prototype[mock] = function () {
|
strudel.Pattern.prototype[mock] = function () {
|
||||||
return this;
|
return this;
|
||||||
|
|
@ -163,6 +164,7 @@ evalScope(
|
||||||
loadCsound,
|
loadCsound,
|
||||||
loadcsound,
|
loadcsound,
|
||||||
setcps: id,
|
setcps: id,
|
||||||
|
setcpm: id,
|
||||||
Clock: {}, // whatever
|
Clock: {}, // whatever
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -168,9 +168,14 @@ Korrekt, der echte Vorteil dieser Schreibweise zeigt sich wenn du Elemente entfe
|
||||||
|
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
**Tempo ändern mit `cpm`**
|
**Tempo ändern mit `setcpm`**
|
||||||
|
|
||||||
<MiniRepl client:visible tune={`sound("<bd hh rim hh>*8").cpm(90/4)`} punchcard />
|
<MiniRepl
|
||||||
|
client:visible
|
||||||
|
tune={`setcpm(90/4)
|
||||||
|
sound("<bd hh rim hh>*8")`}
|
||||||
|
punchcard
|
||||||
|
/>
|
||||||
|
|
||||||
<Box>
|
<Box>
|
||||||
|
|
||||||
|
|
@ -233,8 +238,9 @@ Bolero:
|
||||||
|
|
||||||
<MiniRepl
|
<MiniRepl
|
||||||
client:visible
|
client:visible
|
||||||
tune={`sound("sd sd*3 sd sd*3 sd sd sd sd*3 sd sd*3 sd*3 sd*3")
|
tune={`
|
||||||
.cpm(10)`}
|
setcpm(10)
|
||||||
|
sound("sd sd*3 sd sd*3 sd sd sd sd*3 sd sd*3 sd*3 sd*3")`}
|
||||||
punchcard
|
punchcard
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
@ -313,18 +319,23 @@ Das haben wir bisher gelernt:
|
||||||
Die mit Apostrophen umgebene Mini-Notation benutzt man normalerweise in einer sogenannten Funktion.
|
Die mit Apostrophen umgebene Mini-Notation benutzt man normalerweise in einer sogenannten Funktion.
|
||||||
Die folgenden Funktionen haben wir bereits gesehen:
|
Die folgenden Funktionen haben wir bereits gesehen:
|
||||||
|
|
||||||
| Name | Description | Example |
|
| Name | Description | Example |
|
||||||
| ----- | -------------------------------------- | ----------------------------------------------------------------------- |
|
| ------ | -------------------------------------- | ----------------------------------------------------------------------- |
|
||||||
| sound | Spielt den Sound mit dem Namen | <MiniRepl client:visible tune={`sound("bd sd")`} /> |
|
| sound | Spielt den Sound mit dem Namen | <MiniRepl client:visible tune={`sound("bd sd")`} /> |
|
||||||
| bank | Wählt die Soundbank / Drum Machine | <MiniRepl client:visible tune={`sound("bd sd").bank("RolandTR909")`} /> |
|
| bank | Wählt die Soundbank / Drum Machine | <MiniRepl client:visible tune={`sound("bd sd").bank("RolandTR909")`} /> |
|
||||||
| cpm | Tempo in **C**ycles **p**ro **M**inute | <MiniRepl client:visible tune={`sound("bd sd").cpm(90)`} /> |
|
| setcpm | Tempo in **C**ycles **p**ro **M**inute | <MiniRepl client:visible tune={`setcpm(90); sound("bd sd")`} /> |
|
||||||
| n | Sample Nummer | <MiniRepl client:visible tune={`n("0 1 4 2").sound("jazz")`} /> |
|
| n | Sample Nummer | <MiniRepl client:visible tune={`n("0 1 4 2").sound("jazz")`} /> |
|
||||||
|
|
||||||
## Beispiele
|
## Beispiele
|
||||||
|
|
||||||
**Einfacher Rock Beat**
|
**Einfacher Rock Beat**
|
||||||
|
|
||||||
<MiniRepl client:visible tune={`sound("bd sd, hh*4").bank("RolandTR505").cpm(100/2)`} punchcard />
|
<MiniRepl
|
||||||
|
client:visible
|
||||||
|
tune={`setcpm(100/2)
|
||||||
|
sound("bd sd, hh*4").bank("RolandTR505")`}
|
||||||
|
punchcard
|
||||||
|
/>
|
||||||
|
|
||||||
**Klassischer House**
|
**Klassischer House**
|
||||||
|
|
||||||
|
|
@ -339,7 +350,12 @@ Bestimmte Drum Patterns werden oft genreübergreifend wiederverwendet.
|
||||||
|
|
||||||
We Will Rock you
|
We Will Rock you
|
||||||
|
|
||||||
<MiniRepl client:visible tune={`sound("bd*2 cp").bank("RolandTR707").cpm(81/2)`} punchcard />
|
<MiniRepl
|
||||||
|
client:visible
|
||||||
|
tune={`setcpm(81/2)
|
||||||
|
sound("bd*2 cp").bank("RolandTR707")`}
|
||||||
|
punchcard
|
||||||
|
/>
|
||||||
|
|
||||||
**Yellow Magic Orchestra - Firecracker**
|
**Yellow Magic Orchestra - Firecracker**
|
||||||
|
|
||||||
|
|
@ -354,12 +370,13 @@ We Will Rock you
|
||||||
|
|
||||||
<MiniRepl
|
<MiniRepl
|
||||||
client:visible
|
client:visible
|
||||||
tune={`sound(\`
|
tune={`setcpm(90/4)
|
||||||
|
sound(\`
|
||||||
[- - oh - ] [- - - - ] [- - - - ] [- - - - ],
|
[- - oh - ] [- - - - ] [- - - - ] [- - - - ],
|
||||||
[hh hh - - ] [hh - hh - ] [hh - hh - ] [hh - hh - ],
|
[hh hh - - ] [hh - hh - ] [hh - hh - ] [hh - hh - ],
|
||||||
[- - - - ] [cp - - - ] [- - - - ] [cp - - - ],
|
[- - - - ] [cp - - - ] [- - - - ] [cp - - - ],
|
||||||
[bd - - - ] [- - - bd] [- - bd - ] [- - - bd]
|
[bd - - - ] [- - - bd] [- - bd - ] [- - - bd]
|
||||||
\`).cpm(90/4)`}
|
\`)`}
|
||||||
punchcard
|
punchcard
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
@ -367,12 +384,13 @@ We Will Rock you
|
||||||
|
|
||||||
<MiniRepl
|
<MiniRepl
|
||||||
client:visible
|
client:visible
|
||||||
tune={`sound(\`
|
tune={`setcpm(88/4)
|
||||||
|
sound(\`
|
||||||
[- - - - ] [- - - - ] [- - - - ] [- - oh:1 - ],
|
[- - - - ] [- - - - ] [- - - - ] [- - oh:1 - ],
|
||||||
[hh hh hh hh] [hh hh hh hh] [hh hh hh hh] [hh hh - - ],
|
[hh hh hh hh] [hh hh hh hh] [hh hh hh hh] [hh hh - - ],
|
||||||
[- - - - ] [cp - - - ] [- - - - ] [- cp - - ],
|
[- - - - ] [cp - - - ] [- - - - ] [- cp - - ],
|
||||||
[bd bd - - ] [- - bd - ] [bd bd - bd ] [- - - - ]
|
[bd bd - - ] [- - bd - ] [bd bd - bd ] [- - - - ]
|
||||||
\`).bank("RolandTR808").cpm(88/4)`}
|
\`).bank("RolandTR808")`}
|
||||||
punchcard
|
punchcard
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
@ -380,11 +398,11 @@ We Will Rock you
|
||||||
|
|
||||||
<MiniRepl
|
<MiniRepl
|
||||||
client:visible
|
client:visible
|
||||||
tune={`s(\`jazz*2,
|
tune={`setcpm(100/2)
|
||||||
|
s(\`jazz*2,
|
||||||
insect [crow metal] - -,
|
insect [crow metal] - -,
|
||||||
- space:4 - space:1,
|
- space:4 - space:1,
|
||||||
- wind\`)
|
- wind\`)`}
|
||||||
.cpm(100/2)`}
|
|
||||||
punchcard
|
punchcard
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,13 +56,13 @@ Diese Seite ist eine Auflistung aller im Workshop vorgestellten Funktionen.
|
||||||
|
|
||||||
## Pattern-Effekte
|
## Pattern-Effekte
|
||||||
|
|
||||||
| Name | Beschreibung | Beispiel |
|
| Name | Beschreibung | Beispiel |
|
||||||
| ---- | --------------------------------- | ----------------------------------------------------------------------------------- |
|
| ------ | --------------------------------- | ----------------------------------------------------------------------------------- |
|
||||||
| cpm | Tempo in Cycles pro Minute | <MiniRepl client:visible tune={`sound("bd sd").cpm(90)`} /> |
|
| setcpm | Tempo in Cycles pro Minute | <MiniRepl client:visible tune={`setcpm(90); sound("bd sd")`} /> |
|
||||||
| fast | schneller | <MiniRepl client:visible tune={`sound("bd sd").fast(2)`} /> |
|
| fast | schneller | <MiniRepl client:visible tune={`sound("bd sd").fast(2)`} /> |
|
||||||
| slow | langsamer | <MiniRepl client:visible tune={`sound("bd sd").slow(2)`} /> |
|
| slow | langsamer | <MiniRepl client:visible tune={`sound("bd sd").slow(2)`} /> |
|
||||||
| rev | rückwärts | <MiniRepl client:visible tune={`n("0 2 4 6").scale("C:minor").rev()`} /> |
|
| rev | rückwärts | <MiniRepl client:visible tune={`n("0 2 4 6").scale("C:minor").rev()`} /> |
|
||||||
| jux | einen Stereo-Kanal modifizieren | <MiniRepl client:visible tune={`n("0 2 4 6").scale("C:minor").jux(rev)`} /> |
|
| jux | einen Stereo-Kanal modifizieren | <MiniRepl client:visible tune={`n("0 2 4 6").scale("C:minor").jux(rev)`} /> |
|
||||||
| add | addiert Zahlen oder Noten | <MiniRepl client:visible tune={`n("0 2 4 6".add("<0 1 2 1>")).scale("C:minor")`} /> |
|
| add | addiert Zahlen oder Noten | <MiniRepl client:visible tune={`n("0 2 4 6".add("<0 1 2 1>")).scale("C:minor")`} /> |
|
||||||
| ply | jedes Element schneller machen | <MiniRepl client:visible tune={`s("bd sd").ply("<1 2 3>")`} /> |
|
| ply | jedes Element schneller machen | <MiniRepl client:visible tune={`s("bd sd").ply("<1 2 3>")`} /> |
|
||||||
| off | verzögert eine modifizierte Kopie | <MiniRepl client:visible tune={`s("bd sd, hh*4").off(1/8, x=>x.speed(2))`} /> |
|
| off | verzögert eine modifizierte Kopie | <MiniRepl client:visible tune={`s("bd sd, hh*4").off(1/8, x=>x.speed(2))`} /> |
|
||||||
|
|
|
||||||
|
|
@ -247,15 +247,17 @@ We can also declare different samples for different regions of the keyboard:
|
||||||
|
|
||||||
<MiniRepl
|
<MiniRepl
|
||||||
client:idle
|
client:idle
|
||||||
tune={`samples({
|
tune={`setcpm(60)
|
||||||
|
samples({
|
||||||
'moog': {
|
'moog': {
|
||||||
'g2': 'moog/004_Mighty%20Moog%20G2.wav',
|
'g2': 'moog/004_Mighty%20Moog%20G2.wav',
|
||||||
'g3': 'moog/005_Mighty%20Moog%20G3.wav',
|
'g3': 'moog/005_Mighty%20Moog%20G3.wav',
|
||||||
'g4': 'moog/006_Mighty%20Moog%20G4.wav',
|
'g4': 'moog/006_Mighty%20Moog%20G4.wav',
|
||||||
}}, 'github:tidalcycles/dirt-samples');
|
}}, 'github:tidalcycles/dirt-samples')
|
||||||
|
|
||||||
note("g2!2 <bb2 c3>!2, <c4@3 [<eb4 bb3> g4 f4]>")
|
note("g2!2 <bb2 c3>!2, <c4@3 [<eb4 bb3> g4 f4]>")
|
||||||
.s('moog').clip(1)
|
.s('moog').clip(1)
|
||||||
.gain(.5).cpm(60)`}
|
.gain(.5)`}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
The sampler will always pick the closest matching sample for the current note!
|
The sampler will always pick the closest matching sample for the current note!
|
||||||
|
|
|
||||||
|
|
@ -43,21 +43,33 @@ This is why the same CPS can produce different perceived tempos.
|
||||||
|
|
||||||
## Setting CPM
|
## Setting CPM
|
||||||
|
|
||||||
If you're familiar with BPM, you can use the `cpm` method to set the tempo in cycles per minute:
|
If you're familiar with BPM, you can use the `setcpm` method to set the global tempo in cycles per minute:
|
||||||
|
|
||||||
<MiniRepl client:visible tune={`s("bd hh").cpm(110)`} />
|
<MiniRepl
|
||||||
|
client:visible
|
||||||
|
tune={`setcpm(110)
|
||||||
|
s("bd hh")`}
|
||||||
|
/>
|
||||||
|
|
||||||
If you want to add more beats per cycle, you might want to divide the cpm:
|
If you want to add more beats per cycle, you might want to divide the cpm:
|
||||||
|
|
||||||
<MiniRepl client:visible tune={`s("bd sd bd rim, hh*8").cpm(110/4)`} />
|
<MiniRepl
|
||||||
|
client:visible
|
||||||
|
tune={`setcpm(110/4)
|
||||||
|
s("bd sd bd rim, hh*8")`}
|
||||||
|
/>
|
||||||
|
|
||||||
Or using 2 beats per cycle:
|
Or using 2 beats per cycle:
|
||||||
|
|
||||||
<MiniRepl client:visible tune={`s("bd sd, hh*4").cpm(110/2)`} />
|
<MiniRepl
|
||||||
|
client:visible
|
||||||
|
tune={`setcpm(110/2)
|
||||||
|
s("bd sd, hh*4")`}
|
||||||
|
/>
|
||||||
|
|
||||||
<Box>
|
<Box>
|
||||||
|
|
||||||
To set a specific bpm, use `.cpm(bpm/bpc)`
|
To set a specific bpm, use `setcpm(bpm/bpc)`
|
||||||
|
|
||||||
- bpm: the target beats per minute
|
- bpm: the target beats per minute
|
||||||
- bpc: the number of perceived beats per cycle
|
- bpc: the number of perceived beats per cycle
|
||||||
|
|
@ -74,22 +86,31 @@ Many music programs use it as a default.
|
||||||
Strudel does not a have concept of bars or measures, there are only cycles.
|
Strudel does not a have concept of bars or measures, there are only cycles.
|
||||||
How you use them is up to you. Above, we've had this example:
|
How you use them is up to you. Above, we've had this example:
|
||||||
|
|
||||||
<MiniRepl client:visible tune={`s("bd sd bd rim, hh*8").cpm(110/4)`} />
|
<MiniRepl
|
||||||
|
client:visible
|
||||||
|
tune={`setcpm(110/4)
|
||||||
|
s("bd sd bd rim, hh*8")`}
|
||||||
|
/>
|
||||||
|
|
||||||
This could be interpreted as 4/4 time with a tempo of 110bpm.
|
This could be interpreted as 4/4 time with a tempo of 110bpm.
|
||||||
We could write out multiple bars like this:
|
We could write out multiple bars like this:
|
||||||
|
|
||||||
<MiniRepl
|
<MiniRepl
|
||||||
client:visible
|
client:visible
|
||||||
tune={`s(\`<
|
tune={`setcpm(110/4)
|
||||||
|
s(\`<
|
||||||
[bd sd bd rim, hh*8]
|
[bd sd bd rim, hh*8]
|
||||||
[bd sd bd rim*2, hh*8]
|
[bd sd bd rim*2, hh*8]
|
||||||
>\`).cpm(110/4)`}
|
>\`)`}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
Instead of writing out each bar separately, we could express this much shorter:
|
Instead of writing out each bar separately, we could express this much shorter:
|
||||||
|
|
||||||
<MiniRepl client:visible tune={`s("bd <sd rim*<1 2>>,hh*4").cpm(110/2)`} />
|
<MiniRepl
|
||||||
|
client:visible
|
||||||
|
tune={`setcpm(110/2)
|
||||||
|
s("bd <sd rim*<1 2>>,hh*4")`}
|
||||||
|
/>
|
||||||
|
|
||||||
Here we can see that thinking in cycles rather than bars simplifies things a lot!
|
Here we can see that thinking in cycles rather than bars simplifies things a lot!
|
||||||
These types of simplifications work because of the repetitive nature of rhythm.
|
These types of simplifications work because of the repetitive nature of rhythm.
|
||||||
|
|
@ -109,10 +130,11 @@ We could also write multiple bars with different time signatures:
|
||||||
|
|
||||||
<MiniRepl
|
<MiniRepl
|
||||||
client:visible
|
client:visible
|
||||||
tune={`s(\`<
|
tune={`setcpm(110*2)
|
||||||
|
s(\`<
|
||||||
[bd hh rim]@3
|
[bd hh rim]@3
|
||||||
[bd hh rim sd]@4
|
[bd hh rim sd]@4
|
||||||
>\`).cpm(110*2)`}
|
>\`)`}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
Here we switch between 3/4 and 4/4, keeping the same tempo.
|
Here we switch between 3/4 and 4/4, keeping the same tempo.
|
||||||
|
|
@ -121,10 +143,11 @@ If we don't specify the length, we get what's called a metric modulation:
|
||||||
|
|
||||||
<MiniRepl
|
<MiniRepl
|
||||||
client:visible
|
client:visible
|
||||||
tune={`s(\`<
|
tune={`setcpm(110/2)
|
||||||
|
s(\`<
|
||||||
[bd hh rim]
|
[bd hh rim]
|
||||||
[bd hh rim sd]
|
[bd hh rim sd]
|
||||||
>\`).cpm(110/2)`}
|
>\`)`}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
Now the 3 elements get the same time as the 4 elements, which is why the tempo changes.
|
Now the 3 elements get the same time as the 4 elements, which is why the tempo changes.
|
||||||
|
|
|
||||||
|
|
@ -216,8 +216,9 @@ Finding the right notes can be difficult.. Scales are here to help:
|
||||||
|
|
||||||
<MiniRepl
|
<MiniRepl
|
||||||
client:visible
|
client:visible
|
||||||
tune={`n("0 2 4 <[6,8] [7,9]>")
|
tune={`setcpm(60)
|
||||||
.scale("C:minor").sound("piano").cpm(60)`}
|
n("0 2 4 <[6,8] [7,9]>")
|
||||||
|
.scale("C:minor").sound("piano")`}
|
||||||
punchcard
|
punchcard
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
@ -242,9 +243,10 @@ Just like anything, we can automate the scale with a pattern:
|
||||||
|
|
||||||
<MiniRepl
|
<MiniRepl
|
||||||
client:visible
|
client:visible
|
||||||
tune={`n("<0 -3>, 2 4 <[6,8] [7,9]>")
|
tune={`setcpm(60)
|
||||||
|
n("<0 -3>, 2 4 <[6,8] [7,9]>")
|
||||||
.scale("<C:major D:mixolydian>/4")
|
.scale("<C:major D:mixolydian>/4")
|
||||||
.sound("piano").cpm(60)`}
|
.sound("piano")`}
|
||||||
punchcard
|
punchcard
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
@ -275,9 +277,10 @@ Try changing that number!
|
||||||
|
|
||||||
<MiniRepl
|
<MiniRepl
|
||||||
client:visible
|
client:visible
|
||||||
tune={`n("<[4@2 4] [5@2 5] [6@2 6] [5@2 5]>*2")
|
tune={`setcpm(60)
|
||||||
|
n("<[4@2 4] [5@2 5] [6@2 6] [5@2 5]>*2")
|
||||||
.scale("<C2:mixolydian F2:mixolydian>/4")
|
.scale("<C2:mixolydian F2:mixolydian>/4")
|
||||||
.sound("gm_acoustic_bass").cpm(60)`}
|
.sound("gm_acoustic_bass")`}
|
||||||
punchcard
|
punchcard
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
@ -291,7 +294,12 @@ This is also sometimes called triplet swing. You'll often find it in blues and j
|
||||||
|
|
||||||
**Replicate**
|
**Replicate**
|
||||||
|
|
||||||
<MiniRepl client:visible tune={`note("c!2 [eb,<g a bb a>]").sound("piano").cpm(60)`} punchcard />
|
<MiniRepl
|
||||||
|
client:visible
|
||||||
|
tune={`setcpm(60)
|
||||||
|
note("c!2 [eb,<g a bb a>]").sound("piano")`}
|
||||||
|
punchcard
|
||||||
|
/>
|
||||||
|
|
||||||
<Box>
|
<Box>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -166,9 +166,14 @@ Try also changing the number at the end to change the tempo!
|
||||||
|
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
**changing the tempo with cpm**
|
**changing the tempo with setcpm**
|
||||||
|
|
||||||
<MiniRepl client:visible tune={`sound("<bd hh rim hh>*8").cpm(90/4)`} punchcard />
|
<MiniRepl
|
||||||
|
client:visible
|
||||||
|
tune={`setcpm(90/4)
|
||||||
|
sound("<bd hh rim hh>*8")`}
|
||||||
|
punchcard
|
||||||
|
/>
|
||||||
|
|
||||||
<Box>
|
<Box>
|
||||||
|
|
||||||
|
|
@ -283,12 +288,12 @@ This is what we've learned so far:
|
||||||
|
|
||||||
The Mini-Notation is usually used inside some function. These are the functions we've seen so far:
|
The Mini-Notation is usually used inside some function. These are the functions we've seen so far:
|
||||||
|
|
||||||
| Name | Description | Example |
|
| Name | Description | Example |
|
||||||
| ----- | ----------------------------------- | --------------------------------------------------------------------------------- |
|
| ------ | ----------------------------------- | --------------------------------------------------------------------------------- |
|
||||||
| sound | plays the sound of the given name | <MiniRepl client:visible tune={`sound("bd sd [- bd] sd")`} /> |
|
| sound | plays the sound of the given name | <MiniRepl client:visible tune={`sound("bd sd [- bd] sd")`} /> |
|
||||||
| bank | selects the sound bank | <MiniRepl client:visible tune={`sound("bd sd [- bd] sd").bank("RolandTR909")`} /> |
|
| bank | selects the sound bank | <MiniRepl client:visible tune={`sound("bd sd [- bd] sd").bank("RolandTR909")`} /> |
|
||||||
| cpm | sets the tempo in cycles per minute | <MiniRepl client:visible tune={`sound("bd sd [- bd] sd").cpm(45)`} /> |
|
| setcpm | sets the tempo in cycles per minute | <MiniRepl client:visible tune={`setcpm(45); sound("bd sd [- bd] sd")`} /> |
|
||||||
| n | select sample number | <MiniRepl client:visible tune={`n("0 1 4 2 0 6 3 2").sound("jazz")`} /> |
|
| n | select sample number | <MiniRepl client:visible tune={`n("0 1 4 2 0 6 3 2").sound("jazz")`} /> |
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
|
|
@ -296,8 +301,8 @@ The Mini-Notation is usually used inside some function. These are the functions
|
||||||
|
|
||||||
<MiniRepl
|
<MiniRepl
|
||||||
client:visible
|
client:visible
|
||||||
tune={`sound("[bd sd]*2, hh*8").bank("RolandTR505")
|
tune={`setcpm(100/4)
|
||||||
.cpm(100/4)`}
|
sound("[bd sd]*2, hh*8").bank("RolandTR505")`}
|
||||||
punchcard
|
punchcard
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
@ -314,14 +319,20 @@ Certain drum patterns are reused across genres.
|
||||||
|
|
||||||
We Will Rock you
|
We Will Rock you
|
||||||
|
|
||||||
<MiniRepl client:visible tune={`sound("bd*2 cp").bank("RolandTR707").cpm(81/2)`} punchcard />
|
<MiniRepl
|
||||||
|
client:visible
|
||||||
|
tune={`setcpm(81/2)
|
||||||
|
sound("bd*2 cp").bank("RolandTR707")`}
|
||||||
|
punchcard
|
||||||
|
/>
|
||||||
|
|
||||||
**Yellow Magic Orchestra - Firecracker**
|
**Yellow Magic Orchestra - Firecracker**
|
||||||
|
|
||||||
<MiniRepl
|
<MiniRepl
|
||||||
client:visible
|
client:visible
|
||||||
tune={`sound("bd sd, - - - hh - hh - -, - perc - perc:1*2")
|
tune={`setcpm(120/2)
|
||||||
.bank("RolandCompurhythm1000").cpm(120/2)`}
|
sound("bd sd, - - - hh - hh - -, - perc - perc:1*2")
|
||||||
|
.bank("RolandCompurhythm1000")`}
|
||||||
punchcard
|
punchcard
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
@ -329,12 +340,14 @@ We Will Rock you
|
||||||
|
|
||||||
<MiniRepl
|
<MiniRepl
|
||||||
client:visible
|
client:visible
|
||||||
tune={`sound(\`
|
tune={`
|
||||||
|
setcpm(90/4)
|
||||||
|
sound(\`
|
||||||
[- - oh - ] [- - - - ] [- - - - ] [- - - - ],
|
[- - oh - ] [- - - - ] [- - - - ] [- - - - ],
|
||||||
[hh hh - - ] [hh - hh - ] [hh - hh - ] [hh - hh - ],
|
[hh hh - - ] [hh - hh - ] [hh - hh - ] [hh - hh - ],
|
||||||
[- - - - ] [cp - - - ] [- - - - ] [cp - - - ],
|
[- - - - ] [cp - - - ] [- - - - ] [cp - - - ],
|
||||||
[bd - - - ] [- - - bd] [- - bd - ] [- - - bd]
|
[bd - - - ] [- - - bd] [- - bd - ] [- - - bd]
|
||||||
\`).cpm(90/4)`}
|
\`)`}
|
||||||
punchcard
|
punchcard
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
@ -342,12 +355,13 @@ We Will Rock you
|
||||||
|
|
||||||
<MiniRepl
|
<MiniRepl
|
||||||
client:visible
|
client:visible
|
||||||
tune={`sound(\`
|
tune={`setcpm(88/4)
|
||||||
|
sound(\`
|
||||||
[- - - - ] [- - - - ] [- - - - ] [- - oh:1 - ],
|
[- - - - ] [- - - - ] [- - - - ] [- - oh:1 - ],
|
||||||
[hh hh hh hh] [hh hh hh hh] [hh hh hh hh] [hh hh - - ],
|
[hh hh hh hh] [hh hh hh hh] [hh hh hh hh] [hh hh - - ],
|
||||||
[- - - - ] [cp - - - ] [- - - - ] [~ cp - - ],
|
[- - - - ] [cp - - - ] [- - - - ] [~ cp - - ],
|
||||||
[bd bd - - ] [- - bd - ] [bd bd - bd ] [- - - - ]
|
[bd bd - - ] [- - bd - ] [bd bd - bd ] [- - - - ]
|
||||||
\`).bank("RolandTR808").cpm(88/4)`}
|
\`).bank("RolandTR808")`}
|
||||||
punchcard
|
punchcard
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
@ -355,11 +369,11 @@ We Will Rock you
|
||||||
|
|
||||||
<MiniRepl
|
<MiniRepl
|
||||||
client:visible
|
client:visible
|
||||||
tune={`s(\`jazz*2,
|
tune={`setcpm(100/2)
|
||||||
|
s(\`jazz*2,
|
||||||
insect [crow metal] - -,
|
insect [crow metal] - -,
|
||||||
- space:4 - space:1,
|
- space:4 - space:1,
|
||||||
- wind\`)
|
- wind\`)`}
|
||||||
.cpm(100/2)`}
|
|
||||||
punchcard
|
punchcard
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,9 +68,10 @@ Try commenting out one or more by adding `//` before a line
|
||||||
|
|
||||||
<MiniRepl
|
<MiniRepl
|
||||||
client:visible
|
client:visible
|
||||||
tune={`note("c2 [eb3,g3] ".add("<0 <1 -1>>"))
|
tune={`setcpm(60)
|
||||||
|
note("c2 [eb3,g3] ".add("<0 <1 -1>>"))
|
||||||
.color("<cyan <magenta yellow>>").adsr("[.1 0]:.2:[1 0]")
|
.color("<cyan <magenta yellow>>").adsr("[.1 0]:.2:[1 0]")
|
||||||
.sound("gm_acoustic_bass").room(.5).cpm(60)`}
|
.sound("gm_acoustic_bass").room(.5)`}
|
||||||
punchcard
|
punchcard
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
@ -84,9 +85,10 @@ We can add as often as we like:
|
||||||
|
|
||||||
<MiniRepl
|
<MiniRepl
|
||||||
client:visible
|
client:visible
|
||||||
tune={`note("c2 [eb3,g3]".add("<0 <1 -1>>").add("0,7"))
|
tune={`setcpm(60)
|
||||||
|
note("c2 [eb3,g3]".add("<0 <1 -1>>").add("0,7"))
|
||||||
.color("<cyan <magenta yellow>>").adsr("[.1 0]:.2:[1 0]")
|
.color("<cyan <magenta yellow>>").adsr("[.1 0]:.2:[1 0]")
|
||||||
.sound("gm_acoustic_bass").room(.5).cpm(60)`}
|
.sound("gm_acoustic_bass").room(.5)`}
|
||||||
punchcard
|
punchcard
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,13 +56,13 @@ This page is just a listing of all functions covered in the workshop!
|
||||||
|
|
||||||
## Pattern Effects
|
## Pattern Effects
|
||||||
|
|
||||||
| name | description | example |
|
| name | description | example |
|
||||||
| ---- | ----------------------------------- | ----------------------------------------------------------------------------------- |
|
| ------ | ----------------------------------- | ----------------------------------------------------------------------------------- |
|
||||||
| cpm | sets the tempo in cycles per minute | <MiniRepl client:visible tune={`sound("bd sd [~ bd] sd").cpm(45)`} /> |
|
| setcpm | sets the tempo in cycles per minute | <MiniRepl client:visible tune={`setcpm(45); sound("bd sd [~ bd] sd")`} /> |
|
||||||
| fast | speed up | <MiniRepl client:visible tune={`sound("bd sd [~ bd] sd").fast(2)`} /> |
|
| fast | speed up | <MiniRepl client:visible tune={`sound("bd sd [~ bd] sd").fast(2)`} /> |
|
||||||
| slow | slow down | <MiniRepl client:visible tune={`sound("bd sd [~ bd] sd").slow(2)`} /> |
|
| slow | slow down | <MiniRepl client:visible tune={`sound("bd sd [~ bd] sd").slow(2)`} /> |
|
||||||
| rev | reverse | <MiniRepl client:visible tune={`n("0 2 4 6").scale("C:minor").rev()`} /> |
|
| rev | reverse | <MiniRepl client:visible tune={`n("0 2 4 6").scale("C:minor").rev()`} /> |
|
||||||
| jux | split left/right, modify right | <MiniRepl client:visible tune={`n("0 2 4 6").scale("C:minor").jux(rev)`} /> |
|
| jux | split left/right, modify right | <MiniRepl client:visible tune={`n("0 2 4 6").scale("C:minor").jux(rev)`} /> |
|
||||||
| add | add numbers / notes | <MiniRepl client:visible tune={`n("0 2 4 6".add("<0 1 2 1>")).scale("C:minor")`} /> |
|
| add | add numbers / notes | <MiniRepl client:visible tune={`n("0 2 4 6".add("<0 1 2 1>")).scale("C:minor")`} /> |
|
||||||
| ply | speed up each event n times | <MiniRepl client:visible tune={`s("bd sd").ply("<1 2 3>")`} /> |
|
| ply | speed up each event n times | <MiniRepl client:visible tune={`s("bd sd").ply("<1 2 3>")`} /> |
|
||||||
| off | copy, shift time & modify | <MiniRepl client:visible tune={`s("bd sd, hh*4").off(1/8, x=>x.speed(2))`} /> |
|
| off | copy, shift time & modify | <MiniRepl client:visible tune={`s("bd sd, hh*4").off(1/8, x=>x.speed(2))`} /> |
|
||||||
|
|
|
||||||
|
|
@ -313,26 +313,6 @@ stack(
|
||||||
)
|
)
|
||||||
.fast(2/3)
|
.fast(2/3)
|
||||||
.pianoroll()`;
|
.pianoroll()`;
|
||||||
/*
|
|
||||||
export const bridgeIsOver = `// "Bridge is over"
|
|
||||||
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
|
||||||
// @by Felix Roos, bassline by BDP - The Bridge Is Over
|
|
||||||
|
|
||||||
samples({mad:'https://freesound.org/data/previews/22/22274_109943-lq.mp3'})
|
|
||||||
stack(
|
|
||||||
stack(
|
|
||||||
note("c3*2 [[c3@1.4 bb2] ab2] gb2*2 <[[gb2@1.4 ab2] bb2] gb2>")
|
|
||||||
.gain(.8).clip("[.5 1]*2"),
|
|
||||||
n("<0 1 2 3 4 3 2 1>")
|
|
||||||
.clip(.5)
|
|
||||||
.echoWith(8, 1/32, (x,i)=>x.add(n(i)).velocity(Math.pow(.7,i)))
|
|
||||||
.scale('c4 whole tone')
|
|
||||||
.echo(3, 1/8, .5)
|
|
||||||
).piano(),
|
|
||||||
s("mad").slow(2)
|
|
||||||
).cpm(78).slow(4)
|
|
||||||
.pianoroll()
|
|
||||||
`; */
|
|
||||||
|
|
||||||
export const goodTimes = `// "Good times"
|
export const goodTimes = `// "Good times"
|
||||||
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue