This commit is contained in:
Felix Roos 2022-02-19 21:51:58 +01:00
parent ecec96c943
commit d3dce4c662
4 changed files with 84 additions and 8 deletions

View File

@ -187,6 +187,9 @@ class Pattern {
_filterValues(value_test) {
return new Pattern((span) => this.query(span).filter((hap) => value_test(hap.value)));
}
_removeUndefineds() {
return this._filterValues((val) => val != void 0);
}
onsetsOnly() {
return this._filterEvents((hap) => hap.hasOnset());
}
@ -351,6 +354,20 @@ class Pattern {
_late(offset) {
return this._early(0 - offset);
}
struct(...binary_pats) {
const binary_pat = sequence(binary_pats);
return binary_pat.fmap((b) => (val) => b ? val : void 0).appLeft(this)._removeUndefineds();
}
mask(...binary_pats) {
const binary_pat = sequence(binary_pats);
return binary_pat.fmap((b) => (val) => b ? val : void 0).appRight(this)._removeUndefineds();
}
invert() {
return this.fmap((x) => !x);
}
inv() {
return this.invert();
}
when(binary_pat, func) {
const true_pat = binary_pat._filterValues(id);
const false_pat = binary_pat._filterValues((val) => !val);
@ -546,6 +563,10 @@ const off = curry((t, f, pat) => pat.off(t, f));
const jux = curry((f, pat) => pat.jux(f));
const append = curry((a, pat) => pat.append(a));
const superimpose = curry((array, pat) => pat.superimpose(...array));
const struct = curry((a, pat) => pat.struct(a));
const mask = curry((a, pat) => pat.mask(a));
const invert = (pat) => pat.invert();
const inv = (pat) => pat.inv();
Pattern.prototype.composable = {fast, slow, early, late, superimpose};
export function makeComposable(func) {
Object.entries(Pattern.prototype.composable).forEach(([functionName, composable]) => {
@ -608,5 +629,9 @@ export {
off,
jux,
append,
superimpose
superimpose,
struct,
mask,
invert,
inv
};

View File

@ -7711,10 +7711,14 @@ synth('sawtooth16').autofilter('<1 4 8>'.m)`,
height: 150,
mdxType: "MiniRepl"
}), /*#__PURE__*/ _react1.mdx("p", null, `TODO: use range instead of octave.
TODO: find out why composition does not work`), /*#__PURE__*/ _react1.mdx("h2", null, `MIDI API`), /*#__PURE__*/ _react1.mdx("p", null, `TODO, see `, /*#__PURE__*/ _react1.mdx("a", {
TODO: find out why composition does not work`), /*#__PURE__*/ _react1.mdx("h2", null, `MIDI API`), /*#__PURE__*/ _react1.mdx("p", null, `Strudel also supports midi via `, /*#__PURE__*/ _react1.mdx("a", {
parentName: "p",
"href": "https://github.com/tidalcycles/strudel/blob/main/repl/src/midi.ts"
}, `https://github.com/tidalcycles/strudel/blob/main/repl/src/midi.ts`)), /*#__PURE__*/ _react1.mdx("h1", null, `Contributing`), /*#__PURE__*/ _react1.mdx("p", null, `Contributions of any sort are very welcome! You can contribute by editing `, /*#__PURE__*/ _react1.mdx("a", {
"href": "https://npmjs.com/package/webmidi"
}, `webmidi`), `.`), /*#__PURE__*/ _react1.mdx("h3", null, `midi(outputName?)`), /*#__PURE__*/ _react1.mdx("p", null, `Make sure to have a midi device connected or to use an IAC Driver.
If no outputName is given, it uses the first midi output it finds.`), /*#__PURE__*/ _react1.mdx("p", null, `Midi is currently not supported by the mini repl used here, but you can `, /*#__PURE__*/ _react1.mdx("a", {
parentName: "p",
"href": "https://strudel.tidalcycles.org/#c3RhY2soIjxDXjcgQTcgRG03IEc3PiIubS52b2ljaW5ncygpLCAnPEMzIEEyIEQzIEcyPicubSkKICAubWlkaSgp"
}, `open the midi example in the repl`), `.`), /*#__PURE__*/ _react1.mdx("p", null, `In the REPL, you will se a log of the available MIDI devices.`), /*#__PURE__*/ _react1.mdx("h1", null, `Contributing`), /*#__PURE__*/ _react1.mdx("p", null, `Contributions of any sort are very welcome! You can contribute by editing `, /*#__PURE__*/ _react1.mdx("a", {
parentName: "p",
"href": "https://github.com/tidalcycles/strudel/blob/main/repl/src/tutorial/tutorial.mdx"
}, `this file`), `.
@ -41875,6 +41879,14 @@ parcelHelpers.export(exports, "append", ()=>append
);
parcelHelpers.export(exports, "superimpose", ()=>superimpose
);
parcelHelpers.export(exports, "struct", ()=>struct
);
parcelHelpers.export(exports, "mask", ()=>mask
);
parcelHelpers.export(exports, "invert", ()=>invert
);
parcelHelpers.export(exports, "inv", ()=>inv
);
var _fractionJs = require("fraction.js");
var _fractionJsDefault = parcelHelpers.interopDefault(_fractionJs);
var _ramda = require("ramda"); // will remove this as soon as compose is implemented here
@ -42115,6 +42127,10 @@ class Pattern {
)
);
}
_removeUndefineds() {
return this._filterValues((val)=>val != undefined
);
}
onsetsOnly() {
// Returns a new pattern that will only return events where the start
// of the 'whole' timespan matches the start of the 'part'
@ -42309,6 +42325,27 @@ class Pattern {
// Equivalent of Tidal's ~> operator
return this._early(0 - offset);
}
struct(...binary_pats) {
// Re structure the pattern according to a binary pattern (false values are dropped)
const binary_pat = sequence(binary_pats);
return binary_pat.fmap((b)=>(val)=>b ? val : undefined
).appLeft(this)._removeUndefineds();
}
mask(...binary_pats) {
// Only let through parts of pattern corresponding to true values in the given binary pattern
const binary_pat = sequence(binary_pats);
return binary_pat.fmap((b)=>(val)=>b ? val : undefined
).appRight(this)._removeUndefineds();
}
invert() {
// Swap true/false in a binary pattern
return this.fmap((x)=>!x
);
}
inv() {
// alias for invert()
return this.invert();
}
when(binary_pat, func) {
//binary_pat = sequence(binary_pat)
const true_pat = binary_pat._filterValues(id);
@ -42424,10 +42461,12 @@ Pattern.prototype.factories = {
pr
};
// the magic happens in Pattern constructor. Keeping this in prototype enables adding methods from the outside (e.g. see tonal.ts)
// Elemental patterns
// Nothing
const silence = new Pattern((_)=>[]
);
function pure(value) {
// Returns a pattern that repeats the given value once per cycle
// A discrete value that repeats once per cycle
function query(span) {
return span.spanCycles.map((subspan)=>new Hap(_fractionJsDefault.default(subspan.begin).wholeCycle(), subspan, value)
);
@ -42435,13 +42474,16 @@ function pure(value) {
return new Pattern(query);
}
function steady(value) {
// A continuous value
return new Pattern((span)=>Hap(undefined, span, value)
);
}
function reify(thing) {
// Tunrs something into a pattern, unless it's already a pattern
if (thing?.constructor?.name == "Pattern") return thing;
return pure(thing);
}
// Basic functions for combining patterns
function stack(...pats) {
const reified = pats.map((pat)=>reify(pat)
);
@ -42489,6 +42531,7 @@ function cat(...pats) {
return fastcat(...pats);
}
function timeCat(...timepats) {
// Like cat, but where each step has a temporal 'weight'
const total = timepats.map((a)=>a[0]
).reduce((a, b)=>a.add(b)
, _fractionJsDefault.default(0));
@ -42581,6 +42624,14 @@ const append = curry((a, pat)=>pat.append(a)
);
const superimpose = curry((array, pat)=>pat.superimpose(...array)
);
const struct = curry((a, pat)=>pat.struct(a)
);
const mask = curry((a, pat)=>pat.mask(a)
);
const invert = (pat)=>pat.invert()
;
const inv = (pat)=>pat.inv()
;
// problem: curried functions with spread arguments must have pat at the beginning
// with this, we cannot keep the pattern open at the end.. solution for now: use array to keep using pat as last arg
// these are the core composable functions. they are extended with Pattern.prototype.define below
@ -108907,4 +108958,4 @@ exports.default = cx;
},{"@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}]},["3uVTb"], "3uVTb", "parcelRequire94c2")
//# sourceMappingURL=index.8b62917f.js.map
//# sourceMappingURL=index.dc15e374.js.map

File diff suppressed because one or more lines are too long

View File

@ -11,6 +11,6 @@
<body>
<div id="root"></div>
<noscript>You need to enable JavaScript to run this app.</noscript>
<script src="/tutorial/index.8b62917f.js" defer=""></script>
<script src="/tutorial/index.dc15e374.js" defer=""></script>
</body>
</html>