mirror of
https://github.com/eliasstepanik/strudel-docker.git
synced 2026-01-16 16:18:32 +00:00
Merge branch 'main' into pattern_selection
This commit is contained in:
commit
500ddf3946
@ -114,7 +114,7 @@ You can run the same check with `pnpm check`
|
||||
## Package Workflow
|
||||
|
||||
The project is split into multiple [packages](https://github.com/tidalcycles/strudel/tree/main/packages) with independent versioning.
|
||||
When you run `pnpm i` on the root folder, [pnpm workspaces](https://pnpm.io/workspaces) will install all dependencies of all subpackages. This will allow any js file to import `@strudel.cycles/<package-name>` to get the local version,
|
||||
When you run `pnpm i` on the root folder, [pnpm workspaces](https://pnpm.io/workspaces) will install all dependencies of all subpackages. This will allow any js file to import `@strudel/<package-name>` to get the local version,
|
||||
allowing to develop multiple packages at the same time.
|
||||
|
||||
## Package Publishing
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
/>
|
||||
<div id="output"></div>
|
||||
<script type="module">
|
||||
const strudel = await import('https://cdn.skypack.dev/@strudel.cycles/core@0.6.8');
|
||||
const strudel = await import('https://cdn.skypack.dev/@strudel/core@0.6.8');
|
||||
Object.assign(window, strudel); // assign all strudel functions to global scope to use with eval
|
||||
const input = document.getElementById('text');
|
||||
const getEvents = () => {
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
/>
|
||||
<canvas id="canvas"></canvas>
|
||||
<script type="module">
|
||||
const strudel = await import('https://cdn.skypack.dev/@strudel.cycles/core@0.6.8');
|
||||
const strudel = await import('https://cdn.skypack.dev/@strudel/core@0.6.8');
|
||||
// this adds all strudel functions to the global scope, to be used by eval
|
||||
Object.assign(window, strudel);
|
||||
// setup elements
|
||||
|
||||
@ -16,34 +16,40 @@
|
||||
</div>
|
||||
<div id="output"></div>
|
||||
<script type="module">
|
||||
import { controls, repl, evalScope } from 'https://cdn.skypack.dev/@strudel.cycles/core@0.6.8';
|
||||
import { mini } from 'https://cdn.skypack.dev/@strudel.cycles/mini@0.6.0';
|
||||
import { transpiler } from 'https://cdn.skypack.dev/@strudel.cycles/transpiler@0.6.0';
|
||||
import { controls, repl, evalScope } from 'https://cdn.skypack.dev/@strudel/core@0.11.0';
|
||||
import { mini } from 'https://cdn.skypack.dev/@strudel/mini@0.11.0';
|
||||
import { transpiler } from 'https://cdn.skypack.dev/@strudel/transpiler@0.11.0';
|
||||
import {
|
||||
getAudioContext,
|
||||
webaudioOutput,
|
||||
initAudioOnFirstClick,
|
||||
} from 'https://cdn.skypack.dev/@strudel.cycles/webaudio@0.6.0';
|
||||
registerSynthSounds,
|
||||
} from 'https://cdn.skypack.dev/@strudel/webaudio@0.11.0';
|
||||
|
||||
initAudioOnFirstClick();
|
||||
const ctx = getAudioContext();
|
||||
const input = document.getElementById('text');
|
||||
input.innerHTML = getTune();
|
||||
|
||||
evalScope(
|
||||
const loadModules = evalScope(
|
||||
controls,
|
||||
import('https://cdn.skypack.dev/@strudel.cycles/core@0.6.8'),
|
||||
import('https://cdn.skypack.dev/@strudel.cycles/mini@0.6.0'),
|
||||
import('https://cdn.skypack.dev/@strudel.cycles/tonal@0.6.0'),
|
||||
import('https://cdn.skypack.dev/@strudel.cycles/webaudio@0.6.0'),
|
||||
import('https://cdn.skypack.dev/@strudel/core@0.11.0'),
|
||||
import('https://cdn.skypack.dev/@strudel/mini@0.11.0'),
|
||||
import('https://cdn.skypack.dev/@strudel/tonal@0.11.0'),
|
||||
import('https://cdn.skypack.dev/@strudel/webaudio@0.11.0'),
|
||||
);
|
||||
|
||||
const initAudio = Promise.all([initAudioOnFirstClick(), registerSynthSounds()]);
|
||||
|
||||
const { evaluate } = repl({
|
||||
defaultOutput: webaudioOutput,
|
||||
getTime: () => ctx.currentTime,
|
||||
transpiler,
|
||||
});
|
||||
document.getElementById('start').addEventListener('click', () => evaluate(input.value));
|
||||
document.getElementById('start').addEventListener('click', async () => {
|
||||
await loadModules;
|
||||
await initAudio;
|
||||
evaluate(input.value);
|
||||
});
|
||||
|
||||
function getTune() {
|
||||
return `await samples('github:tidalcycles/Dirt-Samples/master')
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<script src="https://unpkg.com/@strudel.cycles/embed@latest"></script>
|
||||
<script src="https://unpkg.com/@strudel/embed@0.11.0"></script>
|
||||
<!-- <script src="./embed.js"></script> -->
|
||||
<strudel-repl>
|
||||
<!--
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { StrudelMirror } from '@strudel/codemirror';
|
||||
import { funk42 } from './tunes';
|
||||
import { drawPianoroll, evalScope, controls } from '@strudel.cycles/core';
|
||||
import { drawPianoroll, evalScope, controls } from '@strudel/core';
|
||||
import './style.css';
|
||||
import { initAudioOnFirstClick } from '@strudel.cycles/webaudio';
|
||||
import { transpiler } from '@strudel.cycles/transpiler';
|
||||
import { getAudioContext, webaudioOutput, registerSynthSounds } from '@strudel.cycles/webaudio';
|
||||
import { registerSoundfonts } from '@strudel.cycles/soundfonts';
|
||||
import { initAudioOnFirstClick } from '@strudel/webaudio';
|
||||
import { transpiler } from '@strudel/transpiler';
|
||||
import { getAudioContext, webaudioOutput, registerSynthSounds } from '@strudel/webaudio';
|
||||
import { registerSoundfonts } from '@strudel/soundfonts';
|
||||
|
||||
// init canvas
|
||||
const canvas = document.getElementById('roll');
|
||||
@ -26,10 +26,10 @@ const editor = new StrudelMirror({
|
||||
initAudioOnFirstClick(); // needed to make the browser happy (don't await this here..)
|
||||
const loadModules = evalScope(
|
||||
controls,
|
||||
import('@strudel.cycles/core'),
|
||||
import('@strudel.cycles/mini'),
|
||||
import('@strudel.cycles/tonal'),
|
||||
import('@strudel.cycles/webaudio'),
|
||||
import('@strudel/core'),
|
||||
import('@strudel/mini'),
|
||||
import('@strudel/tonal'),
|
||||
import('@strudel/webaudio'),
|
||||
);
|
||||
await Promise.all([loadModules, registerSynthSounds(), registerSoundfonts()]);
|
||||
},
|
||||
|
||||
@ -13,11 +13,11 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@strudel/codemirror": "workspace:*",
|
||||
"@strudel.cycles/core": "workspace:*",
|
||||
"@strudel.cycles/mini": "workspace:*",
|
||||
"@strudel.cycles/soundfonts": "workspace:*",
|
||||
"@strudel.cycles/tonal": "workspace:*",
|
||||
"@strudel.cycles/transpiler": "workspace:*",
|
||||
"@strudel.cycles/webaudio": "workspace:*"
|
||||
"@strudel/core": "workspace:*",
|
||||
"@strudel/mini": "workspace:*",
|
||||
"@strudel/soundfonts": "workspace:*",
|
||||
"@strudel/tonal": "workspace:*",
|
||||
"@strudel/transpiler": "workspace:*",
|
||||
"@strudel/webaudio": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { controls, repl, evalScope } from '@strudel.cycles/core';
|
||||
import { getAudioContext, webaudioOutput, initAudioOnFirstClick } from '@strudel.cycles/webaudio';
|
||||
import { transpiler } from '@strudel.cycles/transpiler';
|
||||
import { controls, repl, evalScope } from '@strudel/core';
|
||||
import { getAudioContext, webaudioOutput, initAudioOnFirstClick } from '@strudel/webaudio';
|
||||
import { transpiler } from '@strudel/transpiler';
|
||||
import tune from './tune.mjs';
|
||||
|
||||
const ctx = getAudioContext();
|
||||
@ -10,10 +10,10 @@ initAudioOnFirstClick();
|
||||
|
||||
evalScope(
|
||||
controls,
|
||||
import('@strudel.cycles/core'),
|
||||
import('@strudel.cycles/mini'),
|
||||
import('@strudel.cycles/webaudio'),
|
||||
import('@strudel.cycles/tonal'),
|
||||
import('@strudel/core'),
|
||||
import('@strudel/mini'),
|
||||
import('@strudel/webaudio'),
|
||||
import('@strudel/tonal'),
|
||||
);
|
||||
|
||||
const { evaluate } = repl({
|
||||
|
||||
@ -13,10 +13,10 @@
|
||||
"vite": "^5.0.10"
|
||||
},
|
||||
"dependencies": {
|
||||
"@strudel.cycles/core": "workspace:*",
|
||||
"@strudel.cycles/mini": "workspace:*",
|
||||
"@strudel.cycles/transpiler": "workspace:*",
|
||||
"@strudel.cycles/webaudio": "workspace:*",
|
||||
"@strudel.cycles/tonal": "workspace:*"
|
||||
"@strudel/core": "workspace:*",
|
||||
"@strudel/mini": "workspace:*",
|
||||
"@strudel/transpiler": "workspace:*",
|
||||
"@strudel/webaudio": "workspace:*",
|
||||
"@strudel/tonal": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
||||
14
package.json
14
package.json
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "@strudel.cycles/monorepo",
|
||||
"name": "@strudel/monorepo",
|
||||
"version": "0.5.0",
|
||||
"private": true,
|
||||
"description": "Port of tidalcycles to javascript",
|
||||
@ -45,12 +45,12 @@
|
||||
},
|
||||
"homepage": "https://strudel.cc",
|
||||
"dependencies": {
|
||||
"@strudel.cycles/core": "workspace:*",
|
||||
"@strudel.cycles/mini": "workspace:*",
|
||||
"@strudel.cycles/tonal": "workspace:*",
|
||||
"@strudel.cycles/transpiler": "workspace:*",
|
||||
"@strudel.cycles/webaudio": "workspace:*",
|
||||
"@strudel.cycles/xen": "workspace:*"
|
||||
"@strudel/core": "workspace:*",
|
||||
"@strudel/mini": "workspace:*",
|
||||
"@strudel/tonal": "workspace:*",
|
||||
"@strudel/transpiler": "workspace:*",
|
||||
"@strudel/webaudio": "workspace:*",
|
||||
"@strudel/xen": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"dependency-tree": "^10.0.9",
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
# Packages
|
||||
|
||||
Each folder represents one of the @strudel.cycles/* packages [published to npm](https://www.npmjs.com/org/strudel.cycles).
|
||||
Each folder represents one of the @strudel/* packages [published to npm](https://www.npmjs.com/org/strudel).
|
||||
|
||||
To understand how those pieces connect, refer to the [Technical Manual](https://github.com/tidalcycles/strudel/wiki/Technical-Manual) or the individual READMEs.
|
||||
|
||||
@ -12,7 +12,7 @@ import {
|
||||
lineNumbers,
|
||||
drawSelection,
|
||||
} from '@codemirror/view';
|
||||
import { Pattern, Drawer, repl, cleanupDraw } from '@strudel.cycles/core';
|
||||
import { Pattern, Drawer, repl, cleanupDraw } from '@strudel/core';
|
||||
import { isAutoCompletionEnabled } from './autocomplete.mjs';
|
||||
import { isTooltipEnabled } from './tooltip.mjs';
|
||||
import { flash, isFlashEnabled } from './flash.mjs';
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel/codemirror",
|
||||
"version": "0.9.0",
|
||||
"version": "0.11.0",
|
||||
"description": "Codemirror Extensions for Strudel",
|
||||
"main": "index.mjs",
|
||||
"publishConfig": {
|
||||
@ -41,14 +41,14 @@
|
||||
"@codemirror/state": "^6.4.0",
|
||||
"@codemirror/view": "^6.23.0",
|
||||
"@lezer/highlight": "^1.2.0",
|
||||
"@nanostores/persistent": "^0.9.1",
|
||||
"@replit/codemirror-emacs": "^6.0.1",
|
||||
"@replit/codemirror-vim": "^6.1.0",
|
||||
"@replit/codemirror-vscode-keymap": "^6.0.2",
|
||||
"@strudel.cycles/core": "workspace:*",
|
||||
"@strudel/core": "workspace:*",
|
||||
"@uiw/codemirror-themes": "^4.21.21",
|
||||
"@uiw/codemirror-themes-all": "^4.21.21",
|
||||
"nanostores": "^0.9.5",
|
||||
"@nanostores/persistent": "^0.9.1"
|
||||
"nanostores": "^0.9.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^5.0.10"
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { ref, pure } from '@strudel.cycles/core';
|
||||
import { ref, pure } from '@strudel/core';
|
||||
import { WidgetType, ViewPlugin, Decoration } from '@codemirror/view';
|
||||
import { StateEffect, StateField } from '@codemirror/state';
|
||||
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
# @strudel.cycles/core
|
||||
# @strudel/core
|
||||
|
||||
This package contains the bare essence of strudel.
|
||||
|
||||
## Install
|
||||
|
||||
```sh
|
||||
npm i @strudel.cycles/core --save
|
||||
npm i @strudel/core --save
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
```js
|
||||
import { sequence } from '@strudel.cycles/core';
|
||||
import { sequence } from '@strudel/core';
|
||||
|
||||
const pattern = sequence('a', ['b', 'c']);
|
||||
|
||||
@ -33,7 +33,7 @@ b: 3/2 - 7/4
|
||||
c: 7/4 - 2
|
||||
```
|
||||
|
||||
- [play with @strudel.cycles/core on codesandbox](https://codesandbox.io/s/strudel-core-test-forked-9ywhv7?file=/src/index.js).
|
||||
- [play with @strudel/core on codesandbox](https://codesandbox.io/s/strudel-core-test-forked-9ywhv7?file=/src/index.js).
|
||||
- [open color pattern example](https://raw.githack.com/tidalcycles/strudel/main/packages/core/examples/canvas.html)
|
||||
- [open minimal repl example](https://raw.githack.com/tidalcycles/strudel/main/packages/core/examples/vanilla.html)
|
||||
- [open minimal vite example](./examples/vite-vanilla-repl/)
|
||||
@ -97,7 +97,7 @@ const generic_params = [
|
||||
*/
|
||||
['postgain'],
|
||||
/**
|
||||
* Like {@link gain}, but linear.
|
||||
* Like `gain`, but linear.
|
||||
*
|
||||
* @name amp
|
||||
* @param {number | Pattern} amount gain.
|
||||
@ -856,7 +856,7 @@ const generic_params = [
|
||||
*/
|
||||
['detune', 'det'],
|
||||
/**
|
||||
* Set dryness of reverb. See {@link room} and {@link size} for more information about reverb.
|
||||
* Set dryness of reverb. See `room` and `size` for more information about reverb.
|
||||
*
|
||||
* @name dry
|
||||
* @param {number | Pattern} dry 0 = wet, 1 = dry
|
||||
@ -868,7 +868,7 @@ const generic_params = [
|
||||
['dry'],
|
||||
// TODO: does not seem to do anything
|
||||
/*
|
||||
* Used when using {@link begin}/{@link end} or {@link chop}/{@link striate} and friends, to change the fade out time of the 'grain' envelope.
|
||||
* Used when using `begin`/`end` or `chop`/`striate` and friends, to change the fade out time of the 'grain' envelope.
|
||||
*
|
||||
* @name fadeTime
|
||||
* @param {number | Pattern} time between 0 and 1
|
||||
@ -891,6 +891,82 @@ const generic_params = [
|
||||
*
|
||||
*/
|
||||
['freq'],
|
||||
// pitch envelope
|
||||
/**
|
||||
* Attack time of pitch envelope.
|
||||
*
|
||||
* @name pattack
|
||||
* @synonyms patt
|
||||
* @param {number | Pattern} time time in seconds
|
||||
* @example
|
||||
* note("<c eb g bb>").pattack("<0 .1 .25 .5>")
|
||||
*
|
||||
*/
|
||||
['pattack', 'patt'],
|
||||
/**
|
||||
* Decay time of pitch envelope.
|
||||
*
|
||||
* @name pdecay
|
||||
* @synonyms pdec
|
||||
* @param {number | Pattern} time time in seconds
|
||||
* @example
|
||||
* note("<c eb g bb>").pdecay("<0 .1 .25 .5>")
|
||||
*
|
||||
*/
|
||||
['pdecay', 'pdec'],
|
||||
// TODO: how to use psustain?!
|
||||
['psustain', 'psus'],
|
||||
/**
|
||||
* Release time of pitch envelope
|
||||
*
|
||||
* @name prelease
|
||||
* @synonyms prel
|
||||
* @param {number | Pattern} time time in seconds
|
||||
* @example
|
||||
* note("<c eb g bb> ~")
|
||||
* .release(.5) // to hear the pitch release
|
||||
* .prelease("<0 .1 .25 .5>")
|
||||
*
|
||||
*/
|
||||
['prelease', 'prel'],
|
||||
/**
|
||||
* Amount of pitch envelope. Negative values will flip the envelope.
|
||||
* If you don't set other pitch envelope controls, `pattack:.2` will be the default.
|
||||
*
|
||||
* @name penv
|
||||
* @param {number | Pattern} semitones change in semitones
|
||||
* @example
|
||||
* note("c")
|
||||
* .penv("<12 7 1 .5 0 -1 -7 -12>")
|
||||
*
|
||||
*/
|
||||
['penv'],
|
||||
/**
|
||||
* Curve of envelope. Defaults to linear. exponential is good for kicks
|
||||
*
|
||||
* @name pcurve
|
||||
* @param {number | Pattern} type 0 = linear, 1 = exponential
|
||||
* @example
|
||||
* note("g1*2")
|
||||
* .s("sine").pdec(.5)
|
||||
* .penv(32)
|
||||
* .pcurve("<0 1>")
|
||||
*
|
||||
*/
|
||||
['pcurve'],
|
||||
/**
|
||||
* Sets the range anchor of the envelope:
|
||||
* - anchor 0: range = [note, note + penv]
|
||||
* - anchor 1: range = [note - penv, note]
|
||||
* If you don't set an anchor, the value will default to the psustain value.
|
||||
*
|
||||
* @name panchor
|
||||
* @param {number | Pattern} anchor anchor offset
|
||||
* @example
|
||||
* note("c").penv(12).panchor("<0 .5 1 .5>")
|
||||
*
|
||||
*/
|
||||
['panchor'],
|
||||
// TODO: https://tidalcycles.org/docs/configuration/MIDIOSC/control-voltage/#gate
|
||||
['gate', 'gat'],
|
||||
// ['hatgrain'],
|
||||
@ -1115,7 +1191,7 @@ const generic_params = [
|
||||
*/
|
||||
[['ir', 'i'], 'iresponse'],
|
||||
/**
|
||||
* Sets the room size of the reverb, see {@link room}.
|
||||
* Sets the room size of the reverb, see `room`.
|
||||
* When this property is changed, the reverb will be recaculated, so only change this sparsely..
|
||||
*
|
||||
* @name roomsize
|
||||
@ -1173,7 +1249,7 @@ const generic_params = [
|
||||
*/
|
||||
['speed'],
|
||||
/**
|
||||
* Used in conjunction with {@link speed}, accepts values of "r" (rate, default behavior), "c" (cycles), or "s" (seconds). Using `unit "c"` means `speed` will be interpreted in units of cycles, e.g. `speed "1"` means samples will be stretched to fill a cycle. Using `unit "s"` means the playback speed will be adjusted so that the duration is the number of seconds specified by `speed`.
|
||||
* Used in conjunction with `speed`, accepts values of "r" (rate, default behavior), "c" (cycles), or "s" (seconds). Using `unit "c"` means `speed` will be interpreted in units of cycles, e.g. `speed "1"` means samples will be stretched to fill a cycle. Using `unit "s"` means the playback speed will be adjusted so that the duration is the number of seconds specified by `speed`.
|
||||
*
|
||||
* @name unit
|
||||
* @param {number | string | Pattern} unit see description above
|
||||
@ -1209,7 +1285,7 @@ const generic_params = [
|
||||
* Formant filter to make things sound like vowels.
|
||||
*
|
||||
* @name vowel
|
||||
* @param {string | Pattern} vowel You can use a e i o u.
|
||||
* @param {string | Pattern} vowel You can use a e i o u ae aa oe ue y uh un en an on, corresponding to [a] [e] [i] [o] [u] [æ] [ɑ] [ø] [y] [ɯ] [ʌ] [œ̃] [ɛ̃] [ɑ̃] [ɔ̃]. Aliases: aa = å = ɑ, oe = ø = ö, y = ı, ae = æ.
|
||||
* @example
|
||||
* note("c2 <eb2 <g2 g1>>").s('sawtooth')
|
||||
* .vowel("<a e i <o u>>")
|
||||
|
||||
@ -30,12 +30,12 @@ export { default as drawLine } from './drawLine.mjs';
|
||||
// below won't work with runtime.mjs (json import fails)
|
||||
/* import * as p from './package.json';
|
||||
export const version = p.version; */
|
||||
logger('🌀 @strudel.cycles/core loaded 🌀');
|
||||
logger('🌀 @strudel/core loaded 🌀');
|
||||
if (globalThis._strudelLoaded) {
|
||||
console.warn(
|
||||
`@strudel.cycles/core was loaded more than once...
|
||||
`@strudel/core was loaded more than once...
|
||||
This might happen when you have multiple versions of strudel installed.
|
||||
Please check with "npm ls @strudel.cycles/core".`,
|
||||
Please check with "npm ls @strudel/core".`,
|
||||
);
|
||||
}
|
||||
globalThis._strudelLoaded = true;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel.cycles/core",
|
||||
"version": "0.9.0",
|
||||
"name": "@strudel/core",
|
||||
"version": "0.11.0",
|
||||
"description": "Port of Tidal Cycles to JavaScript",
|
||||
"main": "index.mjs",
|
||||
"type": "module",
|
||||
|
||||
@ -26,7 +26,7 @@ export class Pattern {
|
||||
/**
|
||||
* Create a pattern. As an end user, you will most likely not create a Pattern directly.
|
||||
*
|
||||
* @param {function} query - The function that maps a {@link State} to an array of {@link Hap}.
|
||||
* @param {function} query - The function that maps a `State` to an array of `Hap`.
|
||||
* @noAutocomplete
|
||||
*/
|
||||
constructor(query) {
|
||||
@ -39,7 +39,7 @@ export class Pattern {
|
||||
|
||||
/**
|
||||
* Returns a new pattern, with the function applied to the value of
|
||||
* each hap. It has the alias {@link Pattern#fmap}.
|
||||
* each hap. It has the alias `fmap`.
|
||||
* @synonyms fmap
|
||||
* @param {Function} func to to apply to the value
|
||||
* @returns Pattern
|
||||
@ -51,7 +51,7 @@ export class Pattern {
|
||||
}
|
||||
|
||||
/**
|
||||
* see {@link Pattern#withValue}
|
||||
* see `withValue`
|
||||
* @noAutocomplete
|
||||
*/
|
||||
fmap(func) {
|
||||
@ -115,7 +115,7 @@ export class Pattern {
|
||||
}
|
||||
|
||||
/**
|
||||
* As with {@link Pattern#appBoth}, but the `whole` timespan is not the intersection,
|
||||
* As with `appBoth`, but the `whole` timespan is not the intersection,
|
||||
* but the timespan from the function of patterns that this method is called
|
||||
* on. In practice, this means that the pattern structure, including onsets,
|
||||
* are preserved from the pattern of functions (often referred to as the left
|
||||
@ -148,7 +148,7 @@ export class Pattern {
|
||||
}
|
||||
|
||||
/**
|
||||
* As with {@link Pattern#appLeft}, but `whole` timespans are instead taken from the
|
||||
* As with `appLeft`, but `whole` timespans are instead taken from the
|
||||
* pattern of values, i.e. structure is preserved from the right hand/outer
|
||||
* pattern.
|
||||
* @param {Pattern} pat_val
|
||||
@ -387,7 +387,7 @@ export class Pattern {
|
||||
}
|
||||
|
||||
/**
|
||||
* As with {@link Pattern#withQuerySpan}, but the function is applied to both the
|
||||
* As with `withQuerySpan`, but the function is applied to both the
|
||||
* begin and end time of the query timespan.
|
||||
* @param {Function} func the function to apply
|
||||
* @returns Pattern
|
||||
@ -398,7 +398,7 @@ export class Pattern {
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to {@link Pattern#withQuerySpan}, but the function is applied to the timespans
|
||||
* Similar to `withQuerySpan`, but the function is applied to the timespans
|
||||
* of all haps returned by pattern queries (both `part` timespans, and where
|
||||
* present, `whole` timespans).
|
||||
* @param {Function} func
|
||||
@ -410,7 +410,7 @@ export class Pattern {
|
||||
}
|
||||
|
||||
/**
|
||||
* As with {@link Pattern#withHapSpan}, but the function is applied to both the
|
||||
* As with `withHapSpan`, but the function is applied to both the
|
||||
* begin and end time of the hap timespans.
|
||||
* @param {Function} func the function to apply
|
||||
* @returns Pattern
|
||||
@ -431,7 +431,7 @@ export class Pattern {
|
||||
}
|
||||
|
||||
/**
|
||||
* As with {@link Pattern#withHaps}, but applies the function to every hap, rather than every list of haps.
|
||||
* As with `withHaps`, but applies the function to every hap, rather than every list of haps.
|
||||
* @param {Function} func
|
||||
* @returns Pattern
|
||||
* @noAutocomplete
|
||||
@ -499,7 +499,7 @@ export class Pattern {
|
||||
}
|
||||
|
||||
/**
|
||||
* As with {@link Pattern#filterHaps}, but the function is applied to values
|
||||
* As with `filterHaps`, but the function is applied to values
|
||||
* inside haps.
|
||||
* @param {Function} value_test
|
||||
* @returns Pattern
|
||||
@ -621,7 +621,7 @@ export class Pattern {
|
||||
}
|
||||
|
||||
/**
|
||||
* More human-readable version of the {@link Pattern#firstCycleValues} accessor.
|
||||
* More human-readable version of the `firstCycleValues` accessor.
|
||||
* @noAutocomplete
|
||||
*/
|
||||
get showFirstCycle() {
|
||||
@ -691,7 +691,7 @@ export class Pattern {
|
||||
// Methods without corresponding toplevel functions
|
||||
|
||||
/**
|
||||
* Layers the result of the given function(s). Like {@link Pattern.superimpose}, but without the original pattern:
|
||||
* Layers the result of the given function(s). Like `superimpose`, but without the original pattern:
|
||||
* @name layer
|
||||
* @memberof Pattern
|
||||
* @synonyms apply
|
||||
@ -1154,8 +1154,8 @@ export function isPattern(thing) {
|
||||
/* if (!thing instanceof Pattern) {
|
||||
console.warn(
|
||||
`Found Pattern that fails "instanceof Pattern" check.
|
||||
This may happen if you are using multiple versions of @strudel.cycles/core.
|
||||
Please check by running "npm ls @strudel.cycles/core".`,
|
||||
This may happen if you are using multiple versions of @strudel/core.
|
||||
Please check by running "npm ls @strudel/core".`,
|
||||
);
|
||||
console.log(thing);
|
||||
} */
|
||||
@ -1189,7 +1189,7 @@ export function stack(...pats) {
|
||||
|
||||
/** Concatenation: combines a list of patterns, switching between them successively, one per cycle:
|
||||
*
|
||||
* synonyms: {@link cat}
|
||||
* synonyms: `cat`
|
||||
*
|
||||
* @return {Pattern}
|
||||
* @example
|
||||
@ -1244,7 +1244,7 @@ export function cat(...pats) {
|
||||
return slowcat(...pats);
|
||||
}
|
||||
|
||||
/** Like {@link Pattern.seq}, but each step has a length, relative to the whole.
|
||||
/** Like `seq`, but each step has a length, relative to the whole.
|
||||
* @return {Pattern}
|
||||
* @example
|
||||
* timeCat([3,"e3"],[1, "g3"]).note() // "e3@3 g3".note()
|
||||
@ -1279,7 +1279,7 @@ export function fastcat(...pats) {
|
||||
return slowcat(...pats)._fast(pats.length);
|
||||
}
|
||||
|
||||
/** See {@link fastcat} */
|
||||
/** See `fastcat` */
|
||||
export function sequence(...pats) {
|
||||
return fastcat(...pats);
|
||||
}
|
||||
@ -1636,7 +1636,7 @@ export const { fastGap, fastgap } = register(['fastGap', 'fastgap'], function (f
|
||||
});
|
||||
|
||||
/**
|
||||
* Similar to compress, but doesn't leave gaps, and the 'focus' can be bigger than a cycle
|
||||
* Similar to `compress`, but doesn't leave gaps, and the 'focus' can be bigger than a cycle
|
||||
* @example
|
||||
* s("bd hh sd hh").focus(1/4, 3/4)
|
||||
*/
|
||||
@ -1753,7 +1753,7 @@ export const lastOf = register('lastOf', function (n, func, pat) {
|
||||
*/
|
||||
|
||||
/**
|
||||
* An alias for {@link firstOf}
|
||||
* An alias for `firstOf`
|
||||
* @name every
|
||||
* @memberof Pattern
|
||||
* @param {number} n how many cycles
|
||||
@ -2365,7 +2365,7 @@ export const { loopAt, loopat } = register(['loopAt', 'loopat'], function (facto
|
||||
// It is still here to work in cases where repl.mjs is not used
|
||||
/**
|
||||
* Makes the sample fit its event duration. Good for rhythmical loops like drum breaks.
|
||||
* Similar to loopAt.
|
||||
* Similar to `loopAt`.
|
||||
* @name fit
|
||||
* @example
|
||||
* samples({ rhodes: 'https://cdn.freesound.org/previews/132/132051_316502-lq.mp3' })
|
||||
|
||||
@ -7,7 +7,7 @@ This program is free software: you can redistribute it and/or modify it under th
|
||||
import { Hap } from './hap.mjs';
|
||||
import { Pattern, fastcat, reify, silence, stack, register } from './pattern.mjs';
|
||||
import Fraction from './fraction.mjs';
|
||||
import { id, _mod, clamp } from './util.mjs';
|
||||
import { id, _mod, clamp, objectMap } from './util.mjs';
|
||||
|
||||
export function steady(value) {
|
||||
// A continuous value
|
||||
@ -156,31 +156,96 @@ export const _irand = (i) => rand.fmap((x) => Math.trunc(x * i));
|
||||
*/
|
||||
export const irand = (ipat) => reify(ipat).fmap(_irand).innerJoin();
|
||||
|
||||
/**
|
||||
* pick from the list of values (or patterns of values) via the index using the given
|
||||
* pattern of integers
|
||||
const _pick = function (lookup, pat, modulo = true) {
|
||||
const array = Array.isArray(lookup);
|
||||
const len = Object.keys(lookup).length;
|
||||
|
||||
lookup = objectMap(lookup, reify);
|
||||
|
||||
if (len === 0) {
|
||||
return silence;
|
||||
}
|
||||
return pat.fmap((i) => {
|
||||
let key = i;
|
||||
if (array) {
|
||||
key = modulo ? Math.round(key) % len : clamp(Math.round(key), 0, lookup.length - 1);
|
||||
}
|
||||
return lookup[key];
|
||||
});
|
||||
};
|
||||
|
||||
/** * Picks patterns (or plain values) either from a list (by index) or a lookup table (by name).
|
||||
* Similar to `inhabit`, but maintains the structure of the original patterns.
|
||||
* @param {Pattern} pat
|
||||
* @param {*} xs
|
||||
* @returns {Pattern}
|
||||
* @example
|
||||
* note(pick("<0 1 [2!2] 3>", ["g a", "e f", "f g f g" , "g a c d"]))
|
||||
* note("<0 1 2!2 3>".pick(["g a", "e f", "f g f g" , "g c d"]))
|
||||
* @example
|
||||
* sound("<0 1 [2,0]>".pick(["bd sd", "cp cp", "hh hh"]))
|
||||
* @example
|
||||
* sound("<0!2 [0,1] 1>".pick(["bd(3,8)", "sd sd"]))
|
||||
* @example
|
||||
* s("<a!2 [a,b] b>".pick({a: "bd(3,8)", b: "sd sd"}))
|
||||
*/
|
||||
|
||||
export const pick = (pat, xs) => {
|
||||
xs = xs.map(reify);
|
||||
if (xs.length == 0) {
|
||||
return silence;
|
||||
export const pick = function (lookup, pat) {
|
||||
// backward compatibility - the args used to be flipped
|
||||
if (Array.isArray(pat)) {
|
||||
[pat, lookup] = [lookup, pat];
|
||||
}
|
||||
return pat
|
||||
.fmap((i) => {
|
||||
const key = clamp(Math.round(i), 0, xs.length - 1);
|
||||
return xs[key];
|
||||
})
|
||||
.innerJoin();
|
||||
return __pick(lookup, pat);
|
||||
};
|
||||
|
||||
const __pick = register('pick', function (lookup, pat) {
|
||||
return _pick(lookup, pat, false).innerJoin();
|
||||
});
|
||||
|
||||
/** * The same as `pick`, but if you pick a number greater than the size of the list,
|
||||
* it wraps around, rather than sticking at the maximum value.
|
||||
* For example, if you pick the fifth pattern of a list of three, you'll get the
|
||||
* second one.
|
||||
* @param {Pattern} pat
|
||||
* @param {*} xs
|
||||
* @returns {Pattern}
|
||||
*/
|
||||
|
||||
export const pickmod = register('pickmod', function (lookup, pat) {
|
||||
return _pick(lookup, pat, true).innerJoin();
|
||||
});
|
||||
|
||||
/**
|
||||
* pick from the list of values (or patterns of values) via the index using the given
|
||||
/** * Picks patterns (or plain values) either from a list (by index) or a lookup table (by name).
|
||||
* Similar to `pick`, but cycles are squeezed into the target ('inhabited') pattern.
|
||||
* @param {Pattern} pat
|
||||
* @param {*} xs
|
||||
* @returns {Pattern}
|
||||
* @example
|
||||
* "<a b [a,b]>".inhabit({a: s("bd(3,8)"),
|
||||
b: s("cp sd")
|
||||
})
|
||||
* @example
|
||||
* s("a@2 [a b] a".inhabit({a: "bd(3,8)", b: "sd sd"})).slow(4)
|
||||
*/
|
||||
export const inhabit = register('inhabit', function (lookup, pat) {
|
||||
return _pick(lookup, pat, true).squeezeJoin();
|
||||
});
|
||||
|
||||
/** * The same as `inhabit`, but if you pick a number greater than the size of the list,
|
||||
* it wraps around, rather than sticking at the maximum value.
|
||||
* For example, if you pick the fifth pattern of a list of three, you'll get the
|
||||
* second one.
|
||||
* @param {Pattern} pat
|
||||
* @param {*} xs
|
||||
* @returns {Pattern}
|
||||
*/
|
||||
|
||||
export const inhabitmod = register('inhabit', function (lookup, pat) {
|
||||
return _pick(lookup, pat, false).squeezeJoin();
|
||||
});
|
||||
|
||||
/**
|
||||
* Pick from the list of values (or patterns of values) via the index using the given
|
||||
* pattern of integers. The selected pattern will be compressed to fit the duration of the selecting event
|
||||
* @param {Pattern} pat
|
||||
* @param {*} xs
|
||||
@ -356,7 +421,7 @@ export const degradeBy = register('degradeBy', function (x, pat) {
|
||||
export const degrade = register('degrade', (pat) => pat._degradeBy(0.5));
|
||||
|
||||
/**
|
||||
* Inverse of {@link Pattern#degradeBy}: Randomly removes events from the pattern by a given amount.
|
||||
* Inverse of `degradeBy`: Randomly removes events from the pattern by a given amount.
|
||||
* 0 = 100% chance of removal
|
||||
* 1 = 0% chance of removal
|
||||
* Events that would be removed by degradeBy are let through by undegradeBy and vice versa (see second example).
|
||||
@ -380,7 +445,7 @@ export const undegrade = register('undegrade', (pat) => pat._undegradeBy(0.5));
|
||||
/**
|
||||
*
|
||||
* Randomly applies the given function by the given probability.
|
||||
* Similar to {@link Pattern#someCyclesBy}
|
||||
* Similar to `someCyclesBy`
|
||||
*
|
||||
* @name sometimesBy
|
||||
* @memberof Pattern
|
||||
@ -415,7 +480,7 @@ export const sometimes = register('sometimes', function (func, pat) {
|
||||
/**
|
||||
*
|
||||
* Randomly applies the given function by the given probability on a cycle by cycle basis.
|
||||
* Similar to {@link Pattern#sometimesBy}
|
||||
* Similar to `sometimesBy`
|
||||
*
|
||||
* @name someCyclesBy
|
||||
* @memberof Pattern
|
||||
|
||||
@ -46,6 +46,7 @@ import {
|
||||
rev,
|
||||
time,
|
||||
run,
|
||||
pick,
|
||||
} from '../index.mjs';
|
||||
|
||||
import { steady } from '../signal.mjs';
|
||||
@ -1057,4 +1058,63 @@ describe('Pattern', () => {
|
||||
expect(slowcat(0, 1).repeatCycles(2).fast(6).firstCycleValues).toStrictEqual([0, 0, 1, 1, 0, 0]);
|
||||
});
|
||||
});
|
||||
describe('inhabit', () => {
|
||||
it('Can pattern named patterns', () => {
|
||||
expect(
|
||||
sameFirst(
|
||||
sequence('a', 'b', stack('a', 'b')).inhabit({ a: sequence(1, 2), b: sequence(10, 20, 30) }),
|
||||
sequence([1, 2], [10, 20, 30], stack([1, 2], [10, 20, 30])),
|
||||
),
|
||||
);
|
||||
});
|
||||
it('Can pattern indexed patterns', () => {
|
||||
expect(
|
||||
sameFirst(
|
||||
sequence('0', '1', stack('0', '1')).inhabit([sequence(1, 2), sequence(10, 20, 30)]),
|
||||
sequence([1, 2], [10, 20, 30], stack([1, 2], [10, 20, 30])),
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('pick', () => {
|
||||
it('Can pattern named patterns', () => {
|
||||
expect(
|
||||
sameFirst(
|
||||
sequence('a', 'b', 'a', stack('a', 'b')).pick({ a: sequence(1, 2, 3, 4), b: sequence(10, 20, 30, 40) }),
|
||||
sequence(1, 20, 3, stack(4, 40)),
|
||||
),
|
||||
);
|
||||
});
|
||||
it('Can pattern indexed patterns', () => {
|
||||
expect(
|
||||
sameFirst(
|
||||
sequence(0, 1, 0, stack(0, 1)).pick([sequence(1, 2, 3, 4), sequence(10, 20, 30, 40)]),
|
||||
sequence(1, 20, 3, stack(4, 40)),
|
||||
),
|
||||
);
|
||||
});
|
||||
it('Clamps indexes', () => {
|
||||
expect(
|
||||
sameFirst(sequence(0, 1, 2, 3).pick([sequence(1, 2, 3, 4), sequence(10, 20, 30, 40)]), sequence(1, 20, 30, 40)),
|
||||
);
|
||||
});
|
||||
it('Is backwards compatible', () => {
|
||||
expect(
|
||||
sameFirst(
|
||||
pick([sequence('a', 'b'), sequence('c', 'd')], sequence(0, 1)),
|
||||
pick(sequence(0, 1), [sequence('a', 'b'), sequence('c', 'd')]),
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('pickmod', () => {
|
||||
it('Wraps indexes', () => {
|
||||
expect(
|
||||
sameFirst(
|
||||
sequence(0, 1, 2, 3).pickmod([sequence(1, 2, 3, 4), sequence(10, 20, 30, 40)]),
|
||||
sequence(1, 20, 3, 40),
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -316,3 +316,10 @@ export function hash2code(hash) {
|
||||
return base64ToUnicode(decodeURIComponent(hash));
|
||||
//return atob(decodeURIComponent(codeParam || ''));
|
||||
}
|
||||
|
||||
export function objectMap(obj, fn) {
|
||||
if (Array.isArray(obj)) {
|
||||
return obj.map(fn);
|
||||
}
|
||||
return Object.fromEntries(Object.entries(obj).map(([k, v], i) => [k, fn(v, k, i)]));
|
||||
}
|
||||
|
||||
1
packages/csound/README.md
Normal file
1
packages/csound/README.md
Normal file
@ -0,0 +1 @@
|
||||
# @strudel/csound
|
||||
@ -1,5 +1,5 @@
|
||||
import { getFrequency, logger, register } from '@strudel.cycles/core';
|
||||
import { getAudioContext } from '@strudel.cycles/webaudio';
|
||||
import { getFrequency, logger, register } from '@strudel/core';
|
||||
import { getAudioContext } from '@strudel/webaudio';
|
||||
import csd from './project.csd?raw';
|
||||
// import livecodeOrc from './livecode.orc?raw';
|
||||
import presetsOrc from './presets.orc?raw';
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel.cycles/csound",
|
||||
"version": "0.9.0",
|
||||
"name": "@strudel/csound",
|
||||
"version": "0.11.0",
|
||||
"description": "csound bindings for strudel",
|
||||
"main": "index.mjs",
|
||||
"publishConfig": {
|
||||
@ -33,8 +33,8 @@
|
||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||
"dependencies": {
|
||||
"@csound/browser": "6.18.7",
|
||||
"@strudel.cycles/core": "workspace:*",
|
||||
"@strudel.cycles/webaudio": "workspace:*"
|
||||
"@strudel/core": "workspace:*",
|
||||
"@strudel/webaudio": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^5.0.10"
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Invoke } from './utils.mjs';
|
||||
import { Pattern, noteToMidi } from '@strudel.cycles/core';
|
||||
import { Pattern, noteToMidi } from '@strudel/core';
|
||||
|
||||
const ON_MESSAGE = 0x90;
|
||||
const OFF_MESSAGE = 0x80;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { parseNumeral, Pattern } from '@strudel.cycles/core';
|
||||
import { parseNumeral, Pattern } from '@strudel/core';
|
||||
import { Invoke } from './utils.mjs';
|
||||
|
||||
Pattern.prototype.osc = function () {
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
"url": "https://github.com/tidalcycles/strudel/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"@strudel.cycles/core": "workspace:*",
|
||||
"@strudel/core": "workspace:*",
|
||||
"@tauri-apps/api": "^1.5.3"
|
||||
},
|
||||
"homepage": "https://github.com/tidalcycles/strudel#readme"
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
# @strudel.cycles/embed
|
||||
# @strudel/embed
|
||||
|
||||
This package contains a embeddable web component for the Strudel REPL.
|
||||
|
||||
## Usage
|
||||
|
||||
Either install with `npm i @strudel.cycles/embed` or just use a cdn to import the script:
|
||||
Either install with `npm i @strudel/embed` or just use a cdn to import the script:
|
||||
|
||||
```html
|
||||
<script src="https://unpkg.com/@strudel.cycles/embed@latest"></script>
|
||||
<script src="https://unpkg.com/@strudel/embed@latest"></script>
|
||||
<strudel-repl>
|
||||
<!--
|
||||
note(`[[e5 [b4 c5] d5 [c5 b4]]
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel.cycles/embed",
|
||||
"version": "0.2.0",
|
||||
"name": "@strudel/embed",
|
||||
"version": "0.11.0",
|
||||
"description": "Embeddable Web Component to load a Strudel REPL into an iframe",
|
||||
"main": "embed.js",
|
||||
"type": "module",
|
||||
|
||||
@ -27,7 +27,7 @@ npm i @strudel/hydra
|
||||
Then add the import to your evalScope:
|
||||
|
||||
```js
|
||||
import { evalScope } from '@strudel.cycles/core';
|
||||
import { evalScope } from '@strudel/core';
|
||||
|
||||
evalScope(
|
||||
import('@strudel/hydra')
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { getDrawContext } from '@strudel.cycles/core';
|
||||
import { getDrawContext } from '@strudel/core';
|
||||
|
||||
let latestOptions;
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel/hydra",
|
||||
"version": "0.9.0",
|
||||
"version": "0.11.0",
|
||||
"description": "Hydra integration for strudel",
|
||||
"main": "hydra.mjs",
|
||||
"publishConfig": {
|
||||
@ -33,7 +33,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||
"dependencies": {
|
||||
"@strudel.cycles/core": "workspace:*",
|
||||
"@strudel/core": "workspace:*",
|
||||
"hydra-synth": "^1.3.29"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
# @strudel.cycles/midi
|
||||
# @strudel/midi
|
||||
|
||||
This package adds midi functionality to strudel Patterns.
|
||||
|
||||
## Install
|
||||
|
||||
```sh
|
||||
npm i @strudel.cycles/midi --save
|
||||
npm i @strudel/midi --save
|
||||
```
|
||||
|
||||
@ -5,8 +5,8 @@ This program is free software: you can redistribute it and/or modify it under th
|
||||
*/
|
||||
|
||||
import * as _WebMidi from 'webmidi';
|
||||
import { Pattern, isPattern, logger, ref } from '@strudel.cycles/core';
|
||||
import { noteToMidi } from '@strudel.cycles/core';
|
||||
import { Pattern, isPattern, logger, ref } from '@strudel/core';
|
||||
import { noteToMidi } from '@strudel/core';
|
||||
import { Note } from 'webmidi';
|
||||
// if you use WebMidi from outside of this package, make sure to import that instance:
|
||||
export const { WebMidi } = _WebMidi;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel.cycles/midi",
|
||||
"version": "0.9.0",
|
||||
"name": "@strudel/midi",
|
||||
"version": "0.11.0",
|
||||
"description": "Midi API for strudel",
|
||||
"main": "index.mjs",
|
||||
"publishConfig": {
|
||||
@ -29,8 +29,8 @@
|
||||
},
|
||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||
"dependencies": {
|
||||
"@strudel.cycles/core": "workspace:*",
|
||||
"@strudel.cycles/webaudio": "workspace:*",
|
||||
"@strudel/core": "workspace:*",
|
||||
"@strudel/webaudio": "workspace:*",
|
||||
"webmidi": "^3.1.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
# @strudel.cycles/mini
|
||||
# @strudel/mini
|
||||
|
||||
This package contains the mini notation parser and pattern generator.
|
||||
|
||||
## Install
|
||||
|
||||
```sh
|
||||
npm i @strudel.cycles/mini --save
|
||||
npm i @strudel/mini --save
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
```js
|
||||
import { mini } from '@strudel.cycles/mini';
|
||||
import { mini } from '@strudel/mini';
|
||||
|
||||
const pattern = mini('a [b c*2]');
|
||||
|
||||
@ -28,7 +28,7 @@ yields:
|
||||
(7/8 -> 1/1, 7/8 -> 1/1, c)
|
||||
```
|
||||
|
||||
[Play with @strudel.cycles/mini codesandbox](https://codesandbox.io/s/strudel-mini-example-oe9wcu?file=/src/index.js)
|
||||
[Play with @strudel/mini codesandbox](https://codesandbox.io/s/strudel-mini-example-oe9wcu?file=/src/index.js)
|
||||
|
||||
## Mini Notation API
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@ This program is free software: you can redistribute it and/or modify it under th
|
||||
*/
|
||||
|
||||
import * as krill from './krill-parser.js';
|
||||
import * as strudel from '@strudel.cycles/core';
|
||||
import * as strudel from '@strudel/core';
|
||||
|
||||
const randOffset = 0.0003;
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel.cycles/mini",
|
||||
"version": "0.9.0",
|
||||
"name": "@strudel/mini",
|
||||
"version": "0.11.0",
|
||||
"description": "Mini notation for strudel",
|
||||
"main": "index.mjs",
|
||||
"type": "module",
|
||||
@ -32,7 +32,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||
"dependencies": {
|
||||
"@strudel.cycles/core": "workspace:*"
|
||||
"@strudel/core": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"peggy": "^3.0.2",
|
||||
|
||||
@ -5,7 +5,7 @@ This program is free software: you can redistribute it and/or modify it under th
|
||||
*/
|
||||
|
||||
import { getLeafLocation, getLeafLocations, mini, mini2ast } from '../mini.mjs';
|
||||
import '@strudel.cycles/core/euclid.mjs';
|
||||
import '@strudel/core/euclid.mjs';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
describe('mini', () => {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# @strudel.cycles/osc
|
||||
# @strudel/osc
|
||||
|
||||
OSC output for strudel patterns! Currently only tested with super collider / super dirt.
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ This program is free software: you can redistribute it and/or modify it under th
|
||||
|
||||
import OSC from 'osc-js';
|
||||
|
||||
import { logger, parseNumeral, Pattern } from '@strudel.cycles/core';
|
||||
import { logger, parseNumeral, Pattern } from '@strudel/core';
|
||||
|
||||
let connection; // Promise<OSC>
|
||||
function connect() {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel.cycles/osc",
|
||||
"version": "0.9.0",
|
||||
"name": "@strudel/osc",
|
||||
"version": "0.11.0",
|
||||
"description": "OSC messaging for strudel",
|
||||
"main": "osc.mjs",
|
||||
"publishConfig": {
|
||||
@ -36,7 +36,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||
"dependencies": {
|
||||
"@strudel.cycles/core": "workspace:*",
|
||||
"@strudel/core": "workspace:*",
|
||||
"osc-js": "^2.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel/repl",
|
||||
"version": "0.9.4",
|
||||
"version": "0.11.0",
|
||||
"description": "Strudel REPL as a Web Component",
|
||||
"main": "index.mjs",
|
||||
"publishConfig": {
|
||||
@ -33,15 +33,15 @@
|
||||
},
|
||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||
"dependencies": {
|
||||
"@strudel.cycles/core": "workspace:*",
|
||||
"@strudel.cycles/midi": "workspace:*",
|
||||
"@strudel.cycles/mini": "workspace:*",
|
||||
"@strudel.cycles/soundfonts": "workspace:*",
|
||||
"@strudel.cycles/tonal": "workspace:*",
|
||||
"@strudel.cycles/transpiler": "workspace:*",
|
||||
"@strudel.cycles/webaudio": "workspace:*",
|
||||
"@strudel/codemirror": "workspace:*",
|
||||
"@strudel/hydra": "workspace:*"
|
||||
"@strudel/core": "workspace:*",
|
||||
"@strudel/hydra": "workspace:*",
|
||||
"@strudel/midi": "workspace:*",
|
||||
"@strudel/mini": "workspace:*",
|
||||
"@strudel/soundfonts": "workspace:*",
|
||||
"@strudel/tonal": "workspace:*",
|
||||
"@strudel/transpiler": "workspace:*",
|
||||
"@strudel/webaudio": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-replace": "^5.0.5",
|
||||
|
||||
@ -1,22 +1,22 @@
|
||||
import { controls, noteToMidi, valueToMidi, Pattern, evalScope } from '@strudel.cycles/core';
|
||||
import { registerSynthSounds, registerZZFXSounds, samples } from '@strudel.cycles/webaudio';
|
||||
import * as core from '@strudel.cycles/core';
|
||||
import { controls, noteToMidi, valueToMidi, Pattern, evalScope } from '@strudel/core';
|
||||
import { registerSynthSounds, registerZZFXSounds, samples } from '@strudel/webaudio';
|
||||
import * as core from '@strudel/core';
|
||||
|
||||
export async function prebake() {
|
||||
const modulesLoading = evalScope(
|
||||
// import('@strudel.cycles/core'),
|
||||
// import('@strudel/core'),
|
||||
core,
|
||||
import('@strudel.cycles/mini'),
|
||||
import('@strudel.cycles/tonal'),
|
||||
import('@strudel.cycles/webaudio'),
|
||||
import('@strudel/mini'),
|
||||
import('@strudel/tonal'),
|
||||
import('@strudel/webaudio'),
|
||||
import('@strudel/codemirror'),
|
||||
import('@strudel/hydra'),
|
||||
import('@strudel.cycles/soundfonts'),
|
||||
import('@strudel.cycles/midi'),
|
||||
// import('@strudel.cycles/xen'),
|
||||
// import('@strudel.cycles/serial'),
|
||||
// import('@strudel.cycles/csound'),
|
||||
// import('@strudel.cycles/osc'),
|
||||
import('@strudel/soundfonts'),
|
||||
import('@strudel/midi'),
|
||||
// import('@strudel/xen'),
|
||||
// import('@strudel/serial'),
|
||||
// import('@strudel/csound'),
|
||||
// import('@strudel/osc'),
|
||||
controls, // sadly, this cannot be exported from core directly (yet)
|
||||
);
|
||||
// load samples
|
||||
@ -26,10 +26,10 @@ export async function prebake() {
|
||||
registerSynthSounds(),
|
||||
registerZZFXSounds(),
|
||||
//registerSoundfonts(),
|
||||
// need dynamic import here, because importing @strudel.cycles/soundfonts fails on server:
|
||||
// => getting "window is not defined", as soon as "@strudel.cycles/soundfonts" is imported statically
|
||||
// need dynamic import here, because importing @strudel/soundfonts fails on server:
|
||||
// => getting "window is not defined", as soon as "@strudel/soundfonts" is imported statically
|
||||
// seems to be a problem with soundfont2
|
||||
import('@strudel.cycles/soundfonts').then(({ registerSoundfonts }) => registerSoundfonts()),
|
||||
import('@strudel/soundfonts').then(({ registerSoundfonts }) => registerSoundfonts()),
|
||||
samples(`${ds}/tidal-drum-machines.json`),
|
||||
samples(`${ds}/piano.json`),
|
||||
samples(`${ds}/Dirt-Samples.json`),
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { getDrawContext, silence } from '@strudel.cycles/core';
|
||||
import { transpiler } from '@strudel.cycles/transpiler';
|
||||
import { getAudioContext, webaudioOutput } from '@strudel.cycles/webaudio';
|
||||
import { getDrawContext, silence } from '@strudel/core';
|
||||
import { transpiler } from '@strudel/transpiler';
|
||||
import { getAudioContext, webaudioOutput } from '@strudel/webaudio';
|
||||
import { StrudelMirror, codemirrorSettings } from '@strudel/codemirror';
|
||||
import { prebake } from './prebake.mjs';
|
||||
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
# @strudel.cycles/serial
|
||||
# @strudel/serial
|
||||
|
||||
This package adds webserial functionality to strudel Patterns, for e.g. sending messages to arduino microcontrollers.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel.cycles/serial",
|
||||
"version": "0.9.0",
|
||||
"name": "@strudel/serial",
|
||||
"version": "0.11.0",
|
||||
"description": "Webserial API for strudel",
|
||||
"main": "serial.mjs",
|
||||
"publishConfig": {
|
||||
@ -29,7 +29,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||
"dependencies": {
|
||||
"@strudel.cycles/core": "workspace:*"
|
||||
"@strudel/core": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^5.0.10"
|
||||
|
||||
@ -4,7 +4,7 @@ Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/st
|
||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Pattern, isPattern } from '@strudel.cycles/core';
|
||||
import { Pattern, isPattern } from '@strudel/core';
|
||||
|
||||
var writeMessagers = {};
|
||||
var choosing = false;
|
||||
|
||||
1
packages/soundfonts/README.md
Normal file
1
packages/soundfonts/README.md
Normal file
@ -0,0 +1 @@
|
||||
# @strudel/soundfonts
|
||||
@ -1,5 +1,12 @@
|
||||
import { noteToMidi, freqToMidi, getSoundIndex } from '@strudel.cycles/core';
|
||||
import { getAudioContext, registerSound, getParamADSR, getADSRValues } from '@strudel.cycles/webaudio';
|
||||
import { noteToMidi, freqToMidi, getSoundIndex } from '@strudel/core';
|
||||
import {
|
||||
getAudioContext,
|
||||
registerSound,
|
||||
getParamADSR,
|
||||
getADSRValues,
|
||||
getPitchEnvelope,
|
||||
getVibratoOscillator,
|
||||
} from '@strudel/webaudio';
|
||||
import gm from './gm.mjs';
|
||||
|
||||
let loadCache = {};
|
||||
@ -149,10 +156,16 @@ export function registerSoundfonts() {
|
||||
getParamADSR(node.gain, attack, decay, sustain, release, 0, 0.3, time, holdEnd, 'linear');
|
||||
let envEnd = holdEnd + release + 0.01;
|
||||
|
||||
// vibrato
|
||||
let vibratoOscillator = getVibratoOscillator(bufferSource.detune, value, time);
|
||||
// pitch envelope
|
||||
getPitchEnvelope(bufferSource.detune, value, time, holdEnd);
|
||||
|
||||
bufferSource.stop(envEnd);
|
||||
const stop = (releaseTime) => {};
|
||||
bufferSource.onended = () => {
|
||||
bufferSource.disconnect();
|
||||
vibratoOscillator?.stop();
|
||||
node.disconnect();
|
||||
onended();
|
||||
};
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel.cycles/soundfonts",
|
||||
"version": "0.9.0",
|
||||
"name": "@strudel/soundfonts",
|
||||
"version": "0.11.0",
|
||||
"description": "Soundsfont support for strudel",
|
||||
"main": "index.mjs",
|
||||
"publishConfig": {
|
||||
@ -30,8 +30,8 @@
|
||||
},
|
||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||
"dependencies": {
|
||||
"@strudel.cycles/core": "workspace:*",
|
||||
"@strudel.cycles/webaudio": "workspace:*",
|
||||
"@strudel/core": "workspace:*",
|
||||
"@strudel/webaudio": "workspace:*",
|
||||
"sfumato": "^0.1.2",
|
||||
"soundfont2": "^0.4.0"
|
||||
},
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Pattern, getPlayableNoteValue, noteToMidi } from '@strudel.cycles/core';
|
||||
import { getAudioContext, registerSound } from '@strudel.cycles/webaudio';
|
||||
import { Pattern, getPlayableNoteValue, noteToMidi } from '@strudel/core';
|
||||
import { getAudioContext, registerSound } from '@strudel/webaudio';
|
||||
import { loadSoundfont as _loadSoundfont, startPresetNote } from 'sfumato';
|
||||
|
||||
Pattern.prototype.soundfont = function (sf, n = 0) {
|
||||
|
||||
@ -31,10 +31,10 @@ export const getParamADSR = (
|
||||
decay = nanFallback(decay);
|
||||
sustain = nanFallback(sustain);
|
||||
release = nanFallback(release);
|
||||
|
||||
const ramp = curve === 'exponential' ? 'exponentialRampToValueAtTime' : 'linearRampToValueAtTime';
|
||||
if (curve === 'exponential') {
|
||||
min = Math.max(0.0001, min);
|
||||
min = min === 0 ? 0.001 : min;
|
||||
max = max === 0 ? 0.001 : max;
|
||||
}
|
||||
const range = max - min;
|
||||
const peak = max;
|
||||
@ -42,12 +42,17 @@ export const getParamADSR = (
|
||||
const duration = end - begin;
|
||||
|
||||
const envValAtTime = (time) => {
|
||||
let val;
|
||||
if (attack > time) {
|
||||
let slope = getSlope(min, peak, 0, attack);
|
||||
return time * slope + (min > peak ? min : 0);
|
||||
val = time * slope + (min > peak ? min : 0);
|
||||
} else {
|
||||
return (time - attack) * getSlope(peak, sustainVal, 0, decay) + peak;
|
||||
val = (time - attack) * getSlope(peak, sustainVal, 0, decay) + peak;
|
||||
}
|
||||
if (curve === 'exponential') {
|
||||
val = val || 0.001;
|
||||
}
|
||||
return val;
|
||||
};
|
||||
|
||||
param.setValueAtTime(min, begin);
|
||||
@ -144,3 +149,40 @@ export function drywet(dry, wet, wetAmount = 0) {
|
||||
wet_gain.connect(mix);
|
||||
return mix;
|
||||
}
|
||||
|
||||
let curves = ['linear', 'exponential'];
|
||||
export function getPitchEnvelope(param, value, t, holdEnd) {
|
||||
// envelope is active when any of these values is set
|
||||
const hasEnvelope = value.pattack ?? value.pdecay ?? value.psustain ?? value.prelease ?? value.penv;
|
||||
if (!hasEnvelope) {
|
||||
return;
|
||||
}
|
||||
const penv = nanFallback(value.penv, 1, true);
|
||||
const curve = curves[value.pcurve ?? 0];
|
||||
let [pattack, pdecay, psustain, prelease] = getADSRValues(
|
||||
[value.pattack, value.pdecay, value.psustain, value.prelease],
|
||||
curve,
|
||||
[0.2, 0.001, 1, 0.001],
|
||||
);
|
||||
let panchor = value.panchor ?? psustain;
|
||||
const cents = penv * 100; // penv is in semitones
|
||||
const min = 0 - cents * panchor;
|
||||
const max = cents - cents * panchor;
|
||||
getParamADSR(param, pattack, pdecay, psustain, prelease, min, max, t, holdEnd, curve);
|
||||
}
|
||||
|
||||
export function getVibratoOscillator(param, value, t) {
|
||||
const { vibmod = 0.5, vib } = value;
|
||||
let vibratoOscillator;
|
||||
if (vib > 0) {
|
||||
vibratoOscillator = getAudioContext().createOscillator();
|
||||
vibratoOscillator.frequency.value = vib;
|
||||
const gain = getAudioContext().createGain();
|
||||
// Vibmod is the amount of vibrato, in semitones
|
||||
gain.gain.value = vibmod * 100;
|
||||
vibratoOscillator.connect(gain);
|
||||
gain.connect(param);
|
||||
vibratoOscillator.start(t);
|
||||
return vibratoOscillator;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "superdough",
|
||||
"version": "0.9.12",
|
||||
"version": "0.10.0",
|
||||
"description": "simple web audio synth and sampler intended for live coding. inspired by superdirt and webdirt.",
|
||||
"main": "index.mjs",
|
||||
"type": "module",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { noteToMidi, valueToMidi, getSoundIndex } from './util.mjs';
|
||||
import { getAudioContext, registerSound } from './index.mjs';
|
||||
import { getADSRValues, getParamADSR } from './helpers.mjs';
|
||||
import { getADSRValues, getParamADSR, getPitchEnvelope, getVibratoOscillator } from './helpers.mjs';
|
||||
import { logger } from './logger.mjs';
|
||||
|
||||
const bufferCache = {}; // string: Promise<ArrayBuffer>
|
||||
@ -244,8 +244,6 @@ export async function onTriggerSample(t, value, onended, bank, resolveUrl) {
|
||||
loopEnd = 1,
|
||||
end = 1,
|
||||
duration,
|
||||
vib,
|
||||
vibmod = 0.5,
|
||||
} = value;
|
||||
// load sample
|
||||
if (speed === 0) {
|
||||
@ -263,17 +261,7 @@ export async function onTriggerSample(t, value, onended, bank, resolveUrl) {
|
||||
const bufferSource = await getSampleBufferSource(s, n, note, speed, freq, bank, resolveUrl);
|
||||
|
||||
// vibrato
|
||||
let vibratoOscillator;
|
||||
if (vib > 0) {
|
||||
vibratoOscillator = getAudioContext().createOscillator();
|
||||
vibratoOscillator.frequency.value = vib;
|
||||
const gain = getAudioContext().createGain();
|
||||
// Vibmod is the amount of vibrato, in semitones
|
||||
gain.gain.value = vibmod * 100;
|
||||
vibratoOscillator.connect(gain);
|
||||
gain.connect(bufferSource.detune);
|
||||
vibratoOscillator.start(0);
|
||||
}
|
||||
let vibratoOscillator = getVibratoOscillator(bufferSource.detune, value, t);
|
||||
|
||||
// asny stuff above took too long?
|
||||
if (ac.currentTime > t) {
|
||||
@ -310,6 +298,9 @@ export async function onTriggerSample(t, value, onended, bank, resolveUrl) {
|
||||
|
||||
getParamADSR(node.gain, attack, decay, sustain, release, 0, 1, t, holdEnd, 'linear');
|
||||
|
||||
// pitch envelope
|
||||
getPitchEnvelope(bufferSource.detune, value, t, holdEnd);
|
||||
|
||||
const out = ac.createGain(); // we need a separate gain for the cutgroups because firefox...
|
||||
node.connect(out);
|
||||
bufferSource.onended = function () {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { midiToFreq, noteToMidi } from './util.mjs';
|
||||
import { registerSound, getAudioContext } from './superdough.mjs';
|
||||
import { gainNode, getADSRValues, getParamADSR } from './helpers.mjs';
|
||||
import { gainNode, getADSRValues, getParamADSR, getPitchEnvelope, getVibratoOscillator } from './helpers.mjs';
|
||||
import { getNoiseMix, getNoiseOscillator } from './noise.mjs';
|
||||
|
||||
const mod = (freq, range = 1, type = 'sine') => {
|
||||
@ -105,15 +105,11 @@ export function waveformN(partials, type) {
|
||||
}
|
||||
|
||||
// expects one of waveforms as s
|
||||
export function getOscillator(
|
||||
s,
|
||||
t,
|
||||
{
|
||||
export function getOscillator(s, t, value) {
|
||||
let {
|
||||
n: partials,
|
||||
note,
|
||||
freq,
|
||||
vib = 0,
|
||||
vibmod = 0.5,
|
||||
noise = 0,
|
||||
// fm
|
||||
fmh: fmHarmonicity = 1,
|
||||
@ -126,8 +122,7 @@ export function getOscillator(
|
||||
fmvelocity: fmVelocity,
|
||||
fmwave: fmWaveform = 'sine',
|
||||
duration,
|
||||
},
|
||||
) {
|
||||
} = value;
|
||||
let ac = getAudioContext();
|
||||
let o;
|
||||
// If no partials are given, use stock waveforms
|
||||
@ -184,17 +179,10 @@ export function getOscillator(
|
||||
}
|
||||
|
||||
// Additional oscillator for vibrato effect
|
||||
let vibratoOscillator;
|
||||
if (vib > 0) {
|
||||
vibratoOscillator = getAudioContext().createOscillator();
|
||||
vibratoOscillator.frequency.value = vib;
|
||||
const gain = getAudioContext().createGain();
|
||||
// Vibmod is the amount of vibrato, in semitones
|
||||
gain.gain.value = vibmod * 100;
|
||||
vibratoOscillator.connect(gain);
|
||||
gain.connect(o.detune);
|
||||
vibratoOscillator.start(t);
|
||||
}
|
||||
let vibratoOscillator = getVibratoOscillator(o.detune, value, t);
|
||||
|
||||
// pitch envelope
|
||||
getPitchEnvelope(o.detune, value, t, t + duration);
|
||||
|
||||
let noiseMix;
|
||||
if (noise) {
|
||||
|
||||
@ -5,6 +5,37 @@ export var vowelFormant = {
|
||||
i: { freqs: [270, 1850, 2900, 3350, 3590], gains: [1, 0.0631, 0.0631, 0.0158, 0.0158], qs: [40, 90, 100, 120, 120] },
|
||||
o: { freqs: [430, 820, 2700, 3000, 3300], gains: [1, 0.3162, 0.0501, 0.0794, 0.01995], qs: [40, 80, 100, 120, 120] },
|
||||
u: { freqs: [370, 630, 2750, 3000, 3400], gains: [1, 0.1, 0.0708, 0.0316, 0.01995], qs: [40, 60, 100, 120, 120] },
|
||||
ae: { freqs: [650, 1515, 2400, 3000, 3350], gains: [1, 0.5, 0.1008, 0.0631, 0.0126], qs: [80, 90, 120, 130, 140] },
|
||||
aa: { freqs: [560, 900, 2570, 3000, 3300], gains: [1, 0.5, 0.0708, 0.0631, 0.0126], qs: [80, 90, 120, 130, 140] },
|
||||
oe: { freqs: [500, 1430, 2300, 3000, 3300], gains: [1, 0.2, 0.0708, 0.0316, 0.01995], qs: [40, 60, 100, 120, 120] },
|
||||
ue: { freqs: [250, 1750, 2150, 3200, 3300], gains: [1, 0.1, 0.0708, 0.0316, 0.01995], qs: [40, 60, 100, 120, 120] },
|
||||
y: { freqs: [400, 1460, 2400, 3000, 3300], gains: [1, 0.2, 0.0708, 0.0316, 0.02995], qs: [40, 60, 100, 120, 120] },
|
||||
uh: { freqs: [600, 1250, 2100, 3100, 3500], gains: [1, 0.3, 0.0608, 0.0316, 0.01995], qs: [40, 70, 100, 120, 130] },
|
||||
un: { freqs: [500, 1240, 2280, 3000, 3500], gains: [1, 0.1, 0.1708, 0.0216, 0.02995], qs: [40, 60, 100, 120, 120] },
|
||||
en: { freqs: [600, 1480, 2450, 3200, 3300], gains: [1, 0.15, 0.0708, 0.0316, 0.02995], qs: [40, 60, 100, 120, 120] },
|
||||
an: { freqs: [700, 1050, 2500, 3000, 3300], gains: [1, 0.1, 0.0708, 0.0316, 0.02995], qs: [40, 60, 100, 120, 120] },
|
||||
on: { freqs: [500, 1080, 2350, 3000, 3300], gains: [1, 0.1, 0.0708, 0.0316, 0.02995], qs: [40, 60, 100, 120, 120] },
|
||||
get æ() {
|
||||
return this.ae;
|
||||
},
|
||||
get ø() {
|
||||
return this.oe;
|
||||
},
|
||||
get ɑ() {
|
||||
return this.aa;
|
||||
},
|
||||
get å() {
|
||||
return this.aa;
|
||||
},
|
||||
get ö() {
|
||||
return this.oe;
|
||||
},
|
||||
get ü() {
|
||||
return this.ue;
|
||||
},
|
||||
get ı() {
|
||||
return this.y;
|
||||
},
|
||||
};
|
||||
if (typeof GainNode !== 'undefined') {
|
||||
class VowelNode extends GainNode {
|
||||
|
||||
@ -1,18 +1,18 @@
|
||||
# @strudel.cycles/tonal
|
||||
# @strudel/tonal
|
||||
|
||||
This package adds tonal / harmonic functions to strudel Patterns.
|
||||
|
||||
## Install
|
||||
|
||||
```sh
|
||||
npm i @strudel.cycles/tonal --save
|
||||
npm i @strudel/tonal --save
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
```js
|
||||
import { sequence } from '@strudel.cycles/core';
|
||||
import '@strudel.cycles/tonal';
|
||||
import { sequence } from '@strudel/core';
|
||||
import '@strudel/tonal';
|
||||
|
||||
const pattern = sequence(0, [1, 2]).scale('C major');
|
||||
|
||||
@ -27,7 +27,7 @@ yields:
|
||||
(3/4 -> 1/1, 3/4 -> 1/1, E3)
|
||||
```
|
||||
|
||||
[play with @strudel.cycles/tonal codesandbox](https://codesandbox.io/s/strudel-tonal-example-rgc5if?file=/src/index.js)
|
||||
[play with @strudel/tonal codesandbox](https://codesandbox.io/s/strudel-tonal-example-rgc5if?file=/src/index.js)
|
||||
|
||||
## Tonal API
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel.cycles/tonal",
|
||||
"version": "0.9.0",
|
||||
"name": "@strudel/tonal",
|
||||
"version": "0.11.0",
|
||||
"description": "Tonal functions for strudel",
|
||||
"main": "index.mjs",
|
||||
"publishConfig": {
|
||||
@ -31,7 +31,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||
"dependencies": {
|
||||
"@strudel.cycles/core": "workspace:*",
|
||||
"@strudel/core": "workspace:*",
|
||||
"@tonaljs/tonal": "^4.7.2",
|
||||
"chord-voicings": "^0.0.1",
|
||||
"webmidi": "^3.1.8"
|
||||
|
||||
@ -7,7 +7,7 @@ This program is free software: you can redistribute it and/or modify it under th
|
||||
// import { strict as assert } from 'assert';
|
||||
|
||||
import '../tonal.mjs'; // need to import this to add prototypes
|
||||
import { pure, controls, seq } from '@strudel.cycles/core';
|
||||
import { pure, controls, seq } from '@strudel/core';
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { mini } from '../../mini/mini.mjs';
|
||||
const { n } = controls;
|
||||
|
||||
@ -5,7 +5,7 @@ This program is free software: you can redistribute it and/or modify it under th
|
||||
*/
|
||||
|
||||
import { Note, Interval, Scale } from '@tonaljs/tonal';
|
||||
import { register, _mod, silence, logger, pure, isNote } from '@strudel.cycles/core';
|
||||
import { register, _mod, silence, logger, pure, isNote } from '@strudel/core';
|
||||
import { stepInNamedScale } from './tonleiter.mjs';
|
||||
|
||||
const octavesInterval = (octaves) => (octaves <= 0 ? -1 : 1) + octaves * 7 + 'P';
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { isNote, isNoteWithOctave, _mod, noteToMidi, tokenizeNote } from '@strudel.cycles/core';
|
||||
import { isNote, isNoteWithOctave, _mod, noteToMidi, tokenizeNote } from '@strudel/core';
|
||||
import { Interval, Scale } from '@tonaljs/tonal';
|
||||
|
||||
// https://codesandbox.io/s/stateless-voicings-g2tmz0?file=/src/lib.js:0-2515
|
||||
|
||||
@ -4,7 +4,7 @@ Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/st
|
||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { stack, register, silence, logger } from '@strudel.cycles/core';
|
||||
import { stack, register, silence, logger } from '@strudel/core';
|
||||
import { renderVoicing } from './tonleiter.mjs';
|
||||
import _voicings from 'chord-voicings';
|
||||
import { complex, simple } from './ireal.mjs';
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# @strudel.cycles/transpiler
|
||||
# @strudel/transpiler
|
||||
|
||||
This package contains a JS code transpiler with the following features:
|
||||
|
||||
@ -9,14 +9,14 @@ This package contains a JS code transpiler with the following features:
|
||||
## Install
|
||||
|
||||
```sh
|
||||
npm i @strudel.cycles/transpiler
|
||||
npm i @strudel/transpiler
|
||||
```
|
||||
|
||||
## Use
|
||||
|
||||
```js
|
||||
import { transpiler } from '@strudel.cycles/core';
|
||||
import { evaluate } from '@strudel.cycles/core';
|
||||
import { transpiler } from '@strudel/core';
|
||||
import { evaluate } from '@strudel/core';
|
||||
|
||||
transpiler('note("c3 [e3,g3]")', { wrapAsync: false, addReturn: false, simpleLocs: true });
|
||||
/* mini('c3 [e3,g3]').withMiniLocation(7,17) */
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { evaluate as _evaluate } from '@strudel.cycles/core';
|
||||
import { evaluate as _evaluate } from '@strudel/core';
|
||||
import { transpiler } from './transpiler.mjs';
|
||||
export * from './transpiler.mjs';
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel.cycles/transpiler",
|
||||
"version": "0.9.0",
|
||||
"name": "@strudel/transpiler",
|
||||
"version": "0.11.0",
|
||||
"description": "Transpiler for strudel user code. Converts syntactically correct but semantically meaningless JS into evaluatable strudel code.",
|
||||
"main": "index.mjs",
|
||||
"publishConfig": {
|
||||
@ -30,8 +30,8 @@
|
||||
},
|
||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||
"dependencies": {
|
||||
"@strudel.cycles/core": "workspace:*",
|
||||
"@strudel.cycles/mini": "workspace:*",
|
||||
"@strudel/core": "workspace:*",
|
||||
"@strudel/mini": "workspace:*",
|
||||
"acorn": "^8.11.3",
|
||||
"escodegen": "^2.1.0",
|
||||
"estree-walker": "^3.0.1"
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import escodegen from 'escodegen';
|
||||
import { parse } from 'acorn';
|
||||
import { walk } from 'estree-walker';
|
||||
import { isNoteWithOctave } from '@strudel.cycles/core';
|
||||
import { getLeafLocations } from '@strudel.cycles/mini';
|
||||
import { isNoteWithOctave } from '@strudel/core';
|
||||
import { getLeafLocations } from '@strudel/mini';
|
||||
|
||||
export function transpiler(input, options = {}) {
|
||||
const { wrapAsync = false, addReturn = true, emitMiniLocations = true, emitWidgets = true } = options;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel/web",
|
||||
"version": "0.9.0",
|
||||
"version": "0.11.0",
|
||||
"description": "Easy to setup, opiniated bundle of Strudel for the browser.",
|
||||
"main": "web.mjs",
|
||||
"publishConfig": {
|
||||
@ -33,11 +33,11 @@
|
||||
},
|
||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||
"dependencies": {
|
||||
"@strudel.cycles/core": "workspace:*",
|
||||
"@strudel.cycles/mini": "workspace:*",
|
||||
"@strudel.cycles/tonal": "workspace:*",
|
||||
"@strudel.cycles/transpiler": "workspace:*",
|
||||
"@strudel.cycles/webaudio": "workspace:*"
|
||||
"@strudel/core": "workspace:*",
|
||||
"@strudel/mini": "workspace:*",
|
||||
"@strudel/tonal": "workspace:*",
|
||||
"@strudel/transpiler": "workspace:*",
|
||||
"@strudel/webaudio": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^5.0.10"
|
||||
|
||||
@ -1,25 +1,25 @@
|
||||
export * from '@strudel.cycles/core';
|
||||
export * from '@strudel.cycles/webaudio';
|
||||
//export * from '@strudel.cycles/soundfonts';
|
||||
export * from '@strudel.cycles/transpiler';
|
||||
export * from '@strudel.cycles/mini';
|
||||
export * from '@strudel.cycles/tonal';
|
||||
export * from '@strudel.cycles/webaudio';
|
||||
import { Pattern, evalScope, controls } from '@strudel.cycles/core';
|
||||
import { initAudioOnFirstClick, registerSynthSounds, webaudioScheduler } from '@strudel.cycles/webaudio';
|
||||
// import { registerSoundfonts } from '@strudel.cycles/soundfonts';
|
||||
import { evaluate as _evaluate } from '@strudel.cycles/transpiler';
|
||||
import { miniAllStrings } from '@strudel.cycles/mini';
|
||||
export * from '@strudel/core';
|
||||
export * from '@strudel/webaudio';
|
||||
//export * from '@strudel/soundfonts';
|
||||
export * from '@strudel/transpiler';
|
||||
export * from '@strudel/mini';
|
||||
export * from '@strudel/tonal';
|
||||
export * from '@strudel/webaudio';
|
||||
import { Pattern, evalScope, controls } from '@strudel/core';
|
||||
import { initAudioOnFirstClick, registerSynthSounds, webaudioScheduler } from '@strudel/webaudio';
|
||||
// import { registerSoundfonts } from '@strudel/soundfonts';
|
||||
import { evaluate as _evaluate } from '@strudel/transpiler';
|
||||
import { miniAllStrings } from '@strudel/mini';
|
||||
|
||||
// init logic
|
||||
export async function defaultPrebake() {
|
||||
const loadModules = evalScope(
|
||||
evalScope,
|
||||
controls,
|
||||
import('@strudel.cycles/core'),
|
||||
import('@strudel.cycles/mini'),
|
||||
import('@strudel.cycles/tonal'),
|
||||
import('@strudel.cycles/webaudio'),
|
||||
import('@strudel/core'),
|
||||
import('@strudel/mini'),
|
||||
import('@strudel/tonal'),
|
||||
import('@strudel/webaudio'),
|
||||
{ hush, evaluate },
|
||||
);
|
||||
await Promise.all([loadModules, registerSynthSounds() /* , registerSoundfonts() */]);
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# @strudel.cycles/webaudio
|
||||
# @strudel/webaudio
|
||||
|
||||
This package contains helpers to make music with strudel and the Web Audio API.
|
||||
It is a thin binding to [superdough](https://www.npmjs.com/package/superdough).
|
||||
@ -6,14 +6,14 @@ It is a thin binding to [superdough](https://www.npmjs.com/package/superdough).
|
||||
## Install
|
||||
|
||||
```sh
|
||||
npm i @strudel.cycles/webaudio --save
|
||||
npm i @strudel/webaudio --save
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
```js
|
||||
import { repl, controls } from "@strudel.cycles/core";
|
||||
import { initAudioOnFirstClick, getAudioContext, webaudioOutput } from "@strudel.cycles/webaudio";
|
||||
import { repl, controls } from "@strudel/core";
|
||||
import { initAudioOnFirstClick, getAudioContext, webaudioOutput } from "@strudel/webaudio";
|
||||
const { note } = controls;
|
||||
|
||||
initAudioOnFirstClick();
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel.cycles/webaudio",
|
||||
"version": "0.9.0",
|
||||
"name": "@strudel/webaudio",
|
||||
"version": "0.11.0",
|
||||
"description": "Web Audio helpers for Strudel",
|
||||
"main": "index.mjs",
|
||||
"type": "module",
|
||||
@ -34,7 +34,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||
"dependencies": {
|
||||
"@strudel.cycles/core": "workspace:*",
|
||||
"@strudel/core": "workspace:*",
|
||||
"superdough": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Pattern, getDrawContext, clamp } from '@strudel.cycles/core';
|
||||
import { Pattern, getDrawContext, clamp } from '@strudel/core';
|
||||
import { analyser, getAnalyzerData } from 'superdough';
|
||||
|
||||
export function drawTimeScope(
|
||||
|
||||
@ -4,7 +4,7 @@ Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/st
|
||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import * as strudel from '@strudel.cycles/core';
|
||||
import * as strudel from '@strudel/core';
|
||||
import { superdough, getAudioContext, setLogger, doughTrigger } from 'superdough';
|
||||
const { Pattern, logger } = strudel;
|
||||
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
# @strudel.cycles/xen
|
||||
# @strudel/xen
|
||||
|
||||
This package adds xenharmonic / microtonal functions to strudel Patterns. Further documentation + examples will follow.
|
||||
|
||||
## Install
|
||||
|
||||
```sh
|
||||
npm i @strudel.cycles/xen --save
|
||||
npm i @strudel/xen --save
|
||||
```
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel.cycles/xen",
|
||||
"version": "0.9.0",
|
||||
"name": "@strudel/xen",
|
||||
"version": "0.11.0",
|
||||
"description": "Xenharmonic API for strudel",
|
||||
"main": "index.mjs",
|
||||
"publishConfig": {
|
||||
@ -30,7 +30,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||
"dependencies": {
|
||||
"@strudel.cycles/core": "workspace:*"
|
||||
"@strudel/core": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^5.0.10",
|
||||
|
||||
@ -5,7 +5,7 @@ This program is free software: you can redistribute it and/or modify it under th
|
||||
*/
|
||||
|
||||
import Tune from './tunejs.js';
|
||||
import { register } from '@strudel.cycles/core';
|
||||
import { register } from '@strudel/core';
|
||||
|
||||
export const tune = register('tune', (scale, pat) => {
|
||||
const tune = new Tune();
|
||||
|
||||
@ -4,7 +4,7 @@ Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/st
|
||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { register, _mod, parseNumeral } from '@strudel.cycles/core';
|
||||
import { register, _mod, parseNumeral } from '@strudel/core';
|
||||
|
||||
export function edo(name) {
|
||||
if (!/^[1-9]+[0-9]*edo$/.test(name)) {
|
||||
|
||||
231
pnpm-lock.yaml
generated
231
pnpm-lock.yaml
generated
@ -8,22 +8,22 @@ importers:
|
||||
|
||||
.:
|
||||
dependencies:
|
||||
'@strudel.cycles/core':
|
||||
'@strudel/core':
|
||||
specifier: workspace:*
|
||||
version: link:packages/core
|
||||
'@strudel.cycles/mini':
|
||||
'@strudel/mini':
|
||||
specifier: workspace:*
|
||||
version: link:packages/mini
|
||||
'@strudel.cycles/tonal':
|
||||
'@strudel/tonal':
|
||||
specifier: workspace:*
|
||||
version: link:packages/tonal
|
||||
'@strudel.cycles/transpiler':
|
||||
'@strudel/transpiler':
|
||||
specifier: workspace:*
|
||||
version: link:packages/transpiler
|
||||
'@strudel.cycles/webaudio':
|
||||
'@strudel/webaudio':
|
||||
specifier: workspace:*
|
||||
version: link:packages/webaudio
|
||||
'@strudel.cycles/xen':
|
||||
'@strudel/xen':
|
||||
specifier: workspace:*
|
||||
version: link:packages/xen
|
||||
devDependencies:
|
||||
@ -72,27 +72,27 @@ importers:
|
||||
|
||||
examples/codemirror-repl:
|
||||
dependencies:
|
||||
'@strudel.cycles/core':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/core
|
||||
'@strudel.cycles/mini':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/mini
|
||||
'@strudel.cycles/soundfonts':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/soundfonts
|
||||
'@strudel.cycles/tonal':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/tonal
|
||||
'@strudel.cycles/transpiler':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/transpiler
|
||||
'@strudel.cycles/webaudio':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/webaudio
|
||||
'@strudel/codemirror':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/codemirror
|
||||
'@strudel/core':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/core
|
||||
'@strudel/mini':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/mini
|
||||
'@strudel/soundfonts':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/soundfonts
|
||||
'@strudel/tonal':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/tonal
|
||||
'@strudel/transpiler':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/transpiler
|
||||
'@strudel/webaudio':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/webaudio
|
||||
devDependencies:
|
||||
vite:
|
||||
specifier: ^5.0.10
|
||||
@ -110,19 +110,19 @@ importers:
|
||||
|
||||
examples/minimal-repl:
|
||||
dependencies:
|
||||
'@strudel.cycles/core':
|
||||
'@strudel/core':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/core
|
||||
'@strudel.cycles/mini':
|
||||
'@strudel/mini':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/mini
|
||||
'@strudel.cycles/tonal':
|
||||
'@strudel/tonal':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/tonal
|
||||
'@strudel.cycles/transpiler':
|
||||
'@strudel/transpiler':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/transpiler
|
||||
'@strudel.cycles/webaudio':
|
||||
'@strudel/webaudio':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/webaudio
|
||||
devDependencies:
|
||||
@ -178,7 +178,7 @@ importers:
|
||||
'@replit/codemirror-vscode-keymap':
|
||||
specifier: ^6.0.2
|
||||
version: 6.0.2(@codemirror/autocomplete@6.11.1)(@codemirror/commands@6.3.3)(@codemirror/language@6.10.0)(@codemirror/lint@6.4.2)(@codemirror/search@6.5.5)(@codemirror/state@6.4.0)(@codemirror/view@6.23.0)
|
||||
'@strudel.cycles/core':
|
||||
'@strudel/core':
|
||||
specifier: workspace:*
|
||||
version: link:../core
|
||||
'@uiw/codemirror-themes':
|
||||
@ -213,10 +213,10 @@ importers:
|
||||
'@csound/browser':
|
||||
specifier: 6.18.7
|
||||
version: 6.18.7(eslint@8.56.0)
|
||||
'@strudel.cycles/core':
|
||||
'@strudel/core':
|
||||
specifier: workspace:*
|
||||
version: link:../core
|
||||
'@strudel.cycles/webaudio':
|
||||
'@strudel/webaudio':
|
||||
specifier: workspace:*
|
||||
version: link:../webaudio
|
||||
devDependencies:
|
||||
@ -226,7 +226,7 @@ importers:
|
||||
|
||||
packages/desktopbridge:
|
||||
dependencies:
|
||||
'@strudel.cycles/core':
|
||||
'@strudel/core':
|
||||
specifier: workspace:*
|
||||
version: link:../core
|
||||
'@tauri-apps/api':
|
||||
@ -237,7 +237,7 @@ importers:
|
||||
|
||||
packages/hydra:
|
||||
dependencies:
|
||||
'@strudel.cycles/core':
|
||||
'@strudel/core':
|
||||
specifier: workspace:*
|
||||
version: link:../core
|
||||
hydra-synth:
|
||||
@ -253,10 +253,10 @@ importers:
|
||||
|
||||
packages/midi:
|
||||
dependencies:
|
||||
'@strudel.cycles/core':
|
||||
'@strudel/core':
|
||||
specifier: workspace:*
|
||||
version: link:../core
|
||||
'@strudel.cycles/webaudio':
|
||||
'@strudel/webaudio':
|
||||
specifier: workspace:*
|
||||
version: link:../webaudio
|
||||
webmidi:
|
||||
@ -269,7 +269,7 @@ importers:
|
||||
|
||||
packages/mini:
|
||||
dependencies:
|
||||
'@strudel.cycles/core':
|
||||
'@strudel/core':
|
||||
specifier: workspace:*
|
||||
version: link:../core
|
||||
devDependencies:
|
||||
@ -285,7 +285,7 @@ importers:
|
||||
|
||||
packages/osc:
|
||||
dependencies:
|
||||
'@strudel.cycles/core':
|
||||
'@strudel/core':
|
||||
specifier: workspace:*
|
||||
version: link:../core
|
||||
osc-js:
|
||||
@ -301,33 +301,33 @@ importers:
|
||||
|
||||
packages/repl:
|
||||
dependencies:
|
||||
'@strudel.cycles/core':
|
||||
specifier: workspace:*
|
||||
version: link:../core
|
||||
'@strudel.cycles/midi':
|
||||
specifier: workspace:*
|
||||
version: link:../midi
|
||||
'@strudel.cycles/mini':
|
||||
specifier: workspace:*
|
||||
version: link:../mini
|
||||
'@strudel.cycles/soundfonts':
|
||||
specifier: workspace:*
|
||||
version: link:../soundfonts
|
||||
'@strudel.cycles/tonal':
|
||||
specifier: workspace:*
|
||||
version: link:../tonal
|
||||
'@strudel.cycles/transpiler':
|
||||
specifier: workspace:*
|
||||
version: link:../transpiler
|
||||
'@strudel.cycles/webaudio':
|
||||
specifier: workspace:*
|
||||
version: link:../webaudio
|
||||
'@strudel/codemirror':
|
||||
specifier: workspace:*
|
||||
version: link:../codemirror
|
||||
'@strudel/core':
|
||||
specifier: workspace:*
|
||||
version: link:../core
|
||||
'@strudel/hydra':
|
||||
specifier: workspace:*
|
||||
version: link:../hydra
|
||||
'@strudel/midi':
|
||||
specifier: workspace:*
|
||||
version: link:../midi
|
||||
'@strudel/mini':
|
||||
specifier: workspace:*
|
||||
version: link:../mini
|
||||
'@strudel/soundfonts':
|
||||
specifier: workspace:*
|
||||
version: link:../soundfonts
|
||||
'@strudel/tonal':
|
||||
specifier: workspace:*
|
||||
version: link:../tonal
|
||||
'@strudel/transpiler':
|
||||
specifier: workspace:*
|
||||
version: link:../transpiler
|
||||
'@strudel/webaudio':
|
||||
specifier: workspace:*
|
||||
version: link:../webaudio
|
||||
devDependencies:
|
||||
'@rollup/plugin-replace':
|
||||
specifier: ^5.0.5
|
||||
@ -341,7 +341,7 @@ importers:
|
||||
|
||||
packages/serial:
|
||||
dependencies:
|
||||
'@strudel.cycles/core':
|
||||
'@strudel/core':
|
||||
specifier: workspace:*
|
||||
version: link:../core
|
||||
devDependencies:
|
||||
@ -351,10 +351,10 @@ importers:
|
||||
|
||||
packages/soundfonts:
|
||||
dependencies:
|
||||
'@strudel.cycles/core':
|
||||
'@strudel/core':
|
||||
specifier: workspace:*
|
||||
version: link:../core
|
||||
'@strudel.cycles/webaudio':
|
||||
'@strudel/webaudio':
|
||||
specifier: workspace:*
|
||||
version: link:../webaudio
|
||||
sfumato:
|
||||
@ -383,7 +383,7 @@ importers:
|
||||
|
||||
packages/tonal:
|
||||
dependencies:
|
||||
'@strudel.cycles/core':
|
||||
'@strudel/core':
|
||||
specifier: workspace:*
|
||||
version: link:../core
|
||||
'@tonaljs/tonal':
|
||||
@ -405,10 +405,10 @@ importers:
|
||||
|
||||
packages/transpiler:
|
||||
dependencies:
|
||||
'@strudel.cycles/core':
|
||||
'@strudel/core':
|
||||
specifier: workspace:*
|
||||
version: link:../core
|
||||
'@strudel.cycles/mini':
|
||||
'@strudel/mini':
|
||||
specifier: workspace:*
|
||||
version: link:../mini
|
||||
acorn:
|
||||
@ -430,19 +430,19 @@ importers:
|
||||
|
||||
packages/web:
|
||||
dependencies:
|
||||
'@strudel.cycles/core':
|
||||
'@strudel/core':
|
||||
specifier: workspace:*
|
||||
version: link:../core
|
||||
'@strudel.cycles/mini':
|
||||
'@strudel/mini':
|
||||
specifier: workspace:*
|
||||
version: link:../mini
|
||||
'@strudel.cycles/tonal':
|
||||
'@strudel/tonal':
|
||||
specifier: workspace:*
|
||||
version: link:../tonal
|
||||
'@strudel.cycles/transpiler':
|
||||
'@strudel/transpiler':
|
||||
specifier: workspace:*
|
||||
version: link:../transpiler
|
||||
'@strudel.cycles/webaudio':
|
||||
'@strudel/webaudio':
|
||||
specifier: workspace:*
|
||||
version: link:../webaudio
|
||||
devDependencies:
|
||||
@ -452,7 +452,7 @@ importers:
|
||||
|
||||
packages/webaudio:
|
||||
dependencies:
|
||||
'@strudel.cycles/core':
|
||||
'@strudel/core':
|
||||
specifier: workspace:*
|
||||
version: link:../core
|
||||
superdough:
|
||||
@ -465,7 +465,7 @@ importers:
|
||||
|
||||
packages/xen:
|
||||
dependencies:
|
||||
'@strudel.cycles/core':
|
||||
'@strudel/core':
|
||||
specifier: workspace:*
|
||||
version: link:../core
|
||||
devDependencies:
|
||||
@ -490,6 +490,9 @@ importers:
|
||||
'@astrojs/react':
|
||||
specifier: ^3.0.9
|
||||
version: 3.0.9(@types/react-dom@18.2.18)(@types/react@18.2.46)(react-dom@18.2.0)(react@18.2.0)(vite@5.0.11)
|
||||
'@astrojs/rss':
|
||||
specifier: ^4.0.2
|
||||
version: 4.0.2
|
||||
'@astrojs/tailwind':
|
||||
specifier: ^5.1.0
|
||||
version: 5.1.0(astro@4.0.8)(tailwindcss@3.4.0)
|
||||
@ -511,51 +514,51 @@ importers:
|
||||
'@nanostores/react':
|
||||
specifier: ^0.7.1
|
||||
version: 0.7.1(nanostores@0.9.5)(react@18.2.0)
|
||||
'@strudel.cycles/core':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/core
|
||||
'@strudel.cycles/csound':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/csound
|
||||
'@strudel.cycles/midi':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/midi
|
||||
'@strudel.cycles/mini':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/mini
|
||||
'@strudel.cycles/osc':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/osc
|
||||
'@strudel.cycles/serial':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/serial
|
||||
'@strudel.cycles/soundfonts':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/soundfonts
|
||||
'@strudel.cycles/tonal':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/tonal
|
||||
'@strudel.cycles/transpiler':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/transpiler
|
||||
'@strudel.cycles/webaudio':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/webaudio
|
||||
'@strudel.cycles/xen':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/xen
|
||||
'@strudel/codemirror':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/codemirror
|
||||
'@strudel/core':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/core
|
||||
'@strudel/csound':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/csound
|
||||
'@strudel/desktopbridge':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/desktopbridge
|
||||
'@strudel/hydra':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/hydra
|
||||
'@strudel/midi':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/midi
|
||||
'@strudel/mini':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/mini
|
||||
'@strudel/osc':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/osc
|
||||
'@strudel/repl':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/repl
|
||||
'@strudel/serial':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/serial
|
||||
'@strudel/soundfonts':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/soundfonts
|
||||
'@strudel/tonal':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/tonal
|
||||
'@strudel/transpiler':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/transpiler
|
||||
'@strudel/webaudio':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/webaudio
|
||||
'@strudel/xen':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/xen
|
||||
'@supabase/supabase-js':
|
||||
specifier: ^2.39.1
|
||||
version: 2.39.1
|
||||
@ -890,6 +893,13 @@ packages:
|
||||
- vite
|
||||
dev: false
|
||||
|
||||
/@astrojs/rss@4.0.2:
|
||||
resolution: {integrity: sha512-Hb9GKAyvsn5EUjZtB6SniesBScMQe7SQinEHLY5EFa74QEvgcWaXTmA0Mb0P3vqDSN3d/NTYbGivprrSAawfnA==}
|
||||
dependencies:
|
||||
fast-xml-parser: 4.3.3
|
||||
kleur: 4.1.5
|
||||
dev: false
|
||||
|
||||
/@astrojs/tailwind@5.1.0(astro@4.0.8)(tailwindcss@3.4.0):
|
||||
resolution: {integrity: sha512-BJoCDKuWhU9FT2qYg+fr6Nfb3qP4ShtyjXGHKA/4mHN94z7BGcmauQK23iy+YH5qWvTnhqkd6mQPQ1yTZTe9Ig==}
|
||||
peerDependencies:
|
||||
@ -7182,6 +7192,13 @@ packages:
|
||||
/fast-levenshtein@2.0.6:
|
||||
resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
|
||||
|
||||
/fast-xml-parser@4.3.3:
|
||||
resolution: {integrity: sha512-coV/D1MhrShMvU6D0I+VAK3umz6hUaxxhL0yp/9RjfiYUfAv14rDhGQL+PLForhMdr0wq3PiV07WtkkNjJjNHg==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
strnum: 1.0.5
|
||||
dev: false
|
||||
|
||||
/fastq@1.15.0:
|
||||
resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==}
|
||||
dependencies:
|
||||
@ -12637,6 +12654,10 @@ packages:
|
||||
acorn: 8.11.3
|
||||
dev: true
|
||||
|
||||
/strnum@1.0.5:
|
||||
resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==}
|
||||
dev: false
|
||||
|
||||
/strong-log-transformer@2.1.0:
|
||||
resolution: {integrity: sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# @strudel.cycles/tauri
|
||||
# @strudel/tauri
|
||||
|
||||
Rust source files for building native desktop apps using Tauri
|
||||
|
||||
|
||||
@ -2408,6 +2408,40 @@ exports[`runs examples > example "hush" example index 0 1`] = `
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "inhabit" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/8 | s:bd ]",
|
||||
"[ 3/8 → 1/2 | s:bd ]",
|
||||
"[ 3/4 → 7/8 | s:bd ]",
|
||||
"[ 1/1 → 3/2 | s:cp ]",
|
||||
"[ 3/2 → 2/1 | s:sd ]",
|
||||
"[ 2/1 → 17/8 | s:bd ]",
|
||||
"[ 2/1 → 5/2 | s:cp ]",
|
||||
"[ 19/8 → 5/2 | s:bd ]",
|
||||
"[ 5/2 → 3/1 | s:sd ]",
|
||||
"[ 11/4 → 23/8 | s:bd ]",
|
||||
"[ 3/1 → 25/8 | s:bd ]",
|
||||
"[ 27/8 → 7/2 | s:bd ]",
|
||||
"[ 15/4 → 31/8 | s:bd ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "inhabit" example index 1 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/4 | s:bd ]",
|
||||
"[ 3/4 → 1/1 | s:bd ]",
|
||||
"[ 3/2 → 7/4 | s:bd ]",
|
||||
"[ 2/1 → 33/16 | s:bd ]",
|
||||
"[ 35/16 → 9/4 | s:bd ]",
|
||||
"[ 19/8 → 39/16 | s:bd ]",
|
||||
"[ 5/2 → 11/4 | s:sd ]",
|
||||
"[ 11/4 → 3/1 | s:sd ]",
|
||||
"[ 3/1 → 25/8 | s:bd ]",
|
||||
"[ 27/8 → 7/2 | s:bd ]",
|
||||
"[ 15/4 → 31/8 | s:bd ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "inside" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/8 | note:D3 ]",
|
||||
@ -3332,6 +3366,55 @@ exports[`runs examples > example "pan" example index 0 1`] = `
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "panchor" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/1 | note:c penv:12 panchor:0 ]",
|
||||
"[ 1/1 → 2/1 | note:c penv:12 panchor:0.5 ]",
|
||||
"[ 2/1 → 3/1 | note:c penv:12 panchor:1 ]",
|
||||
"[ 3/1 → 4/1 | note:c penv:12 panchor:0.5 ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "pattack" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/1 | note:c pattack:0 ]",
|
||||
"[ 1/1 → 2/1 | note:eb pattack:0.1 ]",
|
||||
"[ 2/1 → 3/1 | note:g pattack:0.25 ]",
|
||||
"[ 3/1 → 4/1 | note:bb pattack:0.5 ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "pcurve" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/2 | note:g1 s:sine pdecay:0.5 penv:32 pcurve:0 ]",
|
||||
"[ 1/2 → 1/1 | note:g1 s:sine pdecay:0.5 penv:32 pcurve:0 ]",
|
||||
"[ 1/1 → 3/2 | note:g1 s:sine pdecay:0.5 penv:32 pcurve:1 ]",
|
||||
"[ 3/2 → 2/1 | note:g1 s:sine pdecay:0.5 penv:32 pcurve:1 ]",
|
||||
"[ 2/1 → 5/2 | note:g1 s:sine pdecay:0.5 penv:32 pcurve:0 ]",
|
||||
"[ 5/2 → 3/1 | note:g1 s:sine pdecay:0.5 penv:32 pcurve:0 ]",
|
||||
"[ 3/1 → 7/2 | note:g1 s:sine pdecay:0.5 penv:32 pcurve:1 ]",
|
||||
"[ 7/2 → 4/1 | note:g1 s:sine pdecay:0.5 penv:32 pcurve:1 ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "pdecay" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/1 | note:c pdecay:0 ]",
|
||||
"[ 1/1 → 2/1 | note:eb pdecay:0.1 ]",
|
||||
"[ 2/1 → 3/1 | note:g pdecay:0.25 ]",
|
||||
"[ 3/1 → 4/1 | note:bb pdecay:0.5 ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "penv" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/1 | note:c penv:12 ]",
|
||||
"[ 1/1 → 2/1 | note:c penv:7 ]",
|
||||
"[ 2/1 → 3/1 | note:c penv:1 ]",
|
||||
"[ 3/1 → 4/1 | note:c penv:0.5 ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "perlin" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/4 | s:hh cutoff:512.5097280354112 ]",
|
||||
@ -3552,10 +3635,61 @@ exports[`runs examples > example "pick" example index 0 1`] = `
|
||||
"[ 9/4 → 5/2 | note:g ]",
|
||||
"[ 5/2 → 11/4 | note:f ]",
|
||||
"[ 11/4 → 3/1 | note:g ]",
|
||||
"[ 3/1 → 13/4 | note:g ]",
|
||||
"[ 13/4 → 7/2 | note:a ]",
|
||||
"[ 7/2 → 15/4 | note:c ]",
|
||||
"[ 15/4 → 4/1 | note:d ]",
|
||||
"[ 3/1 → 13/4 | note:f ]",
|
||||
"[ 13/4 → 7/2 | note:g ]",
|
||||
"[ 7/2 → 15/4 | note:f ]",
|
||||
"[ 15/4 → 4/1 | note:g ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "pick" example index 1 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/2 | s:bd ]",
|
||||
"[ 1/2 → 1/1 | s:sd ]",
|
||||
"[ 1/1 → 3/2 | s:cp ]",
|
||||
"[ 3/2 → 2/1 | s:cp ]",
|
||||
"[ 2/1 → 5/2 | s:hh ]",
|
||||
"[ 2/1 → 5/2 | s:bd ]",
|
||||
"[ 5/2 → 3/1 | s:hh ]",
|
||||
"[ 5/2 → 3/1 | s:sd ]",
|
||||
"[ 3/1 → 7/2 | s:bd ]",
|
||||
"[ 7/2 → 4/1 | s:sd ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "pick" example index 2 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/8 | s:bd ]",
|
||||
"[ 3/8 → 1/2 | s:bd ]",
|
||||
"[ 3/4 → 7/8 | s:bd ]",
|
||||
"[ 1/1 → 9/8 | s:bd ]",
|
||||
"[ 11/8 → 3/2 | s:bd ]",
|
||||
"[ 7/4 → 15/8 | s:bd ]",
|
||||
"[ 2/1 → 17/8 | s:bd ]",
|
||||
"[ 2/1 → 5/2 | s:sd ]",
|
||||
"[ 19/8 → 5/2 | s:bd ]",
|
||||
"[ 5/2 → 3/1 | s:sd ]",
|
||||
"[ 11/4 → 23/8 | s:bd ]",
|
||||
"[ 3/1 → 7/2 | s:sd ]",
|
||||
"[ 7/2 → 4/1 | s:sd ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "pick" example index 3 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/8 | s:bd ]",
|
||||
"[ 3/8 → 1/2 | s:bd ]",
|
||||
"[ 3/4 → 7/8 | s:bd ]",
|
||||
"[ 1/1 → 9/8 | s:bd ]",
|
||||
"[ 11/8 → 3/2 | s:bd ]",
|
||||
"[ 7/4 → 15/8 | s:bd ]",
|
||||
"[ 2/1 → 17/8 | s:bd ]",
|
||||
"[ 2/1 → 5/2 | s:sd ]",
|
||||
"[ 19/8 → 5/2 | s:bd ]",
|
||||
"[ 5/2 → 3/1 | s:sd ]",
|
||||
"[ 11/4 → 23/8 | s:bd ]",
|
||||
"[ 3/1 → 7/2 | s:sd ]",
|
||||
"[ 7/2 → 4/1 | s:sd ]",
|
||||
]
|
||||
`;
|
||||
|
||||
@ -3660,6 +3794,15 @@ exports[`runs examples > example "postgain" example index 0 1`] = `
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "prelease" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/2 | note:c release:0.5 prelease:0 ]",
|
||||
"[ 1/1 → 3/2 | note:eb release:0.5 prelease:0.1 ]",
|
||||
"[ 2/1 → 5/2 | note:g release:0.5 prelease:0.25 ]",
|
||||
"[ 3/1 → 7/2 | note:bb release:0.5 prelease:0.5 ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "press" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/2 | s:hh ]",
|
||||
|
||||
@ -3,25 +3,25 @@
|
||||
// it might require mocking more stuff when tunes added that use other functions
|
||||
|
||||
// import * as tunes from './tunes.mjs';
|
||||
import { evaluate } from '@strudel.cycles/transpiler';
|
||||
import { evalScope } from '@strudel.cycles/core';
|
||||
import * as strudel from '@strudel.cycles/core';
|
||||
import * as webaudio from '@strudel.cycles/webaudio';
|
||||
import controls from '@strudel.cycles/core/controls.mjs';
|
||||
// import gist from '@strudel.cycles/core/gist.js';
|
||||
import { mini, m } from '@strudel.cycles/mini/mini.mjs';
|
||||
// import * as voicingHelpers from '@strudel.cycles/tonal/voicings.mjs';
|
||||
// import euclid from '@strudel.cycles/core/euclid.mjs';
|
||||
// import '@strudel.cycles/midi/midi.mjs';
|
||||
import * as tonalHelpers from '@strudel.cycles/tonal';
|
||||
import '@strudel.cycles/xen/xen.mjs';
|
||||
// import '@strudel.cycles/xen/tune.mjs';
|
||||
// import '@strudel.cycles/core/euclid.mjs';
|
||||
// import '@strudel.cycles/core/speak.mjs'; // window is not defined
|
||||
// import '@strudel.cycles/osc/osc.mjs';
|
||||
// import '@strudel.cycles/webaudio/webaudio.mjs';
|
||||
// import '@strudel.cycles/serial/serial.mjs';
|
||||
// import controls from '@strudel.cycles/core/controls.mjs';
|
||||
import { evaluate } from '@strudel/transpiler';
|
||||
import { evalScope } from '@strudel/core';
|
||||
import * as strudel from '@strudel/core';
|
||||
import * as webaudio from '@strudel/webaudio';
|
||||
import controls from '@strudel/core/controls.mjs';
|
||||
// import gist from '@strudel/core/gist.js';
|
||||
import { mini, m } from '@strudel/mini/mini.mjs';
|
||||
// import * as voicingHelpers from '@strudel/tonal/voicings.mjs';
|
||||
// import euclid from '@strudel/core/euclid.mjs';
|
||||
// import '@strudel/midi/midi.mjs';
|
||||
import * as tonalHelpers from '@strudel/tonal';
|
||||
import '@strudel/xen/xen.mjs';
|
||||
// import '@strudel/xen/tune.mjs';
|
||||
// import '@strudel/core/euclid.mjs';
|
||||
// import '@strudel/core/speak.mjs'; // window is not defined
|
||||
// import '@strudel/osc/osc.mjs';
|
||||
// import '@strudel/webaudio/webaudio.mjs';
|
||||
// import '@strudel/serial/serial.mjs';
|
||||
// import controls from '@strudel/core/controls.mjs';
|
||||
import '../website/src/repl/piano';
|
||||
|
||||
class MockedNode {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "@strudel.cycles/website",
|
||||
"name": "@strudel/website",
|
||||
"type": "module",
|
||||
"version": "0.6.0",
|
||||
"private": true,
|
||||
@ -16,6 +16,7 @@
|
||||
"@astro-community/astro-embed-youtube": "^0.4.3",
|
||||
"@astrojs/mdx": "^2.0.3",
|
||||
"@astrojs/react": "^3.0.9",
|
||||
"@astrojs/rss": "^4.0.2",
|
||||
"@astrojs/tailwind": "^5.1.0",
|
||||
"@docsearch/css": "^3.5.2",
|
||||
"@docsearch/react": "^3.5.2",
|
||||
@ -23,21 +24,21 @@
|
||||
"@heroicons/react": "^2.1.1",
|
||||
"@nanostores/persistent": "^0.9.1",
|
||||
"@nanostores/react": "^0.7.1",
|
||||
"@strudel.cycles/core": "workspace:*",
|
||||
"@strudel.cycles/csound": "workspace:*",
|
||||
"@strudel.cycles/midi": "workspace:*",
|
||||
"@strudel.cycles/mini": "workspace:*",
|
||||
"@strudel.cycles/osc": "workspace:*",
|
||||
"@strudel.cycles/serial": "workspace:*",
|
||||
"@strudel.cycles/soundfonts": "workspace:*",
|
||||
"@strudel.cycles/tonal": "workspace:*",
|
||||
"@strudel.cycles/transpiler": "workspace:*",
|
||||
"@strudel.cycles/webaudio": "workspace:*",
|
||||
"@strudel.cycles/xen": "workspace:*",
|
||||
"@strudel/codemirror": "workspace:*",
|
||||
"@strudel/core": "workspace:*",
|
||||
"@strudel/csound": "workspace:*",
|
||||
"@strudel/desktopbridge": "workspace:*",
|
||||
"@strudel/hydra": "workspace:*",
|
||||
"@strudel/midi": "workspace:*",
|
||||
"@strudel/mini": "workspace:*",
|
||||
"@strudel/osc": "workspace:*",
|
||||
"@strudel/repl": "workspace:*",
|
||||
"@strudel/serial": "workspace:*",
|
||||
"@strudel/soundfonts": "workspace:*",
|
||||
"@strudel/tonal": "workspace:*",
|
||||
"@strudel/transpiler": "workspace:*",
|
||||
"@strudel/webaudio": "workspace:*",
|
||||
"@strudel/xen": "workspace:*",
|
||||
"@supabase/supabase-js": "^2.39.1",
|
||||
"@tailwindcss/forms": "^0.5.7",
|
||||
"@tailwindcss/typography": "^0.5.10",
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
---
|
||||
import type { CollectionEntry } from 'astro:content';
|
||||
|
||||
type Props = CollectionEntry<'blog'>['data'];
|
||||
type Props = { post: CollectionEntry<'blog'> };
|
||||
|
||||
const { post } = Astro.props;
|
||||
const { Content } = await post.render();
|
||||
@ -9,7 +9,7 @@ import { format } from 'date-fns';
|
||||
---
|
||||
|
||||
<article
|
||||
class="prose max-w-none prose-headings:font-sans prose-headings:font-black prose-headings:text-slate-900 dark:prose-headings:text-gray-200 dark:text-gray-400 dark:prose-strong:text-gray-400 dark:prose-code:text-slate-400 dark:prose-a:text-gray-300 prose-a:text-slate-900 prose-blockquote:text-slate-800 dark:prose-blockquote:text-slate-400"
|
||||
class="prose max-w-none prose-headings:font-sans prose-headings:font-black prose-headings:text-slate-900 dark:prose-headings:text-gray-200 dark:text-gray-400 dark:prose-strong:text-gray-400 dark:prose-code:text-slate-400 dark:prose-a:text-gray-300 prose-a:text-slate-900 prose-blockquote:text-slate-800 dark:prose-blockquote:text-slate-400 border-b-4 border-lineHighlight pt-4"
|
||||
>
|
||||
<div class="pb-2">
|
||||
<div class="md:flex justify-between">
|
||||
|
||||
@ -10,7 +10,7 @@ const baseNoTrailing = BASE_URL.endsWith('/') ? BASE_URL.slice(0, -1) : BASE_URL
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
|
||||
<link rel="alternate" type="application/rss+xml" title={`RSS Feed for strudel.cc`} href="/rss.xml" />
|
||||
<link rel="icon" type="image/svg+xml" href={`${baseNoTrailing}/favicon.ico`} />
|
||||
|
||||
<meta
|
||||
@ -24,7 +24,7 @@ const baseNoTrailing = BASE_URL.endsWith('/') ? BASE_URL.slice(0, -1) : BASE_URL
|
||||
<base href={BASE_URL} />
|
||||
|
||||
<!-- Scrollable a11y code helper -->
|
||||
<script src{`${baseNoTrailing}/make-scrollable-code-focusable.js`} is:inline></script>
|
||||
<script {`${baseNoTrailing}/make-scrollable-code-focusable.js`} is:inline></script>
|
||||
|
||||
<script src="/src/pwa.ts"></script>
|
||||
<!-- this does not work for some reason: -->
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
---
|
||||
import { SITE, OPEN_GRAPH, Frontmatter } from '../config';
|
||||
import { SITE, OPEN_GRAPH, type Frontmatter } from '../config';
|
||||
|
||||
export interface Props {
|
||||
frontmatter: Frontmatter;
|
||||
@ -25,11 +25,3 @@ const imageAlt = frontmatter.image?.alt ?? OPEN_GRAPH.image.alt;
|
||||
<meta property="og:image:alt" content={imageAlt} />
|
||||
<meta name="description" property="og:description" content={frontmatter.description ?? SITE.description} />
|
||||
<meta property="og:site_name" content={SITE.title} />
|
||||
|
||||
<!-- Twitter Tags -->
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:site" content={OPEN_GRAPH.twitter} />
|
||||
<meta name="twitter:title" content={formattedContentTitle} />
|
||||
<meta name="twitter:description" content={frontmatter.description ?? SITE.description} />
|
||||
<meta name="twitter:image" content={canonicalImageSrc} />
|
||||
<meta name="twitter:image:alt" content={imageAlt} />
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import useEvent from '@src/useEvent.mjs';
|
||||
import useFrame from '@src/useFrame.mjs';
|
||||
import { getAudioContext } from '@strudel.cycles/webaudio';
|
||||
import { midi2note } from '@strudel.cycles/core';
|
||||
import { getAudioContext } from '@strudel/webaudio';
|
||||
import { midi2note } from '@strudel/core';
|
||||
import { useState, useRef, useEffect } from 'react';
|
||||
import Claviature from '@components/Claviature';
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { colorMap } from '@strudel.cycles/core/color.mjs';
|
||||
import { colorMap } from '@strudel/core/color.mjs';
|
||||
import React from 'react';
|
||||
|
||||
const Colors = () => {
|
||||
|
||||
@ -1,4 +1,19 @@
|
||||
export function Icon({ type }) {
|
||||
if (type === 'skip') {
|
||||
// !Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.
|
||||
return (
|
||||
<svg
|
||||
fillRule="evenodd"
|
||||
fill="currentColor"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
height="16"
|
||||
width="10"
|
||||
viewBox="0 0 320 512"
|
||||
>
|
||||
<path d="M52.5 440.6c-9.5 7.9-22.8 9.7-34.1 4.4S0 428.4 0 416V96C0 83.6 7.2 72.3 18.4 67s24.5-3.6 34.1 4.4l192 160L256 241V96c0-17.7 14.3-32 32-32s32 14.3 32 32V416c0 17.7-14.3 32-32 32s-32-14.3-32-32V271l-11.5 9.6-192 160z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
|
||||
{
|
||||
@ -31,6 +46,13 @@ export function Icon({ type }) {
|
||||
clipRule="evenodd"
|
||||
/>
|
||||
),
|
||||
skip: (
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M52.5 440.6c-9.5 7.9-22.8 9.7-34.1 4.4S0 428.4 0 416V96C0 83.6 7.2 72.3 18.4 67s24.5-3.6 34.1 4.4l192 160L256 241V96c0-17.7 14.3-32 32-32s32 14.3 32 32V416c0 17.7-14.3 32-32 32s-32-14.3-32-32V271l-11.5 9.6-192 160z"
|
||||
clipRule="evenodd"
|
||||
/>
|
||||
),
|
||||
}[type]
|
||||
}
|
||||
</svg>
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { useState, useRef, useCallback, useMemo, useEffect } from 'react';
|
||||
import { Icon } from './Icon';
|
||||
import { silence, getPunchcardPainter, noteToMidi } from '@strudel.cycles/core';
|
||||
import { transpiler } from '@strudel.cycles/transpiler';
|
||||
import { getAudioContext, webaudioOutput } from '@strudel.cycles/webaudio';
|
||||
import { silence, getPunchcardPainter, noteToMidi, _mod } from '@strudel/core';
|
||||
import { transpiler } from '@strudel/transpiler';
|
||||
import { getAudioContext, webaudioOutput, initAudioOnFirstClick } from '@strudel/webaudio';
|
||||
import { StrudelMirror } from '@strudel/codemirror';
|
||||
// import { prebake } from '@strudel/repl';
|
||||
import { prebake } from '../repl/prebake.mjs';
|
||||
@ -10,14 +10,16 @@ import { loadModules } from '../repl/util.mjs';
|
||||
import Claviature from '@components/Claviature';
|
||||
import useClient from '@src/useClient.mjs';
|
||||
|
||||
let prebaked, modulesLoading;
|
||||
let prebaked, modulesLoading, audioLoading;
|
||||
if (typeof window !== 'undefined') {
|
||||
prebaked = prebake();
|
||||
modulesLoading = loadModules();
|
||||
audioLoading = initAudioOnFirstClick();
|
||||
}
|
||||
|
||||
export function MiniRepl({
|
||||
tune: code,
|
||||
tune,
|
||||
tunes,
|
||||
hideHeader = false,
|
||||
canvasHeight = 100,
|
||||
onTrigger,
|
||||
@ -26,6 +28,7 @@ export function MiniRepl({
|
||||
claviature,
|
||||
claviatureLabels,
|
||||
}) {
|
||||
const code = tunes ? tunes[0] : tune;
|
||||
const id = useMemo(() => s4(), []);
|
||||
const canvasId = useMemo(() => `canvas-${id}`, [id]);
|
||||
const shouldDraw = !!punchcard || !!claviature;
|
||||
@ -75,7 +78,7 @@ export function MiniRepl({
|
||||
}
|
||||
return pat;
|
||||
},
|
||||
prebake: async () => Promise.all([modulesLoading, prebaked]),
|
||||
prebake: async () => Promise.all([modulesLoading, prebaked, audioLoading]),
|
||||
onUpdateState: (state) => {
|
||||
setReplState({ ...state });
|
||||
},
|
||||
@ -91,6 +94,14 @@ export function MiniRepl({
|
||||
const containerRef = useRef();
|
||||
const client = useClient();
|
||||
|
||||
const [tuneIndex, setTuneIndex] = useState(0);
|
||||
const changeTune = (index) => {
|
||||
index = _mod(index, tunes.length);
|
||||
setTuneIndex(index);
|
||||
editorRef.current?.setCode(tunes[index]);
|
||||
editorRef.current?.evaluate();
|
||||
};
|
||||
|
||||
if (!client) {
|
||||
return <pre>{code}</pre>;
|
||||
}
|
||||
@ -119,6 +130,28 @@ export function MiniRepl({
|
||||
<Icon type="refresh" />
|
||||
</button>
|
||||
</div>
|
||||
{tunes && (
|
||||
<div className="flex">
|
||||
<button
|
||||
className={
|
||||
'cursor-pointer w-16 flex items-center justify-center p-1 border-r border-lineHighlight text-foreground bg-lineHighlight hover:bg-background'
|
||||
}
|
||||
onClick={() => changeTune(tuneIndex - 1)}
|
||||
>
|
||||
<div className="rotate-180">
|
||||
<Icon type="skip" />
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
className={
|
||||
'cursor-pointer w-16 flex items-center justify-center p-1 border-r border-lineHighlight text-foreground bg-lineHighlight hover:bg-background'
|
||||
}
|
||||
onClick={() => changeTune(tuneIndex + 1)}
|
||||
>
|
||||
<Icon type="skip" />
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div className="overflow-auto relative p-1">
|
||||
|
||||
81
website/src/examples.mjs
Normal file
81
website/src/examples.mjs
Normal file
@ -0,0 +1,81 @@
|
||||
export const examples = [
|
||||
`// "coastline" @by eddyflux
|
||||
await samples('github:eddyflux/crate')
|
||||
setcps(.75)
|
||||
let chords = chord("<Bbm9 Fm9>/4").dict('ireal')
|
||||
stack(
|
||||
stack( // DRUMS
|
||||
s("bd").struct("<[x*<1 2> [~@3 x]] x>"),
|
||||
s("~ [rim, sd:<2 3>]").room("<0 .2>"),
|
||||
n("[0 <1 3>]*<2!3 4>").s("hh"),
|
||||
s("rd:<1!3 2>*2").mask("<0 0 1 1>/16").gain(.5)
|
||||
).bank('crate')
|
||||
.mask("<[0 1] 1 1 1>/16".early(.5))
|
||||
, // CHORDS
|
||||
chords.offset(-1).voicing().s("gm_epiano1:1")
|
||||
.phaser(4).room(.5)
|
||||
, // MELODY
|
||||
n("<0!3 1*2>").set(chords).mode("root:g2")
|
||||
.voicing().s("gm_acoustic_bass"),
|
||||
chords.n("[0 <4 3 <2 5>>*2](<3 5>,8)")
|
||||
.set(x).anchor("D5").voicing()
|
||||
.segment(4).clip(rand.range(.4,.8))
|
||||
.room(.75).shape(.3).delay(.25)
|
||||
.fm(sine.range(3,8).slow(8))
|
||||
.lpf(sine.range(500,1000).slow(8)).lpq(5)
|
||||
.rarely(ply("2")).chunk(4, fast(2))
|
||||
.gain(perlin.range(.6, .9))
|
||||
.mask("<0 1 1 0>/16")
|
||||
)
|
||||
.late("[0 .01]*4").late("[0 .01]*2").size(4)`,
|
||||
`// "broken cut 1" @by froos
|
||||
|
||||
await samples('github:tidalcycles/Dirt-Samples/master')
|
||||
samples({
|
||||
'slap': 'https://cdn.freesound.org/previews/495/495416_10350281-lq.mp3',
|
||||
'whirl': 'https://cdn.freesound.org/previews/495/495313_10350281-lq.mp3',
|
||||
'attack': 'https://cdn.freesound.org/previews/494/494947_10350281-lq.mp3'
|
||||
})
|
||||
|
||||
setcps(1.25)
|
||||
|
||||
note("[c2 ~](3,8)*2,eb,g,bb,d").s("sawtooth")
|
||||
.noise(0.3)
|
||||
.lpf(perlin.range(800,2000).mul(0.6))
|
||||
.lpenv(perlin.range(1,5)).lpa(.25).lpd(.1).lps(0)
|
||||
.add.mix(note("<0!3 [1 <4!3 12>]>")).late(.5)
|
||||
.vib("4:.2")
|
||||
.room(1).roomsize(4).slow(4)
|
||||
.stack(
|
||||
s("bd").late("<0.01 .251>"),
|
||||
s("breaks165:1/2").fit()
|
||||
.chop(4).sometimesBy(.4, ply("2"))
|
||||
.sometimesBy(.1, ply("4")).release(.01)
|
||||
.gain(1.5).sometimes(mul(speed("1.05"))).cut(1)
|
||||
,
|
||||
s("<whirl attack>?").delay(".8:.1:.8").room(2).slow(8).cut(2),
|
||||
).reset("<x@30 [x*[8 [8 [16 32]]]]@2>".late(2))`,
|
||||
`// "acidic tooth" @by eddyflux
|
||||
setcps(1)
|
||||
stack(
|
||||
note("[<g1 f1>/8](<3 5>,8)")
|
||||
.clip(perlin.range(.15,1.5))
|
||||
.release(.1)
|
||||
.s("sawtooth")
|
||||
.lpf(sine.range(400,800).slow(16))
|
||||
.lpq(cosine.range(6,14).slow(3))
|
||||
.lpenv(sine.mul(4).slow(4))
|
||||
.lpd(.2).lpa(.02)
|
||||
.ftype('24db')
|
||||
.rarely(add(note(12)))
|
||||
.room(.2).shape(.3).postgain(.5)
|
||||
.superimpose(x=>x.add(note(12)).delay(.5).bpf(1000))
|
||||
.gain("[.2 1@3]*2") // fake sidechain
|
||||
,
|
||||
stack(
|
||||
s("bd*2").mask("<0@4 1@16>"),
|
||||
s("hh*8").gain(saw.mul(saw.fast(2))).clip(sine)
|
||||
.mask("<0@8 1@16>")
|
||||
).bank('RolandTR909')
|
||||
)`,
|
||||
];
|
||||
@ -32,7 +32,18 @@ const posts = (await getCollection('blog')).sort((a, b) => compareDesc(a.data.da
|
||||
<LeftSidebar currentPage={currentPage} />
|
||||
</aside>
|
||||
<PageContent>
|
||||
{posts.map((post) => <BlogPost post={post} />)}
|
||||
<div class="border-b-4 border-lineHighlight py-4">
|
||||
<h1>Strudel Blog</h1>
|
||||
<p>
|
||||
Welcome to the Strudel Blog, where we will keep you updated with the latest changes and things happening
|
||||
in the strudelsphere. You can subscribe to this blog using <a target="_blank" href="/rss.xml"
|
||||
>this rss link</a
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
<div class="space-y-8">
|
||||
{posts.map((post) => <BlogPost post={post} />)}
|
||||
</div>
|
||||
</PageContent>
|
||||
<aside class="fixed right-0 h-full overflow-auto pr-4 pl-0 pb-16 hidden xl:block" title="Table of Contents">
|
||||
<RightSidebar
|
||||
|
||||
@ -4,7 +4,7 @@ layout: ../../../layouts/MainLayout.astro
|
||||
---
|
||||
|
||||
import { MiniRepl } from '@src/docs/MiniRepl';
|
||||
import { midi2note } from '@strudel.cycles/core/';
|
||||
import { midi2note } from '@strudel/core/';
|
||||
import Box from '@components/Box.astro';
|
||||
import QA from '@components/QA';
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { createCanvas } from 'canvas';
|
||||
import { pianoroll } from '@strudel.cycles/core';
|
||||
import { evaluate } from '@strudel.cycles/transpiler';
|
||||
import { pianoroll } from '@strudel/core';
|
||||
import { evaluate } from '@strudel/transpiler';
|
||||
import '../../../../test/runtime.mjs';
|
||||
import * as tunes from '../../repl/tunes.mjs';
|
||||
|
||||
|
||||
@ -138,6 +138,60 @@ There is one filter envelope for each filter type and thus one set of envelope f
|
||||
|
||||
<JsDoc client:idle name="lpenv" h={0} />
|
||||
|
||||
# Pitch Envelope
|
||||
|
||||
You can also control the pitch with envelopes!
|
||||
Pitch envelopes can breathe life into static sounds:
|
||||
|
||||
<MiniRepl
|
||||
client:idle
|
||||
tune={`n("<-4,0 5 2 1>*<2!3 4>")
|
||||
.scale("<C F>/8:pentatonic")
|
||||
.s("gm_electric_guitar_jazz")
|
||||
.penv("<.5 0 7 -2>*2").vib("4:.1")
|
||||
.phaser(2).delay(.25).room(.3)
|
||||
.size(4).fast(.75)`}
|
||||
/>
|
||||
|
||||
You also create some lovely chiptune-style sounds:
|
||||
|
||||
<MiniRepl
|
||||
client:idle
|
||||
tune={`n(run("<4 8>/16")).jux(rev)
|
||||
.chord("<C^7 <Db^7 Fm7>>")
|
||||
.dict('ireal')
|
||||
.voicing().add(note("<0 1>/8"))
|
||||
.dec(.1).room(.2)
|
||||
.segment("<4 [2 8]>")
|
||||
.penv("<0 <2 -2>>").patt(.02)`}
|
||||
/>
|
||||
|
||||
Let's break down all pitch envelope controls:
|
||||
|
||||
## pattack
|
||||
|
||||
<JsDoc client:idle name="pattack" h={0} />
|
||||
|
||||
## pdecay
|
||||
|
||||
<JsDoc client:idle name="pdecay" h={0} />
|
||||
|
||||
## prelease
|
||||
|
||||
<JsDoc client:idle name="prelease" h={0} />
|
||||
|
||||
## penv
|
||||
|
||||
<JsDoc client:idle name="penv" h={0} />
|
||||
|
||||
## pcurve
|
||||
|
||||
<JsDoc client:idle name="pcurve" h={0} />
|
||||
|
||||
## panchor
|
||||
|
||||
<JsDoc client:idle name="panchor" h={0} />
|
||||
|
||||
# Dynamics
|
||||
|
||||
## gain
|
||||
|
||||
@ -4,8 +4,6 @@ layout: ../../layouts/MainLayout.astro
|
||||
---
|
||||
|
||||
import { MiniRepl } from '../../docs/MiniRepl';
|
||||
import { JsDoc } from '../../docs/JsDoc';
|
||||
import { samples } from '@strudel.cycles/webaudio';
|
||||
|
||||
see https://strudel.cc/?zMEo5kowGrFc
|
||||
|
||||
|
||||
@ -4,8 +4,6 @@ layout: ../../layouts/MainLayout.astro
|
||||
---
|
||||
|
||||
import { MiniRepl } from '../../docs/MiniRepl';
|
||||
import { JsDoc } from '../../docs/JsDoc';
|
||||
import { samples } from '@strudel.cycles/webaudio';
|
||||
|
||||
Note:
|
||||
|
||||
|
||||
19
website/src/pages/rss.xml.js
Normal file
19
website/src/pages/rss.xml.js
Normal file
@ -0,0 +1,19 @@
|
||||
import rss from '@astrojs/rss';
|
||||
import { getCollection } from 'astro:content';
|
||||
|
||||
export async function GET(context) {
|
||||
const posts = (await getCollection('blog')).filter((p) => !p.data.draft);
|
||||
const options = {
|
||||
title: 'Strudel Blog',
|
||||
description:
|
||||
'The Strudel Blog will keep you updated with the latest changes and things happening in the strudelsphere.',
|
||||
site: context.site,
|
||||
items: posts.map((post) => ({
|
||||
link: `/blog/#${post.slug}`,
|
||||
title: post.data.title,
|
||||
pubDate: post.data.date,
|
||||
description: post.data.description,
|
||||
})),
|
||||
};
|
||||
return rss(options);
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
import { createCanvas } from 'canvas';
|
||||
import { pianoroll } from '@strudel.cycles/core';
|
||||
import { evaluate } from '@strudel.cycles/transpiler';
|
||||
import { pianoroll } from '@strudel/core';
|
||||
import { evaluate } from '@strudel/transpiler';
|
||||
import '../../../../test/runtime.mjs';
|
||||
import { getMyPatterns } from '../../my_patterns';
|
||||
|
||||
@ -14,10 +14,7 @@ export async function GET({ params, request }) {
|
||||
const ctx = canvas.getContext('2d');
|
||||
pianoroll({ time: 4, haps, ctx, playhead: 1, fold: 1, background: 'transparent', playheadColor: 'transparent' });
|
||||
const buffer = canvas.toBuffer('image/png');
|
||||
return {
|
||||
body: buffer,
|
||||
encoding: 'binary',
|
||||
};
|
||||
return new Response(buffer);
|
||||
}
|
||||
export async function getStaticPaths() {
|
||||
const patterns = await getMyPatterns();
|
||||
|
||||
@ -16,16 +16,16 @@ The purpose of the multiple packages is to
|
||||
|
||||
## Overview
|
||||
|
||||
[See the latest published packages on npm](https://www.npmjs.com/search?q=%40strudel.cycles).
|
||||
[See the latest published packages on npm](https://www.npmjs.com/search?q=%40strudel).
|
||||
Here is an overview of all the packages:
|
||||
|
||||
### Essential Packages
|
||||
|
||||
These package are the most essential. You might want to use all of those if you're using strudel in your project:
|
||||
|
||||
- [core](https://github.com/tidalcycles/strudel/tree/main/packages/core#strudelcyclescore): tidal pattern engine with core primitives
|
||||
- [mini](https://github.com/tidalcycles/strudel/tree/main/packages/mini#strudelcyclesmini): mini notation parser + core bindings
|
||||
- [transpiler](https://github.com/tidalcycles/strudel/tree/main/packages/transpiler#strudelcyclestranspiler): user code transpiler. syntax sugar + highlighting
|
||||
- [core](https://github.com/tidalcycles/strudel/tree/main/packages/core#strudelcore): tidal pattern engine with core primitives
|
||||
- [mini](https://github.com/tidalcycles/strudel/tree/main/packages/mini#strudelmini): mini notation parser + core bindings
|
||||
- [transpiler](https://github.com/tidalcycles/strudel/tree/main/packages/transpiler#strudeltranspiler): user code transpiler. syntax sugar + highlighting
|
||||
|
||||
### Language Extensions
|
||||
|
||||
@ -38,23 +38,24 @@ These packages extend the pattern language by specific functions
|
||||
|
||||
These packages provide bindings for different ways to output strudel patterns:
|
||||
|
||||
- [webaudio](https://github.com/tidalcycles/strudel/tree/main/packages/webaudio#strudelcycleswebaudio): the default webaudio output
|
||||
- [osc](https://github.com/tidalcycles/strudel/tree/main/packages/osc#strudelcyclesosc): bindings to communicate via OSC
|
||||
- [midi](https://github.com/tidalcycles/strudel/tree/main/packages/midi#strudelcyclesmidi): webmidi bindings
|
||||
- [csound](https://github.com/tidalcycles/strudel/tree/main/packages/csound#strudelcyclescsound): csound bindings
|
||||
- [soundfonts](https://github.com/tidalcycles/strudel/tree/main/packages/serial#strudelcyclessoundfonts): Soundfont support
|
||||
- [serial](https://github.com/tidalcycles/strudel/tree/main/packages/serial#strudelcyclesserial): webserial bindings
|
||||
- [webaudio](https://github.com/tidalcycles/strudel/tree/main/packages/webaudio#strudelwebaudio): the default webaudio output
|
||||
- [osc](https://github.com/tidalcycles/strudel/tree/main/packages/osc#strudelosc): bindings to communicate via OSC
|
||||
- [midi](https://github.com/tidalcycles/strudel/tree/main/packages/midi#strudelmidi): webmidi bindings
|
||||
- [csound](https://github.com/tidalcycles/strudel/tree/main/packages/csound#strudelcsound): csound bindings
|
||||
- [soundfonts](https://github.com/tidalcycles/strudel/tree/main/packages/serial#strudelsoundfonts): Soundfont support
|
||||
- [serial](https://github.com/tidalcycles/strudel/tree/main/packages/serial#strudelserial): webserial bindings
|
||||
|
||||
### Others
|
||||
|
||||
- [embed](https://github.com/tidalcycles/strudel/tree/main/packages/embed#strudelcyclesembed): embeddable REPL web component
|
||||
- [react](https://github.com/tidalcycles/strudel/tree/main/packages/react#strudelcyclesreact): react hooks and components for strudel
|
||||
- [embed](https://github.com/tidalcycles/strudel/tree/main/packages/embed#strudelembed): embeddable REPL web component
|
||||
|
||||
### No Longer Maintained
|
||||
|
||||
- [react](https://www.npmjs.com/package/@strudel.cycles/react): react hooks and components for strudel
|
||||
- [eval](https://www.npmjs.com/package/@strudel.cycles/eval): old code transpiler
|
||||
- [tone](https://www.npmjs.com/package/@strudel.cycles/tone): bindings for Tone.js instruments and effects
|
||||
- [webdirt](https://www.npmjs.com/package/@strudel.cycles/webdirt): webdirt bindings, replaced by webaudio package
|
||||
- any `@strudel.cycles/*` packages have been renamed to `@strudel/*` since version 0.10.0.
|
||||
|
||||
## Tools
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user