Docs

Since Linum is a new project, the work on this documentation is in progress. Any and all fixes/contributions will be greatly appreciated.

Table of contents

For users

Representation of notes

In the standard configuration, the notes C-B correspond to the numbers 1-12, while 0 denotes a rest. For example, the C major scale (C D E F G A B) is directly mapped to the numbers 1, 3, 5, 6, 8, 10, and 12. This can be written as follows:

| 1 3 5 6 8 10 12

Notice the bar character (|) at the start. In Linum, all sections of music must begin with a bar – empty lines are ignored. The file structure used is therefore completely up to you. Linum doesn’t even take time signatures into account. One bar might take four beats while another takes five, although it is recommended to keep the timing of bars consistent. Single-line comments can be made using the hashtag character (#).

Linum also supports the creation of chords by putting notes into parentheses, for example the C major chord:

| (1 5 8)

Note length

By default, all notes in Linum are quarter notes. By placing any number of notes or chords into brackets, their length is divided by two. For example, here’s the C major scale in eighth notes:

| [1 3 5 6 8 10 12]

Brackets can be repeated to create even shorter notes. In the next example, there are three eighth notes followed by four sixteenth notes:

| [1 3 5 [6 8 10 12]]

Making notes longer can only be done individually – the length operators = and * serve this purpose:

Both of them can be put after a note, but = must always precede *. In the example below, the first bar contains a half note, the second bar a dotted half note, the third bar a whole note, and the fourth bar a dotted whole note:

| 1=
| 1=*
| 1==
| 1==*

All of the above, of course, also applies to chords. If = is used inside brackets, they are ignored. In the example below there are two chords with the length of a half note:

| [(1 5 8)= 3 5 6 8 10] (5 8 12)=

Notes and chords can be enclosed in braces to create tuplets. Tuplets always last the duration of a quarter note, and their length can be adjusted using the same notation applied to regular notes. Here’s a basic triplet example:

| {1 1 1}

Tuplets can also be nested:

| {[1 {1 1 1}] 1 [{1 1 1 1 1 1 1}]} 1

Octaves

There are four operators that allow changing the octave in a bar:

In short, < and > have a “memory”, while + and - only change the note or chord that follows them. This provides a wide range of possible configurations that increase the readability of the code. For example the C major scale across two octaves starting from C4 can be written like this:

| 1 3 5 6 8 10 12 +1 +3 +5 +6 +8 +10 +12

But also like this:

| 1 3 5 6 8 10 12 > 1 3 5 6 8 10 12

On every new bar, all octave shifts are reset. This means that the C in the second bar of the following code is C4:

| >>> 1
| 1

The < and > operators have specific placement rules. They can’t be placed inside chords or as the first item in brackets, and they must precede + and -. For example, the code below is invalid in two places:

| [ < 1 3 5 6 8 10] +(5 8 > 1)

In contrast, this theoretically equivalent code is correct:

| < [1 3 5 6 8 10] +(5 8 +1)

Command-line tool

Linum has a command line tool with the following arguments:

In general, the only options that usually need to be changed are the input, sound, and tempo options. The program can be installed by downloading a recent release or compiled on UNIX-like systems using the following commands:

git clone https://codeberg.org/oxetene/linum
make -C linum

The easiest way to compile Linum on Windows is through the MSYS2 project by installing the mingw-w64-gcc and mingw-w64-dlfcn packages.

Examples can be generated with a command similar to the one below:

linum -i examples/turret_wife_serenade.n -t 100

To convert WAV files to other formats, use the following FFmpeg command:

ffmpeg -i out.wav out.mp3

For developers

Syntax highlighting

The only syntax highlighting currently supported is for the micro text editor:

filetype: linum

detect:
    filename: "\\.n$"

rules:
    - type: "\\||\\(|\\)|\\{|\\}|\\[|\\]"
    - symbol: "<|>|\\+|-|=|\\*"
    - comment: "#.*$"

Language grammar and parsing

All the rules explained in the user section are defined by the following formal grammar:

<start>  ::= "|" <line>;

<repeat> ::= <group> <line>;
<group>  ::= "{" <repeat> "}" <tail> | "[" <repeat> "]" | <chord>;
<line>   ::= <perm> <repeat> | "";

<chord>  ::= <temp> <format> <tail>;
<format> ::= "(" <notes> ")" | "N";
<notes>  ::= <num> <notes> | <num>;
<num>    ::= <temp> "N";

<tail>   ::= <mul> <dot>;
<perm>   ::= "P" | "";
<temp>   ::= "T" | "";
<mul>    ::= "=" | "";
<dot>    ::= "*" | "";

Where N is a number, P is a permanent octave shift (< or >), and T is a temporary octave shift (+ or -). During development, the website BNFGen was found to be incredibly useful, and the BNF grammar above is compatible with it. Many thanks to Daniil Baturin for creating this tool.

Generating custom sounds

As mentioned earlier, Linum supports modding through the -m flag. All default values can be changed, and custom instruments can be created with functions that return the sample for a given note, length and time. Mods can be written in C and compiled as shared objects.

The default mod is located in the mod.c file. Exercise caution when writing custom mods – no safety checks are performed, and an incorrect mod can easily cause the program to segfault.

Planned features