Merge commit '83a46c68dc6583ad36b256bc0d03e0913ecbc1f0' into webaudio-compat

This commit is contained in:
Felix Roos 2022-04-18 18:33:47 +02:00
commit 3d74b8a2fa
18 changed files with 150 additions and 3657 deletions

View File

@ -1,16 +1,16 @@
{
"files": {
"main.css": "/static/css/main.0d689283.css",
"main.js": "/static/js/main.f7b8088f.js",
"main.js": "/static/js/main.df1472e5.js",
"static/js/787.1c52cb78.chunk.js": "/static/js/787.1c52cb78.chunk.js",
"static/media/logo.svg": "/static/media/logo.ac95051720b3dccfe511e0e02d8e1029.svg",
"index.html": "/index.html",
"main.0d689283.css.map": "/static/css/main.0d689283.css.map",
"main.f7b8088f.js.map": "/static/js/main.f7b8088f.js.map",
"main.df1472e5.js.map": "/static/js/main.df1472e5.js.map",
"787.1c52cb78.chunk.js.map": "/static/js/787.1c52cb78.chunk.js.map"
},
"entrypoints": [
"static/css/main.0d689283.css",
"static/js/main.f7b8088f.js"
"static/js/main.df1472e5.js"
]
}

View File

@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Strudel REPL"/><title>Strudel REPL</title><script defer="defer" src="/static/js/main.f7b8088f.js"></script><link href="/static/css/main.0d689283.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Strudel REPL"/><title>Strudel REPL</title><script defer="defer" src="/static/js/main.df1472e5.js"></script><link href="/static/css/main.0d689283.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>

File diff suppressed because one or more lines are too long

3
docs/static/js/main.df1472e5.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><link rel="icon" href="/tutorial/favicon.e3ab9dd9.ico"><link rel="stylesheet" type="text/css" href="/tutorial/index.757e9f9d.css"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="description" content="Strudel REPL"><title>Strudel Tutorial</title></head><body> <div id="root"></div> <noscript>You need to enable JavaScript to run this app.</noscript> <script src="/tutorial/index.36c08014.js" defer></script> </body></html>
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><link rel="icon" href="/tutorial/favicon.e3ab9dd9.ico"><link rel="stylesheet" type="text/css" href="/tutorial/index.757e9f9d.css"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="description" content="Strudel REPL"><title>Strudel Tutorial</title></head><body> <div id="root"></div> <noscript>You need to enable JavaScript to run this app.</noscript> <script src="/tutorial/index.a35b0e47.js" defer></script> </body></html>

