doc: random functions

This commit is contained in:
Felix Roos 2022-09-14 23:16:24 +02:00
parent a022e5bb93
commit ce91d36b7a
2 changed files with 172 additions and 2 deletions

View File

@ -5,7 +5,7 @@ This program is free software: you can redistribute it and/or modify it under th
*/ */
import { Hap } from './hap.mjs'; import { Hap } from './hap.mjs';
import { Pattern, fastcat, reify, silence, stack } from './pattern.mjs'; import { Pattern, fastcat, reify, silence, stack, isPattern } from './pattern.mjs';
import Fraction from './fraction.mjs'; import Fraction from './fraction.mjs';
import { id } from './util.mjs'; import { id } from './util.mjs';
@ -233,16 +233,44 @@ Pattern.prototype._degradeByWith = function (withPat, x) {
* @param {number} amount - a number between 0 and 1 * @param {number} amount - a number between 0 and 1
* @returns Pattern * @returns Pattern
* @example * @example
* s("hh*8").degradeBy(0.5).out() * s("hh*8").degradeBy(0.2).out()
*/ */
Pattern.prototype._degradeBy = function (x) { Pattern.prototype._degradeBy = function (x) {
return this._degradeByWith(rand, x); return this._degradeByWith(rand, x);
}; };
/**
*
* Randomly removes 50% of events from the pattern. Shorthand for `.degradeBy(0.5)`
*
* @name degrade
* @memberof Pattern
* @returns Pattern
* @example
* s("hh*8").degrade().out()
*/
Pattern.prototype.degrade = function () { Pattern.prototype.degrade = function () {
return this._degradeBy(0.5); return this._degradeBy(0.5);
}; };
/**
* Inverse of {@link Pattern#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).
*
* @name undegradeBy
* @memberof Pattern
* @param {number} amount - a number between 0 and 1
* @returns Pattern
* @example
* s("hh*8").undegradeBy(0.2).out()
* @example
* stack(
* s("hh*8").undegradeBy(0.2),
* s("bd*8").degradeBy(0.8)
* ).out()
*/
Pattern.prototype._undegradeBy = function (x) { Pattern.prototype._undegradeBy = function (x) {
return this._degradeByWith( return this._degradeByWith(
rand.fmap((r) => 1 - r), rand.fmap((r) => 1 - r),
@ -258,6 +286,25 @@ Pattern.prototype._sometimesBy = function (x, func) {
return stack(this._degradeBy(x), func(this._undegradeBy(1 - x))); return stack(this._degradeBy(x), func(this._undegradeBy(1 - x)));
}; };
// https://github.com/tidalcycles/strudel/discussions/198
/* Pattern.prototype._sometimesBy = function (x, other) {
other = typeof other === 'function' ? other(this._undegradeBy(1 - x)) : reify(other)._undegradeBy(1 - x);
return stack(this._degradeBy(x), other);
}; */
/**
*
* Randomly applies the given function by the given probability.
* Similar to {@link Pattern#someCyclesBy}
*
* @name sometimesBy
* @memberof Pattern
* @param {number | Pattern} probability - a number between 0 and 1
* @param {function} function - the transformation to apply
* @returns Pattern
* @example
* s("hh(3,8)").sometimesBy(.4, x=>x.speed("0.5")).out()
*/
Pattern.prototype.sometimesBy = function (patx, func) { Pattern.prototype.sometimesBy = function (patx, func) {
const pat = this; const pat = this;
return reify(patx) return reify(patx)
@ -265,6 +312,7 @@ Pattern.prototype.sometimesBy = function (patx, func) {
.innerJoin(); .innerJoin();
}; };
// why does this exist? it is identical to sometimesBy
Pattern.prototype._sometimesByPre = function (x, func) { Pattern.prototype._sometimesByPre = function (x, func) {
return stack(this._degradeBy(x), func(this).undegradeBy(1 - x)); return stack(this._degradeBy(x), func(this).undegradeBy(1 - x));
}; };
@ -276,6 +324,17 @@ Pattern.prototype.sometimesByPre = function (patx, func) {
.innerJoin(); .innerJoin();
}; };
/**
*
* Applies the given function with a 50% chance
*
* @name sometimes
* @memberof Pattern
* @param {function} function - the transformation to apply
* @returns Pattern
* @example
* s("hh*4").sometimes(x=>x.speed("0.5")).out()
*/
Pattern.prototype.sometimes = function (func) { Pattern.prototype.sometimes = function (func) {
return this._sometimesBy(0.5, func); return this._sometimesBy(0.5, func);
}; };
@ -291,6 +350,19 @@ Pattern.prototype._someCyclesBy = function (x, func) {
); );
}; };
/**
*
* Randomly applies the given function by the given probability on a cycle by cycle basis.
* Similar to {@link Pattern#sometimesBy}
*
* @name someCyclesBy
* @memberof Pattern
* @param {number | Pattern} probability - a number between 0 and 1
* @param {function} function - the transformation to apply
* @returns Pattern
* @example
* s("hh(3,8)").someCyclesBy(.3, x=>x.speed("0.5")).out()
*/
Pattern.prototype.someCyclesBy = function (patx, func) { Pattern.prototype.someCyclesBy = function (patx, func) {
const pat = this; const pat = this;
return reify(patx) return reify(patx)
@ -298,30 +370,100 @@ Pattern.prototype.someCyclesBy = function (patx, func) {
.innerJoin(); .innerJoin();
}; };
/**
*
* Shorthand for `.someCyclesBy(0.5, fn)`
*
* @name someCycles
* @memberof Pattern
* @returns Pattern
* @example
* s("hh(3,8)").someCycles(x=>x.speed("0.5")).out()
*/
Pattern.prototype.someCycles = function (func) { Pattern.prototype.someCycles = function (func) {
return this._someCyclesBy(0.5, func); return this._someCyclesBy(0.5, func);
}; };
/**
*
* Shorthand for `.sometimesBy(0.75, fn)`
*
* @name often
* @memberof Pattern
* @returns Pattern
* @example
* s("hh*8").often(x=>x.speed("0.5")).out()
*/
Pattern.prototype.often = function (func) { Pattern.prototype.often = function (func) {
return this.sometimesBy(0.75, func); return this.sometimesBy(0.75, func);
}; };
/**
*
* Shorthand for `.sometimesBy(0.25, fn)`
*
* @name rarely
* @memberof Pattern
* @returns Pattern
* @example
* s("hh*8").rarely(x=>x.speed("0.5")).out()
*/
Pattern.prototype.rarely = function (func) { Pattern.prototype.rarely = function (func) {
return this.sometimesBy(0.25, func); return this.sometimesBy(0.25, func);
}; };
/**
*
* Shorthand for `.sometimesBy(0.1, fn)`
*
* @name almostNever
* @memberof Pattern
* @returns Pattern
* @example
* s("hh*8").almostNever(x=>x.speed("0.5")).out()
*/
Pattern.prototype.almostNever = function (func) { Pattern.prototype.almostNever = function (func) {
return this.sometimesBy(0.1, func); return this.sometimesBy(0.1, func);
}; };
/**
*
* Shorthand for `.sometimesBy(0.9, fn)`
*
* @name almostAlways
* @memberof Pattern
* @returns Pattern
* @example
* s("hh*8").almostAlways(x=>x.speed("0.5")).out()
*/
Pattern.prototype.almostAlways = function (func) { Pattern.prototype.almostAlways = function (func) {
return this.sometimesBy(0.9, func); return this.sometimesBy(0.9, func);
}; };
/**
*
* Shorthand for `.sometimesBy(0, fn)` (never calls fn)
*
* @name never
* @memberof Pattern
* @returns Pattern
* @example
* s("hh*8").never(x=>x.speed("0.5")).out()
*/
Pattern.prototype.never = function (func) { Pattern.prototype.never = function (func) {
return this; return this;
}; };
/**
*
* Shorthand for `.sometimesBy(1, fn)` (always calls fn)
*
* @name always
* @memberof Pattern
* @returns Pattern
* @example
* s("hh*8").always(x=>x.speed("0.5")).out()
*/
Pattern.prototype.always = function (func) { Pattern.prototype.always = function (func) {
return func(this); return func(this);
}; };

View File

@ -450,8 +450,36 @@ Stacks the given pattern to the current pattern:
<MiniRepl tune={`"c4,eb4,g4".stack("bb4,d5")`} /> <MiniRepl tune={`"c4,eb4,g4".stack("bb4,d5")`} />
## Randomness
These methods add random behavior to your Patterns.
{{ 'Pattern.degradeBy' | jsdoc }} {{ 'Pattern.degradeBy' | jsdoc }}
{{ 'Pattern.degrade' | jsdoc }}
{{ 'Pattern.undegradeBy' | jsdoc }}
{{ 'Pattern.sometimesBy' | jsdoc }}
{{ 'Pattern.sometimes' | jsdoc }}
{{ 'Pattern.someCyclesBy' | jsdoc }}
{{ 'Pattern.someCycles' | jsdoc }}
{{ 'Pattern.often' | jsdoc }}
{{ 'Pattern.rarely' | jsdoc }}
{{ 'Pattern.almostNever' | jsdoc }}
{{ 'Pattern.almostAlways' | jsdoc }}
{{ 'Pattern.never' | jsdoc }}
{{ 'Pattern.always' | jsdoc }}
## Tone API ## Tone API
To make the sounds more interesting, we can use Tone.js instruments ands effects. To make the sounds more interesting, we can use Tone.js instruments ands effects.