home   sections   references   cd:s   about   links   heptagon 
 no margins   view as black text on white background 


Polymath, a simple cgi toy to explore polyrhythms

Have you ever wondered what 17 over 15 sounds like?

Well, here is a tool to explore those sorts of questions very easily and quickly. It is a web-based cgi program that converts a string into a midi file and plays it immediately. The syntax of the string is very simple and pretty much streamlined to formulate and explore these exact type of questions about rhythm and specifically polyrhythms. Examples of strings are:

	4 4 4 4
		play four quarter notes
	(17, 16 * 17) | (15, 16 * 15)
		play 17 over 15

Basically you specify the timing values using a number. '4' means 'quarter note', '8' means eighth note, and so on. Parentheses indicate tuplets. (3, 8 8 8) are triplets, (5, 8 8 8 8 8) are quintuplets, and so on. Parentheses can be nested. And notes can be repeated with '*' .

Some more examples

	4 4 (3, 8 8 8 8 8 8)
		play two quarter notes and six 8th note triplets
	4 4 (5, 4, 8 8 8 8 8)
		play two quarter notes and five 8th note quintuplets
		(same length as previous example — 4 4 (3, 8 8 8 8 8 8) )
More examples, ideally with score graphics, would probably go here when this is done.

Basic syntax

Tracks are separated by the character '|'. Each track will be played simultaneously, using its own MIDI note. Each track specifies a rhythm pattern, using a list of items.

Items are separated by space (whitespace). Items can be:

A parenthesized list has either two, or three parts, separated by commas. Examples would be
	(3, 8 8 8)
		insert three 8th-note triplets
	(3, 2, 8 8 8)
		means the same thing: insert three 8th-note triplets.
		(read: three are now in the space of two, and insert three eighth notes)
	(5, 8 8 8)
		insert three 8th-note quintuplets
	(5, 4, 8 8 8)
		same: insert three 8th-note quintuplets. quintuplets are
		assumed to be "five over four" (more about this later)

Here's a more detailed explanation of parenthesized list. The last part is always one or more items, like:

	8 8P 16 32 2

Note that because a parenthesized list is itself an item, this means you can include further parenthesized lists. I.e., you can nest parentheses, the same way you can "nest" tuplets in music notation, that is, you can have a tuplet inside another tuplet:

	(11, 8, (3, 4, 8 8 8) 8P 16 32 (3, 8 8 8))

The first part (after the left parenthesis and before the first comma) is a number. The second (optional) part, is also a number. If you omit the second number it will be guessed. In the case of triplets, for instance, "three over two" is usually implied.

Let's discuss a list with three parts first. If we say that the three part list is constructed this way:

	(X, Y, items) 

which simply means,

		insert the items but fit X notes in the space of Y notes. 

An example:

	(11, 8, 32 32 32)
		insert three 32nd notes, but timed so that 11 of them
		would fit in the space of 8 notes.

If there are only two parts to the parenthesized list, like in (3, 8 8 8) this means that the second number (Y) is implied. It is taken (guessed) to be the closest power of two, with preference to a lower number. So (3, 8) = (3, 2, 8) ; (5, 8) = (5, 4, 8) ; (7, 8) = (7, 8, 8) . Note that this is certainly not always what you want, ie, (11, 8) = (11, 8, 8) when you perhaps meant (11, 12, 8) or (11, 16, 8) .

Anyway, the example would be input as:

	4 8 8 (5, 4, 16 16 16 16 16) (7, 4, 32 32P (3, 32 32
	32) (7, 8, 32 32 32 32 32 16) 16)

Other stuff

You can repeat things by using the character '*', and a number. So,
	8 * 10
		is equal to 8 8 8 8 8 8 8 8 8 8
and
	(11, 16, (3, 16) 4 * 7) * 5 | 8 * 104 33
		does what you expect it to. 
Note that '*' is not commutative here, like in the rest of the math universe! 7 * 8 is not the same thing as 8 * 7!

