Monday, August 5, 2024

Heptatonic scales with a minor third

Which heptatonic scales consist entirely of semitones, whole tones, and a single minor third, without having two semitones in a row?

The heptatonic scales that consist entirely of semitones and whole tones without having two semitones in a row are the diatonic and the melodic minor. Both contain two semitones and five whole tones. There are only two ways of dividing the five whole tones into two groups.

2-2-1-2-2-2-1 (diatonic: two and three whole tones)
2-1-2-2-2-2-1 (melodic minor: one and four whole tones)

Subtracting the minor third from the octave leaves nine semitones remaining. All of our candidates must contain three semitones and three whole tones (3 × 1 + 3 × 2 = 9), because the other possibilities (five semitones and two whole tones, or seven semitones and one whole tone) unavoidably have at least two semitones in a row.

If the minor third’s neighbors are both semitones (1-3-1), what remains are a semitone and three whole tones, which can have only two viable configurations: 2-1-2-2 (the harmonic minor) and 2-2-1-2 (the harmonic major). All other configurations would place a semitone on the outside, where it would abut one of the minor third’s semitone neighbors, producing two semitones in a row.

2-1-2-2-1-3-1 (harmonic minor)
2-2-1-2-1-3-1 (harmonic major)

If the minor third’s neighbors are both whole tones (2-3-2), what remains are three semitones and a whole tone, and all of their possible orders have at least two semitones in a row.

Thus the only other candidates must have a semitone and a whole tone neighboring the minor third. The semitone may come before the minor third (1-3-2), or after it (2-3-1). What remains are a pair of semitones and a pair of whole tones, and their possible orders are as follows:

1-1-2-2
2-1-1-2
2-2-1-1
1-2-2-1
1-2-1-2
2-1-2-1

The first three orders have two semitones in a row and are therefore trivially dismissed. The fourth order can also be dismissed, because placing semitones at both ends ensures that one of them will abut the minor third’s neighboring semitone, again producing two semitones in a row. Only the last two orders are viable.

To recap, we have two sets of tones. One set contains a pair of semitones and a pair of whole tones interlaced. The other set contains a whole tone, a minor third, and a semitone. Each set has only two viable orders:

Set A: 1-2-1-2, 2-1-2-1
Set B: 1-3-2, 2-3-1

To form a complete heptatonic scale, we must pick one ordering from each set. Only four combinations are possible.

1-2-1-2, 1-3-2 (A1, B1)
1-2-1-2, 2-3-1 (A1, B2)
2-1-2-1, 1-3-2 (A2, B1)
2-1-2-1, 2-3-1 (A2, B2)

The second and third possibilities have two semitones in a row, leaving only the first and last:

1-2-1-2-1-3-2
2-1-2-1-2-3-1

Both of these results exhibit the octatonic diminished scale’s characteristic pattern of alternating semitones and whole tones. Both results are reducible to prime set 7-31, which can be arrived at by removing a note from the octatonic diminished scale (8-28).

Now we can answer the original question. The heptatonic scales that consist entirely of semitones, whole tones, and a single minor third, without having two semitones in a row are 7-32 (the harmonic minor and harmonic major) and 7-31 (the octatonic diminished scale with one note removed). For clarity, the final results are shown with the minor third always between the the sixth and seventh scale degrees:

2-1-2-2-1-3-1 (harmonic minor; 7-32)
2-2-1-2-1-3-1 (harmonic major; 7-32 inverted)
1-2-1-2-1-3-2 (fourth mode of Romanian major; 7-31)
2-1-2-1-2-3-1 (third mode of Hungarian major; 7-31 inverted)

Monday, February 5, 2024

The Modulation bar's new Targets pane now supports editing, but only to a limited extent, and here's why

The latest version of Polymeter adds an optional Target pane in the Modulations bar. This new pane also supports editing of the targets, to a limited extent. The table below shows which types of editing the Target pane supports.

EditSupported
Change type or targetYes
InsertNo
Insert GroupYes
DeleteYes
Cut/Copy/PasteNo
SortNo
Drag ReorderNo

Astute readers will notice that Delete is supported, but not Insert. This is most unusual and deserves some explanation. Also, Insert Group is supported, but not Insert. What is so special about Insert?

