Objective
To use HTML, CSS, JavaScript, and PHP to make a 12-tone matrix with various display options.
Sources
matrix-maker.php (form using ‘post’ method)
mat-guts.php (main PHP code)
mat-style.css (css styles)
Link: mikelkuehn.com/codex/matrix-maker.php
Overview
In a nutshell, the 12-tone row is a technique invented by composer Arnold Schoenberg in the early 1920s. It is simply a thematic ordering of all 12 pitches (C, C#, D… A#, B) within the octave. In modern times we call these pitch-classes (pcs) since they are abstracted from actual musical examples. (It is sometimes useful for musicians to use numeric notation instead of note names e.g., 0=C, 1=C#/D-flat, … 10=A#/B-flat, 11=B). There are 12 possible “transpositions” of a 12-tone row (unique versions under musical transposition) and 12 “inversions” (i.e., the intervals between pitches are turned upside down then transposed 12 times). Since a 12-tone row is a fixed ordering of the 12 discrete pcs, we can also read the transpositions and inversions backwards (“retrograde” and “retrograde inversion”). Using group theory, all 48 of these orderings (12 + 12 + 12 + 12) can form a “magic square” (aka “row table” or “matrix”).
Here are some basic resources for understanding 12-tone music, etc.:
http://openmusictheory.com/twelveToneBasics.html
http://jan.ucc.nau.edu/~krr2/12tone/12tone1.html
An Example of a 12-tone matrix with note names and pitch classes:
In the early 1990s I made a Unix command-line C program that displayed a 12-tone matrix on the screen. The objective was not only to construct the matrix but to use Unix escape characters to display some of the pcs in color. (The highlighting of the pcs can be useful when composing with this tool.) I wanted to be able to highlight one or more pcs in order to easily see certain musical relationships across different rows or columns.
The Rewrite
In redesigning the program I was quite pleasantly surprised at how easy it was to convert the bulk of my C library over to PHP. It ultimately took me more time to wrap my head around the layout and CSS than it did to do the PHP programming. The input to the script is controlled by an HTML form that accommodates various options for the flavor of the resulting matrix, including three different notational formats (two types of single digit numbers as well as note-names). Here’s the landing page/form:
And the (resulting page) output to the above:
In addition to the options mentioned above, the matrix can have multiple highlighted pcs that are set in checkboxes:
The above results in the matrix below:
If the “suppress” option is enabled, all non-highlighted pcs are omitted (suppressed) from the display. (This helps to identify various patterns and musical relationships inherent between the base row and its various operations.)
Implementation
The meat of the matrix algorithm is this code (C style):
pc = (((row[i] * type % 12) + row[j] + offset) % 12;
This allows each pc of the matrix to be computed in one fell swoop. In the code above, the variable “offset” is used for creating a matrix that starts with the first row pc (row[0]), otherwise the matrix is normalized to start on 0. Since the pc world is essentially a mod 12 universe, different types of matrices can be implemented with different multipliers (represented by the variable “type” in the code above). Mod 12 assures that the results will be mapped into the range of 0-11. For example, to create the inverse of a pc we would normally subtract the value of the pc from 12 (12 – pc). However, by using mod 12 we can also obtain the inverse by multiplying each pc by 11, then taking the mod 12 result. For example: using the subtraction method: 12 – 2 = 10. Using the mod 12 method: 2 x 11 = 22 mod 12 = 10. The latter is more elegant because it allows for other kinds of operations via the route of multiplication. For example, the “M” (or circle of fourths operator) equates to “pc * 5 mod 12” (e.g., 11 * 5 = 55 mod 12 = 7). There are four types of matrices that I have allowed for: T (pc * 1), I (pc * 11), M (pc * 5), and MI (pc * 7). The “type” variable in the code above is simply one of the four multipliers listed above (1, 11, 5, or 7). In summary, this method allows us to do a variety of work with one line of code. Finally, in an effort to separate content from the display, I’ve calculated and stored the matrix in a two-dimensional array for retrieval at the display stage. This is slightly less efficient than calculating the matrix when making the display page, but it allows for encapsulation, reuse, and more options for future redesign. Here’s the main PHP function for calculating and storing the matrix:
Pitch-Class Highlighting
The most sophisticated feature of the implementation (and an improvement over the 1992 version) is the way the highlighted pcs are encoded. If we wanted to search for only one pc in the matrix, it would be easy to check each pc as it is displayed against one marked for highlighting. (Basically we would just need a logical “and” when checking the two pcs. If both are the same pc then we highlight it.) However, if we want to highlight more than one pc, things get complicated since we would need to check each pc in the matrix against multiple highlighted pcs. We can do this by encoding the highlighted pc(s) into a single number using a bit vector. (See Knuth’s “Bitwise Tricks and Techniques” from The Art of Computer Programming, vol 4 for in depth information.)
In a nutshell, we create a binary number (all bits off) and then flip-on the bits that represent the decimal numbers that we want to encode into the binary number. As an example, if we have pcs 1, 2, and 7 marked for highlighting we would turn those bits on in a 12-bit binary number:
0000 1000 0110 (bits 1, 2 and 7 on, read right to left)
21 (2) + 22 (4) + 27 (128) = 134
(N.B. in the binary number the bits are read from right to left and represent the successive powers of 2.)
To do the comparison we must also encode the matrix pc as a bit vector. For example:
0000 0000 0100 (pc 3 = bit 3 on)
23 = 6
Next, we can use low-level logical bit comparisons to check if the highlighted pc bit vector contains the pc. For example, using a bitwise “and” we can compare the bits in the decimal numbers 6 and 134 like so:
0000 0000 0100 (pc 3 = bit 3 = 6 decimal)
0000 1000 0110 (pcs 1,2,7 = bits 1,2,7 = 134 decimal)
============== AND
0000 0000 0100 (both bit 3s on) RESULT
( 1 occurs in the result if both bits were on in the two numbers.)
In the above example, the conditional statement “if (6 and 134)” evaluates to “true,” meaning that the pc we checked (3) is a subset of the highlighted pcs. In summary, we can check many numbers in one conditional statement using the code:
“if (pc & bitvector) then highlight” (pseudo-code)
Because of the way the form input works there isn’t much room for input errors. However, it is possible to create a non 12-tone row simply by duplicating/omitting one of the 12 pcs (and it may be musically desirable to this). However, it may also be a case of human error, so I would like to notify the user if less than 12 pcs have been inputted. Since having all 12 pcs once always adds to 66 (12+11+10+9+8+7+6+5+4+3+2+1), I can check the sum of the input pcs to determine if all 12 are present (a classic 12-tone row) or if some are missing (a “non 12-tone row”). The following PHP code checks the sum using the built-in “array_sum()” function and sets a boolean variable (“is12t”) to save the state of the row (12-tone or not):
$is12t = (array_sum($row) == 66? true : false);
Then, when printing, I’ve added a choice of two different headings on the output display page:
In conclusion, using a small code base, matrix-maker.php demonstrates my first attempt at a full stack script that incorporates HTML, CSS, JavaScript, and PHP in a musically useful application.
BTW, in case you were wondering: the 12-tone row used in this example comes from Alban Berg’s Violin Concerto (1935) —I highly recommend checking it out!