theallelectricsmartgrid

LameJuis

LameJuis is an esoteric, layered sequencer that turns the six gate bits from the Theory of Time into polyphonic pitch. The implementation is in private/src/LameJuis.hpp, private/src/HarmonicSheaf.hpp, and private/src/IndexArp.hpp; the Nonagon wires the six time-loop gates into LameJuis and uses one LameJuis lane per trio (three voices share one lane’s pitch logic).

For fixed accepted configuration, the six gate bits x in I⁶ determine the set of available notes. The selected note also depends on the index arp’s choice argument, derived from the loop-cycle position. Modulating the Theory of Time therefore moves both the gate bits and the arp through this polyphonic process. Live loop-rhythm edits are held until the edited loop’s next tick.


1. The map M and the sheaf F^M_x(U)

Let M : I⁶ → pitch. Here “pitch” is represented as volt-per-octave (or equivalently log₂ of a just-intonation ratio). Composing M with the Theory of Time would give a single melody; we want many interlocking melodies, so we introduce a lens and a sheaf.


2. Trios and lens assignment

There are 9 voices in 3 trios of 3 voices each. Each trio is assigned one LameJuis lane (there are 3 lanes, one per trio). The performer assigns a lens U to that lane via the co-mute UI: which of the 6 dimensions are “read” vs “co-mute”. At each time x in I⁶, the trio must pick a note from F^M_x(U). That choice is made by the index arp (see below) and a section choice strategy.


3. Index arp: clock, reset, rhythm, and range

The index arp (IndexArp, used per voice inside NonagonIndexArp) turns the signed loop-cycle position of a chosen clock loop into a choice value that is then used to pick a note from F^M_x(U).

3.1 Clock and reset

3.2 Gate sequencer (rhythm)

This per-voice arp rhythm is separate from the per-loop Theory of Time rhythm that provides each LameJuis input bit. A loop tick clocks the arp even if that loop’s gate value repeats; editing the loop rhythm does not create an extra tick.

3.3 Point in range


4. Section choice strategies

Once we have the set F^M_x(U) (all M(y) for y ~_U x), we select a note from it using a section choice strategy (HarmonicSheaf::SectionChoiceStrategy) with the index-arp output as m_choiceValue.

Each lane has a strategy (toggled in the UI) and an optional base strategy (defaults to None). The Lane::Chooser first runs the base strategy to get a base section value, then adds that to m_choiceValue and runs the main strategy. This two-stage approach allows composing strategies.

The available strategies (HarmonicSheaf::SectionChooser):

The result is a single pitch (volt-per-octave) per voice; that pitch is then used by the rest of the synth (e.g. V/O output, possible octave shift from the UI). Whether a trigger is emitted (note on) for that pitch is decided by the Multi-Phasor Gate (pitch-changed vs sub-trigger, mutes, interrupt).


5. The map M: logic operations and accumulators

M(x) is not a single ratio; it is computed by a matrix of logic operations feeding accumulators, whose outputs are combined additively in volt-per-octave (i.e. multiplicatively as ratios).

5.1 Structure

5.2 Logic operations

Each LogicOperation (the “simple functions” in the user’s description) does the following:

An operation owns its six matrix elements, active and inverted masks, RHS table, and output target. Its m_countTotal counts accepted non-muted input bits. An accumulator owns an interval; each section’s m_total[acc] counts active operation rows targeting it. An empty row contributes to no accumulator, regardless of its stored target.

So M(x) is built from up to 6 active boolean functions; each contributes 0 or 1 to one of 3 accumulators; the accumulators have fixed intervals (octave, fifth, third, etc.); and the final pitch is the sum in V/O of (interval × exponent) per accumulator.

5.3 Extra Timbre Modulators

In addition to pitch, the logic matrix provides extra timbre modulators. For each of the 3 accumulators, the matrix computes the ratio of operations that evaluated to high versus the total number of active operations targeting that accumulator (m_high[acc] / m_total[acc]). An accumulator with no active rows yields zero. The Nonagon captures these three values in [0, 1] as each voice’s m_extraTimbre when that voice triggers and holds them until its next trigger. These can be routed to DSP parameters (like filter cutoff or wavefolder depth) to provide rhythmic modulation that is perfectly synchronized with the pitch sequence.


6. Edit acceptance, cache updates, and note timing

The Nonagon supplies each input’s gate value and a separate m_ticked flag from AnyTick(i). A modulated loop crossing counts even when consecutive rhythm steps have the same gate value.

A channel selects a new section only on its existing read flag or arp trigger. Section equality compares both m_high and m_total for every accumulator; the selected result also compares evaluated pitch. Thus a denominator-only change can request another note at the same pitch, on the next permitted channel update. This includes zero-high sections such as 0/4 and 0/3, even though both timbre ratios are zero. Cache rebuilding and equality checks do not add reads or move them off the rhythmic grid. The existing trigger, mute, and interrupt controls still determine whether a requested note starts.

7. Statelessness

Because:

the pitch-selection mapping is deterministic for a fixed accepted configuration and choice argument. Pending edits, accepted configuration, and held channel selections are stateful as described above. Live Theory of Time rhythm edits take effect only at that loop’s next modulated tick, so the output gate is explicitly held between ticks. Modulating the Theory of Time (e.g. phase modulation, different clock/reset, or different topology) only changes x and the index over time; the logic remains consistent.