Let’s start by clarifying the semantics of the Insert command. The essence of this command is that it inserts something empty. For example, in a spreadsheet, the command typically inserts an empty row or column. In a text document, the command might insert a blank line. The idea is that Insert creates space for something, the contents of which will be specified later.

In the Modulation bar’s Source pane, the Insert command has the expected behavior. It inserts a modulation with the source track set to none. This means that the modulation does nothing, because it’s not connecting anything yet. In other words, the Insert command effectively inserts an empty modulation. Space is allocated for a new modulation, but further action is required to make the modulation functional. The user must select a source track other than none, and may optionally also change the modulation type.

Another important piece of background is that Polymeter’s data architecture is asymmetrical with respect to modulations. A track contains a list of the tracks that modulate it, but conversely, a track does not contain a list of the tracks it modulates. In the language of signal processing, a track maintains a list of its sources, but not its sinks. Sink here is synonymous with target. The reason for this is that the sequencer only ever needs to know which source tracks are modulating the track it’s working on. It doesn’t care about targets.

If we think of modulations as a tree-like hierarchical network, we can say that the sequencer traverses that network in only one direction, from the root towards the leaves. Because the sequencer never needs to work backwards from leaves towards the root, it can get away with keeping track of sources but not sinks. This data structure is known as singly-linked, versus doubly-linked, and it greatly simplifies the architecture. It also speeds performance, and avoids many bugs that can arise from so-called double bookkeeping. A modulation consists of one and only one element within a track, so there’s no ambiguity: it either exists, or it doesn’t.

With all that in mind, we return to the mysterious absence of the Insert command from the Modulation bar’s Target pane. Let’s consider an example. We have two tracks, called A and B, and we want A to modulate B. In other words, A is the source and B is the target. One could imagine adding this modulation to A, but as explained above, that’s impossible, because a track doesn’t list its targets; instead, it lists its sources. Our intention must be reversed: a modulator must be added to track B, referencing track A as its source. Track A is not edited at all. The target track is edited, not the source track. (see illustration)

Now try to imagine the following hypothetical situation, in which the Target pane does support Insert. We select a track, because we want it to target another track, but we don’t know which track it’s supposed to target yet. So we’re adding an empty modulation. In the Target pane, we select Insert. As we observed above, our selected track (the source) will not be modified. Instead, the target track must be modified. But since the target hasn’t been specified yet, where shall we put the empty modulation? The answer is: nowhere. We can’t insert an empty modulation in the Target pane because there’s nowhere to put it, and this is why the Target pane doesn’t support the Insert command. In order to insert a modulation in the Target pane, we need to know what the target is beforehand. That’s why Insert Group is supported: before inserting anything, it displays a modal dialog prompting the user to select the target track(s).

Thursday, January 25, 2024

The latest version of Polymeter adds a long-overdue feature: the Modulations bar now optionally shows targets as well as sources. This can be very useful for complex modulation networks. Until now, the only way to see the modulation targets of a track was via the Graph bar, with the graph’s Scope set to Targets or Bidirectional. The Graph bar requires installing Graphviz, so users who didn’t do that had no way of viewing modulation targets at all. But even if they did have Graphviz installed, the Modulations bar is easier to use, and it’s also the obvious place to look for this information.

To use this new feature, select Show Targets in the Modulation bar’s context menu. This command toggles the visibility of the Targets pane, in other words it shows the pane if it’s hidden, or hides it if it’s showing. When the Targets pane is shown, the Modulations bar is split into two panes, separated by a draggable splitter. The window is split horizontally by default, but if you prefer a vertical split, right-click the splitter to show its context menu, and select Vertical.

You might wonder why this feature wasn’t added sooner. It’s actually a challenge to implement, because the application’s architecture has a fundamental asymmetry between modulation sources and targets. Basically the issue is that modulations are singly- rather than doubly-linked. Each track keeps a list of the tracks that modulate it, i.e. its sources, but a track does NOT keep a list of tracks that it modulates. It could, but it doesn’t, and that’s because the sequencer engine—the part of the app that actually sequences MIDI, as opposed to mere user interface code—doesn’t care about modulation targets.

