Files
biggy 05fd6440bd docs: add agent guidance and historical audit report
Add root AGENT.md with project conventions, build verification steps,
source layout, style rules, and real-time/concurrency requirements.
Add per-module AGENT.md files for each existing and proposed source
subdirectory. Add AUDIT_REPORT.md as a historical Phase 1 snapshot
documenting memory management, error handling, concurrency model,
naming conventions, and anti-pattern catalog.
2026-09-09 13:25:02 +02:00

2.0 KiB

synth module

This directory contains guidance. All files listed below remain in the parent Source/ directory. The preparation rules below are requirements for changes, not a claim that lazy wavetable allocation has already been fixed.

  • Wavetable.h, Wavetable.cpp
  • Oscillator.h, Oscillator.cpp
  • SubOscillator.h, SubOscillator.cpp
  • NoiseOscillator.h, NoiseOscillator.cpp
  • Envelope.h, Envelope.cpp
  • LFO.h, LFO.cpp
  • Filter.h, Filter.cpp
  • FilterBank.h, FilterBank.cpp
  • SynthVoice.h, SynthVoice.cpp

Rules

  • Use noexcept on every per-sample DSP path and cheap getter.
  • Use std::array for fixed-size state and std::vector<float> for delay lines and table buffers.
  • Size every buffer and delay line in prepare(), never in process or render.
  • Clamp filter and envelope state so extreme settings cannot produce NaN or inf.
  • Use juce::MathConstants<T>::pi and twoPi instead of raw pi literals.
  • Use (size_t) casts when indexing containers with int loop variables.
  • Pass global per-block state into voices as a const RenderContext&.
  • Never allocate memory in the audio path.

IF-THEN

  • IF a wavetable is read in the render path THEN build all tables in prepare() by calling WavetableLibrary::prebuild() before the first block.
  • IF a parameter is read every block THEN snapshot it into a struct (OscParams, RenderContext) instead of reading the APVTS per sample.

Examples

// BAD: lazy table build reached from the render path allocates on the audio thread
const Wavetable& wt = library.getTable (wave);
// GOOD: build once at prepare time, then only read const references
library.prebuild();                 // in prepareToPlay
const Wavetable& wt = library.getTable (wave);   // lookup, no allocation
// BAD: raw pi literal duplicated across files
const double step = 6.28318530717958647692 * freq / sr;
// GOOD: single source
const double step = juce::MathConstants<double>::twoPi * freq / sr;

This file overrides /AGENT.md where they conflict.