Fixing a thousand bugs

This commit is contained in:
2023-10-08 19:05:20 +02:00
parent 89a0f8a0a3
commit 0a23ff442f
3 changed files with 46 additions and 56 deletions

View File

@ -1,6 +1,6 @@
import { type UserAPI } from "./API";
import { safeScale, stepsToScale } from "zifferjs";
export { };
export {};
declare global {
interface Array<T> {
@ -12,13 +12,12 @@ declare global {
random(index: number): T;
rand(index: number): T;
degrade(amount: number): T;
repeatAll(amount: number): T;
repeatPair(amount: number): T;
repeat(amount: number): T;
repeatEven(amount: number): T;
repeatOdd(amount: number): T;
beat(division: number): T;
b(division: number): T;
bar(): T;
pulse(): T;
pick(): T;
loop(index: number): T;
shuffle(): this;
@ -26,7 +25,6 @@ declare global {
scaleArp(scaleName: string): this;
rotate(steps: number): this;
unique(): this;
in(value: T): boolean;
square(): number[];
sqrt(): number[];
gen(min: number, max: number, times: number): number[];
@ -34,18 +32,14 @@ declare global {
}
export const makeArrayExtensions = (api: UserAPI) => {
Array.prototype.in = function <T>(this: T[], value: T): boolean {
return this.includes(value);
};
Array.prototype.square = function(): number[] {
Array.prototype.square = function (): number[] {
/**
* @returns New array with squared values.
*/
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.
*/
@ -54,7 +48,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
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.
* @returns New array with added values.
@ -62,7 +56,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
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.
* @returns New array with subtracted values.
@ -70,7 +64,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
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.
* @returns New array with multiplied values.
@ -78,7 +72,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
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.
* @returns New array with divided values. Throws if division by zero.
@ -87,7 +81,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
return this.map((x: number) => x / amount);
};
Array.prototype.pick = function() {
Array.prototype.pick = function () {
/**
* Returns a random element from an array.
*
@ -96,7 +90,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
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.
* @param min - The minimum value of the random numbers
@ -113,25 +107,22 @@ export const makeArrayExtensions = (api: UserAPI) => {
);
};
Array.prototype.bar = function() {
Array.prototype.bar = function (value: number = 1) {
/**
* Returns an element from an array based on the current bar.
*
* @param array - The array of values to pick from
*/
return this[api.app.clock.time_position.bar % this.length];
if (value === 1) {
return this[api.app.clock.time_position.bar % this.length];
} else {
return this[
Math.floor(api.app.clock.time_position.bar / value) % this.length
];
}
};
Array.prototype.pulse = function() {
/**
* Returns an element from an array based on the current pulse.
*
* @param array - The array of values to pick from
*/
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 timepos = api.app.clock.pulses_since_origin;
const slice_count = Math.floor(
@ -141,7 +132,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
};
Array.prototype.b = Array.prototype.beat;
Array.prototype.shuffle = function() {
Array.prototype.shuffle = function () {
/**
* Shuffles the array in place.
*
@ -160,7 +151,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
return this;
};
Array.prototype.rotate = function(steps: number) {
Array.prototype.rotate = function (steps: number) {
/**
* Rotates the array in place.
*
@ -180,7 +171,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
return this;
};
Array.prototype.unique = function() {
Array.prototype.unique = function () {
/**
* Removes duplicate elements from the array in place.
*
@ -213,7 +204,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
if (this.length <= 1) {
return this;
}
for (let i = 0; i < this.length;) {
for (let i = 0; i < this.length; ) {
const rand = api.randomGen() * 100;
if (rand < amount) {
if (this.length > 1) {
@ -228,7 +219,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
return this;
};
Array.prototype.repeatAll = function <T>(this: T[], amount: number = 1) {
Array.prototype.repeat = function <T>(this: T[], amount: number = 1) {
/**
* Repeats all elements in the array n times.
*
@ -250,7 +241,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
return this;
};
Array.prototype.repeatPair = function <T>(this: T[], amount: number = 1) {
Array.prototype.repeatOdd = function <T>(this: T[], amount: number = 1) {
/**
* Repeats all elements in the array n times, except for the
* elements at odd indexes.
@ -280,7 +271,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
return this;
};
Array.prototype.repeatOdd = function <T>(this: T[], amount: number = 1) {
Array.prototype.repeatEven = function <T>(this: T[], amount: number = 1) {
/**
* Repeats all elements in the array n times, except for the
* elements at even indexes.
@ -326,7 +317,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
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.
* The index will wrap over the array.
@ -337,7 +328,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
return this[index % this.length];
};
Array.prototype.random = function() {
Array.prototype.random = function () {
/**
* Returns a random element from the array.
*
@ -348,7 +339,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
Array.prototype.rand = Array.prototype.random;
};
Array.prototype.scale = function(
Array.prototype.scale = function (
scale: string = "major",
base_note: number = 0
) {
@ -372,7 +363,7 @@ Array.prototype.scale = function(
});
};
Array.prototype.scaleArp = function(
Array.prototype.scaleArp = function (
scaleName: string = "major",
boundary: number = 0
) {

View File

@ -164,7 +164,7 @@ export abstract class Event {
return this.modify(func);
};
private modify = (func: Function): Event => {
modify = (func: Function): Event => {
/**
* Returns a transformed Event. This function is used internally by the
* other functions of this class. It is just a wrapper for the function

View File

@ -6,11 +6,11 @@ export const patterns = (application: Editor): string => {
return `
# Patterns
Music really comes to life when you start playing with algorithmic patterns. They can be used to describe a melody, a rhythm, a texture, a set of custom parameters or anything else you can think of. Topos comes with a lot of different abstractions to deal with musical patterns of increasing complexity. Some knowledge of patterns and how to use them will help you to break out of simple loops and repeating structures.
Playing with fixed values is fine but what if you could give more life to your parameters? Having parameters that can vary over time is important to describe melodies, rhythms, complex textures, etc. Topos comes with a lot of different abstractions to deal with musical patterns of increasing complexity. Some knowledge of patterns and how to use them will help you to break out of simple loops and repeating structures.
## Working with Arrays
## Arrays
JavaScript is using [Arrays](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) as a data structure for lists. Topos is extending them with custom methods that allow you to enter softly into a universe of musical patterns. These methods can often be chained to compose a more complex expression: <ic>[1, 2, 3].repeatOdd(5).palindrome().beat()</ic>.
One of the most basic JavaScript data structures is [Arrays](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array). Topos is extending this data structure with custom methods that makes it usable for describing patterns that evolve over time. These methods can often be chained to compose more complex expressions: <ic>[1, 2, 3].repeatOdd(5).palindrome().beat()</ic>.
- <ic>beat(division: number)</ic>: this method will return the next value in the list every _n_ pulses. By default, <ic>1</ic> equals to one beat but integer and floating point number values are supported as well. This method is extremely powerful and can be used for many different purposes. Check out the examples.
@ -52,8 +52,7 @@ flip(4)::beat(2)::snd('pad').n(2).shape(.5).orbit(2).room(0.9).size(0.9).release
false
)}
- <ic>pulse()</ic>: returns the index of the list corresponding to the current pulse (with wrapping). This method will return a different value for each pulse.
- <ic>bar()</ic>: returns the index of the list corresponding to the current bar (with wrapping). This method will return a different value for each bar.
- <ic>bar(value: number = 1)</ic>: returns the next value every bar (if <ic>value = 1</ic>). Using a larger value will return the next value every <ic>n</ic> bars.
${makeExample(
"A simple drumbeat in no time!",
@ -126,8 +125,8 @@ beat(.25)::snd('amencutup').n([1,2,3,4,5,6,7,8,9].degrade(20).loop($(1))).out()
true
)}
- <ic>repeatAll(amount: number)</ic>: repeat every list elements _n_ times.
- <ic>repeatPair(amount: number)</ic>: repeaet every pair element of the list _n_ times.
- <ic>repeat(amount: number)</ic>: repeat every list elements _n_ times.
- <ic>repeatEven(amount: number)</ic>: repeaet every pair element of the list _n_ times.
- <ic>repeatOdd(amount: number)</ic>: repeaet every odd element of the list _n_ times.
${makeExample(
@ -183,31 +182,31 @@ ${makeExample(
beat(1)::snd('sine').sustain(0.1).freq([100,100,100,100,200].unique().beat()).out()
`,
true
)}
)}
- <ic>scale(scale: string, base note: number)</ic>: Map each element of the list to the closest note of the slected scale. [0, 2, 3, 5 ].scale("major", 50) returns [50, 52, <ic>54</ic>, 55]. You can use western scale names like (Major, Minor, Minor pentatonic ...) or [zeitler](https://ianring.com/musictheory/scales/traditions/zeitler) scale names. Alternatively you can also use the integers as used by Ian Ring in his [study of scales](https://ianring.com/musictheory/scales/).
${makeExample(
"Mapping the note array to the E3 major scale",
`
"Mapping the note array to the E3 major scale",
`
beat(1) :: snd('gtr')
.note([0, 5, 2, 1, 7].scale("Major", 52).beat())
.out()
`,
true
true
)}
- <ic>scaleArp(scale: string, mask: number)</ic>: extrapolate a custom-masked scale from each list elements. [0].scale("major", 3) returns [0,2,4]. <ic>scaleArp</ic> supports the same scales as <ic>scale</ic>.
${makeExample(
"Extrapolate a 3-elements Mixolydian scale from 2 notes",
`
"Extrapolate a 3-elements Mixolydian scale from 2 notes",
`
beat(1) :: snd('gtr')
.note([0, 5].scaleArp("mixolydian", 3).beat() + 50)
.out()
`,
true
)}
true
)}
- <ic>add()</ic>: add a given amount to every list element.