3674
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -179,14 +179,16 @@ export class Pattern {
const query = function (state) {
const haps = [];
for (const hap_func of pat_func.query(state)) {
const event_vals = pat_val.query(state.setSpan(hap_func.part));
const event_vals = pat_val.query(state.setSpan(hap_func.wholeOrPart()));
for (const hap_val of event_vals) {
const new_whole = hap_func.whole;
const new_part = hap_func.part.intersection_e(hap_val.part);
const new_value = hap_func.value(hap_val.value);
const new_context = hap_val.combineContext(hap_func);
const hap = new Hap(new_whole, new_part, new_value, new_context);
haps.push(hap);
const new_part = hap_func.part.intersection(hap_val.part);
if (new_part) {
const new_value = hap_func.value(hap_val.value);
const new_context = hap_val.combineContext(hap_func);
const hap = new Hap(new_whole, new_part, new_value, new_context);
haps.push(hap);
}
}
}
return haps;
@ -200,14 +202,16 @@ export class Pattern {
const query = function (state) {
const haps = [];
for (const hap_val of pat_val.query(state)) {
const hap_funcs = pat_func.query(state.setSpan(hap_val.part));
const hap_funcs = pat_func.query(state.setSpan(hap_val.wholeOrPart()));
for (const hap_func of hap_funcs) {
const new_whole = hap_val.whole;
const new_part = hap_func.part.intersection_e(hap_val.part);
const new_value = hap_func.value(hap_val.value);
const new_context = hap_val.combineContext(hap_func);
const hap = new Hap(new_whole, new_part, new_value, new_context);
haps.push(hap);
const new_part = hap_func.part.intersection(hap_val.part);
if (new_part) {
const new_value = hap_func.value(hap_val.value);
const new_context = hap_val.combineContext(hap_func);
const hap = new Hap(new_whole, new_part, new_value, new_context);
haps.push(hap);
}
}
}
return haps;
@ -558,7 +562,7 @@ export class Pattern {
}
_segment(rate) {
return this.struct(pure(true).fast(rate));
return this.struct(pure(true)._fast(rate));
}
invert() {

View File

@ -5,7 +5,7 @@ import { id } from './util.mjs';
export function steady(value) {
// A continuous value
return new Pattern((span) => Hap(undefined, span, value));
return new Pattern((state) => [new Hap(undefined, state.span, value)]);
}
export const signal = (func) => {
@ -47,7 +47,7 @@ const timeToIntSeed = (x) => xorwise(Math.trunc(_frac(x / 300) * 536870912));
const intSeedToRand = (x) => (x % 536870912) / 536870912;
const timeToRand = (x) => intSeedToRand(timeToIntSeed(x));
const timeToRand = (x) => Math.abs(intSeedToRand(timeToIntSeed(x)));
const timeToRandsPrime = (seed, n) => {
const result = [];
@ -60,8 +60,7 @@ const timeToRandsPrime = (seed, n) => {
const timeToRands = (t, n) => timeToRandsPrime(timeToIntSeed(t), n);
export const rand2 = signal(timeToRand);
export const rand = rand2.fmap(Math.abs);
export const rand = signal(timeToRand);
export const _brandBy = (p) => rand.fmap((x) => x < p);
export const brandBy = (pPat) => reify(pPat).fmap(_brandBy).innerJoin();
@ -71,14 +70,37 @@ export const _irand = (i) => rand.fmap((x) => Math.trunc(x * i));
export const irand = (ipat) => reify(ipat).fmap(_irand).innerJoin();
export const chooseWith = (pat, xs) => {
xs = xs.map(reify);
if (xs.length == 0) {
return silence;
}
return pat.range(0, xs.length).fmap((i) => xs[Math.floor(i)]);
return pat.range(0, xs.length).fmap((i) => xs[Math.floor(i)]).outerJoin();
};
export const choose = (...xs) => chooseWith(rand, xs);
const _wchooseWith = function (pat, ...pairs) {
const values = pairs.map((pair) => reify(pair[0]));
const weights = [];
let accum = 0;
for (const pair of pairs) {
accum += pair[1];
weights.push(accum);
}
const total = accum;
const match = function(r) {
const find = r * total;
return values[weights.findIndex((x) => x > find, weights)];
};
return pat.fmap(match);
};
const wchooseWith = (...args) => _wchooseWith(...args).outerJoin()
export const wchoose = (...pairs) => wchooseWith(rand, ...pairs);
export const wchooseCycles = (...pairs) => _wchooseWith(rand, ...pairs).innerJoin();
export const perlinWith = (pat) => {
const pata = pat.fmap(Math.floor);
const patb = pat.fmap((t) => Math.floor(t) + 1);
@ -142,6 +164,24 @@ Pattern.prototype.sometimesPre = function (func) {
return this._sometimesByPre(0.5, func);
};
Pattern.prototype._someCyclesBy = function (x, func) {
return stack(
this._degradeByWith(rand._segment(1), x),
func(this._degradeByWith(rand.fmap((r) => 1 - r)._segment(1), 1 - x)),
);
};
Pattern.prototype.someCyclesBy = function (patx, func) {
const pat = this;
return reify(patx)
.fmap((x) => pat._someCyclesBy(x, func))
.innerJoin();
};
Pattern.prototype.someCycles = function (func) {
return this._someCyclesBy(0.5, func);
};
Pattern.prototype.often = function (func) {
return this.sometimesBy(0.75, func);
};

View File

@ -36,6 +36,9 @@ import {
id,
ply,
} from '../index.mjs';
import { steady } from '../signal.mjs';
//import { Time } from 'tone';
import pkg from 'tone';
const { Time } = pkg;
@ -108,6 +111,18 @@ describe('Hap', function () {
assert.deepStrictEqual(state3, { incrementme: 12 });
});
});
describe('wholeOrPart()', () => {
const ts1 = new TimeSpan(Fraction(0), Fraction(1));
const ts0_5 = new TimeSpan(Fraction(0), Fraction(0.5));
const continuousHap = new Hap(undefined, ts1, 'hello');
const discreteHap = new Hap(ts1, ts0_5, 'hello');
it('Can pick a whole', () => {
assert.deepStrictEqual(discreteHap.wholeOrPart(), ts1);
});
it('Can pick a part', () => {
assert.deepStrictEqual(continuousHap.wholeOrPart(), ts1);
});
});
});
describe('Pattern', function () {
@ -399,7 +414,7 @@ describe('Pattern', function () {
});
});
describe('struct()', function () {
it('Can restructure a pattern', function () {
it('Can restructure a discrete pattern', function () {
assert.deepStrictEqual(sequence('a', 'b').struct(sequence(true, true, true)).firstCycle(), [
hap(ts(0, third), ts(0, third), 'a'),
hap(ts(third, twothirds), ts(third, 0.5), 'a'),
@ -425,6 +440,9 @@ describe('Pattern', function () {
sequence('a', ['a', silence], 'a').firstCycle(),
);
});
it('Can structure a continuous pattern', () => {
assert.deepStrictEqual(steady('a').struct(true, [true, true]).firstCycle(), sequence('a', ['a', 'a']).firstCycle());
});
});
describe('mask()', function () {
it('Can fragment a pattern', function () {

View File

@ -81,8 +81,7 @@ export class TimeSpan {
// Like 'sect', but raises an exception if the timespans don't intersect.
const result = this.intersection(other);
if (result == undefined) {
// TODO - raise exception
// raise ValueError(f'TimeSpan {self} and TimeSpan {other} do not intersect')
throw 'TimeSpans do not intersect';
}
return result;
}

View File

@ -21,6 +21,7 @@
"algorave"
],
"author": "Felix Roos <flix91@gmail.com>",
"contributors": ["Alex McLean <alex@slab.org>"],
"license": "GPL-3.0-or-later",
"bugs": {
"url": "https://github.com/tidalcycles/strudel/issues"

View File

@ -1,6 +1,6 @@
{
"name": "@strudel.cycles/webaudio",
"version": "0.0.5",
"version": "0.0.6",
"description": "Web Audio helpers for Strudel",
"main": "index.mjs",
"directories": {

View File

@ -1,4 +1,5 @@
import ClockWorker from './clockworker.mjs';
import { State, TimeSpan } from '@strudel.cycles/core';
class Scheduler {
worker;