tblswvs 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/es5/helpers.d.ts +8 -0
- package/lib/es5/helpers.js +50 -0
- package/lib/es5/helpers.js.map +1 -0
- package/lib/es5/index.d.ts +8 -0
- package/lib/es5/index.js +25 -0
- package/lib/es5/index.js.map +1 -0
- package/lib/es5/key.d.ts +21 -0
- package/lib/es5/key.js +178 -0
- package/lib/es5/key.js.map +1 -0
- package/lib/es5/lindenmayer_system.d.ts +62 -0
- package/lib/es5/lindenmayer_system.js +94 -0
- package/lib/es5/lindenmayer_system.js.map +1 -0
- package/lib/es5/markov_chain.d.ts +8 -0
- package/lib/es5/markov_chain.js +28 -0
- package/lib/es5/markov_chain.js.map +1 -0
- package/lib/es5/melodic_vector.d.ts +29 -0
- package/lib/es5/melodic_vector.js +49 -0
- package/lib/es5/melodic_vector.js.map +1 -0
- package/lib/es5/melody.d.ts +106 -0
- package/lib/es5/melody.js +199 -0
- package/lib/es5/melody.js.map +1 -0
- package/lib/es5/mode.d.ts +33 -0
- package/lib/es5/mode.js +98 -0
- package/lib/es5/mode.js.map +1 -0
- package/lib/es5/note_data.d.ts +22 -0
- package/lib/es5/note_data.js +693 -0
- package/lib/es5/note_data.js.map +1 -0
- package/lib/es5/rhythm.d.ts +31 -0
- package/lib/es5/rhythm.js +68 -0
- package/lib/es5/rhythm.js.map +1 -0
- package/lib/es5/sequence.d.ts +3 -0
- package/lib/es5/sequence.js +3 -0
- package/lib/es5/sequence.js.map +1 -0
- package/lib/es5/tblswvs_error.d.ts +3 -0
- package/lib/es5/tblswvs_error.js +12 -0
- package/lib/es5/tblswvs_error.js.map +1 -0
- package/lib/es5/transformation.d.ts +4 -0
- package/lib/es5/transformation.js +3 -0
- package/lib/es5/transformation.js.map +1 -0
- package/lib/es6/helpers.js +43 -0
- package/lib/es6/helpers.js.map +1 -0
- package/lib/es6/index.js +9 -0
- package/lib/es6/index.js.map +1 -0
- package/lib/es6/key.js +174 -0
- package/lib/es6/key.js.map +1 -0
- package/lib/es6/lindenmayer_system.js +90 -0
- package/lib/es6/lindenmayer_system.js.map +1 -0
- package/lib/es6/markov_chain.js +24 -0
- package/lib/es6/markov_chain.js.map +1 -0
- package/lib/es6/melodic_vector.js +45 -0
- package/lib/es6/melodic_vector.js.map +1 -0
- package/lib/es6/melody.js +195 -0
- package/lib/es6/melody.js.map +1 -0
- package/lib/es6/mode.js +94 -0
- package/lib/es6/mode.js.map +1 -0
- package/lib/es6/note_data.js +690 -0
- package/lib/es6/note_data.js.map +1 -0
- package/lib/es6/rhythm.js +64 -0
- package/lib/es6/rhythm.js.map +1 -0
- package/lib/es6/sequence.js +2 -0
- package/lib/es6/sequence.js.map +1 -0
- package/lib/es6/tblswvs_error.js +8 -0
- package/lib/es6/tblswvs_error.js.map +1 -0
- package/lib/es6/transformation.js +2 -0
- package/lib/es6/transformation.js.map +1 -0
- package/package.json +23 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Melody } from "./melody";
|
|
2
|
+
import { Sequence } from "./sequence";
|
|
3
|
+
import { Transformation } from "./transformation";
|
|
4
|
+
/**
|
|
5
|
+
* A Rhythm is a sequence of 1s and 0s that can transform a Melody object by letting the Melody's notes
|
|
6
|
+
* pass through for a rhythm 1, or "on", step and inserting rests for a rhythm 0, or "off", step.
|
|
7
|
+
*
|
|
8
|
+
* Like the MelodicVector class, the steps property of this class that stores its sequence data does
|
|
9
|
+
* not need to have the same number of elements as in the Melody that it is transforming. The MelodicVector's
|
|
10
|
+
* steps will instead be repeated until it is expanded to the size of the Melody's steps.
|
|
11
|
+
*/
|
|
12
|
+
export declare class Rhythm implements Sequence, Transformation {
|
|
13
|
+
steps: (1 | 0)[];
|
|
14
|
+
length?: number;
|
|
15
|
+
fillMode: ("wrap" | "silence");
|
|
16
|
+
/**
|
|
17
|
+
* Create a new Rhythm.
|
|
18
|
+
*
|
|
19
|
+
* @param steps Array of 1s and 0s that will represent the rhythm.
|
|
20
|
+
* @param fillMode "wrap" (default) or "silence" to determine how the rhythm will fill itself when longer than the melody
|
|
21
|
+
* @param length number the length of the resulting melody after this rhythm is applied to it
|
|
22
|
+
*/
|
|
23
|
+
constructor(steps: (1 | 0)[], fillMode?: ("wrap" | "silence"), length?: number);
|
|
24
|
+
/**
|
|
25
|
+
* Apply this rhythm to a given Melody.
|
|
26
|
+
*
|
|
27
|
+
* @param melody Melody to transform with by this rhythm
|
|
28
|
+
* @returns a new Melody object with its steps transformed by this rhythm
|
|
29
|
+
*/
|
|
30
|
+
applyTo(melody: Melody): Melody;
|
|
31
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Rhythm = void 0;
|
|
4
|
+
const melody_1 = require("./melody");
|
|
5
|
+
/**
|
|
6
|
+
* A Rhythm is a sequence of 1s and 0s that can transform a Melody object by letting the Melody's notes
|
|
7
|
+
* pass through for a rhythm 1, or "on", step and inserting rests for a rhythm 0, or "off", step.
|
|
8
|
+
*
|
|
9
|
+
* Like the MelodicVector class, the steps property of this class that stores its sequence data does
|
|
10
|
+
* not need to have the same number of elements as in the Melody that it is transforming. The MelodicVector's
|
|
11
|
+
* steps will instead be repeated until it is expanded to the size of the Melody's steps.
|
|
12
|
+
*/
|
|
13
|
+
class Rhythm {
|
|
14
|
+
/**
|
|
15
|
+
* Create a new Rhythm.
|
|
16
|
+
*
|
|
17
|
+
* @param steps Array of 1s and 0s that will represent the rhythm.
|
|
18
|
+
* @param fillMode "wrap" (default) or "silence" to determine how the rhythm will fill itself when longer than the melody
|
|
19
|
+
* @param length number the length of the resulting melody after this rhythm is applied to it
|
|
20
|
+
*/
|
|
21
|
+
constructor(steps, fillMode = "wrap", length) {
|
|
22
|
+
this.steps = steps;
|
|
23
|
+
this.fillMode = fillMode;
|
|
24
|
+
this.length = length;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Apply this rhythm to a given Melody.
|
|
28
|
+
*
|
|
29
|
+
* @param melody Melody to transform with by this rhythm
|
|
30
|
+
* @returns a new Melody object with its steps transformed by this rhythm
|
|
31
|
+
*/
|
|
32
|
+
applyTo(melody) {
|
|
33
|
+
const rhythmHits = this.steps.filter(step => step != 0).length;
|
|
34
|
+
const stepHits = Math.ceil(melody.steps.length / rhythmHits);
|
|
35
|
+
let transformedSequence = new Array(stepHits).fill(this.steps).flat();
|
|
36
|
+
if (this.length !== undefined) {
|
|
37
|
+
if (this.length > transformedSequence.length) {
|
|
38
|
+
let remainingStepCount = this.length - transformedSequence.length;
|
|
39
|
+
if (this.fillMode == "silence") {
|
|
40
|
+
transformedSequence.push(...new Array(remainingStepCount).fill(0));
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
let remainingSteps = Math.ceil(remainingStepCount / this.steps.length);
|
|
44
|
+
transformedSequence.push(...new Array(remainingSteps).fill(this.steps).flat());
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/*
|
|
48
|
+
* Truncate the sequence as a final check to make sure it is not longer than the rhythm length
|
|
49
|
+
* This could happen because this Rhythm's steps are shorter than the transformations's
|
|
50
|
+
* steps or because the transformedSequence filled out more steps than necessary
|
|
51
|
+
*/
|
|
52
|
+
transformedSequence = transformedSequence.slice(0, this.length);
|
|
53
|
+
}
|
|
54
|
+
let processedStepIndex = 0;
|
|
55
|
+
transformedSequence.forEach((step, i) => {
|
|
56
|
+
if (step == 1) {
|
|
57
|
+
transformedSequence[i] = melody.steps[processedStepIndex % melody.steps.length];
|
|
58
|
+
processedStepIndex++;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
transformedSequence[i] = melody.restSymbol;
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
return new melody_1.Melody(transformedSequence, melody.restSymbol, melody.melodicMode);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
exports.Rhythm = Rhythm;
|
|
68
|
+
//# sourceMappingURL=rhythm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rhythm.js","sourceRoot":"","sources":["../../../src/rhythm.ts"],"names":[],"mappings":";;;AAAA,qCAAkC;AAKlC;;;;;;;GAOG;AACH,MAAa,MAAM;IAMf;;;;;;OAMG;IACH,YAAY,KAAc,EAAE,WAA+B,MAAM,EAAE,MAAe;QAC9E,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACzB,CAAC;IAGD;;;;;OAKG;IACH,OAAO,CAAC,MAAc;QAClB,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;QAC/D,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,UAAU,CAAC,CAAC;QAC7D,IAAI,mBAAmB,GAAG,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;QAEtE,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE;YAC3B,IAAI,IAAI,CAAC,MAAM,GAAG,mBAAmB,CAAC,MAAM,EAAE;gBAC1C,IAAI,kBAAkB,GAAG,IAAI,CAAC,MAAM,GAAG,mBAAmB,CAAC,MAAM,CAAC;gBAClE,IAAI,IAAI,CAAC,QAAQ,IAAI,SAAS,EAAE;oBAC5B,mBAAmB,CAAC,IAAI,CAAC,GAAG,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;iBACtE;qBAAM;oBACH,IAAI,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;oBACvE,mBAAmB,CAAC,IAAI,CAAC,GAAG,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;iBAClF;aACJ;YACD;;;;cAIE;YACF,mBAAmB,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;SACnE;QAED,IAAI,kBAAkB,GAAG,CAAC,CAAC;QAC3B,mBAAmB,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;YACpC,IAAI,IAAI,IAAI,CAAC,EAAE;gBACX,mBAAmB,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,kBAAkB,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;gBAChF,kBAAkB,EAAE,CAAC;aACxB;iBAAM;gBACH,mBAAmB,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC;aAC9C;QACL,CAAC,CAAC,CAAC;QAEH,OAAO,IAAI,eAAM,CAAC,mBAAmB,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;IAClF,CAAC;CACJ;AA7DD,wBA6DC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sequence.js","sourceRoot":"","sources":["../../../src/sequence.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TblswvsError = void 0;
|
|
4
|
+
class TblswvsError extends Error {
|
|
5
|
+
constructor(message) {
|
|
6
|
+
super(message);
|
|
7
|
+
// Set the prototype explicitly.
|
|
8
|
+
Object.setPrototypeOf(this, TblswvsError.prototype);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
exports.TblswvsError = TblswvsError;
|
|
12
|
+
//# sourceMappingURL=tblswvs_error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tblswvs_error.js","sourceRoot":"","sources":["../../../src/tblswvs_error.ts"],"names":[],"mappings":";;;AAAA,MAAa,YAAa,SAAQ,KAAK;IACnC,YAAY,OAAe;QACvB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,gCAAgC;QAChC,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC;IACxD,CAAC;CACJ;AAND,oCAMC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transformation.js","sourceRoot":"","sources":["../../../src/transformation.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { TblswvsError } from "./tblswvs_error";
|
|
2
|
+
export const INCOMPATIBLE_SEQ_MSG = "A Sequence can only be made new from and Array of Sequence " +
|
|
3
|
+
"objects that share the same rest symbol and mode";
|
|
4
|
+
export const NON_INTEGER_INPUTS = "Numbers must be integers";
|
|
5
|
+
export const SELF_SIMILARITY_REQUIRES_COPRIMES = "A self-similar melody can only be produced for an input sequence length " +
|
|
6
|
+
"that is coprime with the output sequence length";
|
|
7
|
+
export const SCALE_DEGREE_ERROR = "Scale degrees must be negative or positive, but not 0";
|
|
8
|
+
export const unique = (value, index, self) => {
|
|
9
|
+
return self.indexOf(value) === index;
|
|
10
|
+
};
|
|
11
|
+
export const areCoprime = (num1, num2) => {
|
|
12
|
+
if (!Number.isInteger(num1) || !Number.isInteger(num2))
|
|
13
|
+
throw new TblswvsError(NON_INTEGER_INPUTS);
|
|
14
|
+
const smaller = num1 > num2 ? num2 : num1;
|
|
15
|
+
for (let i = 2; i <= smaller; i++)
|
|
16
|
+
if ((num1 % i === 0) && (num2 % i === 0))
|
|
17
|
+
return false;
|
|
18
|
+
return true;
|
|
19
|
+
};
|
|
20
|
+
export const rotate = (arr, offset) => {
|
|
21
|
+
let copy = arr.slice();
|
|
22
|
+
if (copy.length > offset) {
|
|
23
|
+
copy.unshift(...copy.splice(-offset));
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
let i = 0;
|
|
27
|
+
while (i < offset) {
|
|
28
|
+
copy.unshift(copy.splice(-1));
|
|
29
|
+
i++;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return copy;
|
|
33
|
+
};
|
|
34
|
+
export const inversionMap = (range) => {
|
|
35
|
+
let map = new Map();
|
|
36
|
+
const intervals = (Array.isArray(range)) ?
|
|
37
|
+
range.filter(unique).sort((a, b) => a - b) :
|
|
38
|
+
[...new Array(range).keys()].map(i => i + 1);
|
|
39
|
+
for (let i = 0; i < intervals.length; i++)
|
|
40
|
+
map.set(intervals[i], intervals[intervals.length - i - 1]);
|
|
41
|
+
return map;
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../src/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAG/C,MAAM,CAAC,MAAM,oBAAoB,GAC7B,6DAA6D;IAC7D,kDAAkD,CAAC;AAEvD,MAAM,CAAC,MAAM,kBAAkB,GAAG,0BAA0B,CAAC;AAE7D,MAAM,CAAC,MAAM,iCAAiC,GAC1C,0EAA0E;IAC1E,iDAAiD,CAAC;AAEtD,MAAM,CAAC,MAAM,kBAAkB,GAC3B,uDAAuD,CAAC;AAG5D,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,KAAU,EAAE,KAAa,EAAE,IAAS,EAAE,EAAE;IAC3D,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC;AACzC,CAAC,CAAA;AAGD,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,IAAY,EAAE,IAAY,EAAE,EAAE;IACrD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC;QAClD,MAAM,IAAI,YAAY,CAAC,kBAAkB,CAAC,CAAC;IAE/C,MAAM,OAAO,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IAC1C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,OAAO,EAAE,CAAC,EAAE;QAC7B,IAAI,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;YACpC,OAAO,KAAK,CAAC;IAErB,OAAO,IAAI,CAAC;AAChB,CAAC,CAAC;AAGF,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,GAAU,EAAE,MAAc,EAAS,EAAE;IACxD,IAAI,IAAI,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC;IACvB,IAAI,IAAI,CAAC,MAAM,GAAG,MAAM,EAAE;QACtB,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;KACzC;SAAM;QACH,IAAI,CAAC,GAAG,CAAC,CAAC;QACV,OAAO,CAAC,GAAG,MAAM,EAAE;YACf,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9B,CAAC,EAAE,CAAC;SACP;KACJ;IACD,OAAO,IAAI,CAAC;AAChB,CAAC,CAAA;AAGD,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,KAAwB,EAAuB,EAAE;IAC1E,IAAI,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC;IAEpB,MAAM,SAAS,GAAa,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC5C,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC5C,CAAC,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAErD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE;QACrC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAE/D,OAAO,GAAG,CAAC;AACf,CAAC,CAAA"}
|
package/lib/es6/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from "./melody";
|
|
2
|
+
export * from "./mode";
|
|
3
|
+
export * from "./key";
|
|
4
|
+
export * from "./melodic_vector";
|
|
5
|
+
export * from "./rhythm";
|
|
6
|
+
export * from "./lindenmayer_system";
|
|
7
|
+
export * from "./markov_chain";
|
|
8
|
+
export * from "./helpers";
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,OAAO,CAAC;AACtB,cAAc,kBAAkB,CAAC;AACjC,cAAc,UAAU,CAAC;AACzB,cAAc,sBAAsB,CAAC;AACrC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC"}
|
package/lib/es6/key.js
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
2
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
3
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
4
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
|
+
};
|
|
6
|
+
var _Key_instances, _Key_negativeDegree, _Key_calculateChordRoot, _Key_calculateChordDegree, _Key_calculateScaleNotes, _Key_calculateInversions;
|
|
7
|
+
import { Mode, Scale } from "./mode";
|
|
8
|
+
import * as noteData from "./note_data";
|
|
9
|
+
import * as helpers from "./helpers";
|
|
10
|
+
import { TblswvsError } from "./tblswvs_error";
|
|
11
|
+
export class Key {
|
|
12
|
+
constructor(tonic, scale) {
|
|
13
|
+
_Key_instances.add(this);
|
|
14
|
+
this.scale = scale;
|
|
15
|
+
this.mode = new Mode(scale);
|
|
16
|
+
if (typeof tonic == "string") {
|
|
17
|
+
this.tonic = tonic;
|
|
18
|
+
this.midiTonic = noteData.chromaticScale.indexOf(tonic);
|
|
19
|
+
this.octave = 1;
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
this.tonic = noteData.chromaticScale[tonic % 12];
|
|
23
|
+
this.midiTonic = tonic % 12;
|
|
24
|
+
this.octave = noteData.noteData[tonic].octave;
|
|
25
|
+
}
|
|
26
|
+
this.scaleName = Scale[scale];
|
|
27
|
+
this.name = `${this.tonic} ${this.scaleName}`;
|
|
28
|
+
this.scaleNotes = __classPrivateFieldGet(this, _Key_instances, "m", _Key_calculateScaleNotes).call(this);
|
|
29
|
+
this.inversions = __classPrivateFieldGet(this, _Key_instances, "m", _Key_calculateInversions).call(this);
|
|
30
|
+
const inversionRange = Array.from(this.inversions.keys()).sort((a, b) => a - b);
|
|
31
|
+
this.inversionMin = inversionRange[0];
|
|
32
|
+
this.inversionMax = inversionRange[inversionRange.length - 1];
|
|
33
|
+
}
|
|
34
|
+
degree(d, octaveTranspose) {
|
|
35
|
+
if (d == 0)
|
|
36
|
+
throw new TblswvsError(helpers.SCALE_DEGREE_ERROR);
|
|
37
|
+
if (d < 0)
|
|
38
|
+
return __classPrivateFieldGet(this, _Key_instances, "m", _Key_negativeDegree).call(this, d, octaveTranspose);
|
|
39
|
+
// The degree octave may start higher than the current key's octave (e.g., the 9th in a diatonic scale)
|
|
40
|
+
let degreeOctave = this.octave + Math.floor((d - 1) / this.scaleNotes.length);
|
|
41
|
+
const noteIndex = this.mode.scaleOffsets[(d - 1) % this.scaleNotes.length] + this.midiTonic + (degreeOctave * 12) + 24;
|
|
42
|
+
let degree = Object.assign({}, noteData.noteData[noteIndex]);
|
|
43
|
+
// Reset the generic note to the scale notes to correctly identify when a scale degree should be a flat, rather than
|
|
44
|
+
// the default sharp for noteData.
|
|
45
|
+
degree.note = this.scaleNotes[(d - 1) % this.scaleNotes.length];
|
|
46
|
+
degree.scaleDegree = d;
|
|
47
|
+
if (octaveTranspose != undefined) {
|
|
48
|
+
degree.octave += octaveTranspose;
|
|
49
|
+
degree.midi += (octaveTranspose * 12);
|
|
50
|
+
}
|
|
51
|
+
return degree;
|
|
52
|
+
}
|
|
53
|
+
chord(degree, type, octaveTransposition) {
|
|
54
|
+
let quality = (type == "T") ? this.mode.chordQualities[degree - 1] : type;
|
|
55
|
+
/*
|
|
56
|
+
* octaveTransposition: the calling client may request transposition (-/+)
|
|
57
|
+
* this.midiTonic: scale pitch class (0-11)
|
|
58
|
+
* this.octave * 12: the Key has a default lowest octave
|
|
59
|
+
* + 24: lowest MIDI octave, -2, means this.octave*12 could be as low as -24, which should be brought up to MIDI note 0
|
|
60
|
+
*/
|
|
61
|
+
let midiTransposition = (octaveTransposition == undefined ? 0 : octaveTransposition * 12) + this.midiTonic + (this.octave * 12) + 24;
|
|
62
|
+
let midi = noteData.chordTypes[quality].intervals.reduce((midiNotes, intv) => {
|
|
63
|
+
midiNotes.push(intv + this.mode.scaleOffsets[degree - 1] + midiTransposition);
|
|
64
|
+
return midiNotes;
|
|
65
|
+
}, []);
|
|
66
|
+
return {
|
|
67
|
+
midi: midi,
|
|
68
|
+
quality: quality,
|
|
69
|
+
root: __classPrivateFieldGet(this, _Key_instances, "m", _Key_calculateChordRoot).call(this, midi, quality),
|
|
70
|
+
degree: __classPrivateFieldGet(this, _Key_instances, "m", _Key_calculateChordDegree).call(this, quality, degree),
|
|
71
|
+
keyTransposition: octaveTransposition == undefined ? 0 : octaveTransposition
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
midi2note(midiNoteNumber) {
|
|
75
|
+
const normalizedNumber = midiNoteNumber % 12;
|
|
76
|
+
const normalizedIndex = this.mode.scaleOffsets.indexOf(normalizedNumber);
|
|
77
|
+
if (normalizedIndex != -1) {
|
|
78
|
+
return this.scaleNotes[normalizedIndex] + noteData.noteData[midiNoteNumber].octave;
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
let note = noteData.noteData[midiNoteNumber].note;
|
|
82
|
+
const nearestNote = this.scaleNotes.find(n => n[0] == note[0]);
|
|
83
|
+
note += (nearestNote != undefined && nearestNote.length == 2) ? "♮" : "";
|
|
84
|
+
return note + noteData.noteData[midiNoteNumber].octave;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
degreeInversion(scaleDegree) {
|
|
88
|
+
if (scaleDegree < this.inversionMin)
|
|
89
|
+
scaleDegree = this.inversionMin;
|
|
90
|
+
else if (scaleDegree > this.inversionMax)
|
|
91
|
+
scaleDegree = this.inversionMax;
|
|
92
|
+
const invertedScaleDegree = this.inversions.get(scaleDegree);
|
|
93
|
+
if (invertedScaleDegree == undefined)
|
|
94
|
+
return { octave: -3, note: "", midi: -1 };
|
|
95
|
+
else
|
|
96
|
+
return this.degree(invertedScaleDegree);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
_Key_instances = new WeakSet(), _Key_negativeDegree = function _Key_negativeDegree(d, octaveTranspose) {
|
|
100
|
+
// For negative indices, start by getting the step offsets in reverse order...
|
|
101
|
+
let revCopy = this.mode.stepOffsets.slice().reverse();
|
|
102
|
+
// Then determine how many copies of the array are needed to index the current scale degree
|
|
103
|
+
// (e.g., -8 for C Major would be the second B, so copies should be 2)
|
|
104
|
+
let copies = Math.ceil(-d / revCopy.length);
|
|
105
|
+
// Create a version of the reversed step offsets that can reach the scale degree needed.
|
|
106
|
+
let expanded = new Array(copies).fill(revCopy).flat();
|
|
107
|
+
// Finally, subtract negative offsets from the current Key's root and correct the default sharps to flats as needed.
|
|
108
|
+
const noteIndex = this.octave * 12 + this.midiTonic + 24 - expanded.slice(0, -d).reduce((total, offset) => total += offset, 0);
|
|
109
|
+
let degree = Object.assign({}, noteData.noteData[noteIndex]);
|
|
110
|
+
degree.note = this.scaleNotes.at(d % this.scaleNotes.length);
|
|
111
|
+
degree.scaleDegree = d;
|
|
112
|
+
if (octaveTranspose != undefined) {
|
|
113
|
+
degree.octave += octaveTranspose;
|
|
114
|
+
degree.midi += (octaveTranspose * 12);
|
|
115
|
+
}
|
|
116
|
+
return degree;
|
|
117
|
+
}, _Key_calculateChordRoot = function _Key_calculateChordRoot(chordMidi, chordQuality) {
|
|
118
|
+
let inversion = chordQuality.split("/")[1];
|
|
119
|
+
if (inversion == undefined) {
|
|
120
|
+
return this.midi2note(chordMidi[0]).replace(/[0-9]/g, "");
|
|
121
|
+
}
|
|
122
|
+
else if (inversion == "2" || inversion == "3" || inversion == "4") {
|
|
123
|
+
return this.midi2note(chordMidi[2]).replace(/[0-9]/g, "");
|
|
124
|
+
}
|
|
125
|
+
else if (inversion == "5") {
|
|
126
|
+
return this.midi2note(chordMidi[1]).replace(/[0-9]/g, "");
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
return this.midi2note(chordMidi[0]).replace(/[0-9]/g, "");
|
|
130
|
+
}
|
|
131
|
+
}, _Key_calculateChordDegree = function _Key_calculateChordDegree(quality, degree) {
|
|
132
|
+
if (quality.startsWith("M")) {
|
|
133
|
+
return quality.replace("M", noteData.chordNumeralsMap[degree]);
|
|
134
|
+
}
|
|
135
|
+
else if (quality.startsWith("m")) {
|
|
136
|
+
return quality.replace("m", noteData.chordNumeralsMap[degree].toLowerCase());
|
|
137
|
+
}
|
|
138
|
+
else if (quality.startsWith("aug")) {
|
|
139
|
+
return quality.replace("aug", noteData.chordNumeralsMap[degree]) + "+";
|
|
140
|
+
}
|
|
141
|
+
else if (quality.startsWith("dim")) {
|
|
142
|
+
return quality.replace("dim", noteData.chordNumeralsMap[degree]).toLowerCase() + "o";
|
|
143
|
+
}
|
|
144
|
+
else if (quality.startsWith("sus2")) {
|
|
145
|
+
return noteData.chordNumeralsMap[degree] + quality;
|
|
146
|
+
}
|
|
147
|
+
else if (quality.startsWith("sus4")) {
|
|
148
|
+
return quality.replace("sus2", noteData.chordNumeralsMap[degree]) + "sus4";
|
|
149
|
+
}
|
|
150
|
+
else if (quality.startsWith("WT")) {
|
|
151
|
+
return quality.replace("WT", noteData.chordNumeralsMap[degree]).toLowerCase() + "WT";
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
return degree + quality;
|
|
155
|
+
}
|
|
156
|
+
}, _Key_calculateScaleNotes = function _Key_calculateScaleNotes() {
|
|
157
|
+
const rotatedAbsolute = helpers.rotate(noteData.scaleNoteCandidates, -noteData.scaleNoteCandidates.findIndex(n => n.includes(this.tonic)));
|
|
158
|
+
let scaleAbcNotes = helpers.rotate(noteData.abcNotesMidiOrder, -noteData.abcNotesMidiOrder.indexOf(this.tonic[0]));
|
|
159
|
+
if (this.mode.scaleDegreeMapping.length != 0) {
|
|
160
|
+
scaleAbcNotes = this.mode.scaleDegreeMapping.map(d => scaleAbcNotes[Math.floor(d) - 1]);
|
|
161
|
+
}
|
|
162
|
+
return scaleAbcNotes.map((n, i) => {
|
|
163
|
+
const absoluteIndex = this.mode.scaleOffsets[i];
|
|
164
|
+
return rotatedAbsolute[absoluteIndex].find((sn) => sn[0] == n);
|
|
165
|
+
});
|
|
166
|
+
}, _Key_calculateInversions = function _Key_calculateInversions() {
|
|
167
|
+
const positiveDegrees = [...new Array(this.mode.stepOffsets.length * 2 + 1).keys()].map(d => d + 1);
|
|
168
|
+
const negativeDegrees = positiveDegrees.slice(0, this.mode.stepOffsets.length).reverse().map(d => d * -1);
|
|
169
|
+
this.inversionMin = negativeDegrees[0];
|
|
170
|
+
this.inversionMax = positiveDegrees[positiveDegrees.length - 1];
|
|
171
|
+
const blerg = negativeDegrees.concat(positiveDegrees);
|
|
172
|
+
return helpers.inversionMap(blerg);
|
|
173
|
+
};
|
|
174
|
+
//# sourceMappingURL=key.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"key.js","sourceRoot":"","sources":["../../../src/key.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lindenmayer Systems (or L-Systems) are string rewriting systems developed by, and named after, the Hungarian
|
|
3
|
+
* biologist who used the algorithm to model the growth of plants and cell structures.
|
|
4
|
+
*
|
|
5
|
+
* This class represents a simple implementation of L-Systems where you can create one with a starting axiom,
|
|
6
|
+
* add new "production rules," and generate new iterations of the L-System string. Additionally, this version
|
|
7
|
+
* implements branching using the square bracket characters '[' and ']'. Branching enables an L-System string
|
|
8
|
+
* to be translated into a 2-dimensional matrix.
|
|
9
|
+
*/
|
|
10
|
+
export class LindenmayerSystem {
|
|
11
|
+
/**
|
|
12
|
+
* Create a new LindenmayerSystem object.
|
|
13
|
+
*
|
|
14
|
+
* @param axiom the initial string for this L-System
|
|
15
|
+
*/
|
|
16
|
+
constructor(axiom) {
|
|
17
|
+
this.axiom = axiom;
|
|
18
|
+
this.string = axiom;
|
|
19
|
+
this.productionRules = {};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Add a new production rule to the L-System.
|
|
23
|
+
*
|
|
24
|
+
* @param rule a string rewriting rule in the form of an object that has the properties "matchStr" and "output"
|
|
25
|
+
*/
|
|
26
|
+
add(rule) {
|
|
27
|
+
this.productionRules[rule.matchStr] = rule.output;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Get the current list of production rule matching strings. To see the rewriting output for each rule,
|
|
31
|
+
* access the productionRules property.
|
|
32
|
+
*
|
|
33
|
+
* @returns string[] the production rules matching strings
|
|
34
|
+
*/
|
|
35
|
+
rules() {
|
|
36
|
+
return Object.keys(this.productionRules);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Advance the L-System by one generation.
|
|
40
|
+
*
|
|
41
|
+
* The current string, which is equal to the axiom until advanced,
|
|
42
|
+
* will have its letters run thru the production rules. When a letter matches a production rule's "matchStr"
|
|
43
|
+
* property, it will be replaced by the same production rule's "output" property in the resulting string.
|
|
44
|
+
* When no match is found the current letter will simply be added without replacement.
|
|
45
|
+
*
|
|
46
|
+
* This will update the object's "string" property.
|
|
47
|
+
*/
|
|
48
|
+
advance() {
|
|
49
|
+
this.string = this.string.split(" ").map(letter => {
|
|
50
|
+
return letter in this.productionRules ? this.productionRules[letter] : letter;
|
|
51
|
+
}).join(" ");
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Get the current "string" as a matrix.
|
|
55
|
+
*
|
|
56
|
+
* A matrix representation is really only useful for L-System strings with branching characters so that
|
|
57
|
+
* the matrix has multiple rows. The intention is to return a 2-D table-like representation of a branching
|
|
58
|
+
* L-System string so that represents a polyphonic event sequence. The columns can be treated as sequencer
|
|
59
|
+
* steps and the rows as simultaneous/polyphonic events for the current step/column.
|
|
60
|
+
*
|
|
61
|
+
* @returns string[][] a 2-dimensional matrix representation of the current L-System string
|
|
62
|
+
*/
|
|
63
|
+
matrix() {
|
|
64
|
+
let matrix = new Array();
|
|
65
|
+
matrix.push(new Array());
|
|
66
|
+
let rowIndex = 0, colIndex = 0, branchCoordinates = [rowIndex, colIndex];
|
|
67
|
+
this.string.split(" ").forEach((letter, i) => {
|
|
68
|
+
if (letter == "[") {
|
|
69
|
+
// When starting a new branch, note where the branch origin is for returning when the branch
|
|
70
|
+
// ceases, increment the row count and create an Array for the new row.
|
|
71
|
+
branchCoordinates = [rowIndex, colIndex];
|
|
72
|
+
rowIndex = matrix.length;
|
|
73
|
+
matrix.push(new Array());
|
|
74
|
+
colIndex -= 1;
|
|
75
|
+
}
|
|
76
|
+
else if (letter == "]") {
|
|
77
|
+
// When a branch terminates, return the cursor to the branching coordinates.
|
|
78
|
+
rowIndex = branchCoordinates[0];
|
|
79
|
+
colIndex = branchCoordinates[1];
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
// Add the current letter to the next position
|
|
83
|
+
matrix[rowIndex][colIndex] = letter;
|
|
84
|
+
colIndex += 1;
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
return matrix;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=lindenmayer_system.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lindenmayer_system.js","sourceRoot":"","sources":["../../../src/lindenmayer_system.ts"],"names":[],"mappings":"AAMA;;;;;;;;GAQG;AACH,MAAM,OAAO,iBAAiB;IAM1B;;;;OAIG;IACH,YAAY,KAAa;QACrB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,eAAe,GAAG,EAAE,CAAC;IAC9B,CAAC;IAGD;;;;OAIG;IACH,GAAG,CAAC,IAAoB;QACpB,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;IACtD,CAAC;IAGD;;;;;OAKG;IACH,KAAK;QACD,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAC7C,CAAC;IAGD;;;;;;;;;OASG;IACH,OAAO;QACH,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE;YAC9C,OAAO,MAAM,IAAI,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QAClF,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACjB,CAAC;IAGD;;;;;;;;;OASG;IACH,MAAM;QACF,IAAI,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC;QACzB,IAAI,QAAQ,GAAG,CAAC,EAAE,QAAQ,GAAG,CAAC,EAAE,iBAAiB,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAEzE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YACzC,IAAI,MAAM,IAAI,GAAG,EAAE;gBAEf,4FAA4F;gBAC5F,uEAAuE;gBACvE,iBAAiB,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;gBACzC,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC;gBACzB,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC;gBACzB,QAAQ,IAAI,CAAC,CAAC;aAEjB;iBAAM,IAAI,MAAM,IAAI,GAAG,EAAE;gBAEtB,4EAA4E;gBAC5E,QAAQ,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC;gBAChC,QAAQ,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC;aAEnC;iBAAM;gBAEH,8CAA8C;gBAC9C,MAAM,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAC;gBACpC,QAAQ,IAAI,CAAC,CAAC;aACjB;QACL,CAAC,CAAC,CAAC;QAEH,OAAO,MAAM,CAAC;IAClB,CAAC;CACJ"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export class MarkovChain {
|
|
2
|
+
constructor(input) {
|
|
3
|
+
this.input = input;
|
|
4
|
+
this.stateTransitionMatrix = this.generateStm();
|
|
5
|
+
}
|
|
6
|
+
get(previous, current) {
|
|
7
|
+
const candidates = this.stateTransitionMatrix.get(`${previous}:${current}`) || [];
|
|
8
|
+
return candidates[Math.floor(Math.random() * candidates.length)];
|
|
9
|
+
}
|
|
10
|
+
generateStm() {
|
|
11
|
+
return this.input.steps.reduce((stm, step, i, arr) => {
|
|
12
|
+
if (i < arr.length - 1) {
|
|
13
|
+
const prevStep = (i == 0) ? step : arr[i - 1];
|
|
14
|
+
const nextStep = arr[i + 1];
|
|
15
|
+
const key = `${prevStep}:${step}`;
|
|
16
|
+
const values = stm.get(key) || new Array();
|
|
17
|
+
values.push(nextStep);
|
|
18
|
+
stm.set(key, values);
|
|
19
|
+
}
|
|
20
|
+
return stm;
|
|
21
|
+
}, new Map);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=markov_chain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markov_chain.js","sourceRoot":"","sources":["../../../src/markov_chain.ts"],"names":[],"mappings":"AAGA,MAAM,OAAO,WAAW;IAKpB,YAAY,KAAa;QACrB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,qBAAqB,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACpD,CAAC;IAGD,GAAG,CAAC,QAAgB,EAAE,OAAe;QACjC,MAAM,UAAU,GAAG,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,GAAG,QAAQ,IAAI,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC;QAClF,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;IACrE,CAAC;IAGO,WAAW;QACf,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE;YACjD,IAAI,CAAC,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE;gBACpB,MAAM,QAAQ,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBAC9C,MAAM,QAAQ,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBAC5B,MAAM,GAAG,GAAQ,GAAG,QAAQ,IAAI,IAAI,EAAE,CAAC;gBACvC,MAAM,MAAM,GAAK,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,KAAK,EAAE,CAAC;gBAC7C,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACtB,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;aACxB;YACD,OAAO,GAAG,CAAC;QACf,CAAC,EAAE,IAAI,GAAgC,CAAC,CAAC;IAC7C,CAAC;CACJ"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { MelodyType } from "./melody";
|
|
2
|
+
/**
|
|
3
|
+
* A MelodicVector is a sequence of numbers that can transform a Melody object by applying vector
|
|
4
|
+
* addition to a numerical representation of the Melody's note data.
|
|
5
|
+
*
|
|
6
|
+
* This class is not a true vector in the mathematical sense. For example, the steps property of
|
|
7
|
+
* this class that stores its sequence data does not need to have the same number of elements as
|
|
8
|
+
* in the Melody that it is transforming. The MelodicVector's steps will instead be repeated until
|
|
9
|
+
* it is expanded to the size of the Melody's steps.
|
|
10
|
+
*/
|
|
11
|
+
export class MelodicVector {
|
|
12
|
+
/**
|
|
13
|
+
* Create a new MelodicVector object.
|
|
14
|
+
*
|
|
15
|
+
* @param steps number[] the steps that represent the object's vector
|
|
16
|
+
*/
|
|
17
|
+
constructor(steps) {
|
|
18
|
+
this.steps = steps;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Transforms a melody by vector addition. Note that the vector step length and melody step
|
|
22
|
+
* length do not need to be equal.
|
|
23
|
+
*
|
|
24
|
+
* @param Melody the melody to transform withe the current vector
|
|
25
|
+
* @returns new Melody with steps based on summing the input melody steps and the vector steps
|
|
26
|
+
*/
|
|
27
|
+
applyTo(melody) {
|
|
28
|
+
// First generate an array of steps that will match the melody's length.
|
|
29
|
+
const size = Math.ceil((melody.steps.length / this.steps.length));
|
|
30
|
+
const expandedSteps = new Array(size).fill(this.steps).flat().slice(0, melody.steps.length);
|
|
31
|
+
// Create a copy of the melody so that the rest symbol and mode are carried forward.
|
|
32
|
+
// Then apply the vector addition.
|
|
33
|
+
const transformedMelody = melody.clone();
|
|
34
|
+
transformedMelody.steps = expandedSteps.map((step, i) => {
|
|
35
|
+
if (melody.melodicMode == MelodyType.Degrees && melody.steps[i] == 0)
|
|
36
|
+
return 0;
|
|
37
|
+
else if (melody.steps[i] == melody.restSymbol)
|
|
38
|
+
return melody.steps[i];
|
|
39
|
+
else
|
|
40
|
+
return step + melody.steps[i];
|
|
41
|
+
});
|
|
42
|
+
return transformedMelody;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=melodic_vector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"melodic_vector.js","sourceRoot":"","sources":["../../../src/melodic_vector.ts"],"names":[],"mappings":"AACA,OAAO,EAAU,UAAU,EAAE,MAAM,UAAU,CAAC;AAI9C;;;;;;;;GAQG;AACH,MAAM,OAAO,aAAa;IAItB;;;;OAIG;IACH,YAAY,KAAe;QACvB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACvB,CAAC;IAGD;;;;;;OAMG;IACH,OAAO,CAAC,MAAc;QAClB,wEAAwE;QACxE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;QAClE,MAAM,aAAa,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAE5F,oFAAoF;QACpF,kCAAkC;QAClC,MAAM,iBAAiB,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC;QACzC,iBAAiB,CAAC,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;YACpD,IAAI,MAAM,CAAC,WAAW,IAAI,UAAU,CAAC,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;gBAChE,OAAO,CAAC,CAAC;iBACR,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,UAAU;gBACzC,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;;gBAEvB,OAAO,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QAEH,OAAO,iBAAiB,CAAC;IAC7B,CAAC;CACJ"}
|