diff --git a/packages/core/pattern.mjs b/packages/core/pattern.mjs index d9b63d14..7f5ad154 100644 --- a/packages/core/pattern.mjs +++ b/packages/core/pattern.mjs @@ -513,11 +513,14 @@ export class Pattern { } /** - * Assumes a numerical pattern, containing unipolar values in the range 0 .. - * 1. Returns a new pattern with values scaled to the given min/max range. - * @param {Number} min - * @param {Number} max + * Assumes a numerical pattern, containing unipolar values in the range 0 .. 1. + * Returns a new pattern with values scaled to the given min/max range. + * Most useful in combination with continuous patterns. + * @name range + * @memberof Pattern * @returns Pattern + * @example + * s("bd sd,hh*4").cutoff(sine.range(500,2000).slow(4)).out() */ range(min, max) { return this.mul(max - min).add(min); @@ -741,7 +744,7 @@ export class Pattern { * @param {number | Pattern} factor speed up factor * @returns Pattern * @example - * seq(e5, b4, d5, c5).fast(2) // "[e5 b4 d5 c5]*2" + * s(" hh").fast(2).out() // s("[ hh]*2").out() */ _fast(factor) { const fastQuery = this.withQueryTime((t) => t.mul(factor)); @@ -756,7 +759,7 @@ export class Pattern { * @param {number | Pattern} factor slow down factor * @returns Pattern * @example - * seq(e5, b4, d5, c5).slow(2) // "[e5 b4 d5 c5]/2" + * s(" hh").slow(2).out() // s("[ hh]/2").out() */ _slow(factor) { return this._fast(Fraction(1).div(factor)); @@ -847,6 +850,17 @@ export class Pattern { return this._zoom(0, t)._slow(t); } + /** + * Applies the given structure to the pattern: + * + * @name struct + * @memberof Pattern + * @returns Pattern + * @example + * "c3,eb3,g3" + * .struct("x ~ x ~ ~ x ~ x ~ ~ ~ x ~ x ~ ~") + * .slow(4).note().out() + */ // struct(...binary_pats) { // // Re structure the pattern according to a binary pattern (false values are dropped) // const binary_pat = sequence(binary_pats); @@ -917,7 +931,7 @@ export class Pattern { * @example * note("c3 d3 e3 g3").every(4, x=>x.rev()).out() */ - every(n, func) { + every(n, func) { const pat = this; const pats = Array(n - 1).fill(pat); // pats.unshift(func(pat)); @@ -940,7 +954,7 @@ export class Pattern { pats.unshift(func(pat)); return slowcatPrime(...pats); } - + /** * Applies the given function every n cycles, starting from the last cycle. * @name each @@ -951,7 +965,7 @@ export class Pattern { * @example * note("c3 d3 e3 g3").every(4, x=>x.rev()).out() */ - each(n, func) { + each(n, func) { const pat = this; const pats = Array(n - 1).fill(pat); pats.push(func(pat)); @@ -1277,12 +1291,11 @@ Pattern.prototype.factories = { // Nothing export const silence = new Pattern((_) => []); -/** A discrete value that repeats once per cycle: +/** A discrete value that repeats once per cycle. * - * @param {any} value - The value to repeat * @returns {Pattern} * @example - * pure('e4') + * pure('e4') // "e4" */ export function pure(value) { function query(state) { @@ -1312,12 +1325,11 @@ export function reify(thing) { return pure(thing); } -/** The given items are played at the same time at the same length: +/** The given items are played at the same time at the same length. * - * @param {...any} items - The items to stack * @return {Pattern} * @example - * stack(g3, b3, [e4, d4]) + * stack(g3, b3, [e4, d4]) // "g3,b3,[e4,d4]" */ export function stack(...pats) { // Array test here is to avoid infinite recursions.. @@ -1330,7 +1342,6 @@ export function stack(...pats) { * * synonyms: {@link cat} * - * @param {...any} items - The items to concatenate * @return {Pattern} * @example * slowcat(e5, b4, [d5, c5]) @@ -1386,16 +1397,22 @@ export function fastcat(...pats) { return slowcat(...pats)._fast(pats.length); } -/** See {@link slowcat} */ +/** The given items are con**cat**enated, where each one takes one cycle. Synonym: slowcat + * + * @param {...any} items - The items to concatenate + * @return {Pattern} + * @example + * cat(e5, b4, [d5, c5]) // "" + * + */ export function cat(...pats) { return slowcat(...pats); } -/** Like {@link fastcat}, but where each step has a temporal weight: - * @param {...Array} items - The items to concatenate +/** Like {@link seq}, but each step has a length, relative to the whole. * @return {Pattern} * @example - * timeCat([3,e3],[1, g3]) + * timeCat([3,e3],[1, g3]) // "e3@3 g3" */ export function timeCat(...timepats) { const total = timepats.map((a) => a[0]).reduce((a, b) => a.add(b), Fraction(0)); @@ -1414,7 +1431,11 @@ export function sequence(...pats) { return fastcat(...pats); } -/** See {@link fastcat} */ +/** Like **cat**, but the items are crammed into one cycle. Synonyms: fastcat, sequence + * @example + * seq(e5, b4, [d5, c5]) // "e5 b4 [d5 c5]" + * + */ export function seq(...pats) { return fastcat(...pats); } @@ -1463,6 +1484,14 @@ export function pm(...args) { polymeter(...args); } +/* + * Plays the given items at the same time, within the same length: + * @param {...any} items - The items to play + * @return {Pattern} + * @example + * + * + */ export function polyrhythm(...xs) { const seqs = xs.map((a) => sequence(a)); diff --git a/packages/core/signal.mjs b/packages/core/signal.mjs index f7c33152..8637c30e 100644 --- a/packages/core/signal.mjs +++ b/packages/core/signal.mjs @@ -74,7 +74,7 @@ export const square2 = square._toBipolar(); * * @return {Pattern} * @example - * triangle.segment(2).range(0,7).scale('C minor') + * tri.segment(8).range(0,7).scale('C minor') * */ export const tri = fastcat(isaw, saw); diff --git a/tutorial/tutorial.mdx b/tutorial/tutorial.mdx index dc963734..46da410f 100644 --- a/tutorial/tutorial.mdx +++ b/tutorial/tutorial.mdx @@ -413,65 +413,21 @@ The above is the same as: Using strings, you can also use "#". -## Functions that create Patterns +## Pattern Factories -The following functions will return a pattern. We will see later what that means. +The following functions will return a pattern. -## pure(value) - -To create a pattern from a value, you can wrap the value in pure: - - +{{ 'pure' | jsdoc }} Most of the time, you won't need that function as input values of pattern creating functions are purified by default. -### cat(...values) +{{ 'cat' | jsdoc }} -The given items are con**cat**enated, where each one takes one cycle: +{{ 'seq' | jsdoc }} - +{{ 'stack' | jsdoc }} -- Square brackets will create a subsequence -- The function **slowcat** does the same as **cat**. - -### seq(...values) - -Like **cat**, but the items are crammed into one cycle: - - - -- Synonyms: **fastcat**, **sequence** - -### stack(...values) - -The given items are played at the same time at the same length: - - - -- Square Brackets will create a subsequence - -### Nesting functions - -You can nest functions inside one another: - - - -The above is equivalent to - -"`} /> - -### timeCat(...[weight,value]) - -Like with "@" in mini notation, we can specify weights to the items in a sequence: - - +{{ 'timeCat' | jsdoc }} + + +## Combining Patterns + +You can freely mix JS patterns, mini patterns and values! For example, this pattern: + + + +...is equivalent to: + + + +... as well as: + +"`} /> + +While mini notation is almost always shorter, it only has a handful of modifiers: \* / ! @. +When using JS patterns, there is a lot more you can do. + ## Time Modifiers The following functions modify a pattern temporal structure in some way. @@ -505,18 +498,9 @@ The following functions modify a pattern temporal structure in some way. {{ 'Pattern.rev' | jsdoc }} -### struct(binary_pat) +{{ 'Pattern.struct' | jsdoc }} -Applies the given structure to the pattern: - - - -This is also useful to sample signals: - - +{{ 'Pattern.legato' | jsdoc }} ## Conditional Modifiers @@ -616,7 +600,36 @@ Like layer, but with a single function: ".scale('C minor').apply(scaleTranspose("0,2,4"))`} /> -## Randomness +{{ 'Pattern.range' | jsdoc }} + +## Continuous Signals + +Signals are patterns with continuous values, meaning they have theoretically infinite steps. +They can provide streams of numbers that can be sampled at discrete points in time. + +## + +{{ 'saw' | jsdoc }} + +{{ 'sine' | jsdoc }} + +{{ 'cosine' | jsdoc }} + +{{ 'tri' | jsdoc }} + +{{ 'square' | jsdoc }} + +### Ranges from -1 to 1 + +There is also `saw2`, `sine2`, `cosine2`, `tri2` and `square2` which have a range from -1 to 1! + +{{ 'rand' | jsdoc }} + +{{ 'perlin' | jsdoc }} + +{{ 'irand' | jsdoc }} + +## Random Modifiers These methods add random behavior to your Patterns. @@ -648,12 +661,6 @@ These methods add random behavior to your Patterns. {{ 'Pattern.always' | jsdoc }} -{{ 'rand' | jsdoc }} - -{{ 'perlin' | jsdoc }} - -{{ 'irand' | jsdoc }} - ## Tone API To make the sounds more interesting, we can use Tone.js instruments ands effects. @@ -903,67 +910,6 @@ If you want to contribute in another way, either

-# API Docs - -The following is generated from the source documentation. - -## Pattern Factories - -The following functions will return a pattern. We will see later what that means. - -{{ 'pure' | jsdoc }} - -{{ 'slowcat' | jsdoc }} - -{{ 'fastcat' | jsdoc }} - -{{ 'stack' | jsdoc }} - -{{ 'timeCat' | jsdoc }} - -{{ 'polyrhythm' | jsdoc }} - -## Pattern Modifiers - -{{ 'Pattern.slow' | jsdoc }} - -{{ 'Pattern.fast' | jsdoc }} - -{{ 'Pattern.early' | jsdoc }} - -{{ 'Pattern.late' | jsdoc }} - -{{ 'Pattern.rev' | jsdoc }} - -{{ 'Pattern.legato' | jsdoc }} - -## Continuous Signals - -Signals are patterns with continuous values, meaning they have theoretically infinite steps. -They can provide streams of numbers that can be sampled at discrete points in time. - -{{ 'Pattern.range' | jsdoc }} - -{{ 'saw' | jsdoc }} - -{{ 'saw2' | jsdoc }} - -{{ 'sine' | jsdoc }} - -{{ 'sine2' | jsdoc }} - -{{ 'cosine' | jsdoc }} - -{{ 'cosine2' | jsdoc }} - -{{ 'tri' | jsdoc }} - -{{ 'tri2' | jsdoc }} - -{{ 'square' | jsdoc }} - -{{ 'square2' | jsdoc }} - ## Using Samples with Webdirt You can use the powerful sampling engine [Webdirt](https://github.com/dktr0/WebDirt) with Strudel.