diff --git a/repl/src/tunes.ts b/repl/src/tunes.ts index 17c0e930..9147f4b8 100644 --- a/repl/src/tunes.ts +++ b/repl/src/tunes.ts @@ -593,3 +593,29 @@ stack( .legato(cosine.struct("x*8").add(4/5).mul(4/5).fast(8)) .velocity(sine.struct("x*8").add(3/5).mul(2/5).fast(8)) .tone((await piano()).chain(out())).fast(3/4)`; + +// iter, stut, stutWith +export const undergroundPlumber = `backgroundImage('https://images.nintendolife.com/news/2016/08/video_exploring_the_funky_inspiration_for_the_super_mario_bros_underground_theme/large.jpg',{ + className:'darken' +}) +const drums = await players({ + bd: 'bd/BT0A0D0.wav', + sn: 'sn/ST0T0S3.wav', + hh: 'hh/000_hh3closedhh.wav', + cp: 'cp/HANDCLP0.wav', +}, 'https://loophole-letters.vercel.app/samples/tidal/') +stack( +"< sn> hh".fast(4).slow(2).tone(drums.chain(vol(.5),out())), + stack( + "[c2 a1 bb1 ~] ~" + .stut(2, .6, 1/16) + .legato(.4) + .slow(2) + .tone(synth({...osc('sawtooth7'),...adsr(0,.3,0)}).chain(out())), + "[g2,[c3 eb3]]".iter(4) + .stutWith(4, 1/4, (x,n)=>x.transpose(n*12).velocity(Math.pow(.4,n))) + .legato(.1) + ) + .transpose("<0@2 5 0 7 5 0 -5>/2") + .pianoroll({minMidi:21,maxMidi:180, background:'transparent',inactive:'#3F8F90',active:'#DE3123'}) +)`; diff --git a/strudel.mjs b/strudel.mjs index aba06811..72a3fff3 100644 --- a/strudel.mjs +++ b/strudel.mjs @@ -9,6 +9,8 @@ const flatten = arr => [].concat(...arr) const id = a => a +const range = (min, max) => Array.from({ length: max - min + 1 }, (_, i) => i + min); + export function curry(func, overload) { const fn = function curried(...args) { if (args.length >= func.length) { @@ -713,6 +715,18 @@ class Pattern { return this.stack(...funcs.map((func) => func(this))); } + stutWith(times, time, func) { + return stack(...range(0, times - 1).map((i) => func(this.late(i * time), i))); + } + + stut(times, feedback, time) { + return this.stutWith(times, time, (pat, i) => pat.velocity(Math.pow(feedback, i))); + } + + iter(times) { + return slowcat(...range(0, times - 1).map((i) => this.early(i/times))); + } + edit(...funcs) { return stack(...funcs.map(func => func(this))); } @@ -1023,6 +1037,6 @@ export {Fraction, TimeSpan, Hap, Pattern, pure, stack, slowcat, fastcat, cat, timeCat, sequence, polymeter, pm, polyrhythm, pr, reify, silence, fast, slow, early, late, rev, add, sub, mul, div, union, every, when, off, jux, append, superimpose, - struct, mask, invert, inv, + struct, mask, invert, inv, id, range }