More shaper shapes, starting with a diode fold #64

Open
opened 2026-09-05 16:19:01 +00:00 by bcox · 0 comments
Owner

dsp/shaper.h owns the curve list -- three today: soft clip, hard clip, fold.
The file is built for exactly this: it is the only place that knows which
curves exist, and each curve declares its own MinimumRatio beside its
transfer function, so a new curve is one edit rather than two with the second
easy to forget. Both switches are under -Werror=switch, so a new enumerator
fails the build at the curve and at the ratio.

Appending needs no format bump and no reader change. plugin/patch_format.h
validates the stored byte against kShapeCount and reads an unknown value
back as kSoftClip; the editor's combo at editor/patch_view.h:2023 is sized
from kShapeCount.

The filter drives are untouched: dsp/ladder.h uses its own LadderSaturate
deliberately and dsp/va_filter.h shares it. ProcessShaper is only the VA
layer's insert.

Reach. Today only the VA layer has a shaper insert, with three insert
points. #43 adds one to the FM pair. Anything added here lands in both.

In scope

  • Diode fold. kFold is a period-4 triangle reflection: perfectly
    symmetric, even crease depths, which reads clean and digital. A 259/Serge
    folder has uneven and asymmetric creases, and that is most of its character.

Candidates, not decided

  • True wrap -- modulo rather than reflect, so a discontinuous sawtooth
    transfer. Much harsher than a fold, and it is literally what #43 asked for
    ("wave wrappers").
  • Sine fold -- folding through sin() instead of triangle reflection:
    smooth creases, no corners, materially less aliasing, so a lower ratio.
  • Rectifier, full and half wave -- octave-up and added even harmonics
    respectively. Cheap, and a west-coast staple.
  • Asymmetric soft clip -- a different curve above and below zero, which is
    what tube and transformer saturation actually are. bias gets partway there
    but the curve itself stays symmetric.
  • Quantize / crush -- memoryless and cheap, maximally aliasing, so a high
    ratio.

Each shape needs its MinimumRatio argued rather than guessed. shaper.h's
rule is to round up: a user cannot override the derived ratio, so
under-delivering means aliasing they cannot fix.

`dsp/shaper.h` owns the curve list -- three today: soft clip, hard clip, fold. The file is built for exactly this: it is the only place that knows which curves exist, and each curve declares its own `MinimumRatio` beside its transfer function, so a new curve is one edit rather than two with the second easy to forget. Both switches are under `-Werror=switch`, so a new enumerator fails the build at the curve *and* at the ratio. Appending needs no format bump and no reader change. `plugin/patch_format.h` validates the stored byte against `kShapeCount` and reads an unknown value back as `kSoftClip`; the editor's combo at `editor/patch_view.h:2023` is sized from `kShapeCount`. The filter drives are untouched: `dsp/ladder.h` uses its own `LadderSaturate` deliberately and `dsp/va_filter.h` shares it. `ProcessShaper` is only the VA layer's insert. **Reach.** Today only the VA layer has a shaper insert, with three insert points. #43 adds one to the FM pair. Anything added here lands in both. ## In scope - **Diode fold.** `kFold` is a period-4 triangle reflection: perfectly symmetric, even crease depths, which reads clean and digital. A 259/Serge folder has uneven and asymmetric creases, and that is most of its character. ## Candidates, not decided - **True wrap** -- modulo rather than reflect, so a discontinuous sawtooth transfer. Much harsher than a fold, and it is literally what #43 asked for ("wave wrappers"). - **Sine fold** -- folding through `sin()` instead of triangle reflection: smooth creases, no corners, materially less aliasing, so a lower ratio. - **Rectifier**, full and half wave -- octave-up and added even harmonics respectively. Cheap, and a west-coast staple. - **Asymmetric soft clip** -- a different curve above and below zero, which is what tube and transformer saturation actually are. `bias` gets partway there but the curve itself stays symmetric. - **Quantize / crush** -- memoryless and cheap, maximally aliasing, so a high ratio. Each shape needs its `MinimumRatio` argued rather than guessed. `shaper.h`'s rule is to round up: a user cannot override the derived ratio, so under-delivering means aliasing they cannot fix.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
bcox/tymbal#64
No description provided.