/** * moduleRegistry.js — Defines all available module types * Each module type specifies: ports, params, icon, category, and audio factory */ export const PORT_TYPE = { AUDIO: 'audio', CONTROL: 'control', TRIGGER: 'trigger', }; // Module type definitions const registry = {}; export function defineModule(type, def) { registry[type] = { type, ...def }; } export function getModuleDef(type) { return registry[type] || null; } export function getAllModuleDefs() { return Object.values(registry); } export function getModulesByCategory() { const cats = {}; for (const def of Object.values(registry)) { if (!cats[def.category]) cats[def.category] = []; cats[def.category].push(def); } return cats; } // ==================== SOURCE ==================== defineModule('oscillator', { name: 'Oscillator', icon: '~', category: 'Source', inputs: [ { name: 'freq', type: PORT_TYPE.AUDIO, label: 'Freq' }, { name: 'detune', type: PORT_TYPE.CONTROL, label: 'Detune' }, ], outputs: [ { name: 'out', type: PORT_TYPE.AUDIO, label: 'Out' }, ], params: { waveform: { type: 'select', options: ['sine', 'square', 'sawtooth', 'triangle'], default: 'sawtooth', label: 'Wave' }, frequency: { type: 'knob', min: 20, max: 8000, default: 440, unit: 'Hz', label: 'Freq' }, detune: { type: 'knob', min: -1200, max: 1200, default: 0, unit: 'ct', label: 'Detune' }, }, }); defineModule('lfo', { name: 'LFO', icon: '∿', category: 'Source', inputs: [], outputs: [ { name: 'out', type: PORT_TYPE.CONTROL, label: 'Out' }, ], params: { waveform: { type: 'select', options: ['sine', 'square', 'sawtooth', 'triangle'], default: 'sine', label: 'Wave' }, frequency: { type: 'knob', min: 0.01, max: 50, default: 2, unit: 'Hz', label: 'Rate' }, amplitude: { type: 'knob', min: 0, max: 1, default: 0.5, unit: '', label: 'Depth' }, }, }); defineModule('noise', { name: 'Noise', icon: '⣿', category: 'Source', inputs: [], outputs: [ { name: 'out', type: PORT_TYPE.AUDIO, label: 'Out' }, ], params: { type: { type: 'select', options: ['white', 'pink', 'brown'], default: 'white', label: 'Type' }, }, }); // ==================== FILTER ==================== defineModule('filter', { name: 'Filter', icon: '▽', category: 'Filter', inputs: [ { name: 'in', type: PORT_TYPE.AUDIO, label: 'In' }, { name: 'cutoff', type: PORT_TYPE.CONTROL, label: 'Cutoff' }, ], outputs: [ { name: 'out', type: PORT_TYPE.AUDIO, label: 'Out' }, ], params: { type: { type: 'select', options: ['lowpass', 'highpass', 'bandpass', 'notch'], default: 'lowpass', label: 'Type' }, frequency: { type: 'knob', min: 20, max: 20000, default: 1000, unit: 'Hz', label: 'Cutoff' }, Q: { type: 'knob', min: 0.1, max: 20, default: 1, unit: '', label: 'Reso' }, }, }); // ==================== ENVELOPE ==================== defineModule('envelope', { name: 'Envelope', icon: '⏤╲', category: 'Modulation', inputs: [ { name: 'gate', type: PORT_TYPE.TRIGGER, label: 'Gate' }, ], outputs: [ { name: 'out', type: PORT_TYPE.CONTROL, label: 'Out' }, ], params: { attack: { type: 'knob', min: 0.001, max: 4, default: 0.01, unit: 's', label: 'Attack' }, decay: { type: 'knob', min: 0.001, max: 4, default: 0.2, unit: 's', label: 'Decay' }, sustain: { type: 'knob', min: 0, max: 1, default: 0.5, unit: '', label: 'Sustain' }, release: { type: 'knob', min: 0.001, max: 8, default: 0.5, unit: 's', label: 'Release' }, }, }); // ==================== AMPLIFIER ==================== defineModule('vca', { name: 'VCA', icon: '△', category: 'Utility', inputs: [ { name: 'in', type: PORT_TYPE.AUDIO, label: 'In' }, { name: 'cv', type: PORT_TYPE.CONTROL, label: 'CV' }, ], outputs: [ { name: 'out', type: PORT_TYPE.AUDIO, label: 'Out' }, ], params: { gain: { type: 'knob', min: 0, max: 1, default: 0.8, unit: '', label: 'Gain' }, }, }); // ==================== EFFECTS ==================== defineModule('delay', { name: 'Delay', icon: '⟫', category: 'Effect', inputs: [ { name: 'in', type: PORT_TYPE.AUDIO, label: 'In' }, ], outputs: [ { name: 'out', type: PORT_TYPE.AUDIO, label: 'Out' }, ], params: { delayTime: { type: 'knob', min: 0.01, max: 2, default: 0.3, unit: 's', label: 'Time' }, feedback: { type: 'knob', min: 0, max: 0.95, default: 0.4, unit: '', label: 'Feedbk' }, wet: { type: 'knob', min: 0, max: 1, default: 0.5, unit: '', label: 'Mix' }, }, }); defineModule('reverb', { name: 'Reverb', icon: '◌', category: 'Effect', inputs: [ { name: 'in', type: PORT_TYPE.AUDIO, label: 'In' }, ], outputs: [ { name: 'out', type: PORT_TYPE.AUDIO, label: 'Out' }, ], params: { decay: { type: 'knob', min: 0.1, max: 15, default: 3, unit: 's', label: 'Decay' }, wet: { type: 'knob', min: 0, max: 1, default: 0.4, unit: '', label: 'Mix' }, }, }); defineModule('distortion', { name: 'Distortion', icon: '⚡', category: 'Effect', inputs: [ { name: 'in', type: PORT_TYPE.AUDIO, label: 'In' }, ], outputs: [ { name: 'out', type: PORT_TYPE.AUDIO, label: 'Out' }, ], params: { distortion: { type: 'knob', min: 0, max: 1, default: 0.4, unit: '', label: 'Drive' }, wet: { type: 'knob', min: 0, max: 1, default: 0.5, unit: '', label: 'Mix' }, }, }); // ==================== MIXER ==================== defineModule('mixer', { name: 'Mixer', icon: '≡', category: 'Utility', inputs: [ { name: 'in1', type: PORT_TYPE.AUDIO, label: 'In 1' }, { name: 'in2', type: PORT_TYPE.AUDIO, label: 'In 2' }, { name: 'in3', type: PORT_TYPE.AUDIO, label: 'In 3' }, { name: 'in4', type: PORT_TYPE.AUDIO, label: 'In 4' }, ], outputs: [ { name: 'out', type: PORT_TYPE.AUDIO, label: 'Out' }, ], params: { gain1: { type: 'knob', min: 0, max: 1, default: 0.8, unit: '', label: 'Ch 1' }, gain2: { type: 'knob', min: 0, max: 1, default: 0.8, unit: '', label: 'Ch 2' }, gain3: { type: 'knob', min: 0, max: 1, default: 0.8, unit: '', label: 'Ch 3' }, gain4: { type: 'knob', min: 0, max: 1, default: 0.8, unit: '', label: 'Ch 4' }, }, }); // ==================== SCOPE ==================== defineModule('scope', { name: 'Scope', icon: '📊', category: 'Utility', inputs: [ { name: 'in', type: PORT_TYPE.AUDIO, label: 'In' }, ], outputs: [], params: {}, }); // ==================== CV TO GATE ==================== defineModule('cv2gate', { name: 'CV→Gate', icon: '⚡', category: 'Utility', inputs: [ { name: 'in', type: PORT_TYPE.CONTROL, label: 'CV In' }, ], outputs: [ { name: 'gate', type: PORT_TYPE.TRIGGER, label: 'Gate' }, ], params: { threshold: { type: 'knob', min: 0, max: 1, default: 0.5, unit: '', label: 'Thresh' }, }, }); // ==================== OUTPUT ==================== defineModule('output', { name: 'Output', icon: '🔊', category: 'Output', inputs: [ { name: 'left', type: PORT_TYPE.AUDIO, label: 'Left' }, { name: 'right', type: PORT_TYPE.AUDIO, label: 'Right' }, ], outputs: [], params: { volume: { type: 'knob', min: -60, max: 6, default: -6, unit: 'dB', label: 'Volume' }, }, }); // ==================== KEYBOARD ==================== defineModule('keyboard', { name: 'Keyboard', icon: '🎹', category: 'Source', inputs: [], outputs: [ { name: 'freq', type: PORT_TYPE.AUDIO, label: 'Freq' }, { name: 'gate', type: PORT_TYPE.TRIGGER, label: 'Gate' }, ], params: { octave: { type: 'knob', min: 1, max: 8, default: 4, unit: '', label: 'Octave' }, }, }); // ==================== DRUM PAD ==================== defineModule('drumpad', { name: 'Drum Pad', icon: '🥁', category: 'Source', inputs: [], outputs: [ { name: 'freq', type: PORT_TYPE.AUDIO, label: 'Freq' }, { name: 'gate', type: PORT_TYPE.TRIGGER, label: 'Gate' }, ], params: {}, }); // ==================== SEQUENCER ==================== defineModule('sequencer', { name: 'Sequencer', icon: '▦', category: 'Source', inputs: [], outputs: [ { name: 'freq', type: PORT_TYPE.AUDIO, label: 'Freq' }, { name: 'gate', type: PORT_TYPE.TRIGGER, label: 'Gate' }, ], params: { bpm: { type: 'knob', min: 40, max: 300, default: 140, unit: 'bpm', label: 'BPM' }, steps: { type: 'select', options: ['8', '16', '32'], default: '16', label: 'Steps' }, swing: { type: 'knob', min: 0, max: 0.5, default: 0, unit: '', label: 'Swing' }, }, // Custom data: step notes/gates stored in module.params._steps }); // ==================== PIANO ROLL ==================== defineModule('pianoroll', { name: 'Piano Roll', icon: '🎼', category: 'Source', inputs: [], outputs: [ { name: 'freq', type: PORT_TYPE.AUDIO, label: 'Freq' }, { name: 'gate', type: PORT_TYPE.TRIGGER, label: 'Gate' }, ], params: { bpm: { type: 'knob', min: 40, max: 300, default: 140, unit: 'bpm', label: 'BPM' }, loop: { type: 'select', options: ['on', 'off'], default: 'on', label: 'Loop' }, bars: { type: 'select', options: ['1', '2', '4', '8'], default: '4', label: 'Bars' }, }, // Custom data: notes stored in module.params._notes = [{note, start, duration}, ...] });