auto pan effect~
parent
7abccd7a38
commit
5d9b39f84b
8
notes
8
notes
|
@ -43,7 +43,9 @@ TODO {
|
|||
revert-to-saved menu action
|
||||
|
||||
distortion effect
|
||||
auto pan
|
||||
> auto pan
|
||||
|
||||
uh... maybe save/load samples as s16 instead of f32
|
||||
|
||||
automation node {
|
||||
listens for one specific param
|
||||
|
@ -57,12 +59,8 @@ TODO {
|
|||
focusable control to set param
|
||||
}
|
||||
|
||||
look into performance/timing/sync of audio engine; it's having buffer issues way more than it feels like it should
|
||||
|
||||
editing song info should probably be an UndoStack action
|
||||
|
||||
X eventually swap over to actually using ffmpeg as a library >_>
|
||||
|
||||
figure out what to actually do with directory config
|
||||
|
||||
buffer helper akin to what quicklevel does {
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
#include "autopan.h"
|
||||
|
||||
using Xybrid::Effects::AutoPan;
|
||||
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>
|
||||
|
||||
RegisterPlugin(AutoPan, {
|
||||
i->id = "fx:autopan";
|
||||
i->displayName = "Auto Pan";
|
||||
i->category = "Effect";
|
||||
})
|
||||
|
||||
AutoPan::AutoPan() { }
|
||||
|
||||
void AutoPan::init() {
|
||||
addPort(Port::Input, Port::Audio, 0);
|
||||
addPort(Port::Output, Port::Audio, 0);
|
||||
}
|
||||
|
||||
void AutoPan::reset() {
|
||||
cyc = 0.0;
|
||||
}
|
||||
|
||||
void AutoPan::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 sr = audioEngine->curSampleRate();
|
||||
auto ts = audioEngine->curTickSize();
|
||||
|
||||
auto eRate = rate;
|
||||
|
||||
auto tl = static_cast<double>(ts) / static_cast<double>(sr); // tick length
|
||||
for (size_t f = 0; f < ts; f++) {
|
||||
AudioFrame fCurrent = (*in)[f];
|
||||
auto cc = cyc + (static_cast<double>(f) / static_cast<double>(sr)) * eRate;
|
||||
|
||||
(*out)[f] = fCurrent.gainBalance(0.0, level * std::sin(cc * 2*PI));
|
||||
}
|
||||
|
||||
cyc = std::fmod(cyc + tl*eRate, 1.0);
|
||||
}
|
||||
|
||||
void AutoPan::saveData(QCborMap& m) const {
|
||||
m[qs("level")] = level;
|
||||
m[qs("rate")] = rate;
|
||||
}
|
||||
|
||||
void AutoPan::loadData(const QCborMap& m) {
|
||||
level = m.value("level").toDouble(level);
|
||||
rate = m.value("rate").toDouble(rate);
|
||||
}
|
||||
|
||||
void AutoPan::onGadgetCreated() {
|
||||
if (!obj) return;
|
||||
auto l = new LayoutGadget(obj);
|
||||
|
||||
(new KnobGadget(l))->bind(rate)->setLabel(qs("Rate"))->setRange(0.0, 8.0, 0.01, -1, 0.001)->setDefault(1.0);
|
||||
KnobGadget::autoBalance(l, level)->setLabel(qs("Level"));
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
#pragma once
|
||||
|
||||
#include "data/node.h"
|
||||
|
||||
namespace Xybrid::Effects {
|
||||
class AutoPan : public Data::Node {
|
||||
double level;
|
||||
double rate = 1.0;
|
||||
|
||||
double cyc; // current cycle tracking
|
||||
|
||||
public:
|
||||
AutoPan();
|
||||
~AutoPan() 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;
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue