Skip to content

Commit 01bc487

Browse files
bwhitmanclaude
andcommitted
c_dsp_demo: heavy distortion effect
Third example kind: a stateless overdrive — drive gain into a +/-1.0 clamp, cubic soft clip (y = x - x^3/3) to round the corners, 3/2 renormalize for the 2/3 knee. Integer-only, so it compiles on all three backends; `drive` is the knob to edit live. The demo now plays the CZ notes clean, bitcrushed, then distorted. Verified in the browser on the web build: enabled on bus 0 it runs in the AMY worklet and lifts a quiet sine's output peak 5.8x into the saturator, no worklet errors. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 14ce229 commit 01bc487

1 file changed

Lines changed: 30 additions & 1 deletion

File tree

tulip/fs/tulip/ex/c_dsp_demo.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,26 @@
3838
}
3939
"""
4040

41+
# --- An effect: heavy distortion --------------------------------------------
42+
# Overdrive: slam the signal into a ceiling. Multiply by a big drive gain,
43+
# clamp to +/-1.0, then round the corners off with a cubic soft clip
44+
# (y = x - x^3/3, the classic saturator) so it growls instead of buzzing.
45+
# The knee tops out at 2/3, so scale by 3/2 to bring peaks back to 1.0.
46+
# Stateless -- no statics needed. Crank `drive` for more filth.
47+
48+
DIST = """
49+
int drive = 10; // 1 = clean boost, 10 = heavy. edit me!
50+
int i = 0;
51+
while (i < frames * chans) {
52+
int s = buf[i] * drive;
53+
if (s > 8388608) s = 8388608; // clamp to +/-1.0 (S8.23)
54+
if (s < -8388608) s = -8388608;
55+
int y = s - fxmul(fxmul(s, s), s) / 3;
56+
buf[i] = y + y / 2;
57+
i = i + 1;
58+
}
59+
"""
60+
4161
# --- An oscillator: CZ-101-style phase distortion "saw" --------------------
4262
# Casio's CZ series makes bright waves without a filter: read a plain cosine
4363
# with a *bent* phase. The first `dcw` fraction of the cycle sweeps the
@@ -65,6 +85,7 @@
6585

6686
def run():
6787
tulip.install_c_process('crush', CRUSH)
88+
tulip.install_c_process('dist', DIST)
6889
tulip.install_c_osc('cz', CZ)
6990

7091
# Point AMY osc 200 at our oscillator and set up its envelope. Use a HIGH
@@ -86,7 +107,15 @@ def run():
86107
time.sleep(0.4)
87108
time.sleep(1)
88109
tulip.c_process('crush', False)
110+
111+
print("same notes, heavy distortion...")
112+
tulip.c_process('dist', True)
113+
for note in (48, 52, 55, 60):
114+
amy.send(osc=200, note=note, vel=1)
115+
time.sleep(0.4)
116+
time.sleep(1)
117+
tulip.c_process('dist', False)
89118
tulip.c_osc('cz', 200, False)
90-
print("done. try editing CZ's dcw and re-running -- reinstalls hot-swap.")
119+
print("done. try editing CZ's dcw or DIST's drive and re-running -- reinstalls hot-swap.")
91120

92121
run()

0 commit comments

Comments
 (0)