Chapter 4 — Varispeed Overdubbing Looper (gen~)

Varispeed Overdubbing: Collaboration with Graham Wakefield

This chapter is something of an anomaly within the book. It addresses problems that require solutions more complex than are easily achieved using the usual visual, object-based approach to Max patching—at least at this time. As a result, it moves into more advanced territory.

Up until this point, we’ve used standard gen~ operators in our patching. Doing so has enabled us to easily move from MSP to gen~-based visual patching, and to preserve the visual flow of data through the patchers we create.

Creating our new patcher requires us to use the Gen environment’s codebox operator, which enables us to perform procedural text-based coding using the GenExpr language that is at the heart of gen~ itself.

Everything in a gen~-based patcher—both the gen~ operators and the contents of a codebox operator—is merged into a single representation used to generate and compile fast native CPU machine code on-the-fly. So, while there is absolutely no difference in terms of performance between using visual patching or using a codebox operator in gen~ to do the same thing, there are two places where you absolutely need to use a codebox operator.

The codebox operator is the only way to have precise control of the order of reads and writes for working with delays and operations on data and buffer operators. Since we need to lay out a specific order for these operations in our looper, we’ll be using a codebox operator. (The codebox operator is also necessary for something we don’t need to do—to perform procedural branching and looping with if(), for(), or while().)

The patcher we’re creating here requires approaches we cannot easily achieve using the usual visual, object-based approach to Max patching—at least at this time. As a result, it moves into more advanced territory.

Rather than following the step-by-step trajectory of earlier chapters, we recommend first reading below about the problem itself, and then examining the commented codebox in the example patcher to see one possible solution. You are, of course, free to skip the discussion entirely and simply use the patcher. However, we believe the ideas explored here are worth engaging with, as this chapter presents a varispeed overdubbing looper in gen~ that overcomes key limitations by drawing on more technical DSP strategies.

Problems

There are problems that occur with the previous gen~ patcher when overdubbing at different rates of speed and/or direction—in particular, when overdubbing at non-equal divisions of the speed—we get sonic artifacts that sound like distorted buzzing metallic sounds.

Additionally, there are clicks when the loop transitions from the end to the start. For some of us, the glitchiness can be embraced and used aesthetically, but for others, it is an unappealing mess.

The Fundamental Writing Problem

The distortion issue arises from the way digital audio buffers operate. A buffer is essentially an array of consecutive audio samples. When you write at speed = 1, each passing moment of real time corresponds to exactly one buffer location being filled. Sample 1 goes in slot 1, sample 2 in slot 2, and so forth—the buffer fills continuously with no gaps. It works and sounds great.

However, problems begin as soon as the write speed deviates from 1. For example, at speed = 1.5, the write head advances 1.5 samples per sample frame of real time. You write to position 0, then 1.5, then 3, then 4.5, and so on. The positions between those samples remain either unfilled or contain old data from previous passes. When the read head later encounters this patchwork of new and old samples, the result is a characteristic, distorted, buzzing, metallic sound.

The situation becomes even more complex when speed changes are smoothed, modulated, or reversed, since the write position is constantly moving at non-integer rates. No amount of interpolation or filtering on playback can repair audio data that was never written coherently in the first place.

In short, our original varispeed overdubbing method has somewhat corrupted the contents of the buffer, leading to those sonic artifacts. This behavior isn’t a bug or an implementation mistake—it’s a structural DSP problem, and a problem whose solution required careful thought.

We reached out to Graham Wakefield, the original author of gen~ and co-author with Gregory Taylor of the book Generating Sound & Organizing Time: Thinking with gen~ (Book 1). Graham, through a series of emails and Zoom calls, worked with us to create a codebox-based patcher that solved our problem.

Two Viable Architectural Solutions

Once this problem was understood, Graham presented two possible solutions to us, unpacked each one, and then devised a hybrid patcher that combined elements of both solutions. The following descriptions are gleaned from our emails, Zoom calls, and example patchers he shared.

Solution 1: The Delay-Based Approach

The first solution treats the buffer not as a static loop, but as a continuously running delay line with feedback.

With this solution, the write head always advances at exactly one sample per sample frame of real time. A counter increments continuously, and its value is sent directly to poke~. This guarantees that every consecutive buffer position contains sequential audio samples. There are no gaps, and therefore, no distorted, buzzing, metallic artifacts.

Playback is handled by a read head that trails behind the write head by a fixed distance equal to the desired loop length. For example, a two-second loop at 44.1 kHz places the read head 88,200 samples behind the write head. This position is calculated by subtracting the loop length (in samples) from the current write position and reading from the buffer using peek~ with interpolation enabled.

A conceptual shift is important: the “loop” is no longer a fixed region of the buffer. Instead, it is a moving window of audio that follows behind the present moment. The buffer itself continuously scrolls forward, wrapping around as needed.

