add note calls everywhere

This commit is contained in:
Felix Roos 2022-10-29 17:38:54 +02:00
parent 5d7e46b246
commit 08c4c641ec
6 changed files with 95 additions and 62 deletions

View File

@ -32,52 +32,52 @@ const euclid = (pulses, steps, rotation = 0) => {
* @returns Pattern
* @example
* // The Cuban tresillo pattern.
* n("c3").euclid(3,8)
* note("c3").euclid(3,8)
*/
/**
* @example // A thirteenth century Persian rhythm called Khafif-e-ramal.
* n("c3").euclid(2,5)
* note("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)
* note("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.
* "c3".euclid(3,5,2)
* note("c3").euclid(3,5,2)
* @example // A Ruchenitza rhythm used in a Bulgarian folk-dance.
* "c3".euclid(3,7)
* note("c3").euclid(3,7)
* @example // The Cuban tresillo pattern.
* "c3".euclid(3,8)
* note("c3").euclid(3,8)
* @example // Another Ruchenitza Bulgarian folk-dance rhythm.
* "c3".euclid(4,7)
* note("c3").euclid(4,7)
* @example // The Aksak rhythm of Turkey.
* "c3".euclid(4,9)
* note("c3").euclid(4,9)
* @example // The metric pattern used by Frank Zappa in his piece titled Outside Now.
* "c3".euclid(4,11)
* note("c3").euclid(4,11)
* @example // Yields the York-Samai pattern, a popular Arab rhythm.
* "c3".euclid(5,6)
* note("c3").euclid(5,6)
* @example // The Nawakhat pattern, another popular Arab rhythm.
* "c3".euclid(5,7)
* note("c3").euclid(5,7)
* @example // The Cuban cinquillo pattern.
* "c3".euclid(5,8)
* note("c3").euclid(5,8)
* @example // A popular Arab rhythm called Agsag-Samai.
* "c3".euclid(5,9)
* note("c3").euclid(5,9)
* @example // The metric pattern used by Moussorgsky in Pictures at an Exhibition.
* "c3".euclid(5,11)
* note("c3").euclid(5,11)
* @example // The Venda clapping pattern of a South African childrens song.
* "c3".euclid(5,12)
* note("c3").euclid(5,12)
* @example // The Bossa-Nova rhythm necklace of Brazil.
* "c3".euclid(5,16)
* note("c3").euclid(5,16)
* @example // A typical rhythm played on the Bendir (frame drum).
* "c3".euclid(7,8)
* note("c3").euclid(7,8)
* @example // A common West African bell pattern.
* "c3".euclid(7,12)
* note("c3").euclid(7,12)
* @example // A Samba rhythm necklace from Brazil.
* "c3".euclid(7,16,14)
* note("c3").euclid(7,16,14)
* @example // A rhythm necklace used in the Central African Republic.
* "c3".euclid(9,16)
* note("c3").euclid(9,16)
* @example // A rhythm necklace of the Aka Pygmies of Central Africa.
* "c3".euclid(11,24,14)
* note("c3").euclid(11,24,14)
* @example // Another rhythm necklace of the Aka Pygmies of the upper Sangha.
* "c3".euclid(13,24,5)
* note("c3").euclid(13,24,5)
*/
Pattern.prototype.euclid = function (pulses, steps, rotation = 0) {
return this.struct(euclid(pulses, steps, rotation));

View File

@ -472,7 +472,7 @@ export class Pattern {
* @memberof Pattern
* @returns Pattern
* @example
* "0.5 1.5 2.5".round().scale('C major')
* "0.5 1.5 2.5".round().scale('C major').note()
*/
round() {
return this._asNumber().fmap((v) => Math.round(v));
@ -704,7 +704,7 @@ export class Pattern {
* @name apply
* @memberof Pattern
* @example
* "<c3 eb3 g3>".scale('C minor').apply(scaleTranspose("0,2,4"))
* "<c3 eb3 g3>".scale('C minor').apply(scaleTranspose("0,2,4")).note()
*/
_apply(func) {
return func(this);
@ -925,9 +925,9 @@ export class Pattern {
* @memberof Pattern
* @returns Pattern
* @example
* "c3,eb3,g3"
* note("c3,eb3,g3")
* .struct("x ~ x ~ ~ x ~ x ~ ~ ~ x ~ x ~ ~")
* .slow(4).note()
* .slow(4)
*/
// struct(...binary_pats) {
// // Re structure the pattern according to a binary pattern (false values are dropped)
@ -984,7 +984,7 @@ export class Pattern {
* @param {function} func
* @returns Pattern
* @example
* "c3 eb3 g3".when("<0 1>/2", x=>x.sub(5))
* "c3 eb3 g3".when("<0 1>/2", x=>x.sub(5)).note()
*/
when(binary_pat, func) {
//binary_pat = sequence(binary_pat)
@ -1003,7 +1003,7 @@ export class Pattern {
* @param {function} func function to apply
* @returns Pattern
* @example
* "c3 eb3 g3".off(1/8, x=>x.add(7))
* "c3 eb3 g3".off(1/8, x=>x.add(7)).note()
*/
off(time_pat, func) {
return stack(this, func(this.late(time_pat)));
@ -1077,7 +1077,7 @@ export class Pattern {
* @memberof Pattern
* @returns Pattern
* @example
* "c3 d3 e3 g3".rev()
* note("c3 d3 e3 g3").rev()
*/
rev() {
const pat = this;
@ -1297,7 +1297,7 @@ export class Pattern {
* @name legato
* @memberof Pattern
* @example
* n("c3 eb3 g3 c4").legato("<.25 .5 1 2>")
* note("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))));
@ -1387,14 +1387,14 @@ function _composeOp(a, b, func) {
* @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')
* "0 2 4".add("<0 3 4 0>").scale('C major').note()
* // Without add, the equivalent would be:
* // "<[0 2 4] [3 5 7] [4 6 8] [0 2 4]>".scale('C major')
* // "<[0 2 4] [3 5 7] [4 6 8] [0 2 4]>".scale('C major').note()
* @example
* // You can also use add with notes:
* "c3 e3 g3".add("<0 5 7 0>")
* "c3 e3 g3".add("<0 5 7 0>").note()
* // Behind the scenes, the notes are converted to midi numbers:
* // "48 52 55".add("<0 5 7 0>")
* // "48 52 55".add("<0 5 7 0>").note()
*/
add: [(a, b) => a + b, numOrString], // support string concatenation
/**
@ -1403,7 +1403,7 @@ function _composeOp(a, b, func) {
* @name sub
* @memberof Pattern
* @example
* "0 2 4".sub("<0 1 2 3>").scale('C4 minor')
* "0 2 4".sub("<0 1 2 3>").scale('C4 minor').note()
* // See add for more information.
*/
sub: [(a, b) => a - b, num],
@ -1579,7 +1579,7 @@ export function reify(thing) {
*
* @return {Pattern}
* @example
* stack(g3, b3, [e4, d4]) // "g3,b3,[e4,d4]"
* stack(g3, b3, [e4, d4]).note() // "g3,b3,[e4,d4]".note()
*/
export function stack(...pats) {
// Array test here is to avoid infinite recursions..
@ -1652,7 +1652,7 @@ export function fastcat(...pats) {
* @param {...any} items - The items to concatenate
* @return {Pattern}
* @example
* cat(e5, b4, [d5, c5]) // "<e5 b4 [d5 c5]>"
* cat(e5, b4, [d5, c5]).note() // "<e5 b4 [d5 c5]>".note()
*
*/
export function cat(...pats) {
@ -1662,7 +1662,7 @@ export function cat(...pats) {
/** Like {@link seq}, but each step has a length, relative to the whole.
* @return {Pattern}
* @example
* timeCat([3,e3],[1, g3]) // "e3@3 g3"
* timeCat([3,e3],[1, g3]).note() // "e3@3 g3".note()
*/
export function timeCat(...timepats) {
const total = timepats.map((a) => a[0]).reduce((a, b) => a.add(b), Fraction(0));
@ -1683,7 +1683,7 @@ export function sequence(...pats) {
/** Like **cat**, but the items are crammed into one cycle. Synonyms: fastcat, sequence
* @example
* seq(e5, b4, [d5, c5]) // "e5 b4 [d5 c5]"
* seq(e5, b4, [d5, c5]).note() // "e5 b4 [d5 c5]".note()
*
*/
export function seq(...pats) {

View File

@ -27,9 +27,9 @@ export const isaw2 = isaw._toBipolar();
*
* @return {Pattern}
* @example
* "c3 [eb3,g3] g2 [g3,bb3]".legato(saw.slow(4))
* "c3 [eb3,g3] g2 [g3,bb3]".legato(saw.slow(4)).note()
* @example
* saw.range(0,8).segment(8).scale('C major').slow(4)
* saw.range(0,8).segment(8).scale('C major').slow(4).note()
*
*/
export const saw = signal((t) => t % 1);
@ -42,7 +42,7 @@ export const sine2 = signal((t) => Math.sin(Math.PI * 2 * t));
*
* @return {Pattern}
* @example
* sine.segment(16).range(0,15).slow(2).scale('C minor')
* sine.segment(16).range(0,15).slow(2).scale('C minor').note()
*
*/
export const sine = sine2._fromBipolar();
@ -52,7 +52,7 @@ export const sine = sine2._fromBipolar();
*
* @return {Pattern}
* @example
* stack(sine,cosine).segment(16).range(0,15).slow(2).scale('C minor')
* stack(sine,cosine).segment(16).range(0,15).slow(2).scale('C minor').note()
*
*/
export const cosine = sine._early(Fraction(1).div(4));
@ -63,7 +63,7 @@ export const cosine2 = sine2._early(Fraction(1).div(4));
*
* @return {Pattern}
* @example
* square.segment(2).range(0,7).scale('C minor')
* square.segment(2).range(0,7).scale('C minor').note()
*
*/
export const square = signal((t) => Math.floor((t * 2) % 2));

View File

@ -69,9 +69,9 @@ function scaleOffset(scale, offset, note) {
* @memberof Pattern
* @name transpose
* @example
* "c2 c3".fast(2).transpose("<0 -2 5 3>".slow(2)).transpose(0)
* "c2 c3".fast(2).transpose("<0 -2 5 3>".slow(2)).note()
* @example
* "c2 c3".fast(2).transpose("<1P -2M 4P 3m>".slow(2)).transpose(0)
* "c2 c3".fast(2).transpose("<1P -2M 4P 3m>".slow(2)).note()
*/
Pattern.prototype._transpose = function (intervalOrSemitones) {
@ -107,6 +107,7 @@ Pattern.prototype._transpose = function (intervalOrSemitones) {
* "-8 [2,4,6]"
* .scale('C4 bebop major')
* .scaleTranspose("<0 -1 -2 -3 -4 -5 -6 -4>")
* .note()
*/
Pattern.prototype._scaleTranspose = function (offset /* : number | string */) {
@ -134,9 +135,10 @@ Pattern.prototype._scaleTranspose = function (offset /* : number | string */) {
* @name scale
* @param {string} scale Name of scale
* @returns Pattern
* @example
* @example
* "0 2 4 6 4 2"
* .scale(seq('C2 major', 'C2 minor').slow(2))
* .note()
*/
Pattern.prototype._scale = function (scale /* : string */) {

View File

@ -40,7 +40,7 @@ Pattern.prototype.fmapNested = function (func) {
* @param {range} range note range for possible voicings (optional, defaults to `['F3', 'A4']`)
* @returns Pattern
* @example
* stack("<C^7 A7 Dm7 G7>".voicings(), "<C3 A2 D3 G2>")
* stack("<C^7 A7 Dm7 G7>".voicings(), "<C3 A2 D3 G2>").note()
*/
Pattern.prototype.voicings = function (range) {

View File

@ -260,9 +260,9 @@ resulting in a rhythmical structure of "x ~ ~ x ~ ~ x ~" (3 beats over 8 segment
<br />
# Web Audio Output
# Synths, Samples & Effects
The default way to output sound is by using the Web Audio Output.
Let's take a closer look at how we can control synths, sounds and effects.
## Synths
@ -447,11 +447,38 @@ Wether you're using a synth or a sample, you can apply these effects:
<br />
# Core API
# JavaScript API
While the mini notation is powerful on its own, there is much more to discover.
Internally, the mini notation will expand to use the actual functional JavaScript API.
For example, this Pattern in Mini Notation:
<MiniRepl tune={`note("c3 eb3 g3")`} />
is equivalent to this Pattern without Mini Notation:
<MiniRepl tune={`note(seq(c3, eb3, g3))`} />
Similarly, there is an equivalent function for every aspect of the mini notation.
Which representation to use is a matter of context. As a rule of thumb, you can think of the JavaScript API
to fit better for the larger context, while mini notation is more practical for individiual rhythms.
## Limits of Mini Notation
While the Mini Notation is a powerful way to write rhythms shortly, it also has its limits. Take this example:
<MiniRepl
tune={`stack(
note("c2 eb2(3,8)").s('sawtooth').cutoff(800),
s("bd,~ sd,hh*4")
)`}
/>
Here, we are using mini notation for the individual rhythms, while using the function `stack` to mix them.
While stack is also available as `,` in mini notation, we cannot use it here, because we have different types of sounds.
## Notes
Notes are automatically available as variables:
@ -474,15 +501,17 @@ To avoid getting to many nested parens, there is an alternative syntax to add a
<MiniRepl tune={`seq(d4, fs4, a4).note()`} />
You can use this with any function that declares a type, just make sure to leave the parens empty!
You can use this with any function that declares a type (like `n`, `s`, `note`, `freq` etc), just make sure to leave the parens empty!
## Pattern Factories
The following functions will return a pattern.
<!--
{{ 'pure' | jsdoc }}
Most of the time, you won't need that function as input values of pattern creating functions are purified by default.
-->
{{ 'cat' | jsdoc }}
@ -526,7 +555,7 @@ You can freely mix JS patterns, mini patterns and values! For example, this patt
stack(a3,c3,e4),
stack(b3,d3,fs4),
stack(b3,e4,g4)
)`}
).note()`}
/>
...is equivalent to:
@ -537,12 +566,12 @@ You can freely mix JS patterns, mini patterns and values! For example, this patt
"a3,c3,e4",
"b3,d3,f#4",
"b3,e4,g4"
)`}
).note()`}
/>
... as well as:
<MiniRepl tune={`"<[g3,b3,e4] [a3,c3,e4] [b3,d3,f#4] [b3,e4,g4]>"`} />
<MiniRepl tune={`note("<[g3,b3,e4] [a3,c3,e4] [b3,d3,f#4] [b3,e4,g4]>")`} />
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.
@ -689,13 +718,13 @@ The Tonal API, uses [tonaljs](https://github.com/tonaljs/tonal) to provide helpe
Transposes all notes to the given number of semitones:
<MiniRepl tune={`"c2 c3".fast(2).transpose("<0 -2 5 3>".slow(2)).transpose(0)`} />
<MiniRepl tune={`"c2 c3".fast(2).transpose("<0 -2 5 3>".slow(2)).note()`} />
This method gets really exciting when we use it with a pattern as above.
Instead of numbers, scientific interval notation can be used as well:
<MiniRepl tune={`"c2 c3".fast(2).transpose("<1P -2M 4P 3m>".slow(2)).transpose(1)`} />
<MiniRepl tune={`"c2 c3".fast(2).transpose("<1P -2M 4P 3m>".slow(2)).note()`} />
### scale(name)
@ -703,7 +732,8 @@ Turns numbers into notes in the scale (zero indexed). Also sets scale for other
<MiniRepl
tune={`"0 2 4 6 4 2"
.scale(seq('C2 major', 'C2 minor').slow(2))`}
.scale(seq('C2 major', 'C2 minor').slow(2))
.note()`}
/>
Note that the scale root is octaved here. You can also omit the octave, then index zero will default to octave 3.
@ -717,14 +747,15 @@ Transposes notes inside the scale by the number of steps:
<MiniRepl
tune={`"-8 [2,4,6]"
.scale('C4 bebop major')
.scaleTranspose("<0 -1 -2 -3 -4 -5 -6 -4>")`}
.scaleTranspose("<0 -1 -2 -3 -4 -5 -6 -4>")
.note()`}
/>
### voicings(range?)
Turns chord symbols into voicings, using the smoothest voice leading possible:
<MiniRepl tune={`stack("<C^7 A7 Dm7 G7>".voicings(), "<C3 A2 D3 G2>")`} />
<MiniRepl tune={`stack("<C^7 A7 Dm7 G7>".voicings(), "<C3 A2 D3 G2>").note()`} />
<!-- TODO: use voicing collection as first param + patternify. -->
@ -732,7 +763,7 @@ Turns chord symbols into voicings, using the smoothest voice leading possible:
Turns chord symbols into root notes of chords in given octave.
<MiniRepl tune={`"<C^7 A7b13 Dm7 G7>".rootNotes(3)`} />
<MiniRepl tune={`"<C^7 A7b13 Dm7 G7>".rootNotes(3).note()`} />
Together with layer, struct and voicings, this can be used to create a basic backing track:
@ -740,7 +771,7 @@ Together with layer, struct and voicings, this can be used to create a basic bac
tune={`"<C^7 A7b13 Dm7 G7>".layer(
x => x.voicings(['d3','g4']).struct("~ x"),
x => x.rootNotes(2).tone(synth(osc('sawtooth4')).chain(out()))
)`}
).note()`}
/>
<!-- TODO: use range instead of octave. -->