Merge branch 'scales' of github.com:JulienH2000/Topos into scales
This commit is contained in:
@ -1,6 +1,6 @@
|
|||||||
import { type UserAPI } from "./API";
|
import { type UserAPI } from "./API";
|
||||||
import { safeScale } from "zifferjs";
|
import { safeScale } from "zifferjs";
|
||||||
export { };
|
export {};
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface Array<T> {
|
interface Array<T> {
|
||||||
@ -37,14 +37,14 @@ export const makeArrayExtensions = (api: UserAPI) => {
|
|||||||
return this.includes(value);
|
return this.includes(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
Array.prototype.square = function(): number[] {
|
Array.prototype.square = function (): number[] {
|
||||||
/**
|
/**
|
||||||
* @returns New array with squared values.
|
* @returns New array with squared values.
|
||||||
*/
|
*/
|
||||||
return this.map((x: number) => x * x);
|
return this.map((x: number) => x * x);
|
||||||
};
|
};
|
||||||
|
|
||||||
Array.prototype.sqrt = function(): number[] {
|
Array.prototype.sqrt = function (): number[] {
|
||||||
/**
|
/**
|
||||||
* @returns New array with square roots of values. Throws if any element is negative.
|
* @returns New array with square roots of values. Throws if any element is negative.
|
||||||
*/
|
*/
|
||||||
@ -53,7 +53,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
|
|||||||
return this.map((x: number) => Math.sqrt(x));
|
return this.map((x: number) => Math.sqrt(x));
|
||||||
};
|
};
|
||||||
|
|
||||||
Array.prototype.add = function(amount: number): number[] {
|
Array.prototype.add = function (amount: number): number[] {
|
||||||
/**
|
/**
|
||||||
* @param amount - The value to add to each element in the array.
|
* @param amount - The value to add to each element in the array.
|
||||||
* @returns New array with added values.
|
* @returns New array with added values.
|
||||||
@ -61,7 +61,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
|
|||||||
return this.map((x: number) => x + amount);
|
return this.map((x: number) => x + amount);
|
||||||
};
|
};
|
||||||
|
|
||||||
Array.prototype.sub = function(amount: number): number[] {
|
Array.prototype.sub = function (amount: number): number[] {
|
||||||
/**
|
/**
|
||||||
* @param amount - The value to subtract from each element in the array.
|
* @param amount - The value to subtract from each element in the array.
|
||||||
* @returns New array with subtracted values.
|
* @returns New array with subtracted values.
|
||||||
@ -69,7 +69,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
|
|||||||
return this.map((x: number) => x - amount);
|
return this.map((x: number) => x - amount);
|
||||||
};
|
};
|
||||||
|
|
||||||
Array.prototype.mult = function(amount: number): number[] {
|
Array.prototype.mult = function (amount: number): number[] {
|
||||||
/**
|
/**
|
||||||
* @param amount - The value to multiply with each element in the array.
|
* @param amount - The value to multiply with each element in the array.
|
||||||
* @returns New array with multiplied values.
|
* @returns New array with multiplied values.
|
||||||
@ -77,7 +77,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
|
|||||||
return this.map((x: number) => x * amount);
|
return this.map((x: number) => x * amount);
|
||||||
};
|
};
|
||||||
|
|
||||||
Array.prototype.div = function(amount: number): number[] {
|
Array.prototype.div = function (amount: number): number[] {
|
||||||
/**
|
/**
|
||||||
* @param amount - The value to divide each element in the array by.
|
* @param amount - The value to divide each element in the array by.
|
||||||
* @returns New array with divided values. Throws if division by zero.
|
* @returns New array with divided values. Throws if division by zero.
|
||||||
@ -86,7 +86,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
|
|||||||
return this.map((x: number) => x / amount);
|
return this.map((x: number) => x / amount);
|
||||||
};
|
};
|
||||||
|
|
||||||
Array.prototype.pick = function() {
|
Array.prototype.pick = function () {
|
||||||
/**
|
/**
|
||||||
* Returns a random element from an array.
|
* Returns a random element from an array.
|
||||||
*
|
*
|
||||||
@ -95,7 +95,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
|
|||||||
return this[Math.floor(api.randomGen() * this.length)];
|
return this[Math.floor(api.randomGen() * this.length)];
|
||||||
};
|
};
|
||||||
|
|
||||||
Array.prototype.gen = function(min: number, max: number, times: number) {
|
Array.prototype.gen = function (min: number, max: number, times: number) {
|
||||||
/**
|
/**
|
||||||
* Returns an array of random numbers.
|
* Returns an array of random numbers.
|
||||||
* @param min - The minimum value of the random numbers
|
* @param min - The minimum value of the random numbers
|
||||||
@ -112,7 +112,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
Array.prototype.bar = function() {
|
Array.prototype.bar = function () {
|
||||||
/**
|
/**
|
||||||
* Returns an element from an array based on the current bar.
|
* Returns an element from an array based on the current bar.
|
||||||
*
|
*
|
||||||
@ -121,7 +121,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
|
|||||||
return this[api.app.clock.time_position.bar % this.length];
|
return this[api.app.clock.time_position.bar % this.length];
|
||||||
};
|
};
|
||||||
|
|
||||||
Array.prototype.pulse = function() {
|
Array.prototype.pulse = function () {
|
||||||
/**
|
/**
|
||||||
* Returns an element from an array based on the current pulse.
|
* Returns an element from an array based on the current pulse.
|
||||||
*
|
*
|
||||||
@ -130,7 +130,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
|
|||||||
return this[api.app.clock.time_position.pulse % this.length];
|
return this[api.app.clock.time_position.pulse % this.length];
|
||||||
};
|
};
|
||||||
|
|
||||||
Array.prototype.beat = function(divisor: number = 1) {
|
Array.prototype.beat = function (divisor: number = 1) {
|
||||||
const chunk_size = divisor; // Get the first argument (chunk size)
|
const chunk_size = divisor; // Get the first argument (chunk size)
|
||||||
const timepos = api.app.clock.pulses_since_origin;
|
const timepos = api.app.clock.pulses_since_origin;
|
||||||
const slice_count = Math.floor(
|
const slice_count = Math.floor(
|
||||||
@ -139,7 +139,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
|
|||||||
return this[slice_count % this.length];
|
return this[slice_count % this.length];
|
||||||
};
|
};
|
||||||
|
|
||||||
Array.prototype.shuffle = function() {
|
Array.prototype.shuffle = function () {
|
||||||
/**
|
/**
|
||||||
* Shuffles the array in place.
|
* Shuffles the array in place.
|
||||||
*
|
*
|
||||||
@ -158,7 +158,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
|
|||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
Array.prototype.rotate = function(steps: number) {
|
Array.prototype.rotate = function (steps: number) {
|
||||||
/**
|
/**
|
||||||
* Rotates the array in place.
|
* Rotates the array in place.
|
||||||
*
|
*
|
||||||
@ -178,7 +178,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
|
|||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
Array.prototype.unique = function() {
|
Array.prototype.unique = function () {
|
||||||
/**
|
/**
|
||||||
* Removes duplicate elements from the array in place.
|
* Removes duplicate elements from the array in place.
|
||||||
*
|
*
|
||||||
@ -211,7 +211,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
|
|||||||
if (this.length <= 1) {
|
if (this.length <= 1) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
for (let i = 0; i < this.length;) {
|
for (let i = 0; i < this.length; ) {
|
||||||
const rand = api.randomGen() * 100;
|
const rand = api.randomGen() * 100;
|
||||||
if (rand < amount) {
|
if (rand < amount) {
|
||||||
if (this.length > 1) {
|
if (this.length > 1) {
|
||||||
@ -324,7 +324,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
|
|||||||
return left_to_right.concat(right_to_left);
|
return left_to_right.concat(right_to_left);
|
||||||
};
|
};
|
||||||
|
|
||||||
Array.prototype.loop = function(index: number) {
|
Array.prototype.loop = function (index: number) {
|
||||||
/**
|
/**
|
||||||
* Returns an element from the array based on the index.
|
* Returns an element from the array based on the index.
|
||||||
* The index will wrap over the array.
|
* The index will wrap over the array.
|
||||||
@ -335,7 +335,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
|
|||||||
return this[index % this.length];
|
return this[index % this.length];
|
||||||
};
|
};
|
||||||
|
|
||||||
Array.prototype.random = function() {
|
Array.prototype.random = function () {
|
||||||
/**
|
/**
|
||||||
* Returns a random element from the array.
|
* Returns a random element from the array.
|
||||||
*
|
*
|
||||||
@ -346,24 +346,30 @@ export const makeArrayExtensions = (api: UserAPI) => {
|
|||||||
Array.prototype.rand = Array.prototype.random;
|
Array.prototype.rand = Array.prototype.random;
|
||||||
};
|
};
|
||||||
|
|
||||||
Array.prototype.scale = function(scale: string = "major", base_note: number = 0) {
|
Array.prototype.scale = function (
|
||||||
|
scale: string = "major",
|
||||||
|
base_note: number = 0
|
||||||
|
) {
|
||||||
/**
|
/**
|
||||||
* @param scale - the scale name
|
* @param scale - the scale name
|
||||||
* @param base_note - the base note to start at (MIDI note number)
|
* @param base_note - the base note to start at (MIDI note number)
|
||||||
*/
|
*/
|
||||||
if (SCALES.hasOwnProperty(scale)) {
|
|
||||||
const selected_scale = SCALES[scale];
|
const selected_scale = SCALES[scale];
|
||||||
return this.map((value) => {
|
return this.map((value) => {
|
||||||
const octaveShift = Math.floor(value / selected_scale.length) * 12 * Math.sign(value);
|
const octaveShift =
|
||||||
return selected_scale[Math.abs(value) % selected_scale.length] + base_note + octaveShift;
|
Math.floor(value / selected_scale.length) * 12 * Math.sign(value);
|
||||||
|
return (
|
||||||
|
selected_scale[Math.abs(value) % selected_scale.length] +
|
||||||
|
base_note +
|
||||||
|
octaveShift
|
||||||
|
);
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
return this.map((value) => value + base_note);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Array.prototype.scale = function (
|
||||||
Array.prototype.scale = function(scale: string = "major", base_note: number = 0) {
|
scale: string = "major",
|
||||||
|
base_note: number = 0
|
||||||
|
) {
|
||||||
/**
|
/**
|
||||||
* @param scale - the scale name
|
* @param scale - the scale name
|
||||||
* @param base_note - the base note to start at (MIDI note number)
|
* @param base_note - the base note to start at (MIDI note number)
|
||||||
@ -373,25 +379,46 @@ Array.prototype.scale = function(scale: string = "major", base_note: number = 0)
|
|||||||
|
|
||||||
// This is a helper function to handle up or down octaviation.
|
// This is a helper function to handle up or down octaviation.
|
||||||
const mod = (n: number, m: number) => ((n % m) + m) % m;
|
const mod = (n: number, m: number) => ((n % m) + m) % m;
|
||||||
let selected_scale = safeScale(scale);
|
|
||||||
|
if (SCALES.hasOwnProperty(scale)) {
|
||||||
|
const selected_scale = SCALES[scale];
|
||||||
return this.map((value) => {
|
return this.map((value) => {
|
||||||
const octaveShift = Math.floor(value / selected_scale.length) * 12;
|
const octaveShift = Math.floor(value / selected_scale.length) * 12;
|
||||||
return selected_scale[mod(value, selected_scale.length)] + base_note + octaveShift;
|
return (
|
||||||
|
selected_scale[mod(value, selected_scale.length)] +
|
||||||
|
base_note +
|
||||||
|
octaveShift
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
return this.map((value) => value + base_note);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Array.prototype.arp = function(scaleName: string = "major") {
|
Array.prototype.arp = function (scaleName: string = "major", mask: number = 0) {
|
||||||
/*
|
/*
|
||||||
* Ajouter documentation
|
* @param scaleName - the scale name
|
||||||
|
* @param mask - the length of the mask
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
const scale = safeScale[scaleName];
|
const scale = safeScale[scaleName];
|
||||||
|
|
||||||
|
//input protect from unknow scale
|
||||||
|
|
||||||
|
if (!scale) {
|
||||||
|
throw new Error(`Unknown scale ${scaleName}`);
|
||||||
|
}
|
||||||
|
|
||||||
let result = [];
|
let result = [];
|
||||||
for (let j = 0; j < scale.length; j++) {
|
|
||||||
|
mask = mask > scale.length ? scale.length : mask;
|
||||||
|
mask = mask == 0 ? scale.length : mask;
|
||||||
|
|
||||||
|
for (let j = 0; j < mask; j++) {
|
||||||
for (let i = 0; i < this.length; i++) {
|
for (let i = 0; i < this.length; i++) {
|
||||||
result.push(this[i] + scale[j]);
|
result.push(this[i] + scale[j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -183,7 +183,75 @@ ${makeExample(
|
|||||||
beat(1)::snd('sine').sustain(0.1).freq([100,100,100,100,200].unique().beat()).out()
|
beat(1)::snd('sine').sustain(0.1).freq([100,100,100,100,200].unique().beat()).out()
|
||||||
`,
|
`,
|
||||||
true
|
true
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
- <ic>scale(scale: string, mask: number)</ic>: extrapolate a custom-masked scale from each list elements. _[0].scale("major", 3)_ returns _[0,2,4]_
|
||||||
|
|
||||||
|
${makeExample(
|
||||||
|
"Extrapolate a 3-elements Persian scale from 2 notes",
|
||||||
|
`
|
||||||
|
beat(1) :: snd('gtr')
|
||||||
|
.note([0,5].scale("persian", 3).beat() + 50)
|
||||||
|
.out()
|
||||||
|
`,
|
||||||
|
true
|
||||||
|
)}
|
||||||
|
|
||||||
|
- Currently supported scales :
|
||||||
|
| Scale name | Values |
|
||||||
|
|------------|------------------------|
|
||||||
|
| major | 0, 2, 4, 5, 7, 9, 11
|
||||||
|
| naturalMinor | 0, 2, 3, 5, 7, 8, 10
|
||||||
|
| harmonicMinor | 0, 2, 3, 5, 7, 8, 11
|
||||||
|
| melodicMinor | 0, 2, 3, 5, 7, 9, 11
|
||||||
|
| dorian | 0, 2, 3, 5, 7, 9, 10
|
||||||
|
| phrygian | 0, 1, 3, 5, 7, 8, 10
|
||||||
|
| lydian | 0, 2, 4, 6, 7, 9, 11
|
||||||
|
| mixolydian | 0, 2, 4, 5, 7, 9, 10
|
||||||
|
| aeolian | 0, 2, 3, 5, 7, 8, 10
|
||||||
|
| locrian | 0, 1, 3, 5, 6, 8, 10
|
||||||
|
| wholeTone | 0, 2, 4, 6, 8, 10
|
||||||
|
| majorPentatonic | 0, 2, 4, 7, 9
|
||||||
|
| minorPentatonic | 0, 3, 5, 7, 10
|
||||||
|
| chromatic | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
|
||||||
|
| blues | 0, 3, 5, 6, 7, 10
|
||||||
|
| diminished | 0, 2, 3, 5, 6, 8, 9, 11
|
||||||
|
| neapolitanMinor | 0, 1, 3, 5, 7, 8, 11
|
||||||
|
| neapolitanMajor | 0, 1, 3, 5, 7, 9, 11
|
||||||
|
| enigmatic | 0, 1, 4, 6, 8, 10, 11],
|
||||||
|
| doubleHarmonic | 0, 1, 4, 5, 7, 8, 11
|
||||||
|
| octatonic | 0, 2, 3, 5, 6, 8, 9, 11
|
||||||
|
| bebopDominant | 0, 2, 4, 5, 7, 9, 10, 11
|
||||||
|
| bebopMajor | 0, 2, 4, 5, 7, 8, 9, 11
|
||||||
|
| bebopMinor | 0, 2, 3, 5, 7, 8, 9, 11
|
||||||
|
| bebopDorian | 0, 2, 3, 4, 5, 7, 9, 10
|
||||||
|
| harmonicMajor | 0, 2, 4, 5, 7, 8, 11
|
||||||
|
| hungarianMinor | 0, 2, 3, 6, 7, 8, 11
|
||||||
|
| hungarianMajor | 0, 3, 4, 6, 7, 9, 10
|
||||||
|
| oriental | 0, 1, 4, 5, 6, 9, 10
|
||||||
|
| romanianMinor | 0, 2, 3, 6, 7, 9, 10
|
||||||
|
| spanishGypsy | 0, 1, 4, 5, 7, 8, 10
|
||||||
|
| jewish | 0, 1, 4, 5, 7, 8, 10
|
||||||
|
| hindi | 0, 2, 4, 5, 7, 8, 10
|
||||||
|
| japanese | 0, 1, 5, 7, 8
|
||||||
|
| hirajoshi | 0, 2, 3, 7, 8
|
||||||
|
| kumoi | 0, 2, 3, 7, 9
|
||||||
|
| inSen | 0, 1, 5, 7, 10
|
||||||
|
| iwato | 0, 1, 5, 6, 10
|
||||||
|
| yo | 0, 2, 5, 7, 9
|
||||||
|
| minorBlues | 0, 3, 5, 6, 7, 10
|
||||||
|
| algerian | 0, 2, 3, 5, 6, 7, 8, 11
|
||||||
|
| augmented | 0, 3, 4, 7, 8, 11
|
||||||
|
| balinese | 0, 1, 3, 7, 8
|
||||||
|
| byzantine | 0, 1, 4, 5, 7, 8, 11
|
||||||
|
| chinese | 0, 4, 6, 7, 11
|
||||||
|
| egyptian |0, 2, 5, 7, 10
|
||||||
|
| eightToneSpanish | 0, 1, 3, 4, 5, 6, 8, 10
|
||||||
|
| hawaiian | 0, 2, 3, 5, 7, 9, 10
|
||||||
|
| hindustan | 0, 2, 4, 5, 7, 8, 10
|
||||||
|
| persian | 0, 1, 4, 5, 6, 8, 11
|
||||||
|
| eastIndianPurvi | 0, 1, 4, 6, 7, 8, 11
|
||||||
|
| orientalA | 0, 1, 4, 5, 6, 9, 10
|
||||||
|
|
||||||
- <ic>add()</ic>: add a given amount to every list element.
|
- <ic>add()</ic>: add a given amount to every list element.
|
||||||
- <ic>sub()</ic>: add a given amount to every list element.
|
- <ic>sub()</ic>: add a given amount to every list element.
|
||||||
|
|||||||
Reference in New Issue
Block a user