sound.",
example: "sound('bd').out()",
},
tempo: {
name: "tempo",
category: "time",
description: "Get or set the current beats per minute.",
example: "tempo(135) // set the bpm to 135",
},
out: {
name: "out",
category: "audio",
description: "Connect the sound() chain to the output",
example: "sound('clap').out()",
},
script: {
name: "script",
category: "core",
description: "Execute one or more local scripts",
example: "beat(1) :: script(1)",
},
clear_script: {
name: "clear_script",
category: "core",
description: "Deletes the given script",
example: "clear_script(2)",
},
copy_script: {
name: "copy_script",
category: "core",
description: "Copy the script from to the script to",
example: "copy_script(1, 2)",
},
warp: {
name: "warp",
category: "core",
description: "jumps to the n tick of the clock.",
example: "warp(1) :: log('back to the big bang!')",
},
beat_warp: {
name: "beat_warp",
category: "core",
description: "jumps to the n beat of the clock.",
example: "beat_warp(1) :: log('back to the first beat!')",
},
flipbar: {
name: "flipbar",
category: "time",
description:
"works just like flip at the level of bars instead of beats",
example: "flipbar(2)::beat(1)::snd('kick').out()",
},
onbar: {
name: "onbar",
category: "time",
description: "return true when targetted bar(s) is/are reached in period",
example: "onbar(4, 4)::beat(.5)::snd('hh').out();",
},
begin: {
name: "begin",
category: "sampling",
description: "Audio playback start time (0-1)",
example: "sound('cp').begin(.5).out()",
},
end: {
name: "end",
category: "sampling",
description: "Audio playback end time (0-1)",
example: "sound('cp').end(.5).out()",
},
mouseX: {
name: "mouseX",
category: "mouse",
description: "Mouse X position (big float)",
example: "log(mouseX())",
},
mouseY: {
name: "mouseY",
category: "mouse",
description: "Mouse Y position (big float)",
example: "log(mouseY())",
},
noteX: {
name: "noteX",
category: "mouse",
description: "Mouse X position (as MIDI note)",
example: "log(noteX())",
},
noteY: {
name: "noteY",
category: "mouse",
description: "Mouse Y position (as MIDI note)",
example: "log(noteY())",
},
cut: {
name: "cut",
category: "sampling",
description: "Cutting sample when other sample met on same orbit (0 or 1)",
example: "sound('cp').cut(1).out()",
},
pan: {
name: "pan",
category: "audio",
description: "Stereo panning (-1 to 1)",
example: "sound('cp').pan(-1).out()",
},
zrand: {
name: "zrand",
category: "synthesis",
description: "ZzFX randomisation factor",
example: "sound('zzfx').zrand(.5).out()",
},
curve: {
name: "curve",
category: "synthesis",
description: "ZzFX waveshaping (0-3)",
example: "sound('zzfx').curve(1).out()",
},
slide: {
name: "slide",
category: "synthesis",
description: "ZzFX pitch slide",
example: "sound('zzfx').slide(1).out()",
},
deltaSlide: {
name: "deltaSlide",
category: "synthesis",
description: "ZzFX pitch delta slide",
example: "sound('zzfx').deltaSlide(1).out()",
},
pitchJump: {
name: "pitchJump",
category: "synthesis",
description: "ZzFX pitch jump",
example: "sound('zzfx').pitchJump(1).out()",
},
pitchJumpTime: {
name: "pitchJumpTime",
category: "synthesis",
description: "ZzFX pitch jump time (time before jump)",
example: "sound('zzfx').pitchJumpTime(1).out()",
},
zcrush: {
name: "zcrush",
category: "synthesis",
description: "ZzFX bitcrushing",
example: "sound('zzfx').zcrush(1).out()",
},
zdelay: {
name: "zdelay",
category: "synthesis",
description: "ZzFX delay",
example: "sound('zzfx').zdelay(1).out()",
},
tremolo: {
name: "tremolo",
category: "synthesis",
description: "ZzFX weird tremolo effect",
example: "sound('zzfx').tremolo(1).out()",
},
speak: {
name: "speak",
category: "synthesis",
description: "Text to speech synthesizer",
example: "beat(2) :: speak('Topos!','fr',irand(0,5))",
},
midi_outputs: {
name: "midi_outputs",
category: "midi",
description: "List of available MIDI outputs",
example: "midi_outputs()",
},
midi_output: {
name: "midi_output",
category: "midi",
description: "Set the current MIDI output",
example: "midi_output('IAC Driver Bus 1')",
},
midi: {
name: "midi",
category: "midi",
description: "Send a MIDI message",
example: "midi(144, 60, 100)",
},
control_change: {
name: "control_change",
category: "midi",
description: "Send a MIDI control change message",
example: "control_change({control: 1, value: 60, channel: 10})",
},
program_change: {
name: "program_change",
category: "midi",
description: "Send a MIDI program change message",
example: "program_change(1, 10)",
},
sysex: {
name: "sysex",
category: "midi",
description: "Send a MIDI sysex message",
example: "sysex(0xF0, 0x7D, 0x00, 0x06, 0x01, 0xF7)",
},
midi_clock: {
name: "midi_clock",
category: "midi",
description: "Send a MIDI clock message",
example: "midi_clock()",
},
degrade: {
name: "degrade",
category: "patterns",
description: "Removes n% of the given array randomly",
example: "[0,1,2,3].degrade(20)",
},
loop: {
name: "loop",
category: "patterns",
description: "Loop over the given array using an iterator",
example: "[0,1,2,3].loop($(1))",
},
$: {
name: "$",
category: "patterns",
description: "Iterator",
example: "[0,1,2,3].loop($(1))",
},
counter: {
name: "counter",
category: "patterns",
description: "Counter/iterator",
example: "counter('my_counter_, 20, 1)",
},
drunk: {
name: "drunk",
category: "patterns",
description: "Returns the next value in a drunk walk",
example: "drunk()",
},
drunk_max: {
name: "drunk_max",
category: "patterns",
description: "Sets the maximum value of the drunk walk",
example: "drunk_max(10)",
},
drunk_min: {
name: "drunk_min",
category: "patterns",
description: "Sets the minimum value of the drunk walk",
example: "drunk_min(0)",
},
drunk_wrap: {
name: "drunk_wrap",
category: "patterns",
description: "Wraps (or not) of the drunk walk (boolean)",
example: "drunk_wrap(true)",
},
v: {
name: "v",
category: "variable",
description: "Global Variable setter or getter",
example: "v('my_var', 10) // Sets global variable 'my_var' to 10",
},
delete_variable: {
name: "delete_variable",
category: "variable",
description: "Deletes the given global variable",
example: "delete_variable('my_var')",
},
clear_variables: {
name: "clear_variables",
category: "variable",
description: "Clears all global variables",
example: "clear_variables()",
},
shuffle: {
name: "shuffle",
category: "patterns",
description: "Shuffle the given array",
example: "[0,1,2,3].shuffle()",
},
rotate: {
name: "rotate",
category: "patterns",
description: "Rotate the given array to the right for n indexes",
example: "[0,1,2,3].rotate(2)",
},
unique: {
name: "unique",
category: "patterns",
description: "Remove duplicates from the given array",
example: "[0,1,2,3,3,3].unique()",
},
add: {
name: "add",
category: "patterns",
description: "Add a value to each element of the given array",
example: "[0,1,2,3].add(1)",
},
sub: {
name: "sub",
category: "patterns",
description: "Substract a value to each element of the given array",
example: "[0,1,2,3].sub(1)",
},
mul: {
name: "mul",
category: "patterns",
description: "Multiply each element of the given array by a value",
example: "[0,1,2,3].mul(2)",
},
div: {
name: "div",
category: "patterns",
description: "Divide each element of the given array by a value",
example: "[0,1,2,3].div(2)",
},
scale: {
name: "scale",
category: "patterns",
description: "Scale setter used by Ziffers",
example: "z0('0 1 2 3').scale('major').out()",
},
zzfx: {
name: "zzfx",
category: "synthesis",
description: "ZzFX sound generator",
example: "sound('zzfx').zzfx(...).out()",
},
vib: {
name: "vib",
category: "synthesis",
description: "Vibrato frequency",
example: "sound('sine').vib(1).vibmod(0.5).out()",
},
vibmod: {
name: "vibmod",
category: "synthesis",
description: "Vibrato modulation amount",
example: "sound('sine').vib(1).vibmod(4).out()",
},
fill: {
name: "fill",
category: "performance",
description: "Detects if the Alt key is pressed",
example: "fill() ? 1 : 0.5",
},
ratio: {
name: "ratio",
category: "synthesis",
description: "Compressor ratio",
example: "sound('sine').comp(1).ratio(4).out()",
},
knee: {
name: "knee",
category: "synthesis",
description: "Compressor knee (dB)",
example: "sound('sine').comp(-4).knee(4).out()",
},
compAttack: {
name: "compAttack",
category: "synthesis",
description: "Compressor attack time (in seconds)",
example: "sound('sine').comp(-4).compAttack(0.1).out()",
},
compRelease: {
name: "compRelease",
category: "synthesis",
description: "Compressor release time (in seconds)",
example: "sound('sine').comp(-4).compRelease(0.1).out()",
},
noise: {
name: "noise",
category: "synthesis",
description: "Noise amount in the signal (0-1)",
example: "sound('triangle').noise(.25).out()",
},
};
export const inlineHoveringTips = hoverTooltip(
(view: any, pos: any, side: any) => {
let { from, to, text } = view.state.doc.lineAt(pos);
let start = pos,
end = pos;
while (start > from && /\w/.test(text[start - from - 1])) start--;
while (end < to && /\w/.test(text[end - from])) end++;
if ((start == pos && side < 0) || (end == pos && side > 0)) return null;
return {
pos: start,
end,
above: true,
// @ts-ignore
create(view: EditorView) {
if (
text.slice(start - from, end - from) in completionDatabase ===
false
) {
return { dom: document.createElement("div") };
}
let completion =
completionDatabase[text.slice(start - from, end - from)] || {};
let divContent = `
${completion.name} [${completion.category}]
${completion.description}
${completion.example}
`;
let dom = document.createElement("div");
dom.classList.add("px-4", "py-2", "bg-neutral-700", "rounded-lg");
dom.innerHTML = divContent;
return { dom };
},
};
},
);
export const toposCompletions = (context: CompletionContext) => {
let word = context.matchBefore(/\w*/);
if (word) {
if (word.from == word.to && !context.explicit) return null;
return {
from: word.from,
options: Object.keys(completionDatabase).map((key) => ({
label: key,
type: completionDatabase[key].category,
info: () => {
let div = document.createElement("div");
div.innerHTML = `
${completionDatabase[key].name} [${completionDatabase[key].category}]
${completionDatabase[key].description}
${completionDatabase[key].example}
`;
div.classList.add("px-4", "py-2", "rounded-lg", "w-92");
return div;
},
})),
};
}
};
export const soundCompletions = (context: CompletionContext) => {
let map = soundMap.get();
delete map._base;
let match = context.matchBefore(/sound\(/);
if (match) {
let from = match.from + "sound(".length;
return {
from,
options: Object.keys(map).map((key) => ({
label: key,
type: map[key].data.type,
apply: `"${key}"`,
})),
};
}
return null;
};