Skip to content

Commit

Permalink
Merge pull request #228 from tidalcycles/just-another-docs-branch
Browse files Browse the repository at this point in the history
Just another docs branch
  • Loading branch information
felixroos committed Oct 26, 2022
2 parents cf11472 + 603c55f commit 2ed290a
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 75 deletions.
13 changes: 8 additions & 5 deletions packages/core/controls.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,12 @@ const generic_params = [
*/
['f', 'accelerate', 'a pattern of numbers that speed up (or slow down) samples while they play.'],
/**
* Like {@link amp}, but exponential.
* Controls the gain by an exponential amount.
*
* @name gain
* @param {number | Pattern} amount gain.
* @example
* s("bd*8").gain(".7*2 1 .7*2 1 .7 1").osc()
* s("hh*8").gain(".4!2 1 .4!2 1 .4 1").out()
*
*/
[
Expand Down Expand Up @@ -147,10 +147,12 @@ const generic_params = [
/**
* a pattern of numbers from 0 to 1. Skips the beginning of each sample, e.g. `0.25` to cut off the first quarter from each sample.
*
* @memberof Pattern
* @name begin
* @param {number | Pattern} amount between 0 and 1, where 1 is the length of the sample
* @example
* s("rave").begin("<0 .25 .5 .75>").osc()
* samples({ rave: 'rave/AREUREADY.wav' }, 'github:tidalcycles/Dirt-Samples/master/')
* s("rave").begin("<0 .25 .5 .75>").out()
*
*/
[
Expand All @@ -159,12 +161,13 @@ const generic_params = [
'a pattern of numbers from 0 to 1. Skips the beginning of each sample, e.g. `0.25` to cut off the first quarter from each sample.',
],
/**
* The same as {@link begin}, but cuts off the end off each sample.
* The same as .begin, but cuts off the end off each sample.
*
* @memberof Pattern
* @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>").osc()
* s("bd*2,ho*4").end("<.1 .2 .5 1>").out()
*
*/
[
Expand Down
17 changes: 13 additions & 4 deletions packages/core/euclid.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,19 @@ const euclid = (pulses, steps, rotation = 0) => {
* describe a large number of rhythms used in the most important music world traditions.
*
* @memberof Pattern
* @name euclid
* @param {number} pulses the number of onsets / beats
* @param {number} steps the number of steps to fill
* @param {number} rotation (optional) offset in steps
* @returns Pattern
* @example // The Cuban tresillo pattern.
* "c3".euclid(3,8)
* @example
* // The Cuban tresillo pattern.
* n("c3").euclid(3,8).out()
*/

/**
* @example // A thirteenth century Persian rhythm called Khafif-e-ramal.
* "c3".euclid(2,5)
* n("c3").euclid(2,5)
* @example // The archetypal pattern of the Cumbia from Colombia, as well as a Calypso rhythm from Trinidad.
* "c3".euclid(3,4)
* @example // Another thirteenth century Persian rhythm by the name of Khafif-e-ramal, as well as a Rumanian folk-dance rhythm.
Expand Down Expand Up @@ -79,7 +84,11 @@ Pattern.prototype.euclid = function (pulses, steps, rotation = 0) {
};

/**
* Similar to {@link Pattern#euclid}, but each pulse is held until the next pulse, so there will be no gaps.
* Similar to `.euclid`, but each pulse is held until the next pulse, so there will be no gaps.
* @name euclidLegato
* @memberof Pattern
* @example
* n("g2").decay(.1).sustain(.3).euclidLegato(3,8).out()
*/
Pattern.prototype.euclidLegato = function (pulses, steps, rotation = 0) {
const bin_pat = euclid(pulses, steps, rotation);
Expand Down
100 changes: 95 additions & 5 deletions packages/core/pattern.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,11 @@ export class Pattern {
/**
* Assumes a numerical pattern. Returns a new pattern with all values rounded
* to the nearest integer.
* @name round
* @memberof Pattern
* @returns Pattern
* @example
* "0.5 1.5 2.5".round().scale('C major')
*/
round() {
return this._asNumber().fmap((v) => Math.round(v));
Expand Down Expand Up @@ -695,6 +699,13 @@ export class Pattern {
return this.fmap(func)._squeezeJoin();
}

/**
* Like layer, but with a single function:
* @name apply
* @memberof Pattern
* @example
* "<c3 eb3 g3>".scale('C minor').apply(scaleTranspose("0,2,4"))
*/
_apply(func) {
return func(this);
}
Expand Down Expand Up @@ -772,7 +783,7 @@ export class Pattern {
_focus(b, e) {
return this._fast(Fraction(1).div(e.sub(b))).late(b.cyclePos());
}

_focusSpan(span) {
return this._focus(span.begin, span.end);
}
Expand Down Expand Up @@ -818,6 +829,20 @@ export class Pattern {
return this.fmap((x) => pure(x)._fast(factor))._squeezeJoin();
}

/**
* Cuts each sample into the given number of parts, allowing you to explore a technique known as 'granular synthesis'.
* It turns a pattern of samples into a pattern of parts of samples.
* @name chop
* @memberof Pattern
* @returns Pattern
* @example
* samples({ rhodes: 'https://cdn.freesound.org/previews/132/132051_316502-lq.mp3' })
* s("rhodes")
* .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);
const slice_objects = slices.map((i) => ({ begin: i / n, end: (i + 1) / n }));
Expand Down Expand Up @@ -1189,6 +1214,9 @@ export class Pattern {
* @name echo
* @memberof Pattern
* @returns Pattern
* @param {number} times how many times to repeat
* @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()
*/
Expand Down Expand Up @@ -1261,16 +1289,40 @@ export class Pattern {
return this.withHapSpan((span) => new TimeSpan(span.begin, span.begin.add(value)));
}

// sets hap relative duration of haps
/**
*
* Multiplies the hap duration with the given factor.
* @name legato
* @memberof Pattern
* @example
* n("c3 eb3 g3 c4").legato("<.25 .5 1 2>").out()
*/
_legato(value) {
return this.withHapSpan((span) => new TimeSpan(span.begin, span.begin.add(span.end.sub(span.begin).mul(value))));
}

/**
*
* Sets the velocity from 0 to 1. Is multiplied together with gain.
* @name velocity
* @example
* s("hh*8")
* .gain(".4!2 1 .4!2 1 .4 1")
* .velocity(".4 1").out()
*/
_velocity(velocity) {
return this._withContext((context) => ({ ...context, velocity: (context.velocity || 1) * velocity }));
}

// move this to controls? (speed and unit are controls)
/**
* Makes the sample fit the given number of cycles by changing the speed.
* @name loopAt
* @memberof Pattern
* @returns Pattern
* @example
* samples({ rhodes: 'https://cdn.freesound.org/previews/132/132051_316502-lq.mp3' })
* s("rhodes").loopAt(4,1).out()
*/
_loopAt(factor, cps = 1) {
return this.speed((1 / factor) * cps)
.unit('c')
Expand Down Expand Up @@ -1326,9 +1378,48 @@ function _composeOp(a, b, func) {
keepif: [(a, b) => (b ? a : undefined)],

// numerical functions
/**
*
* Assumes a pattern of numbers. Adds the given number to each item in the pattern.
* @name add
* @memberof Pattern
* @example
* // Here, the triad 0, 2, 4 is shifted by different amounts
* "0 2 4".add("<0 3 4 0>").scale('C major')
* // Without add, the equivalent would be:
* // "<[0 2 4] [3 5 7] [4 6 8] [0 2 4]>".scale('C major')
* @example
* // You can also use add with notes:
* "c3 e3 g3".add("<0 5 7 0>")
* // Behind the scenes, the notes are converted to midi numbers:
* // "48 52 55".add("<0 5 7 0>")
*/
add: [(a, b) => a + b, numOrString], // support string concatenation
/**
*
* Like add, but the given numbers are subtracted.
* @name sub
* @memberof Pattern
* @example
* "0 2 4".sub("<0 1 2 3>").scale('C4 minor')
* // See add for more information.
*/
sub: [(a, b) => a - b, num],
/**
*
* Multiplies each number by the given factor.
* @name mul
* @memberof Pattern
* @example
* "1 1.5 [1.66, <2 2.33>]".mul(150).freq().out()
*/
mul: [(a, b) => a * b, num],
/**
*
* Divides each number by the given factor.
* @name div
* @memberof Pattern
*/
div: [(a, b) => a / b, num],
mod: [mod, num],
pow: [Math.pow, num],
Expand Down Expand Up @@ -1370,8 +1461,7 @@ function _composeOp(a, b, func) {
// avoid union, as we want to throw away the value of 'b' completely
result = pat['_op' + how](other, (a) => (b) => op(a, b));
result = result._removeUndefineds();
}
else {
} else {
result = pat['_op' + how](other, (a) => (b) => _composeOp(a, b, op));
}
return result;
Expand Down
3 changes: 3 additions & 0 deletions packages/webaudio/reverb.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@ if (typeof AudioContext !== 'undefined') {
return convolver;
};
}

// TODO: make the reverb more exciting
// check out https://blog.gskinner.com/archives/2019/02/reverb-web-audio-api.html
11 changes: 5 additions & 6 deletions tutorial/Tutorial.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,24 @@ import '@strudel.cycles/react/dist/style.css';

ReactDOM.render(
<React.StrictMode>
<div className="min-h-screen">
<header className="flex-none flex justify-start sticky top-0 z-[2] w-full h-16 px-2 items-center border-b border-gray-200 bg-white">
<div className="p-4 w-full flex justify-between">
<div className="min-h-screen bg-slate-900">
<header className="flex-none flex justify-start sticky top-0 z-[2] w-full h-16 px-2 items-center border-b border-slate-500 text-white bg-slate-900 z-[100]">
<div className="p-4 w-full flex justify-between items-center">
<div className="flex items-center space-x-2">
<img src={'https://tidalcycles.org/img/logo.svg'} className="Tidal-logo w-10 h-10" alt="logo" />
<h1 className="text-xl cursor-pointer" onClick={() => window.scrollTo(0, 0)}>
Strudel Tutorial
</h1>
</div>
{!window.location.href.includes('localhost') && (
<div className="flex space-x-4">
<div className="flex space-x-4 text-slate-200">
<a href="../">go to REPL</a>
</div>
)}
</div>
</header>
<main className="p-4 pl-6 max-w-3xl prose">
<main className="p-4 pl-6 max-w-3xl prose prose-invert">
<Tutorial />
{/* <ApiDoc /> */}
</main>
</div>
</React.StrictMode>,
Expand Down

0 comments on commit 2ed290a

Please sign in to comment.