move files around

This commit is contained in:
2023-11-18 00:54:10 +01:00
parent 9fecea05f8
commit f27b20bbb1
10 changed files with 21 additions and 19 deletions

View File

@ -0,0 +1,83 @@
import { type Editor } from "../../main";
import { makeExampleFactory, key_shortcut } from "../../Documentation";
export const code = (application: Editor): string => {
const makeExample = makeExampleFactory(application);
return `
# Code
Topos scripts are using the [JavaScript](https://en.wikipedia.org/wiki/JavaScript) syntax. This is the language used to write pretty much anything in a web browser. JavaScript is easy to learn, and even faster to learn if you are already familiar with other programming languages. Here are some good resources if you want to learn more about it:
- [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. Any web developer knows about it.
- [Learn JS in Y Minutes](https://learnxinyminutes.com/docs/javascript/): a good tour of the language. Can be useful as a refresher.
- [The Modern JavaScript Tutorial](https://javascript.info/): another well known source to learn the language.
**You do not need to have any prior knowledge of programming** to use Topos**.
# How is the code evaluated?
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:. There are some things to keep in mind:
- **about variables:** the state of your variables is not kept between iterations. If you write <ic>let a = 2</ic> and remove that value from your script, **it will crash**! Variable and state is not preserved between each run of the script. 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**. There is also **global variables**.
- **about errors and printing:** your code will crash! Don't worry, we do our best to make it crash in the most gracious way possible. Most errors are caught and displayed in the interface. For weirder bugs, open the dev console with ${key_shortcut(
"Ctrl + Shift + I"
)}. You cannot directly use <ic>console.log('hello, world')</ic> in the interface but you can use <ic>log(message)</ic> to print a one line message. You will have to open the console as well to see your messages being printed there!
- **about new syntax:** sometimes, we had some fun with JavaScript's syntax in order to make it easier/faster to write on stage. <ic>&&</ic> can also be written <ic>::</ic> or <ic>-></ic> because it is faster to type or better for the eyes!
# Common idioms
There are some techniques to keep code short and tidy. Don't try to write the shortest possible code! Use shortcuts when it makes sense. Take a look at the following examples:
${makeExample(
"Shortening your if conditions",
`
// The && symbol (overriden by :: in Topos) is very often used for conditions!
beat(.75) :: snd('linnhats').n([1,4,5].beat()).out()
beat(1) :: snd('bd').out()
//if (true) && log('very true')
// These two lines are the same:
// beat(1) && snd('bd').out()
//// beat(1) :: snd('bd').out()
`,
true
)}
${makeExample(
"More complex conditions using ?",
`
// The ? symbol can be used to write a if/true/false condition
beat(4) ? snd('kick').out() : beat(2) :: snd('snare').out()
// (true) ? log('very true') : log('very false')
`,
false
)}
${makeExample(
"Using not and other short symbols",
`
// The ! symbol can be used to reverse a condition
beat(4) ? snd('kick').out() : beat(2) :: snd('snare').out()
!beat(2) :: beat(0.5) :: snd('clap').out()
`,
false
)}
# About crashes and bugs
Things will crash! It's part of the show! You will learn progressively to avoid mistakes and to write safer code. Do not hesitate to kill the page or to stop the transport if you feel overwhelmed by an algorithm blowing up. There is no safeguard to stop you from doing most things. This is to ensure that you have all the available possible room to write bespoke code and experiment with your ideas through code.
${makeExample(
"This example will crash! Who cares?",
`
// This is crashing. See? No harm!
qjldfqsdklqsjdlkqjsdlqkjdlksjd
`,
true
)}
`;
};

View File

