Charles Petzold



“Fantasy on a Fugue” (Revisited)

August 2, 2024
Roscoe, N.Y.

This has been on my to-do list for 40 years.

Around 1980, while immersed in the music of Philip Glass and Steve Reich, I became intrigued by the idea of process music and conceived of a composition based on the Fugue in C minor from Book 1 of J. S. Bach’s Well-Tempered Clavier, a piece I had first heard (along with its accompanying Prelude) on Wendy Carlos’s groundbreaking album Switched-On Bach in 1969 when I was 16 years old.

The composition I dreamed up can be described in one sentence:

Bach’s Fugue in C Minor (BWV 847) is played from beginning to end in one-measure windows that advance by a sixteenth note after a certain number of repetitions.

In effect the fugue is played in slow motion, but I figured that the tempo would be set so fast that the listener would experience a blistering flurry of notes, which seemed kind of cool to me.

I knew that this might be played by a human being, but certainly not me, whose uncoordinated fingers can’t even manage Bach’s Two-Part Inventions. Fortunately, at the time that I concocted this composition, I was building a microprocessor-controlled digital electronic music synthesizer that I figured could play this composition for me. Indeed, the prospect of transforming a Bach fugue into Philip Glassian trippiness was a major impetus to finishing the synthesizer and programming it to play music.

And so I did. In May 1982, I was able to play the composition from my synthesizer and record it. By this time I was calling it Fantasy on a Fugue, despite the fact that it didn’t at all fit the notion of a musical fantasy. Oh well: too late now to change the name now.

But I was never quite happy with it. I thought that such a brilliant conception deserved a better realization. Over the decades, I’ve wanted to revisit Fantasy on a Fugue, and I began to think it might be made more interactive, and perhaps more visual. By the late 1990’s Windows had acquired sound-generation facilities that I explored with much enthusiasm — the classic 5th edition of Programming Windows published in 1999 has a 130-page chapter devoted to sound and music — but I never had enough free time to implement a new version of this composition. Ten years later, I was playing around with Silverlight, which had the potential of allowing me to put a new version of Fantasy on a Fugue on a website so that the entire world could experience it (or perhaps charge my apartment with torches and pitchforks). I explored Silverlight sound generation sufficiently to write a little sequencer, but then I got into Windows Phone and Windows 8, and Silverlight slipped away before I could get much deeper.

Recently I’ve been exploring the Web Audio API, which I believe has a somewhat better chance of surviving longer than Silverlight. By combining Web Audio with the graphics of the HTML5 Canvas, I could do things that were unfathomable when I conceived this composition over 40 years ago.

So here it is, enhanced with a synchronized visual display of the score and a bunch of sliders for interactivity:

Fantasy on a Fugue

Bass (bottom)

Alto (middle)

Treble (top)

To see this in action, all you need do is press the triangular Play button in the center under the displayed score. The fugue is first played normally from beginning to end. Then the fugue begins from the beginning but this time with one-measure windows repeated four times each. At first, this window includes only the first note of the fugue, so it’s not very interesting, but once the window advances so that a whole measure of notes is played, it definitely gets more entertaining, and with sufficient patience, the other two voices enter and then it’s a party. Interestingly, even with all the repetition, the result is still technically a fugue. With the default settings, Fantasy on a Fugue runs about an hour. It concludes with the fugue played normally again.

You can pause and resume at any time, or if it becomes too intolerable, you can press the Stop button. (Your browser will also pause the program if the browser is minimized or the tab is hidden.) You can also change the Volume, the Tempo in quarter notes per minute, and (while the repetitive part is going) the number of Repetitions for each one-measure window. If you’re impatient, setting the tempo at 140 quarter notes a minute with just 1 repetition will get it all over and done with in 17 minutes. With a tempo of 40 quarter notes a minute and 10 repetitions, Fantasy on a Fugue will play for about 7½ hours. All settings are saved and restored when you refresh or revisit the web page. To return them all to “factory settings,” press the Restore Default Values button.

Sometimes notes longer than a sixteenth in duration straddle the one-measure window. Notes that begin before the window but have a duration that continues into the window are treated as if they begin at the beginning of the window. Notes that begin before or during the window but have a duration that exceeds the end of the window are treated as if the duration does not exceed the end of the window.

The Fugue in C minor is in three voices. Normally it’s shown on two staves for conventional performance on a harpsichord or piano. For purposes of clarity, I’ve given each voice its own staff. You can use the three sets of sliders under the blue headings to change the sound of the voices and their volumes.

The tones are generated using a technique called Frequency Modulation (FM) Synthesis, first popularized by John Chowning at Stanford University in an article published in the Journal of the Audio Engineering Society in 1973. FM Synthesis can be quite complex, but I’ve used a simple approach here: Each voice is just two sine waves, referred to as the “carrier” and the “modulator". The modulator alters the frequency of the carrier so that the resultant waveform is:

sin(fct+Isin(fmt))

