|
| 1 | +# Compare 2 - Dual Window Comparator |
| 2 | + |
| 3 | +Based on Joranalogue Audio Design Compare 2. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +A dual window comparator that checks if an input voltage falls between two threshold levels (the "window"). Unlike a simple comparator that triggers above a single threshold, a window comparator activates when the input is within a defined range. Includes a logic section combining both comparators' outputs. |
| 8 | + |
| 9 | +## Sources |
| 10 | + |
| 11 | +- [Joranalogue Official Product Page](https://joranalogue.com/products/compare-2) |
| 12 | +- [ModularGrid](https://modulargrid.net/e/joranalogue-audio-design-compare-2) |
| 13 | +- [Waveform Magazine Review](https://waveformmagazine.com/waveform-reviews/joranalogue-compare-2/) |
| 14 | +- [Elevator Sound](https://www.elevatorsound.com/product/joranalogue-compare-2-eurorack-dual-comparator-module/) |
| 15 | +- [Manua.ls Manual](https://www.manua.ls/joranalogue/compare-2/manual) |
| 16 | + |
| 17 | +## Specifications |
| 18 | + |
| 19 | +- **Width**: 8HP |
| 20 | +- **Depth**: 30mm |
| 21 | +- **Power**: +12V: 20mA, -12V: 15mA |
| 22 | + |
| 23 | +## How Window Comparator Works |
| 24 | + |
| 25 | +A window comparator has two thresholds: a lower and an upper. The output activates when the input voltage is between these thresholds (inside the "window"). |
| 26 | + |
| 27 | +``` |
| 28 | +Upper threshold ----+---- |
| 29 | + | | Window (output HIGH when input is here) |
| 30 | +Lower threshold ----+---- |
| 31 | +``` |
| 32 | + |
| 33 | +### Shift and Size Parameters |
| 34 | + |
| 35 | +The window is defined by two parameters: |
| 36 | +- **Shift**: Moves the entire window up or down (sets the center point) |
| 37 | +- **Size**: Sets the distance between upper and lower thresholds (window width) |
| 38 | + |
| 39 | +``` |
| 40 | +Upper threshold = Shift + (Size / 2) |
| 41 | +Lower threshold = Shift - (Size / 2) |
| 42 | +``` |
| 43 | + |
| 44 | +Example with Shift=0V, Size=2V: |
| 45 | +- Upper threshold = +1V |
| 46 | +- Lower threshold = -1V |
| 47 | +- Output HIGH when input is between -1V and +1V |
| 48 | + |
| 49 | +## Controls |
| 50 | + |
| 51 | +### Per Comparator (x2) |
| 52 | + |
| 53 | +| Control | Function | Range | |
| 54 | +|---------|----------|-------| |
| 55 | +| Shift knob | Center of detection window | -5V to +5V (0V at center) | |
| 56 | +| Size knob | Width of detection window | 0V to 10V | |
| 57 | +| Shift CV | Modulates shift | Added to knob | |
| 58 | +| Size CV | Modulates size | Added to knob | |
| 59 | + |
| 60 | +### Inputs |
| 61 | + |
| 62 | +| Input | Function | |
| 63 | +|-------|----------| |
| 64 | +| In (left) | Signal input for comparator 1 | |
| 65 | +| In (right) | Signal input for comparator 2 (normalled from left) | |
| 66 | +| Shift CV (left) | CV for shift 1 (normalled to right) | |
| 67 | +| Size CV (left) | CV for size 1 (normalled to right) | |
| 68 | +| Shift CV (right) | CV for shift 2 | |
| 69 | +| Size CV (right) | CV for size 2 | |
| 70 | + |
| 71 | +### Outputs |
| 72 | + |
| 73 | +| Output | Function | |
| 74 | +|--------|----------| |
| 75 | +| Out (per comparator) | Gate when input is INSIDE window (10V in our implementation) | |
| 76 | +| Not (per comparator) | Gate when input is OUTSIDE window (inverted) | |
| 77 | +| AND | Gate when BOTH comparators' Out are HIGH | |
| 78 | +| OR | Gate when EITHER comparator's Out is HIGH | |
| 79 | +| XOR | Gate when exactly ONE comparator's Out is HIGH | |
| 80 | +| FF (Flip-Flop) | Toggles on rising edge of XOR output | |
| 81 | + |
| 82 | +**Note**: Real Joranalogue outputs +5V gates; our implementation uses 10V to match system standard (0/10V gates). |
| 83 | + |
| 84 | +## LED Behavior |
| 85 | + |
| 86 | +Three-color LEDs per comparator: |
| 87 | +- **Blue** (state=0): Input voltage is BELOW the window |
| 88 | +- **Red** (state=1): Input voltage is ABOVE the window |
| 89 | +- **White** (state=0.5): Input voltage is INSIDE the window |
| 90 | +- **Off** (state=-1): Window size is negative AND signal is within this "negative window" |
| 91 | + |
| 92 | +Logic section has LEDs for AND, OR, XOR, FF outputs (on/off only). |
| 93 | + |
| 94 | +## Algorithm |
| 95 | + |
| 96 | +### Window Comparator Logic |
| 97 | + |
| 98 | +```javascript |
| 99 | +function windowCompare(input, shift, size) { |
| 100 | + const halfSize = size / 2; |
| 101 | + const lower = shift - halfSize; |
| 102 | + const upper = shift + halfSize; |
| 103 | + |
| 104 | + // Inside window = output HIGH |
| 105 | + // Zero size means window is closed - never triggers |
| 106 | + const inside = size > 0 && input >= lower && input <= upper; |
| 107 | + |
| 108 | + return { |
| 109 | + out: inside ? 10 : 0, // 10V gate when inside (system standard) |
| 110 | + not: inside ? 0 : 10, // 10V gate when outside |
| 111 | + state: input < lower ? 'below' : (input > upper ? 'above' : 'inside') |
| 112 | + }; |
| 113 | +} |
| 114 | +``` |
| 115 | + |
| 116 | +### Logic Section |
| 117 | + |
| 118 | +```javascript |
| 119 | +function logic(out1, out2, lastFF) { |
| 120 | + const a = out1 > 0; |
| 121 | + const b = out2 > 0; |
| 122 | + |
| 123 | + return { |
| 124 | + and: (a && b) ? 10 : 0, |
| 125 | + or: (a || b) ? 10 : 0, |
| 126 | + xor: (a !== b) ? 10 : 0, |
| 127 | + ff: lastFF // Toggle on rising edge of out1 |
| 128 | + }; |
| 129 | +} |
| 130 | +``` |
| 131 | + |
| 132 | +### Flip-Flop Behavior |
| 133 | + |
| 134 | +The FF output toggles state on each rising edge of the **XOR** signal (per manual): |
| 135 | +- When XOR goes from LOW to HIGH, FF toggles |
| 136 | +- FF stays at its current state otherwise |
| 137 | +- This means FF toggles when one comparator changes state while the other stays the same |
| 138 | + |
| 139 | +## Implementation Notes |
| 140 | + |
| 141 | +### Normalization |
| 142 | + |
| 143 | +- Left input is normalled to right input (same signal to both comparators if right not patched) |
| 144 | +- Left Shift CV is normalled to right Shift CV |
| 145 | +- Left Size CV is normalled to right Size CV |
| 146 | + |
| 147 | +This allows modulating both comparators with single CV sources. |
| 148 | + |
| 149 | +### Negative Size |
| 150 | + |
| 151 | +When Size is negative (or CV pushes it negative), the window is "inverted" - the upper threshold is below the lower threshold. In this case, no input can be "inside" the window, so Out stays LOW and Not stays HIGH. |
| 152 | + |
| 153 | +### Edge Cases |
| 154 | + |
| 155 | +- Size = 0: Window is infinitely thin, practically never triggers |
| 156 | +- Very large Size: Window encompasses full input range, always triggers |
| 157 | +- Shift at extremes with large Size: Window clips at voltage rails |
| 158 | + |
| 159 | +## Suggested Module Spec |
| 160 | + |
| 161 | +```javascript |
| 162 | +{ |
| 163 | + id: 'cmp2', |
| 164 | + name: 'CMP2', |
| 165 | + hp: 8, |
| 166 | + category: 'utility', |
| 167 | + |
| 168 | + params: { |
| 169 | + shift1: 0, // -5 to +5 |
| 170 | + size1: 5, // 0 to 10 |
| 171 | + shift2: 0, |
| 172 | + size2: 5 |
| 173 | + }, |
| 174 | + |
| 175 | + inputs: { |
| 176 | + in1: 'cv', |
| 177 | + in2: 'cv', // normalled from in1 |
| 178 | + shiftCV1: 'cv', |
| 179 | + sizeCV1: 'cv', |
| 180 | + shiftCV2: 'cv', // normalled from shiftCV1 |
| 181 | + sizeCV2: 'cv' // normalled from sizeCV1 |
| 182 | + }, |
| 183 | + |
| 184 | + outputs: { |
| 185 | + out1: 'gate', |
| 186 | + not1: 'gate', |
| 187 | + out2: 'gate', |
| 188 | + not2: 'gate', |
| 189 | + and: 'gate', |
| 190 | + or: 'gate', |
| 191 | + xor: 'gate', |
| 192 | + ff: 'gate' |
| 193 | + }, |
| 194 | + |
| 195 | + leds: ['state1', 'state2', 'and', 'or', 'xor', 'ff'] |
| 196 | +} |
| 197 | +``` |
| 198 | + |
| 199 | +## Patch Ideas |
| 200 | + |
| 201 | +1. **Rhythm from LFO**: Feed øchd into Compare 2, adjust window to extract gates at specific parts of the waveform |
| 202 | +2. **Pulse width modulation**: Feed audio into input, adjust Size to change duty cycle of output pulses |
| 203 | +3. **Frequency doubler**: Small window at zero crossing doubles trigger rate |
| 204 | +4. **Complex gates**: Use logic outputs to combine two rhythm patterns |
| 205 | +5. **Voltage-controlled swing**: Modulate Shift with slow LFO to vary when gates fire |
| 206 | +6. **Audio-rate digital ring mod**: Feed two audio signals, use XOR output |
0 commit comments