@ -0,0 +1,102 @@
import { key_shortcut, makeExampleFactory } from "../../Documentation";
import { type Editor } from "../../main";
import topos_arch from "./topos_arch.svg";
import many_universes from "./many_universes.svg";
export const software_interface = (application: Editor): string => {
const makeExample = makeExampleFactory(application);
return `
# Interface
The Topos interface is designed on a simple concept: _scripts_ and _universes_. By understanding how the interface works, you will already understand quite a lot. Make sure to learn the dedicated keybindings as well. They will give you extra powers!
<object type="image/svg+xml" data=${topos_arch} style="width: 100%; height: auto; background-color: transparent"></object>
# Scripts
Every Topos session is composed of **local**, **global** and **init** scripts. These scripts form a structure called a "_universe_". The scripts can describe whatever you want: songs, sketches, small tools, or whatever. All the scripts are written using the JavaScript programming language. They describe a musical or algorithmic process. You can call them anytime.
- **the global script** (${key_shortcut(
"Ctrl + G"
)}): _Evaluated for every clock pulse_. The central piece, acting as the conductor for all the other scripts. You can also jam directly from the global script to test your ideas before pushing them to a separate script. You can also access that script using the ${key_shortcut(
"F10"
)} key.
- **the local scripts** (${key_shortcut(
"Ctrl + L"
)}): _Evaluated on demand_. Local scripts are used to store anything too complex to sit in the global script. It can be a musical process, a whole section of your composition, a complex controller that you've built for your hardware, etc... You can also switch to one of the local scripts by using the function keys (${key_shortcut(
"F1"
)} to ${key_shortcut("F9")}).
- **the init script** (${key_shortcut(
"Ctrl + I"
)}): _Evaluated on program load_. Used to set up the software the session to the desired state before playing, for example changing bpm or to initialize global variables (See Functions). You can also access that script using the ${key_shortcut(
"F11"
)} key.
- **the note file** (${key_shortcut(
"Ctrl + N"
)}): _Not evaluated_. Used to store your thoughts or commentaries about the session you are currently playing. It is nothing more than a scratchpad really!
${makeExample(
"Calling scripts to form a musical piece",
`
beat(1) :: script(1) // Calling local script n°1
flip(4) :: beat(.5) :: script(2) // Calling script n°2
`,
true
)}
${makeExample(
"Script execution can become musical too!",
`
// Use algorithms to pick a script.
beat(1) :: script([1, 3, 5].pick())
flip(4) :: beat([.5, .25].beat(16)) :: script(
[5, 6, 7, 8].beat())
`,
false
)}
### Navigating the interface
The interface is centered around the manipulation of scripts. Take a look at the left bar:
- **pencil icon:** notes. Used to take project notes about your "_universe_".
- **down arrow**: init script. Runs once when the project is loaded.
- **text with note**: global script, it acts as the **conductor** for your piece.
- **folder icon**: local scripts (from 1 to 9).
### Managing scripts programatically
There are some useful functions to help you manage your scripts:
- <ic>copy_script(from: number, to: number)</ic>: copy the content of a script to another.
- <ic>delete_script(index: number)</ic>: clear the content of a script. Warning: this is irreversible!
# Universes
<object type="image/svg+xml" data=${many_universes} style="width: 100%; height: auto; background-color: transparent"></object>
A set of files is called a _universe_. You can switch between universes immediately immediately by pressing ${key_shortcut(
"Ctrl + B"
)}. You can also create a new universe by entering a name. Load a universe by typing its name. Once a universe is loaded, it is not possible to call any data/code from any other universe. Switching between universes does not stop the transport nor reset the clock. The context switches but time keeps flowing. This can be useful for transitioning between songs / parts.
There are some useful functions to help you manage your universes:
- <ic>copy_universe(from: string, to: string)</ic>: copy the content of a universe to another.
- <ic>delete_universe(name: string)</ic>: delete a universe. Warning: this is irreversible!
# Sharing your work
**Click the share button**. The URL of the website will change to something much longer. This URL will automatically be copied to your clipboard. Send this link to your friends to share the universe you are currently working on with them. You can use a service like [tinyurl](https://tinyurl.com/) to shorten your links.
- The imported universe will always get a randomly generated name such as: <ic>random_silly_llama</ic>.
- Topos will automatically fetch and switch to the universe that was sent to you.
`;
};

View File

