mirror of
https://codeberg.org/uzu/strudel
synced 2026-07-12 22:15:27 -04:00
Merge pull request #1363 from tidalcycles/berlinnoise
feat: berlin noise
This commit is contained in:
@@ -486,13 +486,34 @@ export const wchooseCycles = (...pairs) => _wchooseWith(rand.segment(1), ...pair
|
||||
|
||||
export const wrandcat = wchooseCycles;
|
||||
|
||||
// this function expects pat to be a pattern of floats...
|
||||
export const perlinWith = (pat) => {
|
||||
const pata = pat.fmap(Math.floor);
|
||||
const patb = pat.fmap((t) => Math.floor(t) + 1);
|
||||
function _perlin(t) {
|
||||
let ta = Math.floor(t);
|
||||
let tb = ta + 1;
|
||||
const smootherStep = (x) => 6.0 * x ** 5 - 15.0 * x ** 4 + 10.0 * x ** 3;
|
||||
const interp = (x) => (a) => (b) => a + smootherStep(x) * (b - a);
|
||||
return pat.sub(pata).fmap(interp).appBoth(pata.fmap(timeToRand)).appBoth(patb.fmap(timeToRand));
|
||||
const v = interp(t - ta)(timeToRand(ta))(timeToRand(tb));
|
||||
return v;
|
||||
}
|
||||
export const perlinWith = (tpat) => {
|
||||
return tpat.fmap(_perlin);
|
||||
};
|
||||
|
||||
function _berlin(t) {
|
||||
const prevRidgeStartIndex = Math.floor(t);
|
||||
const nextRidgeStartIndex = prevRidgeStartIndex + 1;
|
||||
|
||||
const prevRidgeBottomPoint = timeToRand(prevRidgeStartIndex);
|
||||
const nextRidgeTopPoint = timeToRand(nextRidgeStartIndex) + prevRidgeBottomPoint;
|
||||
|
||||
const currentPercent = (t - prevRidgeStartIndex) / (nextRidgeStartIndex - prevRidgeStartIndex);
|
||||
const interp = (a, b, t) => {
|
||||
return a + (b - a) * t;
|
||||
};
|
||||
return interp(prevRidgeBottomPoint, nextRidgeTopPoint, currentPercent) / 2;
|
||||
}
|
||||
|
||||
export const berlinWith = (tpat) => {
|
||||
return tpat.fmap(_berlin);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -506,6 +527,18 @@ export const perlinWith = (pat) => {
|
||||
*/
|
||||
export const perlin = perlinWith(time.fmap((v) => Number(v)));
|
||||
|
||||
/**
|
||||
* Generates a continuous pattern of [berlin noise](conceived by Jame Coyne and Jade Rowland as a joke but turned out to be surprisingly cool and useful,
|
||||
* like perlin noise but with sawtooth waves), in the range 0..1.
|
||||
*
|
||||
* @name berlin
|
||||
* @example
|
||||
* // ascending arpeggios
|
||||
* n("0!16".add(berlin.fast(4).mul(14))).scale("d:minor")
|
||||
*
|
||||
*/
|
||||
export const berlin = berlinWith(time.fmap((v) => Number(v)));
|
||||
|
||||
export const degradeByWith = register(
|
||||
'degradeByWith',
|
||||
(withPat, x, pat) => pat.fmap((a) => (_) => a).appLeft(withPat.filterValues((v) => v > x)),
|
||||
|
||||
@@ -882,7 +882,6 @@ class ByteBeatProcessor extends AudioWorkletProcessor {
|
||||
const funcValue = this.func(local_t);
|
||||
let signal = (funcValue & 255) / 127.5 - 1;
|
||||
const out = signal * 0.2;
|
||||
|
||||
for (let c = 0; c < output.length; c++) {
|
||||
//prevent speaker blowout via clipping if threshold exceeds
|
||||
output[c][i] = clamp(out, -0.4, 0.4);
|
||||
|
||||
@@ -1051,6 +1051,75 @@ exports[`runs examples > example "begin" example index 0 1`] = `
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "berlin" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/16 | note:D3 ]",
|
||||
"[ 1/16 → 1/8 | note:E3 ]",
|
||||
"[ 1/8 → 3/16 | note:F3 ]",
|
||||
"[ 3/16 → 1/4 | note:G3 ]",
|
||||
"[ 1/4 → 5/16 | note:A3 ]",
|
||||
"[ 5/16 → 3/8 | note:C4 ]",
|
||||
"[ 3/8 → 7/16 | note:D4 ]",
|
||||
"[ 7/16 → 1/2 | note:F4 ]",
|
||||
"[ 1/2 → 9/16 | note:D4 ]",
|
||||
"[ 9/16 → 5/8 | note:E4 ]",
|
||||
"[ 5/8 → 11/16 | note:E4 ]",
|
||||
"[ 11/16 → 3/4 | note:E4 ]",
|
||||
"[ 3/4 → 13/16 | note:F3 ]",
|
||||
"[ 13/16 → 7/8 | note:F3 ]",
|
||||
"[ 7/8 → 15/16 | note:F3 ]",
|
||||
"[ 15/16 → 1/1 | note:F3 ]",
|
||||
"[ 1/1 → 17/16 | note:E3 ]",
|
||||
"[ 17/16 → 9/8 | note:E3 ]",
|
||||
"[ 9/8 → 19/16 | note:E3 ]",
|
||||
"[ 19/16 → 5/4 | note:F3 ]",
|
||||
"[ 5/4 → 21/16 | note:E3 ]",
|
||||
"[ 21/16 → 11/8 | note:F3 ]",
|
||||
"[ 11/8 → 23/16 | note:G3 ]",
|
||||
"[ 23/16 → 3/2 | note:A3 ]",
|
||||
"[ 3/2 → 25/16 | note:A3 ]",
|
||||
"[ 25/16 → 13/8 | note:Bb3 ]",
|
||||
"[ 13/8 → 27/16 | note:Bb3 ]",
|
||||
"[ 27/16 → 7/4 | note:Bb3 ]",
|
||||
"[ 7/4 → 29/16 | note:F3 ]",
|
||||
"[ 29/16 → 15/8 | note:G3 ]",
|
||||
"[ 15/8 → 31/16 | note:Bb3 ]",
|
||||
"[ 31/16 → 2/1 | note:C4 ]",
|
||||
"[ 2/1 → 33/16 | note:C4 ]",
|
||||
"[ 33/16 → 17/8 | note:D4 ]",
|
||||
"[ 17/8 → 35/16 | note:F4 ]",
|
||||
"[ 35/16 → 9/4 | note:G4 ]",
|
||||
"[ 9/4 → 37/16 | note:Bb3 ]",
|
||||
"[ 37/16 → 19/8 | note:Bb3 ]",
|
||||
"[ 19/8 → 39/16 | note:Bb3 ]",
|
||||
"[ 39/16 → 5/2 | note:C4 ]",
|
||||
"[ 5/2 → 41/16 | note:F3 ]",
|
||||
"[ 41/16 → 21/8 | note:F3 ]",
|
||||
"[ 21/8 → 43/16 | note:G3 ]",
|
||||
"[ 43/16 → 11/4 | note:A3 ]",
|
||||
"[ 11/4 → 45/16 | note:A3 ]",
|
||||
"[ 45/16 → 23/8 | note:A3 ]",
|
||||
"[ 23/8 → 47/16 | note:A3 ]",
|
||||
"[ 47/16 → 3/1 | note:A3 ]",
|
||||
"[ 3/1 → 49/16 | note:E3 ]",
|
||||
"[ 49/16 → 25/8 | note:G3 ]",
|
||||
"[ 25/8 → 51/16 | note:Bb3 ]",
|
||||
"[ 51/16 → 13/4 | note:C4 ]",
|
||||
"[ 13/4 → 53/16 | note:D4 ]",
|
||||
"[ 53/16 → 27/8 | note:E4 ]",
|
||||
"[ 27/8 → 55/16 | note:G4 ]",
|
||||
"[ 55/16 → 7/2 | note:A4 ]",
|
||||
"[ 7/2 → 57/16 | note:Bb3 ]",
|
||||
"[ 57/16 → 29/8 | note:Bb3 ]",
|
||||
"[ 29/8 → 59/16 | note:C4 ]",
|
||||
"[ 59/16 → 15/4 | note:C4 ]",
|
||||
"[ 15/4 → 61/16 | note:F3 ]",
|
||||
"[ 61/16 → 31/8 | note:G3 ]",
|
||||
"[ 31/8 → 63/16 | note:G3 ]",
|
||||
"[ 63/16 → 4/1 | note:A3 ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "binary" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/3 | s:hh ]",
|
||||
|
||||
Reference in New Issue
Block a user