mirror of
https://codeberg.org/uzu/strudel
synced 2026-07-21 20:55:12 -04:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 11be5db628 | |||
| 779d303572 | |||
| 788f344012 | |||
| 33c9326427 | |||
| 9ef57152e4 | |||
| f8f2fb608d | |||
| 1cf6b37ee4 | |||
| 76822717f4 | |||
| 4142b113e9 | |||
| 3c123538e9 | |||
| 73996997e5 | |||
| c4d14594ce | |||
| 657960024d |
@@ -7,7 +7,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [14, 16, 17]
|
||||
node-version: [16, 17]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
@@ -19,11 +19,3 @@ cd repl
|
||||
npm install
|
||||
npm run start
|
||||
```
|
||||
|
||||
## Build
|
||||
|
||||
```bash
|
||||
cd repl
|
||||
npm run build
|
||||
npm run static # <- test static build
|
||||
```
|
||||
|
||||
+1
-1
@@ -2,5 +2,5 @@
|
||||
"packages": [
|
||||
"packages/*"
|
||||
],
|
||||
"version": "0.0.1"
|
||||
"version": "independent"
|
||||
}
|
||||
|
||||
@@ -1,3 +1,36 @@
|
||||
# @strudel.cycles/core
|
||||
|
||||
This package contains the bare essence of strudel.
|
||||
|
||||
## Install
|
||||
|
||||
```sh
|
||||
npm i @strudel.cycles/core --save
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
```js
|
||||
import { sequence, State, TimeSpan } from '@strudel.cycles/core';
|
||||
|
||||
const pattern = sequence('a', ['b', 'c']);
|
||||
|
||||
const events = pattern.query(new State(new TimeSpan(0, 2)));
|
||||
|
||||
const spans = events.map(
|
||||
(event) => `${event.value}: ${event.whole.begin.toFraction()} - ${event.whole.end.toFraction()} `,
|
||||
);
|
||||
```
|
||||
|
||||
spans:
|
||||
|
||||
```log
|
||||
a: 0 - 1/2
|
||||
b: 1/2 - 3/4
|
||||
c: 3/4 - 1
|
||||
a: 1 - 3/2
|
||||
b: 3/2 - 7/4
|
||||
c: 7/4 - 2
|
||||
```
|
||||
|
||||
[play with @strudel.cycles/core on codesandbox](https://codesandbox.io/s/strudel-core-test-qmz6qr?file=/src/index.js).
|
||||
|
||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel.cycles/core",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.2",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel.cycles/core",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.2",
|
||||
"description": "Port of Tidal Cycles to JavaScript",
|
||||
"main": "strudel.mjs",
|
||||
"type": "module",
|
||||
|
||||
@@ -138,6 +138,10 @@ class Hap {
|
||||
}
|
||||
}
|
||||
|
||||
get duration() {
|
||||
return this.whole.end.sub(this.whole.begin).valueOf();
|
||||
}
|
||||
|
||||
withSpan(func) {
|
||||
// Returns a new event with the function f applies to the event timespan.
|
||||
const whole = this.whole ? func(this.whole) : undefined
|
||||
@@ -1034,7 +1038,6 @@ Pattern.prototype.bootstrap = function() {
|
||||
}
|
||||
return [functionName, curry(composable, makeComposable)];
|
||||
}));
|
||||
|
||||
// note: this === Pattern.prototypetgh6z
|
||||
this.patternified.forEach((prop) => {
|
||||
// the following will patternify all functions in Pattern.prototype.patternified
|
||||
|
||||
@@ -3,6 +3,39 @@
|
||||
This package contains the strudel code transformer and evaluator.
|
||||
It allows creating strudel patterns from input code that is optimized for minimal keystrokes and human readability.
|
||||
|
||||
## Install
|
||||
|
||||
```sh
|
||||
npm i @strudel.cycles/eval --save
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
```js
|
||||
import { evaluate, extend } from '@strudel.cycles/eval';
|
||||
import * as strudel from '@strudel.cycles/core';
|
||||
|
||||
extend(strudel); // add strudel to eval scope
|
||||
|
||||
async function run(code) {
|
||||
const { pattern } = await evaluate(code);
|
||||
const events = pattern.firstCycle();
|
||||
console.log(events.map((e) => e.show()).join('\n'));
|
||||
}
|
||||
|
||||
run('sequence([a3, [b3, c4]])');
|
||||
```
|
||||
|
||||
yields:
|
||||
|
||||
```js
|
||||
(0/1 -> 1/2, 0/1 -> 1/2, a3)
|
||||
(1/2 -> 3/4, 1/2 -> 3/4, b3)
|
||||
(3/4 -> 1/1, 3/4 -> 1/1, c4)
|
||||
```
|
||||
|
||||
[play with @strudel.cycles/eval on codesandbox](https://codesandbox.io/s/strudel-eval-example-ndz1d8?file=/src/index.js)
|
||||
|
||||
## Dev Notes
|
||||
|
||||
shift-traverser is currently monkey patched because its package.json uses estraverse@^4.2.0,
|
||||
|
||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel.cycles/eval",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.2",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel.cycles/eval",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.2",
|
||||
"description": "Code evaluator for strudel",
|
||||
"main": "evaluate.mjs",
|
||||
"directories": {
|
||||
@@ -28,7 +28,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||
"dependencies": {
|
||||
"@strudel.cycles/core": "^0.0.1",
|
||||
"@strudel.cycles/core": "^0.0.2",
|
||||
"estraverse": "^5.3.0",
|
||||
"shift-ast": "^6.1.0",
|
||||
"shift-codegen": "^7.0.3",
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
# @strudel.cycles/midi
|
||||
|
||||
This package adds midi functionality to strudel Patterns.
|
||||
|
||||
## Install
|
||||
|
||||
```sh
|
||||
npm i @strudel.cycles/midi --save
|
||||
```
|
||||
|
||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel.cycles/midi",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.2",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel.cycles/midi",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.2",
|
||||
"description": "Midi API for strudel",
|
||||
"main": "midi.mjs",
|
||||
"repository": {
|
||||
@@ -21,7 +21,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||
"dependencies": {
|
||||
"@strudel.cycles/tone": "^0.0.1",
|
||||
"@strudel.cycles/tone": "^0.0.2",
|
||||
"tone": "^14.7.77",
|
||||
"webmidi": "^2.5.2"
|
||||
}
|
||||
|
||||
@@ -1,3 +1,37 @@
|
||||
# @strudel.cycles/mini
|
||||
|
||||
This package contains the mini notation parser and pattern generator.
|
||||
|
||||
## Install
|
||||
|
||||
```sh
|
||||
npm i @strudel.cycles/mini --save
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
```js
|
||||
import { mini } from '@strudel.cycles/mini';
|
||||
|
||||
const pattern = mini('a [b c*2]');
|
||||
|
||||
const events = pattern.firstCycle().map((e) => e.show());
|
||||
console.log(events);
|
||||
|
||||
document.getElementById('app').innerHTML = events.join('<br/>');
|
||||
```
|
||||
|
||||
yields:
|
||||
|
||||
```log
|
||||
(0/1 -> 1/2, 0/1 -> 1/2, a)
|
||||
(1/2 -> 3/4, 1/2 -> 3/4, b)
|
||||
(3/4 -> 7/8, 3/4 -> 7/8, c)
|
||||
(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)
|
||||
|
||||
## Mini Notation API
|
||||
|
||||
See "Mini Notation" in the [Strudel Tutorial](https://strudel.tidalcycles.org/tutorial/)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel.cycles/mini",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.2",
|
||||
"description": "Mini notation for strudel",
|
||||
"main": "mini.mjs",
|
||||
"type": "module",
|
||||
@@ -25,7 +25,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||
"dependencies": {
|
||||
"@strudel.cycles/eval": "^0.0.1",
|
||||
"@strudel.cycles/tone": "^0.0.1"
|
||||
"@strudel.cycles/eval": "^0.0.2",
|
||||
"@strudel.cycles/tone": "^0.0.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,34 @@
|
||||
# @strudel.cycles/tonal
|
||||
|
||||
This package adds tonal / harmonic functions to strudel Patterns.
|
||||
|
||||
## Install
|
||||
|
||||
```sh
|
||||
npm i @strudel.cycles/tonal --save
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
```js
|
||||
import { sequence } from '@strudel.cycles/core';
|
||||
import '@strudel.cycles/tonal';
|
||||
|
||||
const pattern = sequence(0, [1, 2]).scale('C major');
|
||||
|
||||
const events = pattern.firstCycle().map((e) => e.show());
|
||||
```
|
||||
|
||||
yields:
|
||||
|
||||
```js
|
||||
(0/1 -> 1/2, 0/1 -> 1/2, C3)
|
||||
(1/2 -> 3/4, 1/2 -> 3/4, D3)
|
||||
(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)
|
||||
|
||||
## Tonal API
|
||||
|
||||
See "Tonal API" in the [Strudel Tutorial](https://strudel.tidalcycles.org/tutorial/)
|
||||
|
||||
Generated
+2756
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel.cycles/tonal",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.2",
|
||||
"description": "Tonal functions for strudel",
|
||||
"main": "tonal.mjs",
|
||||
"type": "module",
|
||||
@@ -25,6 +25,8 @@
|
||||
},
|
||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||
"dependencies": {
|
||||
"@strudel.cycles/core": "^0.0.1"
|
||||
"@strudel.cycles/core": "^0.0.2",
|
||||
"@tonaljs/tonal": "^4.6.5",
|
||||
"webmidi": "^3.0.15"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import { Note, Interval, Scale } from '@tonaljs/tonal';
|
||||
import { Pattern as _Pattern } from '@strudel.cycles/core/strudel.mjs';
|
||||
import { Pattern } from '@strudel.cycles/core';
|
||||
import { mod } from '@strudel.cycles/core/util.mjs';
|
||||
|
||||
const Pattern = _Pattern; // as any;
|
||||
|
||||
// transpose note inside scale by offset steps
|
||||
// function scaleTranspose(scale: string, offset: number, note: string) {
|
||||
export function scaleTranspose(scale, offset, note) {
|
||||
|
||||
@@ -2,6 +2,12 @@
|
||||
|
||||
This package adds Tone.js functions to strudel Patterns.
|
||||
|
||||
## Install
|
||||
|
||||
```sh
|
||||
npm i @strudel.cycles/tone --save
|
||||
```
|
||||
|
||||
## Dev Notes
|
||||
|
||||
- `@tonejs/piano` has peer dependency on `webmidi@^2.5.1`! A newer version of webmidi will break.
|
||||
|
||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel.cycles/tone",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.2",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel.cycles/tone",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.2",
|
||||
"description": "Tone.js API for strudel",
|
||||
"main": "tone.mjs",
|
||||
"type": "module",
|
||||
@@ -22,7 +22,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||
"dependencies": {
|
||||
"@strudel.cycles/core": "^0.0.1",
|
||||
"@strudel.cycles/core": "^0.0.2",
|
||||
"@tonejs/piano": "^0.2.1",
|
||||
"chord-voicings": "^0.0.1",
|
||||
"tone": "^14.7.77"
|
||||
|
||||
+1
-34
@@ -1,4 +1,4 @@
|
||||
import { Pattern as _Pattern } from '@strudel.cycles/core';
|
||||
import { Pattern } from '@strudel.cycles/core';
|
||||
import * as _Tone from 'tone';
|
||||
|
||||
// import Tone from here, to make sure to get the same AudioContext
|
||||
@@ -41,11 +41,8 @@ defaultSynth.set({
|
||||
// what about
|
||||
// https://www.charlie-roberts.com/gibberish/playground/
|
||||
|
||||
const Pattern = _Pattern;
|
||||
|
||||
// with this function, you can play the pattern with any tone synth
|
||||
Pattern.prototype.tone = function (instrument) {
|
||||
// instrument.toDestination();
|
||||
return this._withEvent((event) => {
|
||||
const onTrigger = (time, event) => {
|
||||
let note;
|
||||
@@ -74,36 +71,6 @@ Pattern.prototype.tone = function (instrument) {
|
||||
note = getPlayableNoteValue(event);
|
||||
instrument.triggerAttackRelease(note, event.duration, time, velocity);
|
||||
}
|
||||
/* switch (instrument.constructor.name) {
|
||||
case 'PluckSynth':
|
||||
note = getPlayableNoteValue(event);
|
||||
instrument.triggerAttack(note, time);
|
||||
break;
|
||||
case 'NoiseSynth':
|
||||
instrument.triggerAttackRelease(event.duration, time); // noise has no value
|
||||
break;
|
||||
case 'Piano':
|
||||
note = getPlayableNoteValue(event);
|
||||
instrument.keyDown({ note, time, velocity });
|
||||
instrument.keyUp({ note, time: time + event.duration, velocity });
|
||||
break;
|
||||
case 'Sampler':
|
||||
note = getPlayableNoteValue(event);
|
||||
instrument.triggerAttackRelease(note, event.duration, time, velocity);
|
||||
break;
|
||||
case 'Players':
|
||||
if (!instrument.has(event.value)) {
|
||||
throw new Error(`name "${event.value}" not defined for players`);
|
||||
}
|
||||
const player = instrument.player(event.value);
|
||||
// velocity ?
|
||||
player.start(time);
|
||||
player.stop(time + event.duration);
|
||||
break;
|
||||
default:
|
||||
note = getPlayableNoteValue(event);
|
||||
instrument.triggerAttackRelease(note, event.duration, time, velocity);
|
||||
} */
|
||||
};
|
||||
return event.setContext({ ...event.context, instrument, onTrigger });
|
||||
});
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
# @strudel.cycles/xen
|
||||
|
||||
This package adds xenharmonic / microtonal functions to strudel Patterns.
|
||||
|
||||
## Install
|
||||
|
||||
```sh
|
||||
npm i @strudel.cycles/xen --save
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel.cycles/xen",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.2",
|
||||
"description": "Xenharmonic API for strudel",
|
||||
"main": "xen.mjs",
|
||||
"scripts": {
|
||||
@@ -24,6 +24,6 @@
|
||||
},
|
||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||
"dependencies": {
|
||||
"@strudel.cycles/core": "^0.0.1"
|
||||
"@strudel.cycles/core": "^0.0.2"
|
||||
}
|
||||
}
|
||||
|
||||
+27
-1
@@ -1,6 +1,32 @@
|
||||
# Strudel REPL
|
||||
|
||||
TBD
|
||||
This is the REPL for Strudel. REPL stands for
|
||||
|
||||
- Read
|
||||
- Evaluate
|
||||
- Play!
|
||||
- Loop
|
||||
|
||||
The REPL is deployed at [strudel.tidalcycles.org](https://strudel.tidalcycles.org/).
|
||||
|
||||
## Run REPL locally
|
||||
|
||||
```bash
|
||||
# from project root
|
||||
npm install
|
||||
npx lerna bootstrap
|
||||
cd repl
|
||||
npm install
|
||||
npm run start
|
||||
```
|
||||
|
||||
## Build REPL
|
||||
|
||||
```bash
|
||||
cd repl
|
||||
npm run build # <- builds repl + tutorial to ../docs
|
||||
npm run static # <- test static build
|
||||
```
|
||||
|
||||
## Dev Notes
|
||||
|
||||
|
||||
@@ -42,16 +42,10 @@ function useCycle(props) {
|
||||
?.filter((event) => event.part.begin.equals(event.whole.begin))
|
||||
.forEach((event) => {
|
||||
Tone.getTransport().schedule((time) => {
|
||||
const toneEvent = {
|
||||
time: event.whole.begin.valueOf(),
|
||||
duration: event.whole.end.sub(event.whole.begin).valueOf(),
|
||||
value: event.value,
|
||||
context: event.context,
|
||||
};
|
||||
onEvent(time, toneEvent);
|
||||
onEvent(time, event);
|
||||
Tone.Draw.schedule(() => {
|
||||
// do drawing or DOM manipulation here
|
||||
onDraw?.(time, toneEvent);
|
||||
onDraw?.(time, event);
|
||||
}, time);
|
||||
}, event.part.begin.valueOf());
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user