Week 8 — Wrap-up


The Evergreen State College · Summer 2026 · 12 credits
Student: Travis Inskeep · Faculty Sponsor: Jessica Carey

Eidolon · Independent Learning ContractWK·8

This is the last week of the contract, and the deliverable is the instrument itself rather than another component of it. Eidolon is an eight-voice hybrid synthesizer that builds as VST3, AU and CLAP from one source tree. This page presents five pieces of music written to play it, the distributable that produces them, and an honest account of which contract rows were met and which were not.

Five pieces

Every prior week ended in a measurement. A filter sweep is clean, an envelope does not click, a route reaches its target. Those are necessary and they are not sufficient, because an instrument that passes every test can still be unpleasant to play. So the final evidence is music.

There are five pieces and each one is the lead witness for a different capability, so the set covers the instrument rather than showing one idea five times. Each runs between two and a half and three minutes. That length is earned by development rather than repetition: material enters and leaves, register and dynamics move, the voicing is turned while it sounds, and the last section is an ending that is arrived at rather than a truncation.

All five are deterministic offline renders from a headless tool, not real-time captures. Each is peak normalised to the same level, so the pieces sit at a comparable loudness and none was mastered further. The section maps below are generated from the same tempo and beat positions the render tool uses, so the times are the piece's own structure rather than a listening estimate.

  1. 0:00IntroBass alone, half time. Cutoff opens 220 to 650 Hz under it.
  2. 0:11GrooveThe identity figure arrives. The motif enters over it at 0:22.
  3. 0:34DevelopmentThe harmony drops a tone. Folder Drive and Resonance climb together.
  4. 0:56LiftBass thins to half notes, the motif goes up an octave, Cutoff to 1.5 kHz.
  5. 1:11BreakdownThe bass drops out entirely. The motif is alone and its filter closes to 900 Hz, which is the clearest look at the filter in the piece.
  6. 1:26ReturnBass returns syncopated. The motif answers a third higher.
  7. 1:49ClimaxA sixteenth-note pedal under Resonance 0.52 and Cutoff 2.2 kHz, the widest the filter opens.
  8. 2:15DescentRegister and cutoff fall together into the ending.

Transition or frameSection that foregrounds the capability

Controls are named as they appear in the editor. Cutoff and Resonance are Front surface controls on the Filters panel; the wavefolder Drive is on the Oscillators panel.

Folded Motion, 2:37. Subtractive synthesis, which means the filter is doing the work. Two voices: a bass on two detuned sub oscillators through a pair of wavefolders into a 24 dB low pass, and a motif on a formant wavetable through a gentler 12 dB filter. Across eight sections the bass filter opens from 220 Hz to 2.2 kHz while resonance climbs from 0.10 to 0.52. The arrangement is built so that reads as an arc rather than a sweep, which is why the bass leaves entirely at the breakdown and comes back syncopated.
  1. 0:00EmergenceWidth opens 2.0 to 5.5 while Center rises 1.0 to 2.2. A near-sine becomes a pad.
  2. 0:19StatementThe progression arrives. Tilt drifts -0.10 to +0.10 underneath it, moving energy from the low partials to the high.
  3. 0:44WideningUp a fourth. Width 5.5 to 17.0 and Center to 5.0, with Cutoff opening to pass the added partials.
  4. 1:16InharmonicStretch runs 0 to 0.42, so the partials leave the harmonic series. A second additive layer enters beneath on a narrow Width of 1.5.
  5. 1:47CollapseStretch returns to 0, the window closes, and the drone leaves.
  6. 2:13ReopeningWidth alone opens to 26, with Center held low and Tilt up. The same chord, a different spectrum.
  7. 2:35EndingThe window keeps closing while a 1.75 s Release carries the held chord out.

Transition or frameSection that foregrounds the capability

Center, Cutoff and Release are Front surface controls, on the Oscillators, Filters and VCA panels. Width, Tilt and Stretch are on the Detail surface, under OSC 1, ENGINE - ADD. Center exists only while Osc 1 is in additive mode, so the control appears with the engine it belongs to.

