A light-weight alternative to Alda
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
examples
.gitignore
LICENSE
Makefile
README.rst
config
grammar.ebnf
instruments.scm
mididump
test.scm
waka
waka2ly

README.rst

waka

About

waka is a MIDI REPL for composing music interactively. It's built upon Kawa, JLine3 and the javax.sound.midi package from Java SE.

Setup

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 kawa-git and java-jline3 packages from my PKGBUILDs repository. Copy waka to a location on your PATH and you're all set to go!

Usage

Run 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 and C-c in REPL mode, to exit press C-d. The grammar for sequences is adapted from Alda and documented in a separate file.

Both 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 waka.

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:

|     | c5# | d5# |     | f5# | g5# | a5# |     | c6# | d6# |
|  1  |  2  |  3  |  4  |  5  |  6  |  7  |  8  |  9  |  0  |
   | c5  | d5  | e5  | f5  | g5  | a5  | b5  | c6  | d6  | e6  |
   |  q  |  w  |  e  |  r  |  t  |  y  |  u  |  i  |  o  |  p  |
     |     | c4# | d4# |     | f4# | g4# | a4# |     |     |
     |  a  |  s  |  d  |  f  |  g  |  h  |  j  |  k  |  l  |
        | c4  | d4  | e4  | f4  | g4  | a4  | b4  |
        |  z  |  x  |  c  |  v  |  b  |  n  |  m  |

If you're experiencing issues such as static noise under Pulseaudio, you can temporarily suspend it with pasuspender -- env PULSE_SERVER= waka.

Language

This is an informal summary of the grammar. REPL mode accepts sequences whereas batch mode expects a superset of them known as a score.

Sequence

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%.

c2. c4

Durations can be concatenated by using a tilde. An alternative way of specifying c2.. would be:

c2~4~8

Accidentals change the pitch by a semitone. + increases and - decreases it. Much like with dots, an arbitrary amount can be chained together.

c+ d+ f+ g+ a+

Notes can be combined to a chord by concatenating them with a slash:

c1/e/g c/e-/g

To change octaves in a chord, precede the note with as many < or > needed. < shifts down, > shifts up.

a1/>c/e e/c/<a

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:

r1~2~4 r4

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, (foo) returns the current value of foo whereas (foo bar) sets the value of foo to 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

Score

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

Debugging

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 waka2ly script leverages Lilypond to generate a file that can be typeset with lilypond for visual debugging.