where fc and fm are the carrier and modulator frequencies, respectively, and I (called the Modulation Index) is the ratio of the peak deviation to the modulating frequency. The instantaneous frequency is the first derivative of that, or:

fc+Ifmcos(fmt)

Using sliders, you can change the FM parameters and the resultant sound independently for each voice: The ratio of the carrier frequency to the modulator frequency is adjustable by the slider labeled C:M Ratio and governs the partials that are generated. The Modulation Index governs the intensity of these partials. You can also set the individual Volume to isolate voices.

But note: If you set the Modulation Index to 0 or something close to it, the voice becomes just a sine wave. In that case, if the first number in the C:M Ratio is something other than 1, the pitch will not be correct. More extreme values of C:M and the Modulation Index might result in unusual sounds. Parental supervision is advised.

I’ve implemented envelopes for both the volume of the carrier and the Modulation Index but these are hard-coded.

The Original Realization

If you’re interested, an MP3 of the recording of the original 1982 rendition of Fantasy on a Fugue is available on my webpage Adventures in Electronic Music. I wrote the program that realized this composition in an interpreted Music Programming Language that I invented and which is described in Appendix II of that document starting on page 38. The MPL program listing for Fantasy on a Fugue is in Appendix I.The MPL statements were interpreted by hand-assembled Z-80 machine code, which then made use of other routines (also written in hand-assembled Z-80 machine code) to control the synthesizer.

The New Realization

This new version of Fantasy on a Fugue is written in JavaScript and makes use of the HTML5 Canvas for rendering the score, the Web Audio API for generating the sound, and simple HTML and CSS for the UI elements. All the JavaScript code runs on the client and is accessible from the page source of this HTML file or by clicking the boldface links below.

I knew I wanted to display the score of the Bach Fugue, but instead of just scrolling it horizontally as seen in many YouTube videos, I wanted to highlight the individual notes as they were playing. This requirement meant that I couldn’t simply display a printed score lifted from the internet. I would have to write graphics code to render the score in real time.

From the Mutopia Project website, I found the score of J. S. Bach’s Fugue in C minor, BWV 847 in both printed and encoded versions. The foundational encoding of the score is a LilyPond (.ly) file. LilyPond is a cross-platform open-source music formatting program that interprets an .ly file to generate a PDF of the score as well as a MIDI (Musical Instrument Digital Interface) file, all of which are included on the Mutopia Project page.

I’ve played around with MIDI files before (such as in the MidiColors program I wrote for the February 26, 2002 issue of PC Magazine), but I was reluctant to write a MIDI file parser in JavaScript, and I was even less eager to write even a simple LilyPond file interpreter. Fortunately, I found a page provided by the Tone.js folks (which I had considered using for my tone generation) that converts MIDI files to JSON. Much joy was experienced.

However, the MIDI file and the JSON file both combine the three voices of the fugue into two channels. I instead wanted three channels. I discovered that it was fairly simple to alter the LilyPond file to separate the score into three staves. LilyPond then generated a new MIDI file, which I then converted to JSON, and that’s what I used in this program. It’s stored among the source code as BachFugue.json.js.

The FantasyOnAFugue.js file defines a class that handles all the UI, instantiates the other classes, and controls the playback of the composition. The overall timing is based on the requestAnimationFrame function, which is synchronized with the video refresh clock.

The CompositionPlayer class in the CompositionPlayer.js file uses the JSON score to play the composition, both in “normal” and “windowed” renditions. To avoid hiccups due to other processes running on the machine, it uses look-ahead timing as described in the webpage "A Tale of Two Clocks” by Chris Wilson. The Web Audio API is built for such look-ahead timing, allowing events to be scheduled to be played at particular times, and even encompassing envelope segments. CompositionPlayer obtains tones from FMToneSupply, which instantiates and caches instances of FMTone, both of which are defined in the FMToneSupply.js file. The voices are spatially separated with bass on the left, alto in the middle, and treble on the right.

As CompositionPlayer is playing the composition, it encodes in each note in the JSON file the audio context time that the note is to be pressed and released. The code in ScoreDisplay.js interprets the same JSON file used by CompositionPlayer to render the score and highlight those notes currently being played. At first glance, the code in ScoreDisplay might seem generalized, but it is not. Generalized code to render a musical score is quite complex. According to Wikipedia, the LilyPond source “includes over 600,000 lines of C++, 140,000 lines of Scheme, and 120,000 lines of Python code.” ScoreDisplay has only about 1300 lines. As you’ll note, the notes are very strictly spaced horizontally based on their durations because it was much much easier to write it that way. Very little code exists that is not specifically needed. For example, ScoreDisplay doesn’t handle dotted notes because none appear in the Fugue in C minor. All accidentals apply only to the notes to which they are attached.

For some complex musical symbols, ScoreDisplay uses graphical paths defined in the MusicalSymbols.js file. These were obtained from SVG files on Wikipedia.

Considering the work I devoted to getting this working, it would be a shame for me not to adapt the code for other musical projects, wouldn’t you agree?