From ecc4e1803ceb244c4b75b73d3eb3c84157637d8a Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Thu, 27 Oct 2022 19:47:07 +0200 Subject: [PATCH] remove all occurrences of .out() --- packages/core/controls.mjs | 30 +++++----- packages/core/euclid.mjs | 4 +- packages/core/pattern.mjs | 62 +++++++++---------- packages/core/signal.mjs | 40 ++++++------- packages/embed/README.md | 1 - packages/embed/example.html | 1 - packages/webaudio/README.md | 12 ++-- packages/webaudio/sampler.mjs | 2 +- repl/src/tunes.mjs | 50 ++++++++-------- tutorial/tutorial.mdx | 109 ++++++++++++---------------------- 10 files changed, 139 insertions(+), 172 deletions(-) diff --git a/packages/core/controls.mjs b/packages/core/controls.mjs index 6b669660..a19931cf 100644 --- a/packages/core/controls.mjs +++ b/packages/core/controls.mjs @@ -23,7 +23,7 @@ const generic_params = [ * @name s * @param {string | Pattern} sound The sound / pattern of sounds to pick * @example - * s("bd hh").out() + * s("bd hh") * */ ['s', 's', 'sound'], @@ -67,7 +67,7 @@ const generic_params = [ * @name gain * @param {number | Pattern} amount gain. * @example - * s("hh*8").gain(".4!2 1 .4!2 1 .4 1").out() + * s("hh*8").gain(".4!2 1 .4!2 1 .4 1") * */ [ @@ -129,7 +129,7 @@ const generic_params = [ * @name bandf * @param {number | Pattern} frequency center frequency * @example - * s("bd sd,hh*3").bandf("<1000 2000 4000 8000>").out() + * s("bd sd,hh*3").bandf("<1000 2000 4000 8000>") * */ ['f', 'bandf', 'A pattern of numbers from 0 to 1. Sets the center frequency of the band-pass filter.'], @@ -140,7 +140,7 @@ const generic_params = [ * @name bandq * @param {number | Pattern} q q factor * @example - * s("bd sd").bandf(500).bandq("<0 1 2 3>").out() + * s("bd sd").bandf(500).bandq("<0 1 2 3>") * */ ['f', 'bandq', 'a pattern of anumbers from 0 to 1. Sets the q-factor of the band-pass filter.'], @@ -152,7 +152,7 @@ const generic_params = [ * @param {number | Pattern} amount between 0 and 1, where 1 is the length of the sample * @example * samples({ rave: 'rave/AREUREADY.wav' }, 'github:tidalcycles/Dirt-Samples/master/') - * s("rave").begin("<0 .25 .5 .75>").out() + * s("rave").begin("<0 .25 .5 .75>") * */ [ @@ -167,7 +167,7 @@ const generic_params = [ * @name end * @param {number | Pattern} length 1 = whole sample, .5 = half sample, .25 = quarter sample etc.. * @example - * s("bd*2,ho*4").end("<.1 .2 .5 1>").out() + * s("bd*2,ho*4").end("<.1 .2 .5 1>") * */ [ @@ -205,7 +205,7 @@ const generic_params = [ * @name crush * @param {number | Pattern} depth between 1 (for drastic reduction in bit-depth) to 16 (for barely no reduction). * @example - * s(",hh*3").fast(2).crush("<16 8 7 6 5 4 3 2>").out() + * s(",hh*3").fast(2).crush("<16 8 7 6 5 4 3 2>") * */ [ @@ -219,7 +219,7 @@ const generic_params = [ * @name coarse * @param {number | Pattern} factor 1 for original 2 for half, 3 for a third and so on. * @example - * s("bd sd,hh*4").coarse("<1 4 8 16 32>").out() + * s("bd sd,hh*4").coarse("<1 4 8 16 32>") * */ [ @@ -256,7 +256,7 @@ const generic_params = [ * @name cutoff * @param {number | Pattern} frequency audible between 0 and 20000 * @example - * s("bd sd,hh*3").cutoff("<4000 2000 1000 500 200 100>").out() + * s("bd sd,hh*3").cutoff("<4000 2000 1000 500 200 100>") * */ // TODO: add lpf synonym @@ -267,7 +267,7 @@ const generic_params = [ * @name hcutoff * @param {number | Pattern} frequency audible between 0 and 20000 * @example - * s("bd sd,hh*4").hcutoff("<4000 2000 1000 500 200 100>").out() + * s("bd sd,hh*4").hcutoff("<4000 2000 1000 500 200 100>") * */ // TODO: add hpf synonym @@ -282,7 +282,7 @@ const generic_params = [ * @name hresonance * @param {number | Pattern} q resonance factor between 0 and 1 * @example - * s("bd sd,hh*4").hcutoff(2000).hresonance("<0 10 20 30>").out() + * s("bd sd,hh*4").hcutoff(2000).hresonance("<0 10 20 30>") * */ [ @@ -297,7 +297,7 @@ const generic_params = [ * @name resonance * @param {number | Pattern} q resonance factor between 0 and 1 * @example - * s("bd sd,hh*4").cutoff(2000).resonance("<0 10 20 30>").out() + * s("bd sd,hh*4").cutoff(2000).resonance("<0 10 20 30>") * */ ['f', 'resonance', 'a pattern of numbers from 0 to 1. Specifies the resonance of the low-pass filter.'], @@ -496,7 +496,7 @@ const generic_params = [ * @name pan * @param {number | Pattern} pan between 0 and 1, from left to right (assuming stereo), once round a circle (assuming multichannel) * @example - * s("[bd hh]*2").pan("<.5 1 .5 0>").out() + * s("[bd hh]*2").pan("<.5 1 .5 0>") * */ [ @@ -599,7 +599,7 @@ const generic_params = [ * @name shape * @param {number | Pattern} distortion between 0 and 1 * @example - * s("bd sd,hh*4").shape("<0 .2 .4 .6 .8>").out() + * s("bd sd,hh*4").shape("<0 .2 .4 .6 .8>") * */ [ @@ -665,7 +665,7 @@ const generic_params = [ * @param {string | Pattern} vowel You can use a e i o u. * @example * note("c2 >").s('sawtooth') - * .vowel(">").out() + * .vowel(">") * */ [ diff --git a/packages/core/euclid.mjs b/packages/core/euclid.mjs index 96f5b40d..8cb36857 100644 --- a/packages/core/euclid.mjs +++ b/packages/core/euclid.mjs @@ -32,7 +32,7 @@ const euclid = (pulses, steps, rotation = 0) => { * @returns Pattern * @example * // The Cuban tresillo pattern. - * n("c3").euclid(3,8).out() + * n("c3").euclid(3,8) */ /** @@ -88,7 +88,7 @@ Pattern.prototype.euclid = function (pulses, steps, rotation = 0) { * @name euclidLegato * @memberof Pattern * @example - * n("g2").decay(.1).sustain(.3).euclidLegato(3,8).out() + * n("g2").decay(.1).sustain(.3).euclidLegato(3,8) */ Pattern.prototype.euclidLegato = function (pulses, steps, rotation = 0) { const bin_pat = euclid(pulses, steps, rotation); diff --git a/packages/core/pattern.mjs b/packages/core/pattern.mjs index 7c917be3..3750539b 100644 --- a/packages/core/pattern.mjs +++ b/packages/core/pattern.mjs @@ -524,7 +524,7 @@ export class Pattern { * @memberof Pattern * @returns Pattern * @example - * s("bd sd,hh*4").cutoff(sine.range(500,2000).slow(4)).out() + * s("bd sd,hh*4").cutoff(sine.range(500,2000).slow(4)) */ _range(min, max) { return this.mul(max - min).add(min); @@ -718,7 +718,7 @@ export class Pattern { * @example * "<0 2 4 6 ~ 4 ~ 2 0!3 ~!5>*4" * .layer(x=>x.add("0,2")) - * .scale('C minor').note().out() + * .scale('C minor').note() */ layer(...funcs) { return stack(...funcs.map((func) => func(this))); @@ -756,11 +756,13 @@ export class Pattern { const cycle = begin.sam(); const beginPos = begin.sub(cycle).div(factor).min(1); const endPos = end.sub(cycle).div(factor).min(1); - const newPart = new TimeSpan(cycle.add(beginPos), cycle.add(endPos)) - const newWhole = !hap.whole ? undefined : new TimeSpan( - newPart.begin.sub(begin.sub(hap.whole.begin).div(factor)), - newPart.end.add(hap.whole.end.sub(end).div(factor)) - ); + const newPart = new TimeSpan(cycle.add(beginPos), cycle.add(endPos)); + const newWhole = !hap.whole + ? undefined + : new TimeSpan( + newPart.begin.sub(begin.sub(hap.whole.begin).div(factor)), + newPart.end.add(hap.whole.end.sub(end).div(factor)), + ); return new Hap(newWhole, newPart, hap.value, hap.context); }; return this.withQuerySpan(qf)._withHap(ef)._splitQueries(); @@ -796,7 +798,7 @@ export class Pattern { * @param {number | Pattern} factor speed up factor * @returns Pattern * @example - * s(" hh").fast(2).out() // s("[ hh]*2").out() + * s(" hh").fast(2) // s("[ hh]*2") */ _fast(factor) { const fastQuery = this.withQueryTime((t) => t.mul(factor)); @@ -811,7 +813,7 @@ export class Pattern { * @param {number | Pattern} factor slow down factor * @returns Pattern * @example - * s(" hh").slow(2).out() // s("[ hh]/2").out() + * s(" hh").slow(2) // s("[ hh]/2") */ _slow(factor) { return this._fast(Fraction(1).div(factor)); @@ -841,7 +843,7 @@ export class Pattern { * .chop(4) * .rev() // reverse order of chops * .loopAt(4,1) // fit sample into 4 cycles - * .out() + * */ _chop(n) { const slices = Array.from({ length: n }, (x, i) => i); @@ -872,7 +874,7 @@ export class Pattern { * @param {number | Pattern} cycles number of cycles to nudge left * @returns Pattern * @example - * "bd ~".stack("hh ~".early(.1)).s().out() + * "bd ~".stack("hh ~".early(.1)).s() */ _early(offset) { offset = Fraction(offset); @@ -887,7 +889,7 @@ export class Pattern { * @param {number | Pattern} cycles number of cycles to nudge right * @returns Pattern * @example - * "bd ~".stack("hh ~".late(.1)).s().out() + * "bd ~".stack("hh ~".late(.1)).s() */ _late(offset) { offset = Fraction(offset); @@ -925,7 +927,7 @@ export class Pattern { * @example * "c3,eb3,g3" * .struct("x ~ x ~ ~ x ~ x ~ ~ ~ x ~ x ~ ~") - * .slow(4).note().out() + * .slow(4).note() */ // struct(...binary_pats) { // // Re structure the pattern according to a binary pattern (false values are dropped) @@ -1015,7 +1017,7 @@ export class Pattern { * @param {function} func function to apply * @returns Pattern * @example - * note("c3 d3 e3 g3").every(4, x=>x.rev()).out() + * note("c3 d3 e3 g3").every(4, x=>x.rev()) */ every(n, func) { const pat = this; @@ -1032,7 +1034,7 @@ export class Pattern { * @param {function} func function to apply * @returns Pattern * @example - * note("c3 d3 e3 g3").every(4, x=>x.rev()).out() + * note("c3 d3 e3 g3").every(4, x=>x.rev()) */ every(n, func) { const pat = this; @@ -1049,7 +1051,7 @@ export class Pattern { * @param {function} func function to apply * @returns Pattern * @example - * note("c3 d3 e3 g3").every(4, x=>x.rev()).out() + * note("c3 d3 e3 g3").every(4, x=>x.rev()) */ each(n, func) { const pat = this; @@ -1126,7 +1128,7 @@ export class Pattern { * @example * s("hh*2").stack( * n("c2(3,8)") - * ).out() + * ) */ stack(...pats) { return stack(this, ...pats); @@ -1143,7 +1145,7 @@ export class Pattern { * @example * s("hh*2").seq( * n("c2(3,8)") - * ).out() + * ) */ seq(...pats) { return sequence(this, ...pats); @@ -1156,7 +1158,7 @@ export class Pattern { * @example * s("hh*2").cat( * n("c2(3,8)") - * ).out() + * ) */ cat(...pats) { return cat(this, ...pats); @@ -1178,7 +1180,7 @@ export class Pattern { * @example * "<0 2 4 6 ~ 4 ~ 2 0!3 ~!5>*4" * .superimpose(x=>x.add(2)) - * .scale('C minor').note().out() + * .scale('C minor').note() */ superimpose(...funcs) { return this.stack(...funcs.map((func) => func(this))); @@ -1203,7 +1205,7 @@ export class Pattern { * @example * "<0 [2 4]>" * .echoWith(4, 1/8, (p,n) => p.add(n*2)) - * .scale('C minor').note().legato(.2).out() + * .scale('C minor').note().legato(.2) */ _echoWith(times, time, func) { return stack(...listRange(0, times - 1).map((i) => func(this.late(Fraction(time).mul(i)), i))); @@ -1218,7 +1220,7 @@ export class Pattern { * @param {number} time cycle offset between iterations * @param {number} feedback velocity multiplicator for each iteration * @example - * s("bd sd").echo(3, 1/6, .8).out() + * s("bd sd").echo(3, 1/6, .8) */ _echo(times, time, feedback) { return this._echoWith(times, time, (pat, i) => pat.velocity(Math.pow(feedback, i))); @@ -1230,7 +1232,7 @@ export class Pattern { * @memberof Pattern * @returns Pattern * @example - * note("0 1 2 3".scale('A minor')).iter(4).out() + * note("0 1 2 3".scale('A minor')).iter(4) */ iter(times, back = false) { return slowcat(...listRange(0, times - 1).map((i) => (back ? this.late(i / times) : this.early(i / times)))); @@ -1242,7 +1244,7 @@ export class Pattern { * @memberof Pattern * @returns Pattern * @example - * note("0 1 2 3".scale('A minor')).iterBack(4).out() + * note("0 1 2 3".scale('A minor')).iterBack(4) */ iterBack(times) { return this.iter(times, true); @@ -1254,7 +1256,7 @@ export class Pattern { * @memberof Pattern * @returns Pattern * @example - * "0 1 2 3".chunk(4, x=>x.add(7)).scale('A minor').note().out() + * "0 1 2 3".chunk(4, x=>x.add(7)).scale('A minor').note() */ _chunk(n, func, back = false) { const binary = Array(n - 1).fill(false); @@ -1269,7 +1271,7 @@ export class Pattern { * @memberof Pattern * @returns Pattern * @example - * "0 1 2 3".chunkBack(4, x=>x.add(7)).scale('A minor').note().out() + * "0 1 2 3".chunkBack(4, x=>x.add(7)).scale('A minor').note() */ _chunkBack(n, func) { return this._chunk(n, func, true); @@ -1295,7 +1297,7 @@ export class Pattern { * @name legato * @memberof Pattern * @example - * n("c3 eb3 g3 c4").legato("<.25 .5 1 2>").out() + * n("c3 eb3 g3 c4").legato("<.25 .5 1 2>") */ _legato(value) { return this.withHapSpan((span) => new TimeSpan(span.begin, span.begin.add(span.end.sub(span.begin).mul(value)))); @@ -1308,7 +1310,7 @@ export class Pattern { * @example * s("hh*8") * .gain(".4!2 1 .4!2 1 .4 1") - * .velocity(".4 1").out() + * .velocity(".4 1") */ _velocity(velocity) { return this._withContext((context) => ({ ...context, velocity: (context.velocity || 1) * velocity })); @@ -1321,7 +1323,7 @@ export class Pattern { * @returns Pattern * @example * samples({ rhodes: 'https://cdn.freesound.org/previews/132/132051_316502-lq.mp3' }) - * s("rhodes").loopAt(4,1).out() + * s("rhodes").loopAt(4,1) */ _loopAt(factor, cps = 1) { return this.speed((1 / factor) * cps) @@ -1411,7 +1413,7 @@ function _composeOp(a, b, func) { * @name mul * @memberof Pattern * @example - * "1 1.5 [1.66, <2 2.33>]".mul(150).freq().out() + * "1 1.5 [1.66, <2 2.33>]".mul(150).freq() */ mul: [(a, b) => a * b, num], /** diff --git a/packages/core/signal.mjs b/packages/core/signal.mjs index 8637c30e..a33e3bdb 100644 --- a/packages/core/signal.mjs +++ b/packages/core/signal.mjs @@ -120,7 +120,7 @@ const timeToRands = (t, n) => timeToRandsPrime(timeToIntSeed(t), n); * @name rand * @example * // randomly change the cutoff - * s("bd sd,hh*4").cutoff(rand.range(500,2000)).out() + * s("bd sd,hh*4").cutoff(rand.range(500,2000)) * */ export const rand = signal(timeToRand); @@ -142,7 +142,7 @@ export const _irand = (i) => rand.fmap((x) => Math.trunc(x * i)); * @param {number} n max value (exclusive) * @example * // randomly select scale notes from 0 - 7 (= C to C) - * irand(8).struct("x(3,8)").scale('C minor').note().out() + * irand(8).struct("x(3,8)").scale('C minor').note() * */ export const irand = (ipat) => reify(ipat).fmap(_irand).innerJoin(); @@ -208,9 +208,9 @@ Pattern.prototype.choose2 = function (...xs) { * Picks one of the elements at random each cycle. * @returns {Pattern} * @example - * chooseCycles("bd", "hh", "sd").s().fast(4).out() + * chooseCycles("bd", "hh", "sd").s().fast(4) * @example - * "bd | hh | sd".s().fast(4).out() + * "bd | hh | sd".s().fast(4) */ export const chooseCycles = (...xs) => chooseInWith(rand.segment(1), xs); @@ -252,7 +252,7 @@ export const perlinWith = (pat) => { * @name perlin * @example * // randomly change the cutoff - * s("bd sd,hh*4").cutoff(perlin.range(500,2000)).out() + * s("bd sd,hh*4").cutoff(perlin.range(500,2000)) * */ export const perlin = perlinWith(time); @@ -271,9 +271,9 @@ Pattern.prototype._degradeByWith = function (withPat, x) { * @param {number} amount - a number between 0 and 1 * @returns Pattern * @example - * s("hh*8").degradeBy(0.2).out() + * s("hh*8").degradeBy(0.2) * @example - * s("[hh?0.2]*8").out() + * s("[hh?0.2]*8") */ Pattern.prototype._degradeBy = function (x) { return this._degradeByWith(rand, x); @@ -287,9 +287,9 @@ Pattern.prototype._degradeBy = function (x) { * @memberof Pattern * @returns Pattern * @example - * s("hh*8").degrade().out() + * s("hh*8").degrade() * @example - * s("[hh?]*8").out() + * s("[hh?]*8") */ Pattern.prototype.degrade = function () { return this._degradeBy(0.5); @@ -306,7 +306,7 @@ Pattern.prototype.degrade = function () { * @param {number} amount - a number between 0 and 1 * @returns Pattern * @example - * s("hh*8").undegradeBy(0.2).out() + * s("hh*8").undegradeBy(0.2) */ Pattern.prototype._undegradeBy = function (x) { return this._degradeByWith( @@ -340,7 +340,7 @@ Pattern.prototype._sometimesBy = function (x, func) { * @param {function} function - the transformation to apply * @returns Pattern * @example - * s("hh(3,8)").sometimesBy(.4, x=>x.speed("0.5")).out() + * s("hh(3,8)").sometimesBy(.4, x=>x.speed("0.5")) */ Pattern.prototype.sometimesBy = function (patx, func) { const pat = this; @@ -370,7 +370,7 @@ Pattern.prototype.sometimesByPre = function (patx, func) { * @param {function} function - the transformation to apply * @returns Pattern * @example - * s("hh*4").sometimes(x=>x.speed("0.5")).out() + * s("hh*4").sometimes(x=>x.speed("0.5")) */ Pattern.prototype.sometimes = function (func) { return this._sometimesBy(0.5, func); @@ -398,7 +398,7 @@ Pattern.prototype._someCyclesBy = function (x, func) { * @param {function} function - the transformation to apply * @returns Pattern * @example - * s("hh(3,8)").someCyclesBy(.3, x=>x.speed("0.5")).out() + * s("hh(3,8)").someCyclesBy(.3, x=>x.speed("0.5")) */ Pattern.prototype.someCyclesBy = function (patx, func) { const pat = this; @@ -415,7 +415,7 @@ Pattern.prototype.someCyclesBy = function (patx, func) { * @memberof Pattern * @returns Pattern * @example - * s("hh(3,8)").someCycles(x=>x.speed("0.5")).out() + * s("hh(3,8)").someCycles(x=>x.speed("0.5")) */ Pattern.prototype.someCycles = function (func) { return this._someCyclesBy(0.5, func); @@ -429,7 +429,7 @@ Pattern.prototype.someCycles = function (func) { * @memberof Pattern * @returns Pattern * @example - * s("hh*8").often(x=>x.speed("0.5")).out() + * s("hh*8").often(x=>x.speed("0.5")) */ Pattern.prototype.often = function (func) { return this.sometimesBy(0.75, func); @@ -443,7 +443,7 @@ Pattern.prototype.often = function (func) { * @memberof Pattern * @returns Pattern * @example - * s("hh*8").rarely(x=>x.speed("0.5")).out() + * s("hh*8").rarely(x=>x.speed("0.5")) */ Pattern.prototype.rarely = function (func) { return this.sometimesBy(0.25, func); @@ -457,7 +457,7 @@ Pattern.prototype.rarely = function (func) { * @memberof Pattern * @returns Pattern * @example - * s("hh*8").almostNever(x=>x.speed("0.5")).out() + * s("hh*8").almostNever(x=>x.speed("0.5")) */ Pattern.prototype.almostNever = function (func) { return this.sometimesBy(0.1, func); @@ -471,7 +471,7 @@ Pattern.prototype.almostNever = function (func) { * @memberof Pattern * @returns Pattern * @example - * s("hh*8").almostAlways(x=>x.speed("0.5")).out() + * s("hh*8").almostAlways(x=>x.speed("0.5")) */ Pattern.prototype.almostAlways = function (func) { return this.sometimesBy(0.9, func); @@ -485,7 +485,7 @@ Pattern.prototype.almostAlways = function (func) { * @memberof Pattern * @returns Pattern * @example - * s("hh*8").never(x=>x.speed("0.5")).out() + * s("hh*8").never(x=>x.speed("0.5")) */ Pattern.prototype.never = function (func) { return this; @@ -499,7 +499,7 @@ Pattern.prototype.never = function (func) { * @memberof Pattern * @returns Pattern * @example - * s("hh*8").always(x=>x.speed("0.5")).out() + * s("hh*8").always(x=>x.speed("0.5")) */ Pattern.prototype.always = function (func) { return func(this); diff --git a/packages/embed/README.md b/packages/embed/README.md index c3b7f3ee..b0ccf52b 100644 --- a/packages/embed/README.md +++ b/packages/embed/README.md @@ -18,7 +18,6 @@ Either install with `npm i @strudel.cycles/embed` or just use a cdn to import th .legato(sine.range(0.3, 2).slow(28)) .wave("sawtooth square".fast(2)) .filter('lowpass', cosine.range(500,4000).slow(16)) - .out() .pianoroll({minMidi:20,maxMidi:120,background:'#202124'}) --> diff --git a/packages/embed/example.html b/packages/embed/example.html index 820422b4..9e6fca15 100644 --- a/packages/embed/example.html +++ b/packages/embed/example.html @@ -10,7 +10,6 @@ .legato(sine.range(0.3, 2).slow(28)) .wave("sawtooth square".fast(2)) .filter('lowpass', cosine.range(500,4000).slow(16)) - .out() .pianoroll({minMidi:20,maxMidi:120,background:'#202124'}) --> diff --git a/packages/webaudio/README.md b/packages/webaudio/README.md index 6db6c1fa..e91086cd 100644 --- a/packages/webaudio/README.md +++ b/packages/webaudio/README.md @@ -15,13 +15,13 @@ npm i @strudel.cycles/webaudio --save import { Scheduler, getAudioContext } from '@strudel.cycles/webaudio'; const scheduler = new Scheduler({ - audioContext: getAudioContext(), - interval: 0.1, - onEvent: (e) => e.context?.createAudioNode?.(e), - }); -const pattern = sequence([55, 99], 110).osc('sawtooth').out() + audioContext: getAudioContext(), + interval: 0.1, + onEvent: (e) => e.context?.createAudioNode?.(e), +}); +const pattern = sequence([55, 99], 110).osc('sawtooth'); scheduler.setPattern(pattern); -scheduler.start() +scheduler.start(); //scheduler.stop() ``` diff --git a/packages/webaudio/sampler.mjs b/packages/webaudio/sampler.mjs index 23b37b25..d3905c5b 100644 --- a/packages/webaudio/sampler.mjs +++ b/packages/webaudio/sampler.mjs @@ -98,7 +98,7 @@ export const loadGithubSamples = async (path, nameFn) => { * bd: '808bd/BD0000.WAV', * sd: '808sd/SD0010.WAV' * }, 'https://raw.githubusercontent.com/tidalcycles/Dirt-Samples/master/'); - * s("[bd ~]*2, [~ hh]*2, ~ sd").out() + * s("[bd ~]*2, [~ hh]*2, ~ sd") * */ diff --git a/repl/src/tunes.mjs b/repl/src/tunes.mjs index d1c7b987..225e84fe 100644 --- a/repl/src/tunes.mjs +++ b/repl/src/tunes.mjs @@ -155,7 +155,7 @@ export const zeldasRescue = `stack( .gain(.1) .s('triangle') .room(1) - .out()`; + `; export const caverave = `const keys = x => x.s('sawtooth').cutoff(1200).gain(.5).attack(0).decay(.16).sustain(.3).release(.1); @@ -186,7 +186,7 @@ const synths = stack( stack( drums.fast(2), synths -).slow(2).out()`; +).slow(2)`; export const sampleDrums = `samples({ bd: 'bd/BT0A0D0.wav', @@ -198,7 +198,7 @@ stack( "", "hh*4", "~ " -).s().out() +).s() `; // TODO: @@ -290,7 +290,7 @@ export const barryHarris = `backgroundImage( .scale('C bebop major') .transpose("<0 1 2 1>/8") .slow(2) - .note().piano().out() + .note().piano() `; export const blippyRhodes = `samples({ @@ -331,7 +331,7 @@ stack( .slow(2).superimpose(x=>x.add(.02)) .note().gain(.3) .s('sawtooth').cutoff(600), -).fast(3/2).out()`; +).fast(3/2)`; export const wavyKalimba = `samples({ 'kalimba': { c5:'https://freesound.org/data/previews/536/536549_11935698-lq.mp3' } @@ -359,7 +359,7 @@ stack( .clip(1) .s('kalimba') .delay(.2) - .out()`; + `; // TODO: rework tune to use freq /* @@ -401,7 +401,7 @@ stack( .scaleTranspose("0 4 0 6".early(".125 .5")).layer(scaleTranspose("0,<2 [4,6] [5,7]>/4")) ).slow(2) .velocity(sine.struct("x*8").add(3/5).mul(2/5).fast(8)) - .note().piano().out()`; + .note().piano()`; // iter, echo, echoWith 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' }) @@ -425,7 +425,7 @@ stack( .echoWith(4, 1/8, (x,n)=>x.transpose(n*12).velocity(Math.pow(.4,n))) .legato(.1) .layer(h).note() -).out() +) .fast(2/3) .pianoroll({})`; @@ -444,7 +444,7 @@ stack( ).transpose(-1).note().piano(), s("mad").slow(2) ).cpm(78).slow(4) - .out() + .pianoroll() `; @@ -463,7 +463,7 @@ stack( .scale(scale) .scaleTranspose("<0>".slow(4)) .transpose(5) -.note().piano().out() +.note().piano() .velocity(.8) .slow(2) .pianoroll({maxMidi:100,minMidi:20})`; @@ -475,7 +475,7 @@ export const echoPiano = `"<0 2 [4 6](3,4,1) 3*2>" .off(1/2, x=>x.scaleTranspose(6).color('steelblue')) .legato(.5) .echo(4, 1/8, .5) -.note().piano().out() +.note().piano() .pianoroll()`; export const sml1 = ` @@ -511,7 +511,7 @@ stack( f3!2 e3!2 ab3!2 ~!2 >\` .legato(.5) -).fast(2) // .note().piano().out()`; +).fast(2) // .note().piano()`; /* // TODO: does not work on linux (at least for me..) @@ -554,7 +554,7 @@ stack( "".euclidLegato(6,8,1).note().s('bass').clip(1).gain(.8) ) .slow(6) - .out() + .pianoroll({minMidi:20,maxMidi:120,background:'transparent'}) `; @@ -570,7 +570,7 @@ export const waa2 = `n( .cutoff(cosine.range(500,4000).slow(16)) .gain(.5) .room(.5) - .out()`; + `; export const hyperpop = `const lfo = cosine.slow(15); const lfo2 = sine.slow(16); @@ -618,7 +618,7 @@ stack( "~ sn", "[~ hh3]*2" ).s().fast(2).gain(.7) -).slow(2).out() +).slow(2) // strudel disable-highlighting`; export const festivalOfFingers3 = `"[-7*3],0,2,6,[8 7]" @@ -634,7 +634,7 @@ export const festivalOfFingers3 = `"[-7*3],0,2,6,[8 7]" .scale(cat('D dorian','G mixolydian','C dorian','F mixolydian')) .legato(1) .slow(2) -.note().piano().out() +.note().piano() //.pianoroll({maxMidi:160})`; export const bossa = ` @@ -642,7 +642,7 @@ const scales = sequence('C minor', ['D locrian', 'G phrygian'], 'Bb2 minor', ['C stack( "".fast(2).struct("x ~ x@3 x ~ x ~ ~ ~ x ~ x@3".late(1/8)).early(1/8).slow(2).voicings(), "[~ [0 ~]] 0 [~ [4 ~]] 4".sub(7).restart(scales).scale(scales).early(.25) -).note().piano().out().slow(2)`; +).note().piano().slow(2)`; /* export const customTrigger = `stack( freq("55 [110,165] 110 [220,275]".mul("<1 <3/4 2/3>>").struct("x(3,8)").layer(x=>x.mul("1.006,.995"))), @@ -701,7 +701,7 @@ stack( .echoWith(4,.125,(x,n)=>x.gain(.15*1/(n+1))) // echo notes //.hush() ) - .out() + .slow(3/2)`; export const swimmingWithSoundfonts = `stack( @@ -763,7 +763,7 @@ export const swimmingWithSoundfonts = `stack( "[G2 C2 F2 F2]" ).s('Acoustic Bass: Bass') ).slow(51) - .out()`; + `; export const outroMusic = `samples({ bd: ['bd/BT0AADA.wav','bd/BT0AAD0.wav','bd/BT0A0DA.wav','bd/BT0A0D3.wav','bd/BT0A0D0.wav','bd/BT0A0A7.wav'], @@ -790,7 +790,7 @@ export const outroMusic = `samples({ .n(3).color('gray') ).slow(3/2) //.pianoroll({autorange:1,vertical:1,fold:0}) - .out()`; + `; export const bassFuge = `samples({ flbass: ['00_c2_finger_long_neck.wav','01_c2_finger_short_neck.wav','02_c2_finger_long_bridge.wav','03_c2_finger_short_bridge.wav','04_c2_pick_long.wav','05_c2_pick_short.wav','06_c2_palm_mute.wav'] }, 'github:cleary/samples-flbass/main/') @@ -814,7 +814,7 @@ x=>x.add(7).color('steelblue') //.hcutoff(400) .clip(1) .stack(s("bd:1*2,~ sd:0,[~ hh:0]*2")) -.out() + .pianoroll({vertical:1})`; export const bossaRandom = `const chords = "" @@ -826,7 +826,7 @@ stack( x? ~ ~ x@3 ~ x | x? ~ ~ x ~ x@3\`), roots.struct("x [~ x?0.2] x [~ x?] | x!4 | x@2 ~ ~ ~ x x x").transpose("0 7") -).slow(2).pianoroll().note().piano().out()`; +).slow(2).pianoroll().note().piano()`; export const chop = `samples({ p: 'https://cdn.freesound.org/previews/648/648433_11943129-lq.mp3' }) @@ -837,14 +837,14 @@ s("p") .shape(.4) .decay(.1) .sustain(.6) - .out()`; + `; export const delay = `stack( s("bd ") .delay("<0 .5>") .delaytime(".16 | .33") .delayfeedback(".6 | .8") - ).sometimes(x=>x.speed("-1")).out()`; + ).sometimes(x=>x.speed("-1"))`; export const orbit = `stack( s("bd ") @@ -856,4 +856,4 @@ export const orbit = `stack( .delaytime(.08) .delayfeedback(.7) .orbit(2) - ).sometimes(x=>x.speed("-1")).out()`; + ).sometimes(x=>x.speed("-1"))`; diff --git a/tutorial/tutorial.mdx b/tutorial/tutorial.mdx index bee7bef4..45d82009 100644 --- a/tutorial/tutorial.mdx +++ b/tutorial/tutorial.mdx @@ -18,34 +18,33 @@ The best place to actually make music with Strudel is the [Strudel REPL](https:/ To get a taste of what Strudel can do, check out this track: /8"), -"~ ".tone(snare).bypass("<0@7 1>/4"), -"[~ c4]*2".tone(hihat) -); -const thru = (x) => x.transpose("<0 1>/8").transpose(-1); -const synths = stack( -"/2".scale(timeCat([3,'C minor'],[1,'C melodic minor']).slow(8)).struct("[~ x]\*2") -.layer( -scaleTranspose(0).early(0), -scaleTranspose(2).early(1/8), -scaleTranspose(7).early(1/4), -scaleTranspose(8).early(3/8) -).layer(thru).tone(keys).bypass("<1 0>/16"), -"/2".struct("[x [~ x] <[~ [~ x]]!3 [x x]>@2]/2".fast(2)).layer(thru).tone(bass), -"/2".struct("~ [x@0.1 ~]".fast(2)).voicings().layer(thru).every(2, early(1/8)).tone(keys).bypass("<0@7 1>/8".early(1/4)) -) + tune={`samples({ + bd: ['bd/BT0AADA.wav','bd/BT0AAD0.wav','bd/BT0A0DA.wav','bd/BT0A0D3.wav','bd/BT0A0D0.wav','bd/BT0A0A7.wav'], + sd: ['sd/rytm-01-classic.wav','sd/rytm-00-hard.wav'], + hh: ['hh27/000_hh27closedhh.wav','hh/000_hh3closedhh.wav'], +}, 'github:tidalcycles/Dirt-Samples/master/'); stack( -drums.fast(2), -synths -).slow(2); -`} +s("bd,[~ ],hh(3,4)") // drums +.speed(perlin.range(.7,.9)) // random sample speed variation +,"" // bassline +.off(1/8,x=>x.add(12).degradeBy(.5)) // random octave jumps +.add(perlin.range(0,.5)) // random pitch variation +.superimpose(add(.05)) // add second, slightly detuned voice +.n() // wrap in "n" +.decay(.15).sustain(0) // make each note of equal length +.s('sawtooth') // waveform +.gain(.4) // turn down +.cutoff(sine.slow(7).range(300,5000)) // automate cutoff +,">".voicings() // chords +.superimpose(x=>x.add(.04)) // add second, slightly detuned voice +.add(perlin.range(0,.5)) // random pitch variation +.n() // wrap in "n" +.s('sawtooth') // waveform +.gain(.16) // turn down +.cutoff(500) // fixed cutoff +.attack(1) // slowly fade in +) +.slow(3/2)`} /> [Open this track in the REPL](https://strudel.tidalcycles.org/#KCkgPT4gewogIGNvbnN0IGRlbGF5ID0gbmV3IEZlZWRiYWNrRGVsYXkoMS84LCAuNCkuY2hhaW4odm9sKDAuNSksIG91dCk7CiAgY29uc3Qga2ljayA9IG5ldyBNZW1icmFuZVN5bnRoKCkuY2hhaW4odm9sKC44KSwgb3V0KTsKICBjb25zdCBzbmFyZSA9IG5ldyBOb2lzZVN5bnRoKCkuY2hhaW4odm9sKC44KSwgb3V0KTsKICBjb25zdCBoaWhhdCA9IG5ldyBNZXRhbFN5bnRoKCkuc2V0KGFkc3IoMCwgLjA4LCAwLCAuMSkpLmNoYWluKHZvbCguMykuY29ubmVjdChkZWxheSksb3V0KTsKICBjb25zdCBiYXNzID0gbmV3IFN5bnRoKCkuc2V0KHsgLi4ub3NjKCdzYXd0b290aCcpLCAuLi5hZHNyKDAsIC4xLCAuNCkgfSkuY2hhaW4obG93cGFzcyg5MDApLCB2b2woLjUpLCBvdXQpOwogIGNvbnN0IGtleXMgPSBuZXcgUG9seVN5bnRoKCkuc2V0KHsgLi4ub3NjKCdzYXd0b290aCcpLCAuLi5hZHNyKDAsIC41LCAuMiwgLjcpIH0pLmNoYWluKGxvd3Bhc3MoMTIwMCksIHZvbCguNSksIG91dCk7CiAgCiAgY29uc3QgZHJ1bXMgPSBzdGFjaygKICAgICdjMSoyJy5tLnRvbmUoa2ljaykuYnlwYXNzKCc8MEA3IDE%2BLzgnLm0pLAogICAgJ34gPHghNyBbeEAzIHhdPicubS50b25lKHNuYXJlKS5ieXBhc3MoJzwwQDcgMT4vNCcubSksCiAgICAnW34gYzRdKjInLm0udG9uZShoaWhhdCkKICApOwogIAogIGNvbnN0IHRocnUgPSAoeCkgPT4geC50cmFuc3Bvc2UoJzwwIDE%2BLzgnLm0pLnRyYW5zcG9zZSgtMSk7CiAgY29uc3Qgc3ludGhzID0gc3RhY2soCiAgICAnPGViNCBkNCBjNCBiMz4vMicubS5zY2FsZSh0aW1lQ2F0KFszLCdDIG1pbm9yJ10sWzEsJ0MgbWVsb2RpYyBtaW5vciddKS5zbG93KDgpKS5ncm9vdmUoJ1t%2BIHhdKjInLm0pCiAgICAuZWRpdCgKICAgICAgc2NhbGVUcmFuc3Bvc2UoMCkuZWFybHkoMCksCiAgICAgIHNjYWxlVHJhbnNwb3NlKDIpLmVhcmx5KDEvOCksCiAgICAgIHNjYWxlVHJhbnNwb3NlKDcpLmVhcmx5KDEvNCksCiAgICAgIHNjYWxlVHJhbnNwb3NlKDgpLmVhcmx5KDMvOCkKICAgICkuZWRpdCh0aHJ1KS50b25lKGtleXMpLmJ5cGFzcygnPDEgMD4vMTYnLm0pLAogICAgJzxDMiBCYjEgQWIxIFtHMSBbRzIgRzFdXT4vMicubS5ncm9vdmUoJ1t4IFt%2BIHhdIDxbfiBbfiB4XV0hMyBbeCB4XT5AMl0vMicubS5mYXN0KDIpKS5lZGl0KHRocnUpLnRvbmUoYmFzcyksCiAgICAnPENtNyBCYjcgRm03IEc3YjEzPi8yJy5tLmdyb292ZSgnfiBbeEAwLjEgfl0nLm0uZmFzdCgyKSkudm9pY2luZ3MoKS5lZGl0KHRocnUpLmV2ZXJ5KDIsIGVhcmx5KDEvOCkpLnRvbmUoa2V5cykuYnlwYXNzKCc8MEA3IDE%2BLzgnLm0uZWFybHkoMS80KSkKICApCiAgcmV0dXJuIHN0YWNrKAogICAgZHJ1bXMuZmFzdCgyKSwgCiAgICBzeW50aHMKICApLnNsb3coMik7Cn0%3D) @@ -191,52 +190,20 @@ resulting in a rhythmical structure of "x ~ ~ x ~ ~ x ~" (3 beats over 8 segment # Web Audio Output The default way to output sound is by using the Web Audio Output. -Here is a little beat to show some of the possibilities: - -],hh(3,4)") // drums -.speed(perlin.range(.7,.9)) // random sample speed variation -,"" // bassline -.off(1/8,x=>x.add(12).degradeBy(.5)) // random octave jumps -.add(perlin.range(0,.5)) // random pitch variation -.superimpose(add(.05)) // add second, slightly detuned voice -.n() // wrap in "n" -.decay(.15).sustain(0) // make each note of equal length -.s('sawtooth') // waveform -.gain(.4) // turn down -.cutoff(sine.slow(7).range(300,5000)) // automate cutoff -,">".voicings() // chords -.superimpose(x=>x.add(.04)) // add second, slightly detuned voice -.add(perlin.range(0,.5)) // random pitch variation -.n() // wrap in "n" -.s('sawtooth') // waveform -.gain(.16) // turn down -.cutoff(500) // fixed cutoff -.attack(1) // slowly fade in -) -.slow(3/2) -.out()`} -/> ## Synths So far, all the mini notation examples all used the same sound, which is kind of boring. We can change the sound, using the `s` function: ->").s('sawtooth').out()`} /> +>").s('sawtooth')`} /> Here, we are wrapping our notes inside `note` and set the sound using `s`, connected by a dot. Those functions are only 2 of many ways to alter the properties, or _params_ of a sound. The power of patterns allows us to sequence any _param_ independently: ->").s("").out()`} /> +>").s("")`} /> Now we not only pattern the notes, but the sound as well! `sawtooth` `square` and `triangle` are the basic waveforms available in `s`. @@ -247,14 +214,14 @@ You can control the envelope of a synth using the `attack`, `decay`, `sustain` a >").s('sawtooth') - .attack(.1).decay(.1).sustain(.2).release(.1).out()`} + .attack(.1).decay(.1).sustain(.2).release(.1)`} /> ## Samples Besides Synths, `s` can also play back samples: - + To know which sounds are available, open the [default sample map](https://strudel.tidalcycles.org/EmuSP12.json) @@ -268,7 +235,7 @@ You can load your own sample map like this: sd: 'sd/rytm-01-classic.wav', hh: 'hh27/000_hh27closedhh.wav', }, 'https://raw.githubusercontent.com/tidalcycles/Dirt-Samples/master/'); -s("bd sd,hh*8").out()`} +s("bd sd,hh*8")`} /> The `samples` function takes an object that maps sound names to audio file paths. @@ -282,7 +249,7 @@ Because github is a popular choice to dump samples, there is a shortcut for that sd: 'sd/rytm-01-classic.wav', hh: 'hh27/000_hh27closedhh.wav', }, 'github:tidalcycles/Dirt-Samples/master/'); -s("bd sd,hh*8").out()`} +s("bd sd,hh*8")`} /> The format is `github:user/repo/branch/`. @@ -297,7 +264,7 @@ It is also possible, to declare multiple files for one sound, using the array no sd: ['sd/rytm-01-classic.wav','sd/rytm-00-hard.wav'], hh: ['hh27/000_hh27closedhh.wav','hh/000_hh3closedhh.wav'], }, 'github:tidalcycles/Dirt-Samples/master/'); -s(",~ ,[hh:0 hh:1]*2").out()`} +s(",~ ,[hh:0 hh:1]*2")`} /> The `:0` `:1` etc. are the indices of the array. @@ -309,7 +276,7 @@ The sample number can also be set using `n`: sd: ['sd/rytm-01-classic.wav','sd/rytm-00-hard.wav'], hh: ['hh27/000_hh27closedhh.wav','hh/000_hh3closedhh.wav'], }, 'github:tidalcycles/Dirt-Samples/master/'); -s("bd,~ sd,hh*4").n("<0 1>").out()`} +s("bd,~ sd,hh*4").n("<0 1>")`} /> ### Pitched Sounds @@ -320,7 +287,7 @@ For pitched sounds, you can use `note`, just like with synths: tune={`samples({ "gtr": 'gtr/0001_cleanC.wav', }, 'github:tidalcycles/Dirt-Samples/master/'); -note("g3 [bb3 c4] @2").s('gtr').gain(.5).out()`} +note("g3 [bb3 c4] @2").s('gtr').gain(.5)`} /> Here, the guitar samples will overlap, because they always play till the end. @@ -331,7 +298,7 @@ If we want them to behave more like a synth, we can add `clip(1)`: "gtr": 'gtr/0001_cleanC.wav', }, 'github:tidalcycles/Dirt-Samples/master/'); note("g3 [bb3 c4] @2").s('gtr').clip(1) - .gain(.5).out()`} + .gain(.5)`} /> ### Base Pitch @@ -344,7 +311,7 @@ If we have 2 samples with different base pitches, we can make them in tune by sp "moog": { 'g3': 'moog/005_Mighty%20Moog%20G3.wav' }, }, 'github:tidalcycles/Dirt-Samples/master/'); note("g3 [bb3 c4] @2").s("gtr,moog").clip(1) - .gain(.5).out()`} + .gain(.5)`} /> If a sample has no pitch set, `c3` is the default. @@ -360,7 +327,7 @@ We can also declare different samples for different regions of the keyboard: }}, 'github:tidalcycles/Dirt-Samples/master/'); note("g2!2 !2, g4 f4]>") .s('moog').clip(1) - .gain(.5).out()`} + .gain(.5)`} /> The sampler will always pick the closest matching sample for the current note!