Blog 2: Set Info (October 2018)

Objective

To use HTML, CSS, JavaScript, and PHP to make a script that will list basic  information (via music set theory) about a collection of pitches.

Sources

set-info.php (form using ‘post’ method and PHP code)
set-help.php (HTML help page)
set-table.php (array of set-classes for table lookup)
si-style.css (css styles)
Link: mikelkuehn.com/codex/set-info.php

Overview

Here’s a fascinating musical question: how many combinations of pitches are possible within one octave? Using some math, there are 212 subsets of 12 elements, yielding 4096 subsets of the octave. Since one of those is the empty (null) set, there are 4095 distinct ways to depress combinations of notes within one octave (from all single pitches, through various chords, to all 12 notes at once).  We can think of these combinations as “chords” (though it wouldn’t be proper to use that musical term for the 12 that are just single notes).  Those 4095 “chords” aren’t all unique in terms of their harmonic/structural content, many possess identical intervalic content.  Using a “major triad” as an example, we could have several versions (C, E, G / F, A, C / E, G#, B / etc).  As music evolved and tuning systems for Western music moved into the standard of equal temperament (12 equally spaced notes within the octave), composers began to think about ways to identify chords with a single “normalized” label.  Musicians often give examples in the key of C to simplify a concept in order to compare it with other musical structures.  We might talk about a C major triad but, in theory, know that it implies we could have 11 other major triads built on various roots (C#, D, D#, … A#, B). The American composer Elliot Carter was one of the first to make a list of all possible chords and give them each a name (though his list isn’t commonly known or used).  While we already have labels for classes of common chords that occur in the periods of Bach, Beethoven, and Brahms (i.e., major, dominant 7th, diminished, etc.), there are other chords that don’t have standardized names—for example: C, C♯, E.

Forte: The Structure of Atonal Music (1973)

In his 1973 book, The Structure of Atonal Music, music theorist Allen Forte created a normalized list of all the classes of possible chords, which he called set classes. (“Set class” because each set of pitches can be assigned a single representation from many related possibilities — for example, think of using a C major triad as the representation for all major triads.)  The term “prime form”  describes the unique representation (in pitch-classes) of all intervalic-related chords of a specific cardinality (i.e., size).  Forte’s book contains the first published list of set class labels and prime forms. For example the notation “3-8[026]” states that the set-class consists of 3 elements and has the label “8” since it occurs, somewhat arbitrarily, as the 8th element in Forte’s table.  “[026]” is the prime form representation of pitch-classes.  As mentioned above, the 4095 possible chords aren’t all unique; when boiled-down to their prime form examples there are 223 unique set-classes (chords of cardinality 1=1, 2=6, 3=12, 4=29, 5=38, 6=50, 7=38, 8-29, 9=12, 10=6, 11=1, 12=1).

More information on pitch-class sets and prime form can be found here.

A Program to Compute Prime Form

In 1989, I took a course in music set theory taught by composer and music theorist Robert Morris at the Eastman School of Music. During that course I wrote a program in Basic that would compute the prime form of any group of pitches via table lookup and a complicated algorithm.  While it worked, the problem was that the algorithm involved a method invented for humans which translated into lots of operations that permuted arrays of integers.  Looking-up large sets of pitches created a noticeable delay on my 1989 16Mhz 286 IBM clone (from a fraction of a second for small sets to around 5 seconds for large sets of 9+ elements).  In 1990, during a year-long course in Pascal (at Eastman with Aleck Brinkman), I was able to rewrite the code with an existing computer algorithm based on bit vectors.  In short, a bit vector is a technique of representing groups of smaller numbers encoded into the bits of a larger number.  For example, using 12-bit numbers (0-4095) we can encode any unique combination of pitch-classes as bits.  Say we have the pitch-classes 1, 2, and 5: we can represent them using a binary number (i.e., bit vector by flipping on representative  bits like this:

0000 0010 0110

Reading this number as a binary number, and adding the on-bits from right to left, we get the decimal number 38 —  that is, we add the successive powers of two that are “turned-on”: (21 = 2) + (22=4) + (25=32) = 38.

It is much more efficient to represent a pitch-class set using a bit vector than an array.  In addition, transposition can be accomplished by using the bitwise operators shift left (<<) and shift right (>>).  “Shift left” transposes up one semitone, “shift right” down one semitone.

The bit vector prime form algorithm is:1.

  1. get a pcset of non-duplicating pcs, call it W
  2. encode W as a bit vector, call it X
  3. encode the inversion (12-pcs) of W as a bit vector, call it Y
  4. Shift X left (12-bit circular2) 12 times (all transpositions), save the version with the lowest decimal value.
  5. Shift Y left (12-bit circular) 12 times (all inversions via transpositions), save the version with the lowest decimal value.
  6. compare the decimal value of X and Y: If X < Y then X = the prime form, else Y = the prime form
  7. Use the prime form as the index (hash key) to find the SC number in the data structure (i.e., table lookup).

The 1992 C implementation of the program does more than just calculate the prime form — it provides other useful musical information such as the complement (missing pcs in the octave), the operational mapping from the original pcs to the prime form, and various other technical information (M/MI and Z relation, interval vector, invariance vector, etc.), which is beyond the scope of this post.  In short, the program is quite calculation intensive making the use of bit vectors much more efficient than array-based methods.

Set Info (1992), first screen
Set Info (1992), results

The PHP rewrite

In designing the PHP rewrite in 2018, I made a few changes.  First, I decided to only include the pertinent information about the set-class as found at the top of the second screen.

The main reason for this decision was to accommodate various screen sizes (desktop/mobile) and to get the information to display quickly since the table at the bottom of the original screen is calculation intensive. The unused information from the original version would be better suited to a separate program.

Set Info: landing page

In this version I have made a few changes to the original 1992 C version:

  • The initial help screen has now been moved to a linked “instruction” page.
  • The output can now exist in several formats including note names (e.g., “C#” instead of “1”).
  • The information is listed in a nicely formatted HTML table and the prime form is displayed in color so that it can be seen quickly.
Set Info: resulting data

Set Info: help page

Implementation

The main decisions in the PHP version were how best implement the table lookup (in order to find the Forte label/number of each set-class) and how to retrieve the input in a simple manner.

Table lookup

In the original C version, the table lookup is coded as a 223-element array where each index holds the following struct data type.

struct sets {
    int set;  /* decimal hash key value */
    int card; /* cardinality of set-class */
    int num;  /* Forte number */
    int mmi;  /* M/MI relation */
    int z;    /* Z relation */
};

Since PHP does not have a “struct” type I could have implemented the lookup-table as a simple class (object) or a two-dimensional array.  Because this project is fairly simple, I decided upon the array model since it cut down on the complexity of the code.  In the new version, each subscript of the 223-element array holds a 5-element subarray reflecting the data in the fields of the “set” struct above. (Another way that this could have been coded was by building-in some specific key values to the PHP array, which would have been a bit nasty to enter.)  An example of the PHP data structure (2-dimensional array):

/* subarray position: hash index, card, Forte #, M/MI, Z */
$sets = array(
array(1,1,1,1,0),
array(3,2,1,5,0),
array(5,2,2,2,0),
array(7,3,1,9,0),
array(9,2,3,3,0),
array(11,3,2,7,0),
array(15,4,1,23,0),
array(17,2,4,4,0),
array(19,3,3,11,0),
array(21,3,6,6,38),
array(23,4,2,22,0),
...
)

As implied above, the prime form algorithm can be seen as a hash function: it calculates a “code” that is used to index the information in the set table (i.e., hash table) (above).  The first value is the “key” or hash value which can be accessed quickly using a binary search algorithm.

Set Info: table lookup with binary search

Input Parsing

Perhaps the most important part of the PHP implementation was deciding how to input the data (pitch classes) in the most practical and efficient manner for the user.  My objective was to allow keyboard only input (if desired) in a simple HTML form text input box.  The code needed to distinguish between data entered in two formats:

  • a string of characters represented as single digit pitch classes (0-9, AaBbTtEe) that could include optional separations by white space and/or commas.
  • a Forte-style set-class number such as 6-19.

Additionally, I wanted to check for certain input errors such as:

  • illegal characters
  • too many characters
  • illegal Forte set-class numbers
  • non-legal first characters (‘,’ and ‘-‘)

The input function can take various types of text input in the HTML text entry box:

input stored as comments
71t6e 7, 1, 10, 6, 11 compact input
0, 1, 6, 7 0, 1, 6, 7 formatted
4-29 0, 1, 3, 7 Forte # lookup
48147597ab932075558102910e 0, 1, 2, 3, 4, 5, 7, 8, 9, A, B pruned and sorted

The main function for getting the user input (pitch classes or set-id number) is shown below.  My strategy was to try and check for the most obvious errors first.  If an error is found, the code calls”error” —a user defined function—  which prints a specific message to the user based on the error thrown.

Set Info: input parser

To facilitate the use of the computer keyboard (instead of the mouse), I added an “autofocus” attribute to the text input box in the HTML form. This ensures that the text field is highlighted and ready for keyboard input when landing on the page. Since the text input is activated by return and the submit button is the next form field, all information can be accomplished with the keyboard only (if desired).

In the interest of brevity, I have left out most details of the code, but hope that this demonstrates the basic objectives and implementation of this new version of Set Info. Based on years of using and optimizing the original Unix command-line C version, my overriding goal was to create an internet accessible tool that could be used quickly and easily.

Footnotes

1: This algorithm is well-documented in Brinkman, Alexander R., Pascal Programming for Music Research, University of Chicago Press, 1989. pp. 628-29.  My code for the functions that calculate the prime form via bit vectors is based on Brinkman’s. I’ve translated and adjusted much of the code from his Pascal version to PHP.  Individuals who made important contributions to the early (1970s) computer algorithm are: Bo Alphonse, Leland Smith, Daniel Starr, and Aleck Brinkman.  The SC table was designed by Allen Forte with adjustments made by John Rahn and Robert Morris.

2: 12-bit circular: Essentially we shift all the bit values one bit to the left.  However, since this is a mod 12 system we basically construct a ring or loop out of the bits so that if the 12th bit is on, shifting right will move that bit to the 0th bit.

Blog 1: Matrix Maker (Sept 2018)

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:

12-tone matrix (note names)
12-tone matrix (pcs)

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.

Search: The original C program (with highlighted pcs), 1992

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!

 

Blog 0: Some background…

I’ve always had a fascination with computers. In the early 1980s when most people didn’t have a personal computer, my high-school friend Eric Mellencamp’s father was a computer enthusiast. I’d spend hours at their house, on their vintage Apple II,  playing the Flight Simulator II.  Later, in 1984, we’d play with their Apple Macintosh— a new life-changing computer. My friend John Beasley, an LA-based studio musician, had a professional music studio and was using the original Macintosh to control his many MIDI keyboards; I learned a lot about the MIDI protocol by playing around in his studio and watching him work.

At the university of North Texas, during my undergraduate degree in composition, I studied computer music with Larry Austin and Phil Winsor and hung-out at UNT’s Center for Experimental Music and Intermedia (CEMI) where many of the graduate students were writing code as a means to explore algorithmic composition. One of the DMA gurus there, Gene DeLisa, was making some very compelling computer music and was also generating mesmerizing computer art with fractal algorithms that he programmed in C. (DeLisa and Winsor went on to write a book, Computer Music in C). At that time, CEMI didn’t have access to using any software synthesis languages (e.g., Csound) because, while they had a copy of the source code, the computer system (a DEC Vax 11/780) was located across campus and didn’t have a digital-to-analog converter (DAC) — even if it had, it would have meant walking across campus (from the VT100 terminal in the music building to the computing center) in order to hear the output!  A lot of the doctoral students were writing code in Basic (on the Vax) and using the output to shape different parameters of their acoustic compositions (e.g., rhythm, pitch, etc.).  Some of them were writing code with the output formatted for use as a note-list with the Synclavier digital synthesis system.  I was one of those that caught this bug.  I convinced one of my friends — Kurt Kuniyasu, an ex-professional COBOL programmer — to teach me the basic principals of programming so that I could experiment with using simple algorithmic ideas (e.g., techniques such as weighted probabilities to make pitch or rhythmic textures). I converted my code to run on a “PC,” then imported the output into a Macintosh MIDI editor and made a jazzy atonal piece called Groove (1989).

When I graduated from UNT in 1989, I bought my first PC — a 286 “clone.”  At the computer store, I actually had to argue with the sales person about purchasing the 20 megabyte hard drive because in his opinion, “you’d never have a need for that much space!”  I decided upon the PC over a Mac since the Mac was much more difficult to program on because there was no easy access to the underlying OS (System 6).

At the Eastman School of Music  in 1990-91 I took an intensive year-long course in Pascal with Aleck Brinkman. His newly minted book “Pascal Programming for Music Research” served as our course textbook; it was a telephone book-sized lifetime achievement of well-researched programming knowledge that toured through all the essential programming algorithms (string manipulation from scratch, sorting, searching, etc.) and data structures (arrays, linked lists, hash tables, binary trees, etc.).  At this time I became entranced by coding and wrote many programs to help with my music or the analysis of works that I wanted to study; these were mostly set-theoretic programs but I also wrote an early ear-training program to access my computer’s speaker in order to test my ear with various intervals.  A main influence in this period was my composition teacher, Robert Morris, who (aside from being an important American composer) is one of the pioneers of the musical branch of set theory, and had done a lot of programming in Fortran starting in the late 1970s.  In addition to Brinkman, he shared many insights that were fundamental to my understanding of programming and the pursuit of thinking in an elegant and logical manner.

In 1991-93, while working on my Ph.D, I served as the Unix system administrator at the Eastman School of Music where my job was to maintain a cluster of three Sun-3/60 computers with a base of about 50 users, and to compile and troubleshoot computer music software that was being shared between various universities and slightly different Unix systems. These 32-bit mini computers were housed in the Eastman Computer Music Center (ECMC), then directed by composer Allan Schindler, and served mostly composers working in early versions of the software synthesis language Csound as well as theorists, musicologists, and composers who were programming in Pascal and C.  I also took a course in Unix system administration at the University of Rochester.

In 1991 I bought a copy of Kernighan and Ritchie and learned C and, ever since, have been coding on a semi-weekly basis to solve my own music-related research problems (see here for two examples).  As an example: for my 2004 guitar piece Unfoldings, I created a program that simulates a human hand on a fretboard in order to find as many “resonant” chords as possible (six-note chords containing unison doublings). This program allows me to sort through the many possibilities to find those that I like. Below is an example of a portion of the output for one particular run; the “ASCII graphics” image is of a guitar neck from the player’s perspective (the performer would be looking down from the 6th string to the 1st):

Many of the programs that I use today were initially written in the early 90s at Eastman.  Since C is very portable, I have recompiled these over the years on many different systems (various flavors of Unix and Linux, PCs, Macs, Raspberry Pis, SGI, NeXTs, etc.).  Below is the output from a program that I’ve been revising for the past several decades called Array Editor (AED) — it helps me manipulate large partition-grouped layers of pitch-classes which it stores as rows of linked lists:

Screen image from AED (1993-)

I have also been active in the field of computer music since the late 1980s. In 2000, I created a free Unix command-line computer music application called nGen, which can be used to generate complex Csound “score files” as well as MIDI files (more information can be found here). I have worked extensively in the software synthesis languages Csound, Max/MSP, and most recently Super Collider.  From 2000 to 2011 I taught advanced computer music at Bowling Green State University and continually advise a small number of music students in their endeavors with various directed research problems in computing and/or software synthesis and real-time/live computer music.

In August 2018 I started to expand my language-base, which was mostly C and a little Python,  by learning PHP, JavaScript, and CSS. The first “full stack”  project that I made is called Matrix Maker, which builds on a C program I wrote in 1992.  If you are interested in that, please see my first blog post… (Blog 1). I’ll also be creating more posts about my older programs…

I invite you to know get to know more about me and my music through my website: mikelkuehn.com.