remove all occurrences of .out()

This commit is contained in:
Felix Roos 2022-10-27 19:47:07 +02:00
parent 5c230c2d65
commit ecc4e1803c
10 changed files with 139 additions and 172 deletions

View File

@ -23,7 +23,7 @@ const generic_params = [
* @name s * @name s
* @param {string | Pattern} sound The sound / pattern of sounds to pick * @param {string | Pattern} sound The sound / pattern of sounds to pick
* @example * @example
* s("bd hh").out() * s("bd hh")
* *
*/ */
['s', 's', 'sound'], ['s', 's', 'sound'],
@ -67,7 +67,7 @@ const generic_params = [
* @name gain * @name gain
* @param {number | Pattern} amount gain. * @param {number | Pattern} amount gain.
* @example * @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 * @name bandf
* @param {number | Pattern} frequency center frequency * @param {number | Pattern} frequency center frequency
* @example * @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.'], ['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 * @name bandq
* @param {number | Pattern} q q factor * @param {number | Pattern} q q factor
* @example * @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.'], ['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 * @param {number | Pattern} amount between 0 and 1, where 1 is the length of the sample
* @example * @example
* samples({ rave: 'rave/AREUREADY.wav' }, 'github:tidalcycles/Dirt-Samples/master/') * 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 * @name end
* @param {number | Pattern} length 1 = whole sample, .5 = half sample, .25 = quarter sample etc.. * @param {number | Pattern} length 1 = whole sample, .5 = half sample, .25 = quarter sample etc..
* @example * @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 * @name crush
* @param {number | Pattern} depth between 1 (for drastic reduction in bit-depth) to 16 (for barely no reduction). * @param {number | Pattern} depth between 1 (for drastic reduction in bit-depth) to 16 (for barely no reduction).
* @example * @example
* s("<bd sd>,hh*3").fast(2).crush("<16 8 7 6 5 4 3 2>").out() * s("<bd sd>,hh*3").fast(2).crush("<16 8 7 6 5 4 3 2>")
* *
*/ */
[ [
@ -219,7 +219,7 @@ const generic_params = [
* @name coarse * @name coarse
* @param {number | Pattern} factor 1 for original 2 for half, 3 for a third and so on. * @param {number | Pattern} factor 1 for original 2 for half, 3 for a third and so on.
* @example * @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 * @name cutoff
* @param {number | Pattern} frequency audible between 0 and 20000 * @param {number | Pattern} frequency audible between 0 and 20000
* @example * @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 // TODO: add lpf synonym
@ -267,7 +267,7 @@ const generic_params = [
* @name hcutoff * @name hcutoff
* @param {number | Pattern} frequency audible between 0 and 20000 * @param {number | Pattern} frequency audible between 0 and 20000
* @example * @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 // TODO: add hpf synonym
@ -282,7 +282,7 @@ const generic_params = [
* @name hresonance * @name hresonance
* @param {number | Pattern} q resonance factor between 0 and 1 * @param {number | Pattern} q resonance factor between 0 and 1
* @example * @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 * @name resonance
* @param {number | Pattern} q resonance factor between 0 and 1 * @param {number | Pattern} q resonance factor between 0 and 1
* @example * @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.'], ['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 * @name pan
* @param {number | Pattern} pan between 0 and 1, from left to right (assuming stereo), once round a circle (assuming multichannel) * @param {number | Pattern} pan between 0 and 1, from left to right (assuming stereo), once round a circle (assuming multichannel)
* @example * @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 * @name shape
* @param {number | Pattern} distortion between 0 and 1 * @param {number | Pattern} distortion between 0 and 1
* @example * @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. * @param {string | Pattern} vowel You can use a e i o u.
* @example * @example
* note("c2 <eb2 <g2 g1>>").s('sawtooth') * note("c2 <eb2 <g2 g1>>").s('sawtooth')
* .vowel("<a e i <o u>>").out() * .vowel("<a e i <o u>>")
* *
*/ */
[ [

View File

@ -32,7 +32,7 @@ const euclid = (pulses, steps, rotation = 0) => {
* @returns Pattern * @returns Pattern
* @example * @example
* // The Cuban tresillo pattern. * // 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 * @name euclidLegato
* @memberof Pattern * @memberof Pattern
* @example * @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) { Pattern.prototype.euclidLegato = function (pulses, steps, rotation = 0) {
const bin_pat = euclid(pulses, steps, rotation); const bin_pat = euclid(pulses, steps, rotation);

View File

@ -524,7 +524,7 @@ export class Pattern {
* @memberof Pattern * @memberof Pattern
* @returns Pattern * @returns Pattern
* @example * @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) { _range(min, max) {
return this.mul(max - min).add(min); return this.mul(max - min).add(min);
@ -718,7 +718,7 @@ export class Pattern {
* @example * @example
* "<0 2 4 6 ~ 4 ~ 2 0!3 ~!5>*4" * "<0 2 4 6 ~ 4 ~ 2 0!3 ~!5>*4"
* .layer(x=>x.add("0,2")) * .layer(x=>x.add("0,2"))
* .scale('C minor').note().out() * .scale('C minor').note()
*/ */
layer(...funcs) { layer(...funcs) {
return stack(...funcs.map((func) => func(this))); return stack(...funcs.map((func) => func(this)));
@ -756,11 +756,13 @@ export class Pattern {
const cycle = begin.sam(); const cycle = begin.sam();
const beginPos = begin.sub(cycle).div(factor).min(1); const beginPos = begin.sub(cycle).div(factor).min(1);
const endPos = end.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 newPart = new TimeSpan(cycle.add(beginPos), cycle.add(endPos));
const newWhole = !hap.whole ? undefined : new TimeSpan( const newWhole = !hap.whole
newPart.begin.sub(begin.sub(hap.whole.begin).div(factor)), ? undefined
newPart.end.add(hap.whole.end.sub(end).div(factor)) : 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 new Hap(newWhole, newPart, hap.value, hap.context);
}; };
return this.withQuerySpan(qf)._withHap(ef)._splitQueries(); return this.withQuerySpan(qf)._withHap(ef)._splitQueries();
@ -796,7 +798,7 @@ export class Pattern {
* @param {number | Pattern} factor speed up factor * @param {number | Pattern} factor speed up factor
* @returns Pattern * @returns Pattern
* @example * @example
* s("<bd sd> hh").fast(2).out() // s("[<bd sd> hh]*2").out() * s("<bd sd> hh").fast(2) // s("[<bd sd> hh]*2")
*/ */
_fast(factor) { _fast(factor) {
const fastQuery = this.withQueryTime((t) => t.mul(factor)); const fastQuery = this.withQueryTime((t) => t.mul(factor));
@ -811,7 +813,7 @@ export class Pattern {
* @param {number | Pattern} factor slow down factor * @param {number | Pattern} factor slow down factor
* @returns Pattern * @returns Pattern
* @example * @example
* s("<bd sd> hh").slow(2).out() // s("[<bd sd> hh]/2").out() * s("<bd sd> hh").slow(2) // s("[<bd sd> hh]/2")
*/ */
_slow(factor) { _slow(factor) {
return this._fast(Fraction(1).div(factor)); return this._fast(Fraction(1).div(factor));
@ -841,7 +843,7 @@ export class Pattern {
* .chop(4) * .chop(4)
* .rev() // reverse order of chops * .rev() // reverse order of chops
* .loopAt(4,1) // fit sample into 4 cycles * .loopAt(4,1) // fit sample into 4 cycles
* .out() *
*/ */
_chop(n) { _chop(n) {
const slices = Array.from({ length: n }, (x, i) => i); 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 * @param {number | Pattern} cycles number of cycles to nudge left
* @returns Pattern * @returns Pattern
* @example * @example
* "bd ~".stack("hh ~".early(.1)).s().out() * "bd ~".stack("hh ~".early(.1)).s()
*/ */
_early(offset) { _early(offset) {
offset = Fraction(offset); offset = Fraction(offset);
@ -887,7 +889,7 @@ export class Pattern {
* @param {number | Pattern} cycles number of cycles to nudge right * @param {number | Pattern} cycles number of cycles to nudge right
* @returns Pattern * @returns Pattern
* @example * @example
* "bd ~".stack("hh ~".late(.1)).s().out() * "bd ~".stack("hh ~".late(.1)).s()
*/ */
_late(offset) { _late(offset) {
offset = Fraction(offset); offset = Fraction(offset);
@ -925,7 +927,7 @@ export class Pattern {
* @example * @example
* "c3,eb3,g3" * "c3,eb3,g3"
* .struct("x ~ x ~ ~ x ~ x ~ ~ ~ x ~ x ~ ~") * .struct("x ~ x ~ ~ x ~ x ~ ~ ~ x ~ x ~ ~")
* .slow(4).note().out() * .slow(4).note()
*/ */
// struct(...binary_pats) { // struct(...binary_pats) {
// // Re structure the pattern according to a binary pattern (false values are dropped) // // 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 * @param {function} func function to apply
* @returns Pattern * @returns Pattern
* @example * @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) { every(n, func) {
const pat = this; const pat = this;
@ -1032,7 +1034,7 @@ export class Pattern {
* @param {function} func function to apply * @param {function} func function to apply
* @returns Pattern * @returns Pattern
* @example * @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) { every(n, func) {
const pat = this; const pat = this;
@ -1049,7 +1051,7 @@ export class Pattern {
* @param {function} func function to apply * @param {function} func function to apply
* @returns Pattern * @returns Pattern
* @example * @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) { each(n, func) {
const pat = this; const pat = this;
@ -1126,7 +1128,7 @@ export class Pattern {
* @example * @example
* s("hh*2").stack( * s("hh*2").stack(
* n("c2(3,8)") * n("c2(3,8)")
* ).out() * )
*/ */
stack(...pats) { stack(...pats) {
return stack(this, ...pats); return stack(this, ...pats);
@ -1143,7 +1145,7 @@ export class Pattern {
* @example * @example
* s("hh*2").seq( * s("hh*2").seq(
* n("c2(3,8)") * n("c2(3,8)")
* ).out() * )
*/ */
seq(...pats) { seq(...pats) {
return sequence(this, ...pats); return sequence(this, ...pats);
@ -1156,7 +1158,7 @@ export class Pattern {
* @example * @example
* s("hh*2").cat( * s("hh*2").cat(
* n("c2(3,8)") * n("c2(3,8)")
* ).out() * )
*/ */
cat(...pats) { cat(...pats) {
return cat(this, ...pats); return cat(this, ...pats);
@ -1178,7 +1180,7 @@ export class Pattern {
* @example * @example
* "<0 2 4 6 ~ 4 ~ 2 0!3 ~!5>*4" * "<0 2 4 6 ~ 4 ~ 2 0!3 ~!5>*4"
* .superimpose(x=>x.add(2)) * .superimpose(x=>x.add(2))
* .scale('C minor').note().out() * .scale('C minor').note()
*/ */
superimpose(...funcs) { superimpose(...funcs) {
return this.stack(...funcs.map((func) => func(this))); return this.stack(...funcs.map((func) => func(this)));
@ -1203,7 +1205,7 @@ export class Pattern {
* @example * @example
* "<0 [2 4]>" * "<0 [2 4]>"
* .echoWith(4, 1/8, (p,n) => p.add(n*2)) * .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) { _echoWith(times, time, func) {
return stack(...listRange(0, times - 1).map((i) => func(this.late(Fraction(time).mul(i)), i))); 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} time cycle offset between iterations
* @param {number} feedback velocity multiplicator for each iteration * @param {number} feedback velocity multiplicator for each iteration
* @example * @example
* s("bd sd").echo(3, 1/6, .8).out() * s("bd sd").echo(3, 1/6, .8)
*/ */
_echo(times, time, feedback) { _echo(times, time, feedback) {
return this._echoWith(times, time, (pat, i) => pat.velocity(Math.pow(feedback, i))); return this._echoWith(times, time, (pat, i) => pat.velocity(Math.pow(feedback, i)));
@ -1230,7 +1232,7 @@ export class Pattern {
* @memberof Pattern * @memberof Pattern
* @returns Pattern * @returns Pattern
* @example * @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) { iter(times, back = false) {
return slowcat(...listRange(0, times - 1).map((i) => (back ? this.late(i / times) : this.early(i / times)))); 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 * @memberof Pattern
* @returns Pattern * @returns Pattern
* @example * @example
* note("0 1 2 3".scale('A minor')).iterBack(4).out() * note("0 1 2 3".scale('A minor')).iterBack(4)
*/ */
iterBack(times) { iterBack(times) {
return this.iter(times, true); return this.iter(times, true);
@ -1254,7 +1256,7 @@ export class Pattern {
* @memberof Pattern * @memberof Pattern
* @returns Pattern * @returns Pattern
* @example * @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) { _chunk(n, func, back = false) {
const binary = Array(n - 1).fill(false); const binary = Array(n - 1).fill(false);
@ -1269,7 +1271,7 @@ export class Pattern {
* @memberof Pattern * @memberof Pattern
* @returns Pattern * @returns Pattern
* @example * @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) { _chunkBack(n, func) {
return this._chunk(n, func, true); return this._chunk(n, func, true);
@ -1295,7 +1297,7 @@ export class Pattern {
* @name legato * @name legato
* @memberof Pattern * @memberof Pattern
* @example * @example
* n("c3 eb3 g3 c4").legato("<.25 .5 1 2>").out() * n("c3 eb3 g3 c4").legato("<.25 .5 1 2>")
*/ */
_legato(value) { _legato(value) {
return this.withHapSpan((span) => new TimeSpan(span.begin, span.begin.add(span.end.sub(span.begin).mul(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 * @example
* s("hh*8") * s("hh*8")
* .gain(".4!2 1 .4!2 1 .4 1") * .gain(".4!2 1 .4!2 1 .4 1")
* .velocity(".4 1").out() * .velocity(".4 1")
*/ */
_velocity(velocity) { _velocity(velocity) {
return this._withContext((context) => ({ ...context, velocity: (context.velocity || 1) * velocity })); return this._withContext((context) => ({ ...context, velocity: (context.velocity || 1) * velocity }));
@ -1321,7 +1323,7 @@ export class Pattern {
* @returns Pattern * @returns Pattern
* @example * @example
* samples({ rhodes: 'https://cdn.freesound.org/previews/132/132051_316502-lq.mp3' }) * 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) { _loopAt(factor, cps = 1) {
return this.speed((1 / factor) * cps) return this.speed((1 / factor) * cps)
@ -1411,7 +1413,7 @@ function _composeOp(a, b, func) {
* @name mul * @name mul
* @memberof Pattern * @memberof Pattern
* @example * @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], mul: [(a, b) => a * b, num],
/** /**

View File

@ -120,7 +120,7 @@ const timeToRands = (t, n) => timeToRandsPrime(timeToIntSeed(t), n);
* @name rand * @name rand
* @example * @example
* // randomly change the cutoff * // 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); 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) * @param {number} n max value (exclusive)
* @example * @example
* // randomly select scale notes from 0 - 7 (= C to C) * // 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(); 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. * Picks one of the elements at random each cycle.
* @returns {Pattern} * @returns {Pattern}
* @example * @example
* chooseCycles("bd", "hh", "sd").s().fast(4).out() * chooseCycles("bd", "hh", "sd").s().fast(4)
* @example * @example
* "bd | hh | sd".s().fast(4).out() * "bd | hh | sd".s().fast(4)
*/ */
export const chooseCycles = (...xs) => chooseInWith(rand.segment(1), xs); export const chooseCycles = (...xs) => chooseInWith(rand.segment(1), xs);
@ -252,7 +252,7 @@ export const perlinWith = (pat) => {
* @name perlin * @name perlin
* @example * @example
* // randomly change the cutoff * // 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); export const perlin = perlinWith(time);
@ -271,9 +271,9 @@ 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.2).out() * s("hh*8").degradeBy(0.2)
* @example * @example
* s("[hh?0.2]*8").out() * s("[hh?0.2]*8")
*/ */
Pattern.prototype._degradeBy = function (x) { Pattern.prototype._degradeBy = function (x) {
return this._degradeByWith(rand, x); return this._degradeByWith(rand, x);
@ -287,9 +287,9 @@ Pattern.prototype._degradeBy = function (x) {
* @memberof Pattern * @memberof Pattern
* @returns Pattern * @returns Pattern
* @example * @example
* s("hh*8").degrade().out() * s("hh*8").degrade()
* @example * @example
* s("[hh?]*8").out() * s("[hh?]*8")
*/ */
Pattern.prototype.degrade = function () { Pattern.prototype.degrade = function () {
return this._degradeBy(0.5); return this._degradeBy(0.5);
@ -306,7 +306,7 @@ Pattern.prototype.degrade = function () {
* @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").undegradeBy(0.2).out() * s("hh*8").undegradeBy(0.2)
*/ */
Pattern.prototype._undegradeBy = function (x) { Pattern.prototype._undegradeBy = function (x) {
return this._degradeByWith( return this._degradeByWith(
@ -340,7 +340,7 @@ Pattern.prototype._sometimesBy = function (x, func) {
* @param {function} function - the transformation to apply * @param {function} function - the transformation to apply
* @returns Pattern * @returns Pattern
* @example * @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) { Pattern.prototype.sometimesBy = function (patx, func) {
const pat = this; const pat = this;
@ -370,7 +370,7 @@ Pattern.prototype.sometimesByPre = function (patx, func) {
* @param {function} function - the transformation to apply * @param {function} function - the transformation to apply
* @returns Pattern * @returns Pattern
* @example * @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) { Pattern.prototype.sometimes = function (func) {
return this._sometimesBy(0.5, func); return this._sometimesBy(0.5, func);
@ -398,7 +398,7 @@ Pattern.prototype._someCyclesBy = function (x, func) {
* @param {function} function - the transformation to apply * @param {function} function - the transformation to apply
* @returns Pattern * @returns Pattern
* @example * @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) { Pattern.prototype.someCyclesBy = function (patx, func) {
const pat = this; const pat = this;
@ -415,7 +415,7 @@ Pattern.prototype.someCyclesBy = function (patx, func) {
* @memberof Pattern * @memberof Pattern
* @returns Pattern * @returns Pattern
* @example * @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) { Pattern.prototype.someCycles = function (func) {
return this._someCyclesBy(0.5, func); return this._someCyclesBy(0.5, func);
@ -429,7 +429,7 @@ Pattern.prototype.someCycles = function (func) {
* @memberof Pattern * @memberof Pattern
* @returns Pattern * @returns Pattern
* @example * @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) { Pattern.prototype.often = function (func) {
return this.sometimesBy(0.75, func); return this.sometimesBy(0.75, func);
@ -443,7 +443,7 @@ Pattern.prototype.often = function (func) {
* @memberof Pattern * @memberof Pattern
* @returns Pattern * @returns Pattern
* @example * @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) { Pattern.prototype.rarely = function (func) {
return this.sometimesBy(0.25, func); return this.sometimesBy(0.25, func);
@ -457,7 +457,7 @@ Pattern.prototype.rarely = function (func) {
* @memberof Pattern * @memberof Pattern
* @returns Pattern * @returns Pattern
* @example * @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) { Pattern.prototype.almostNever = function (func) {
return this.sometimesBy(0.1, func); return this.sometimesBy(0.1, func);
@ -471,7 +471,7 @@ Pattern.prototype.almostNever = function (func) {
* @memberof Pattern * @memberof Pattern
* @returns Pattern * @returns Pattern
* @example * @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) { Pattern.prototype.almostAlways = function (func) {
return this.sometimesBy(0.9, func); return this.sometimesBy(0.9, func);
@ -485,7 +485,7 @@ Pattern.prototype.almostAlways = function (func) {
* @memberof Pattern * @memberof Pattern
* @returns Pattern * @returns Pattern
* @example * @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) { Pattern.prototype.never = function (func) {
return this; return this;
@ -499,7 +499,7 @@ Pattern.prototype.never = function (func) {
* @memberof Pattern * @memberof Pattern
* @returns Pattern * @returns Pattern
* @example * @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) { Pattern.prototype.always = function (func) {
return func(this); return func(this);

View File

@ -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)) .legato(sine.range(0.3, 2).slow(28))
.wave("sawtooth square".fast(2)) .wave("sawtooth square".fast(2))
.filter('lowpass', cosine.range(500,4000).slow(16)) .filter('lowpass', cosine.range(500,4000).slow(16))
.out()
.pianoroll({minMidi:20,maxMidi:120,background:'#202124'}) .pianoroll({minMidi:20,maxMidi:120,background:'#202124'})
--> -->
</strudel-repl> </strudel-repl>

View File

@ -10,7 +10,6 @@
.legato(sine.range(0.3, 2).slow(28)) .legato(sine.range(0.3, 2).slow(28))
.wave("sawtooth square".fast(2)) .wave("sawtooth square".fast(2))
.filter('lowpass', cosine.range(500,4000).slow(16)) .filter('lowpass', cosine.range(500,4000).slow(16))
.out()
.pianoroll({minMidi:20,maxMidi:120,background:'#202124'}) .pianoroll({minMidi:20,maxMidi:120,background:'#202124'})
--> -->
</strudel-repl> </strudel-repl>

View File

@ -15,13 +15,13 @@ npm i @strudel.cycles/webaudio --save
import { Scheduler, getAudioContext } from '@strudel.cycles/webaudio'; import { Scheduler, getAudioContext } from '@strudel.cycles/webaudio';
const scheduler = new Scheduler({ const scheduler = new Scheduler({
audioContext: getAudioContext(), audioContext: getAudioContext(),
interval: 0.1, interval: 0.1,
onEvent: (e) => e.context?.createAudioNode?.(e), onEvent: (e) => e.context?.createAudioNode?.(e),
}); });
const pattern = sequence([55, 99], 110).osc('sawtooth').out() const pattern = sequence([55, 99], 110).osc('sawtooth');
scheduler.setPattern(pattern); scheduler.setPattern(pattern);
scheduler.start() scheduler.start();
//scheduler.stop() //scheduler.stop()
``` ```

View File

@ -98,7 +98,7 @@ export const loadGithubSamples = async (path, nameFn) => {
* bd: '808bd/BD0000.WAV', * bd: '808bd/BD0000.WAV',
* sd: '808sd/SD0010.WAV' * sd: '808sd/SD0010.WAV'
* }, 'https://raw.githubusercontent.com/tidalcycles/Dirt-Samples/master/'); * }, 'https://raw.githubusercontent.com/tidalcycles/Dirt-Samples/master/');
* s("[bd ~]*2, [~ hh]*2, ~ sd").out() * s("[bd ~]*2, [~ hh]*2, ~ sd")
* *
*/ */

View File

@ -155,7 +155,7 @@ export const zeldasRescue = `stack(
.gain(.1) .gain(.1)
.s('triangle') .s('triangle')
.room(1) .room(1)
.out()`; `;
export const caverave = `const keys = x => x.s('sawtooth').cutoff(1200).gain(.5).attack(0).decay(.16).sustain(.3).release(.1); 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( stack(
drums.fast(2), drums.fast(2),
synths synths
).slow(2).out()`; ).slow(2)`;
export const sampleDrums = `samples({ export const sampleDrums = `samples({
bd: 'bd/BT0A0D0.wav', bd: 'bd/BT0A0D0.wav',
@ -198,7 +198,7 @@ stack(
"<bd!3 bd(3,4,2)>", "<bd!3 bd(3,4,2)>",
"hh*4", "hh*4",
"~ <sn!3 sn(3,4,1)>" "~ <sn!3 sn(3,4,1)>"
).s().out() ).s()
`; `;
// TODO: // TODO:
@ -290,7 +290,7 @@ export const barryHarris = `backgroundImage(
.scale('C bebop major') .scale('C bebop major')
.transpose("<0 1 2 1>/8") .transpose("<0 1 2 1>/8")
.slow(2) .slow(2)
.note().piano().out() .note().piano()
`; `;
export const blippyRhodes = `samples({ export const blippyRhodes = `samples({
@ -331,7 +331,7 @@ stack(
.slow(2).superimpose(x=>x.add(.02)) .slow(2).superimpose(x=>x.add(.02))
.note().gain(.3) .note().gain(.3)
.s('sawtooth').cutoff(600), .s('sawtooth').cutoff(600),
).fast(3/2).out()`; ).fast(3/2)`;
export const wavyKalimba = `samples({ export const wavyKalimba = `samples({
'kalimba': { c5:'https://freesound.org/data/previews/536/536549_11935698-lq.mp3' } 'kalimba': { c5:'https://freesound.org/data/previews/536/536549_11935698-lq.mp3' }
@ -359,7 +359,7 @@ stack(
.clip(1) .clip(1)
.s('kalimba') .s('kalimba')
.delay(.2) .delay(.2)
.out()`; `;
// TODO: rework tune to use freq // 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")) .scaleTranspose("0 4 0 6".early(".125 .5")).layer(scaleTranspose("0,<2 [4,6] [5,7]>/4"))
).slow(2) ).slow(2)
.velocity(sine.struct("x*8").add(3/5).mul(2/5).fast(8)) .velocity(sine.struct("x*8").add(3/5).mul(2/5).fast(8))
.note().piano().out()`; .note().piano()`;
// iter, echo, echoWith // 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' }) 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))) .echoWith(4, 1/8, (x,n)=>x.transpose(n*12).velocity(Math.pow(.4,n)))
.legato(.1) .legato(.1)
.layer(h).note() .layer(h).note()
).out() )
.fast(2/3) .fast(2/3)
.pianoroll({})`; .pianoroll({})`;
@ -444,7 +444,7 @@ stack(
).transpose(-1).note().piano(), ).transpose(-1).note().piano(),
s("mad").slow(2) s("mad").slow(2)
).cpm(78).slow(4) ).cpm(78).slow(4)
.out()
.pianoroll() .pianoroll()
`; `;
@ -463,7 +463,7 @@ stack(
.scale(scale) .scale(scale)
.scaleTranspose("<0>".slow(4)) .scaleTranspose("<0>".slow(4))
.transpose(5) .transpose(5)
.note().piano().out() .note().piano()
.velocity(.8) .velocity(.8)
.slow(2) .slow(2)
.pianoroll({maxMidi:100,minMidi:20})`; .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')) .off(1/2, x=>x.scaleTranspose(6).color('steelblue'))
.legato(.5) .legato(.5)
.echo(4, 1/8, .5) .echo(4, 1/8, .5)
.note().piano().out() .note().piano()
.pianoroll()`; .pianoroll()`;
export const sml1 = ` export const sml1 = `
@ -511,7 +511,7 @@ stack(
f3!2 e3!2 ab3!2 ~!2 f3!2 e3!2 ab3!2 ~!2
>\` >\`
.legato(.5) .legato(.5)
).fast(2) // .note().piano().out()`; ).fast(2) // .note().piano()`;
/* /*
// TODO: does not work on linux (at least for me..) // TODO: does not work on linux (at least for me..)
@ -554,7 +554,7 @@ stack(
"<D2 A2 G2 F2>".euclidLegato(6,8,1).note().s('bass').clip(1).gain(.8) "<D2 A2 G2 F2>".euclidLegato(6,8,1).note().s('bass').clip(1).gain(.8)
) )
.slow(6) .slow(6)
.out()
.pianoroll({minMidi:20,maxMidi:120,background:'transparent'}) .pianoroll({minMidi:20,maxMidi:120,background:'transparent'})
`; `;
@ -570,7 +570,7 @@ export const waa2 = `n(
.cutoff(cosine.range(500,4000).slow(16)) .cutoff(cosine.range(500,4000).slow(16))
.gain(.5) .gain(.5)
.room(.5) .room(.5)
.out()`; `;
export const hyperpop = `const lfo = cosine.slow(15); export const hyperpop = `const lfo = cosine.slow(15);
const lfo2 = sine.slow(16); const lfo2 = sine.slow(16);
@ -618,7 +618,7 @@ stack(
"~ sn", "~ sn",
"[~ hh3]*2" "[~ hh3]*2"
).s().fast(2).gain(.7) ).s().fast(2).gain(.7)
).slow(2).out() ).slow(2)
// strudel disable-highlighting`; // strudel disable-highlighting`;
export const festivalOfFingers3 = `"[-7*3],0,2,6,[8 7]" 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')) .scale(cat('D dorian','G mixolydian','C dorian','F mixolydian'))
.legato(1) .legato(1)
.slow(2) .slow(2)
.note().piano().out() .note().piano()
//.pianoroll({maxMidi:160})`; //.pianoroll({maxMidi:160})`;
export const bossa = ` export const bossa = `
@ -642,7 +642,7 @@ const scales = sequence('C minor', ['D locrian', 'G phrygian'], 'Bb2 minor', ['C
stack( stack(
"<Cm7 [Dm7b5 G7b9] Bbm7 [Cm7b5 F7b9]>".fast(2).struct("x ~ x@3 x ~ x ~ ~ ~ x ~ x@3".late(1/8)).early(1/8).slow(2).voicings(), "<Cm7 [Dm7b5 G7b9] Bbm7 [Cm7b5 F7b9]>".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) "[~ [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( 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"))), 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 .echoWith(4,.125,(x,n)=>x.gain(.15*1/(n+1))) // echo notes
//.hush() //.hush()
) )
.out()
.slow(3/2)`; .slow(3/2)`;
export const swimmingWithSoundfonts = `stack( export const swimmingWithSoundfonts = `stack(
@ -763,7 +763,7 @@ export const swimmingWithSoundfonts = `stack(
"[G2 C2 F2 F2]" "[G2 C2 F2 F2]"
).s('Acoustic Bass: Bass') ).s('Acoustic Bass: Bass')
).slow(51) ).slow(51)
.out()`; `;
export const outroMusic = `samples({ export const outroMusic = `samples({
bd: ['bd/BT0AADA.wav','bd/BT0AAD0.wav','bd/BT0A0DA.wav','bd/BT0A0D3.wav','bd/BT0A0D0.wav','bd/BT0A0A7.wav'], 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') .n(3).color('gray')
).slow(3/2) ).slow(3/2)
//.pianoroll({autorange:1,vertical:1,fold:0}) //.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'] }, 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/') 'github:cleary/samples-flbass/main/')
@ -814,7 +814,7 @@ x=>x.add(7).color('steelblue')
//.hcutoff(400) //.hcutoff(400)
.clip(1) .clip(1)
.stack(s("bd:1*2,~ sd:0,[~ hh:0]*2")) .stack(s("bd:1*2,~ sd:0,[~ hh:0]*2"))
.out()
.pianoroll({vertical:1})`; .pianoroll({vertical:1})`;
export const bossaRandom = `const chords = "<Am7 Am7 Dm7 E7>" export const bossaRandom = `const chords = "<Am7 Am7 Dm7 E7>"
@ -826,7 +826,7 @@ stack(
x? ~ ~ x@3 ~ x | x? ~ ~ x@3 ~ x |
x? ~ ~ x ~ x@3\`), x? ~ ~ x ~ x@3\`),
roots.struct("x [~ x?0.2] x [~ x?] | x!4 | x@2 ~ ~ ~ x x x").transpose("0 7") 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' }) export const chop = `samples({ p: 'https://cdn.freesound.org/previews/648/648433_11943129-lq.mp3' })
@ -837,14 +837,14 @@ s("p")
.shape(.4) .shape(.4)
.decay(.1) .decay(.1)
.sustain(.6) .sustain(.6)
.out()`; `;
export const delay = `stack( export const delay = `stack(
s("bd <sd cp>") s("bd <sd cp>")
.delay("<0 .5>") .delay("<0 .5>")
.delaytime(".16 | .33") .delaytime(".16 | .33")
.delayfeedback(".6 | .8") .delayfeedback(".6 | .8")
).sometimes(x=>x.speed("-1")).out()`; ).sometimes(x=>x.speed("-1"))`;
export const orbit = `stack( export const orbit = `stack(
s("bd <sd cp>") s("bd <sd cp>")
@ -856,4 +856,4 @@ export const orbit = `stack(
.delaytime(.08) .delaytime(.08)
.delayfeedback(.7) .delayfeedback(.7)
.orbit(2) .orbit(2)
).sometimes(x=>x.speed("-1")).out()`; ).sometimes(x=>x.speed("-1"))`;

View File

@ -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: To get a taste of what Strudel can do, check out this track:
<MiniRepl <MiniRepl
tune={`const delay = new FeedbackDelay(1/8, .4).chain(vol(0.5), out()); tune={`samples({
const kick = new MembraneSynth().chain(vol(.8), out()); bd: ['bd/BT0AADA.wav','bd/BT0AAD0.wav','bd/BT0A0DA.wav','bd/BT0A0D3.wav','bd/BT0A0D0.wav','bd/BT0A0A7.wav'],
const snare = new NoiseSynth().chain(vol(.8), out()); sd: ['sd/rytm-01-classic.wav','sd/rytm-00-hard.wav'],
const hihat = new MetalSynth().set(adsr(0, .08, 0, .1)).chain(vol(.3).connect(delay),out()); hh: ['hh27/000_hh27closedhh.wav','hh/000_hh3closedhh.wav'],
const bass = new Synth().set({ ...osc('sawtooth'), ...adsr(0, .1, .4) }).chain(lowpass(900), vol(.5), out()); }, 'github:tidalcycles/Dirt-Samples/master/');
const keys = new PolySynth().set({ ...osc('sawtooth'), ...adsr(0, .5, .2, .7) }).chain(lowpass(1200), vol(.5), out());
const drums = stack(
"c1*2".tone(kick).bypass("<0@7 1>/8"),
"~ <x!7 [x@3 x]>".tone(snare).bypass("<0@7 1>/4"),
"[~ c4]*2".tone(hihat)
);
const thru = (x) => x.transpose("<0 1>/8").transpose(-1);
const synths = stack(
"<eb4 d4 c4 b3>/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"),
"<C2 Bb1 Ab1 [G1 [G2 G1]]>/2".struct("[x [~ x] <[~ [~ x]]!3 [x x]>@2]/2".fast(2)).layer(thru).tone(bass),
"<Cm7 Bb7 Fm7 G7b13>/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))
)
stack( stack(
drums.fast(2), s("bd,[~ <sd!3 sd(3,4,2)>],hh(3,4)") // drums
synths .speed(perlin.range(.7,.9)) // random sample speed variation
).slow(2); ,"<a1 b1\*2 a1(3,8) e2>" // 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
,"<Am7!3 <Em7 E7b13 Em7 Ebm7b5>>".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) [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 # Web Audio Output
The default way to output sound is by using the 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:
<MiniRepl
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(
s("bd,[~ <sd!3 sd(3,4,2)>],hh(3,4)") // drums
.speed(perlin.range(.7,.9)) // random sample speed variation
,"<a1 b1\*2 a1(3,8) e2>" // 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
,"<Am7!3 <Em7 E7b13 Em7 Ebm7b5>>".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 ## Synths
So far, all the mini notation examples all used the same sound, which is kind of boring. 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: We can change the sound, using the `s` function:
<MiniRepl tune={`note("c2 <eb2 <g2 g1>>").s('sawtooth').out()`} /> <MiniRepl tune={`note("c2 <eb2 <g2 g1>>").s('sawtooth')`} />
Here, we are wrapping our notes inside `note` and set the sound using `s`, connected by a dot. 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. 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: The power of patterns allows us to sequence any _param_ independently:
<MiniRepl tune={`note("c2 <eb2 <g2 g1>>").s("<sawtooth square triangle>").out()`} /> <MiniRepl tune={`note("c2 <eb2 <g2 g1>>").s("<sawtooth square triangle>")`} />
Now we not only pattern the notes, but the sound as well! Now we not only pattern the notes, but the sound as well!
`sawtooth` `square` and `triangle` are the basic waveforms available in `s`. `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
<MiniRepl <MiniRepl
tune={`note("c2 <eb2 <g2 g1>>").s('sawtooth') tune={`note("c2 <eb2 <g2 g1>>").s('sawtooth')
.attack(.1).decay(.1).sustain(.2).release(.1).out()`} .attack(.1).decay(.1).sustain(.2).release(.1)`}
/> />
## Samples ## Samples
Besides Synths, `s` can also play back samples: Besides Synths, `s` can also play back samples:
<MiniRepl tune={`s("bd sd,hh*8,misc/2").out()`} /> <MiniRepl tune={`s("bd sd,hh*8,misc/2")`} />
To know which sounds are available, open the [default sample map](https://strudel.tidalcycles.org/EmuSP12.json) 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', sd: 'sd/rytm-01-classic.wav',
hh: 'hh27/000_hh27closedhh.wav', hh: 'hh27/000_hh27closedhh.wav',
}, 'https://raw.githubusercontent.com/tidalcycles/Dirt-Samples/master/'); }, '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. 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', sd: 'sd/rytm-01-classic.wav',
hh: 'hh27/000_hh27closedhh.wav', hh: 'hh27/000_hh27closedhh.wav',
}, 'github:tidalcycles/Dirt-Samples/master/'); }, 'github:tidalcycles/Dirt-Samples/master/');
s("bd sd,hh*8").out()`} s("bd sd,hh*8")`}
/> />
The format is `github:user/repo/branch/`. 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'], sd: ['sd/rytm-01-classic.wav','sd/rytm-00-hard.wav'],
hh: ['hh27/000_hh27closedhh.wav','hh/000_hh3closedhh.wav'], hh: ['hh27/000_hh27closedhh.wav','hh/000_hh3closedhh.wav'],
}, 'github:tidalcycles/Dirt-Samples/master/'); }, 'github:tidalcycles/Dirt-Samples/master/');
s("<bd:0 bd:1>,~ <sd:0 sd:1>,[hh:0 hh:1]*2").out()`} s("<bd:0 bd:1>,~ <sd:0 sd:1>,[hh:0 hh:1]*2")`}
/> />
The `:0` `:1` etc. are the indices of the array. 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'], sd: ['sd/rytm-01-classic.wav','sd/rytm-00-hard.wav'],
hh: ['hh27/000_hh27closedhh.wav','hh/000_hh3closedhh.wav'], hh: ['hh27/000_hh27closedhh.wav','hh/000_hh3closedhh.wav'],
}, 'github:tidalcycles/Dirt-Samples/master/'); }, 'github:tidalcycles/Dirt-Samples/master/');
s("bd,~ sd,hh*4").n("<0 1>").out()`} s("bd,~ sd,hh*4").n("<0 1>")`}
/> />
### Pitched Sounds ### Pitched Sounds
@ -320,7 +287,7 @@ For pitched sounds, you can use `note`, just like with synths:
tune={`samples({ tune={`samples({
"gtr": 'gtr/0001_cleanC.wav', "gtr": 'gtr/0001_cleanC.wav',
}, 'github:tidalcycles/Dirt-Samples/master/'); }, 'github:tidalcycles/Dirt-Samples/master/');
note("g3 [bb3 c4] <g4 f4 eb4 f3>@2").s('gtr').gain(.5).out()`} note("g3 [bb3 c4] <g4 f4 eb4 f3>@2").s('gtr').gain(.5)`}
/> />
Here, the guitar samples will overlap, because they always play till the end. 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', "gtr": 'gtr/0001_cleanC.wav',
}, 'github:tidalcycles/Dirt-Samples/master/'); }, 'github:tidalcycles/Dirt-Samples/master/');
note("g3 [bb3 c4] <g4 f4 eb4 f3>@2").s('gtr').clip(1) note("g3 [bb3 c4] <g4 f4 eb4 f3>@2").s('gtr').clip(1)
.gain(.5).out()`} .gain(.5)`}
/> />
### Base Pitch ### 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' }, "moog": { 'g3': 'moog/005_Mighty%20Moog%20G3.wav' },
}, 'github:tidalcycles/Dirt-Samples/master/'); }, 'github:tidalcycles/Dirt-Samples/master/');
note("g3 [bb3 c4] <g4 f4 eb4 f3>@2").s("gtr,moog").clip(1) note("g3 [bb3 c4] <g4 f4 eb4 f3>@2").s("gtr,moog").clip(1)
.gain(.5).out()`} .gain(.5)`}
/> />
If a sample has no pitch set, `c3` is the default. 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/'); }}, 'github:tidalcycles/Dirt-Samples/master/');
note("g2!2 <bb2 c3>!2, <c4@3 [<eb4 bb3> g4 f4]>") note("g2!2 <bb2 c3>!2, <c4@3 [<eb4 bb3> g4 f4]>")
.s('moog').clip(1) .s('moog').clip(1)
.gain(.5).out()`} .gain(.5)`}
/> />
The sampler will always pick the closest matching sample for the current note! The sampler will always pick the closest matching sample for the current note!