mirror of
https://github.com/eliasstepanik/strudel-docker.git
synced 2026-01-25 04:28:30 +00:00
Merge pull request #580 from roipoussiere/music_metadata
Music metadata
This commit is contained in:
commit
a3baf07a5c
246
test/metadata.test.mjs
Normal file
246
test/metadata.test.mjs
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
|
import { getMetadata } from '../website/src/pages/metadata_parser';
|
||||||
|
|
||||||
|
describe.concurrent('Metadata parser', () => {
|
||||||
|
it('loads a tag from inline comment', async () => {
|
||||||
|
const tune = `// @title Awesome song`;
|
||||||
|
expect(getMetadata(tune)).toStrictEqual({
|
||||||
|
title: 'Awesome song',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('loads many tags from inline comments', async () => {
|
||||||
|
const tune = `// @title Awesome song
|
||||||
|
// @by Sam`;
|
||||||
|
expect(getMetadata(tune)).toStrictEqual({
|
||||||
|
title: 'Awesome song',
|
||||||
|
by: ['Sam'],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('loads many tags from one inline comment', async () => {
|
||||||
|
const tune = `// @title Awesome song @by Sam`;
|
||||||
|
expect(getMetadata(tune)).toStrictEqual({
|
||||||
|
title: 'Awesome song',
|
||||||
|
by: ['Sam'],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('loads a tag from a block comment', async () => {
|
||||||
|
const tune = `/* @title Awesome song */`;
|
||||||
|
expect(getMetadata(tune)).toStrictEqual({
|
||||||
|
title: 'Awesome song',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('loads many tags from a block comment', async () => {
|
||||||
|
const tune = `/*
|
||||||
|
@title Awesome song
|
||||||
|
@by Sam
|
||||||
|
*/`;
|
||||||
|
expect(getMetadata(tune)).toStrictEqual({
|
||||||
|
title: 'Awesome song',
|
||||||
|
by: ['Sam'],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('loads many tags from many block comments', async () => {
|
||||||
|
const tune = `/* @title Awesome song */
|
||||||
|
/* @by Sam */`;
|
||||||
|
expect(getMetadata(tune)).toStrictEqual({
|
||||||
|
title: 'Awesome song',
|
||||||
|
by: ['Sam'],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('loads many tags from mixed comments', async () => {
|
||||||
|
const tune = `/* @title Awesome song */
|
||||||
|
// @by Sam
|
||||||
|
`;
|
||||||
|
expect(getMetadata(tune)).toStrictEqual({
|
||||||
|
title: 'Awesome song',
|
||||||
|
by: ['Sam'],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('loads a title tag with quotes syntax', async () => {
|
||||||
|
const tune = `// "Awesome song"`;
|
||||||
|
expect(getMetadata(tune)).toStrictEqual({
|
||||||
|
title: 'Awesome song',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('loads a title tag with quotes syntax among other tags', async () => {
|
||||||
|
const tune = `// "Awesome song" made @by Sam`;
|
||||||
|
expect(getMetadata(tune)).toStrictEqual({
|
||||||
|
title: 'Awesome song',
|
||||||
|
by: ['Sam'],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('loads a title tag with quotes syntax from block comment', async () => {
|
||||||
|
const tune = `/* "Awesome song"
|
||||||
|
@by Sam */`;
|
||||||
|
expect(getMetadata(tune)).toStrictEqual({
|
||||||
|
title: 'Awesome song',
|
||||||
|
by: ['Sam'],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not load a title tag with quotes syntax after a prefix', async () => {
|
||||||
|
const tune = `// I don't care about those "metadata".`;
|
||||||
|
expect(getMetadata(tune)).toStrictEqual({});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not load a title tag with quotes syntax after an other comment', async () => {
|
||||||
|
const tune = `// I don't care about those
|
||||||
|
// "metadata"`;
|
||||||
|
expect(getMetadata(tune)).toStrictEqual({});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not load a title tag with quotes syntax after other tags', async () => {
|
||||||
|
const tune = `/*
|
||||||
|
@by Sam aka "Lady Strudel"
|
||||||
|
"Sandyyy"
|
||||||
|
*/`;
|
||||||
|
expect(getMetadata(tune)).toStrictEqual({
|
||||||
|
by: ['Sam aka "Lady Strudel"', '"Sandyyy"'],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('loads a tag list with comma-separated values syntax', async () => {
|
||||||
|
const tune = `// @by Sam, Sandy`;
|
||||||
|
expect(getMetadata(tune)).toStrictEqual({
|
||||||
|
by: ['Sam', 'Sandy'],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('loads a tag list with duplicate keys syntax', async () => {
|
||||||
|
const tune = `// @by Sam
|
||||||
|
// @by Sandy`;
|
||||||
|
expect(getMetadata(tune)).toStrictEqual({
|
||||||
|
by: ['Sam', 'Sandy'],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('loads a tag list with duplicate keys syntax, with prefixes', async () => {
|
||||||
|
const tune = `// song @by Sam
|
||||||
|
// samples @by Sandy`;
|
||||||
|
expect(getMetadata(tune)).toStrictEqual({
|
||||||
|
by: ['Sam', 'Sandy'],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('loads many tag lists with duplicate keys syntax, within code', async () => {
|
||||||
|
const tune = `note("a3 c#4 e4 a4") // @by Sam @license CC0
|
||||||
|
s("bd hh sd hh") // @by Sandy @license CC BY-NC-SA`;
|
||||||
|
expect(getMetadata(tune)).toStrictEqual({
|
||||||
|
by: ['Sam', 'Sandy'],
|
||||||
|
license: ['CC0', 'CC BY-NC-SA'],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('loads a tag list with duplicate keys syntax from block comment', async () => {
|
||||||
|
const tune = `/* @by Sam
|
||||||
|
@by Sandy */`;
|
||||||
|
expect(getMetadata(tune)).toStrictEqual({
|
||||||
|
by: ['Sam', 'Sandy'],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('loads a tag list with newline syntax', async () => {
|
||||||
|
const tune = `/*
|
||||||
|
@by Sam
|
||||||
|
Sandy */`;
|
||||||
|
expect(getMetadata(tune)).toStrictEqual({
|
||||||
|
by: ['Sam', 'Sandy'],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('loads a multiline tag from block comment', async () => {
|
||||||
|
const tune = `/*
|
||||||
|
@details I wrote this song in February 19th, 2023.
|
||||||
|
It was around midnight and I was lying on
|
||||||
|
the sofa in the living room.
|
||||||
|
*/`;
|
||||||
|
expect(getMetadata(tune)).toStrictEqual({
|
||||||
|
details:
|
||||||
|
'I wrote this song in February 19th, 2023. ' +
|
||||||
|
'It was around midnight and I was lying on the sofa in the living room.',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('loads a multiline tag from block comment with duplicate keys', async () => {
|
||||||
|
const tune = `/*
|
||||||
|
@details I wrote this song in February 19th, 2023.
|
||||||
|
@details It was around midnight and I was lying on
|
||||||
|
the sofa in the living room.
|
||||||
|
*/`;
|
||||||
|
expect(getMetadata(tune)).toStrictEqual({
|
||||||
|
details:
|
||||||
|
'I wrote this song in February 19th, 2023. ' +
|
||||||
|
'It was around midnight and I was lying on the sofa in the living room.',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('loads a multiline tag from inline comments', async () => {
|
||||||
|
const tune = `// @details I wrote this song in February 19th, 2023.
|
||||||
|
// @details It was around midnight and I was lying on
|
||||||
|
// @details the sofa in the living room.
|
||||||
|
*/`;
|
||||||
|
expect(getMetadata(tune)).toStrictEqual({
|
||||||
|
details:
|
||||||
|
'I wrote this song in February 19th, 2023. ' +
|
||||||
|
'It was around midnight and I was lying on the sofa in the living room.',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('loads empty tags from inline comments', async () => {
|
||||||
|
const tune = `// @title
|
||||||
|
// @by`;
|
||||||
|
expect(getMetadata(tune)).toStrictEqual({
|
||||||
|
title: '',
|
||||||
|
by: [],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('loads tags with whitespaces from inline comments', async () => {
|
||||||
|
const tune = ` // @title Awesome song
|
||||||
|
// @by Sam Tagada `;
|
||||||
|
expect(getMetadata(tune)).toStrictEqual({
|
||||||
|
title: 'Awesome song',
|
||||||
|
by: ['Sam Tagada'],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('loads tags with whitespaces from block comment', async () => {
|
||||||
|
const tune = ` /* @title Awesome song
|
||||||
|
@by Sam Tagada */ `;
|
||||||
|
expect(getMetadata(tune)).toStrictEqual({
|
||||||
|
title: 'Awesome song',
|
||||||
|
by: ['Sam Tagada'],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('loads empty tags from block comment', async () => {
|
||||||
|
const tune = `/* @title
|
||||||
|
@by */`;
|
||||||
|
expect(getMetadata(tune)).toStrictEqual({
|
||||||
|
title: '',
|
||||||
|
by: [],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not load tags if there is not', async () => {
|
||||||
|
const tune = `note("a3 c#4 e4 a4")`;
|
||||||
|
expect(getMetadata(tune)).toStrictEqual({});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not load code that looks like a metadata tag', async () => {
|
||||||
|
const tune = `const str1 = '@title Awesome song'`;
|
||||||
|
// need a lexer to avoid this one, but it's a pretty rare use case:
|
||||||
|
// const tune = `const str1 = '// @title Awesome song'`;
|
||||||
|
|
||||||
|
expect(getMetadata(tune)).toStrictEqual({});
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -70,6 +70,7 @@ export const SIDEBAR: Sidebar = {
|
|||||||
{ text: 'Patterns', link: 'technical-manual/patterns' },
|
{ text: 'Patterns', link: 'technical-manual/patterns' },
|
||||||
{ text: 'Pattern Alignment', link: 'technical-manual/alignment' },
|
{ text: 'Pattern Alignment', link: 'technical-manual/alignment' },
|
||||||
{ text: 'Strudel vs Tidal', link: 'learn/strudel-vs-tidal' },
|
{ text: 'Strudel vs Tidal', link: 'learn/strudel-vs-tidal' },
|
||||||
|
{ text: 'Music metadata', link: 'learn/metadata' },
|
||||||
],
|
],
|
||||||
Development: [
|
Development: [
|
||||||
{ text: 'REPL', link: 'technical-manual/repl' },
|
{ text: 'REPL', link: 'technical-manual/repl' },
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
---
|
---
|
||||||
import * as tunes from '../../../src/repl/tunes.mjs';
|
import * as tunes from '../../../src/repl/tunes.mjs';
|
||||||
import HeadCommon from '../../components/HeadCommon.astro';
|
import HeadCommon from '../../components/HeadCommon.astro';
|
||||||
|
|
||||||
|
import { getMetadata } from '../metadata_parser';
|
||||||
---
|
---
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
@ -12,7 +14,7 @@ import HeadCommon from '../../components/HeadCommon.astro';
|
|||||||
Object.entries(tunes).map(([name, tune]) => (
|
Object.entries(tunes).map(([name, tune]) => (
|
||||||
<a class="rounded-md bg-slate-900 hover:bg-slate-700 cursor-pointer relative" href={`./#${btoa(tune)}`}>
|
<a class="rounded-md bg-slate-900 hover:bg-slate-700 cursor-pointer relative" href={`./#${btoa(tune)}`}>
|
||||||
<div class="absolute w-full h-full flex justify-center items-center">
|
<div class="absolute w-full h-full flex justify-center items-center">
|
||||||
<span class="bg-slate-800 p-2 rounded-md text-white">{name}</span>
|
<span class="bg-slate-800 p-2 rounded-md text-white">{getMetadata(tune)['title'] || name}</span>
|
||||||
</div>
|
</div>
|
||||||
<img src={`./img/example-${name}.png`} />
|
<img src={`./img/example-${name}.png`} />
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@ -67,6 +67,9 @@ It is a handy way to quickly turn code on and off.
|
|||||||
Try uncommenting this line by deleting `//` and refreshing the pattern.
|
Try uncommenting this line by deleting `//` and refreshing the pattern.
|
||||||
You can also use the keyboard shortcut `cmd-/` to toggle comments on and off.
|
You can also use the keyboard shortcut `cmd-/` to toggle comments on and off.
|
||||||
|
|
||||||
|
You might noticed that some comments in the REPL samples include some words starting with a "@", like `@by` or `@license`.
|
||||||
|
Those are just a convention to define some information about the music. We will talk about it in the [Music metadata](/learn/metadata) section.
|
||||||
|
|
||||||
# Strings
|
# Strings
|
||||||
|
|
||||||
Ok, so what about the content inside the quotes (e.g. `"a3 c#4 e4 a4"`)?
|
Ok, so what about the content inside the quotes (e.g. `"a3 c#4 e4 a4"`)?
|
||||||
|
|||||||
94
website/src/pages/learn/metadata.mdx
Normal file
94
website/src/pages/learn/metadata.mdx
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
---
|
||||||
|
title: Music metadata
|
||||||
|
layout: ../../layouts/MainLayout.astro
|
||||||
|
---
|
||||||
|
|
||||||
|
import { MiniRepl } from '../../docs/MiniRepl';
|
||||||
|
import { JsDoc } from '../../docs/JsDoc';
|
||||||
|
|
||||||
|
# Music metadata
|
||||||
|
|
||||||
|
You can optionally add some music metadata in your Strudel code, by using tags in code comments:
|
||||||
|
|
||||||
|
```js
|
||||||
|
// @title Hey Hoo
|
||||||
|
// @by Sam Tagada
|
||||||
|
// @license CC BY-NC-SA
|
||||||
|
```
|
||||||
|
|
||||||
|
Like other comments, those are ignored by Strudel, but it can be used by other tools to retrieve some information about the music.
|
||||||
|
|
||||||
|
It is for instance used by the [swatch tool](https://github.com/tidalcycles/strudel/tree/main/my-patterns) to display pattern titles in the [examples page](https://strudel.tidalcycles.org/examples/).
|
||||||
|
|
||||||
|
## Alternative syntax
|
||||||
|
|
||||||
|
You can also use comment blocks:
|
||||||
|
|
||||||
|
```js
|
||||||
|
/*
|
||||||
|
@title Hey Hoo
|
||||||
|
@by Sam Tagada
|
||||||
|
@license CC BY-NC-SA
|
||||||
|
*/
|
||||||
|
```
|
||||||
|
|
||||||
|
Or define multiple tags in one line:
|
||||||
|
|
||||||
|
```js
|
||||||
|
// @title Hey Hoo @by Sam Tagada @license CC BY-NC-SA
|
||||||
|
```
|
||||||
|
|
||||||
|
The `title` tag has an alternative syntax using quotes (must be defined at the very begining):
|
||||||
|
|
||||||
|
```js
|
||||||
|
// "Hey Hoo" @by Sam Tagada
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tags list
|
||||||
|
|
||||||
|
Available tags are:
|
||||||
|
|
||||||
|
- `@title`: music title
|
||||||
|
- `@by`: music author(s), separated by comma, eventually followed with a link in `<>` (ex: `@by John Doe <https://example.com>`)
|
||||||
|
- `@license`: music license(s)
|
||||||
|
- `@details`: some additional information about the music
|
||||||
|
- `@url`: web page(s) related to the music (git repo, soundcloud link, etc.)
|
||||||
|
- `@genre`: music genre(s) (pop, jazz, etc)
|
||||||
|
- `@album`: music album name
|
||||||
|
|
||||||
|
## Multiple values
|
||||||
|
|
||||||
|
Some of them accepts several values, using the comma or new line separator, or duplicating the tag:
|
||||||
|
|
||||||
|
```js
|
||||||
|
/*
|
||||||
|
@by Sam Tagada
|
||||||
|
Jimmy
|
||||||
|
@genre pop, jazz
|
||||||
|
@url https://example.com
|
||||||
|
@url https://example.org
|
||||||
|
*/
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also add optional prefixes and use tags where you want:
|
||||||
|
|
||||||
|
```js
|
||||||
|
/*
|
||||||
|
song @by Sam Tagada
|
||||||
|
samples @by Jimmy
|
||||||
|
*/
|
||||||
|
...
|
||||||
|
note("a3 c#4 e4 a4") // @by Sandy
|
||||||
|
```
|
||||||
|
|
||||||
|
## Multiline
|
||||||
|
|
||||||
|
If a tag doesn't accept a list, it can take multi-line values:
|
||||||
|
|
||||||
|
```js
|
||||||
|
/*
|
||||||
|
@details I wrote this song in February 19th, 2023.
|
||||||
|
It was around midnight and I was lying on
|
||||||
|
the sofa in the living room.
|
||||||
|
*/
|
||||||
|
```
|
||||||
34
website/src/pages/metadata_parser.js
Normal file
34
website/src/pages/metadata_parser.js
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
const ALLOW_MANY = ['by', 'url', 'genre', 'license'];
|
||||||
|
|
||||||
|
export function getMetadata(raw_code) {
|
||||||
|
const comment_regexp = /\/\*([\s\S]*?)\*\/|\/\/(.*)$/gm;
|
||||||
|
const comments = [...raw_code.matchAll(comment_regexp)].map((c) => (c[1] || c[2] || '').trim());
|
||||||
|
const tags = {};
|
||||||
|
|
||||||
|
const [prefix, title] = (comments[0] || '').split('"');
|
||||||
|
if (prefix.trim() === '' && title !== undefined) {
|
||||||
|
tags['title'] = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const comment of comments) {
|
||||||
|
const tag_matches = comment.split('@').slice(1);
|
||||||
|
for (const tag_match of tag_matches) {
|
||||||
|
let [tag, tag_value] = tag_match.split(/ (.*)/s);
|
||||||
|
tag = tag.trim();
|
||||||
|
tag_value = (tag_value || '').replaceAll(/ +/g, ' ').trim();
|
||||||
|
|
||||||
|
if (ALLOW_MANY.includes(tag)) {
|
||||||
|
const tag_list = tag_value
|
||||||
|
.split(/[,\n]/)
|
||||||
|
.map((t) => t.trim())
|
||||||
|
.filter((t) => t !== '');
|
||||||
|
tags[tag] = tag in tags ? tags[tag].concat(tag_list) : tag_list;
|
||||||
|
} else {
|
||||||
|
tag_value = tag_value.replaceAll(/\s+/g, ' ');
|
||||||
|
tags[tag] = tag in tags ? tags[tag] + ' ' + tag_value : tag_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tags;
|
||||||
|
}
|
||||||
@ -1,9 +1,11 @@
|
|||||||
|
import { getMetadata } from '../metadata_parser';
|
||||||
|
|
||||||
export function getMyPatterns() {
|
export function getMyPatterns() {
|
||||||
const my = import.meta.glob('../../../../my-patterns/**', { as: 'raw', eager: true });
|
const my = import.meta.glob('../../../../my-patterns/**', { as: 'raw', eager: true });
|
||||||
return Object.fromEntries(
|
return Object.fromEntries(
|
||||||
Object.entries(my) //
|
Object.entries(my)
|
||||||
.filter(([name]) => name.endsWith('.txt')) //
|
.filter(([name]) => name.endsWith('.txt'))
|
||||||
.map(([name, raw]) => [name.split('/').slice(-1), raw]), //
|
.map(([name, raw]) => [getMetadata(raw)['title'] || name.split('/').slice(-1), raw]),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -121,8 +121,10 @@ stack(
|
|||||||
.room(1)
|
.room(1)
|
||||||
//.pianoroll({fold:1})`;
|
//.pianoroll({fold:1})`;
|
||||||
|
|
||||||
export const caverave = `// licensed with CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
export const caverave = `// "Caverave"
|
||||||
// by Felix Roos
|
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
// @by Felix Roos
|
||||||
|
|
||||||
const keys = x => x.s('sawtooth').cutoff(1200).gain(.5)
|
const keys = x => x.s('sawtooth').cutoff(1200).gain(.5)
|
||||||
.attack(0).decay(.16).sustain(.3).release(.1);
|
.attack(0).decay(.16).sustain(.3).release(.1);
|
||||||
|
|
||||||
@ -184,8 +186,10 @@ export const barryHarris = `// adapted from a Barry Harris excercise
|
|||||||
.color('#00B8D4')
|
.color('#00B8D4')
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const blippyRhodes = `// licensed with CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
export const blippyRhodes = `// "Blippy Rhodes"
|
||||||
// by Felix Roos
|
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
// @by Felix Roos
|
||||||
|
|
||||||
samples({
|
samples({
|
||||||
bd: 'samples/tidal/bd/BT0A0D0.wav',
|
bd: 'samples/tidal/bd/BT0A0D0.wav',
|
||||||
sn: 'samples/tidal/sn/ST0T0S3.wav',
|
sn: 'samples/tidal/sn/ST0T0S3.wav',
|
||||||
@ -226,8 +230,10 @@ stack(
|
|||||||
).fast(3/2)
|
).fast(3/2)
|
||||||
//.pianoroll({fold:1})`;
|
//.pianoroll({fold:1})`;
|
||||||
|
|
||||||
export const wavyKalimba = `// licensed with CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
export const wavyKalimba = `// "Wavy kalimba"
|
||||||
// by Felix Roos
|
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
// @by Felix Roos
|
||||||
|
|
||||||
samples({
|
samples({
|
||||||
'kalimba': { c5:'https://freesound.org/data/previews/536/536549_11935698-lq.mp3' }
|
'kalimba': { c5:'https://freesound.org/data/previews/536/536549_11935698-lq.mp3' }
|
||||||
})
|
})
|
||||||
@ -256,8 +262,10 @@ stack(
|
|||||||
.delay(.2)
|
.delay(.2)
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const festivalOfFingers = `// licensed with CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
export const festivalOfFingers = `// "Festival of fingers"
|
||||||
// by Felix Roos
|
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
// @by Felix Roos
|
||||||
|
|
||||||
const chords = "<Cm7 Fm7 G7 F#7>";
|
const chords = "<Cm7 Fm7 G7 F#7>";
|
||||||
stack(
|
stack(
|
||||||
chords.voicings('lefthand').struct("x(3,8,-1)").velocity(.5).off(1/7,x=>x.transpose(12).velocity(.2)),
|
chords.voicings('lefthand').struct("x(3,8,-1)").velocity(.5).off(1/7,x=>x.transpose(12).velocity(.2)),
|
||||||
@ -271,8 +279,10 @@ stack(
|
|||||||
.note().piano()`;
|
.note().piano()`;
|
||||||
|
|
||||||
// iter, echo, echoWith
|
// iter, echo, echoWith
|
||||||
export const undergroundPlumber = `// licensed with CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
export const undergroundPlumber = `// "Underground plumber"
|
||||||
// by Felix Roos, inspired by Friendship - Let's not talk about it (1979) :)
|
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
// @by Felix Roos
|
||||||
|
// @details inspired by Friendship - Let's not talk about it (1979) :)
|
||||||
|
|
||||||
samples({ bd: 'bd/BT0A0D0.wav', sn: 'sn/ST0T0S3.wav', hh: 'hh/000_hh3closedhh.wav', cp: 'cp/HANDCLP0.wav',
|
samples({ bd: 'bd/BT0A0D0.wav', sn: 'sn/ST0T0S3.wav', hh: 'hh/000_hh3closedhh.wav', cp: 'cp/HANDCLP0.wav',
|
||||||
}, 'https://loophole-letters.vercel.app/samples/tidal/')
|
}, 'https://loophole-letters.vercel.app/samples/tidal/')
|
||||||
@ -297,8 +307,10 @@ stack(
|
|||||||
.fast(2/3)
|
.fast(2/3)
|
||||||
.pianoroll({})`;
|
.pianoroll({})`;
|
||||||
|
|
||||||
export const bridgeIsOver = `// licensed with CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
export const bridgeIsOver = `// "Bridge is over"
|
||||||
// by Felix Roos, bassline by BDP - The 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'})
|
samples({mad:'https://freesound.org/data/previews/22/22274_109943-lq.mp3'})
|
||||||
stack(
|
stack(
|
||||||
stack(
|
stack(
|
||||||
@ -318,8 +330,10 @@ stack(
|
|||||||
.pianoroll()
|
.pianoroll()
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const goodTimes = `// licensed with CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
export const goodTimes = `// "Good times"
|
||||||
// by Felix Roos
|
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
// @by Felix Roos
|
||||||
|
|
||||||
const scale = cat('C3 dorian','Bb2 major').slow(4);
|
const scale = cat('C3 dorian','Bb2 major').slow(4);
|
||||||
stack(
|
stack(
|
||||||
"2*4".add(12).scale(scale)
|
"2*4".add(12).scale(scale)
|
||||||
@ -361,8 +375,10 @@ stack(
|
|||||||
.pianoroll({maxMidi:100,minMidi:20})`;
|
.pianoroll({maxMidi:100,minMidi:20})`;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const echoPiano = `// licensed with CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
export const echoPiano = `// "Echo piano"
|
||||||
// by Felix Roos
|
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
// @by Felix Roos
|
||||||
|
|
||||||
"<0 2 [4 6](3,4,2) 3*2>"
|
"<0 2 [4 6](3,4,2) 3*2>"
|
||||||
.scale('D minor')
|
.scale('D minor')
|
||||||
.color('salmon')
|
.color('salmon')
|
||||||
@ -408,8 +424,10 @@ stack(
|
|||||||
.legato(.5)
|
.legato(.5)
|
||||||
).fast(2).note()`;
|
).fast(2).note()`;
|
||||||
|
|
||||||
export const randomBells = `// licensed with CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
export const randomBells = `// "Random bells"
|
||||||
// by Felix Roos
|
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
// @by Felix Roos
|
||||||
|
|
||||||
samples({
|
samples({
|
||||||
bell: { c6: 'https://freesound.org/data/previews/411/411089_5121236-lq.mp3' },
|
bell: { c6: 'https://freesound.org/data/previews/411/411089_5121236-lq.mp3' },
|
||||||
bass: { d2: 'https://freesound.org/data/previews/608/608286_13074022-lq.mp3' }
|
bass: { d2: 'https://freesound.org/data/previews/608/608286_13074022-lq.mp3' }
|
||||||
@ -431,8 +449,10 @@ stack(
|
|||||||
.pianoroll({minMidi:20,maxMidi:120,background:'transparent'})
|
.pianoroll({minMidi:20,maxMidi:120,background:'transparent'})
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const waa2 = `// licensed with CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
export const waa2 = `// "Waa2"
|
||||||
// by Felix Roos
|
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
// @by Felix Roos
|
||||||
|
|
||||||
n(
|
n(
|
||||||
"a4 [a3 c3] a3 c3"
|
"a4 [a3 c3] a3 c3"
|
||||||
.sub("<7 12 5 12>".slow(2))
|
.sub("<7 12 5 12>".slow(2))
|
||||||
@ -447,8 +467,10 @@ n(
|
|||||||
.room(.5)
|
.room(.5)
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const hyperpop = `// licensed with CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
export const hyperpop = `// "Hyperpop"
|
||||||
// by Felix Roos
|
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
// @by Felix Roos
|
||||||
|
|
||||||
const lfo = cosine.slow(15);
|
const lfo = cosine.slow(15);
|
||||||
const lfo2 = sine.slow(16);
|
const lfo2 = sine.slow(16);
|
||||||
const filter1 = x=>x.cutoff(lfo2.range(300,3000));
|
const filter1 = x=>x.cutoff(lfo2.range(300,3000));
|
||||||
@ -498,8 +520,10 @@ stack(
|
|||||||
).slow(2)
|
).slow(2)
|
||||||
// strudel disable-highlighting`;
|
// strudel disable-highlighting`;
|
||||||
|
|
||||||
export const festivalOfFingers3 = `// licensed with CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
export const festivalOfFingers3 = `// "Festival of fingers 3"
|
||||||
// by Felix Roos
|
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
// @by Felix Roos
|
||||||
|
|
||||||
"[-7*3],0,2,6,[8 7]"
|
"[-7*3],0,2,6,[8 7]"
|
||||||
.echoWith(4,1/4, (x,n)=>x
|
.echoWith(4,1/4, (x,n)=>x
|
||||||
.add(n*7)
|
.add(n*7)
|
||||||
@ -516,8 +540,10 @@ export const festivalOfFingers3 = `// licensed with CC BY-NC-SA 4.0 https://crea
|
|||||||
.note().piano()
|
.note().piano()
|
||||||
//.pianoroll({maxMidi:160})`;
|
//.pianoroll({maxMidi:160})`;
|
||||||
|
|
||||||
export const meltingsubmarine = `// licensed with CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
export const meltingsubmarine = `// "Melting submarine"
|
||||||
// by Felix Roos
|
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
// @by Felix Roos
|
||||||
|
|
||||||
await samples('github:tidalcycles/Dirt-Samples/master/')
|
await samples('github:tidalcycles/Dirt-Samples/master/')
|
||||||
stack(
|
stack(
|
||||||
s("bd:5,[~ <sd:1!3 sd:1(3,4,3)>],hh27(3,4,1)") // drums
|
s("bd:5,[~ <sd:1!3 sd:1(3,4,3)>],hh27(3,4,1)") // drums
|
||||||
@ -554,8 +580,10 @@ stack(
|
|||||||
)
|
)
|
||||||
.slow(3/2)`;
|
.slow(3/2)`;
|
||||||
|
|
||||||
export const outroMusic = `// licensed with CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
export const outroMusic = `// "Outro music"
|
||||||
// by Felix Roos
|
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
// @by Felix Roos
|
||||||
|
|
||||||
samples({
|
samples({
|
||||||
bd: ['bd/BT0AADA.wav','bd/BT0AAD0.wav','bd/BT0A0DA.wav','bd/BT0A0D3.wav','bd/BT0A0D0.wav','bd/BT0A0A7.wav'],
|
bd: ['bd/BT0AADA.wav','bd/BT0AAD0.wav','bd/BT0A0DA.wav','bd/BT0A0D3.wav','bd/BT0A0D0.wav','bd/BT0A0A7.wav'],
|
||||||
sd: ['sd/rytm-01-classic.wav','sd/rytm-00-hard.wav'],
|
sd: ['sd/rytm-01-classic.wav','sd/rytm-00-hard.wav'],
|
||||||
@ -583,8 +611,10 @@ samples({
|
|||||||
//.pianoroll({autorange:1,vertical:1,fold:0})
|
//.pianoroll({autorange:1,vertical:1,fold:0})
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const bassFuge = `// licensed with CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
export const bassFuge = `// "Bass fuge"
|
||||||
// by Felix Roos
|
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
// @by Felix Roos
|
||||||
|
|
||||||
samples({ flbass: ['00_c2_finger_long_neck.wav','01_c2_finger_short_neck.wav','02_c2_finger_long_bridge.wav','03_c2_finger_short_bridge.wav','04_c2_pick_long.wav','05_c2_pick_short.wav','06_c2_palm_mute.wav'] },
|
samples({ flbass: ['00_c2_finger_long_neck.wav','01_c2_finger_short_neck.wav','02_c2_finger_long_bridge.wav','03_c2_finger_short_bridge.wav','04_c2_pick_long.wav','05_c2_pick_short.wav','06_c2_palm_mute.wav'] },
|
||||||
'github:cleary/samples-flbass/main/')
|
'github:cleary/samples-flbass/main/')
|
||||||
samples({
|
samples({
|
||||||
@ -609,8 +639,10 @@ x=>x.add(7).color('steelblue')
|
|||||||
.stack(s("bd:1*2,~ sd:0,[~ hh:0]*2"))
|
.stack(s("bd:1*2,~ sd:0,[~ hh:0]*2"))
|
||||||
.pianoroll({vertical:1})`;
|
.pianoroll({vertical:1})`;
|
||||||
|
|
||||||
export const chop = `// licensed with CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
export const chop = `// "Chop"
|
||||||
// by Felix Roos
|
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
// @by Felix Roos
|
||||||
|
|
||||||
samples({ p: 'https://cdn.freesound.org/previews/648/648433_11943129-lq.mp3' })
|
samples({ p: 'https://cdn.freesound.org/previews/648/648433_11943129-lq.mp3' })
|
||||||
|
|
||||||
s("p")
|
s("p")
|
||||||
@ -622,8 +654,10 @@ s("p")
|
|||||||
.sustain(.6)
|
.sustain(.6)
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const delay = `// licensed with CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
export const delay = `// "Delay"
|
||||||
// by Felix Roos
|
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
// @by Felix Roos
|
||||||
|
|
||||||
stack(
|
stack(
|
||||||
s("bd <sd cp>")
|
s("bd <sd cp>")
|
||||||
.delay("<0 .5>")
|
.delay("<0 .5>")
|
||||||
@ -631,8 +665,10 @@ stack(
|
|||||||
.delayfeedback(".6 | .8")
|
.delayfeedback(".6 | .8")
|
||||||
).sometimes(x=>x.speed("-1"))`;
|
).sometimes(x=>x.speed("-1"))`;
|
||||||
|
|
||||||
export const orbit = `// licensed with CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
export const orbit = `// "Orbit"
|
||||||
// by Felix Roos
|
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
// @by Felix Roos
|
||||||
|
|
||||||
stack(
|
stack(
|
||||||
s("bd <sd cp>")
|
s("bd <sd cp>")
|
||||||
.delay(.5)
|
.delay(.5)
|
||||||
@ -645,8 +681,10 @@ stack(
|
|||||||
.orbit(2)
|
.orbit(2)
|
||||||
).sometimes(x=>x.speed("-1"))`;
|
).sometimes(x=>x.speed("-1"))`;
|
||||||
|
|
||||||
export const belldub = `// licensed with CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
export const belldub = `// "Belldub"
|
||||||
// by Felix Roos
|
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
// @by Felix Roos
|
||||||
|
|
||||||
samples({ bell: {b4:'https://cdn.freesound.org/previews/339/339809_5121236-lq.mp3'}})
|
samples({ bell: {b4:'https://cdn.freesound.org/previews/339/339809_5121236-lq.mp3'}})
|
||||||
// "Hand Bells, B, Single.wav" by InspectorJ (www.jshaw.co.uk) of Freesound.org
|
// "Hand Bells, B, Single.wav" by InspectorJ (www.jshaw.co.uk) of Freesound.org
|
||||||
stack(
|
stack(
|
||||||
@ -678,8 +716,10 @@ stack(
|
|||||||
.mask("<1 0>/8")
|
.mask("<1 0>/8")
|
||||||
).slow(5)`;
|
).slow(5)`;
|
||||||
|
|
||||||
export const dinofunk = `// licensed with CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
export const dinofunk = `// "Dinofunk"
|
||||||
// by Felix Roos
|
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
// @by Felix Roos
|
||||||
|
|
||||||
samples({bass:'https://cdn.freesound.org/previews/614/614637_2434927-hq.mp3',
|
samples({bass:'https://cdn.freesound.org/previews/614/614637_2434927-hq.mp3',
|
||||||
dino:{b4:'https://cdn.freesound.org/previews/316/316403_5123851-hq.mp3'}})
|
dino:{b4:'https://cdn.freesound.org/previews/316/316403_5123851-hq.mp3'}})
|
||||||
setVoicingRange('lefthand', ['c3','a4'])
|
setVoicingRange('lefthand', ['c3','a4'])
|
||||||
@ -699,8 +739,10 @@ note("Abm7".voicings('lefthand').struct("x(3,8,1)".slow(2))),
|
|||||||
note("<b4 eb4>").s('dino').delay(.8).slow(8).room(.5)
|
note("<b4 eb4>").s('dino').delay(.8).slow(8).room(.5)
|
||||||
)`;
|
)`;
|
||||||
|
|
||||||
export const sampleDemo = `// licensed with CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
export const sampleDemo = `// "Sample demo"
|
||||||
// by Felix Roos
|
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
// @by Felix Roos
|
||||||
|
|
||||||
stack(
|
stack(
|
||||||
// percussion
|
// percussion
|
||||||
s("[woodblock:1 woodblock:2*2] snare_rim:0,gong/8,brakedrum:1(3,8),~@3 cowbell:3")
|
s("[woodblock:1 woodblock:2*2] snare_rim:0,gong/8,brakedrum:1(3,8),~@3 cowbell:3")
|
||||||
@ -715,8 +757,10 @@ stack(
|
|||||||
.release(.1).room(.5)
|
.release(.1).room(.5)
|
||||||
)`;
|
)`;
|
||||||
|
|
||||||
export const holyflute = `// licensed with CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
export const holyflute = `// "Holy flute"
|
||||||
// by Felix Roos
|
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
// @by Felix Roos
|
||||||
|
|
||||||
"c3 eb3(3,8) c4/2 g3*2"
|
"c3 eb3(3,8) c4/2 g3*2"
|
||||||
.superimpose(
|
.superimpose(
|
||||||
x=>x.slow(2).add(12),
|
x=>x.slow(2).add(12),
|
||||||
@ -728,8 +772,10 @@ export const holyflute = `// licensed with CC BY-NC-SA 4.0 https://creativecommo
|
|||||||
.pianoroll({fold:0,autorange:0,vertical:0,cycles:12,smear:0,minMidi:40})
|
.pianoroll({fold:0,autorange:0,vertical:0,cycles:12,smear:0,minMidi:40})
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const flatrave = `// licensed with CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
export const flatrave = `// "Flatrave"
|
||||||
// by Felix Roos
|
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
// @by Felix Roos
|
||||||
|
|
||||||
stack(
|
stack(
|
||||||
s("bd*2,~ [cp,sd]").bank('RolandTR909'),
|
s("bd*2,~ [cp,sd]").bank('RolandTR909'),
|
||||||
|
|
||||||
@ -751,8 +797,10 @@ stack(
|
|||||||
.decay(.05).sustain(0).delay(.2).degradeBy(.5).mask("<0 1>/16")
|
.decay(.05).sustain(0).delay(.2).degradeBy(.5).mask("<0 1>/16")
|
||||||
)`;
|
)`;
|
||||||
|
|
||||||
export const amensister = `// licensed with CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
export const amensister = `// "Amensister"
|
||||||
// by Felix Roos
|
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
// @by Felix Roos
|
||||||
|
|
||||||
await samples('github:tidalcycles/Dirt-Samples/master')
|
await samples('github:tidalcycles/Dirt-Samples/master')
|
||||||
|
|
||||||
stack(
|
stack(
|
||||||
@ -785,8 +833,10 @@ stack(
|
|||||||
n("0 1").s("east").delay(.5).degradeBy(.8).speed(rand.range(.5,1.5))
|
n("0 1").s("east").delay(.5).degradeBy(.8).speed(rand.range(.5,1.5))
|
||||||
).reset("<x@7 x(5,8,-1)>")`;
|
).reset("<x@7 x(5,8,-1)>")`;
|
||||||
|
|
||||||
export const juxUndTollerei = `// licensed with CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
export const juxUndTollerei = `// "Jux und tollerei"
|
||||||
// by Felix Roos
|
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
// @by Felix Roos
|
||||||
|
|
||||||
note("c3 eb3 g3 bb3").palindrome()
|
note("c3 eb3 g3 bb3").palindrome()
|
||||||
.s('sawtooth')
|
.s('sawtooth')
|
||||||
.jux(x=>x.rev().color('green').s('sawtooth'))
|
.jux(x=>x.rev().color('green').s('sawtooth'))
|
||||||
@ -798,8 +848,10 @@ note("c3 eb3 g3 bb3").palindrome()
|
|||||||
.delay(.5).delaytime(.1).delayfeedback(.4)
|
.delay(.5).delaytime(.1).delayfeedback(.4)
|
||||||
.pianoroll()`;
|
.pianoroll()`;
|
||||||
|
|
||||||
export const csoundDemo = `// licensed with CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
export const csoundDemo = `// "CSound demo"
|
||||||
// by Felix Roos
|
// @license with CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
// @by Felix Roos
|
||||||
|
|
||||||
await loadCsound\`
|
await loadCsound\`
|
||||||
instr CoolSynth
|
instr CoolSynth
|
||||||
iduration = p3
|
iduration = p3
|
||||||
@ -832,10 +884,10 @@ endin\`
|
|||||||
//.pianoroll()
|
//.pianoroll()
|
||||||
.csound('CoolSynth')`;
|
.csound('CoolSynth')`;
|
||||||
|
|
||||||
export const loungeSponge = `
|
export const loungeSponge = `// "Lounge sponge"
|
||||||
// licensed with 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/
|
||||||
// by Felix Roos
|
// @by Felix Roos, livecode.orc by Steven Yi
|
||||||
// livecode.orc by Steven Yi
|
|
||||||
await loadOrc('github:kunstmusik/csound-live-code/master/livecode.orc')
|
await loadOrc('github:kunstmusik/csound-live-code/master/livecode.orc')
|
||||||
|
|
||||||
stack(
|
stack(
|
||||||
@ -852,8 +904,10 @@ stack(
|
|||||||
s("bd*2,[~ hh]*2,~ cp").bank('RolandTR909')
|
s("bd*2,[~ hh]*2,~ cp").bank('RolandTR909')
|
||||||
)`;
|
)`;
|
||||||
|
|
||||||
export const arpoon = `// licensed with CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
export const arpoon = `// "Arpoon"
|
||||||
// "Arpoon" by Felix Roos
|
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
// @by Felix Roos
|
||||||
|
|
||||||
await samples('github:tidalcycles/Dirt-Samples/master')
|
await samples('github:tidalcycles/Dirt-Samples/master')
|
||||||
|
|
||||||
"<<Am7 C^7> C7 F^7 [Fm7 E7b9]>".voicings('lefthand')
|
"<<Am7 C^7> C7 F^7 [Fm7 E7b9]>".voicings('lefthand')
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user