Skip to content

Commit 2469c12

Browse files
more modules
1 parent d965a45 commit 2469c12

14 files changed

Lines changed: 925 additions & 5 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ Browser-based Eurorack modular synthesizer emulator. Patch virtual modules toget
2525
| ARP | Arpeggiator with chord patterns |
2626
| SEQ | 8-step CV/gate sequencer with direction modes |
2727
| EUCLID | Euclidean rhythm generator (evenly distributed triggers) |
28+
| LOGIC | Boolean gate operator (AND/OR) |
29+
| MULT | 2-in, 6-out signal splitter |
2830
| ADSR | Envelope generator |
2931

3032
### Processors

claude.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ Software Eurorack modular synthesizer. Modules pass voltages; sound only at outp
5050

5151
**Self-contained modules**: Each module folder contains DSP + UI definition in one file. Modules export metadata, `createDSP()` factory, and declarative `ui` config.
5252

53-
**Available modules**: `clk` (clock) · `div` (divider) · `lfo` · `nse` (noise) · `sh` (sample&hold) · `quant` (quantizer) · `arp` (arpeggiator) · `seq` (sequencer) · `euclid` (euclidean rhythm) · `vco` · `vcf` · `adsr` · `vca` · `atten` (attenuverter) · `slew` · `mix` · `dly` (delay) · `verb` (reverb) · `kick` · `snare` · `hat` · `scope` · `out`
53+
**Available modules**: `clk` (clock) · `div` (divider) · `lfo` · `nse` (noise) · `sh` (sample&hold) · `quant` (quantizer) · `arp` (arpeggiator) · `seq` (sequencer) · `euclid` (euclidean rhythm) · `logic` (AND/OR gates) · `mult` (signal splitter) · `vco` · `vcf` · `adsr` · `vca` · `atten` (attenuverter) · `slew` · `mix` · `dly` (delay) · `verb` (reverb) · `kick` · `snare` · `hat` · `scope` · `out`
5454

5555
## Project Structure
5656

@@ -80,7 +80,7 @@ tests/dsp/{module}.test.js # Module tests
8080

8181
Processing order is computed dynamically from cable connections using `computeProcessOrder()`:
8282
- Sources process before destinations (topological sort)
83-
- Ties broken by `MODULE_ORDER`: `clk → div → lfo → nse → sh → quant → arp → seq → euclid → vco → vcf → adsr → vca → atten → slew → mix → dly → verb → kick → snare → hat → scope → out`
83+
- Ties broken by `MODULE_ORDER`: `clk → div → lfo → nse → sh → quant → arp → seq → euclid → logic → mult → vco → vcf → adsr → vca → atten → slew → mix → dly → verb → kick → snare → hat → scope → out`
8484
- Cycles (feedback patches) fall back to `MODULE_ORDER`
8585
- Recomputed when cables or modules change
8686

