git clone https://depp.brause.cc/waka.git
You'll need to install the above dependencies first and make sure your
Kawa installation has been built with JLine3 support. If you're using
Arch Linux, you can build and install the
packages from my PKGBUILDs repository. Copy
waka to a location on
PATH and you're all set to go!
waka without any arguments to enter the REPL. It supports a
"free play" mode where pressing a key will play a note and a REPL mode
where you enter a sequence of notes and play them by pressing the
Enter key. Toggling is done by pressing
C-SPC in free play mode
C-c in REPL mode, to exit press
C-d. The grammar for
sequences is adapted from Alda and documented in a separate file.
waka and MIDI files can be played back in batch mode by passing
the file name as the only argument to
waka. To batch convert from
waka to MIDI, pass a
waka file and a MIDI file as arguments to
The settings can be customized by placing a file at
$XDG_CONFIG_HOME/waka/config or if its unset,
~/.config/waka/config. An example file containing all
customizables is available in the repository. Its key map places the
notes from C4 to E6 on the four QWERTY rows:
If you're experiencing issues such as static noise under Pulseaudio,
you can temporarily suspend it with
pasuspender -- env PULSE_SERVER=
This is an informal summary of the grammar. REPL mode accepts sequences whereas batch mode expects a superset of them known as a score.
A sequence consists of (usually, but not always space-separated) items, the simplest of which is a note. Other supported item types are chords (which themselves consist of notes), rests, octave changes, octave shifts and s-expressions. The following plays the chromatic scale:
c1 d e f g a b
To modify how a note is played, append characters to it. A number is interpreted as a duration measured in fractions of a whole note, with the default duration being one-fourth. Once set a duration is used for the subsequent notes until a new duration is specified this way:
c1 e g c2 e g c4 e g
Durations themselves can be lengthened by appending one or more dots. Each dot increases the length of the note by 50%.
Durations can be concatenated by using a tilde. An alternative way of
c2.. would be:
Accidentals change the pitch by a semitone.
+ increases and
decreases it. Much like with dots, an arbitrary amount can be chained
c+ d+ f+ g+ a+
Notes can be combined to a chord by concatenating them with a slash:
To change octaves in a chord, precede the note with as many
< shifts down,
> shifts up.
The octave shift syntax can be used on its own to globally change the octave:
a1 > c e c < a
The octave can be set with
o to an absolute value:
o0 c1 o2 c o4 c o6 c o8 c
Rests introduce a pause and use the same duration syntax as notes:
Bars are considered whitespace
c1 | c2 c | c4 c c c
The hash starts a line comment:
# ignore this
S-expressions can represent all kinds of things. The convention is to
treat them like Scheme parameters or in other words,
the current value of
(foo bar) sets the value of
bar. Currently recognized s-expressions:
(velocity 127) # global velocity: 0 - 127 (tempo 180) # global speed in bpm (bpm 180) # tempo alias (quant 0.9) # fraction of a note to be played: 0.0 - 1.0 (quantize 0.9) # quant alias (quantization 0.9) # quant alias (instrument trumpet) # current instrument, see instruments.scm
A score is a list of sequences, each preceded by a name suffixed by a colon. Every sequence is played on a separate channel. The name determines what instrument is used for the associated sequence.
piano: o4 c d e f g a b trumpet: o3 c d e f g a b
If you want to use the same instrument for more than one channel, you can append a nickname and another colon to the name.
piano:main: o4 c d e f g a b piano:backing: o3 c d e f g a b
Scores can be split up into interleaved parts for easier editing. Make sure the names match up, otherwise they cannot be combined successfully:
piano:main: o4 c d e f piano:backing: o3 c d e f piano:main: o4 g a b > c piano:backing: o3 g a b > c
While listening carefully to the notes is the easiest way to spot
mistakes, it may not be sufficient if you aren't sure about whether
the right notes have been generated. The bundled
leverages Lilypond to generate a file that can be typeset with
lilypond for visual debugging.