Compare commits
17 Commits
superdough
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
| dea8808721 | |||
| aa2eb0651d | |||
| ec68419775 | |||
| cf702fd9f1 | |||
| 5e565e3a11 | |||
| d9906857d3 | |||
| e592499711 | |||
| c13d1bb072 | |||
| d2f9376197 | |||
| 8940bf3505 | |||
| 9d7fe9e815 | |||
| 59dc42b103 | |||
| 47534a0724 | |||
| a36aa53e04 | |||
| 4db41275b4 | |||
| 8b10af555c | |||
| 2ee66cd9fb |
12
ToposServer/package-lock.json
generated
12
ToposServer/package-lock.json
generated
@ -1,16 +1,16 @@
|
||||
{
|
||||
"name": "topos-server",
|
||||
"version": "1.0.0",
|
||||
"version": "0.0.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "topos-server",
|
||||
"version": "1.0.0",
|
||||
"version": "0.0.1",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"osc": "^2.4.4",
|
||||
"ws": "^8.14.2"
|
||||
"ws": "^8.17.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@serialport/binding-mock": {
|
||||
@ -309,9 +309,9 @@
|
||||
"integrity": "sha512-P+6vtWyuDw+MB01X7UeF8TaHBvbCovf4HPEMF/SV7BdDc1SMTiBy13SRD71lQh4ExFTG1d/WNzDGDCyOKSMblw=="
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.14.2",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz",
|
||||
"integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==",
|
||||
"version": "8.17.1",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
|
||||
"integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
|
||||
@ -10,6 +10,6 @@
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"osc": "^2.4.4",
|
||||
"ws": "^8.14.2"
|
||||
"ws": "^8.17.1"
|
||||
}
|
||||
}
|
||||
|
||||
@ -174,6 +174,7 @@
|
||||
<summary class="font-semibold lg:text-xl text-orange-300">Basics</summary>
|
||||
<div class="flex flex-col">
|
||||
<p rel="noopener noreferrer" id="docs_introduction" class="doc_header">Welcome </p>
|
||||
<p rel="noopener noreferrer" id="docs_atelier" class="doc_header">Atelier (FR)</p>
|
||||
<p rel="noopener noreferrer" id="docs_interface" class="doc_header">Interface</p>
|
||||
<p rel="noopener noreferrer" id="docs_interaction" class="doc_header">Interaction</p>
|
||||
<p rel="noopener noreferrer" id="docs_shortcuts" class="doc_header">Keyboard</p>
|
||||
@ -201,7 +202,6 @@
|
||||
<div class="flex flex-col">
|
||||
<p rel="noopener noreferrer" id="docs_audio_basics" class="doc_subheader">Playing a sound</p>
|
||||
<p rel="noopener noreferrer" id="docs_amplitude" class="doc_subheader">Amplitude</p>
|
||||
<p rel="noopener noreferrer" id="docs_pitch" class="doc_subheader">Pitch</p>
|
||||
<p rel="noopener noreferrer" id="docs_sampler" class="doc_subheader">Sampler</p>
|
||||
<p rel="noopener noreferrer" id="docs_synths" class="doc_subheader">Synths</p>
|
||||
<p rel="noopener noreferrer" id="docs_filters" class="doc_subheader">Filters</p>
|
||||
@ -368,10 +368,12 @@
|
||||
<input id="show-completions" type="checkbox" value="" class="w-4 h-4 text-blue-600 rounded focus:ring-blue-600 focus:ring-2">
|
||||
<label for="default-checkbox" class="ml-2 text-sm font-medium text-foreground">Show Completions</label>
|
||||
</div>
|
||||
<!--
|
||||
<div class="flex items-center mb-4 ml-5">
|
||||
<input id="load-demo-songs" type="checkbox" value="" class="w-4 h-4 text-blue-600 rounded focus:ring-blue-600">
|
||||
<label for="default-checkbox" class="ml-2 text-sm font-medium text-foreground">Load Demo Song</label>
|
||||
</div>
|
||||
-->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -22,7 +22,6 @@
|
||||
"@codemirror/theme-one-dark": "^6.1.2",
|
||||
"@replit/codemirror-vim": "^6.0.14",
|
||||
"@strudel.cycles/webaudio": "^0.8.2",
|
||||
"@strudel/soundfonts": "^0.11.0",
|
||||
"@types/marked": "^5.0.1",
|
||||
"@types/showdown": "^2.0.1",
|
||||
"acorn": "^8.10.0",
|
||||
@ -39,7 +38,7 @@
|
||||
"postcss": "^8.4.27",
|
||||
"showdown": "^2.1.0",
|
||||
"showdown-highlight": "^3.1.0",
|
||||
"superdough": "^0.10.0",
|
||||
"superdough": "^0.9.12",
|
||||
"tailwind-highlightjs": "^2.0.1",
|
||||
"tailwindcss": "^3.3.3",
|
||||
"tone": "^14.8.49",
|
||||
|
||||
19
src/API.ts
19
src/API.ts
@ -27,10 +27,6 @@ import {
|
||||
soundMap,
|
||||
// @ts-ignore
|
||||
} from "superdough";
|
||||
import {
|
||||
registerSoundfonts
|
||||
// @ts-ignore
|
||||
} from "@strudel/soundfonts";
|
||||
import { Speaker } from "./extensions/StringExtensions";
|
||||
import { getScaleNotes } from "zifferjs";
|
||||
import { OscilloscopeConfig } from "./Visuals/Oscilloscope";
|
||||
@ -74,7 +70,6 @@ export async function loadSamples() {
|
||||
samples("github:Bubobubobubobubo/Dough-Waveforms/main", undefined, {
|
||||
tag: "Waveforms",
|
||||
}),
|
||||
registerSoundfonts(),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -1607,6 +1602,20 @@ export class UserAPI {
|
||||
};
|
||||
ry = this.rhythm;
|
||||
|
||||
|
||||
public nrhythm = (
|
||||
div: number,
|
||||
pulses: number,
|
||||
length: number,
|
||||
rotate: number = 0,
|
||||
): boolean => {
|
||||
let rhythm = this._euclidean_cycle(pulses, length, rotate).map(n => !n)
|
||||
return (
|
||||
this.beat(div) && rhythm.beat(div)
|
||||
);
|
||||
};
|
||||
nry = this.nrhythm;
|
||||
|
||||
_euclidean_cycle(
|
||||
pulses: number,
|
||||
length: number,
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { type Editor } from "./main";
|
||||
// Basics
|
||||
import { introduction } from "./documentation/basics/welcome";
|
||||
import { atelier } from "./documentation/basics/atelier";
|
||||
import { loading_samples } from "./documentation/learning/samples/loading_samples";
|
||||
import { amplitude } from "./documentation/learning/audio_engine/amplitude";
|
||||
import { pitch } from "./documentation/learning/audio_engine/pitch";
|
||||
import { effects } from "./documentation/learning/audio_engine/effects";
|
||||
import { sampler } from "./documentation/learning/audio_engine/sampler";
|
||||
import { sample_banks } from "./documentation/learning/samples/sample_banks";
|
||||
@ -78,6 +78,7 @@ export const makeExampleFactory = (application: Editor): Function => {
|
||||
|
||||
export const documentation_pages = [
|
||||
"introduction",
|
||||
"atelier",
|
||||
"sampler",
|
||||
"amplitude",
|
||||
"audio_basics",
|
||||
@ -127,6 +128,7 @@ export const documentation_factory = (application: Editor) => {
|
||||
|
||||
return {
|
||||
introduction: introduction(application),
|
||||
atelier: atelier(application),
|
||||
interface: software_interface(application),
|
||||
interaction: interaction(application),
|
||||
code: code(application),
|
||||
@ -153,7 +155,6 @@ export const documentation_factory = (application: Editor) => {
|
||||
generators: generators(application),
|
||||
shortcuts: shortcuts(application),
|
||||
amplitude: amplitude(application),
|
||||
pitch: pitch(application),
|
||||
effects: effects(application),
|
||||
sampler: sampler(application),
|
||||
mouse: mouse(application),
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// import { tutorial_universe } from "./universes/tutorial";
|
||||
import { gzipSync, decompressSync, strFromU8 } from "fflate";
|
||||
import { examples } from "./examples/excerpts";
|
||||
// import { examples } from "./examples/excerpts";
|
||||
import { type Editor } from "./main";
|
||||
import { uniqueNamesGenerator, colors, animals } from "unique-names-generator";
|
||||
import { tryEvaluate } from "./Evaluator";
|
||||
@ -63,7 +63,7 @@ export interface Settings {
|
||||
selected_universe: string;
|
||||
line_numbers: boolean;
|
||||
time_position: boolean;
|
||||
load_demo_songs: boolean;
|
||||
// load_demo_songs: boolean;
|
||||
tips: boolean;
|
||||
completions: boolean;
|
||||
send_clock: boolean;
|
||||
@ -150,7 +150,7 @@ export class AppSettings {
|
||||
public midi_clock_input: string | undefined = undefined;
|
||||
public default_midi_input: string | undefined = undefined;
|
||||
public midi_clock_ppqn: number = 24;
|
||||
public load_demo_songs: boolean = true;
|
||||
// public load_demo_songs: boolean = true;
|
||||
|
||||
constructor() {
|
||||
const settingsFromStorage = JSON.parse(
|
||||
@ -174,7 +174,7 @@ export class AppSettings {
|
||||
this.midi_clock_input = settingsFromStorage.midi_clock_input;
|
||||
this.midi_clock_ppqn = settingsFromStorage.midi_clock_ppqn || 24;
|
||||
this.default_midi_input = settingsFromStorage.default_midi_input;
|
||||
this.load_demo_songs = settingsFromStorage.load_demo_songs;
|
||||
// this.load_demo_songs = settingsFromStorage.load_demo_songs;
|
||||
} else {
|
||||
this.universes = template_universes;
|
||||
}
|
||||
@ -204,7 +204,7 @@ export class AppSettings {
|
||||
midi_clock_input: this.midi_clock_input,
|
||||
midi_clock_ppqn: this.midi_clock_ppqn,
|
||||
default_midi_input: this.default_midi_input,
|
||||
load_demo_songs: this.load_demo_songs,
|
||||
// load_demo_songs: this.load_demo_songs,
|
||||
};
|
||||
}
|
||||
|
||||
@ -232,7 +232,7 @@ export class AppSettings {
|
||||
this.midi_clock_input = settings.midi_clock_input;
|
||||
this.midi_clock_ppqn = settings.midi_clock_ppqn;
|
||||
this.default_midi_input = settings.default_midi_input;
|
||||
this.load_demo_songs = settings.load_demo_songs;
|
||||
// this.load_demo_songs = settings.load_demo_songs;
|
||||
localStorage.setItem("topos", JSON.stringify(this.data));
|
||||
}
|
||||
}
|
||||
@ -245,23 +245,22 @@ export const initializeSelectedUniverse = (app: Editor): void => {
|
||||
* @param app - The main application
|
||||
* @returns void
|
||||
*/
|
||||
if (app.settings.load_demo_songs) {
|
||||
let random_example = examples[Math.floor(Math.random() * examples.length)];
|
||||
app.selected_universe = "Demo";
|
||||
// if (app.settings.load_demo_songs) {
|
||||
// let random_example = examples[Math.floor(Math.random() * examples.length)];
|
||||
// app.selected_universe = "Demo";
|
||||
// app.universes[app.selected_universe] = structuredClone(template_universe);
|
||||
// app.universes[app.selected_universe].global.committed = random_example;
|
||||
// app.universes[app.selected_universe].global.candidate = random_example;
|
||||
// } else {
|
||||
try {
|
||||
app.selected_universe = app.settings.selected_universe;
|
||||
if (app.universes[app.selected_universe] === undefined)
|
||||
app.universes[app.selected_universe] =
|
||||
structuredClone(template_universe);
|
||||
} catch (error) {
|
||||
app.settings.selected_universe = "Welcome";
|
||||
app.selected_universe = app.settings.selected_universe;
|
||||
app.universes[app.selected_universe] = structuredClone(template_universe);
|
||||
app.universes[app.selected_universe].global.committed = random_example;
|
||||
app.universes[app.selected_universe].global.candidate = random_example;
|
||||
} else {
|
||||
try {
|
||||
app.selected_universe = app.settings.selected_universe;
|
||||
if (app.universes[app.selected_universe] === undefined)
|
||||
app.universes[app.selected_universe] =
|
||||
structuredClone(template_universe);
|
||||
} catch (error) {
|
||||
app.settings.selected_universe = "Welcome";
|
||||
app.selected_universe = app.settings.selected_universe;
|
||||
app.universes[app.selected_universe] = structuredClone(template_universe);
|
||||
}
|
||||
}
|
||||
(
|
||||
app.interface.universe_viewer as HTMLInputElement
|
||||
|
||||
@ -44,8 +44,8 @@ export const installInterfaceLogic = (app: Editor) => {
|
||||
app.settings.midi_channels_scripts;
|
||||
(app.interface.midi_clock_ppqn as HTMLInputElement).value =
|
||||
app.settings.midi_clock_ppqn.toString();
|
||||
(app.interface.load_demo_songs as HTMLInputElement).checked =
|
||||
app.settings.load_demo_songs;
|
||||
// (app.interface.load_demo_songs as HTMLInputElement).checked =
|
||||
// app.settings.load_demo_songs;
|
||||
|
||||
const tabs = document.querySelectorAll('[id^="tab-"]');
|
||||
// Iterate over the tabs with an index
|
||||
@ -373,8 +373,8 @@ export const installInterfaceLogic = (app: Editor) => {
|
||||
midiChannelsScripts.checked = app.settings.midi_channels_scripts;
|
||||
const midiClockPpqn = app.interface.midi_clock_ppqn as HTMLInputElement;
|
||||
midiClockPpqn.value = app.settings.midi_clock_ppqn.toString();
|
||||
const loadDemoSongs = app.interface.load_demo_songs as HTMLInputElement;
|
||||
loadDemoSongs.checked = app.settings.load_demo_songs;
|
||||
// const loadDemoSongs = app.interface.load_demo_songs as HTMLInputElement;
|
||||
// loadDemoSongs.checked = app.settings.load_demo_songs;
|
||||
const vimModeCheckbox = app.interface.vim_mode_checkbox as HTMLInputElement;
|
||||
vimModeCheckbox.checked = app.settings.vimMode;
|
||||
|
||||
@ -502,12 +502,12 @@ export const installInterfaceLogic = (app: Editor) => {
|
||||
app.settings.midi_clock_ppqn = value;
|
||||
});
|
||||
|
||||
app.interface.load_demo_songs.addEventListener("change", () => {
|
||||
let checked = (app.interface.load_demo_songs as HTMLInputElement).checked
|
||||
? true
|
||||
: false;
|
||||
app.settings.load_demo_songs = checked;
|
||||
});
|
||||
// app.interface.load_demo_songs.addEventListener("change", () => {
|
||||
// let checked = (app.interface.load_demo_songs as HTMLInputElement).checked
|
||||
// ? true
|
||||
// : false;
|
||||
// app.settings.load_demo_songs = checked;
|
||||
// });
|
||||
|
||||
app.interface.universe_creator.addEventListener("submit", (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
@ -80,13 +80,7 @@ export class SoundEvent extends AudibleEvent {
|
||||
fmrelease: ["fmrelease", "fmrel"],
|
||||
fmvelocity: ["fmvelocity", "fmvel"],
|
||||
fmwave: ["fmwave", "fmw"],
|
||||
pattack: ["pattack", "patt"],
|
||||
pdecay: ["pdecay", "pdec"],
|
||||
psustain: ["psustain", "psus"],
|
||||
prelease: ["prelease", "prel"],
|
||||
penv: ["penv"],
|
||||
pcurve: ["pcurve"],
|
||||
panchor: ["panchor"],
|
||||
phaser: ["phaser", "phas"],
|
||||
phaserDepth: ["phaserDepth", "phasdepth"],
|
||||
phaserSweep: ["phaserSweep", "phassweep"],
|
||||
phaserCenter: ["phaserCenter", "phascenter"],
|
||||
|
||||
14406
src/colors.json
14406
src/colors.json
File diff suppressed because it is too large
Load Diff
BIN
src/documentation/basics/TOPOS_COMMANDS.pdf
Normal file
BIN
src/documentation/basics/TOPOS_COMMANDS.pdf
Normal file
Binary file not shown.
193
src/documentation/basics/atelier.ts
Normal file
193
src/documentation/basics/atelier.ts
Normal file
@ -0,0 +1,193 @@
|
||||
import { type Editor } from "../../main";
|
||||
import { makeExampleFactory } from "../../Documentation";
|
||||
|
||||
export const atelier = (application: Editor): string => {
|
||||
const makeExample = makeExampleFactory(application);
|
||||
return `
|
||||
# Atelier (06 mars 2024)
|
||||
|
||||
Bonjour tout le monde ! Nous sommes :
|
||||
|
||||
- [Rémi Georges](https://remigeorges.fr) : musicien, réalisateur en informatique musicale.
|
||||
- [Agathe Herrou](https://www.youtube.com/@th4music) : musicienne, chercheuse.
|
||||
- [Raphaël Forment](https://raphaelforment.fr) : musicien, doctorant.
|
||||
|
||||
Nous pratiquons le [live coding](https://livecoding.fr). Nous utilisons notre ordinateur comme un instrument de musique, nous programmons de la musique devant notre public. Nous pouvons faire plein de choses comme :
|
||||
|
||||
- créer des instruments de musique, des synthétiseurs, des boîtes à rythme.
|
||||
- jouer des échantillons, charger des images, des vidéos, créer des animations.
|
||||
- contrôler d'autres instruments, jouer avec d'autres musiciens.
|
||||
|
||||
Topos est un instrument de musique. On peut l'utiliser depuis n'importe quel ordinateur, sans avoir à installer quoi que ce soit. Nous l'avons fabriqué pour que tout le monde puisse jouer facilement de la musique.
|
||||
|
||||
|
||||
## Découverte
|
||||
|
||||
<br>
|
||||
|
||||
${makeExample(
|
||||
"Percussions", `
|
||||
tempo(120) // Changer le tempo
|
||||
beat(1)::sound('kick').out()
|
||||
beat(2)::sound('snare').out()
|
||||
beat(.5)::sound('hh').out()
|
||||
`, true,)}
|
||||
|
||||
<br>
|
||||
|
||||
- Qu'est-ce qu'il se passe si je change un nombre ?
|
||||
- Qu'est-ce qu'il se passe si je change un nom ?
|
||||
- Essayez par exemple <ic>"sid"</ic> ou <ic>"trump"</ic>.
|
||||
- Qu'est-ce qu'il se passe si j'enlève <ic>.out()</ic> ?
|
||||
- Est-il possible de jouer un rythme très rapide ou très lent ?
|
||||
|
||||
|
||||
### Ajout d'une basse
|
||||
|
||||
<br>
|
||||
|
||||
${makeExample(
|
||||
"Une basse", `
|
||||
// Aucun changement dans le code
|
||||
beat(1)::sound('kick').out()
|
||||
beat(2)::sound('snare').out()
|
||||
beat(.5)::sound('hh').out()
|
||||
|
||||
// Une nouvelle partie
|
||||
beat([0.25,0.5].beat(1))::sound("pluck")
|
||||
.note([40,45].beat(2)).out()
|
||||
`, true,)}
|
||||
|
||||
<br>
|
||||
|
||||
- Qu'est-ce que le son <ic>"pluck"</ic> ?
|
||||
|
||||
- Que signifie <ic>.note([40,45].beat(2))</ic> ?
|
||||
|
||||
- Que se passe-t-il si je change la valeur dans <ic>.beat(2)</ic> ?
|
||||
|
||||
- Que se passe-t-il lorsque j'ajoute de nouveaux nombres dans <ic>[40, 45]</ic> ?
|
||||
|
||||
### Ajout d'une mélodie
|
||||
|
||||
<br>
|
||||
|
||||
${makeExample(
|
||||
"Le morceau complet", `
|
||||
// Aucun changement dans le code
|
||||
beat(1)::sound('kick').out()
|
||||
beat(2)::sound('snare').out()
|
||||
beat(.5)::sound('hh').out()
|
||||
beat([0.25,0.5].beat(1))::sound("pluck")
|
||||
.note([40,45].beat(2)).out()
|
||||
|
||||
// Nouvelle partie mélodique
|
||||
beat([0.25,0.5].beat())::sound("pluck")
|
||||
.note([0,7,5,8,2,9,0].scale("Major",60).beat(1))
|
||||
.vib(8).vibmod(1/4)
|
||||
.delay(0.5).room(1.5).size(0.5)
|
||||
.out()
|
||||
`, true,)}
|
||||
|
||||
<br>
|
||||
|
||||
Ici, on ajoute une nouvelle mélodie mais il s'agit aussi d'un nouvel instrument. C'est pour cela que le code est plus long. Quand on fait du <em>live coding</em>, on code tout en même temps : notes, rythmes, mélodies, sons. C'est beaucoup de choses ! C'est pour cela que le code est court, on essaie de tout taper très vite en jouant !
|
||||
|
||||
- Que signifie selon vous <ic>vib</ic>, <ic>delay</ic>, <ic>room</ic> ou <ic>size</ic> ?
|
||||
|
||||
- Que se passe-t-il si je change les valeurs dans <ic>vib</ic>, <ic>delay</ic>, <ic>room</ic> ou <ic>size</ic> ?
|
||||
|
||||
<br>
|
||||
|
||||
**Exercices :**
|
||||
|
||||
- Transformer <ic>vib(8)</ic> en <ic>vib([2,4,8].beat(1))</ic>.
|
||||
- Transformer <ic>"pluck"</ic> en <ic>["pluck", "clap"].beat(1)</ic>.
|
||||
|
||||
Vous pouvez aussi utiliser la fonction <ic>rhythm</ic> pour jouer rapidement des rythmes.
|
||||
|
||||
${makeExample(
|
||||
"Rythmes rythmes rythmes", `
|
||||
rhythm(0.5, 3, 8)::sound('bd').out()
|
||||
rhythm(0.5, 3, 8)::sound('clap').out()
|
||||
rhythm(0.5, 6, 8)::sound('hat').out()
|
||||
rhythm(0.25, 6, 8)::sound('hat')
|
||||
.vel(0.3).speed(2).out()
|
||||
rhythm(0.5, 2, 8)::sound('sd').out()
|
||||
`, true)};
|
||||
|
||||
## Créer un instrument
|
||||
|
||||
<br>
|
||||
|
||||
Nous allons créer un nouvel instrument à partir d'un son de base. Voici un premier son :
|
||||
|
||||
${makeExample("Notre son de base", `beat(2)::sound('sine').note(50).ad(0, .5).out()`, true)}
|
||||
|
||||
<br>
|
||||
|
||||
Ce son est assez ennuyeux. Nous allons ajouter quelques paramètres :
|
||||
|
||||
${makeExample("Beaucoup mieux !", `beat(2)::sound('sine').note(50).fmi(2).fmh(2).ad(0, .5).out()`, true)}
|
||||
|
||||
<br>
|
||||
|
||||
Nous allons aussi ajouter quelques effets intéressants :
|
||||
|
||||
${makeExample("Ajout d'un écho", `beat(2)::sound('sine').note(50)
|
||||
.fmi(2).fmh(2).ad(1/16, 1.5)
|
||||
.delay(0.5).delayt(0.75).out()`,
|
||||
true)}
|
||||
|
||||
<br>
|
||||
|
||||
Nous pouvons utiliser plusieurs techniques pour rendre le son plus dynamique :
|
||||
- générer des valeurs aléatoires pour les paramètres
|
||||
- utiliser des générateurs de valeurs (comme <ic>usine</ic>)
|
||||
- utiliser la souris ou un autre contrôleur pour changer les valeurs en temps réel
|
||||
|
||||
${makeExample("Plus dynamique encore", `
|
||||
beat(2)::sound('sine').note([50,55,57,62,66, 69, 74].mouseX())
|
||||
.fmi(usine(1/4)).fmh([1,2,0.5].beat())
|
||||
.ad(1/16, 1.5).delay(0.5).delayt(0.75)
|
||||
.out()`, true)}
|
||||
|
||||
<br>
|
||||
|
||||
Un exemple final, le plus complexe jusqu'à présent :
|
||||
|
||||
${makeExample("Un instrument de musique complet", `
|
||||
beat(2)::sound('triangle')
|
||||
.note([50,55,57,62,66, 69, 74].mouseX())
|
||||
.fmi(usine(1/4)).fmh([1,2,0.5].beat())
|
||||
.ad(1/16, 1.5).delay(0.5).delayt(0.75)
|
||||
.room(0.5).size(8).lpf(usine(1/3)*4000).out()`, true)}
|
||||
|
||||
## Compléments
|
||||
|
||||
${makeExample("Quelques échantillons", `
|
||||
ab ade ades2 ades3 ades4 alex alphabet amencutup armora arp arpy auto
|
||||
baa baa2 bass bass0 bass1 bass2 bass3 bassdm bassfoo battles bd bend
|
||||
bev bin birds birds3 bleep blip blue bottle breaks125 breaks152
|
||||
breaks157 breaks165 breath bubble can casio cb cc chin circus clak
|
||||
click clubkick co coins control cosmicg cp cr crow d db diphone
|
||||
diphone2 dist dork2 dorkbot dr dr2 dr55 dr_few drum drumtraks e east
|
||||
electro1 em2 erk f feel feelfx fest fire flick fm foo future gab
|
||||
gabba gabbaloud gabbalouder glasstap glitch glitch2 gretsch gtr h
|
||||
hand hardcore hardkick haw hc hh hh27 hit hmm ho hoover house ht if
|
||||
ifdrums incoming industrial insect invaders jazz jungbass jungle juno
|
||||
jvbass kicklinn koy kurt latibro led less lighter linnhats lt made
|
||||
made2 mash mash2 metal miniyeah monsterb moog mouth mp3 msg mt mute
|
||||
newnotes noise noise2 notes numbers oc off outdoor pad padlong pebbles
|
||||
perc peri pluck popkick print proc procshort psr rave rave2 ravemono
|
||||
realclaps reverbkick rm rs sax sd seawolf sequential sf sheffield
|
||||
short sid sine sitar sn space speakspell speech speechless speedupdown
|
||||
stab stomp subroc3d sugar sundance tabla tabla2 tablex tacscan tech
|
||||
techno tink tok toys trump ul ulgab uxay v voodoo wind wobble world
|
||||
xmas yeah`, true)}
|
||||
|
||||
|
||||
`
|
||||
};
|
||||
|
||||
|
||||
@ -12,30 +12,30 @@ Welcome to the **Topos** documentation. You can jump here anytime by pressing ${
|
||||
)}. Press again to make the documentation disappear. Contributions are much appreciated! The documentation [lives here](https://github.com/Bubobubobubobubo/topos/tree/main/src/documentation).
|
||||
|
||||
${makeExample(
|
||||
"Welcome! Eval to get started",
|
||||
examples[Math.floor(Math.random() * examples.length)],
|
||||
true,
|
||||
)}
|
||||
"Welcome! Eval to get started",
|
||||
examples[Math.floor(Math.random() * examples.length)],
|
||||
true,
|
||||
)}
|
||||
|
||||
# What is Topos?
|
||||
|
||||
Topos is an _algorithmic_ sequencer. Topos is also a _live coding_ environment. To sum it up, think: "_making music in real time through code_". Code used as an expressive medium for musical improvisation! Topos uses small algorithms to represent musical sequences and processes.
|
||||
|
||||
${makeExample(
|
||||
"Small algorithms for direct musical expression",
|
||||
`
|
||||
"Small algorithms for direct musical expression",
|
||||
`
|
||||
rhythm(.5, 4, 8) :: sound('drum').out()
|
||||
rhythm(.25, [5, 7].beat(2), 8) :: sound(['hc', 'fikea', 'hat'].pick(1))
|
||||
.lpf([500, 4000+usine(1/2)*2000]).pan(r(0, 1)).ad(0, [1, .5])
|
||||
.db(-ir(1,8)).speed([1,[0.5, 2].pick()]).room(0.5).size(3).o(4).out()
|
||||
beat([2,0.5].dur(13.5, 0.5))::snd('fsoftsnare')
|
||||
.n(0).speed([1, 0.5]).o(4).out()`,
|
||||
false,
|
||||
)}
|
||||
false,
|
||||
)}
|
||||
|
||||
${makeExample(
|
||||
"Computer music should be immediate and intuitive",
|
||||
`
|
||||
"Computer music should be immediate and intuitive",
|
||||
`
|
||||
let chord_prog = [0, 0, 5].bar() // Chord progression
|
||||
beat(.25)::snd('sine')
|
||||
.note(chord_prog + [60, 64, 67, 71].mouseX()
|
||||
@ -47,27 +47,25 @@ beat(.25)::snd('sine')
|
||||
.delay(0.5).delayt(0.25).delayfb(0.7) // Delay
|
||||
.room(0.5).size(8) // Reverb
|
||||
.out()`,
|
||||
false,
|
||||
)}
|
||||
false,
|
||||
)}
|
||||
|
||||
${makeExample(
|
||||
"Making the web less dreadful, one beep at at time",
|
||||
`
|
||||
"Making the web less dreadful, one beep at at time",
|
||||
`
|
||||
beat(.5) :: sound('sid').n($(2))
|
||||
.room(1).speed([1,2].pick()).out()
|
||||
beat(.25) :: sound('sid').note(
|
||||
[34, 36, 41].beat(.25) + [[0,-24].pick(),12].beat())
|
||||
.room(0.9).size(0.9).n(4).out()`,
|
||||
false,
|
||||
)}
|
||||
false,
|
||||
)}
|
||||
|
||||
Topos is deeply inspired by the [Monome Teletype](https://monome.org/). The Teletype is/was an open source hardware module for Eurorack synthesizers. While the Teletype was initially born as an hardware module, Topos aims to be a web-browser based cousin of it! It is a sequencer, a scriptable interface, a companion for algorithmic music-making. Topos wishes to fullfill the same goal as the Teletype, keeping the same spirit alive on the web. It is free, open-source, and made to be shared and used by everyone. Learn more about live coding on [livecoding.fr](https://livecoding.fr).
|
||||
|
||||
## Demo Songs
|
||||
## Alternative documentation source (.pdf)
|
||||
|
||||
Reloading the application will get you one random song example to study every time. Press ${key_shortcut(
|
||||
"F5",
|
||||
)} and listen to them all! The demo songs are also used a bit everywhere in the documentation to illustrate some of the working principles :).
|
||||
You can also find a .pdf version listing the principal commands and functions [here](https://github.com/Bubobubobubobubo/topos/blob/main/src/documentation/basics/TOPOS_COMMANDS.pdf). This document has been generated by Chris Collis. It recaps the main sections of this documentation and can be a good companion while learning Topos.
|
||||
|
||||
## Support
|
||||
|
||||
|
||||
@ -1,28 +0,0 @@
|
||||
import { type Editor } from "../../../main";
|
||||
import { makeExampleFactory } from "../../../Documentation";
|
||||
|
||||
export const pitch = (application: Editor): string => {
|
||||
// @ts-ignore
|
||||
const makeExample = makeExampleFactory(application);
|
||||
return `# Pitch
|
||||
|
||||
|
||||
## Pitch envelope
|
||||
|
||||
Similar to the amplitude envelope, you can use an envelope to shape the pitch
|
||||
of your sounds (can be samples or synthesizers). This is super useful to create
|
||||
new timbres out of existing sounds.
|
||||
|
||||
| Method | Alias | Description |
|
||||
|---------|-------|-----------------------------------------------|
|
||||
| <ic>pattack</ic> | patt | Attack time |
|
||||
| <ic>pdecay</ic> | pdec | Decay time |
|
||||
| <ic>psustain</ic> | psus | Sustain value |
|
||||
| <ic>prelease</ic> | prel | Release time |
|
||||
| <ic>penv</ic> | | Pitch envelope strength (positive or negative) |
|
||||
| <ic>panchor</ic> | | Envelope anchor range (0 - 1) |
|
||||
|
||||
Resume writing the pitch documentation here.
|
||||
|
||||
`;
|
||||
};
|
||||
@ -1,6 +1,6 @@
|
||||
import { type UserAPI } from "../API";
|
||||
import { safeScale, stepsToScale } from "zifferjs";
|
||||
export {};
|
||||
export { };
|
||||
|
||||
declare global {
|
||||
interface Array<T> {
|
||||
@ -60,14 +60,14 @@ export const makeArrayExtensions = (api: UserAPI) => {
|
||||
return this[zoneIndex];
|
||||
};
|
||||
|
||||
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.sometimes = function (func: Function): number[] {
|
||||
Array.prototype.sometimes = function(func: Function): number[] {
|
||||
if (api.randomGen() < 0.5) {
|
||||
return func(this);
|
||||
} else {
|
||||
@ -75,11 +75,11 @@ export const makeArrayExtensions = (api: UserAPI) => {
|
||||
}
|
||||
};
|
||||
|
||||
Array.prototype.apply = function (func: Function): number[] {
|
||||
Array.prototype.apply = function(func: Function): number[] {
|
||||
return func(this);
|
||||
};
|
||||
|
||||
Array.prototype.sqrt = function (): number[] {
|
||||
Array.prototype.sqrt = function(): number[] {
|
||||
/**
|
||||
* @returns New array with square roots of values. Throws if any element is negative.
|
||||
*/
|
||||
@ -88,7 +88,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.
|
||||
@ -96,7 +96,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.
|
||||
@ -104,7 +104,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.
|
||||
@ -112,7 +112,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.
|
||||
@ -121,7 +121,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.
|
||||
*
|
||||
@ -130,7 +130,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
|
||||
@ -147,7 +147,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
|
||||
);
|
||||
};
|
||||
|
||||
Array.prototype.bar = function (value: number = 1) {
|
||||
Array.prototype.bar = function(value: number = 1) {
|
||||
/**
|
||||
* Returns an element from an array based on the current bar.
|
||||
*
|
||||
@ -162,7 +162,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
|
||||
}
|
||||
};
|
||||
|
||||
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(
|
||||
@ -172,7 +172,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
|
||||
};
|
||||
Array.prototype.b = Array.prototype.beat;
|
||||
|
||||
Array.prototype.dur = function (...durations: number[]) {
|
||||
Array.prototype.dur = function(...durations: number[]) {
|
||||
const timepos = api.app.clock.pulses_since_origin;
|
||||
const ppqn = api.ppqn();
|
||||
const adjustedDurations: number[] = this.map(
|
||||
@ -195,7 +195,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
|
||||
throw new Error("Durations array does not match the pattern length.");
|
||||
};
|
||||
|
||||
Array.prototype.shuffle = function () {
|
||||
Array.prototype.shuffle = function() {
|
||||
/**
|
||||
* Shuffles the array in place.
|
||||
*
|
||||
@ -214,7 +214,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.
|
||||
*
|
||||
@ -234,7 +234,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
|
||||
return this;
|
||||
};
|
||||
|
||||
Array.prototype.unique = function () {
|
||||
Array.prototype.unique = function() {
|
||||
/**
|
||||
* Removes duplicate elements from the array in place.
|
||||
*
|
||||
@ -267,7 +267,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) {
|
||||
@ -380,7 +380,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.
|
||||
@ -391,7 +391,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.
|
||||
*
|
||||
@ -410,10 +410,10 @@ export const makeArrayExtensions = (api: UserAPI) => {
|
||||
*
|
||||
* @returns the shifted array
|
||||
*/
|
||||
const idx = api.counter(name,limit,step);
|
||||
if(limit) {
|
||||
const idx = api.counter(name, limit, step);
|
||||
if (limit) {
|
||||
return this[idx % this.length];
|
||||
} else if(idx < this.length) {
|
||||
} else if (idx < this.length) {
|
||||
return this[idx];
|
||||
} else {
|
||||
return this[this.length - 1];
|
||||
@ -425,7 +425,7 @@ export const makeArrayExtensions = (api: UserAPI) => {
|
||||
|
||||
|
||||
|
||||
Array.prototype.scale = function (
|
||||
Array.prototype.scale = function(
|
||||
scale: string = "major",
|
||||
base_note: number = 0,
|
||||
) {
|
||||
@ -442,14 +442,14 @@ Array.prototype.scale = function (
|
||||
return this.map((value) => {
|
||||
const octaveShift = Math.floor(value / selected_scale.length) * 12;
|
||||
return (
|
||||
selected_scale[mod(value, selected_scale.length)] +
|
||||
selected_scale[mod(Math.floor(value), selected_scale.length)] +
|
||||
base_note +
|
||||
octaveShift
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
Array.prototype.scaleArp = function (
|
||||
Array.prototype.scaleArp = function(
|
||||
scaleName: string = "major",
|
||||
boundary: number = 0,
|
||||
) {
|
||||
|
||||
10
src/main.ts
10
src/main.ts
@ -213,14 +213,8 @@ export class Editor {
|
||||
loadUniverserFromUrl(this);
|
||||
|
||||
// Set the color scheme for the application
|
||||
let available_themes = Object.keys(colors);
|
||||
if (this.settings.theme in available_themes) {
|
||||
this.readTheme(this.settings.theme);
|
||||
} else {
|
||||
this.settings.theme = "Everblush";
|
||||
this.readTheme(this.settings.theme);
|
||||
}
|
||||
|
||||
this.readTheme(this.settings.theme);
|
||||
|
||||
this.documentationStyle = createDocumentationStyle(this);
|
||||
this.bindings = Object.keys(this.documentationStyle).map((key) => ({
|
||||
type: "output",
|
||||
|
||||
57
yarn.lock
57
yarn.lock
@ -1461,31 +1461,6 @@
|
||||
"@strudel.cycles/core" "0.8.2"
|
||||
nanostores "^0.8.1"
|
||||
|
||||
"@strudel/core@0.11.0":
|
||||
version "0.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@strudel/core/-/core-0.11.0.tgz#65d18c513f04ab1020325be56044c34f255bc37b"
|
||||
integrity sha512-7tOqsm13fsTOd9iPR7NybNN+QbkIyOR7JXpjIMRuQybkH15/NGOTAxNAbghKoesMU8/dLkR7/xVg231Ype3HMQ==
|
||||
dependencies:
|
||||
fraction.js "^4.3.7"
|
||||
|
||||
"@strudel/soundfonts@^0.11.0":
|
||||
version "0.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@strudel/soundfonts/-/soundfonts-0.11.0.tgz#1bfcb6885fad5c07e9e81855fecb59cf55cfd865"
|
||||
integrity sha512-a60Jya1d78lxr6QkEhrbmStrY/H3OneCssuzepfxG7Az1INWuqeTgJ653GcLv9v6+kpdurwAf9SvfHzx9XgbHw==
|
||||
dependencies:
|
||||
"@strudel/core" "0.11.0"
|
||||
"@strudel/webaudio" "0.11.0"
|
||||
sfumato "^0.1.2"
|
||||
soundfont2 "^0.4.0"
|
||||
|
||||
"@strudel/webaudio@0.11.0":
|
||||
version "0.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@strudel/webaudio/-/webaudio-0.11.0.tgz#1c595718c0bd72caec8e34ac2792ddde969e7ecf"
|
||||
integrity sha512-Yqc/th969RREqmqtppXTDZKxIgKBsqEG1aJX9T8sTxvYcgGjCC3auH96TF9JtwfVE/VhTxwsxjZDiLcuXTJtCA==
|
||||
dependencies:
|
||||
"@strudel/core" "0.11.0"
|
||||
superdough "0.10.0"
|
||||
|
||||
"@surma/rollup-plugin-off-main-thread@^2.2.3":
|
||||
version "2.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz#ee34985952ca21558ab0d952f00298ad2190c053"
|
||||
@ -2282,11 +2257,6 @@ fraction.js@^4.2.0:
|
||||
resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950"
|
||||
integrity sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==
|
||||
|
||||
fraction.js@^4.3.7:
|
||||
version "4.3.7"
|
||||
resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7"
|
||||
integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==
|
||||
|
||||
front-matter@^4.0.0:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/front-matter/-/front-matter-4.0.2.tgz#b14e54dc745cfd7293484f3210d15ea4edd7f4d5"
|
||||
@ -2938,11 +2908,6 @@ nanostores@^0.8.1:
|
||||
resolved "https://registry.yarnpkg.com/nanostores/-/nanostores-0.8.1.tgz#963577028ac10eeb50bec376535f4762ab5af9be"
|
||||
integrity sha512-1ZCfQtII2XeFDrtqXL2cdQ/diGrLxzRB3YMyQjn8m7GSGQrJfGST2iuqMpWnS/ZlifhtjgR/SX0Jy6Uij6lRLA==
|
||||
|
||||
nanostores@^0.9.5:
|
||||
version "0.9.5"
|
||||
resolved "https://registry.yarnpkg.com/nanostores/-/nanostores-0.9.5.tgz#4fcfce9786c4bf16e045a899cda2e46e90780a5b"
|
||||
integrity sha512-Z+p+g8E7yzaWwOe5gEUB2Ox0rCEeXWYIZWmYvw/ajNYX8DlXdMvMDj8DWfM/subqPAcsf8l8Td4iAwO1DeIIRQ==
|
||||
|
||||
node-addon-api@^5.0.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.1.0.tgz#49da1ca055e109a23d537e9de43c09cca21eb762"
|
||||
@ -3339,13 +3304,6 @@ set-function-name@^2.0.0:
|
||||
functions-have-names "^1.2.3"
|
||||
has-property-descriptors "^1.0.0"
|
||||
|
||||
sfumato@^0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/sfumato/-/sfumato-0.1.2.tgz#d24cd491456dc3b3e4a3237a457b800b681b4387"
|
||||
integrity sha512-j2s5BLUS5VUNtaK1l+v+yal3XjjV7JXCQIwE5Xs4yiQ3HJ+2Fc/dd3IkkrVHn0AJO2epShSWVoP3GnE0TvPdMg==
|
||||
dependencies:
|
||||
soundfont2 "^0.4.0"
|
||||
|
||||
showdown-highlight@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/showdown-highlight/-/showdown-highlight-3.1.0.tgz#c9ec902c35100e1ac3433761cdb655810120f1e5"
|
||||
@ -3376,11 +3334,6 @@ slip@1.0.2:
|
||||
resolved "https://registry.yarnpkg.com/slip/-/slip-1.0.2.tgz#ba45a923034d6cf41b1a27aebe7128282c8d551f"
|
||||
integrity sha512-XrcHe3NAcyD3wO+O4I13RcS4/3AF+S9RvGNj9JhJeS02HyImwD2E3QWLrmn9hBfL+fB6yapagwxRkeyYzhk98g==
|
||||
|
||||
soundfont2@^0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/soundfont2/-/soundfont2-0.4.0.tgz#a1efd642f2ae247a5530cd530ae364a095126be5"
|
||||
integrity sha512-537WiurDBRbDLVhJMxXLE06D6yWxJCidfPClnibZ0f8dKMDpv+0fIfwCQ8pELE0JqKX05SOJosNJgKzQobaAEA==
|
||||
|
||||
source-map-js@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
|
||||
@ -3507,12 +3460,12 @@ sucrase@^3.32.0:
|
||||
pirates "^4.0.1"
|
||||
ts-interface-checker "^0.1.9"
|
||||
|
||||
superdough@0.10.0, superdough@^0.10.0:
|
||||
version "0.10.0"
|
||||
resolved "https://registry.yarnpkg.com/superdough/-/superdough-0.10.0.tgz#06b027b16f54473f0281fcb0adcc1177d07d6e96"
|
||||
integrity sha512-VMSUyKqTJumAd28I2rN5L8pTbzlp7Vsszri2BHlYipZ4vXO/B88cMjqtLqsCP4KaoARsput0kMXbpZ9JhjWbYQ==
|
||||
superdough@^0.9.12:
|
||||
version "0.9.12"
|
||||
resolved "https://registry.yarnpkg.com/superdough/-/superdough-0.9.12.tgz#455f8860bc13cffbe1d8f391919e8f1dba1ff0b5"
|
||||
integrity sha512-rsdCoYk5rLYster4tE5mSGjotf/TNP3gPpsuK4hxTZNxL92TkdEcbPFLnJfky5oMQJtpRY1XqAXUx3htLbHEZA==
|
||||
dependencies:
|
||||
nanostores "^0.9.5"
|
||||
nanostores "^0.8.1"
|
||||
|
||||
supports-color@^5.3.0:
|
||||
version "5.5.0"
|
||||
|
||||
Reference in New Issue
Block a user