adding the slice and seqslice functions
This commit is contained in:
315
src/API.ts
315
src/API.ts
@ -2,10 +2,10 @@ import { Pitch, Chord, Rest, Event, cachedPattern } from "zifferjs";
|
|||||||
import { MidiConnection } from "./IO/MidiConnection";
|
import { MidiConnection } from "./IO/MidiConnection";
|
||||||
import { tryEvaluate } from "./Evaluator";
|
import { tryEvaluate } from "./Evaluator";
|
||||||
import { DrunkWalk } from "./Utils/Drunk";
|
import { DrunkWalk } from "./Utils/Drunk";
|
||||||
import { LRUCache } from 'lru-cache';
|
import { LRUCache } from "lru-cache";
|
||||||
import { scale } from "./Scales";
|
import { scale } from "./Scales";
|
||||||
import { Editor } from "./main";
|
import { Editor } from "./main";
|
||||||
import { Sound } from './Sound';
|
import { Sound } from "./Sound";
|
||||||
import {
|
import {
|
||||||
samples,
|
samples,
|
||||||
initAudioOnFirstClick,
|
initAudioOnFirstClick,
|
||||||
@ -14,14 +14,13 @@ import {
|
|||||||
} from "superdough";
|
} from "superdough";
|
||||||
|
|
||||||
// This is an LRU cache used for storing persistent patterns
|
// This is an LRU cache used for storing persistent patterns
|
||||||
const cache = new LRUCache({max: 1000, ttl: 1000 * 60 * 5});
|
const cache = new LRUCache({ max: 1000, ttl: 1000 * 60 * 5 });
|
||||||
|
|
||||||
interface ControlChange {
|
interface ControlChange {
|
||||||
channel: number
|
channel: number;
|
||||||
control: number
|
control: number;
|
||||||
value: number
|
value: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
interface Pattern<T> {
|
interface Pattern<T> {
|
||||||
pattern: any[];
|
pattern: any[];
|
||||||
@ -42,7 +41,6 @@ Array.prototype.in = function <T>(this: T[], value: T): boolean {
|
|||||||
return this.includes(value);
|
return this.includes(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
async function loadSamples() {
|
async function loadSamples() {
|
||||||
const ds = "https://raw.githubusercontent.com/felixroos/dough-samples/main/";
|
const ds = "https://raw.githubusercontent.com/felixroos/dough-samples/main/";
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
@ -57,8 +55,7 @@ async function loadSamples() {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
loadSamples()
|
loadSamples();
|
||||||
|
|
||||||
|
|
||||||
export class UserAPI {
|
export class UserAPI {
|
||||||
/**
|
/**
|
||||||
@ -88,7 +85,7 @@ export class UserAPI {
|
|||||||
* @returns the current AudioContext time (wall clock)
|
* @returns the current AudioContext time (wall clock)
|
||||||
*/
|
*/
|
||||||
return this.app.audioContext.currentTime;
|
return this.app.audioContext.currentTime;
|
||||||
}
|
};
|
||||||
|
|
||||||
// =============================================================
|
// =============================================================
|
||||||
// Mouse functions
|
// Mouse functions
|
||||||
@ -99,14 +96,14 @@ export class UserAPI {
|
|||||||
* @returns The current x position of the mouse
|
* @returns The current x position of the mouse
|
||||||
*/
|
*/
|
||||||
return this.app._mouseX;
|
return this.app._mouseX;
|
||||||
}
|
};
|
||||||
|
|
||||||
public mouseY = (): number => {
|
public mouseY = (): number => {
|
||||||
/**
|
/**
|
||||||
* @returns The current y position of the mouse
|
* @returns The current y position of the mouse
|
||||||
*/
|
*/
|
||||||
return this.app._mouseY;
|
return this.app._mouseY;
|
||||||
}
|
};
|
||||||
|
|
||||||
// =============================================================
|
// =============================================================
|
||||||
// Utility functions
|
// Utility functions
|
||||||
@ -125,7 +122,7 @@ export class UserAPI {
|
|||||||
this.app.universes[this.app.selected_universe].locals[arg]
|
this.app.universes[this.app.selected_universe].locals[arg]
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
s = this.script;
|
s = this.script;
|
||||||
|
|
||||||
clear_script = (script: number): void => {
|
clear_script = (script: number): void => {
|
||||||
@ -139,7 +136,7 @@ export class UserAPI {
|
|||||||
committed: "",
|
committed: "",
|
||||||
evaluations: 0,
|
evaluations: 0,
|
||||||
};
|
};
|
||||||
}
|
};
|
||||||
cs = this.clear_script;
|
cs = this.clear_script;
|
||||||
|
|
||||||
copy_script = (from: number, to: number): void => {
|
copy_script = (from: number, to: number): void => {
|
||||||
@ -151,7 +148,7 @@ export class UserAPI {
|
|||||||
*/
|
*/
|
||||||
this.app.universes[this.app.selected_universe].locals[to] =
|
this.app.universes[this.app.selected_universe].locals[to] =
|
||||||
this.app.universes[this.app.selected_universe].locals[from];
|
this.app.universes[this.app.selected_universe].locals[from];
|
||||||
}
|
};
|
||||||
cps = this.copy_script;
|
cps = this.copy_script;
|
||||||
|
|
||||||
// =============================================================
|
// =============================================================
|
||||||
@ -166,7 +163,7 @@ export class UserAPI {
|
|||||||
*/
|
*/
|
||||||
console.log(this.MidiConnection.listMidiOutputs());
|
console.log(this.MidiConnection.listMidiOutputs());
|
||||||
return this.MidiConnection.midiOutputs;
|
return this.MidiConnection.midiOutputs;
|
||||||
}
|
};
|
||||||
|
|
||||||
public midi_output = (outputName: string): void => {
|
public midi_output = (outputName: string): void => {
|
||||||
/**
|
/**
|
||||||
@ -179,9 +176,12 @@ export class UserAPI {
|
|||||||
} else {
|
} else {
|
||||||
this.MidiConnection.switchMidiOutput(outputName);
|
this.MidiConnection.switchMidiOutput(outputName);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
public note = (note: number, options: { [key: string]: number } = {}): void => {
|
public note = (
|
||||||
|
note: number,
|
||||||
|
options: { [key: string]: number } = {}
|
||||||
|
): void => {
|
||||||
/**
|
/**
|
||||||
* Sends a MIDI note to the current MIDI output.
|
* Sends a MIDI note to the current MIDI output.
|
||||||
*
|
*
|
||||||
@ -193,7 +193,7 @@ export class UserAPI {
|
|||||||
const velocity = options.velocity ? options.velocity : 100;
|
const velocity = options.velocity ? options.velocity : 100;
|
||||||
const duration = options.duration ? options.duration : 0.5;
|
const duration = options.duration ? options.duration : 0.5;
|
||||||
this.MidiConnection.sendMidiNote(note, channel, velocity, duration);
|
this.MidiConnection.sendMidiNote(note, channel, velocity, duration);
|
||||||
}
|
};
|
||||||
|
|
||||||
public sysex = (data: Array<number>): void => {
|
public sysex = (data: Array<number>): void => {
|
||||||
/**
|
/**
|
||||||
@ -202,7 +202,7 @@ export class UserAPI {
|
|||||||
* @param data - The sysex data to send
|
* @param data - The sysex data to send
|
||||||
*/
|
*/
|
||||||
this.MidiConnection.sendSysExMessage(data);
|
this.MidiConnection.sendSysExMessage(data);
|
||||||
}
|
};
|
||||||
|
|
||||||
public pitch_bend = (value: number, channel: number): void => {
|
public pitch_bend = (value: number, channel: number): void => {
|
||||||
/**
|
/**
|
||||||
@ -214,7 +214,7 @@ export class UserAPI {
|
|||||||
* @returns The value of the pitch bend
|
* @returns The value of the pitch bend
|
||||||
*/
|
*/
|
||||||
this.MidiConnection.sendPitchBend(value, channel);
|
this.MidiConnection.sendPitchBend(value, channel);
|
||||||
}
|
};
|
||||||
|
|
||||||
public program_change = (program: number, channel: number): void => {
|
public program_change = (program: number, channel: number): void => {
|
||||||
/**
|
/**
|
||||||
@ -224,17 +224,20 @@ export class UserAPI {
|
|||||||
* @param channel - The MIDI channel to send the program change on
|
* @param channel - The MIDI channel to send the program change on
|
||||||
*/
|
*/
|
||||||
this.MidiConnection.sendProgramChange(program, channel);
|
this.MidiConnection.sendProgramChange(program, channel);
|
||||||
}
|
};
|
||||||
|
|
||||||
public midi_clock = (): void => {
|
public midi_clock = (): void => {
|
||||||
/**
|
/**
|
||||||
* Sends a MIDI clock to the current MIDI output.
|
* Sends a MIDI clock to the current MIDI output.
|
||||||
*/
|
*/
|
||||||
this.MidiConnection.sendMidiClock();
|
this.MidiConnection.sendMidiClock();
|
||||||
}
|
};
|
||||||
|
|
||||||
|
public control_change = ({
|
||||||
public control_change = ({control= 20, value= 0, channel=0 }: ControlChange): void => {
|
control = 20,
|
||||||
|
value = 0,
|
||||||
|
channel = 0,
|
||||||
|
}: ControlChange): void => {
|
||||||
/**
|
/**
|
||||||
* Sends a MIDI control change to the current MIDI output.
|
* Sends a MIDI control change to the current MIDI output.
|
||||||
*
|
*
|
||||||
@ -242,53 +245,65 @@ export class UserAPI {
|
|||||||
* @param value - The value of the control
|
* @param value - The value of the control
|
||||||
*/
|
*/
|
||||||
this.MidiConnection.sendMidiControlChange(control, value, channel);
|
this.MidiConnection.sendMidiControlChange(control, value, channel);
|
||||||
}
|
};
|
||||||
|
|
||||||
public midi_panic = (): void => {
|
public midi_panic = (): void => {
|
||||||
/**
|
/**
|
||||||
* Sends a MIDI panic message to the current MIDI output.
|
* Sends a MIDI panic message to the current MIDI output.
|
||||||
*/
|
*/
|
||||||
this.MidiConnection.panic();
|
this.MidiConnection.panic();
|
||||||
}
|
};
|
||||||
|
|
||||||
// =============================================================
|
// =============================================================
|
||||||
// Ziffers related functions
|
// Ziffers related functions
|
||||||
// =============================================================
|
// =============================================================
|
||||||
|
|
||||||
public zn = (input: string,
|
public zn = (
|
||||||
options: {[key: string]: string|number} = {}): Event => {
|
input: string,
|
||||||
const pattern = cachedPattern(input, options);
|
options: { [key: string]: string | number } = {}
|
||||||
//@ts-ignore
|
): Event => {
|
||||||
if(pattern.hasStarted()) {
|
const pattern = cachedPattern(input, options);
|
||||||
|
//@ts-ignore
|
||||||
|
if (pattern.hasStarted()) {
|
||||||
|
const event = pattern.peek();
|
||||||
|
|
||||||
const event = pattern.peek();
|
// Check if event is modified
|
||||||
|
const node = event!.modifiedEvent ? event!.modifiedEvent : event;
|
||||||
|
const channel = (options.channel ? options.channel : 0) as number;
|
||||||
|
const velocity = (options.velocity ? options.velocity : 100) as number;
|
||||||
|
const sustain = (options.sustain ? options.sustain : 0.5) as number;
|
||||||
|
|
||||||
// Check if event is modified
|
if (node instanceof Pitch) {
|
||||||
const node = event!.modifiedEvent ? event!.modifiedEvent : event;
|
if (node.bend) this.MidiConnection.sendPitchBend(node.bend, channel);
|
||||||
const channel = (options.channel ? options.channel : 0) as number;
|
this.MidiConnection.sendMidiNote(
|
||||||
const velocity = (options.velocity ? options.velocity : 100) as number;
|
node.note!,
|
||||||
const sustain = (options.sustain ? options.sustain : 0.5) as number;
|
channel,
|
||||||
|
velocity,
|
||||||
if(node instanceof Pitch) {
|
sustain
|
||||||
if(node.bend) this.MidiConnection.sendPitchBend(node.bend, channel);
|
);
|
||||||
this.MidiConnection.sendMidiNote(node.note!, channel, velocity, sustain);
|
if (node.bend) this.MidiConnection.sendPitchBend(8192, channel);
|
||||||
if(node.bend) this.MidiConnection.sendPitchBend(8192, channel);
|
} else if (node instanceof Chord) {
|
||||||
} else if(node instanceof Chord) {
|
node.pitches.forEach((pitch: Pitch) => {
|
||||||
node.pitches.forEach((pitch: Pitch) => {
|
if (pitch.bend)
|
||||||
if(pitch.bend) this.MidiConnection.sendPitchBend(pitch.bend, channel);
|
this.MidiConnection.sendPitchBend(pitch.bend, channel);
|
||||||
this.MidiConnection.sendMidiNote(pitch.note!, channel, velocity, sustain);
|
this.MidiConnection.sendMidiNote(
|
||||||
if(pitch.bend) this.MidiConnection.sendPitchBend(8192, channel);
|
pitch.note!,
|
||||||
});
|
channel,
|
||||||
} else if(node instanceof Rest) {
|
velocity,
|
||||||
// do nothing for now ...
|
sustain
|
||||||
}
|
);
|
||||||
|
if (pitch.bend) this.MidiConnection.sendPitchBend(8192, channel);
|
||||||
// Remove old modified event
|
});
|
||||||
if(event!.modifiedEvent) event!.modifiedEvent = undefined;
|
} else if (node instanceof Rest) {
|
||||||
|
// do nothing for now ...
|
||||||
}
|
}
|
||||||
//@ts-ignore
|
|
||||||
return pattern.next();
|
// Remove old modified event
|
||||||
}
|
if (event!.modifiedEvent) event!.modifiedEvent = undefined;
|
||||||
|
}
|
||||||
|
//@ts-ignore
|
||||||
|
return pattern.next();
|
||||||
|
};
|
||||||
|
|
||||||
// =============================================================
|
// =============================================================
|
||||||
// Iterator related functions
|
// Iterator related functions
|
||||||
@ -339,7 +354,7 @@ export class UserAPI {
|
|||||||
|
|
||||||
// Return current iterator value
|
// Return current iterator value
|
||||||
return this.iterators[name].value;
|
return this.iterators[name].value;
|
||||||
}
|
};
|
||||||
$ = this.iterator;
|
$ = this.iterator;
|
||||||
|
|
||||||
// =============================================================
|
// =============================================================
|
||||||
@ -361,7 +376,7 @@ export class UserAPI {
|
|||||||
}
|
}
|
||||||
this._drunk.step();
|
this._drunk.step();
|
||||||
return this._drunk.getPosition();
|
return this._drunk.getPosition();
|
||||||
}
|
};
|
||||||
|
|
||||||
public drunk_max = (max: number) => {
|
public drunk_max = (max: number) => {
|
||||||
/**
|
/**
|
||||||
@ -370,7 +385,7 @@ export class UserAPI {
|
|||||||
* @param max - The maximum value of the drunk mechanism
|
* @param max - The maximum value of the drunk mechanism
|
||||||
*/
|
*/
|
||||||
this._drunk.max = max;
|
this._drunk.max = max;
|
||||||
}
|
};
|
||||||
|
|
||||||
public drunk_min = (min: number) => {
|
public drunk_min = (min: number) => {
|
||||||
/**
|
/**
|
||||||
@ -379,7 +394,7 @@ export class UserAPI {
|
|||||||
* @param min - The minimum value of the drunk mechanism
|
* @param min - The minimum value of the drunk mechanism
|
||||||
*/
|
*/
|
||||||
this._drunk.min = min;
|
this._drunk.min = min;
|
||||||
}
|
};
|
||||||
|
|
||||||
public drunk_wrap = (wrap: boolean) => {
|
public drunk_wrap = (wrap: boolean) => {
|
||||||
/**
|
/**
|
||||||
@ -388,7 +403,7 @@ export class UserAPI {
|
|||||||
* @param wrap - Whether the drunk mechanism should wrap around
|
* @param wrap - Whether the drunk mechanism should wrap around
|
||||||
*/
|
*/
|
||||||
this._drunk.toggleWrap(wrap);
|
this._drunk.toggleWrap(wrap);
|
||||||
}
|
};
|
||||||
|
|
||||||
// =============================================================
|
// =============================================================
|
||||||
// Variable related functions
|
// Variable related functions
|
||||||
@ -408,7 +423,7 @@ export class UserAPI {
|
|||||||
this.variables[a] = b;
|
this.variables[a] = b;
|
||||||
return this.variables[a];
|
return this.variables[a];
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
v = this.variable;
|
v = this.variable;
|
||||||
|
|
||||||
public delete_variable = (name: string): void => {
|
public delete_variable = (name: string): void => {
|
||||||
@ -418,7 +433,7 @@ export class UserAPI {
|
|||||||
* @param name - The name of the variable to delete
|
* @param name - The name of the variable to delete
|
||||||
*/
|
*/
|
||||||
delete this.variables[name];
|
delete this.variables[name];
|
||||||
}
|
};
|
||||||
dv = this.delete_variable;
|
dv = this.delete_variable;
|
||||||
|
|
||||||
public clear_variables = (): void => {
|
public clear_variables = (): void => {
|
||||||
@ -430,7 +445,7 @@ export class UserAPI {
|
|||||||
* Use with caution.
|
* Use with caution.
|
||||||
*/
|
*/
|
||||||
this.variables = {};
|
this.variables = {};
|
||||||
}
|
};
|
||||||
cv = this.clear_variables;
|
cv = this.clear_variables;
|
||||||
|
|
||||||
// =============================================================
|
// =============================================================
|
||||||
@ -448,6 +463,20 @@ export class UserAPI {
|
|||||||
return btoa(JSON.stringify(pattern));
|
return btoa(JSON.stringify(pattern));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public slice = (chunk: number): boolean => {
|
||||||
|
const time_pos = this.epulse();
|
||||||
|
const current_chunk = Math.floor(time_pos / chunk);
|
||||||
|
return current_chunk % 2 === 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
public seqslice = (...args: any): any => {
|
||||||
|
const chunk_size = args[0]; // Get the first argument (chunk size)
|
||||||
|
const elements = args.slice(1); // Get the rest of the arguments as an array
|
||||||
|
const timepos = epulse();
|
||||||
|
const slice_count = Math.floor(timepos / chunk_size);
|
||||||
|
return elements[slice_count % elements.length];
|
||||||
|
};
|
||||||
|
|
||||||
public seqmod = (...input: any[]) => {
|
public seqmod = (...input: any[]) => {
|
||||||
if (cache.has(this._sequence_key_generator(input))) {
|
if (cache.has(this._sequence_key_generator(input))) {
|
||||||
let sequence = cache.get(
|
let sequence = cache.get(
|
||||||
@ -458,48 +487,49 @@ export class UserAPI {
|
|||||||
|
|
||||||
if (sequence.options.currentIteration === sequence.options.nextTarget) {
|
if (sequence.options.currentIteration === sequence.options.nextTarget) {
|
||||||
sequence.options.index++;
|
sequence.options.index++;
|
||||||
sequence.options.nextTarget = input[sequence.options.index % input.length];
|
sequence.options.nextTarget =
|
||||||
|
input[sequence.options.index % input.length];
|
||||||
sequence.options.currentIteration = 0;
|
sequence.options.currentIteration = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
cache.set(this._sequence_key_generator(input), {
|
cache.set(this._sequence_key_generator(input), {
|
||||||
pattern: input as any[],
|
pattern: input as any[],
|
||||||
options: sequence.options
|
options: sequence.options,
|
||||||
});
|
});
|
||||||
|
|
||||||
return sequence.options.currentIteration === 0;
|
return sequence.options.currentIteration === 0;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
let pattern_options = {
|
let pattern_options = {
|
||||||
index: -1, nextTarget: this.app.clock.ticks_before_new_bar,
|
index: -1,
|
||||||
currentIteration: 0
|
nextTarget: this.app.clock.ticks_before_new_bar,
|
||||||
|
currentIteration: 0,
|
||||||
};
|
};
|
||||||
if (typeof input[input.length - 1] === "object") {
|
if (typeof input[input.length - 1] === "object") {
|
||||||
pattern_options = {
|
pattern_options = {
|
||||||
...input.pop(),
|
...input.pop(),
|
||||||
...pattern_options as object
|
...(pattern_options as object),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// pattern_options.currentIteration++;
|
// pattern_options.currentIteration++;
|
||||||
// TEST
|
// TEST
|
||||||
pattern_options.nextTarget = this.app.clock.ticks_before_new_bar
|
pattern_options.nextTarget = this.app.clock.ticks_before_new_bar;
|
||||||
|
|
||||||
if (pattern_options.currentIteration === pattern_options.nextTarget) {
|
if (pattern_options.currentIteration === pattern_options.nextTarget) {
|
||||||
pattern_options.index++;
|
pattern_options.index++;
|
||||||
pattern_options.nextTarget = input[pattern_options.index % input.length];
|
pattern_options.nextTarget =
|
||||||
|
input[pattern_options.index % input.length];
|
||||||
pattern_options.currentIteration = 0;
|
pattern_options.currentIteration = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
cache.set(this._sequence_key_generator(input), {
|
cache.set(this._sequence_key_generator(input), {
|
||||||
pattern: input as any[],
|
pattern: input as any[],
|
||||||
options: pattern_options
|
options: pattern_options,
|
||||||
});
|
});
|
||||||
|
|
||||||
return pattern_options.currentIteration === 0;
|
return pattern_options.currentIteration === 0;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
public seq = (...input: any[]) => {
|
public seq = (...input: any[]) => {
|
||||||
/**
|
/**
|
||||||
@ -516,24 +546,24 @@ export class UserAPI {
|
|||||||
* @returns A value in a sequence stored using an LRU Cache
|
* @returns A value in a sequence stored using an LRU Cache
|
||||||
*/
|
*/
|
||||||
if (cache.has(this._sequence_key_generator(input))) {
|
if (cache.has(this._sequence_key_generator(input))) {
|
||||||
let sequence = cache.get(this._sequence_key_generator(input)) as Pattern<any>;
|
let sequence = cache.get(
|
||||||
|
this._sequence_key_generator(input)
|
||||||
|
) as Pattern<any>;
|
||||||
sequence.options.index += 1;
|
sequence.options.index += 1;
|
||||||
cache.set(this._sequence_key_generator(input), sequence);
|
cache.set(this._sequence_key_generator(input), sequence);
|
||||||
return sequence.pattern[
|
return sequence.pattern[sequence.options.index % sequence.pattern.length];
|
||||||
sequence.options.index % sequence.pattern.length
|
|
||||||
];
|
|
||||||
} else {
|
} else {
|
||||||
let pattern_options = { index: 0 };
|
let pattern_options = { index: 0 };
|
||||||
if (typeof input[input.length - 1] === "object") {
|
if (typeof input[input.length - 1] === "object") {
|
||||||
pattern_options = { ...input.pop(), ...pattern_options as object };
|
pattern_options = { ...input.pop(), ...(pattern_options as object) };
|
||||||
}
|
}
|
||||||
cache.set(this._sequence_key_generator(input), {
|
cache.set(this._sequence_key_generator(input), {
|
||||||
pattern: input as any[],
|
pattern: input as any[],
|
||||||
options: pattern_options
|
options: pattern_options,
|
||||||
});
|
});
|
||||||
return cache.get(this._sequence_key_generator(input));
|
return cache.get(this._sequence_key_generator(input));
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
pick = <T>(...array: T[]): T => {
|
pick = <T>(...array: T[]): T => {
|
||||||
/**
|
/**
|
||||||
@ -542,7 +572,7 @@ export class UserAPI {
|
|||||||
* @param array - The array of values to pick from
|
* @param array - The array of values to pick from
|
||||||
*/
|
*/
|
||||||
return array[Math.floor(Math.random() * array.length)];
|
return array[Math.floor(Math.random() * array.length)];
|
||||||
}
|
};
|
||||||
|
|
||||||
seqbeat = <T>(...array: T[]): T => {
|
seqbeat = <T>(...array: T[]): T => {
|
||||||
/**
|
/**
|
||||||
@ -551,7 +581,7 @@ export class UserAPI {
|
|||||||
* @param array - The array of values to pick from
|
* @param array - The array of values to pick from
|
||||||
*/
|
*/
|
||||||
return array[this.ebeat() % array.length];
|
return array[this.ebeat() % array.length];
|
||||||
}
|
};
|
||||||
|
|
||||||
mel = <T>(iterator: number, array: T[]): T => {
|
mel = <T>(iterator: number, array: T[]): T => {
|
||||||
/**
|
/**
|
||||||
@ -561,7 +591,7 @@ export class UserAPI {
|
|||||||
* @param array - The array of values to pick from
|
* @param array - The array of values to pick from
|
||||||
*/
|
*/
|
||||||
return array[iterator % array.length];
|
return array[iterator % array.length];
|
||||||
}
|
};
|
||||||
|
|
||||||
seqbar = <T>(...array: T[]): T => {
|
seqbar = <T>(...array: T[]): T => {
|
||||||
/**
|
/**
|
||||||
@ -570,7 +600,7 @@ export class UserAPI {
|
|||||||
* @param array - The array of values to pick from
|
* @param array - The array of values to pick from
|
||||||
*/
|
*/
|
||||||
return array[(this.app.clock.time_position.bar + 1) % array.length];
|
return array[(this.app.clock.time_position.bar + 1) % array.length];
|
||||||
}
|
};
|
||||||
|
|
||||||
seqpulse = <T>(...array: T[]): T => {
|
seqpulse = <T>(...array: T[]): T => {
|
||||||
/**
|
/**
|
||||||
@ -579,7 +609,7 @@ export class UserAPI {
|
|||||||
* @param array - The array of values to pick from
|
* @param array - The array of values to pick from
|
||||||
*/
|
*/
|
||||||
return array[this.app.clock.time_position.pulse % array.length];
|
return array[this.app.clock.time_position.pulse % array.length];
|
||||||
}
|
};
|
||||||
|
|
||||||
// =============================================================
|
// =============================================================
|
||||||
// Randomness functions
|
// Randomness functions
|
||||||
@ -594,7 +624,7 @@ export class UserAPI {
|
|||||||
* @returns A random integer between min and max
|
* @returns A random integer between min and max
|
||||||
*/
|
*/
|
||||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||||
}
|
};
|
||||||
|
|
||||||
rand = (min: number, max: number): number => {
|
rand = (min: number, max: number): number => {
|
||||||
/**
|
/**
|
||||||
@ -605,7 +635,7 @@ export class UserAPI {
|
|||||||
* @returns A random float between min and max
|
* @returns A random float between min and max
|
||||||
*/
|
*/
|
||||||
return Math.random() * (max - min) + min;
|
return Math.random() * (max - min) + min;
|
||||||
}
|
};
|
||||||
rI = this.randI;
|
rI = this.randI;
|
||||||
r = this.rand;
|
r = this.rand;
|
||||||
|
|
||||||
@ -631,7 +661,7 @@ export class UserAPI {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
return closest;
|
return closest;
|
||||||
}
|
};
|
||||||
quant = this.quantize;
|
quant = this.quantize;
|
||||||
|
|
||||||
public clamp = (value: number, min: number, max: number): number => {
|
public clamp = (value: number, min: number, max: number): number => {
|
||||||
@ -644,7 +674,7 @@ export class UserAPI {
|
|||||||
* @returns A value clamped between min and max
|
* @returns A value clamped between min and max
|
||||||
*/
|
*/
|
||||||
return Math.min(Math.max(value, min), max);
|
return Math.min(Math.max(value, min), max);
|
||||||
}
|
};
|
||||||
cmp = this.clamp;
|
cmp = this.clamp;
|
||||||
|
|
||||||
// =============================================================
|
// =============================================================
|
||||||
@ -663,7 +693,7 @@ export class UserAPI {
|
|||||||
if (n < 1 || n > 500) console.log(`Setting bpm to ${n}`);
|
if (n < 1 || n > 500) console.log(`Setting bpm to ${n}`);
|
||||||
this.app.clock.bpm = n;
|
this.app.clock.bpm = n;
|
||||||
return n;
|
return n;
|
||||||
}
|
};
|
||||||
tempo = this.bpm;
|
tempo = this.bpm;
|
||||||
|
|
||||||
public bpb = (n?: number): number => {
|
public bpb = (n?: number): number => {
|
||||||
@ -678,7 +708,7 @@ export class UserAPI {
|
|||||||
if (n < 1) console.log(`Setting bpb to ${n}`);
|
if (n < 1) console.log(`Setting bpb to ${n}`);
|
||||||
this.app.clock.time_signature[0] = n;
|
this.app.clock.time_signature[0] = n;
|
||||||
return n;
|
return n;
|
||||||
}
|
};
|
||||||
|
|
||||||
public ppqn = (n?: number) => {
|
public ppqn = (n?: number) => {
|
||||||
/**
|
/**
|
||||||
@ -689,7 +719,7 @@ export class UserAPI {
|
|||||||
if (n < 1) console.log(`Setting ppqn to ${n}`);
|
if (n < 1) console.log(`Setting ppqn to ${n}`);
|
||||||
this.app.clock.ppqn = n;
|
this.app.clock.ppqn = n;
|
||||||
return n;
|
return n;
|
||||||
}
|
};
|
||||||
|
|
||||||
public time_signature = (numerator: number, denominator: number): void => {
|
public time_signature = (numerator: number, denominator: number): void => {
|
||||||
/**
|
/**
|
||||||
@ -700,7 +730,7 @@ export class UserAPI {
|
|||||||
* @returns The current time signature
|
* @returns The current time signature
|
||||||
*/
|
*/
|
||||||
this.app.clock.time_signature = [numerator, denominator];
|
this.app.clock.time_signature = [numerator, denominator];
|
||||||
}
|
};
|
||||||
|
|
||||||
// =============================================================
|
// =============================================================
|
||||||
// Probability functions
|
// Probability functions
|
||||||
@ -713,7 +743,7 @@ export class UserAPI {
|
|||||||
* @returns True 10% of the time
|
* @returns True 10% of the time
|
||||||
*/
|
*/
|
||||||
return Math.random() > 0.9;
|
return Math.random() > 0.9;
|
||||||
}
|
};
|
||||||
|
|
||||||
public sometimes = (): boolean => {
|
public sometimes = (): boolean => {
|
||||||
/**
|
/**
|
||||||
@ -722,7 +752,7 @@ export class UserAPI {
|
|||||||
* @returns True 50% of the time
|
* @returns True 50% of the time
|
||||||
*/
|
*/
|
||||||
return Math.random() > 0.5;
|
return Math.random() > 0.5;
|
||||||
}
|
};
|
||||||
|
|
||||||
public rarely = (): boolean => {
|
public rarely = (): boolean => {
|
||||||
/**
|
/**
|
||||||
@ -731,7 +761,7 @@ export class UserAPI {
|
|||||||
* @returns True 25% of the time
|
* @returns True 25% of the time
|
||||||
*/
|
*/
|
||||||
return Math.random() > 0.75;
|
return Math.random() > 0.75;
|
||||||
}
|
};
|
||||||
|
|
||||||
public often = (): boolean => {
|
public often = (): boolean => {
|
||||||
/**
|
/**
|
||||||
@ -740,7 +770,7 @@ export class UserAPI {
|
|||||||
* @returns True 75% of the time
|
* @returns True 75% of the time
|
||||||
*/
|
*/
|
||||||
return Math.random() > 0.25;
|
return Math.random() > 0.25;
|
||||||
}
|
};
|
||||||
|
|
||||||
public almostAlways = (): boolean => {
|
public almostAlways = (): boolean => {
|
||||||
/**
|
/**
|
||||||
@ -749,7 +779,7 @@ export class UserAPI {
|
|||||||
* @returns True 90% of the time
|
* @returns True 90% of the time
|
||||||
*/
|
*/
|
||||||
return Math.random() > 0.1;
|
return Math.random() > 0.1;
|
||||||
}
|
};
|
||||||
|
|
||||||
public dice = (sides: number): number => {
|
public dice = (sides: number): number => {
|
||||||
/**
|
/**
|
||||||
@ -759,7 +789,7 @@ export class UserAPI {
|
|||||||
* @returns The value of a dice roll with n sides
|
* @returns The value of a dice roll with n sides
|
||||||
*/
|
*/
|
||||||
return Math.floor(Math.random() * sides) + 1;
|
return Math.floor(Math.random() * sides) + 1;
|
||||||
}
|
};
|
||||||
|
|
||||||
// =============================================================
|
// =============================================================
|
||||||
// Iterator functions (for loops, with evaluation count, etc...)
|
// Iterator functions (for loops, with evaluation count, etc...)
|
||||||
@ -773,12 +803,11 @@ export class UserAPI {
|
|||||||
*/
|
*/
|
||||||
if (n !== undefined) {
|
if (n !== undefined) {
|
||||||
this.app.universes[this.app.selected_universe].global.evaluations = n;
|
this.app.universes[this.app.selected_universe].global.evaluations = n;
|
||||||
return this.app.universes[this.app.selected_universe]
|
return this.app.universes[this.app.selected_universe];
|
||||||
}
|
}
|
||||||
return this.app.universes[this.app.selected_universe]
|
return this.app.universes[this.app.selected_universe].global
|
||||||
.global
|
|
||||||
.evaluations as number;
|
.evaluations as number;
|
||||||
}
|
};
|
||||||
|
|
||||||
// =============================================================
|
// =============================================================
|
||||||
// Time markers
|
// Time markers
|
||||||
@ -791,7 +820,7 @@ export class UserAPI {
|
|||||||
* @returns The current bar number
|
* @returns The current bar number
|
||||||
*/
|
*/
|
||||||
return this.app.clock.time_position.bar;
|
return this.app.clock.time_position.bar;
|
||||||
}
|
};
|
||||||
|
|
||||||
tick = (): number => {
|
tick = (): number => {
|
||||||
/**
|
/**
|
||||||
@ -800,7 +829,7 @@ export class UserAPI {
|
|||||||
* @returns The current tick number
|
* @returns The current tick number
|
||||||
*/
|
*/
|
||||||
return this.app.clock.tick;
|
return this.app.clock.tick;
|
||||||
}
|
};
|
||||||
|
|
||||||
pulse = (): number => {
|
pulse = (): number => {
|
||||||
/**
|
/**
|
||||||
@ -809,7 +838,7 @@ export class UserAPI {
|
|||||||
* @returns The current pulse number
|
* @returns The current pulse number
|
||||||
*/
|
*/
|
||||||
return this.app.clock.time_position.pulse;
|
return this.app.clock.time_position.pulse;
|
||||||
}
|
};
|
||||||
|
|
||||||
beat = (): number => {
|
beat = (): number => {
|
||||||
/**
|
/**
|
||||||
@ -818,28 +847,28 @@ export class UserAPI {
|
|||||||
* @returns The current beat number
|
* @returns The current beat number
|
||||||
*/
|
*/
|
||||||
return this.app.clock.time_position.beat;
|
return this.app.clock.time_position.beat;
|
||||||
}
|
};
|
||||||
|
|
||||||
ebeat = (): number => {
|
ebeat = (): number => {
|
||||||
/**
|
/**
|
||||||
* Returns the current beat number since the origin of time
|
* Returns the current beat number since the origin of time
|
||||||
*/
|
*/
|
||||||
return this.app.clock.beats_since_origin;
|
return this.app.clock.beats_since_origin;
|
||||||
}
|
};
|
||||||
|
|
||||||
epulse = (): number => {
|
epulse = (): number => {
|
||||||
/**
|
/**
|
||||||
* Returns the current number of pulses elapsed since origin of time
|
* Returns the current number of pulses elapsed since origin of time
|
||||||
*/
|
*/
|
||||||
return this.app.clock.pulses_since_origin;
|
return this.app.clock.pulses_since_origin;
|
||||||
}
|
};
|
||||||
|
|
||||||
onbar = (n: number, ...bar: number[]): boolean => {
|
onbar = (n: number, ...bar: number[]): boolean => {
|
||||||
// n is acting as a modulo on the bar number
|
// n is acting as a modulo on the bar number
|
||||||
const bar_list = [...Array(n).keys()].map((i) => i + 1);
|
const bar_list = [...Array(n).keys()].map((i) => i + 1);
|
||||||
console.log(bar.some((b) => bar_list.includes(b % n)));
|
console.log(bar.some((b) => bar_list.includes(b % n)));
|
||||||
return bar.some((b) => bar_list.includes(b % n));
|
return bar.some((b) => bar_list.includes(b % n));
|
||||||
}
|
};
|
||||||
|
|
||||||
onbeat = (...beat: number[]): boolean => {
|
onbeat = (...beat: number[]): boolean => {
|
||||||
/**
|
/**
|
||||||
@ -853,7 +882,7 @@ export class UserAPI {
|
|||||||
*/
|
*/
|
||||||
let final_pulses: boolean[] = [];
|
let final_pulses: boolean[] = [];
|
||||||
beat.forEach((b) => {
|
beat.forEach((b) => {
|
||||||
b = (b % this.app.clock.time_signature[0]) + 1;
|
b = (b % this.app.clock.time_signature[0]) + 1;
|
||||||
let integral_part = Math.floor(b);
|
let integral_part = Math.floor(b);
|
||||||
let decimal_part = b - integral_part;
|
let decimal_part = b - integral_part;
|
||||||
final_pulses.push(
|
final_pulses.push(
|
||||||
@ -863,7 +892,7 @@ export class UserAPI {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
return final_pulses.some((p) => p == true);
|
return final_pulses.some((p) => p == true);
|
||||||
}
|
};
|
||||||
|
|
||||||
stop = (): void => {
|
stop = (): void => {
|
||||||
/**
|
/**
|
||||||
@ -874,7 +903,7 @@ export class UserAPI {
|
|||||||
*/
|
*/
|
||||||
this.app.clock.pause();
|
this.app.clock.pause();
|
||||||
this.app.setButtonHighlighting("pause", true);
|
this.app.setButtonHighlighting("pause", true);
|
||||||
}
|
};
|
||||||
silence = this.stop;
|
silence = this.stop;
|
||||||
hush = this.stop;
|
hush = this.stop;
|
||||||
|
|
||||||
@ -886,7 +915,7 @@ export class UserAPI {
|
|||||||
* @returns True p% of the time
|
* @returns True p% of the time
|
||||||
*/
|
*/
|
||||||
return Math.random() * 100 < p;
|
return Math.random() * 100 < p;
|
||||||
}
|
};
|
||||||
|
|
||||||
toss = (): boolean => {
|
toss = (): boolean => {
|
||||||
/**
|
/**
|
||||||
@ -900,7 +929,7 @@ export class UserAPI {
|
|||||||
* @see almostNever
|
* @see almostNever
|
||||||
*/
|
*/
|
||||||
return Math.random() > 0.5;
|
return Math.random() > 0.5;
|
||||||
}
|
};
|
||||||
|
|
||||||
min = (...values: number[]): number => {
|
min = (...values: number[]): number => {
|
||||||
/**
|
/**
|
||||||
@ -910,7 +939,7 @@ export class UserAPI {
|
|||||||
* @returns The minimum value of the list of numbers
|
* @returns The minimum value of the list of numbers
|
||||||
*/
|
*/
|
||||||
return Math.min(...values);
|
return Math.min(...values);
|
||||||
}
|
};
|
||||||
|
|
||||||
max = (...values: number[]): number => {
|
max = (...values: number[]): number => {
|
||||||
/**
|
/**
|
||||||
@ -920,7 +949,7 @@ export class UserAPI {
|
|||||||
* @returns The maximum value of the list of numbers
|
* @returns The maximum value of the list of numbers
|
||||||
*/
|
*/
|
||||||
return Math.max(...values);
|
return Math.max(...values);
|
||||||
}
|
};
|
||||||
|
|
||||||
limit = (value: number, min: number, max: number): number => {
|
limit = (value: number, min: number, max: number): number => {
|
||||||
/**
|
/**
|
||||||
@ -932,7 +961,7 @@ export class UserAPI {
|
|||||||
* @returns The limited value
|
* @returns The limited value
|
||||||
*/
|
*/
|
||||||
return Math.min(Math.max(value, min), max);
|
return Math.min(Math.max(value, min), max);
|
||||||
}
|
};
|
||||||
|
|
||||||
delay = (ms: number, func: Function): void => {
|
delay = (ms: number, func: Function): void => {
|
||||||
/**
|
/**
|
||||||
@ -943,7 +972,7 @@ export class UserAPI {
|
|||||||
* @returns The current time signature
|
* @returns The current time signature
|
||||||
*/
|
*/
|
||||||
setTimeout(func, ms);
|
setTimeout(func, ms);
|
||||||
}
|
};
|
||||||
|
|
||||||
delayr = (ms: number, nb: number, func: Function): void => {
|
delayr = (ms: number, nb: number, func: Function): void => {
|
||||||
/**
|
/**
|
||||||
@ -958,7 +987,7 @@ export class UserAPI {
|
|||||||
list.forEach((ms, _) => {
|
list.forEach((ms, _) => {
|
||||||
setTimeout(func, ms);
|
setTimeout(func, ms);
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
mod = (...pulse: number[]): boolean => {
|
mod = (...pulse: number[]): boolean => {
|
||||||
/**
|
/**
|
||||||
@ -968,7 +997,7 @@ export class UserAPI {
|
|||||||
* @returns True if the current pulse is a modulo of any of the given pulses
|
* @returns True if the current pulse is a modulo of any of the given pulses
|
||||||
*/
|
*/
|
||||||
return pulse.some((p) => this.app.clock.time_position.pulse % p === 0);
|
return pulse.some((p) => this.app.clock.time_position.pulse % p === 0);
|
||||||
}
|
};
|
||||||
|
|
||||||
modbar = (...bar: number[]): boolean => {
|
modbar = (...bar: number[]): boolean => {
|
||||||
/**
|
/**
|
||||||
@ -979,7 +1008,7 @@ export class UserAPI {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
return bar.some((b) => this.app.clock.time_position.bar % b === 0);
|
return bar.some((b) => this.app.clock.time_position.bar % b === 0);
|
||||||
}
|
};
|
||||||
|
|
||||||
// =============================================================
|
// =============================================================
|
||||||
// Rythmic generators
|
// Rythmic generators
|
||||||
@ -1001,7 +1030,7 @@ export class UserAPI {
|
|||||||
* @returns boolean value based on the euclidian sequence
|
* @returns boolean value based on the euclidian sequence
|
||||||
*/
|
*/
|
||||||
return this._euclidean_cycle(pulses, length, rotate)[iterator % length];
|
return this._euclidean_cycle(pulses, length, rotate)[iterator % length];
|
||||||
}
|
};
|
||||||
|
|
||||||
_euclidean_cycle(
|
_euclidean_cycle(
|
||||||
pulses: number,
|
pulses: number,
|
||||||
@ -1037,7 +1066,7 @@ export class UserAPI {
|
|||||||
let convert: string = n.toString(2);
|
let convert: string = n.toString(2);
|
||||||
let tobin: boolean[] = convert.split("").map((x: string) => x === "1");
|
let tobin: boolean[] = convert.split("").map((x: string) => x === "1");
|
||||||
return tobin[iterator % tobin.length];
|
return tobin[iterator % tobin.length];
|
||||||
}
|
};
|
||||||
|
|
||||||
// =============================================================
|
// =============================================================
|
||||||
// Low Frequency Oscillators
|
// Low Frequency Oscillators
|
||||||
@ -1063,7 +1092,7 @@ export class UserAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
};
|
||||||
|
|
||||||
sine = (freq: number = 1, offset: number = 0): number => {
|
sine = (freq: number = 1, offset: number = 0): number => {
|
||||||
/**
|
/**
|
||||||
@ -1076,7 +1105,7 @@ export class UserAPI {
|
|||||||
return (
|
return (
|
||||||
Math.sin(this.app.clock.ctx.currentTime * Math.PI * 2 * freq) + offset
|
Math.sin(this.app.clock.ctx.currentTime * Math.PI * 2 * freq) + offset
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
usine = (freq: number = 1, offset: number = 0): number => {
|
usine = (freq: number = 1, offset: number = 0): number => {
|
||||||
/**
|
/**
|
||||||
@ -1088,7 +1117,7 @@ export class UserAPI {
|
|||||||
* @see sine
|
* @see sine
|
||||||
*/
|
*/
|
||||||
return (this.sine(freq, offset) + 1) / 2;
|
return (this.sine(freq, offset) + 1) / 2;
|
||||||
}
|
};
|
||||||
|
|
||||||
saw = (freq: number = 1, offset: number = 0): number => {
|
saw = (freq: number = 1, offset: number = 0): number => {
|
||||||
/**
|
/**
|
||||||
@ -1103,7 +1132,7 @@ export class UserAPI {
|
|||||||
* @see noise
|
* @see noise
|
||||||
*/
|
*/
|
||||||
return ((this.app.clock.ctx.currentTime * freq) % 1) * 2 - 1 + offset;
|
return ((this.app.clock.ctx.currentTime * freq) % 1) * 2 - 1 + offset;
|
||||||
}
|
};
|
||||||
|
|
||||||
usaw = (freq: number = 1, offset: number = 0): number => {
|
usaw = (freq: number = 1, offset: number = 0): number => {
|
||||||
/**
|
/**
|
||||||
@ -1115,7 +1144,7 @@ export class UserAPI {
|
|||||||
* @see saw
|
* @see saw
|
||||||
*/
|
*/
|
||||||
return (this.saw(freq, offset) + 1) / 2;
|
return (this.saw(freq, offset) + 1) / 2;
|
||||||
}
|
};
|
||||||
|
|
||||||
triangle = (freq: number = 1, offset: number = 0): number => {
|
triangle = (freq: number = 1, offset: number = 0): number => {
|
||||||
/**
|
/**
|
||||||
@ -1128,7 +1157,7 @@ export class UserAPI {
|
|||||||
* @see noise
|
* @see noise
|
||||||
*/
|
*/
|
||||||
return Math.abs(this.saw(freq, offset)) * 2 - 1;
|
return Math.abs(this.saw(freq, offset)) * 2 - 1;
|
||||||
}
|
};
|
||||||
|
|
||||||
utriangle = (freq: number = 1, offset: number = 0): number => {
|
utriangle = (freq: number = 1, offset: number = 0): number => {
|
||||||
/**
|
/**
|
||||||
@ -1140,7 +1169,7 @@ export class UserAPI {
|
|||||||
* @see triangle
|
* @see triangle
|
||||||
*/
|
*/
|
||||||
return (this.triangle(freq, offset) + 1) / 2;
|
return (this.triangle(freq, offset) + 1) / 2;
|
||||||
}
|
};
|
||||||
|
|
||||||
square = (freq: number = 1, offset: number = 0): number => {
|
square = (freq: number = 1, offset: number = 0): number => {
|
||||||
/**
|
/**
|
||||||
@ -1153,7 +1182,7 @@ export class UserAPI {
|
|||||||
* @see noise
|
* @see noise
|
||||||
*/
|
*/
|
||||||
return this.saw(freq, offset) > 0 ? 1 : -1;
|
return this.saw(freq, offset) > 0 ? 1 : -1;
|
||||||
}
|
};
|
||||||
|
|
||||||
usquare = (freq: number = 1, offset: number = 0): number => {
|
usquare = (freq: number = 1, offset: number = 0): number => {
|
||||||
/**
|
/**
|
||||||
@ -1165,7 +1194,7 @@ export class UserAPI {
|
|||||||
* @see square
|
* @see square
|
||||||
*/
|
*/
|
||||||
return (this.square(freq, offset) + 1) / 2;
|
return (this.square(freq, offset) + 1) / 2;
|
||||||
}
|
};
|
||||||
|
|
||||||
noise = (): number => {
|
noise = (): number => {
|
||||||
/**
|
/**
|
||||||
@ -1179,7 +1208,7 @@ export class UserAPI {
|
|||||||
* @see noise
|
* @see noise
|
||||||
*/
|
*/
|
||||||
return Math.random() * 2 - 1;
|
return Math.random() * 2 - 1;
|
||||||
}
|
};
|
||||||
|
|
||||||
// =============================================================
|
// =============================================================
|
||||||
// Math functions
|
// Math functions
|
||||||
@ -1193,7 +1222,7 @@ export class UserAPI {
|
|||||||
|
|
||||||
sound = (sound: string) => {
|
sound = (sound: string) => {
|
||||||
return new Sound(sound, this.app);
|
return new Sound(sound, this.app);
|
||||||
}
|
};
|
||||||
|
|
||||||
samples = samples;
|
samples = samples;
|
||||||
|
|
||||||
@ -1206,7 +1235,5 @@ export class UserAPI {
|
|||||||
// TODO: Implement this. This function should change the rate at which the global script
|
// TODO: Implement this. This function should change the rate at which the global script
|
||||||
// is evaluated. This is useful for slowing down the script, or speeding it up. The default
|
// is evaluated. This is useful for slowing down the script, or speeding it up. The default
|
||||||
// would be 1.0, which is the current rate (very speedy).
|
// would be 1.0, which is the current rate (very speedy).
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -284,9 +284,7 @@ const about: string = `
|
|||||||
|
|
||||||
## The Topos Project
|
## The Topos Project
|
||||||
|
|
||||||
Topos is an experimental web based algorithmic sequencer programmed by **BuboBubo** (Raphaël Forment) and **Amiika** (Miika Alonen). It is written using [TypeScript](https://google.fr) and [Vite](https://google.fr). Many thanks to Felix Roos for making the [Superdough](https://www.npmjs.com/package/superdough) audio backend available for experimentation.
|
Topos is an experimental web based algorithmic sequencer programmed by **BuboBubo** ([Raphaël Forment](https://raphaelforment.fr) and **Amiika** ([Miika Alonen](https//github.com/amiika). It is written using [TypeScript](https://google.fr) and [Vite](https://google.fr). Many thanks to Felix Roos for making the [Superdough](https://www.npmjs.com/package/superdough) audio backend available for experimentation. This project is based on the [Monome Teletype](https://monome.org) by [Brian Crabtree](https://nnnnnnnn.co/) and [Kelli Cain](https://kellicain.com/). We hope to follow and honor the same spirit of sharing and experimentation. How much can the Teletype be extended while staying accessible and installation-free?
|
||||||
|
|
||||||
This project is based on the [Monome Teletype](https://monome.org) by Brian Crabtree. We hope to follow and honor the same spirit of sharing and experimentation. How much can the Teletype be extended while staying accessible and installation-free?
|
|
||||||
|
|
||||||
## About Live Coding
|
## About Live Coding
|
||||||
|
|
||||||
@ -294,9 +292,7 @@ This project is based on the [Monome Teletype](https://monome.org) by Brian Crab
|
|||||||
|
|
||||||
## Free and open-source software
|
## Free and open-source software
|
||||||
|
|
||||||
Topos is a free and open-source software distributed under [GPL-3.0](https://github.com/Bubobubobubobubo/Topos/blob/main/LICENSE) licence.
|
Topos is a free and open-source software distributed under [GPL-3.0](https://github.com/Bubobubobubobubo/Topos/blob/main/LICENSE) licence. We welcome all contributions and ideas. You can find the source code on [GitHub](https://github.com/Bubobubobubobubo/topos). You can also join us on [Discord](https://discord.gg/8Q2QV6Z6) to discuss about the project and live coding in general.
|
||||||
We welcome all contributions and ideas. You can find the source code on [GitHub](https://github.com/Bubobubobubobubo/topos).
|
|
||||||
You can also join us on [Discord](https://discord.gg/8Q2QV6Z6) to discuss about the project and live coding in general.
|
|
||||||
|
|
||||||
**Have fun!**
|
**Have fun!**
|
||||||
`;
|
`;
|
||||||
@ -304,7 +300,7 @@ You can also join us on [Discord](https://discord.gg/8Q2QV6Z6) to discuss about
|
|||||||
const code: string = `
|
const code: string = `
|
||||||
# Code
|
# Code
|
||||||
|
|
||||||
Topos is using the [JavaScript](https://en.wikipedia.org/wiki/JavaScript) syntax because it lives in a web browser where JS is the default programming language. It is also a language that you can learn to speak quite fast if you are already familiar with other programming lanugages. You are not going to write a lot of code anyway but familiarity with the language can help. Here are some good resources:
|
Topos is using the [JavaScript](https://en.wikipedia.org/wiki/JavaScript) syntax because it lives in a web browser where JS is the default programming language. It is also a language that you can learn to speak quite fast if you are already familiar with other programming languages. You are not going to write a lot of code anyway but familiarity with the language can help. Here are some good resources:
|
||||||
|
|
||||||
- [MDN (Mozilla Web Docs)](https://developer.mozilla.org/): it covers pretty much anything and is considered to be a reliable source to learn how the web currently works. We use it quite a lot to develop Topos.
|
- [MDN (Mozilla Web Docs)](https://developer.mozilla.org/): it covers pretty much anything and is considered to be a reliable source to learn how the web currently works. We use it quite a lot to develop Topos.
|
||||||
|
|
||||||
@ -319,7 +315,9 @@ You **do not need to have any prior knowledge of programming** to use Topos. It
|
|||||||
The code you enter in any of the scripts is evaluated in strict mode. This tells your browser that the code you run can be optimized quite agressively. We need this because by default, **the global script is evaluated 48 times per beat**. It also means that you can crash at the speed of light :smile:. The local and initialisation scripts are evaluated on demand, one run at a time. There are some things to keep in mind:
|
The code you enter in any of the scripts is evaluated in strict mode. This tells your browser that the code you run can be optimized quite agressively. We need this because by default, **the global script is evaluated 48 times per beat**. It also means that you can crash at the speed of light :smile:. The local and initialisation scripts are evaluated on demand, one run at a time. There are some things to keep in mind:
|
||||||
|
|
||||||
- **about variables:** the state of your variables is not kept between iterations. If you write <icode>let a = 2</icode> and change the value later on, the value will be reset to <icode>2</icode> after each run! There are other ways to deal with variables and to share variables between scripts! Some variables like **iterators** can keep their state between iterations because they are saved **with the file itself**.
|
- **about variables:** the state of your variables is not kept between iterations. If you write <icode>let a = 2</icode> and change the value later on, the value will be reset to <icode>2</icode> after each run! There are other ways to deal with variables and to share variables between scripts! Some variables like **iterators** can keep their state between iterations because they are saved **with the file itself**.
|
||||||
- **about errors and printing:** your code will crash! Don't worry, it will hopefully try to crash in the most gracious way possible. To check if your code is erroring, you will have to open the dev console with ${key_shortcut( "Ctrl + Shift + I")}. You cannot directly use <icode>console.log('hello, world')</icode> in the interface. You will have to open the console as well to see your messages being printed there!
|
- **about errors and printing:** your code will crash! Don't worry, it will hopefully try to crash in the most gracious way possible. To check if your code is erroring, you will have to open the dev console with ${key_shortcut(
|
||||||
|
"Ctrl + Shift + I"
|
||||||
|
)}. You cannot directly use <icode>console.log('hello, world')</icode> in the interface. You will have to open the console as well to see your messages being printed there!
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const functions: string = `
|
const functions: string = `
|
||||||
|
|||||||
Reference in New Issue
Block a user