Goal: build the second synthesis mode, the additive oscillator, which builds a tone up from a sum of sine partials rather than filtering a rich shape down. Done: an AdditiveOscillator sits on the same Oscillator base as Week 2 and sums up to thirty-two partials from a shared sine table. Their amplitudes are set by a movable window, its position and reach controlled by center and width, its slope by tilt, and the spacing of the partials by stretch. The series is band-limited at the top so it does not alias. The evidence below is rendered straight from that oscillator.
The shared base, revisited
Week 2 built the abstract Oscillator so that every mode could share one clock and one note-handling path, and fill in a single method, processSample, to turn the current phase into one output sample. The additive mode is the promised second subclass. The AdditiveOscillator inherits the base phase accumulator and note handling unchanged and supplies only its own processSample, so it drops into the audio-thread lifecycle already in place from Week 1 with nothing else to wire.
The two modes then diverge in method. The subtractive oscillator starts from one harmonically rich shape and leans on band-limiting to tame it. The additive oscillator starts from silence and adds one sine at a time, so its spectrum is whatever set of partials it chooses to sum. That difference is the reason to build both: they reach a similar range of tones from opposite directions, and the tradeoffs, in cost and in control, are the study of the week.
Summing the partials
Additive synthesis rests on a plain idea from Fourier: any periodic tone is a sum of harmonics, sine waves at integer multiples of the fundamental. Build the sum directly and you build the tone. The AdditiveOscillator carries thirty-two partials, each with its own phase, and reads every one from a single shared quarter-wave SineTable rather than calling a trigonometric function per partial per sample.
Summing many sines raises a level problem: a wide tone stacks far more energy than a single partial, so its peak is much higher. Each block the oscillator computes the running sum of the squared partial amplitudes and divides the output by its square root, a normalization that holds the loudness roughly even as the window opens and closes. The result is soft-clamped to the valid range as a final guard, so no setting can overrun the output.
The window: center and width
The thirty-two partial amplitudes are not thirty-two independent sliders. They are shaped by one movable window, an amplitude envelope drawn across the partial series, so a few controls set the whole spectrum at once. The window is a Gaussian curve. center places its peak on a chosen partial, from the fundamental up to the thirty-second, and width sets how many neighbouring partials it reaches before it falls away. A narrow window near the fundamental gives a nearly sinusoidal tone; a wide window higher up gives a formant-like cluster.
The curve is deliberately asymmetric. Its lower side, toward the fundamental, falls a little more gradually than its upper side, toward the top of the series (the code widens the lower half of the bell and narrows the upper half). The asymmetry keeps a shifted center from sounding thin, since a real resonant body tends to trail energy downward more than upward. It is a small shaping choice, but it is audible when the window sweeps.
Tilt and stretch
Two further controls act on the series as a whole. tilt is a spectral slope, applied as a gain in decibels per octave measured across the partials, so a negative tilt darkens the tone by rolling off the upper partials and a positive one brightens it. It is the additive form of the rolloff curve a subtractive filter would draw, set here at the source instead of after it.
Where tilt changes how loud the partials are, stretch changes where they sit. It nudges each partial's frequency away from an exact integer multiple of the fundamental, so partial n lands slightly above or below n times the pitch. Perfect integer spacing gives a fused, organ-like pitch; a small stretch pulls the partials into an inharmonic relationship and gives the tone the metallic character of a struck string, whose stiffness stretches its overtones the same way.
Band-limiting the series
Additive synthesis has one advantage over the subtractive mode when it comes to aliasing: it never generates a partial it did not ask for, so it can simply decline to sum any partial that would sit above the Nyquist frequency. As the pitch rises, the upper partials cross that line one by one and are dropped from the sum. To keep a partial from appearing abruptly as it crosses, the ones just below the limit are faded down a cosine taper rather than switched off, so the top of the spectrum thins smoothly instead of clicking.
One subtlety matters for the loudness. The oscillator runs oversampled, four times the host rate, and the normalization sum is taken from the full window before any high partial is dropped, not after. Removing a partial that would alias therefore lowers the output level, as it should, without changing the balance of the partials that remain in band. The tone gets quieter toward the top of the keyboard, not brighter or thinner, which is the physically correct behavior.
Partial drift and jitter
Thirty-two mathematically exact sines, locked in phase and pitch, sound static. The oscillator keeps them in motion. Each carries a slow, independent drift in phase and a small, faster jitter in amplitude, both a fraction of a decibel, scaled so the higher partials move a little more than the low ones. This motion is always on. It is not a parameter to be dialled up, but a property of the oscillator, the additive equivalent of the per-voice seeding the noise source used in Week 2.
The motion has an audible consequence at the start of a note. At note-on the partials begin aligned in phase, and the first fraction of a second, before the drift has pulled them apart, carries more high-frequency energy than the settled tone that follows. It resolves on its own as the partials decorrelate. This is documented here as a known behavior of the current build, and refining that opening transient is scheduled work, not a finished result.
Evidence
The assets below are rendered headless from the plugin's own additive oscillator (one voice, no analogue coloration, 48 kHz), so they show the real code path, not a model of it. The spectra are drawn from the rendered audio, not computed from the window formula.
tilt (bottom) holds that cluster in place but pulls the upper partials down, the additive rolloff. The low-level detail between the partials is the always-on drift and jitter at work.
Reflection
The synthesis itself was straightforward. Summing sines from a shared table onto the base class from Week 2 was almost mechanical, and the result was immediate: a spectrum I could see and control. The difficulty concentrated in two places. The first was the normalization, which I underestimated. My early tones jumped in loudness every time the window moved, and getting the level to hold even meant thinking carefully about which partials to count in the sum and when, especially at the top of the range where partials are dropping out. The second was restraint. Thirty-two independent amplitudes were a temptation, and my first instinct was to expose all of them. The window, with its handful of controls, is the better instrument, and choosing fewer, more musical controls over raw generality was where the design effort of the week went. The surprise was how much the always-on partial motion mattered. With it switched off the tone is cleaner but duller, and that tradeoff sets up the questions the filter and modulation weeks have to answer.
References
- Julius O. Smith III. Spectral Audio Signal Processing, W3K Publishing, 2011 (Fourier and additive-synthesis foundations).
- Julius O. Smith III and Xavier Serra. PARSHL: An Analysis/Synthesis Program for Non-Harmonic Sounds Based on a Sinusoidal Representation, Proc. International Computer Music Conference (ICMC), 1987 (analysis and synthesis of tones as a sum of sine partials).
- Eleanor Roy. Investigating the Inharmonicity of Piano Strings, Edinburgh Student Journal of Science, vol. 1, no. 2, 2024 (inharmonicity of stiff strings, the basis for the stretch control).