When the sequencer processes a track, it asks the question: “do any other tracks modulate this track?” In other words, it looks at the track’s modulation sources, also known as modulators. The sequencer never asks the question: “what tracks does this track modulate?” The sequencer’s top-level loop completely ignores modulator tracks, because they don’t output MIDI events, by definition. Modulator tracks are only accessed while processing a non-modulator track. More formally, the sequencer iterates modulation sources, but never iterates modulation “sinks”, and this is the reason for the architectural asymmetry.

The primary constraint on the design of the Polymeter application is optimizing the sequencer to maximize speed and throughput. Doubly-linked modulations would not help the sequencer at all. A few aspects of the user interface might benefit from doubly-linked modulations, but this is outweighed by much more complicated code, and the risk of many new bugs, particularly in the area of undoing edits.

So how do we answer the question, “what tracks does this track modulate”? We need that information in order to show the modulations graph, and we also need it to show targets in the Modulations bar. It’s done by creating a special type of lookup table called a cross-reference. To build the cross-reference, we iterate all of the tracks, and for each track, iterate its modulators, if any. While doing that, we put the modulators in “buckets” that correspond to target tracks. That might sound slow, but it’s the kind of thing computers are good at. Also, that process has been greatly optimized in this version, by storing the cross-reference in a “flat” one-dimensional array. Previous versions stored the cross-reference in an array of dynamic arrays, but this incurs significant performance costs, due to the potentially large number of arrays that must be reallocated and copied as they grow.

Stress testing was done to verify that the new modulation targets cross-reference consistently improves performance (it does). The second image in this post shows the stress test in the Graph bar, rendered by Graphviz, which after many years of faithful service continues to be one of my favorite open-source software projects ever.

Thursday, December 14, 2023

Chris Korda scores available

Scores are now FREELY available for many of my compositions! Please read the foreword. The scores were created using LilyPond, with a homegrown software to convert the MIDI files to Lily format.

Admirers of my classical music occasionally ask me for scores, and until now I've been hard-pressed for a solution. The proprietary vendors—Finale, Sibelius, Dorico—not only have big learning curves, they're also painfully expensive and likely to colonize my hard drive. I tried MuseScore, but found it lacking, and its more recent versions behave suspiciously like malware. So instead I opted for the hard road: LilyPond. The issue with LilyPond is that its MIDI import is so flawed that I deemed it necessary to write my own software to convert from MIDI file format to LilyPond format. This DIY approach probably would have been necessary anyway, due to the unique challenges that complex polymeter creates for musical notation.

Essentially LilyPond offloads much of the scoring process onto the user, so that it can focus primarily on engraving, which it does very well. For example, the user is responsible for ties, dots, tuplets, and so forth, and it took me several days to get all that sorted. In the process it became clear that certain aspects of my music defy notation. I will endeavor to explain these aspects, in the hope that the information is useful or at least entertaining.

The biggest problem is that my compositions often contain long arpeggios in which the notes overlap. I do this in order to maintain a consistent harmonic density. In other words, by extending note durations, I ensure that there are always the same number of notes sounding at once, typically four notes. In effect, the arpeggio produces a varying tetrachord, the pitches of which are constantly changing as new notes are added and older notes are removed.

This is a very different effect from merely pressing the sustain pedal. I rarely use the sustain pedal, because doing so juxtaposes too many notes at once, which is particularly problematic in atonal compositions due the potential for excessive dissonance. Also, in the virtual piano I use, the sustain pedal emulates opening the damper, producing complex and unpredictable acoustic effects, whereas merely increasing note durations so that notes overlap has a comparatively simple and predictable effect.

Arpeggios with overlapping notes are not only difficult to play, they’re also very difficult to score, because the score will be so full of ties that it’s nearly impossible to read. My impression is that the notation system doesn't handle this case very well. In any case, I decided to sacrifice verisimilitude in favor of readability, by eliminating all overlaps within each part, so that each part becomes a single-line melody. As is customary, I also removed all offset and swing from the composition prior to conversion. The biggest remaining challenge was detecting and correctly handling tuplets. It sounds easier than it is.