Polyphonic Drift, 2:43. Additive synthesis played as a moving partial window rather than set as a preset. Across seven sections the pad's partial spread opens from 2.0 to 26, its center climbs from 1.0 to 5.0, and its tilt drifts from -0.10 to +0.10. A stretch control takes the partials inharmonic at the midpoint and returns them. No note material changes to produce any of it. The progression is ordinary and the timbre moves underneath it.
  1. 0:00Fade-inTube Mix, Delay Mix, Reverb Mix and Tape Mix rise together from 0.02 to 0.04 into playing levels.
  2. 0:19DelayThe figure arrives on a 280 ms bucket-brigade line. Feedback climbs 0.26 to 0.44 and Delay Mod Depth opens with it, so repeats detune as they stack.
  3. 0:58PlateLong fifths. Reverb Decay stretches 2.3 to 4.2 s and Reverb Diffusion opens to 0.74, turning discrete echoes into a wash.
  4. 1:26TapeSparse and high, where the flaws show. Tape Drive to 0.62, Tape Wow Depth to 0.22, Tape HF Loss to 0.55.
  5. 1:46TubeDense and low, where saturation reads as thickness. Tube Drive to 0.72, and Tube Stages brings in the second stage.
  6. 2:05RecedeEvery mix backs off together and the material descends. The stages are still present, just no longer foregrounded.
  7. 2:22EndingReverb Mix rises into the tail so the piece blooms rather than stops.

Transition or frameSection that foregrounds the capability

Controls are named as they appear on the Effects panel. Ten of the thirteen are Front surface controls. Delay Mod Depth, Reverb Diffusion and Tape Wow Depth are on the Detail surface, under DELAY MODULATION, REVERB CHARACTER and TAPE MOTION.

Circuit Space, 2:37. The effects rack played rather than configured. One voice runs into four stages in series and each section foregrounds a different one. Nothing is switched on or off. Every change is a control moving while the instrument sounds. The voice underneath is a sine carrier frequency modulated by a metallic wavetable an octave above and ring modulated from a third oscillator, then folded twice and filtered at 2.6 kHz.
  1. 0:00Bass alonePosition moves 0.00 to 0.35 with nothing else sounding, so the traverse is audible by itself.
  2. 0:16Pad entersThe pad scans the other way, 0.85 down to 0.35.
  3. 0:37Full traverseThe lead enters and reads the whole table once, Position 0.00 to 1.00.
  4. 1:08High registerThe lead plays high against the brightest frames while the bass drops out.
  5. 1:29Reverse scanThe lead descends the table while the pad climbs it, and the two cross.
  6. 1:50Table changeThe Table itself changes under a sounding note, then a new scan begins in the new frames.
  7. 2:13ConvergeAll three positions arrive at 0.5 together as the harmony resolves.
  8. 2:29EndingThe three drift down together through the ring-out.

Transition or frameSection that foregrounds the capability

Position and Table are Front surface controls on the Oscillators panel, and both appear only while the oscillator is in wavetable mode.

Scanning Glass, 2:35. Wavetable synthesis, where the timbre is a position in a table rather than a filter setting. Three layers read the same mechanism differently: a lead on a harmonics-sweep table, a pad on a folded table detuned against itself, and a bass on a basic analog table. The three positions traverse, cross, and finally converge on the middle of the table. One section changes the table underneath a sounding note, so the frames themselves are replaced and the scan starts again in new material.
  1. 0:00AsleepPlain sustained chords with every modulation depth at zero. LFO 1 wakes over the last eight beats.
  2. 0:20WakingLFO 2, then 3, then 4 arrive over a single held pair of chords.
  3. 0:49Rates riseLFO 1 goes from 0.20 to 3.2 Hz. Undulation becomes growl without a note changing.
  4. 1:14Sample and holdA third layer enters and two sample-and-hold sources step the wavefolder, so the timbre moves in jumps rather than glides.
  5. 1:37StilledEvery depth returns to zero against a held chord. The absence is the demonstration.
  6. 2:00FullEight LFOs across eleven modulation matrix slots, rates driven to 4.2 Hz.
  7. 2:23EndingThe machines slow to a stop under the last chord.

