TruthCat4
TruthCat4 is a truth-table rhythm generator based on chained NOR/NAND Boolean logic. It clocks through the rows of a 5-bit binary truth table and evaluates the expression A op₀ B op₁ C op₂ D op₃ E to produce gate outputs. What makes it unusual is that the same expression can be parenthesised 14 different ways (the Catalan number C₄ = 14), and each bracketing produces a different rhythm from the same inputs. CV1 selects the NOR/NAND operator mix; CV2 selects the bracketing.
Concept
The truth table
The applet maintains a 5-bit step counter. On each clock, the counter value is decoded directly into five Boolean inputs:
Counter value A B C D E
0 = 00000 0 0 0 0 0
1 = 00001 0 0 0 0 1
2 = 00010 0 0 0 1 0
3 = 00011 0 0 0 1 1
...
31 = 11111 1 1 1 1 1
A = bit 4, B = bit 3, C = bit 2, D = bit 1, E = bit 0. The full 32-step cycle visits every combination of five bits exactly once, in binary order.
NOR and NAND
The two operators are:
NOR: X NOR Y = NOT (X OR Y) — true only when BOTH inputs are false (0 NOR 0 = 1)
NAND: X NAND Y = NOT (X AND Y) — true unless BOTH inputs are true (1 NAND 1 = 0)
NOR fires on silence; NAND fires on everything except full density. Both are universal gates — any Boolean function can be built from either one alone.
The four operator slots
The expression has four operator positions:
A op₀ B op₁ C op₂ D op₃ E
Each slot is independently NOR or NAND, giving 16 operator patterns. These are ordered by how many NAND operators they contain (0 through 4). More NANDs generally produces denser rhythms because NAND fires more often; pure NOR (OOOO) produces sparser output.
The 14 parse trees
Without parentheses, A op B op C op D op E is ambiguous. With four binary operators and five operands, there are exactly 14 distinct ways to fully parenthesise the expression — this is the fourth Catalan number (C₄ = 14). Each bracketing assigns a different root operator and different sub-expressions, which changes the result even when the inputs and operators are identical.
This means from a single truth-table row with a single operator pattern you can extract 14 different Boolean results — one per parse tree.
The 16 operator patterns × 14 parse trees = 224 distinct rhythms that OUT1 can generate, all from the same deterministic counter sequence.
A Worked Example
Let’s trace step 6 (counter = 6 = 00110, so A=0, B=0, C=1, D=1, E=0) with operator pattern 0 (OOOO = all NOR) through two different parse trees.
Tree 1 — right-associative: A NOR (B NOR (C NOR (D NOR E)))
D NOR E = 1 NOR 0 = NOT(1 OR 0) = NOT(1) = 0
C NOR 0 = 1 NOR 0 = NOT(1 OR 0) = NOT(1) = 0
B NOR 0 = 0 NOR 0 = NOT(0 OR 0) = NOT(0) = 1
A NOR 1 = 0 NOR 1 = NOT(0 OR 1) = NOT(1) = 0 → OUT1 = LOW
Tree 6 — balanced split: (A NOR B) NOR ((C NOR D) NOR E)
A NOR B = 0 NOR 0 = 1
C NOR D = 1 NOR 1 = NOT(1 OR 1) = NOT(1) = 0
0 NOR E = 0 NOR 0 = 1
1 NOR 1 = NOT(1 OR 1) = NOT(1) = 0 → OUT1 = LOW
Tree 9 — left-spine: (((A NOR B) NOR C) NOR D) NOR E
A NOR B = 0 NOR 0 = 1
1 NOR C = 1 NOR 1 = 0
0 NOR D = 0 NOR 1 = 0
0 NOR E = 0 NOR 0 = 1 → OUT1 = HIGH
Same step, same operators, three different results — solely from the choice of bracketing.
Operator Patterns
The four operator slots correspond to the four positions in the expression:
A op0 B op1 C op2 D op3 E
Each slot is independently NOR or NAND. Displayed as a four-character string where O = NOR and A = NAND (avoiding N which is ambiguous). For example:
OOOO= all NOR — sparsest; fires only when all relevant inputs are falseAAAA= all NAND — densest; fires unless all relevant inputs are trueAOOA= NAND at the outer positions, NOR in the middle
The 16 patterns are ordered by increasing NAND count:
| Index | Pattern | NANDs |
|---|---|---|
| 0 | OOOO | 0 |
| 1 | AOOO | 1 |
| 2 | OAOO | 1 |
| 3 | OOAO | 1 |
| 4 | OOOA | 1 |
| 5 | AAOO | 2 |
| 6 | AOAO | 2 |
| 7 | AOOA | 2 |
| 8 | OAAO | 2 |
| 9 | OAOA | 2 |
| 10 | OOAA | 2 |
| 11 | AAAO | 3 |
| 12 | AAOA | 3 |
| 13 | AOAA | 3 |
| 14 | OAAA | 3 |
| 15 | AAAA | 4 |
Higher CV on CV1 pushes toward more NAND-heavy operator patterns. When Ops is set to CV, CV1 maps directly across all 16 patterns.
Parse Trees (Bracketings)
The 14 parse trees correspond to the 14 ways of fully parenthesising a chain of five values. The operator indices always refer to the original left-to-right positions in the chain (op₀ = between A and B, op₁ = between B and C, etc.) regardless of how the expression is grouped.
| Tree | Expression |
|---|---|
| 1 | A op (B op (C op (D op E))) — right-associative spine |
| 2 | A op (B op ((C op D) op E)) |
| 3 | A op ((B op C) op (D op E)) |
| 4 | A op ((B op (C op D)) op E) |
| 5 | A op (((B op C) op D) op E) |
| 6 | (A op B) op (C op (D op E)) |
| 7 | (A op B) op ((C op D) op E) — balanced binary split |
| 8 | (A op (B op C)) op (D op E) |
| 9 | ((A op B) op C) op (D op E) |
| 10 | (A op (B op (C op D))) op E |
| 11 | (A op ((B op C) op D)) op E |
| 12 | ((A op B) op (C op D)) op E |
| 13 | ((A op (B op C)) op D) op E |
| 14 | (((A op B) op C) op D) op E — left-associative spine |
Trees 1 and 14 are the two extremes: fully right-associative (A is evaluated last) and fully left-associative (E is evaluated last). Trees 7 and 12 are the most balanced, splitting the five operands into roughly equal sub-groups.
The positional importance of each operator slot shifts dramatically between trees. In trees 1–5, op₀ is the root and determines the final output. In trees 10–14, op₃ is the root. In trees 6–7, op₁ is the root. This means changing a single operator slot from NOR to NAND has a completely different effect depending on which tree is active — it might change nearly every step result, or barely affect anything at all.
I/O
| 1 (left) | 2 (right) | |
|---|---|---|
| TRIG | Clock — advance truth-table counter | TR2 — function depends on TR2 Mode setting |
| CV IN | Operator pattern select / CV ctrl | Parse tree select / CV ctrl |
| OUT | Main gate — Boolean result of current step | Related gate — derived from main result per OUT2 Relation setting |
How the Truth Table Works
The applet maintains an internal step counter. On each clock:
- The counter value supplies the five Boolean inputs — A = bit 4, B = bit 3, C = bit 2, D = bit 1, E = bit 0.
- The selected NOR/NAND operator pattern and parse tree determine the Boolean result.
- OUT1 fires a trigger when the result is true. OUT2 fires a trigger based on the OUT2 Relation mode.
- The counter increments and wraps at the configured step length.
At the default 32-step length, all binary combinations from 00000 to 11111 are visited in order, giving a complete deterministic rhythm cycle.
For shorter lengths the counter wraps before reaching 11111, so only a subset of the truth-table rows are used — this produces shorter rhythmic cycles with different densities.
Note: the outputs fire trigger pulses, not gates. If two adjacent steps both evaluate true, both fire independently — you get two separate triggers rather than one long held gate.
Controls
Five parameters, navigated by the encoder (rotate to move cursor, press to enter edit, press again to exit). The cursor order matches the visual layout, top to bottom, left to right:
| Cursor | Parameter | Range | Notes |
|---|---|---|---|
| Ops | Operator pattern | 0–15, or CV | NOR/NAND mix across the four slots |
| Steps | Sequence length | 3, 4, 5, 6, 7, 8, 10, 12, 15, 16, 20, 24, 32 | Default 32 |
| Tree | Parse tree | 1–14 (internal 0–13), or CV | Bracketing of the expression |
| TR2 Mode | TR2 jack function | RST / HLD / TrAdv / OpAdv | See TR2 Modes below |
| OUT2 | OUT2 relation | NXT / NOT / AND / OR / XOR / FLP | See OUT2 Relation below |
TR2 Modes
| Mode | Display | Behaviour |
|---|---|---|
| Reset | RST | Rising edge on TR2 resets the step counter to 0 |
| Hold | HLD | While TR2 is high, TR1 clock pulses do not advance the counter; outputs hold their current values |
| Advance Tree | TrAdv | Rising edge on TR2 increments the Tree setting (wraps 14 → 1) |
| Advance Ops | OpAdv | Rising edge on TR2 increments the Ops setting (wraps 15 → 0) |
Default: RST.
In TrAdv and OpAdv modes, TR2 modifies the base manual setting. If the setting is on CV, advancing wraps through the fixed pattern values only — the CV ctrl slot is not visited by advance.
OUT2 Relation
OUT2 generates a second gate based on the main result and the selected relation. The “adjacent tree” modes compare the current step with the same step evaluated using the next parse tree ((tree + 1) mod 14).
| Mode | Display | OUT2 fires when… |
|---|---|---|
| NXT | NXT | The same step evaluated with the next parse tree would be true |
| NOT | NOT | The current main result is false |
| AND NXT | AND | Both current tree and next tree evaluate true for this step |
| OR NXT | OR | Either current or next tree evaluates true for this step |
| XOR NXT | XOR | Current and next tree results differ for this step |
| FLIP OPS | FLP | Same step and tree but all operators inverted (NOR↔NAND) |
Default: XOR. The XOR mode fires whenever the current and next-tree interpretations of the same step disagree — this is the “ambiguous” reading. It produces a sparser, accented pattern that fires at the points where adjacent parse trees diverge most.
FLIP OPS gives the complementary reading under inverted logic. For mixed operator patterns it creates a contrapuntal rhythm that tends toward the opposite density to OUT1.
Why the Trees Sound Different
The relationship between parse trees and rhythm density is non-obvious but musically rich. A few patterns worth knowing:
Right-spine vs. left-spine at all NOR: Tree 1 (right-associative) evaluates A last. The root operator (op₀) compares A against a possibly-complex sub-expression. If that sub-expression is true, the root NOR fires false. Tree 14 (left-associative) evaluates the opposite way — E is evaluated last, and op₃ determines the final gate. Because NOR fires only when both sides are false, the “shape” of sub-tree trueness cascades differently through each structure.
Balanced trees tend toward low density at all NOR: Trees 7 and 12 split the inputs symmetrically. With all NOR, each sub-expression must be entirely false for its parent to be true. Symmetric splits mean two independent sub-trees must both evaluate false simultaneously — which happens less often than a single chain collapsing.
Single-NAND patterns create asymmetric rhythms: With op₀ = NAND and the rest NOR (pattern 1), tree 1 has op₀ as its root — so the final gate is a NAND. This fires unless the right sub-tree is true AND A is true. Trees 10–14 have op₃ as root (NOR in this pattern), so the NAND at op₀ is buried deep in the expression and only occasionally reaches the output.
Display
The display in context (top-right quadrant example):
↓NOR ↑NAND ← context help (when Ops cursor active)
───────────────
Op: ↓ ↓ ↑ ↓ ← 4 arrow icons: ↓=NOR, ↑=NAND
07/32 T:09 ← current step / length | tree (1-indexed)
RST D:XOR ← TR2 mode | Output2-label:OUT2-mode
C ▌ ▌▌ ▌ ▌▌ ← OUT1 history (16 steps, output letter = C/E/G)
D ▌▌ ▌ ▌▌ ▌ ▌ ← OUT2 history (16 steps, output letter = D/F/H)
The output letters on the history rows adapt to hemisphere position: top-left uses A/B, top-right uses C/D, bottom-left uses E/F, bottom-right uses G/H.
- Op — 4 arrow icons (↓ = NOR, ↑ = NAND); shows “CV N” (CV + live pattern number 1–16) when under CV control
- T — current parse tree number (1-indexed display); when under CV control, the live tree number replaces the “T:” label entirely
- St — current step (1-indexed) / total steps
- RST / HLD / TrAdv / OpAdv — active TR2 mode
- O2 — active OUT2 relation
- Upper history row — scrolling 16-step gate history for OUT1 (filled bar = trigger fired)
- Lower history row — scrolling 16-step gate history for OUT2
The cursor underline moves between the five editable parameters. When the Ops, TR2, or OUT2 cursor is active, the applet name is replaced with context help text.
Tips
- All NOR, tree 1 at 32 steps: This is the simplest case — a right-associative NOR chain. Use it as a reference to learn how the truth table maps to rhythm before exploring other settings. Step 0 (all false) gives NOR(F, NOR(F, NOR(F, NOR(F, F)))) = NOR(F,T) = F — you can trace the whole cycle by hand.
- Steps = 16 as a musical default: 16 gives a clean one-bar cycle at most clock divisions and visits the lower half of the truth table — enough variation without the full 32 steps.
- CV1 and CV2 sweep: Sweeping both CVs simultaneously morphs through the full 224-rhythm space continuously. At low CV, NOR-heavy short-cycle patterns; at high CV, NAND-heavy and differently-bracketed interpretations.
- TrAdv + clock divider: Patch a divided version of your master clock into TR2 in TrAdv mode to automatically cycle through parse trees at a musical rate — e.g. change tree every 4 bars.
- XOR for accent: The default OUT2 mode fires whenever the current and next-tree readings of the same step disagree. This tends to produce a sparser, accented pattern useful as a hi-hat or rimshot layered over the main gate.
- FLIP OPS for counterpoint: OUT2 in FLIP OPS mode gives you two rhythms that are logically opposed. These tend to interlock without completely cancelling — NOR-heavy patterns produce sparser rhythms, NAND-heavy produce denser ones, and FLIP makes OUT2 the reverse of OUT1’s operator logic.
- Hold mode for phrase locks: TR2 in HLD mode lets you freeze the counter mid-phrase while keeping a gate high, then release to continue. Useful for stutter effects or to hold a specific row of the truth table while other modulation changes.
- Short step lengths for dense rhythms: Steps = 3 or 4 gives very rapid cycling through a small set of truth-table rows. Different trees produce wildly different rhythms from these short windows because only a handful of input combinations are visited.
- Matching parse trees to operator density: Tree 7 (balanced split) with high NAND density creates a characteristic “double trigger” rhythm because both halves of the split can independently evaluate true. Tree 1 with high NOR density creates long gaps broken by single triggers — the right-spine structure means any true value anywhere in the chain collapses the NOR cascade.
- Predictable reset points: Because TruthCat4 is fully deterministic, a TR2 reset always returns to the same rhythm. Use RST mode to sync to other sequencers or to drop into a known groove at a section boundary.
Credits
TruthCat4 by Andy Jenkinson / uglifruit, developed with Claude Code (Anthropic).