LilyPond includes two life-saving features. It has a bar check, which validates your LilyPond file to ensure that each bar's worth of notes, ties, tuplets, dots etc. actually add up to a bar. And, it can output a MIDI file that matches the engraved score. I built custom tools to compare the LilyPond MIDI file to my original MIDI file, and thus obtained "round-trip" verification that my compositions passed through the whole process undamaged. Whether the scores are to everyone's taste is another question, but at least they're "correct".

Sunday, December 3, 2023

Pitch class histograms

Behold pitch class histograms for my post-2018 music HERE.

I undertook to analyze the pitch class content of my compositions, and in doing so, to clarify which of them are the most *atonal*, in the sense of using all of the twelve pitch classes approximately equally. The term "pitch class" is from musical set theory, and basically refers to one of the twelve pitches of the equal-tempered chromatic scale, disregarding octaves; for example, the pitch class C consists of the Cs in all octaves.

My method of choice was the pitch class histogram, specifically its "folded fifths" variant which orders the histogram bins according to the cycle of fifths. This ordering "is useful for measuring dominant-tonic relationships and for looking at types of transpositions" according to the documentation for a popular music analysis library called jSymbolic. A modal composition--one that confines itself to a single key--will occupy seven consecutive bins of the folded fifths histogram, making it easy to identify.

A perfectly atonal composition would produce a histogram in which all twelve bars have exactly the same height. This would indicate that the composition's notes are distributed equally among the twelve pitch set classes, or put another way, that each pitch class comprises one twelfth (8.33%) of the composition's notes. This situation is unlikely in practice, but the more closely a composition resembles this idealized case, the more atonal it is.

I had long suspected that "Atunwi" and "Ero Ayo" are my most atonal compositions, and the histograms confirm this. But there were surprises too, for example the "Apologize to the Future" album is more atonal than I realized, particularly the tracks "Overshoot" and "Singularity." The chronological ordering of the albums reveals my gradual cultivation of atonality, starting with "Fazo Kanto" on "Akojo Ajeji."

I looked into using jSymbolic, but decided to roll my own code, in part because I was reluctant to risk installing the Java framework, but also because the primary goal was learning. The chart drawing was done via the Plotly Javascript library, which is free and open source and heartily recommended.

Thursday, April 27, 2023

Odd time and polymeter influences

Here's a list of songs that use odd time signatures or polymeter and have influenced my composing. I created it for a class I taught recently at Trouble in Brussels. It specifies the time signatures used in each song, along with a YouTube link. People often tell me they want to try my Polymeter MIDI sequencer, but they don't know where to start. One thing that can help is to STOP listening to music in 4/4 (at least for a while) and instead listen only to music that's in odd time or polymeter. My list will get you started. “Half of wisdom is learning what to unlearn.” -Larry Niven

Friday, March 31, 2023

PotterDraw synesthesia: LCM

This video visualizes polymeter music using an object that periodically changes shape in multiple ways at once. The music features six percussion instruments, each in a different time signature, with each instrument mapped to a different type of shape modulation. The mappings in order of appearance are: Bass Drum in 2/4 to Radius, Clave in 3/4 to Scallop Depth, Conga in 7/4 to Bend Depth, Snare in 11/4 to Helix Amplitude, Closed Hat in 5/4 to Twist, and Clap in 6/4 to Polygon Roundness. The music is an excerpt of "LCM" from my "More Than Four" album, available on Chapelle XIV. The shape morphing was done in PotterDraw, a software I created for designing virtual pottery and hyperobjects. The object's color is proportional to its radius. I have previously visualized polymeter using phase diagrams in which the different loop lengths are mapped to orbiting planets, but shape-morphing is closer to how I imagine dancing in polymeter would look. PotterDraw is limited to cylindical solids, so I expect better results could be obtained using a general-purpose 3D animation software. I had to hack at PotterDraw a bit to make it read the Polymeter track data, and one useful thing I learned is that Polymeter PLM files are very easy to work with, because they're text in INI format. This is good news for anyone seeking to replicate my results.

Heptatonic scales with a minor third

Which heptatonic scales consist entirely of semitones, whole tones, and a single minor third, without having two semitones in a row? The he...