Merge pull request #199 from tidalcycles/docs-update

document random functions
This commit is contained in:
Felix Roos 2022-09-14 23:46:39 +02:00 committed by GitHub
commit f4c31bcf2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 213 additions and 9 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';
@ -156,8 +156,8 @@ export const chooseInWith = (pat, xs) => {
}; };
/** /**
* Chooses randomly from the given list of values. * Chooses randomly from the given list of elements.
* @param {...any} xs * @param {...any} xs values / patterns to choose from.
* @returns {Pattern} - a continuous pattern. * @returns {Pattern} - a continuous pattern.
*/ */
export const choose = (...xs) => chooseWith(rand, xs); export const choose = (...xs) => chooseWith(rand, xs);
@ -183,6 +183,14 @@ Pattern.prototype.choose2 = function (...xs) {
return chooseWith(this._fromBipolar(), xs); return chooseWith(this._fromBipolar(), xs);
}; };
/**
* Picks one of the elements at random each cycle.
* @returns {Pattern}
* @example
* chooseCycles("bd", "hh", "sd").s().fast(4).out()
* @example
* "bd | hh | sd".s().fast(4).out()
*/
export const chooseCycles = (...xs) => chooseInWith(rand.segment(1), xs); export const chooseCycles = (...xs) => chooseInWith(rand.segment(1), xs);
export const randcat = chooseCycles; export const randcat = chooseCycles;
@ -223,14 +231,53 @@ 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));
}; };
/**
* Randomly removes events from the pattern by a given amount.
* 0 = 0% chance of removal
* 1 = 100% chance of removal
*
* @name degradeBy
* @memberof Pattern
* @param {number} amount - a number between 0 and 1
* @returns Pattern
* @example
* s("hh*8").degradeBy(0.2).out()
* @example
* s("[hh?0.2]*8").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()
* @example
* s("[hh?]*8").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()
*/
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),
@ -246,6 +293,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)
@ -253,6 +319,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));
}; };
@ -264,6 +331,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);
}; };
@ -279,6 +357,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)
@ -286,30 +377,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

@ -38,7 +38,9 @@ export default defineConfig({
'@codemirror/commands', '@codemirror/commands',
'@lezer/highlight', '@lezer/highlight',
'@codemirror/language', '@codemirror/language',
'@uiw/codemirror-themes' '@uiw/codemirror-themes',
'@uiw/react-codemirror',
'@lezer/highlight',
], ],
}, },
target: 'esnext', target: 'esnext',

View File

@ -2,8 +2,8 @@ import { Tone } from '@strudel.cycles/tone';
import { evalScope } from '@strudel.cycles/eval'; import { evalScope } from '@strudel.cycles/eval';
import { MiniRepl as _MiniRepl } from '@strudel.cycles/react'; import { MiniRepl as _MiniRepl } from '@strudel.cycles/react';
import controls from '@strudel.cycles/core/controls.mjs'; import controls from '@strudel.cycles/core/controls.mjs';
import * as WebDirt from 'WebDirt';
import { loadWebDirt } from '@strudel.cycles/webdirt'; import { loadWebDirt } from '@strudel.cycles/webdirt';
import { samples } from '@strudel.cycles/webaudio';
export const defaultSynth = new Tone.PolySynth().chain(new Tone.Gain(0.5), Tone.Destination).set({ export const defaultSynth = new Tone.PolySynth().chain(new Tone.Gain(0.5), Tone.Destination).set({
oscillator: { type: 'triangle' }, oscillator: { type: 'triangle' },
@ -12,6 +12,15 @@ export const defaultSynth = new Tone.PolySynth().chain(new Tone.Gain(0.5), Tone.
}, },
}); });
samples(
{
bd: '808bd/BD0000.WAV',
sd: ['808sd/SD0010.WAV', '808sd/SD0050.WAV', '808sd/SD0000.WAV'],
hh: ['hh27/000_hh27closedhh.wav', 'hh/000_hh3closedhh.wav'],
},
'https://raw.githubusercontent.com/tidalcycles/Dirt-Samples/master/',
);
evalScope( evalScope(
Tone, Tone,
controls, controls,

View File

@ -450,6 +450,38 @@ 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.
{{ 'chooseCycles' | 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.