distortion effect

master
Zithia Satazaki 2022-03-29 00:42:12 -04:00
parent b0b754a37d
commit f969aa0d2e
3 changed files with 127 additions and 1 deletions

2
notes
View File

@ -42,7 +42,7 @@ TODO {
revert-to-saved menu action
distortion effect
- distortion effect
automation node {
listens for one specific param

View File

@ -0,0 +1,99 @@
#include "distortion.h"
using Xybrid::Effects::Distortion;
using namespace Xybrid::Data;
#include "util/strings.h"
#include "nodelib/basics.h"
using namespace Xybrid::NodeLib;
#include "data/audioframe.h"
#include "data/porttypes.h"
#include "config/pluginregistry.h"
using namespace Xybrid::Config;
#include "audio/audioengine.h"
using namespace Xybrid::Audio;
#include "ui/patchboard/nodeobject.h"
#include "ui/gadgets/layoutgadget.h"
#include "ui/gadgets/togglegadget.h"
#include "ui/gadgets/knobgadget.h"
using namespace Xybrid::UI;
#include <cmath>
#include <QCborMap>
// clazy:excludeall=non-pod-global-static
RegisterPlugin(Distortion, {
i->id = "fx:distortion";
i->displayName = "Distortion";
i->category = "Effect";
})
Distortion::Distortion() = default;
void Distortion::init() {
addPort(Port::Input, Port::Audio, 0);
addPort(Port::Output, Port::Audio, 0);
}
void Distortion::reset() {
//
}
namespace {
inline double sxp(double v, double e) {
double s = v < 0 ? -1.0 : 1.0;
return std::pow(std::abs(v), e) * s;
}
inline AudioFrame sxp(AudioFrame v, double e) { return {sxp(v.l, e), sxp(v.r, e)}; }
}
void Distortion::process() {
auto in = std::static_pointer_cast<AudioPort>(port(Port::Input, Port::Audio, 0));
auto out = std::static_pointer_cast<AudioPort>(port(Port::Output, Port::Audio, 0));
in->pull();
out->pull();
auto ts = audioEngine->curTickSize();
auto d = drive.start(), s = shape.start(), m = mix.start(), o = output.start();
for (size_t f = 0; f < ts; f++) {
AudioFrame inp = (*in)[f];
auto g = inp.gainBalance(d.next());
auto pv = s.next();
auto exp = pv > 0.0 ? 1.0 / (1.0 + pv) : -pv + 1.0;
(*out)[f] = AudioFrame::lerp(inp, sxp(g.clamp(), exp), m.next()).gainBalance(o.next());
}
}
void Distortion::saveData(QCborMap& m) const {
drive.save(m);
shape.save(m);
mix.save(m);
output.save(m);
}
void Distortion::loadData(const QCborMap& m) {
drive.load(m);
shape.load(m);
mix.load(m);
output.load(m);
}
void Distortion::onGadgetCreated() {
if (!obj) return;
auto l = new LayoutGadget(obj);
KnobGadget::autoGain(l, drive);
(new KnobGadget(l))->setRange(0, 0, 0.1)->bind(shape)->setTextFunc(KnobGadget::textOffset);
KnobGadget::autoPercent(l, mix);
KnobGadget::autoGain(l, output);
}

View File

@ -0,0 +1,27 @@
#pragma once
#include "data/node.h"
#include "nodelib/param.h"
namespace Xybrid::Effects {
class Distortion : public Data::Node {
NodeLib::Param drive = {"Drive", 0.0, 24.0, 0.0};
NodeLib::Param shape = {"Shape", -5.0, 5.0, 0.0};
NodeLib::Param mix = {"Mix", 0.0, 1.0, 1.0};
NodeLib::Param output = {"Output", -12.0, 12.0, 0.0};
public:
Distortion();
~Distortion() override = default;
void init() override;
void reset() override;
//void release() override;
void process() override;
void saveData(QCborMap&) const override;
void loadData(const QCborMap&) override;
void onGadgetCreated() override;
};
}