--- name: audio-effect description: Create standard SuperCollider audio effects for Bice-Box (delays, reverbs, filters, distortions). Provides templates, ControlSpecs, common patterns, and MCP workflow for safely creating/updating effects. --- # Audio Effect Development Create standard SuperCollider audio effects for Bice-Box (delays, reverbs, filters, distortions, etc.). ## Critical Rules ### ⚠️ FILENAME/DEFNAME MATCHING IS CRITICAL ⚠️ - **defName MUST EXACTLY match filename** (character for character!) - ✅ CORRECT: `reverb.sc` → `var defName = \reverb;` - ✅ CORRECT: `ping_pong_delay.sc` → `var defName = \ping_pong_delay;` - ❌ WRONG: `happy-synth.sc` → `var defName = \happy_synth;` (hyphen vs underscore!) - ❌ WRONG: `my_effect.sc` → `var defName = \my-effect;` (underscore vs hyphen!) - **If faders don't appear in UI, check filename vs defName first!** ### Other Critical Rules - **First THREE lines must be comments**: `// shader: `, `// category: `, and `// description: ` - **Description must be a single line** (~60-80 chars): concise summary of what the effect does - **All variables in ONE block** after parameters - NO `var` declarations anywhere else - **Use specs defaults**: `\param.kr(specs[\param].default)` - **Mono-first**: Process in mono, output `[processed, processed]` - **Analysis out**: Always mono signal to `analysis_out_bus` - **Maximum 12 faders** fit on screen - design parameters accordingly ## Effect Template ```supercollider // shader: oscilloscope // category: Modulation // description: Brief single-line summary of what this effect does ( var defName = \effect_name; // ← MUST match filename exactly! var specs = ( param1: ControlSpec(0.1, 10.0, 'exp', 0, 1.0, "x"), mix: ControlSpec(0.0, 1.0, 'lin', 0, 0.5, "%") ); var def = SynthDef(defName, { // Standard parameters var out = \out.kr(0); var in_bus = \in_bus.kr(0); var analysis_out_bus = \analysis_out_bus.kr; var param1 = \param1.kr(specs[\param1].default); var mix = \mix.kr(specs[\mix].default); // ALL variables declared here! var sig, dry, processed, mono_for_analysis; // Processing sig = In.ar(in_bus); // Mono input dry = sig; processed = sig * param1; // Your effect here processed = XFade2.ar(dry, processed, mix * 2 - 1); // Outputs mono_for_analysis = processed; Out.ar(analysis_out_bus, mono_for_analysis); Out.ar(out, [processed, processed]); }); def.add; "Effect SynthDef 'effect_name' added".postln; ~setupEffect.value(defName, specs); ) ``` ## Feedback Effects Pattern For delays, reverbs, and other feedback-based effects: ```supercollider // Get feedback from previous iteration var fbNode = LocalIn.ar(1); // Create delay with input + feedback var delayed = DelayC.ar(sig + fbNode, maxDelayTime, delayTime); // Send feedback back (with feedback amount control) LocalOut.ar(delayed * feedback); ``` ## Common ControlSpecs ```supercollider // Linear 0-1 parameters (mix, level, etc.) mix: ControlSpec(0.0, 1.0, 'lin', 0, 0.5, "%") // Exponential frequency parameters freq: ControlSpec(20, 2000, 'exp', 0, 440, "Hz") // Gain/amplitude parameters gain: ControlSpec(0.1, 5.0, 'exp', 0, 1.0, "x") // Time-based parameters delay: ControlSpec(0.001, 2.0, 'exp', 0, 0.1, "s") ``` ## Visualizer Comments Add a visualizer comment as the first line to auto-load a visualizer when the effect loads: - **For GLSL shaders:** `// shader: shader_name` (loads from `shaders/` directory) - **For p5.js sketches:** `// p5: sketch_name` (loads from `visual/` directory) Examples: - `// shader: oscilloscope` → loads `shaders/oscilloscope.glsl` - `// shader: palpatine` → loads `shaders/palpatine_image.glsl` (multi-pass) - `// p5: tuner` → loads `visual/tuner.js` **Note:** Visualizer names must be unique across both directories. ## Category Comments Add a category comment on line 2 (after the visualizer comment) to organize effects in the UI: ```supercollider // shader: oscilloscope // category: Distortion ``` **Example categories:** - **Distortion** - overdrive, fuzz, saturation, bitcrushing - **Modulation** - chorus, flanger, phaser, tremolo, vibrato - **Delay** - echo, ping-pong, tape delay, multi-tap - **Reverb** - room, hall, shimmer, ambient - **Filter** - wah, EQ, resonant filters - **Pitch** - harmonizer, octaver, pitch shifter - **Dynamics** - compressor, limiter, gate, expander - **Spectral** - vocoder, freeze, FFT effects - **Lo-Fi** - tape, vinyl, degradation, noise - **Utility** - tuner, bypass, test tones but feel free to create new categories as needed. ## MCP Workflow **Recommended workflow for creating/updating effects:** 1. **Test syntax** - Use `test_supercollider_code` to validate during development ``` mcp__bice-box__test_supercollider_code(scCode: "your code here") ``` 2. **Create/update** - Use `create_or_update_audio_effect` to safely save ``` mcp__bice-box__create_or_update_audio_effect( effectName: "my_effect", scCode: "your code here", makeActive: true // optional, loads effect immediately ) ``` 3. **Activate** - Switch to your effect ``` mcp__bice-box__set_current_effect(effectName: "my_effect") ``` 4. **Tweak parameters** - Adjust live values for testing ``` mcp__bice-box__set_effect_parameters(params: { param1: 2.5, mix: 0.7 }) ``` Note: This only affects live session values. To change defaults, edit the `.sc` file. 5. **Debug errors** - If compilation fails, check logs ``` mcp__bice-box__read_logs(lines: 100, filter: "ERROR") ``` ## Common Patterns ### Distortion/Saturation ```supercollider processed = (sig * drive).tanh; // Soft clipping processed = sig.distort; // Hard distortion processed = sig.softclip; // Soft clipping ``` ### Filtering ```supercollider processed = LPF.ar(sig, cutoff); // Low-pass processed = HPF.ar(sig, cutoff); // High-pass processed = RLPF.ar(sig, cutoff, rq); // Resonant low-pass processed = MoogFF.ar(sig, cutoff, resonance); // Moog-style filter ``` ### Delay/Echo ```supercollider processed = DelayC.ar(sig, maxDelay, delayTime); // Clean delay processed = CombC.ar(sig, maxDelay, delayTime, decayTime); // Comb filter ``` ### Modulation ```supercollider var lfo = SinOsc.kr(rate); // LFO for modulation processed = sig * (1 + (depth * lfo)); // Amplitude modulation ``` ## Tips - Start with simple effects and add complexity gradually - Test with live audio input frequently - Use sensible parameter ranges (exponential for frequency/time, linear for mix) - Keep CPU usage in mind - avoid excessive nesting - Use meaningful parameter names for better UI readability