diff --git a/src/API.ts b/src/API.ts index 19cbb3d..8ed69f7 100644 --- a/src/API.ts +++ b/src/API.ts @@ -22,21 +22,175 @@ interface ControlChange { value: number; } +declare global { + interface Array { + palindrome(): T[]; + random(index: number): T; + rand(index: number): T; + degrade(amount: number): T; + repeatAll(amount: number): T; + repeatPair(amount: number): T; + repeatOdd(amount: number): T; + loop(index: number): T; + div(division: number): T; + shuffle(): this; + rotate(steps: number): this; + unique(): this; + } +} + +Array.prototype.shuffle = function () { + let currentIndex = this.length, + randomIndex; + while (currentIndex !== 0) { + randomIndex = Math.floor(Math.random() * currentIndex); + currentIndex--; + [this[currentIndex], this[randomIndex]] = [ + this[randomIndex], + this[currentIndex], + ]; + } + return this; +}; + +Array.prototype.rotate = function (steps: number) { + const length = this.length; + if (steps < 0) { + steps = length + (steps % length); + } else if (steps > 0) { + steps = steps % length; + } else { + return this; + } + const rotated = this.splice(-steps, steps); + this.unshift(...rotated); + return this; +}; + +Array.prototype.unique = function () { + const seen = new Set(); + let writeIndex = 0; + for (let readIndex = 0; readIndex < this.length; readIndex++) { + const value = this[readIndex]; + if (!seen.has(value)) { + seen.add(value); + this[writeIndex++] = value; + } + } + this.length = writeIndex; + return this; +}; + +Array.prototype.degrade = function (this: T[], amount: number) { + if (amount < 0 || amount > 100) { + throw new Error("Amount should be between 0 and 100"); + } + if (this.length <= 1) { + return this; + } + for (let i = 0; i < this.length; ) { + const rand = Math.random() * 100; + if (rand < amount) { + if (this.length > 1) { + this.splice(i, 1); + } else { + return this; + } + } else { + i++; + } + } + return this; +}; + +Array.prototype.repeatAll = function (this: T[], amount: number) { + if (amount < 1) { + throw new Error("Amount should be at least 1"); + } + let result = []; + for (let i = 0; i < this.length; i++) { + for (let j = 0; j < amount; j++) { + result.push(this[i]); + } + } + this.length = 0; + this.push(...result); + return this; +}; + +Array.prototype.repeatPair = function (this: T[], amount: number) { + if (amount < 1) { + throw new Error("Amount should be at least 1"); + } + + let result = []; + + for (let i = 0; i < this.length; i++) { + // If the index is even, repeat the element + if (i % 2 === 0) { + for (let j = 0; j < amount; j++) { + result.push(this[i]); + } + } else { + result.push(this[i]); + } + } + + // Update the original array + this.length = 0; + this.push(...result); + return this; +}; + +Array.prototype.repeatOdd = function (this: T[], amount: number) { + if (amount < 1) { + throw new Error("Amount should be at least 1"); + } + + let result = []; + + for (let i = 0; i < this.length; i++) { + // If the index is odd, repeat the element + if (i % 2 !== 0) { + for (let j = 0; j < amount; j++) { + result.push(this[i]); + } + } else { + result.push(this[i]); + } + } + + // Update the original array + this.length = 0; + this.push(...result); + return this; +}; + // @ts-ignore -Array.prototype.palindrome = function (index) { +Array.prototype.palindrome = function () { let left_to_right = Array.from(this); let right_to_left = Array.from(this.reverse()); return left_to_right.concat(right_to_left); }; + +// @ts-ignore +Array.prototype.random = function (this: T[], index: number): T { + return this[Math.floor(Math.random() * this.length)]; +}; + +Array.prototype.loop = function (this: T[], index: number): T { + return this[index % this.length]; +}; + // @ts-ignore Array.prototype.random = function (index) { return this[Math.floor(Math.random() * this.length)]; }; -// @ts-ignore + Array.prototype.loop = function (index) { return this[index % this.length]; }; -// @ts-ignore + Array.prototype.rand = Array.prototype.random; /** @@ -52,13 +206,12 @@ Array.prototype.in = function (this: T[], value: T): boolean { }; export async function loadSamples() { - // const ds = "https://raw.githubusercontent.com/felixroos/dough-samples/main/"; return Promise.all([ initAudioOnFirstClick(), - samples("github:Bubobubobubobubo/Topos-Samples/main"), samples("github:tidalcycles/Dirt-Samples/master").then(() => registerSynthSounds() ), + samples("github:Bubobubobubobubo/Topos-Samples/main"), ]); } diff --git a/src/Documentation.ts b/src/Documentation.ts index 9e44c05..5e9fc07 100644 --- a/src/Documentation.ts +++ b/src/Documentation.ts @@ -523,7 +523,7 @@ There are three basic filters: a _lowpass_, _highpass_ and _bandpass_ filters wi \`\`\`javascript mod(.5) && snd('sawtooth') - .cutoff(pick(2000,500)) + usine(.5) * 4000) + .cutoff(pick(2000,500) + usine(.5) * 4000) .resonance(0.9).freq(pick(100,150)) .out() \`\`\` diff --git a/src/classes/SoundEvent.ts b/src/classes/SoundEvent.ts index 33eccd9..28ac166 100644 --- a/src/classes/SoundEvent.ts +++ b/src/classes/SoundEvent.ts @@ -1,6 +1,6 @@ -import { type Editor } from '../main'; -import { AudibleEvent } from './AbstractEvents'; -import { midiToFreq, noteFromPc } from 'zifferjs'; +import { type Editor } from "../main"; +import { AudibleEvent } from "./AbstractEvents"; +import { midiToFreq, noteFromPc } from "zifferjs"; import { superdough, @@ -8,7 +8,6 @@ import { } from "superdough"; export class SoundEvent extends AudibleEvent { - constructor(sound: string | object, public app: Editor) { super(app); if (typeof sound === "string") this.values = { s: sound, dur: 0.5 }; diff --git a/src/main.ts b/src/main.ts index ea93a74..c6685b8 100644 --- a/src/main.ts +++ b/src/main.ts @@ -559,23 +559,6 @@ export class Editor { (globalThis as Record)[name] = value; }); - // Loading from URL bar - let url = new URLSearchParams(window.location.search); - if (url !== undefined) { - let new_universe; - if (url !== null) { - const universeParam = url.get("universe"); - if (universeParam !== null) { - new_universe = JSON.parse(atob(universeParam)); - const randomName: string = uniqueNamesGenerator({ - dictionaries: [adjectives, colors, animals], - }); - this.loadUniverse(randomName, new_universe["universe"]); - this.emptyUrl(); - } - } - } - this.state = EditorState.create({ extensions: [ ...this.editorExtensions, @@ -602,6 +585,23 @@ export class Editor { }); this.changeModeFromInterface("global"); + + // Loading from URL bar + let url = new URLSearchParams(window.location.search); + if (url !== undefined) { + let new_universe; + if (url !== null) { + const universeParam = url.get("universe"); + if (universeParam !== null) { + new_universe = JSON.parse(atob(universeParam)); + const randomName: string = uniqueNamesGenerator({ + dictionaries: [adjectives, colors, animals], + }); + this.loadUniverse(randomName, new_universe["universe"]); + this.emptyUrl(); + } + } + } } get note_buffer() {