2026-08-02 20:03:04 +01:00
|
|
|
#include "Clipper.hpp"
|
2026-08-02 22:58:56 +01:00
|
|
|
#include <cmath>
|
2026-08-02 20:03:04 +01:00
|
|
|
|
2026-08-02 22:58:56 +01:00
|
|
|
Clipper::Clipper(float init_clip, ClipperMode init_mode)
|
2026-08-03 15:43:02 +01:00
|
|
|
: threshold_(init_clip), mode_(init_mode) {}
|
2026-08-02 20:03:04 +01:00
|
|
|
|
|
|
|
|
void Clipper::process(const float *in, float *out, uint32_t frames) {
|
|
|
|
|
for (uint32_t i = 0; i < frames; ++i) {
|
2026-08-02 22:58:56 +01:00
|
|
|
out[i] = clip(in[i]);
|
2026-08-02 20:03:04 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
void Clipper::processStereo(const float *inLeft, const float *inRight,
|
|
|
|
|
float *outLeft, float *outRight, uint32_t frames) {
|
|
|
|
|
for (uint32_t i = 0; i < frames; ++i) {
|
2026-08-02 20:26:06 +01:00
|
|
|
outLeft[i] = clip(inLeft[i]);
|
|
|
|
|
outRight[i] = clip(inRight[i]);
|
2026-08-02 20:03:04 +01:00
|
|
|
}
|
|
|
|
|
}
|
2026-08-02 20:26:06 +01:00
|
|
|
|
|
|
|
|
float Clipper::clip(const float in) {
|
2026-08-02 22:58:56 +01:00
|
|
|
switch (mode_) {
|
|
|
|
|
case kClipperModeHard: {
|
2026-08-03 15:43:02 +01:00
|
|
|
return std::fmin(std::fmax(in, -threshold_), threshold_);
|
2026-08-02 22:58:56 +01:00
|
|
|
}
|
2026-08-03 15:45:34 +01:00
|
|
|
default:
|
2026-08-02 22:58:56 +01:00
|
|
|
case kClipperModeSoft: {
|
2026-08-03 15:43:02 +01:00
|
|
|
float normalized = (in / threshold_) * 0.75f;
|
|
|
|
|
return std::tanh(normalized) * threshold_;
|
2026-08-02 22:58:56 +01:00
|
|
|
}
|
2026-08-02 23:13:42 +01:00
|
|
|
case kClipperModeFold: {
|
|
|
|
|
float x = in;
|
2026-08-03 15:43:02 +01:00
|
|
|
while (x > threshold_ || x < -threshold_) {
|
|
|
|
|
if (x > threshold_) {
|
|
|
|
|
x = 2.0f * threshold_ - x;
|
|
|
|
|
} else if (x < -threshold_) {
|
|
|
|
|
x = -2.0f * threshold_ - x;
|
2026-08-02 23:13:42 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return x;
|
|
|
|
|
}
|
2026-08-02 20:26:06 +01:00
|
|
|
}
|
|
|
|
|
}
|