"Chained multiplication" is also possible now, without parentheses, in case you want to specify repetitions as a number of factors for some reason. It was possible before too, but you had to use parentheses, like this: '(((((4*2)*3)*7)*5)*8)' ; and 4*2*3*7*5*8 is of course a bit more easy on the fingers and brain. The only caveat is that there can be NO WHITESPACE in the chain. So '4 *2*3*7*5*8' is valid, '4 *2 * 3*7 * 5*8' is not. I know, pretty retarded. (The program should all be redone with a proper tokenizing recursive-descent parser algorithm, but I'm too lazy..)

You can insert comments following the character '#'. The comment lasts until the end of the line.

Tracks are played simultaneously. A new track is indicated by '|'.

	(11, 16, 16 * 11) | (17, 16, 16 * 17)
The MIDI notes for each track are determined by typing them into the "MIDI notes" box of the CGI submit form, or an "(N, ... )" command (see below). Apart from numbers, the program understands a limited number of MIDI drum note names, too, namely:
	BD SD 
	HH OH CH (=hihat, open hat, closed hat)
	T1 T2 T3 
	CR CS CB (=crash, china, cowbell)
Numbers are not restricted to powers of two, or even natural numbers.
	16 16 16 12 12 12 3.1415926 10.257 * 4

Note that the "Windows media player" does not loop MIDI files correctly even if set to "repeat forever". There is a timing glitch as the sequence stops and starts again. Don't complain to me, complain to Microsoft.

More experimental features

Here are some features that are not strictly "tuplet related", more of integer-math-related, but that could come in handy nonetheless:

Patterns

It can be painstaking to find the answer to questions like: "if I play 6 groups of 5 sixteenths plus 2 sixteenths, over two bars of normal 4/4, what would that sound like? Would all those sixteenths add up to two bars?" If you're into Meshuggah or a lot of Indian music you'll know exactly what I'm hinting at here.
	(P, tuplet-value, pattern-string)
Polymath to the rescue. The "tuplet-value" is simply what the basic pulse of the pattern will be. The "pattern-string" determines the grouping. You can specify the grouping either with a row of numbers, or a string of the letters 'x' or 'o'. ('x' and '-' work as well) So the question above could be formulated either:
	(P, 16,   5 5 5  5 5 5  2  ) | 4 4 4 4 4 4 4 4 |
	16 * 32
which is the same as:
	(P, 16, 5 * 6 2)|4 * 8|16 * 32
or another way: Ie, 'x' corresponds to a note, and 'o' corresponds to a pause. So '(P, 16, xooxxoox)' is equivalent to '16 16P 16P 16 16 16P 16P 16'. The idea here should be familiar to anyone programming one of those old Roland drum machines like the TR-303. X means note, O means no note.

A number N corresponds to a note, followed by (N-1) pauses. That is, 3 corresponds to xoo, 4 to xooo, 10 to xoooo ooooo. '(P, 16, 1 2 3 4 5 6)' is equivalent to '16   16 16P   16 16P 16P   16 16P 16P 16P   16 16P 16P 16P 16P   16 16P 16P 16P 16P 16P'.

Anyway, the pattern mechanism could be useful — let's say you are asking yourself what goes on in the first subchorus of Meshuggah's "Future Breed Machine" (where it goes "here I am in the hand of.."). You could then deparse the structure and proceed to experiment with something like:

	(t,180)(n,t1 sd cr bd)(p,16,(3 3 5*4 6)*3 5*5 3 4)|
	(P,8,oxoxoxox)*8|0.5P 0.5*3|(p,16, xoooxooo*12 xxxxx*5
	xxxoooo)
(Accents are (P, 16, (3 3 5 * 4 6) * 3 5 * 5 3 4), that is: each of the three first bars have 2 groups of 3, plus 4 groups of 5, plus 6, sixteenths; and the last bar has five groups of five plus three plus 4, sixteenths. (making an even 128 sixteenths or four bars of 8/4))

And if you for some reason immediately wanted to hear quarter note septuplets over this pattern, no problem:

	(t,180)(n,t1 sd cr bd ch)(p,16,(3 3 5*4 6)*3 5*5 3 4)|
	(P,8,oxoxoxox)*8|0.5P 0.5*3|(p,16, xoooxooo*12 xxxxx*5 xxxoooo)|
	(7,4, 4 * 56)
In a lower tempo..

Note! Inside one of these (P ) pattern specifiers, all tuplets are forbidden (obviously.) (P, 16, 5 3 5 3 (4, 5, 8)) doesn't make any sense as the numbers here are counting arguments, and thus have to be natural numbers. If you need tuplets and patterns at the same time, take advantage of the fact that a (P, ) expression simply expands into a 'list of items' (see above) before anything else takes place.

	(127,(p,32,(3 3 5*4 6)*3 5*5 3 4)) | (129,(p,32,(3
	3 5*4 6)*3 5*5 34))

Macros

	(D, macroname, string)
Defines a "macro". (Or you could call it a "subroutine" if you like that concept better.) The macro is invoked by using the macro name with a dollar sign ($) directly in front of it (no space between). $macroname will be replaced by string. That is, if you define the macro 'foobar' thusly:
	(D, foobar, 16 16 (11, 16, 16 * 7 15) )
every instance of '$foobar' will be replaced by '16 16 (11, 16, 16 * 7 15)'. So, if you write
	(D, foobar, 16 16 (11, 16, 16 * 7 15) ) 16 15 14 $foobar 13 14 $foobar
it will be equivalent to
	16 15 14 16 16 (11, 16, 16 * 7 15) 13 14 16 16 (11, 16, 16 * 7 15)
You can nest macros, ie, macros can refer to other macros. If you define macros that refer to themselves you will get what you deserve, even if done indirectly:
	(D, foo, $bar) (D, bar, $foo) $foo bad idea!

Tempo

	(T, tempo)
Specifies the tempo of the generated MIDI file. (Overrides any tempo setting passed via the web page interface.) Only one tempo per file — no tempo changes in the middle. And the tempo is the same for all tracks.

MIDI notes

	(N, notes)
Specifies which MIDI notes should be mapped to each track. Overrides CGI parameter given via the web page interface.

Really experimental features

These syntax possibilities stem from discussions on the Meshuggah forum before it broke again. Basically they are extensions to enable "pattern based programming", that is, "restarting" polymath's logic while appending pattern after pattern to the output. Essentially this is achieved by inserting a % character at the point between the patterns. A double % character (%%) also resets the song position so that anything after will be "overdubbed" onto the current output.

If none of this is making any sense, I have uploaded some of those discussions here.

Disclaimer

The parsing portions of the program do probably not have the most robust or clever solutions. (If some particular string crashes the program, try to rewrite it in a less complicated way.) However, I did take some care to ensure that the code that relates to the timing makes it as accurate as possible. That means, as long as it manages to parse the string completely and generate any output, it will likely be the correct output.

Bugs

I'm sure there's plenty.

Inspiration

Well, I thought of the method to make a toy like this many years ago (1986). But I was spurred into action by checking out Steve Vai's tempo mental page, an excellent reference on standard notation of polyrhythms. (By the way, that page apparently also has its roots in the 80s!)


Page updated Dec 2, 2003 at 20:21 • Email: jens@panix.com

All content copyright © Jens Johansson 2024. No unathorized duplication, copying, mirroring, buggery, archival, or redistribution/retransmission allowed! Any offensively categorical statements passed off as facts herein should only be construed as my very opinionated opinions.