Transition or frameSection that foregrounds the capability

Sources, targets and depths are on the Back surface, which is the dedicated matrix editor. The rates are per-LFO controls on the same surface.

Patient Machines, 2:33. The modulation layer, argued rather than demonstrated. The note material is deliberately the plainest of the five, because the proof that the matrix is working has to be that the sound changes while the notes do not. Every depth starts at zero and is raised by automation, so the first minute is the machines waking one at a time. A third layer never modulates at all, and it is the control the other two are heard against.

The instrument as delivered

Eidolon is eight-voice polyphonic. Each voice runs three oscillator slots that can each be subtractive, additive or wavetable, into two wavefolders, two filters, an amplifier modelled as a transconductance stage into a diode amplifier, and a summing stage. Nonlinearity is distributed along that path rather than concentrated in one output stage. A modulation matrix of twenty-four slots connects any source to any continuous target with signed depth. The full signal path and the reasoning behind it are on the Design Rationale page.

One source tree produces four targets: VST3, AU, CLAP and a standalone application. The CLAP target is built with clap-juce-extensions and reached behavioural parity with the other two in Week 7, with the format divergences written up separately rather than summarised here. One of them is worth naming: CLAP can deliver a parameter change as a sample-accurate event inside the audio call, where VST3 and AU deliver one value per block. Eidolon reads parameters per block regardless, because that is how the JUCE parameter layer consumes them, so the capability is the format's rather than this instrument's.

Every format loads in a host. VST3 and AU load in Ableton Live. VST3 and CLAP load in Bitwig Studio and REAPER. Those are the combinations actually opened and played, so they are the ones claimed here.

The distributable is Apple Silicon only, at macOS 11.0 or newer. That is a real limitation and it has a specific cause: two DSP headers use ARM NEON intrinsics with no scalar fallback, so an Intel slice does not compile. Fixing it means editing frozen DSP code where the vector path is deliberately bit-exact against the scalar one, which makes it a separate piece of work rather than a build flag.

The three bundles are ad-hoc signed and not notarised. That is a decision rather than an unfinished step. Notarisation requires a Developer ID Application certificate, which is a different certificate type from the Apple Development certificate available here, and obtaining one was not put on this project's critical path. The consequence is accepted: a downloaded copy is quarantined by Gatekeeper until the attribute is cleared, and the install notes say so. A manifest records the commit, the deployment target actually reached, and a hash of the executable inside each bundle, so a reader can verify they have the bytes described.

Download

The instrument that made the five pieces above is here, as the three plugin bundles in one archive.

Eidolon 0.1.0, macOS arm64, 6.4 MB. It contains Eidolon.vst3, Eidolon.component and Eidolon.clap. The accompanying manifest records the commit it was built from, the deployment target the binaries actually carry, and a SHA-256 of the executable inside each bundle, so a reader can confirm they have the bytes described rather than take it on trust.

It needs an Apple Silicon Mac running macOS 11.0 or newer. It will not load on an Intel Mac, for the reason given above.

Copy each bundle to the matching folder in your Library: Eidolon.vst3 to ~/Library/Audio/Plug-Ins/VST3/, Eidolon.component to ~/Library/Audio/Plug-Ins/Components/, and Eidolon.clap to ~/Library/Audio/Plug-Ins/CLAP/. Install only the formats your host uses, or the same instrument appears several times in a host that scans them all.

One step is not optional for this build. Because the bundles are ad-hoc signed rather than notarised, macOS quarantines them on download, and from macOS 10.15 onward a host may load a quarantined plug-in only if it is notarised. The symptom is a claim that the plugin is damaged, which is Gatekeeper's wording for unsigned rather than a statement about the file. Clearing the attribute after copying resolves it:

xattr -dr com.apple.quarantine ~/Library/Audio/Plug-Ins/VST3/Eidolon.vst3

The same command applies to the other two paths. Hosts that load Audio Units out of process are the reliable path for an ad-hoc build; a host that enforces library validation on AU components can refuse one even after the attribute is cleared.

The contract, row by row

The contract set out six rows. Five were met and one was not, and the reason for the sixth is structural rather than a matter of effort.

Rows one through four are the instrument itself and its evidence sits in the earlier weeks. C++ and JUCE proficiency is demonstrated by a codebase that compiles cleanly to every format target with the audio thread kept free of allocation and locks. The three oscillator architectures are each implemented and each has a piece above that plays it. The voice signal path and the modulation system are built, and the matrix is the subject of the fifth piece. The effects chain is built and the third piece plays it as an instrument rather than switching it on.

Row five asked for one source tree producing VST3, AU and CLAP, and for documentation articulating concrete format divergences. Both exist. The divergence log is a standalone document rather than a section of this page, because the useful form of it is a reference a reader consults rather than a narrative.

Row six asked for cross-DAW automation integration over OSC, and it was not undertaken. The contract schedules its activities for Week 9, and the contract closes at Week 8, so the row was cut when the schedule was. Nothing in the codebase links an OSC library or opens a socket, and no week claims otherwise.

Reflection

The thing I did not expect is how much of the difficulty was in measurement rather than implementation. Writing a wavefolder is a bounded problem. Deciding whether the one I wrote sounds wrong, and then finding out why, took far longer and taught me more.

The clearest case is in the first piece. A layer had an artifact I could hear and could not find. Every measurement I ran said it was clean, and every one of those measurements was made on the mono sum. The fault was a stereo decorrelation: the layer's top end was almost entirely out of phase, which a mono sum cannot see by construction. The cause turned out to be two oscillators sitting seven hundredths apart in the stereo field while feeding a wavefolder that derives its gain from the mono sum. I had been measuring the one domain where the problem was invisible, and I only found it by asking what my instrument could not detect rather than by looking harder with the same one.

The second thing I learned is that ear and measurement are not rivals and are not interchangeable. My ear found the artifact. It could not have found the cause. The measurement found the cause and would never have gone looking without the complaint. The pieces on this page went through three rounds of listening, and every round produced a mechanism rather than a preference, which is the argument for keeping both in the loop.

What I would do differently is start the music earlier. Building the instrument component by component with a test after each one is a reasonable way to work and it hid a whole class of problem, because a test plays one note and music plays a phrase. Almost everything I found in the last stretch would have surfaced weeks earlier if I had been trying to write with the thing while building it.

References

  • Pirkle, W. C. Designing Software Synthesizer Plugins in C++: With Audio DSP. 2nd ed., 2021. ISBN 9780367510466. Free companion code and errata at willpirkle.com.
  • Pirkle, W. C. Designing Audio Effect Plugins in C++: For AAX, AU, and VST3 with DSP Theory. 2nd ed., 2019. ISBN 9781138591936. Free companion code and errata at willpirkle.com.
  • JUCE framework. Source and documentation, for AudioProcessor and AudioProcessorValueTreeState. Vendored in this project at a pinned commit.
  • CLAP audio plugin specification. Specification headers, read directly rather than through a wrapper's documentation.
  • clap-juce-extensions. Wrapper producing a CLAP target from a JUCE processor. Vendored at a pinned commit.
  • Catch2. Test framework used for the unit and regression suites. Vendored at a pinned commit.
  • Apple. Notarizing macOS software before distribution. The source for the certificate-type requirement described above, and for the rule that a host may load a quarantined plug-in only if it is notarised.
  • ITU-R. Recommendation BS.1770-4, Algorithms to measure audio programme loudness and true-peak audio level, 2015. Used for the section-level balance decisions described above. Superseded by BS.1770-5 in 2023; the measurements here were made against the fourth revision.
Eidolon · Week 8 of 8 · The Evergreen State College