Recording control can be handled in two ways.

  1. One option is to freeze the write head when recording is disabled, locking the loop contents in place.
  2. Another possibly more musically useful option is to keep the write head moving but stop mixing new input into it. This behaves like a delay pedal with infinite feedback: the loop continues, but no new material enters.

Because this system is fundamentally a feedback loop, audio is repeatedly read with interpolation. Over time, this results in a subtle loss of high frequencies. If you pitch a loop down and then back up, the sound will not return perfectly unchanged. Instead, it accumulates filtering, which produces a tape-like degradation that some musicians might find musically appealing.

Speed and pitch changes are achieved by changing the distance between the read and write heads. Bringing them closer together raises pitch and shortens the loop; moving them farther apart lowers pitch and lengthens it. This produces cascading pitch effects similar to those found in digital delay lines.

This approach is robust, efficient, and relatively simple to implement; however, it behaves more like a digital delay than a traditional tape loop.

Solution 2: The BBD-Like Variable-Speed Writer

Initially, the delay-based solution seemed like the answer, but the second solution Graham provided preserves the traditional looper metaphor: the entire buffer represents the loop, and playback speed can be adjusted independently of recording.

The challenge here is writing correctly at variable speeds. If speed = 2, two buffer samples must be written for every one sample of real time. If speed = 0.5, one buffer sample must be written every two samples of real time. With non-integer or modulated speeds, the math becomes significantly more complex.

Solving this requires multiple write operations per sample frame. In gen~, this can only be achieved using a codebox containing a loop that calculates how many samples need to be written during each DSP tick. Fractional remainders must be tracked across frames to maintain accurate timing.

Interpolation is also required at the input stage. When writing fractional samples, simply duplicating input values introduces quantization noise. Instead, the input signal itself must be interpolated between successive samples before being written into the buffer.

According to Graham, this method has clear advantages. Once audio is written into the buffer, it remains pristine. You can pitch material up and down repeatedly, and when you return to the original speed, it will sound the same. However, the CPU cost scales directly with speed, making extreme modulation expensive. Additionally, any overdubbing performed at slowed speeds permanently bakes sample-rate conversion artifacts into the loop.

Additional Complications

Regardless of architecture, several other practical issues, in addition to the overdubbing artifacts, must be addressed:

  • Clicks can occur when recording starts or stops, when overdub modes change, or when the read and write heads cross (especially during reverse playback or aggressive modulation). These are solved with short fades and crossfades.
  • Reverse playback raises conceptual questions: should new overdubs play forward or backward relative to the reversed loop? A musically intuitive choice for some—overdubs playing forward—is technically harder and requires careful head management.
  • Latency compensation is required to ensure that overdubbed material aligns correctly with the existing loop content.
  • Loop length changes without pitch effects demand careful repositioning of the read head and crossfading to avoid audible jumps.
  • Feedback loops can accumulate DC offset and spectral “dulling” as high frequencies are lost; this requires filtering that itself introduces latency and phase considerations.

Graham’s Hybrid Tape-Style Solution

(Example Patcher: 4-1-Varispeed-Overdub-Gen)

The patcher presented in this chapter is based on a hybrid tape-style architecture developed in consultation with Graham. It combines the conceptual clarity of a tape metaphor with the technical gymnastics required to avoid buffer corruption.

In this design, speed controls the rate at which data moves through memory, including negative speeds for reverse playback. Graham created—using codebox—logic that swaps the heads’ reader and writer roles during direction reversals and uses rapid crossfades to prevent clicks. The beauty of this patcher is that overdubbing remains stable at all speeds and directions, even when using the speed modulation to simulate tape warble. To explore the use of codebox in this patcher, open up the example, go into edit mode, and follow the comments to double-click and open gen~.

The loop length can be set in three ways: directly via a parameter, by tapping two impulses to define a duration, or by synchronizing continuously to an external clock. For this example patcher, we have foregrounded the tap method, as it is more common in live looping cases. However, if you take the patcher out of presentation mode, you can see the other methods (in Edit mode). Smoothing the speed enables musically convincing tape-stop effects. A maximum speed limit is imposed to manage CPU load.

Some high-frequency loss will occur due to repeated interpolation, especially at extreme speeds. Rather than treating this as a flaw, the design embraces it as part of the tape-like character of the system. Achieving this required a substantial restructuring of the algorithm and the use of codebox for variable-speed writing loops.

While the complexity of this patcher goes beyond earlier examples in the book, it demonstrates the possibilities within the Max environment of gen~ to build reliable, professional-quality loopers that support overdubbing, varispeed, and reverse playback without artifacts, and shows how far gen~ can be pushed when its underlying DSP constraints are taken seriously. And like our other patchers, this has plenty of room to explore modification possibilities and make it work in a unique, personal manner.