add warning if multiple tabs are used

This commit is contained in:
2023-10-05 00:19:59 +02:00
parent 890131b542
commit 8cbd38bd09
4 changed files with 86 additions and 68 deletions

View File

@ -57,7 +57,7 @@
} }
</style> </style>
<body class="z-0 bg-neutral-800 overflow-y-hidden"> <body id="all" class="z-0 bg-neutral-800 overflow-y-hidden">
<!-- The header is hidden on smaller devices --> <!-- The header is hidden on smaller devices -->
<header class="py-2 block text-white bg-neutral-900"> <header class="py-2 block text-white bg-neutral-900">

View File

@ -50,13 +50,12 @@ Let's pause for a moment and explain what is going on:
- Sounds are **composed** by adding qualifiers/parameters that will modify the sound or synthesizer being played (_e.g_ <ic>sound('...').blabla(...)..something(...).out()</ic>. Think of it as _audio chains_. - Sounds are **composed** by adding qualifiers/parameters that will modify the sound or synthesizer being played (_e.g_ <ic>sound('...').blabla(...)..something(...).out()</ic>. Think of it as _audio chains_.
${makeExample( ${makeExample(
'"Composing" a sound or making a sound chain', '"Composing" a complex sonic object by making a sound chain',
` `
beat(1) :: sound('pad') beat(1) :: sound('pad').n(1)
.begin(rand(0, 0.4)) .begin(rand(0, 0.4))
.freq([50,52].beat()) .freq([50,52].beat())
.size(0.9) .size(0.9).room(0.9)
.room(0.9)
.velocity(0.25) .velocity(0.25)
.pan(usine()).release(2).out()`, .pan(usine()).release(2).out()`,
true true
@ -110,10 +109,9 @@ ${makeExample(
"Let's make something more complex", "Let's make something more complex",
` `
beat(0.25) && sound('jvbass') beat(0.25) && sound('jvbass')
.sometimes(s=>s.speed([1,5,10].pick())) .sometimes(s=>s.speed([2, 0.5].pick()))
.room(0.5) .room(0.9).size(0.9).gain(1)
.gain(1) .cutoff(usine(1/2) * 5000)
.cutoff(usine(2) * 5000)
.out()`, .out()`,
true true
)} )}
@ -131,7 +129,7 @@ There is a special method to choose the _orbit_ that your sound is going to use:
| Method | Alias | Description | | Method | Alias | Description |
|----------|-------|------------------------------------------------------------| |----------|-------|------------------------------------------------------------|
| orbit | o | Orbit number | | <ic>orbit</ic> | o | Orbit number |
## Amplitude ## Amplitude
@ -140,9 +138,9 @@ Simple controls over the amplitude (volume) of a given sound.
| Method | Alias | Description | | Method | Alias | Description |
|----------|-------|------------------------------------------------------------------------------------| |----------|-------|------------------------------------------------------------------------------------|
| gain | | Volume of the synth/sample (exponential) | | <ic>gain</ic> | | Volume of the synth/sample (exponential) |
| velocity | vel | Velocity (amplitude) from <ic>0</ic> to <ic>1</ic>. Multipled with gain | | <ic>velocity</ic> | vel | Velocity (amplitude) from <ic>0</ic> to <ic>1</ic>. Multipled with gain |
| dbgain | db | Attenuation in dB from <ic>-inf</ic> to <ic>+10</ic> (acts as a sound mixer fader) | | <ic>dbgain</ic> | db | Attenuation in dB from <ic>-inf</ic> to <ic>+10</ic> (acts as a sound mixer fader) |
${makeExample( ${makeExample(
"Velocity manipulated by a counter", "Velocity manipulated by a counter",
@ -157,21 +155,24 @@ beat(.5)::snd('cp').vel($(1)%10 / 10).out()`,
| Method | Alias | Description | | Method | Alias | Description |
|---------|-------|-----------------------------------------------| |---------|-------|-----------------------------------------------|
| attack | atk | Attack value (time to maximum volume) | | <ic>attack</ic> | atk | Attack value (time to maximum volume) |
| decay | dec | Decay value (time to decay to sustain level) | | <ic>decay</ic> | dec | Decay value (time to decay to sustain level) |
| sustain | sus | Sustain value (gain when sound is held) | | <ic>sustain</ic> | sus | Sustain value (gain when sound is held) |
| release | rel | Release value (time for the sound to die off) | | <ic>release</ic> | rel | Release value (time for the sound to die off) |
Note that the **sustain** value is not a duration but an amplitude value (how loud). The other values are the time for each stage to take place. Here is a fairly complete example using the <ic>sawtooth</ic> basic waveform. Note that the **sustain** value is not a duration but an amplitude value (how loud). The other values are the time for each stage to take place. Here is a fairly complete example using the <ic>sawtooth</ic> basic waveform.
${makeExample( ${makeExample(
"Simple synthesizer", "Simple synthesizer",
` `
beat(4)::sound('sawtooth').note(50).decay(0.5).sustain(0.5).release(2).gain(0.25).out(); let smooth = (sound) => {
beat(2)::sound('sawtooth').note(50+7).decay(0.5).sustain(0.6).release(2).gain(0.25).out(); return sound.cutoff(r(100,500))
beat(1)::sound('sawtooth').note(50+12).decay(0.5).sustain(0.7).release(2).gain(0.25).out(); .lpadsr(usaw(1/8) * 8, 0.05, .125, 0, 0)
beat(.25)::sound('sawtooth').note([50,57,62].pick() + [12, 24, 0].beat(2)) .gain(r(0.25, 0.4)).adsr(0, r(.2,.4), r(0,0.5), 0)
.cutoff(5000).sustain(0.5).release(0.1).gain(0.25).out() .room(0.9).size(2).o(2).vib(r(2,8)).vibmod(0.125)
}
beat(.25)::smooth(sound('sawtooth').note([50,57,55,60].beat(1))).out();
beat(.25)::smooth(sound('sawtooth').note([50,57,55,60].add(12).beat(1.5))).out();
`, `,
true true
)}; )};
@ -182,17 +183,17 @@ There are some basic controls over the playback of each sample. This allows you
| Method | Alias | Description | | Method | Alias | Description |
|---------|-------|--------------------------------------------------------| |---------|-------|--------------------------------------------------------|
| n | | Select a sample in the current folder (from <ic>0</ic> to infinity) | | <ic>n</ic> | | Select a sample in the current folder (from <ic>0</ic> to infinity) |
| begin | | Beginning of the sample playback (between <ic>0</ic> and <ic>1</ic>) | | <ic>begin</ic> | | Beginning of the sample playback (between <ic>0</ic> and <ic>1</ic>) |
| end | | End of the sample (between <ic>0</ic> and <ic>1</ic>) | | <ic>end</ic> | | End of the sample (between <ic>0</ic> and <ic>1</ic>) |
| loopBegin | | Beginning of the loop section (between <ic>0</ic> and <ic>1</ic>) | | <ic>loopBegin</ic> | | Beginning of the loop section (between <ic>0</ic> and <ic>1</ic>) |
| loopEnd | | End of the loop section (between <ic>0</ic> and <ic>1</ic>) | | <ic>loopEnd</ic> | | End of the loop section (between <ic>0</ic> and <ic>1</ic>) |
| loop | | Whether to loop or not the audio sample | | <ic>loop</ic> | | Whether to loop or not the audio sample |
| stretch | | Stretches the audio playback rate of a sample over <ic>n</ic> beats | | <ic>stretch</ic> | | Stretches the audio playback rate of a sample over <ic>n</ic> beats |
| speed | | Playback speed (<ic>2</ic> = twice as fast) | | <ic>speed</ic> | | Playback speed (<ic>2</ic> = twice as fast) |
| cut | | Set with <ic>0</ic> or <ic>1</ic>. Will cut the sample as soon as another sample is played on the same bus | | <ic>cut</ic> | | Set with <ic>0</ic> or <ic>1</ic>. Will cut the sample as soon as another sample is played on the same bus |
| clip | | Multiply the duration of the sample with the given number | | <ic>clip</ic> | | Multiply the duration of the sample with the given number |
| pan | | Stereo position of the audio playback (<ic>0</ic> = left, <ic>1</ic> = right)| | <ic>pan</ic> | | Stereo position of the audio playback (<ic>0</ic> = left, <ic>1</ic> = right)|
${makeExample( ${makeExample(
"Complex sampling duties", "Complex sampling duties",
@ -224,13 +225,13 @@ There are three basic filters: a _lowpass_, _highpass_ and _bandpass_ filters wi
| Method | Alias | Description | | Method | Alias | Description |
|------------|-------|-----------------------------------------| |------------|-------|-----------------------------------------|
| cutoff | lpf | Cutoff frequency of the lowpass filter | | <ic>cutoff</ic> | lpf | Cutoff frequency of the lowpass filter |
| resonance | lpq | Resonance of the lowpass filter | | <ic>resonance</ic> | lpq | Resonance of the lowpass filter |
| hcutoff | hpf | Cutoff frequency of the highpass filter | | <ic>hcutoff</ic> | hpf | Cutoff frequency of the highpass filter |
| hresonance | hpq | Resonance of the highpass filter | | <ic>hresonance</ic> | hpq | Resonance of the highpass filter |
| bandf | bpf | Cutoff frequency of the bandpass filter | | <ic>bandf</ic> | bpf | Cutoff frequency of the bandpass filter |
| bandq | bpq | Resonance of the bandpass filter | | <ic>bandq</ic> | bpq | Resonance of the bandpass filter |
| vowel | | Formant filter with (vocal quality) | | <ic>vowel</ic> | | Formant filter with (vocal quality) |
${makeExample( ${makeExample(
"Filter sweep using a low frequency oscillator", "Filter sweep using a low frequency oscillator",
@ -249,8 +250,8 @@ A basic reverberator that you can use to give some depth to your sounds. This si
| Method | Alias | Description | | Method | Alias | Description |
|------------|-------|---------------------------------| |------------|-------|---------------------------------|
| room | | The more, the bigger the reverb (between <ic>0</ic> and <ic>1</ic>.| | <ic>room</ic> | | The more, the bigger the reverb (between <ic>0</ic> and <ic>1</ic>.|
| size | | Reverberation amount | | <ic>size</ic> | | Reverberation amount |
${makeExample( ${makeExample(
"Clapping in the cavern", "Clapping in the cavern",
@ -267,9 +268,9 @@ A good sounding delay unit that can go into feedback territory. Use it without m
| Method | Alias | Description | | Method | Alias | Description |
|------------|-----------|---------------------------------| |------------|-----------|---------------------------------|
| delay | | Delay _wet/dry_ (between <ic>0</ic> and <ic>1</ic>) | | <ic>delay</ic> | | Delay _wet/dry_ (between <ic>0</ic> and <ic>1</ic>) |
| delaytime | delayt | Delay time (in milliseconds) | | <ic>delaytime</ic> | delayt | Delay time (in milliseconds) |
| delayfeedback| delayfb | Delay feedback (between <ic>0</ic> and <ic>1</ic>) | | <ic>delayfeedback</ic> | delayfb | Delay feedback (between <ic>0</ic> and <ic>1</ic>) |
${makeExample( ${makeExample(
"Who doesn't like delay?", "Who doesn't like delay?",
@ -285,9 +286,9 @@ beat(1)::snd('kick').out()
| Method | Alias | Description | | Method | Alias | Description |
|------------|-----------|---------------------------------| |------------|-----------|---------------------------------|
| coarse | | Artificial sample-rate lowering | | <ic>coarse</ic> | | Artificial sample-rate lowering |
| crush | | bitcrushing. <ic>1</ic> is extreme, the more you go up, the less it takes effect. | | <ic>crush</ic> | | bitcrushing. <ic>1</ic> is extreme, the more you go up, the less it takes effect. |
| shape | | Waveshaping distortion (between <ic>0</ic> and <ic>1</ic>) | | <ic>shape</ic> | | Waveshaping distortion (between <ic>0</ic> and <ic>1</ic>) |
${makeExample( ${makeExample(

View File

@ -12,43 +12,44 @@ Welcome to the Topos documentation. These pages are offering you an introduction
)}. Press again to make the documentation disappear. All your contributions are welcome! )}. Press again to make the documentation disappear. All your contributions are welcome!
${makeExample( ${makeExample(
"Welcome! Eval to get started", "Welcome! Eval to get started",
examples[Math.floor(Math.random() * examples.length)], examples[Math.floor(Math.random() * examples.length)],
true true
)} )}
## What is Topos? ## What is Topos?
Topos is an _algorithmic_ sequencer. Topos uses small algorithms to represent musical sequences and processes. These can be written in just a few lines of code. Topos is made to be _live-coded_. The _live coder_ strives for the constant interaction with algorithms and sound during a musical performance. Topos is aiming to be a digital playground for live algorithmic music. Topos is an _algorithmic_ sequencer. Topos uses small algorithms to represent musical sequences and processes. These can be written in just a few lines of code. Topos is made to be _live-coded_. The _live coder_ strives for the constant interaction with algorithms and sound during a musical performance. Topos is aiming to be a digital playground for live algorithmic music.
${makeExample( ${makeExample(
"Small algorithms for direct musical expression", "Small algorithms for direct musical expression",
` `
beat(1) :: sound(['kick', 'hat', 'snare', 'hat'].beat(1)).out() beat(1) :: sound(['kick', 'hat', 'snare', 'hat'].beat(1)).out()
beat(.5) :: sound('jvbass').note(35 + [0,12].beat()).out() beat(.5) :: sound('jvbass').note(35 + [0,12].beat()).out()
beat([0.5, 0.25, 1, 2].beat(1)) :: sound('east') beat([0.5, 0.25].beat(1)) :: sound('east')
.room(.5).size(0.5).n(irand(1,5)).out()`, .room(.9).speed(flip(4) ? 1 : 0.95).size(0.9).o(2).n($(1)).out()`,
false false
)} )}
${makeExample( ${makeExample(
"Computer music should be immediate and intuitive", "Computer music should be immediate and intuitive",
`beat(.5)::snd('sine') `beat(.5)::snd('sine')
.delay(0.5).delayt(0.25).delayfb(0.7) .delay(0.5).delayt(0.25).delayfb(0.7)
.room(0.8).size(0.8) .room(0.8).size(0.8)
.freq(mouseX()).out()`, .freq(mouseX()).out()`,
false false
)} )}
${makeExample( ${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)).out() beat(.5) :: sound('sid').n($(2))
.room(1).speed([1,2].pick()).out()
beat(.25) :: sound('sid').note( beat(.25) :: sound('sid').note(
[34, 36, 41].beat(.25) + [[0,-24].pick(),12].beat()) [34, 36, 41].beat(.25) + [[0,-24].pick(),12].beat())
.room(0.9).size(0.9).n(4).out()`, .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 software sequencer from the same family! It is a sequencer, a scriptable interface, a companion for algorithmic music-making. Topos wishes to fullfill the same goal than the Teletype, keeping the same spirit alive on the web. It is free, open-source, and made to be shared and used by everyone. 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 software sequencer from the same family! It is a sequencer, a scriptable interface, a companion for algorithmic music-making. Topos wishes to fullfill the same goal than the Teletype, keeping the same spirit alive on the web. It is free, open-source, and made to be shared and used by everyone.

View File

@ -32,6 +32,21 @@ import showdown from "showdown";
showdown.setFlavor("github"); showdown.setFlavor("github");
import showdownHighlight from "showdown-highlight"; import showdownHighlight from "showdown-highlight";
import { makeStringExtensions } from "./StringExtensions"; import { makeStringExtensions } from "./StringExtensions";
// Broadcast that you're opening a page.
localStorage.openpages = Date.now();
window.addEventListener('storage', function(e) {
if (e.key == "openpages") {
// Listen if anybody else is opening the same page!
localStorage.page_available = Date.now();
}
if (e.key == "page_available") {
document.getElementById("all")!.classList.add("invisible")
alert("Topos is already opened in another tab. Close this tab now to prevent data loss.");
}
}, false);
const classMap = { const classMap = {
h1: "text-white lg:text-4xl text-xl lg:ml-4 lg:mx-4 mx-2 lg:my-4 my-2 lg:mb-4 mb-4 bg-neutral-900 rounded-lg py-2 px-2", h1: "text-white lg:text-4xl text-xl lg:ml-4 lg:mx-4 mx-2 lg:my-4 my-2 lg:mb-4 mb-4 bg-neutral-900 rounded-lg py-2 px-2",
h2: "text-white lg:text-3xl text-xl lg:ml-4 lg:mx-4 mx-2 lg:my-4 my-2 lg:mb-4 mb-4 bg-neutral-900 rounded-lg py-2 px-2", h2: "text-white lg:text-3xl text-xl lg:ml-4 lg:mx-4 mx-2 lg:my-4 my-2 lg:mb-4 mb-4 bg-neutral-900 rounded-lg py-2 px-2",
@ -1160,7 +1175,7 @@ export class Editor {
} }
} }
const app = new Editor(); let app = new Editor();
window.addEventListener("beforeunload", () => { window.addEventListener("beforeunload", () => {
// @ts-ignore // @ts-ignore
@ -1172,3 +1187,4 @@ window.addEventListener("beforeunload", () => {
app.clock.stop(); app.clock.stop();
return null; return null;
}); });