@@ -230,19 +230,21 @@ export default {
230230
| Module | Inputs | Outputs |
231231
|--------|--------|---------|
232232
| clk | — | clock |
233-
| div | clock | div2, div4, div8, div16, div32 |
233+
| div | clock, rate1CV, rate2CV | out1, out2 |
234234
| lfo | rateCV, waveCV, reset | primary, secondary |
235235
| nse | — | white, pink |
236236
| sh | in1, in2, trig1, trig2 | out1, out2 |
237237
| quant | cvIn, trigIn | cvOut, trigOut |
238238
| arp | clock, cvIn, gateIn, hold, pause | cvOut, gateOut |
239239
| seq | clock, reset | cv, gate |
240240
| euclid | clock, reset, lenCV, hitsCV | trig |
241+
| logic | in1, in2 | and, or |
242+
| mult | in1, in2 | out1a, out1b, out1c, out2a, out2b, out2c |
241243
| vco | vOct, fm, pwm, sync | triangle, ramp, pulse |
242244
| vcf | audio, cutoffCV, resCV | lp, bp, hp |
243245
| adsr | gate, retrig | env |
244246
| vca | ch1In, ch2In, ch1CV, ch2CV | ch1Out, ch2Out |
245-
| mix | ch1, ch2, ch3, ch4 | main |
247+
| mix | in1, in2, in3, in4 | out |
246248
| atten | in1, in2 | out1, out2 |
247249
| slew | in1, cv1, in2, cv2 | out1, out2 |
248250
| dly | inL, inR, timeCV, feedbackCV | outL, outR |

node_modules/.vite/vitest/results.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

research/modules/logic.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# 2hp Logic Module Research
2+
3+
## Overview
4+
Logic is a 2-channel boolean gate operator providing AND and OR logic operations for gate/trigger signals.
5+
6+
## Sources
7+
- [2hp Official](https://www.twohp.com/modules/p/logic)
8+
- [ModularGrid](https://modulargrid.net/e/2hp-logic)
9+
- [Elevator Sound](https://www.elevatorsound.com/product/2hp-logic-and-or/)
10+
11+
## Specifications
12+
- Width: 2hp
13+
- Depth: 42-45mm
14+
- Power: 35mA +12V, 3mA -12V
15+
16+
## Panel Layout (top to bottom)
17+
- IN 1 - Input jack for channel 1
18+
- IN 2 - Input jack for channel 2
19+
- AND - Output jack (high when both inputs high)
20+
- OR - Output jack (high when either input high)
21+
22+
## Functionality
23+
24+
### AND Output
25+
- High (10V) when BOTH IN 1 AND IN 2 are high
26+
- Low (0V) otherwise
27+
- Use case: Gating rhythmic events - only triggers when two patterns coincide
28+
29+
### OR Output
30+
- High (10V) when EITHER IN 1 OR IN 2 (or both) are high
31+
- Low (0V) when both inputs are low
32+
- Use case: Combining two rhythmic patterns into one stream
33+
34+
### Normalling
35+
- Channel 1 normals to channel 2 when no cable is present in IN 1
36+
- This means with only IN 2 patched:
37+
- AND output = IN 2 (since IN 1 copies IN 2)
38+
- OR output = IN 2 (same signal ORed with itself)
39+
40+
## Voltage Thresholds
41+
Standard Eurorack gate threshold: signals >= 1V considered HIGH
42+
43+
## Implementation Notes
44+
45+
### DSP Approach
46+
- Sample-by-sample boolean logic
47+
- No edge detection needed - just compare voltage levels
48+
- Output full gate voltage (10V) or 0V
49+
50+
### Considerations
51+
- Should handle both gates (sustained high) and triggers (brief pulses)
52+
- No smoothing/slew needed - instant response
53+
- LED indicators for AND and OR outputs
54+
55+
## Use Cases
56+
1. **Rhythmic gating**: AND two clock divisions to create polyrhythms
57+
2. **Pattern combination**: OR euclidean + sequencer gates for complex rhythms
58+
3. **Conditional triggers**: AND a gate with clock for gated rhythms
59+
4. **Event merging**: OR multiple trigger sources to single destination

research/modules/mult.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# 2hp Mult Module Research
2+
3+
## Overview
4+
Passive 2-input, 6-output signal splitter. Duplicates CV or audio signals to multiple destinations.
5+
6+
## Sources
7+
- [2hp Official](https://www.twohp.com/modules/p/mult)
8+
- [ModularGrid](https://modulargrid.net/e/2hp-mult)
9+
10+
## Specifications
11+
- Width: 2hp
12+
- Depth: 15mm
13+
- Power: Passive (no power required)
14+
- Price: $34
15+
16+
## Panel Layout (top to bottom)
17+
- IN 1 - Input jack for channel 1
18+
- OUT 1A - Output 1 (copy of IN 1)
19+
- OUT 1B - Output 2 (copy of IN 1)
20+
- OUT 1C - Output 3 (copy of IN 1)
21+
- IN 2 - Input jack for channel 2
22+
- OUT 2A - Output 1 (copy of IN 2)
23+
- OUT 2B - Output 2 (copy of IN 2)
24+
- OUT 2C - Output 3 (copy of IN 2)
25+
26+
## Functionality
27+
28+
### Signal Splitting
29+
- Each input is copied to its 3 corresponding outputs
30+
- No attenuation, buffering, or modification - pure signal copy
31+
- Works with any signal type: audio, CV, gates, triggers
32+
33+
### Normalling
34+
- When IN 2 has no cable, it receives IN 1's signal
35+
- This allows a single input to be split 6 ways
36+
- With both inputs patched, operates as two independent 1-to-3 mults
37+
38+
## Implementation Notes
39+
40+
### DSP Approach
41+
- Simple buffer copy operation
42+
- Each output = corresponding input
43+
- Handle normalling: if in2 unpatched, use in1's signal for channel 2
44+
45+
### Considerations
46+
- Since hardware is passive, our implementation should be transparent
47+
- No processing, filtering, or coloring of signal
48+
- LED indicators could show signal presence (even though hardware has none)
49+
50+
## Use Cases
51+
1. **CV distribution**: Send one LFO to modulate multiple parameters
52+
2. **Gate splitting**: Trigger multiple envelopes from one gate
53+
3. **Audio splitting**: Send oscillator to multiple filters/effects
54+
4. **Clock distribution**: Fan out clock to multiple sequencers

src/js/config/patches/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import testArpeggiator from './test-arpeggiator.js';
2121
import testScopeSinewave from './test-scope-sinewave.js';
2222
import testSequencer from './test-sequencer.js';
2323
import testEuclid from './test-euclid.js';
24+
import testLogic from './test-logic.js';
25+
import testMult from './test-mult.js';
2426
import testDelay from './test-delay.js';
2527
import testReverb from './test-reverb.js';
2628
import testAttenuverter from './test-attenuverter.js';
@@ -66,6 +68,8 @@ export const FACTORY_PATCHES = {
6668
[testScopeSinewave.name]: testScopeSinewave,
6769
[testSequencer.name]: testSequencer,
6870
[testEuclid.name]: testEuclid,
71+
[testLogic.name]: testLogic,
72+
[testMult.name]: testMult,
6973
[testDelay.name]: testDelay,
7074
[testReverb.name]: testReverb,
7175
[testAttenuverter.name]: testAttenuverter,
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/**
2+
* Test - Logic Gates
3+
*
4+
* Demonstrates AND/OR logic operations:
5+
* - Two euclidean patterns feed into Logic
6+
* - AND output triggers kick (only when both patterns hit)
7+
* - OR output triggers snare (when either pattern hits)
8+
*
9+
* Try adjusting the euclidean patterns to hear different rhythms.
10+
*/
11+
export default {
12+
name: 'Test - Logic',
13+
factory: true,
14+
state: {
15+
modules: [
16+
{ type: 'clk', instanceId: 'clk', row: 1 },
17+
{ type: 'euclid', instanceId: 'euclid1', row: 1 },
18+
{ type: 'euclid', instanceId: 'euclid2', row: 1 },
19+
{ type: 'logic', instanceId: 'logic', row: 1 },
20+
{ type: 'kick', instanceId: 'kick', row: 1 },
21+
{ type: 'snare', instanceId: 'snare', row: 1 },
22+
{ type: 'mix', instanceId: 'mix', row: 1 },
23+
{ type: 'out', instanceId: 'out', row: 1 }
24+
],
25+
knobs: {
26+
clk: { bpm: 0.35 },
27+
euclid1: { length: 8, hits: 5, rotate: 0 },
28+
euclid2: { length: 8, hits: 3, rotate: 0 },
29+
kick: { tune: 0.4, decay: 0.4, punch: 0.6 },
30+
snare: { tune: 0.5, decay: 0.3, noise: 0.6 },
31+
mix: { lvl1: 0.7, lvl2: 0.5 },
32+
out: { volume: 0.6 }
33+
},
34+
switches: {},
35+
cables: [
36+
// Clock to both euclidean generators
37+
{ fromModule: 'clk', fromPort: 'clock', toModule: 'euclid1', toPort: 'clock' },
38+
{ fromModule: 'clk', fromPort: 'clock', toModule: 'euclid2', toPort: 'clock' },
39+
// Euclidean outputs to logic inputs
40+
{ fromModule: 'euclid1', fromPort: 'trig', toModule: 'logic', toPort: 'in1' },
41+
{ fromModule: 'euclid2', fromPort: 'trig', toModule: 'logic', toPort: 'in2' },
42+
// AND triggers kick, OR triggers snare
43+
{ fromModule: 'logic', fromPort: 'and', toModule: 'kick', toPort: 'trigger' },
44+
{ fromModule: 'logic', fromPort: 'or', toModule: 'snare', toPort: 'trigger' },
45+
// Mix to output
46+
{ fromModule: 'kick', fromPort: 'out', toModule: 'mix', toPort: 'in1' },
47+
{ fromModule: 'snare', fromPort: 'out', toModule: 'mix', toPort: 'in2' },
48+
{ fromModule: 'mix', fromPort: 'out', toModule: 'out', toPort: 'L' },
49+
{ fromModule: 'mix', fromPort: 'out', toModule: 'out', toPort: 'R' }
50+
]
51+
}
52+
};

src/js/config/patches/test-mult.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/**
2+
* Test - Mult
3+
*
4+
* Demonstrates signal splitting:
5+
* - One LFO split to modulate two VCOs at different rates
6+
* - Creates a detuned/chorusing effect
7+
*/
8+
export default {
9+
name: 'Test - Mult',
10+
factory: true,
11+
state: {
12+
modules: [
13+
{ type: 'lfo', instanceId: 'lfo', row: 1 },
14+
{ type: 'mult', instanceId: 'mult', row: 1 },
15+
{ type: 'vco', instanceId: 'vco1', row: 1 },
16+
{ type: 'vco', instanceId: 'vco2', row: 1 },
17+
{ type: 'mix', instanceId: 'mix', row: 1 },
18+
{ type: 'out', instanceId: 'out', row: 1 }
19+
],
20+
knobs: {
21+
lfo: { rate: 0.3, shape: 0.5 },
22+
vco1: { coarse: 0.4, fine: 0 },
23+
vco2: { coarse: 0.4, fine: 0.1 },
24+
mix: { lvl1: 0.6, lvl2: 0.6 },
25+
out: { volume: 0.5 }
26+
},
27+
switches: {
28+
lfo: { range: 0 }
29+
},
30+
cables: [
31+
// LFO to mult input
32+
{ fromModule: 'lfo', fromPort: 'primary', toModule: 'mult', toPort: 'in1' },
33+
// Mult outputs to both VCO pitch inputs
34+
{ fromModule: 'mult', fromPort: 'out1a', toModule: 'vco1', toPort: 'vOct' },
35+
{ fromModule: 'mult', fromPort: 'out1b', toModule: 'vco2', toPort: 'vOct' },
36+
// VCOs to mixer
37+
{ fromModule: 'vco1', fromPort: 'ramp', toModule: 'mix', toPort: 'in1' },
38+
{ fromModule: 'vco2', fromPort: 'ramp', toModule: 'mix', toPort: 'in2' },
39+
// Mix to output
40+
{ fromModule: 'mix', fromPort: 'out', toModule: 'out', toPort: 'L' },
41+
{ fromModule: 'mix', fromPort: 'out', toModule: 'out', toPort: 'R' }
42+
]
43+
}
44+
};

src/js/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ export const DEFAULT_MODULE_ORDER = [
8181
'arp',
8282
'seq',
8383
'euclid',
84+
'logic',
85+
'mult',
8486
'vco',
8587
'vcf',
8688
'adsr',

0 commit comments

Comments
 (0)