From 93e565f8df66e4dcc3099425834daf07bf315a60 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Sat, 28 May 2022 23:43:42 +0200 Subject: [PATCH] document non random signal functions --- doc.json | 318 ++++++++++++++++++++++++++++++++++----- packages/core/signal.mjs | 46 ++++++ tutorial/tutorial.mdx | 27 ++++ 3 files changed, 350 insertions(+), 41 deletions(-) diff --git a/doc.json b/doc.json index caec3b45..af56ea59 100644 --- a/doc.json +++ b/doc.json @@ -1354,7 +1354,7 @@ "meta": { "range": [ 1178, - 31622 + 31915 ], "filename": "pattern.mjs", "lineno": 17, @@ -2876,11 +2876,61 @@ "___id": "T000002R000651", "___s": true }, + { + "comment": "/**\n *\n * @param {...any} funcs\n * @returns Pattern\n * @example\n * \"<[0 1 2 0]!2 [2 3 4 ~]!2 [[4 5] [4 3] 2 [0 ~]]!2 [0 -3 0 ~]!2>\"\n * .layer(\n * x=>x,\n * x=>x.add(7).late(2),\n * x=>x.add(14).late(4),\n * x=>x.add(21).late(6),\n * )\n * .slow(3)\n * .scale('C2 major')\n * .tone((await piano()).toDestination())\n */", + "meta": { + "range": [ + 21980, + 22055 + ], + "filename": "pattern.mjs", + "lineno": 700, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100007825", + "name": "Pattern#layer", + "type": "MethodDefinition", + "paramnames": [ + "funcs" + ] + }, + "vars": { + "": null + } + }, + "params": [ + { + "type": { + "names": [ + "any" + ] + }, + "variable": true, + "name": "funcs" + } + ], + "returns": [ + { + "description": "

Pattern

" + } + ], + "examples": [ + "\"<[0 1 2 0]!2 [2 3 4 ~]!2 [[4 5] [4 3] 2 [0 ~]]!2 [0 -3 0 ~]!2>\"\n.layer(\n x=>x,\n x=>x.add(7).late(2),\n x=>x.add(14).late(4),\n x=>x.add(21).late(6),\n)\n.slow(3)\n.scale('C2 major')\n.tone((await piano()).toDestination())" + ], + "name": "layer", + "longname": "Pattern#layer", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "___id": "T000002R000683", + "___s": true + }, { "comment": "/**\n * Speed up a pattern by the given factor.\n *\n * @name fast\n * @memberof Pattern\n * @param {number | Pattern} factor speed up factor\n * @returns Pattern\n * @example\n * seq(e5, b4, d5, c5).fast(2)\n */", "meta": { "filename": "pattern.mjs", - "lineno": 735, + "lineno": 750, "columnno": 2, "path": "/home/felix/projects/strudel/packages/core", "code": {} @@ -2918,7 +2968,7 @@ "comment": "/**\n * Slow down a pattern over the given number of cycles.\n *\n * @name slow\n * @memberof Pattern\n * @param {number | Pattern} factor slow down factor\n * @returns Pattern\n * @example\n * seq(e5, b4, d5, c5).slow(2)\n */", "meta": { "filename": "pattern.mjs", - "lineno": 750, + "lineno": 765, "columnno": 2, "path": "/home/felix/projects/strudel/packages/core", "code": {} @@ -2956,11 +3006,11 @@ "comment": "/**\n * Returns a new pattern where every other cycle is played once, twice as\n * fast, and offset in time by one quarter of a cycle. Creates a kind of\n * breakbeat feel.\n * @returns Pattern\n */", "meta": { "range": [ - 27788, - 27884 + 28139, + 28235 ], "filename": "pattern.mjs", - "lineno": 904, + "lineno": 919, "columnno": 2, "path": "/home/felix/projects/strudel/packages/core", "code": { @@ -2992,11 +3042,11 @@ "comment": "/** A discrete value that repeats once per cycle:\n *\n * @param {any} value - The value to repeat\n * @returns {Pattern}\n * @example\n * pure('e4')\n */", "meta": { "range": [ - 35703, - 35907 + 35996, + 36200 ], "filename": "pattern.mjs", - "lineno": 1203, + "lineno": 1217, "columnno": 0, "path": "/home/felix/projects/strudel/packages/core", "code": { @@ -3043,11 +3093,11 @@ "comment": "/** The given items are played at the same time at the same length:\n *\n * @param {...any} items - The items to stack\n * @return {Pattern}\n * @example\n * stack(g3, b3, [e4, d4])\n */", "meta": { "range": [ - 36420, - 36693 + 36713, + 36986 ], "filename": "pattern.mjs", - "lineno": 1230, + "lineno": 1244, "columnno": 0, "path": "/home/felix/projects/strudel/packages/core", "code": { @@ -3095,11 +3145,11 @@ "comment": "/** Concatenation: combines a list of patterns, switching between them successively, one per cycle:\n *\n * synonyms: {@link cat}\n *\n * @param {...any} items - The items to concatenate\n * @return {Pattern}\n * @example\n * slowcat(e5, b4, [d5, c5])\n *\n */", "meta": { "range": [ - 36947, - 37858 + 37240, + 38151 ], "filename": "pattern.mjs", - "lineno": 1247, + "lineno": 1261, "columnno": 0, "path": "/home/felix/projects/strudel/packages/core", "code": { @@ -3147,11 +3197,11 @@ "comment": "/** Concatenation: combines a list of patterns, switching between them successively, one per cycle. Unlike slowcat, this version will skip cycles.\n * @param {...any} items - The items to concatenate\n * @return {Pattern}\n */", "meta": { "range": [ - 38084, - 38356 + 38377, + 38649 ], "filename": "pattern.mjs", - "lineno": 1272, + "lineno": 1286, "columnno": 0, "path": "/home/felix/projects/strudel/packages/core", "code": { @@ -3196,11 +3246,11 @@ "comment": "/** Concatenation: as with {@link slowcat}, but squashes a cycle from each pattern into one cycle\n *\n * Synonyms: {@link seq}, {@link sequence}\n *\n * @param {...any} items - The items to concatenate\n * @return {Pattern}\n * @example\n * fastcat(e5, b4, [d5, c5])\n * // sequence(e5, b4, [d5, c5])\n * // seq(e5, b4, [d5, c5])\n */", "meta": { "range": [ - 38684, - 38766 + 38977, + 39059 ], "filename": "pattern.mjs", - "lineno": 1293, + "lineno": 1307, "columnno": 0, "path": "/home/felix/projects/strudel/packages/core", "code": { @@ -3248,11 +3298,11 @@ "comment": "/** See {@link slowcat} */", "meta": { "range": [ - 38795, - 38854 + 39088, + 39147 ], "filename": "pattern.mjs", - "lineno": 1298, + "lineno": 1312, "columnno": 0, "path": "/home/felix/projects/strudel/packages/core", "code": { @@ -3276,11 +3326,11 @@ "comment": "/** Like {@link fastcat}, but where each step has a temporal weight:\n * @param {...Array} items - The items to concatenate\n * @return {Pattern}\n * @example\n * timeCat([3,e3],[1, g3])\n */", "meta": { "range": [ - 39043, - 39402 + 39336, + 39695 ], "filename": "pattern.mjs", - "lineno": 1308, + "lineno": 1322, "columnno": 0, "path": "/home/felix/projects/strudel/packages/core", "code": { @@ -3328,11 +3378,11 @@ "comment": "/** See {@link fastcat} */", "meta": { "range": [ - 39431, - 39495 + 39724, + 39788 ], "filename": "pattern.mjs", - "lineno": 1321, + "lineno": 1335, "columnno": 0, "path": "/home/felix/projects/strudel/packages/core", "code": { @@ -3356,11 +3406,11 @@ "comment": "/** See {@link fastcat} */", "meta": { "range": [ - 39524, - 39583 + 39817, + 39876 ], "filename": "pattern.mjs", - "lineno": 1326, + "lineno": 1340, "columnno": 0, "path": "/home/felix/projects/strudel/packages/core", "code": { @@ -3380,6 +3430,192 @@ "___id": "T000002R000906", "___s": true }, + { + "comment": "/**\n * A sawtooth signal between 0 and 1.\n *\n * @return {Pattern}\n * @example\n * \"c3 [eb3,g3] g2 [g3,bb3]\".legato(saw.slow(4))\n * @example\n * saw.range(0,8).segment(8).scale('C major').slow(4)\n *\n */", + "meta": { + "range": [ + 1558, + 1598 + ], + "filename": "signal.mjs", + "lineno": 35, + "columnno": 0, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100011947", + "name": "exports.saw", + "type": "VariableDeclaration" + } + }, + "description": "

A sawtooth signal between 0 and 1.

", + "returns": [ + { + "type": { + "names": [ + "Pattern" + ] + } + } + ], + "examples": [ + "\"c3 [eb3,g3] g2 [g3,bb3]\".legato(saw.slow(4))", + "saw.range(0,8).segment(8).scale('C major').slow(4)" + ], + "name": "saw", + "longname": "saw", + "kind": "constant", + "scope": "global", + "___id": "T000002R001036", + "___s": true + }, + { + "comment": "/**\n * A sine signal between 0 and 1.\n *\n * @return {Pattern}\n * @example\n * sine.segment(16).range(0,15).slow(2).scale('C minor')\n *\n */", + "meta": { + "range": [ + 1841, + 1882 + ], + "filename": "signal.mjs", + "lineno": 48, + "columnno": 0, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100011985", + "name": "exports.sine", + "type": "VariableDeclaration" + } + }, + "description": "

A sine signal between 0 and 1.

", + "returns": [ + { + "type": { + "names": [ + "Pattern" + ] + } + } + ], + "examples": [ + "sine.segment(16).range(0,15).slow(2).scale('C minor')" + ], + "name": "sine", + "longname": "sine", + "kind": "constant", + "scope": "global", + "___id": "T000002R001042", + "___s": true + }, + { + "comment": "/**\n * A cosine signal between 0 and 1.\n *\n * @return {Pattern}\n * @example\n * stack(sine,cosine).segment(16).range(0,15).slow(2).scale('C minor')\n *\n */", + "meta": { + "range": [ + 2040, + 2094 + ], + "filename": "signal.mjs", + "lineno": 59, + "columnno": 0, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100011993", + "name": "exports.cosine", + "type": "VariableDeclaration" + } + }, + "description": "

A cosine signal between 0 and 1.

", + "returns": [ + { + "type": { + "names": [ + "Pattern" + ] + } + } + ], + "examples": [ + "stack(sine,cosine).segment(16).range(0,15).slow(2).scale('C minor')" + ], + "name": "cosine", + "longname": "cosine", + "kind": "constant", + "scope": "global", + "___id": "T000002R001044", + "___s": true + }, + { + "comment": "/**\n * A square signal between 0 and 1.\n *\n * @return {Pattern}\n * @example\n * square.segment(2).range(0,7).scale('C minor')\n *\n */", + "meta": { + "range": [ + 2287, + 2348 + ], + "filename": "signal.mjs", + "lineno": 71, + "columnno": 0, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100012023", + "name": "exports.square", + "type": "VariableDeclaration" + } + }, + "description": "

A square signal between 0 and 1.

", + "returns": [ + { + "type": { + "names": [ + "Pattern" + ] + } + } + ], + "examples": [ + "square.segment(2).range(0,7).scale('C minor')" + ], + "name": "square", + "longname": "square", + "kind": "constant", + "scope": "global", + "___id": "T000002R001048", + "___s": true + }, + { + "comment": "/**\n * A triangle signal between 0 and 1.\n *\n * @return {Pattern}\n * @example\n * triangle.segment(2).range(0,7).scale('C minor')\n *\n */", + "meta": { + "range": [ + 2531, + 2569 + ], + "filename": "signal.mjs", + "lineno": 82, + "columnno": 0, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100012048", + "name": "exports.tri", + "type": "VariableDeclaration" + } + }, + "description": "

A triangle signal between 0 and 1.

", + "returns": [ + { + "type": { + "names": [ + "Pattern" + ] + } + } + ], + "examples": [ + "triangle.segment(2).range(0,7).scale('C minor')" + ], + "name": "tri", + "longname": "tri", + "kind": "constant", + "scope": "global", + "___id": "T000002R001052", + "___s": true + }, { "comment": "/**\n *\n * Sends each hap as an OSC message, which can be picked up by SuperCollider or any other OSC-enabled software.\n *\n * @name osc\n * @memberof Pattern\n * @returns Pattern\n */", "meta": { @@ -3407,7 +3643,7 @@ "comment": "/**\n * Change the pitch of each value by the given amount. Expects numbers or note strings as values.\n * The amount can be given as a number of semitones or as a string in interval short notation.\n * If you don't care about enharmonic correctness, just use numbers. Otherwise, pass the interval of\n * the form: ST where S is the degree number and T the type of interval with\n *\n * - M = major\n * - m = minor\n * - P = perfect\n * - A = augmented\n * - d = diminished\n *\n * Examples intervals:\n *\n * - 1P = unison\n * - 3M = major third\n * - 3m = minor third\n * - 4P = perfect fourth\n * - 4A = augmented fourth\n * - 5P = perfect fifth\n * - 5d = diminished fifth\n *\n * @param {string | number} amount Either number of semitones or interval string.\n * @returns Pattern\n * @memberof Pattern\n * @name transpose\n * @example\n * \"c2 c3\".fast(2).transpose(\"<0 -2 5 3>\".slow(2)).transpose(0)\n * @example\n * \"c2 c3\".fast(2).transpose(\"<1P -2M 4P 3m>\".slow(2)).transpose(0)\n */", "meta": { "filename": "tonal.mjs", - "lineno": 45, + "lineno": 46, "columnno": 0, "path": "/home/felix/projects/strudel/packages/tonal", "code": {} @@ -3439,14 +3675,14 @@ "scope": "static", "longname": "Pattern.transpose", "kind": "member", - "___id": "T000002R003716", + "___id": "T000002R003717", "___s": true }, { "comment": "/**\n * Transposes notes inside the scale by the number of steps.\n * Expected to be called on a Pattern which already has a {@link Pattern#scale}\n *\n * @memberof Pattern\n * @name scaleTranspose\n * @param {offset} offset number of steps inside the scale\n * @returns Pattern\n * @example\n * \"-8 [2,4,6]\"\n * .scale('C4 bebop major')\n * .scaleTranspose(\"<0 -1 -2 -3 -4 -5 -6 -4>\")\n */", "meta": { "filename": "tonal.mjs", - "lineno": 98, + "lineno": 99, "columnno": 0, "path": "/home/felix/projects/strudel/packages/tonal", "code": {} @@ -3476,14 +3712,14 @@ "scope": "static", "longname": "Pattern.scaleTranspose", "kind": "member", - "___id": "T000002R003720", + "___id": "T000002R003721", "___s": true }, { "comment": "/**\n * Turns numbers into notes in the scale (zero indexed). Also sets scale for other scale operations, like {@link Pattern#scaleTranspose}.\n *\n * The scale name has the form \"TO? N\" wher\n *\n * - T = Tonic\n * - O = Octave (optional, defaults to 3)\n * - N = Name of scale, available names can be found [here](https://github.com/tonaljs/tonal/blob/main/packages/scale-type/data.ts).\n *\n * @memberof Pattern\n * @name scale\n * @param {string} scale Name of scale\n * @returns Pattern\n * @example \n * \"0 2 4 6 4 2\"\n * .scale(seq('C2 major', 'C2 minor').slow(2))\n */", "meta": { "filename": "tonal.mjs", - "lineno": 124, + "lineno": 125, "columnno": 0, "path": "/home/felix/projects/strudel/packages/tonal", "code": {} @@ -3513,7 +3749,7 @@ "scope": "static", "longname": "Pattern.scale", "kind": "member", - "___id": "T000002R003722", + "___id": "T000002R003723", "___s": true }, { @@ -3550,7 +3786,7 @@ "scope": "static", "longname": "Pattern.voicings", "kind": "member", - "___id": "T000002R003747", + "___id": "T000002R003748", "___s": true }, { @@ -3632,7 +3868,7 @@ "/home/felix/projects/strudel/packages/xen/tunejs.js", "/home/felix/projects/strudel/packages/xen/xen.mjs" ], - "___id": "T000002R014016", + "___id": "T000002R014017", "___s": true } ] diff --git a/packages/core/signal.mjs b/packages/core/signal.mjs index 01fdd768..b3eb2d3b 100644 --- a/packages/core/signal.mjs +++ b/packages/core/signal.mjs @@ -22,17 +22,63 @@ export const signal = (func) => { export const isaw = signal((t) => 1 - (t % 1)); export const isaw2 = isaw._toBipolar(); +/** + * A sawtooth signal between 0 and 1. + * + * @return {Pattern} + * @example + * "c3 [eb3,g3] g2 [g3,bb3]".legato(saw.slow(4)) + * @example + * saw.range(0,8).segment(8).scale('C major').slow(4) + * + */ export const saw = signal((t) => t % 1); export const saw2 = saw._toBipolar(); export const sine2 = signal((t) => Math.sin(Math.PI * 2 * t)); + +/** + * A sine signal between 0 and 1. + * + * @return {Pattern} + * @example + * sine.segment(16).range(0,15).slow(2).scale('C minor') + * + */ export const sine = sine2._fromBipolar(); + + +/** + * A cosine signal between 0 and 1. + * + * @return {Pattern} + * @example + * stack(sine,cosine).segment(16).range(0,15).slow(2).scale('C minor') + * + */ export const cosine = sine._early(Fraction(1).div(4)); export const cosine2 = sine2._early(Fraction(1).div(4)); + +/** + * A square signal between 0 and 1. + * + * @return {Pattern} + * @example + * square.segment(2).range(0,7).scale('C minor') + * + */ export const square = signal((t) => Math.floor((t * 2) % 2)); export const square2 = square._toBipolar(); +/** + * A triangle signal between 0 and 1. + * + * @return {Pattern} + * @example + * triangle.segment(2).range(0,7).scale('C minor') + * + */ export const tri = fastcat(isaw, saw); export const tri2 = fastcat(isaw2, saw2); diff --git a/tutorial/tutorial.mdx b/tutorial/tutorial.mdx index f2eace19..077d6f6d 100644 --- a/tutorial/tutorial.mdx +++ b/tutorial/tutorial.mdx @@ -731,6 +731,33 @@ The following functions will return a pattern. We will see later what that means {{ '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 Superdirt via OSC In mainline tidal, the actual sound is generated via Superdirt, which runs inside Supercollider.