@ -0,0 +1,76 @@
import { key_shortcut } from "../../Documentation";
import { type Editor } from "../../main";
import { makeExampleFactory } from "../../Documentation";
export const shortcuts = (app: Editor): string => {
let makeExample = makeExampleFactory(app);
return `
# Keybindings
Topos is made to be controlled entirely with a keyboard. It is recommanded to stop using the mouse as much as possible when you are _live coding_. Here is a list of the most important keybindings:
### Transport
| Shortcut | Key | Description |
|----------|-------|------------------------------------------------------------|
|**Start/Pause** transport|${key_shortcut(
"Ctrl + P"
)}|Start or pause audio playback|
|**Stop** the transport |${key_shortcut(
"Ctrl + S"
)}|Stop and rewind audio playback|
### Moving in the interface
| Shortcut | Key | Description |
|----------|-------|------------------------------------------------------------|
|Universe switch|${key_shortcut("Ctrl + B")}|Switch to a new universe|
|Global Script|${key_shortcut("Ctrl + G")} or ${key_shortcut(
"F10"
)}|Switch to global script |
|Local scripts|${key_shortcut("Ctrl + L")} or ${key_shortcut(
"F11"
)}|Switch to local scripts |
|Init script|${key_shortcut("Ctrl + L")}|Switch to init script|
|Note File|${key_shortcut("Ctrl + N")}|Switch to note file|
|Local Script|${key_shortcut("F1")} to ${key_shortcut(
"F9"
)}|Switch to a specific local script|
|Documentation|${key_shortcut("Ctrl + D")}|Open the documentation|
### Evaluating code
| Shortcut | Key | Description |
|----------|-------|------------------------------------------------------------|
|Evaluate|${key_shortcut("Ctrl + Enter")}| Evaluate the current script |
|Local Eval|${key_shortcut("Ctrl + F1")} to ${key_shortcut(
"Ctrl + F9"
)}|Local File Evaluation|
|Force Eval|${key_shortcut(
"Ctrl + Shift + Enter"
)}|Force evaluation of the current script|
### Special
| Shortcut | Key | Description |
|----------|-------|------------------------------------------------------------|
|Vim Mode|${key_shortcut("Ctrl + V")}| Switch between Vim and Normal Mode|
# Keyboard Fill
By pressing the ${key_shortcut(
"Alt"
)} key, you can trigger the <ic>Fill</ic> mode which can either be <ic>true</ic> or <ic>false</ic>. The fill will be set to <ic>true</ic> as long as the key is held. Try pressing ${key_shortcut(
"Alt"
)} when playing this example:
${makeExample(
"Claping twice as fast with fill",
`
beat(fill() ? 1/4 : 1/2)::sound('cp').out()
`,
true
)}
`;
};

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -0,0 +1,73 @@
import { type Editor } from "../../main";
import { makeExampleFactory } from "../../Documentation";
export const mouse = (app: Editor): string => {
let makeExample = makeExampleFactory(app);
return `
# Mouse
Using the mouse is a fun way to control your code. It's basically an X/Y controller that you don't have to pay for! There are clever actions you can do with the mouse from generating notes to activating scripts conditionally!
## Mouse position
You can get the current position of the mouse on the screen by using the following functions:
- <ic>mouseX()</ic>: the horizontal position of the mouse on the screen (as a floating point number).
- <ic>mouseY()</ic>: the vertical position of the mouse on the screen (as a floating point number).
${makeExample(
"Vibrato controlled by mouse",
`
beat(.25) :: sound('sine')
.note([0,4,5,10,11,15,16]
.palindrome()
.scale('pentatonic', 50).beat(.25)
+ [-12, 0, 12].beat(0.25))
.vib(mouseX()/700).vibmod(mouseY()/200)
.pan(r(0, 1))
.room(0.35).size(4).out()
`,
true
)}
<br>
Current mouse position can also be used to generate notes:
- <ic>noteX()</ic>: returns a MIDI note number (0-127) based on the horizontal position of the mouse on the screen.
- <ic>noteY()</ic>: returns a MIDI note number (0-127) based on the vertical position of the mouse on the screen.
${makeExample(
"Using the mouse to output a note!",
`
beat(.25) :: sound('sine')
.lpf(7000)
.delay(0.5).delayt(1/6).delayfb(0.2)
.note(noteX())
.room(0.35).size(4).out()`,
true
)}
## Mouse and Arrays
You can use the mouse to explore the valuesq contained in an Array:
- <ic>mouseX()</ic>: returns a value from a list by splitting the horizontal space of the screen in _n_ sections.
- <ic>mouseY()</ic>: returns a value from a list by splitting the vertical space of the screen in _n_ sections.
${makeExample(
"Taking values out of an Array with the mouse",
`
log([1,2,3,4].mouseX())
log([4,5,6,7].mouseY())
`,
true
)}
`;
};

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -0,0 +1,72 @@
import { makeExampleFactory, key_shortcut } from "../../Documentation";
import { type Editor } from "../../main";
import { examples } from "../../examples/excerpts";
export const introduction = (application: Editor): string => {
const makeExample = makeExampleFactory(application);
return `
# Welcome
Welcome to the **Topos** documentation. You can jump here anytime by pressing ${key_shortcut(
"Ctrl + D"
)}. 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
)}
# 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",
`
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
)}
${makeExample(
"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()
+ [-12,0,12].beat(0.25)) // Notes
.fmi([1, 1.5, 2, 4].beat()) // FM synthesis
.ad(0, r(0.1, .25)) // Envelope
.lpf(500 + usine(1/4)*1500) // Filter Envelope
.lpad(4, 0, .125)
.delay(0.5).delayt(0.25).delayfb(0.7) // Delay
.room(0.5).size(8) // Reverb
.out()`,
false
)}
${makeExample(
"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
)}
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
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 :).
`;
};