mirror of
https://codeberg.org/uzu/strudel
synced 2026-07-22 05:05:26 -04:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cd1c4632d7 | |||
| f1a850e133 | |||
| 53b61b8d85 | |||
| e1a532500e | |||
| 4cf412b93d | |||
| 54c9c434e0 | |||
| de19f3e5fe | |||
| 8304993481 | |||
| 4c838aeaca | |||
| 547d925065 |
@@ -74,7 +74,7 @@ const fraction = (n) => {
|
|||||||
-> those farey sequences turn out to make pattern querying ~20 times slower! always use strings!
|
-> those farey sequences turn out to make pattern querying ~20 times slower! always use strings!
|
||||||
-> still, some optimizations could be done: .mul .div .add .sub calls still use numbers
|
-> still, some optimizations could be done: .mul .div .add .sub calls still use numbers
|
||||||
*/
|
*/
|
||||||
n = String(n);
|
// n = String(n); // this is actually faster but imprecise...
|
||||||
}
|
}
|
||||||
return Fraction(n);
|
return Fraction(n);
|
||||||
};
|
};
|
||||||
|
|||||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/core",
|
"name": "@strudel.cycles/core",
|
||||||
"version": "0.4.1",
|
"version": "0.4.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/core",
|
"name": "@strudel.cycles/core",
|
||||||
"version": "0.4.1",
|
"version": "0.4.0",
|
||||||
"description": "Port of Tidal Cycles to JavaScript",
|
"description": "Port of Tidal Cycles to JavaScript",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
+629
-559
File diff suppressed because it is too large
Load Diff
@@ -20,7 +20,7 @@ export const signal = (func) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const isaw = signal((t) => 1 - (t % 1));
|
export const isaw = signal((t) => 1 - (t % 1));
|
||||||
export const isaw2 = isaw._toBipolar();
|
export const isaw2 = isaw.toBipolar();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A sawtooth signal between 0 and 1.
|
* A sawtooth signal between 0 and 1.
|
||||||
@@ -33,7 +33,7 @@ export const isaw2 = isaw._toBipolar();
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const saw = signal((t) => t % 1);
|
export const saw = signal((t) => t % 1);
|
||||||
export const saw2 = saw._toBipolar();
|
export const saw2 = saw.toBipolar();
|
||||||
|
|
||||||
export const sine2 = signal((t) => Math.sin(Math.PI * 2 * t));
|
export const sine2 = signal((t) => Math.sin(Math.PI * 2 * t));
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ export const sine2 = signal((t) => Math.sin(Math.PI * 2 * t));
|
|||||||
* sine.segment(16).range(0,15).slow(2).scale('C minor').note()
|
* sine.segment(16).range(0,15).slow(2).scale('C minor').note()
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const sine = sine2._fromBipolar();
|
export const sine = sine2.fromBipolar();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A cosine signal between 0 and 1.
|
* A cosine signal between 0 and 1.
|
||||||
@@ -67,7 +67,7 @@ export const cosine2 = sine2._early(Fraction(1).div(4));
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const square = signal((t) => Math.floor((t * 2) % 2));
|
export const square = signal((t) => Math.floor((t * 2) % 2));
|
||||||
export const square2 = square._toBipolar();
|
export const square2 = square.toBipolar();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A triangle signal between 0 and 1.
|
* A triangle signal between 0 and 1.
|
||||||
@@ -127,7 +127,7 @@ export const rand = signal(timeToRand);
|
|||||||
/**
|
/**
|
||||||
* A continuous pattern of random numbers, between -1 and 1
|
* A continuous pattern of random numbers, between -1 and 1
|
||||||
*/
|
*/
|
||||||
export const rand2 = rand._toBipolar();
|
export const rand2 = rand.toBipolar();
|
||||||
|
|
||||||
export const _brandBy = (p) => rand.fmap((x) => x < p);
|
export const _brandBy = (p) => rand.fmap((x) => x < p);
|
||||||
export const brandBy = (pPat) => reify(pPat).fmap(_brandBy).innerJoin();
|
export const brandBy = (pPat) => reify(pPat).fmap(_brandBy).innerJoin();
|
||||||
@@ -201,7 +201,7 @@ Pattern.prototype.choose = function (...xs) {
|
|||||||
* @returns {Pattern}
|
* @returns {Pattern}
|
||||||
*/
|
*/
|
||||||
Pattern.prototype.choose2 = function (...xs) {
|
Pattern.prototype.choose2 = function (...xs) {
|
||||||
return chooseWith(this._fromBipolar(), xs);
|
return chooseWith(this.fromBipolar(), xs);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -259,7 +259,7 @@ export const perlinWith = (pat) => {
|
|||||||
export const perlin = perlinWith(time.fmap((v) => Number(v)));
|
export const perlin = perlinWith(time.fmap((v) => Number(v)));
|
||||||
|
|
||||||
Pattern.prototype._degradeByWith = function (withPat, x) {
|
Pattern.prototype._degradeByWith = function (withPat, x) {
|
||||||
return this.fmap((a) => (_) => a).appLeft(withPat._filterValues((v) => v > x));
|
return this.fmap((a) => (_) => a).appLeft(withPat.filterValues((v) => v > x));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ import { steady } from '../signal.mjs';
|
|||||||
|
|
||||||
import controls from '../controls.mjs';
|
import controls from '../controls.mjs';
|
||||||
|
|
||||||
const { n } = controls;
|
const { n, s } = controls;
|
||||||
const st = (begin, end) => new State(ts(begin, end));
|
const st = (begin, end) => new State(ts(begin, end));
|
||||||
const ts = (begin, end) => new TimeSpan(Fraction(begin), Fraction(end));
|
const ts = (begin, end) => new TimeSpan(Fraction(begin), Fraction(end));
|
||||||
const hap = (whole, part, value, context = {}) => new Hap(whole, part, value, context);
|
const hap = (whole, part, value, context = {}) => new Hap(whole, part, value, context);
|
||||||
@@ -58,7 +58,7 @@ const third = Fraction(1, 3);
|
|||||||
const twothirds = Fraction(2, 3);
|
const twothirds = Fraction(2, 3);
|
||||||
|
|
||||||
const sameFirst = (a, b) => {
|
const sameFirst = (a, b) => {
|
||||||
return expect(a._sortHapsByPart().firstCycle()).toStrictEqual(b._sortHapsByPart().firstCycle());
|
return expect(a.sortHapsByPart().firstCycle()).toStrictEqual(b.sortHapsByPart().firstCycle());
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('TimeSpan', () => {
|
describe('TimeSpan', () => {
|
||||||
@@ -382,7 +382,7 @@ describe('Pattern', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('copes with breaking up events across cycles', () => {
|
it('copes with breaking up events across cycles', () => {
|
||||||
expect(pure('a').slow(2)._fastGap(2)._setContext({}).query(st(0, 2))).toStrictEqual([
|
expect(pure('a').slow(2)._fastGap(2).setContext({}).query(st(0, 2))).toStrictEqual([
|
||||||
hap(ts(0, 1), ts(0, 0.5), 'a'),
|
hap(ts(0, 1), ts(0, 0.5), 'a'),
|
||||||
hap(ts(0.5, 1.5), ts(1, 1.5), 'a'),
|
hap(ts(0.5, 1.5), ts(1, 1.5), 'a'),
|
||||||
]);
|
]);
|
||||||
@@ -446,8 +446,8 @@ describe('Pattern', () => {
|
|||||||
});
|
});
|
||||||
describe('slow()', () => {
|
describe('slow()', () => {
|
||||||
it('Supports zero-length queries', () => {
|
it('Supports zero-length queries', () => {
|
||||||
expect(steady('a').slow(1)._setContext({}).queryArc(0, 0)).toStrictEqual(
|
expect(steady('a').slow(1).setContext({}).queryArc(0, 0)).toStrictEqual(
|
||||||
steady('a')._setContext({}).queryArc(0, 0),
|
steady('a').setContext({}).queryArc(0, 0),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -465,7 +465,7 @@ describe('Pattern', () => {
|
|||||||
it('Filters true', () => {
|
it('Filters true', () => {
|
||||||
expect(
|
expect(
|
||||||
pure(true)
|
pure(true)
|
||||||
._filterValues((x) => x)
|
.filterValues((x) => x)
|
||||||
.firstCycle().length,
|
.firstCycle().length,
|
||||||
).toBe(1);
|
).toBe(1);
|
||||||
});
|
});
|
||||||
@@ -490,7 +490,7 @@ describe('Pattern', () => {
|
|||||||
pure(10)
|
pure(10)
|
||||||
.when(slowcat(true, false), (x) => x.add(3))
|
.when(slowcat(true, false), (x) => x.add(3))
|
||||||
.fast(4)
|
.fast(4)
|
||||||
._sortHapsByPart()
|
.sortHapsByPart()
|
||||||
.firstCycle(),
|
.firstCycle(),
|
||||||
).toStrictEqual(fastcat(13, 10, 13, 10).firstCycle());
|
).toStrictEqual(fastcat(13, 10, 13, 10).firstCycle());
|
||||||
});
|
});
|
||||||
@@ -577,26 +577,26 @@ describe('Pattern', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('every()', () => {
|
describe('firstOf()', () => {
|
||||||
it('Can apply a function every 3rd time', () => {
|
it('Can apply a function every 3rd time', () => {
|
||||||
expect(
|
expect(
|
||||||
pure('a')
|
pure('a')
|
||||||
.every(3, (x) => x._fast(2))
|
.firstOf(3, (x) => x._fast(2))
|
||||||
._fast(3)
|
._fast(3)
|
||||||
.firstCycle(),
|
.firstCycle(),
|
||||||
).toStrictEqual(sequence(sequence('a', 'a'), 'a', 'a').firstCycle());
|
).toStrictEqual(sequence(sequence('a', 'a'), 'a', 'a').firstCycle());
|
||||||
});
|
});
|
||||||
it('works with currying', () => {
|
it('works with currying', () => {
|
||||||
expect(pure('a').every(3, fast(2))._fast(3).firstCycle()).toStrictEqual(
|
expect(pure('a').firstOf(3, fast(2))._fast(3).firstCycle()).toStrictEqual(
|
||||||
sequence(sequence('a', 'a'), 'a', 'a').firstCycle(),
|
sequence(sequence('a', 'a'), 'a', 'a').firstCycle(),
|
||||||
);
|
);
|
||||||
expect(sequence(3, 4, 5).every(3, add(3)).fast(5).firstCycle()).toStrictEqual(
|
expect(sequence(3, 4, 5).firstOf(3, add(3)).fast(5).firstCycle()).toStrictEqual(
|
||||||
sequence(6, 7, 8, 3, 4, 5, 3, 4, 5, 6, 7, 8, 3, 4, 5).firstCycle(),
|
sequence(6, 7, 8, 3, 4, 5, 3, 4, 5, 6, 7, 8, 3, 4, 5).firstCycle(),
|
||||||
);
|
);
|
||||||
expect(sequence(3, 4, 5).every(2, sub(1)).fast(5).firstCycle()).toStrictEqual(
|
expect(sequence(3, 4, 5).firstOf(2, sub(1)).fast(5).firstCycle()).toStrictEqual(
|
||||||
sequence(2, 3, 4, 3, 4, 5, 2, 3, 4, 3, 4, 5, 2, 3, 4).firstCycle(),
|
sequence(2, 3, 4, 3, 4, 5, 2, 3, 4, 3, 4, 5, 2, 3, 4).firstCycle(),
|
||||||
);
|
);
|
||||||
expect(sequence(3, 4, 5).every(3, add(3)).every(2, sub(1)).fast(2).firstCycle()).toStrictEqual(
|
expect(sequence(3, 4, 5).firstOf(3, add(3)).firstOf(2, sub(1)).fast(2).firstCycle()).toStrictEqual(
|
||||||
sequence(5, 6, 7, 3, 4, 5).firstCycle(),
|
sequence(5, 6, 7, 3, 4, 5).firstCycle(),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -692,7 +692,7 @@ describe('Pattern', () => {
|
|||||||
it('Can set the hap context', () => {
|
it('Can set the hap context', () => {
|
||||||
expect(
|
expect(
|
||||||
pure('a')
|
pure('a')
|
||||||
._setContext([
|
.setContext([
|
||||||
[
|
[
|
||||||
[0, 1],
|
[0, 1],
|
||||||
[1, 2],
|
[1, 2],
|
||||||
@@ -713,13 +713,13 @@ describe('Pattern', () => {
|
|||||||
it('Can update the hap context', () => {
|
it('Can update the hap context', () => {
|
||||||
expect(
|
expect(
|
||||||
pure('a')
|
pure('a')
|
||||||
._setContext([
|
.setContext([
|
||||||
[
|
[
|
||||||
[0, 1],
|
[0, 1],
|
||||||
[1, 2],
|
[1, 2],
|
||||||
],
|
],
|
||||||
])
|
])
|
||||||
._withContext((c) => [
|
.withContext((c) => [
|
||||||
...c,
|
...c,
|
||||||
[
|
[
|
||||||
[3, 4],
|
[3, 4],
|
||||||
@@ -743,7 +743,7 @@ describe('Pattern', () => {
|
|||||||
});
|
});
|
||||||
describe('apply', () => {
|
describe('apply', () => {
|
||||||
it('Can apply a function', () => {
|
it('Can apply a function', () => {
|
||||||
expect(sequence('a', 'b')._apply(fast(2)).firstCycle()).toStrictEqual(sequence('a', 'b').fast(2).firstCycle());
|
expect(sequence('a', 'b').apply(fast(2)).firstCycle()).toStrictEqual(sequence('a', 'b').fast(2).firstCycle());
|
||||||
}),
|
}),
|
||||||
it('Can apply a pattern of functions', () => {
|
it('Can apply a pattern of functions', () => {
|
||||||
expect(sequence('a', 'b').apply(fast(2)).firstCycle()).toStrictEqual(sequence('a', 'b').fast(2).firstCycle());
|
expect(sequence('a', 'b').apply(fast(2)).firstCycle()).toStrictEqual(sequence('a', 'b').fast(2).firstCycle());
|
||||||
@@ -784,18 +784,18 @@ describe('Pattern', () => {
|
|||||||
});
|
});
|
||||||
describe('jux', () => {
|
describe('jux', () => {
|
||||||
it('Can juxtapose', () => {
|
it('Can juxtapose', () => {
|
||||||
expect(pure({ a: 1 }).jux(fast(2))._sortHapsByPart().firstCycle()).toStrictEqual(
|
expect(pure({ a: 1 }).jux(fast(2)).sortHapsByPart().firstCycle()).toStrictEqual(
|
||||||
stack(pure({ a: 1, pan: 0 }), pure({ a: 1, pan: 1 }).fast(2))
|
stack(pure({ a: 1, pan: 0 }), pure({ a: 1, pan: 1 }).fast(2))
|
||||||
._sortHapsByPart()
|
.sortHapsByPart()
|
||||||
.firstCycle(),
|
.firstCycle(),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('juxBy', () => {
|
describe('juxBy', () => {
|
||||||
it('Can juxtapose by half', () => {
|
it('Can juxtapose by half', () => {
|
||||||
expect(pure({ a: 1 }).juxBy(0.5, fast(2))._sortHapsByPart().firstCycle()).toStrictEqual(
|
expect(pure({ a: 1 }).juxBy(0.5, fast(2)).sortHapsByPart().firstCycle()).toStrictEqual(
|
||||||
stack(pure({ a: 1, pan: 0.25 }), pure({ a: 1, pan: 0.75 }).fast(2))
|
stack(pure({ a: 1, pan: 0.25 }), pure({ a: 1, pan: 0.75 }).fast(2))
|
||||||
._sortHapsByPart()
|
.sortHapsByPart()
|
||||||
.firstCycle(),
|
.firstCycle(),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -805,7 +805,7 @@ describe('Pattern', () => {
|
|||||||
expect(
|
expect(
|
||||||
sequence('a', ['a', 'a'])
|
sequence('a', ['a', 'a'])
|
||||||
.fmap((a) => fastcat('b', 'c'))
|
.fmap((a) => fastcat('b', 'c'))
|
||||||
._squeezeJoin()
|
.squeezeJoin()
|
||||||
.firstCycle(),
|
.firstCycle(),
|
||||||
).toStrictEqual(
|
).toStrictEqual(
|
||||||
sequence(
|
sequence(
|
||||||
@@ -820,7 +820,7 @@ describe('Pattern', () => {
|
|||||||
it('Squeezes to the correct cycle', () => {
|
it('Squeezes to the correct cycle', () => {
|
||||||
expect(
|
expect(
|
||||||
pure(time.struct(true))
|
pure(time.struct(true))
|
||||||
._squeezeJoin()
|
.squeezeJoin()
|
||||||
.queryArc(3, 4)
|
.queryArc(3, 4)
|
||||||
.map((x) => x.value),
|
.map((x) => x.value),
|
||||||
).toStrictEqual([Fraction(3.5)]);
|
).toStrictEqual([Fraction(3.5)]);
|
||||||
@@ -857,7 +857,7 @@ describe('Pattern', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('Can chop(2,3)', () => {
|
it('Can chop(2,3)', () => {
|
||||||
expect(pure({ sound: 'a' }).fast(2).chop(2, 3)._sortHapsByPart().firstCycle()).toStrictEqual(
|
expect(pure({ sound: 'a' }).fast(2).chop(2, 3).sortHapsByPart().firstCycle()).toStrictEqual(
|
||||||
sequence(
|
sequence(
|
||||||
[
|
[
|
||||||
{ sound: 'a', begin: 0, end: 0.5 },
|
{ sound: 'a', begin: 0, end: 0.5 },
|
||||||
@@ -869,7 +869,7 @@ describe('Pattern', () => {
|
|||||||
{ sound: 'a', begin: 2 / 3, end: 1 },
|
{ sound: 'a', begin: 2 / 3, end: 1 },
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
._sortHapsByPart()
|
.sortHapsByPart()
|
||||||
.firstCycle(),
|
.firstCycle(),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -893,4 +893,11 @@ describe('Pattern', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
describe('alignments', () => {
|
||||||
|
it('Can squeeze arguments', () => {
|
||||||
|
expect(sequence(1, 2).add.squeeze(4, 5).firstCycle()).toStrictEqual(
|
||||||
|
sequence(5, 6, 6, 7).firstCycle()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/eval",
|
"name": "@strudel.cycles/eval",
|
||||||
"version": "0.4.1",
|
"version": "0.4.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/eval",
|
"name": "@strudel.cycles/eval",
|
||||||
"version": "0.4.1",
|
"version": "0.4.0",
|
||||||
"description": "Code evaluator for strudel",
|
"description": "Code evaluator for strudel",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@strudel.cycles/core": "^0.4.1",
|
"@strudel.cycles/core": "^0.4.0",
|
||||||
"estraverse": "^5.3.0",
|
"estraverse": "^5.3.0",
|
||||||
"shift-ast": "^7.0.0",
|
"shift-ast": "^7.0.0",
|
||||||
"shift-codegen": "^8.1.0",
|
"shift-codegen": "^8.1.0",
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ const { fastcat, evalScope } = strudel;
|
|||||||
|
|
||||||
describe('evaluate', async () => {
|
describe('evaluate', async () => {
|
||||||
await evalScope({ mini }, strudel);
|
await evalScope({ mini }, strudel);
|
||||||
const ev = async (code) => (await evaluate(code)).pattern._firstCycleValues;
|
const ev = async (code) => (await evaluate(code)).pattern.firstCycleValues;
|
||||||
it('Should evaluate strudel functions', async () => {
|
it('Should evaluate strudel functions', async () => {
|
||||||
expect(await ev('pure("c3")')).toEqual(['c3']);
|
expect(await ev('pure("c3")')).toEqual(['c3']);
|
||||||
expect(await ev('cat("c3")')).toEqual(['c3']);
|
expect(await ev('cat("c3")')).toEqual(['c3']);
|
||||||
|
|||||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/midi",
|
"name": "@strudel.cycles/midi",
|
||||||
"version": "0.4.1",
|
"version": "0.4.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/midi",
|
"name": "@strudel.cycles/midi",
|
||||||
"version": "0.4.1",
|
"version": "0.4.0",
|
||||||
"description": "Midi API for strudel",
|
"description": "Midi API for strudel",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"repository": {
|
"repository": {
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@strudel.cycles/tone": "^0.4.1",
|
"@strudel.cycles/tone": "^0.4.0",
|
||||||
"tone": "^14.7.77",
|
"tone": "^14.7.77",
|
||||||
"webmidi": "^3.0.21"
|
"webmidi": "^3.0.21"
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/mini",
|
"name": "@strudel.cycles/mini",
|
||||||
"version": "0.4.1",
|
"version": "0.4.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/mini",
|
"name": "@strudel.cycles/mini",
|
||||||
"version": "0.4.1",
|
"version": "0.4.0",
|
||||||
"description": "Mini notation for strudel",
|
"description": "Mini notation for strudel",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -26,9 +26,9 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@strudel.cycles/core": "^0.4.1",
|
"@strudel.cycles/core": "^0.4.0",
|
||||||
"@strudel.cycles/eval": "^0.4.1",
|
"@strudel.cycles/eval": "^0.4.0",
|
||||||
"@strudel.cycles/tone": "^0.4.1"
|
"@strudel.cycles/tone": "^0.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"peggy": "^2.0.1"
|
"peggy": "^2.0.1"
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ import '@strudel.cycles/core/euclid.mjs';
|
|||||||
import { describe, expect, it } from 'vitest';
|
import { describe, expect, it } from 'vitest';
|
||||||
|
|
||||||
describe('mini', () => {
|
describe('mini', () => {
|
||||||
const minV = (v) => mini(v)._firstCycleValues;
|
const minV = (v) => mini(v).firstCycleValues;
|
||||||
const minS = (v) => mini(v)._showFirstCycle;
|
const minS = (v) => mini(v).showFirstCycle;
|
||||||
it('supports single elements', () => {
|
it('supports single elements', () => {
|
||||||
expect(minV('a')).toEqual(['a']);
|
expect(minV('a')).toEqual(['a']);
|
||||||
});
|
});
|
||||||
|
|||||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/osc",
|
"name": "@strudel.cycles/osc",
|
||||||
"version": "0.3.1",
|
"version": "0.3.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/osc",
|
"name": "@strudel.cycles/osc",
|
||||||
"version": "0.3.1",
|
"version": "0.3.0",
|
||||||
"description": "OSC messaging for strudel",
|
"description": "OSC messaging for strudel",
|
||||||
"main": "osc.mjs",
|
"main": "osc.mjs",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/react",
|
"name": "@strudel.cycles/react",
|
||||||
"version": "0.4.2",
|
"version": "0.4.1",
|
||||||
"description": "React components for strudel",
|
"description": "React components for strudel",
|
||||||
"main": "dist/index.cjs.js",
|
"main": "dist/index.cjs.js",
|
||||||
"module": "dist/index.es.js",
|
"module": "dist/index.es.js",
|
||||||
@@ -39,10 +39,10 @@
|
|||||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/lang-javascript": "^6.1.1",
|
"@codemirror/lang-javascript": "^6.1.1",
|
||||||
"@strudel.cycles/core": "^0.4.1",
|
"@strudel.cycles/core": "^0.4.0",
|
||||||
"@strudel.cycles/tone": "^0.4.1",
|
"@strudel.cycles/tone": "^0.4.0",
|
||||||
"@strudel.cycles/transpiler": "^0.4.1",
|
"@strudel.cycles/transpiler": "^0.4.0",
|
||||||
"@strudel.cycles/webaudio": "^0.4.2",
|
"@strudel.cycles/webaudio": "^0.4.1",
|
||||||
"@uiw/codemirror-themes": "^4.12.4",
|
"@uiw/codemirror-themes": "^4.12.4",
|
||||||
"@uiw/react-codemirror": "^4.12.4",
|
"@uiw/react-codemirror": "^4.12.4",
|
||||||
"react-hook-inview": "^4.5.0"
|
"react-hook-inview": "^4.5.0"
|
||||||
|
|||||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/soundfonts",
|
"name": "@strudel.cycles/soundfonts",
|
||||||
"version": "0.4.2",
|
"version": "0.4.1",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/soundfonts",
|
"name": "@strudel.cycles/soundfonts",
|
||||||
"version": "0.4.2",
|
"version": "0.4.1",
|
||||||
"description": "Soundsfont support for strudel",
|
"description": "Soundsfont support for strudel",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -22,8 +22,8 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@strudel.cycles/core": "^0.4.1",
|
"@strudel.cycles/core": "^0.4.0",
|
||||||
"@strudel.cycles/webaudio": "^0.4.2",
|
"@strudel.cycles/webaudio": "^0.4.1",
|
||||||
"sfumato": "^0.1.2",
|
"sfumato": "^0.1.2",
|
||||||
"soundfont2": "^0.4.0"
|
"soundfont2": "^0.4.0"
|
||||||
},
|
},
|
||||||
|
|||||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/tonal",
|
"name": "@strudel.cycles/tonal",
|
||||||
"version": "0.4.1",
|
"version": "0.4.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/tonal",
|
"name": "@strudel.cycles/tonal",
|
||||||
"version": "0.4.1",
|
"version": "0.4.0",
|
||||||
"description": "Tonal functions for strudel",
|
"description": "Tonal functions for strudel",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@strudel.cycles/core": "^0.4.1",
|
"@strudel.cycles/core": "^0.4.0",
|
||||||
"@tonaljs/tonal": "^4.6.5",
|
"@tonaljs/tonal": "^4.6.5",
|
||||||
"chord-voicings": "^0.0.1",
|
"chord-voicings": "^0.0.1",
|
||||||
"webmidi": "^3.0.21"
|
"webmidi": "^3.0.21"
|
||||||
|
|||||||
@@ -12,6 +12,6 @@ import { describe, it, expect } from 'vitest';
|
|||||||
|
|
||||||
describe('tonal', () => {
|
describe('tonal', () => {
|
||||||
it('Should run tonal functions ', () => {
|
it('Should run tonal functions ', () => {
|
||||||
expect(pure('c3').scale('C major').scaleTranspose(1)._firstCycleValues).toEqual(['D3']);
|
expect(pure('c3').scale('C major').scaleTranspose(1).firstCycleValues).toEqual(['D3']);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ function scaleOffset(scale, offset, note) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Pattern.prototype._transpose = function (intervalOrSemitones) {
|
Pattern.prototype._transpose = function (intervalOrSemitones) {
|
||||||
return this._withHap((hap) => {
|
return this.withHap((hap) => {
|
||||||
const interval = !isNaN(Number(intervalOrSemitones))
|
const interval = !isNaN(Number(intervalOrSemitones))
|
||||||
? Interval.fromSemitones(intervalOrSemitones /* as number */)
|
? Interval.fromSemitones(intervalOrSemitones /* as number */)
|
||||||
: String(intervalOrSemitones);
|
: String(intervalOrSemitones);
|
||||||
@@ -111,7 +111,7 @@ Pattern.prototype._transpose = function (intervalOrSemitones) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Pattern.prototype._scaleTranspose = function (offset /* : number | string */) {
|
Pattern.prototype._scaleTranspose = function (offset /* : number | string */) {
|
||||||
return this._withHap((hap) => {
|
return this.withHap((hap) => {
|
||||||
if (!hap.context.scale) {
|
if (!hap.context.scale) {
|
||||||
throw new Error('can only use scaleTranspose after .scale');
|
throw new Error('can only use scaleTranspose after .scale');
|
||||||
}
|
}
|
||||||
@@ -142,7 +142,7 @@ Pattern.prototype._scaleTranspose = function (offset /* : number | string */) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Pattern.prototype._scale = function (scale /* : string */) {
|
Pattern.prototype._scale = function (scale /* : string */) {
|
||||||
return this._withHap((hap) => {
|
return this.withHap((hap) => {
|
||||||
let note = hap.value;
|
let note = hap.value;
|
||||||
const asNumber = Number(note);
|
const asNumber = Number(note);
|
||||||
if (!isNaN(asNumber)) {
|
if (!isNaN(asNumber)) {
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ Pattern.prototype.voicings = function (range) {
|
|||||||
}
|
}
|
||||||
return this.fmapNested((event) => {
|
return this.fmapNested((event) => {
|
||||||
lastVoicing = getVoicing(event.value, lastVoicing, range);
|
lastVoicing = getVoicing(event.value, lastVoicing, range);
|
||||||
return stack(...lastVoicing)._withContext(() => ({
|
return stack(...lastVoicing).withContext(() => ({
|
||||||
locations: event.context.locations || [],
|
locations: event.context.locations || [],
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|||||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/tone",
|
"name": "@strudel.cycles/tone",
|
||||||
"version": "0.4.1",
|
"version": "0.4.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/tone",
|
"name": "@strudel.cycles/tone",
|
||||||
"version": "0.4.1",
|
"version": "0.4.0",
|
||||||
"description": "Tone.js API for strudel",
|
"description": "Tone.js API for strudel",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@strudel.cycles/core": "^0.4.1",
|
"@strudel.cycles/core": "^0.4.0",
|
||||||
"tone": "^14.7.77"
|
"tone": "^14.7.77"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,6 @@ describe('tone', () => {
|
|||||||
// const s = synth().chain(out()); // TODO: mock audio context?
|
// const s = synth().chain(out()); // TODO: mock audio context?
|
||||||
// assert.deepStrictEqual(s, new Tone.Synth().chain(out()));
|
// assert.deepStrictEqual(s, new Tone.Synth().chain(out()));
|
||||||
const s = {};
|
const s = {};
|
||||||
expect(pure('c3').tone(s)._firstCycleValues).toEqual(['c3']);
|
expect(pure('c3').tone(s).firstCycleValues).toEqual(['c3']);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/transpiler",
|
"name": "@strudel.cycles/transpiler",
|
||||||
"version": "0.4.1",
|
"version": "0.4.0",
|
||||||
"description": "Transpiler for strudel user code. Converts syntactically correct but semantically meaningless JS into evaluatable strudel code.",
|
"description": "Transpiler for strudel user code. Converts syntactically correct but semantically meaningless JS into evaluatable strudel code.",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@strudel.cycles/core": "^0.4.1",
|
"@strudel.cycles/core": "^0.4.0",
|
||||||
"acorn": "^8.8.1",
|
"acorn": "^8.8.1",
|
||||||
"escodegen": "^2.0.0",
|
"escodegen": "^2.0.0",
|
||||||
"estree-walker": "^3.0.1"
|
"estree-walker": "^3.0.1"
|
||||||
|
|||||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/webaudio",
|
"name": "@strudel.cycles/webaudio",
|
||||||
"version": "0.4.2",
|
"version": "0.4.1",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/webaudio",
|
"name": "@strudel.cycles/webaudio",
|
||||||
"version": "0.4.2",
|
"version": "0.4.1",
|
||||||
"description": "Web Audio helpers for Strudel",
|
"description": "Web Audio helpers for Strudel",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -30,6 +30,6 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@strudel.cycles/core": "^0.4.1"
|
"@strudel.cycles/core": "^0.4.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ function getDelay(orbit, delaytime, delayfeedback, t) {
|
|||||||
if (!delays[orbit]) {
|
if (!delays[orbit]) {
|
||||||
const ac = getAudioContext();
|
const ac = getAudioContext();
|
||||||
const dly = ac.createFeedbackDelay(1, delaytime, delayfeedback);
|
const dly = ac.createFeedbackDelay(1, delaytime, delayfeedback);
|
||||||
dly.start(t);
|
dly.start?.(t); // for some reason, this throws when audion extension is installed..
|
||||||
dly.connect(getDestination());
|
dly.connect(getDestination());
|
||||||
delays[orbit] = dly;
|
delays[orbit] = dly;
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/webdirt",
|
"name": "@strudel.cycles/webdirt",
|
||||||
"version": "0.4.1",
|
"version": "0.4.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/webdirt",
|
"name": "@strudel.cycles/webdirt",
|
||||||
"version": "0.4.1",
|
"version": "0.4.0",
|
||||||
"description": "WebDirt integration for Strudel",
|
"description": "WebDirt integration for Strudel",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@strudel.cycles/core": "^0.4.1",
|
"@strudel.cycles/core": "^0.4.0",
|
||||||
"WebDirt": "github:dktr0/WebDirt"
|
"WebDirt": "github:dktr0/WebDirt"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/xen",
|
"name": "@strudel.cycles/xen",
|
||||||
"version": "0.4.1",
|
"version": "0.4.0",
|
||||||
"description": "Xenharmonic API for strudel",
|
"description": "Xenharmonic API for strudel",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -24,6 +24,6 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@strudel.cycles/core": "^0.4.1"
|
"@strudel.cycles/core": "^0.4.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,22 @@
|
|||||||
// Vitest Snapshot v1
|
// Vitest Snapshot v1
|
||||||
|
|
||||||
|
exports[`runs examples > example "_apply" example index 0 1`] = `
|
||||||
|
[
|
||||||
|
"0/1 -> 1/1: {\\"note\\":\\"C3\\"}",
|
||||||
|
"0/1 -> 1/1: {\\"note\\":\\"Eb3\\"}",
|
||||||
|
"0/1 -> 1/1: {\\"note\\":\\"G3\\"}",
|
||||||
|
"1/1 -> 2/1: {\\"note\\":\\"Eb3\\"}",
|
||||||
|
"1/1 -> 2/1: {\\"note\\":\\"G3\\"}",
|
||||||
|
"1/1 -> 2/1: {\\"note\\":\\"Bb3\\"}",
|
||||||
|
"2/1 -> 3/1: {\\"note\\":\\"G3\\"}",
|
||||||
|
"2/1 -> 3/1: {\\"note\\":\\"Bb3\\"}",
|
||||||
|
"2/1 -> 3/1: {\\"note\\":\\"D4\\"}",
|
||||||
|
"3/1 -> 4/1: {\\"note\\":\\"C3\\"}",
|
||||||
|
"3/1 -> 4/1: {\\"note\\":\\"Eb3\\"}",
|
||||||
|
"3/1 -> 4/1: {\\"note\\":\\"G3\\"}",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`runs examples > example "accelerate" example index 0 1`] = `
|
exports[`runs examples > example "accelerate" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"0/1 -> 2/1: {\\"s\\":\\"sax\\",\\"accelerate\\":0}",
|
"0/1 -> 2/1: {\\"s\\":\\"sax\\",\\"accelerate\\":0}",
|
||||||
@@ -807,36 +824,36 @@ exports[`runs examples > example "echo" example index 0 1`] = `
|
|||||||
[
|
[
|
||||||
"0/1 -> 1/2: {\\"s\\":\\"bd\\"}",
|
"0/1 -> 1/2: {\\"s\\":\\"bd\\"}",
|
||||||
"1/2 -> 1/1: {\\"s\\":\\"sd\\"}",
|
"1/2 -> 1/1: {\\"s\\":\\"sd\\"}",
|
||||||
"-4166666666666667/12500000000000000 -> 8333333333333333/50000000000000000: {\\"s\\":\\"sd\\"}",
|
"-1/3 -> 1/6: {\\"s\\":\\"sd\\"}",
|
||||||
"8333333333333333/50000000000000000 -> 8333333333333333/12500000000000000: {\\"s\\":\\"bd\\"}",
|
"1/6 -> 2/3: {\\"s\\":\\"bd\\"}",
|
||||||
"8333333333333333/12500000000000000 -> 7291666666666667/6250000000000000: {\\"s\\":\\"sd\\"}",
|
"2/3 -> 7/6: {\\"s\\":\\"sd\\"}",
|
||||||
"-4166666666666667/25000000000000000 -> 8333333333333333/25000000000000000: {\\"s\\":\\"sd\\"}",
|
"-1/6 -> 1/3: {\\"s\\":\\"sd\\"}",
|
||||||
"8333333333333333/25000000000000000 -> 5208333333333333/6250000000000000: {\\"s\\":\\"bd\\"}",
|
"1/3 -> 5/6: {\\"s\\":\\"bd\\"}",
|
||||||
"5208333333333333/6250000000000000 -> 8333333333333333/6250000000000000: {\\"s\\":\\"sd\\"}",
|
"5/6 -> 4/3: {\\"s\\":\\"sd\\"}",
|
||||||
"1/1 -> 3/2: {\\"s\\":\\"bd\\"}",
|
"1/1 -> 3/2: {\\"s\\":\\"bd\\"}",
|
||||||
"3/2 -> 2/1: {\\"s\\":\\"sd\\"}",
|
"3/2 -> 2/1: {\\"s\\":\\"sd\\"}",
|
||||||
"8333333333333333/12500000000000000 -> 7291666666666667/6250000000000000: {\\"s\\":\\"sd\\"}",
|
"2/3 -> 7/6: {\\"s\\":\\"sd\\"}",
|
||||||
"7291666666666667/6250000000000000 -> 5208333333333333/3125000000000000: {\\"s\\":\\"bd\\"}",
|
"7/6 -> 5/3: {\\"s\\":\\"bd\\"}",
|
||||||
"5208333333333333/3125000000000000 -> 6770833333333333/3125000000000000: {\\"s\\":\\"sd\\"}",
|
"5/3 -> 13/6: {\\"s\\":\\"sd\\"}",
|
||||||
"5208333333333333/6250000000000000 -> 8333333333333333/6250000000000000: {\\"s\\":\\"sd\\"}",
|
"5/6 -> 4/3: {\\"s\\":\\"sd\\"}",
|
||||||
"8333333333333333/6250000000000000 -> 5729166666666667/3125000000000000: {\\"s\\":\\"bd\\"}",
|
"4/3 -> 11/6: {\\"s\\":\\"bd\\"}",
|
||||||
"5729166666666667/3125000000000000 -> 7291666666666667/3125000000000000: {\\"s\\":\\"sd\\"}",
|
"11/6 -> 7/3: {\\"s\\":\\"sd\\"}",
|
||||||
"2/1 -> 5/2: {\\"s\\":\\"bd\\"}",
|
"2/1 -> 5/2: {\\"s\\":\\"bd\\"}",
|
||||||
"5/2 -> 3/1: {\\"s\\":\\"sd\\"}",
|
"5/2 -> 3/1: {\\"s\\":\\"sd\\"}",
|
||||||
"5208333333333333/3125000000000000 -> 6770833333333333/3125000000000000: {\\"s\\":\\"sd\\"}",
|
"5/3 -> 13/6: {\\"s\\":\\"sd\\"}",
|
||||||
"6770833333333333/3125000000000000 -> 8333333333333333/3125000000000000: {\\"s\\":\\"bd\\"}",
|
"13/6 -> 8/3: {\\"s\\":\\"bd\\"}",
|
||||||
"8333333333333333/3125000000000000 -> 4947916666666667/1562500000000000: {\\"s\\":\\"sd\\"}",
|
"8/3 -> 19/6: {\\"s\\":\\"sd\\"}",
|
||||||
"5729166666666667/3125000000000000 -> 7291666666666667/3125000000000000: {\\"s\\":\\"sd\\"}",
|
"11/6 -> 7/3: {\\"s\\":\\"sd\\"}",
|
||||||
"7291666666666667/3125000000000000 -> 8854166666666667/3125000000000000: {\\"s\\":\\"bd\\"}",
|
"7/3 -> 17/6: {\\"s\\":\\"bd\\"}",
|
||||||
"8854166666666667/3125000000000000 -> 5208333333333333/1562500000000000: {\\"s\\":\\"sd\\"}",
|
"17/6 -> 10/3: {\\"s\\":\\"sd\\"}",
|
||||||
"3/1 -> 7/2: {\\"s\\":\\"bd\\"}",
|
"3/1 -> 7/2: {\\"s\\":\\"bd\\"}",
|
||||||
"7/2 -> 4/1: {\\"s\\":\\"sd\\"}",
|
"7/2 -> 4/1: {\\"s\\":\\"sd\\"}",
|
||||||
"8333333333333333/3125000000000000 -> 4947916666666667/1562500000000000: {\\"s\\":\\"sd\\"}",
|
"8/3 -> 19/6: {\\"s\\":\\"sd\\"}",
|
||||||
"4947916666666667/1562500000000000 -> 5729166666666667/1562500000000000: {\\"s\\":\\"bd\\"}",
|
"19/6 -> 11/3: {\\"s\\":\\"bd\\"}",
|
||||||
"5729166666666667/1562500000000000 -> 6510416666666667/1562500000000000: {\\"s\\":\\"sd\\"}",
|
"11/3 -> 25/6: {\\"s\\":\\"sd\\"}",
|
||||||
"8854166666666667/3125000000000000 -> 5208333333333333/1562500000000000: {\\"s\\":\\"sd\\"}",
|
"17/6 -> 10/3: {\\"s\\":\\"sd\\"}",
|
||||||
"5208333333333333/1562500000000000 -> 5989583333333333/1562500000000000: {\\"s\\":\\"bd\\"}",
|
"10/3 -> 23/6: {\\"s\\":\\"bd\\"}",
|
||||||
"5989583333333333/1562500000000000 -> 6770833333333333/1562500000000000: {\\"s\\":\\"sd\\"}",
|
"23/6 -> 13/3: {\\"s\\":\\"sd\\"}",
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@@ -1593,6 +1610,27 @@ exports[`runs examples > example "fastcat" example index 0 1`] = `
|
|||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "firstOf" example index 0 1`] = `
|
||||||
|
[
|
||||||
|
"3/4 -> 1/1: {\\"note\\":\\"c3\\"}",
|
||||||
|
"1/2 -> 3/4: {\\"note\\":\\"d3\\"}",
|
||||||
|
"1/4 -> 1/2: {\\"note\\":\\"e3\\"}",
|
||||||
|
"0/1 -> 1/4: {\\"note\\":\\"g3\\"}",
|
||||||
|
"1/1 -> 5/4: {\\"note\\":\\"c3\\"}",
|
||||||
|
"5/4 -> 3/2: {\\"note\\":\\"d3\\"}",
|
||||||
|
"3/2 -> 7/4: {\\"note\\":\\"e3\\"}",
|
||||||
|
"7/4 -> 2/1: {\\"note\\":\\"g3\\"}",
|
||||||
|
"2/1 -> 9/4: {\\"note\\":\\"c3\\"}",
|
||||||
|
"9/4 -> 5/2: {\\"note\\":\\"d3\\"}",
|
||||||
|
"5/2 -> 11/4: {\\"note\\":\\"e3\\"}",
|
||||||
|
"11/4 -> 3/1: {\\"note\\":\\"g3\\"}",
|
||||||
|
"3/1 -> 13/4: {\\"note\\":\\"c3\\"}",
|
||||||
|
"13/4 -> 7/2: {\\"note\\":\\"d3\\"}",
|
||||||
|
"7/2 -> 15/4: {\\"note\\":\\"e3\\"}",
|
||||||
|
"15/4 -> 4/1: {\\"note\\":\\"g3\\"}",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`runs examples > example "freq" example index 0 1`] = `
|
exports[`runs examples > example "freq" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"0/1 -> 1/4: {\\"freq\\":220,\\"s\\":\\"superzow\\"}",
|
"0/1 -> 1/4: {\\"freq\\":220,\\"s\\":\\"superzow\\"}",
|
||||||
@@ -1793,6 +1831,27 @@ exports[`runs examples > example "iterBack" example index 0 1`] = `
|
|||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "lastOf" example index 0 1`] = `
|
||||||
|
[
|
||||||
|
"0/1 -> 1/4: {\\"note\\":\\"c3\\"}",
|
||||||
|
"1/4 -> 1/2: {\\"note\\":\\"d3\\"}",
|
||||||
|
"1/2 -> 3/4: {\\"note\\":\\"e3\\"}",
|
||||||
|
"3/4 -> 1/1: {\\"note\\":\\"g3\\"}",
|
||||||
|
"1/1 -> 5/4: {\\"note\\":\\"c3\\"}",
|
||||||
|
"5/4 -> 3/2: {\\"note\\":\\"d3\\"}",
|
||||||
|
"3/2 -> 7/4: {\\"note\\":\\"e3\\"}",
|
||||||
|
"7/4 -> 2/1: {\\"note\\":\\"g3\\"}",
|
||||||
|
"2/1 -> 9/4: {\\"note\\":\\"c3\\"}",
|
||||||
|
"9/4 -> 5/2: {\\"note\\":\\"d3\\"}",
|
||||||
|
"5/2 -> 11/4: {\\"note\\":\\"e3\\"}",
|
||||||
|
"11/4 -> 3/1: {\\"note\\":\\"g3\\"}",
|
||||||
|
"15/4 -> 4/1: {\\"note\\":\\"c3\\"}",
|
||||||
|
"7/2 -> 15/4: {\\"note\\":\\"d3\\"}",
|
||||||
|
"13/4 -> 7/2: {\\"note\\":\\"e3\\"}",
|
||||||
|
"3/1 -> 13/4: {\\"note\\":\\"g3\\"}",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`runs examples > example "late" example index 0 1`] = `
|
exports[`runs examples > example "late" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"0/1 -> 1/2: {\\"s\\":\\"bd\\"}",
|
"0/1 -> 1/2: {\\"s\\":\\"bd\\"}",
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
# Strudel Workshop
|
||||||
|
|
||||||
|
This may become a resource to teach strudel in workshop format.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
From the root of the strudel repo:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm i # install strudel project dependencies
|
||||||
|
cd workshop && npm i # install workshop dependencies
|
||||||
|
npm run dev # run dev server
|
||||||
|
```
|
||||||
|
|
||||||
|
This assumes you have node 16+ installed.
|
||||||
|
|
||||||
|
## How to write
|
||||||
|
|
||||||
|
While running the dev server, go to `workshop.mdx` to write!
|
||||||
|
When the file is saved, the browser will hot reload the file and reveal the changes instantly.
|
||||||
|
|
||||||
|
You can use normal markdown + JSX, which enables using the MiniRepl component.
|
||||||
|
You could also add any react component and import it to the mdx file.
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
Running
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
..will output a single `index.html` file to `dist`. This file can either be opened directly in the browser (locally) or uploaded to some server.
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Strudel Workshop</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
<script type="module" src="/src/main.jsx"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Generated
+5982
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"name": "workshop",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.0.0",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite --open",
|
||||||
|
"build": "vite build",
|
||||||
|
"preview": "vite preview"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"react": "^17.0.2",
|
||||||
|
"react-dom": "^17.0.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@mdx-js/mdx": "^1.6.22",
|
||||||
|
"@mdx-js/react": "^1.6.22",
|
||||||
|
"@tailwindcss/typography": "^0.5.8",
|
||||||
|
"@types/react": "^18.0.24",
|
||||||
|
"@types/react-dom": "^18.0.8",
|
||||||
|
"@vitejs/plugin-react": "^2.2.0",
|
||||||
|
"autoprefixer": "^10.4.13",
|
||||||
|
"postcss": "^8.4.19",
|
||||||
|
"tailwindcss": "^3.2.4",
|
||||||
|
"vite": "^3.2.3",
|
||||||
|
"vite-plugin-mdx": "^3.5.11",
|
||||||
|
"vite-plugin-singlefile": "^0.13.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
module.exports = {
|
||||||
|
plugins: {
|
||||||
|
tailwindcss: {},
|
||||||
|
autoprefixer: {},
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import { initAudioOnFirstClick } from '@strudel.cycles/webaudio';
|
||||||
|
import Workshop from './workshop.mdx';
|
||||||
|
|
||||||
|
initAudioOnFirstClick();
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
return (
|
||||||
|
<div className="bg-slate-900 w-screen h-screen overflow-auto">
|
||||||
|
<main className="p-4 pl-6 max-w-3xl prose prose-invert">
|
||||||
|
<Workshop />
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App;
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { evalScope, controls } from '@strudel.cycles/core';
|
||||||
|
import { MiniRepl as _MiniRepl } from '@strudel.cycles/react';
|
||||||
|
import { samples } from '@strudel.cycles/webaudio';
|
||||||
|
import '@strudel.cycles/react/dist/style.css';
|
||||||
|
|
||||||
|
samples('github:tidalcycles/Dirt-Samples/master')
|
||||||
|
|
||||||
|
evalScope(
|
||||||
|
controls,
|
||||||
|
import('@strudel.cycles/core'),
|
||||||
|
// import('@strudel.cycles/tone'),
|
||||||
|
import('@strudel.cycles/tonal'),
|
||||||
|
import('@strudel.cycles/mini'),
|
||||||
|
import('@strudel.cycles/midi'),
|
||||||
|
// import('@strudel.cycles/xen'),
|
||||||
|
import('@strudel.cycles/webaudio'),
|
||||||
|
import('@strudel.cycles/osc'),
|
||||||
|
);
|
||||||
|
|
||||||
|
export function MiniRepl({ tune }) {
|
||||||
|
return <_MiniRepl tune={tune} hideOutsideView={true} />;
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
|
import App from './App';
|
||||||
|
import './index.css';
|
||||||
|
|
||||||
|
ReactDOM.render(
|
||||||
|
<React.StrictMode>
|
||||||
|
<App />
|
||||||
|
</React.StrictMode>,
|
||||||
|
document.getElementById('root'),
|
||||||
|
);
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import { MiniRepl } from './MiniRepl';
|
||||||
|
|
||||||
|
# Workshop
|
||||||
|
|
||||||
|
> This is a starter project for any type of teaching material using strudel!
|
||||||
|
|
||||||
|
## What is Strudel?
|
||||||
|
|
||||||
|
1. A pastry made with fruit or cheese rolled up in layers of thin sheets of dough and then baked.
|
||||||
|
2. a pastry made from multiple, thin layers of dough rolled up and filled with fruit, etc.
|
||||||
|
3. thin sheet of filled dough rolled and baked
|
||||||
|
|
||||||
|
## Some REPLs:
|
||||||
|
|
||||||
|
Small REPL:
|
||||||
|
|
||||||
|
<MiniRepl tune={`s("bd sd,hh*8")`} />
|
||||||
|
|
||||||
|
Big REPL:
|
||||||
|
|
||||||
|
<MiniRepl
|
||||||
|
tune={`await samples({
|
||||||
|
bd: ['bd/BT0AADA.wav','bd/BT0AAD0.wav','bd/BT0A0DA.wav','bd/BT0A0D3.wav','bd/BT0A0D0.wav','bd/BT0A0A7.wav'],
|
||||||
|
sd: ['sd/rytm-01-classic.wav','sd/rytm-00-hard.wav'],
|
||||||
|
hh: ['hh27/000_hh27closedhh.wav','hh/000_hh3closedhh.wav'],
|
||||||
|
}, 'github:tidalcycles/Dirt-Samples/master/');
|
||||||
|
stack(
|
||||||
|
s("bd,[~ <sd!3 sd(3,4,2)>],hh(3,4)") // drums
|
||||||
|
.speed(perlin.range(.7,.9)) // random sample speed variation
|
||||||
|
,"<a1 b1\*2 a1(3,8) e2>" // bassline
|
||||||
|
.off(1/8,x=>x.add(12).degradeBy(.5)) // random octave jumps
|
||||||
|
.add(perlin.range(0,.5)) // random pitch variation
|
||||||
|
.superimpose(add(.05)) // add second, slightly detuned voice
|
||||||
|
.n() // wrap in "n"
|
||||||
|
.decay(.15).sustain(0) // make each note of equal length
|
||||||
|
.s('sawtooth') // waveform
|
||||||
|
.gain(.4) // turn down
|
||||||
|
.cutoff(sine.slow(7).range(300,5000)) // automate cutoff
|
||||||
|
,"<Am7!3 <Em7 E7b13 Em7 Ebm7b5>>".voicings() // chords
|
||||||
|
.superimpose(x=>x.add(.04)) // add second, slightly detuned voice
|
||||||
|
.add(perlin.range(0,.5)) // random pitch variation
|
||||||
|
.n() // wrap in "n"
|
||||||
|
.s('sawtooth') // waveform
|
||||||
|
.gain(.16) // turn down
|
||||||
|
.cutoff(500) // fixed cutoff
|
||||||
|
.attack(1) // slowly fade in
|
||||||
|
)
|
||||||
|
.slow(3/2)`}
|
||||||
|
/>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
module.exports = {
|
||||||
|
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx,mdx}'],
|
||||||
|
theme: {
|
||||||
|
extend: {},
|
||||||
|
},
|
||||||
|
plugins: [require('@tailwindcss/typography')],
|
||||||
|
};
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import react from '@vitejs/plugin-react';
|
||||||
|
import _mdx from 'vite-plugin-mdx';
|
||||||
|
import { viteSingleFile } from 'vite-plugin-singlefile';
|
||||||
|
// import remarkToc from 'remark-toc';
|
||||||
|
// import rehypeSlug from 'rehype-slug';
|
||||||
|
// import rehypeAutolinkHeadings from 'rehype-autolink-headings';
|
||||||
|
|
||||||
|
const mdx = _mdx.default || _mdx;
|
||||||
|
// `options` are passed to `@mdx-js/mdx`
|
||||||
|
const options = {
|
||||||
|
// See https://mdxjs.com/advanced/plugins
|
||||||
|
remarkPlugins: [
|
||||||
|
// remarkToc,
|
||||||
|
// E.g. `remark-frontmatter`
|
||||||
|
],
|
||||||
|
rehypePlugins: [
|
||||||
|
// rehypeSlug, rehypeAutolinkHeadings
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
// https://vitejs.dev/config/
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [react(), mdx(options), viteSingleFile()],
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user