theallelectricsmartgrid

The Encoder System

The Smart Grid One relies entirely on a software-defined parameter system. All “knob” state lives in software, allowing for complete recall, deep modulation, macro control (gestures), and A/B scene morphing.

The core implementation spans private/src/Encoder.hpp, private/src/EncoderBank.hpp, and private/src/EncoderBankBank.hpp.

Ownership now lives in EncoderBankBank: it owns a flat array of BankedEncoderCell instances indexed by SmartGridOneEncoders::Param. Each EncoderBankInternal starts with null base cells and receives raw pointers through PlaceEncoder(...). This makes encoder swapping explicit and keeps base cells empty until they are placed.

Serialization follows ownership: EncoderBankBank::ToJSON() iterates the full encoder array and writes each named parameter, and FromJSON() does the inverse by looking up each name and updating the encoder state.

Base Structure: Tracks and Voices

To accommodate polyphony and quadraphonic effects, the parameter system is structured hierarchically.

Crucially, the base value of a knob is identical for all voices within a track. However, modulation and gestures can apply different offsets to each voice within that track.

Base Encoders vs. Banked Encoders

Deep Modulation

Every BankedEncoderCell can act as a modulation destination.

Gestures (Macros)

Gestures are macro controls mapped to physical analog inputs (Like sliders and joysticks).

Scene Morphing

The entire state of all encoders (base values, modulation depths, and gesture targets) is duplicated across two Scenes (SceneManager.hpp).

UI State and Parameter Slew

Frequency-Dependent Quad Parameters

The Partial Machine uses a Quad bank differently from Delay and Reverb. Its four lanes are interpreted as anchors for FrequencyDependentParameter, not just four speaker channels. If all four lanes share the same base value, the parameter behaves like a normal scalar. If modulation produces different values per lane, each spectral partial interpolates a unique value from its frequency, allowing the same knob to create frequency-dependent attack, decay, density, bandwidth, panning, unison, pitch, and volume behavior.

See Partial Machine for the DSP-side mapping.

Machine-Specific Parameters

Each parameter in the Voice banks can specify which source and filter machines it applies to via bit vectors (MachineFlags). Parameters are defined in ForEachSmartGridOneParam.hpp with sourceMachines and filterMachines arguments (e.g. MachineFlags::x_dualWaveShapingVCOOnly for parameters that only affect the Dual Wave Shaping VCO source).

When the user selects a different source machine (e.g. Thru) or filter machine, UpdateEncodersForMachine() runs and swaps the actual encoder pointers in the grid. Parameters that do not apply are removed by placing nullptr in those positions, which leaves the cell empty and disconnected. This keeps the encoder grid relevant to the active machine while preserving encoder state in the owner array. The update is triggered on machine change (config page) and track change (since each track can have different machines).