waveform and mod dial for THiCC

portability/macos
zetaPRIME 2019-07-20 20:24:13 -04:00
parent 7af2ec5034
commit 24b7c72ef9
3 changed files with 53 additions and 8 deletions

1
notes
View File

@ -33,6 +33,7 @@ parameters {
TODO {
immediate frontburner {
reimplement sample import to IPC from standalone ffmpeg since QAudioDecoder is partially broken on arch and completely broken on macOS
ffprobe -v quiet -show_streams -select_streams a -of json testOut.mp3
distortion effect
single-selection sampler

View File

@ -20,6 +20,7 @@ using namespace Xybrid::UI;
#include "util/strings.h"
#include <cmath>
#include <array>
#include <QDebug>
#include <QRandomGenerator>
@ -44,7 +45,7 @@ namespace {
else return d;
}
}
[[maybe_unused]] inline double lerp(double p, double a, double b) {
[[maybe_unused]] inline double lerp(double a, double b, double p) {
return b * p + a * (1.0 - p);
}
@ -68,15 +69,49 @@ namespace {
return 0.0;
}
[[gnu::optimize("O3")]] double oscSaw(double phase, double delta) {
[[gnu::optimize("O3")]] double push(double in, double mod, double factor) {
double s = in < 0 ? -1 : 1;
in *= s;
//if (mod < 0) mod = 1.0/-mod;
//else mod += 1.0;
mod = mod < 0 ? lerp(1.0, 1.0/factor, -mod) : lerp(1.0, factor, mod);
return std::pow(in, mod)*s;
}
[[gnu::optimize("O3")]] double oscSaw(double phase, double delta, double mod) {
phase = std::fmod(phase + 0.5, 1.0);
double d = phase;// * 0.2 + (std::floor(phase*7.0) / 7.0 + (0.5/7.0)) * 0.8;
d = d * 2.0 - 1.0;
d = push(d, -mod, 5);
d -= polyblep(phase, delta);
return d;
}
[[gnu::optimize("O3")]] double oscSine(double phase, double, double mod) { return push(std::sin(phase*PI*2), -mod, 5); }
[[gnu::optimize("O3")]] double oscPulse(double phase, double delta, double mod) {
double duty = (mod+1.0)/2.0;
double d = 1.0;
if (std::fmod(phase, 1.0) >= duty) d = -1.0;
d += polyblep(std::fmod(phase, 1.0), delta);
d -= polyblep(std::fmod(phase + (1.0 - duty), 1.0), delta);
return d;
}
#pragma GCC diagnostic pop
// wave function list(s)
const constexpr std::array waveFunc = {
&oscSaw,
&oscSine,
&oscPulse,
};
const std::array waveName = {
qs("saw"),
qs("sine"),
qs("pulse"),
};
}
Thicc::Thicc() { }
@ -99,6 +134,8 @@ void Thicc::init() {
core.processNote = [this](Note& note, AudioPort* p) {
double freq;
auto osc = waveFunc[static_cast<size_t>(wave)];
int vc = voices;
double vf = static_cast<double>(vc);
double spr = std::pow(SEMI, detune/(vf/2.0));
@ -122,11 +159,11 @@ void Thicc::init() {
double dm = std::pow(spr, dc);
double sg = i % 2 == 0 ? 1.0 : -1.0;
//o += (std::fmod(pc + si * dm, 1.0) * 2.0 - 1.0) * sg;
o += oscSaw(pc + si * dm, delta * dm) * sg;
o += osc(pc + si * dm, delta * dm, mod) * sg;
}
o /= 1.0 + ((vf - 1.0)/3.0);
o /= 1.0 + ((vf - 1.0)/5.0);
AudioFrame out = o;
(*p)[i] += out.gainBalance(0, note.pan) * note.ampMult();
@ -141,25 +178,31 @@ void Thicc::process() { core.process(this); }
void Thicc::saveData(QCborMap& m) const {
m[qs("adsr")] = adsr;
m[qs("wave")] = wave;
m[qs("voices")] = voices;
m[qs("mod")] = mod;
m[qs("detune")] = detune;
//m[qs("shift")] = shift;
}
void Thicc::loadData(const QCborMap& m) {
adsr = m.value("adsr");
wave = static_cast<int>(m.value("wave").toInteger(wave));
voices = static_cast<int>(m.value("voices").toInteger(voices));
mod = m.value("mod").toDouble(mod);
detune = m.value("detune").toDouble(detune);
//shift = m.value("shift").toDouble(shift);
}
void Thicc::onGadgetCreated() {
auto wn = [](size_t i) { if (i >= waveName.size()) return QString::number(i); return waveName[i]; };
auto l = new LayoutGadget(obj);
(new KnobGadget(l))->bind(wave)->setLabel(qs("Wave"))->setTextFunc(wn)->setRange(0, waveFunc.size()-1, 1, KnobGadget::BigStep);
(new KnobGadget(l))->bind(mod)->setLabel(qs("W. Mod"))->setRange(-1.0, 1.0, 0.01);
l->addSpacer();
(new KnobGadget(l))->bind(voices)->setLabel(qs("Voices"))->setRange(1, 16, 1, KnobGadget::BigStep)->setDefault(1);
(new KnobGadget(l))->bind(detune)->setLabel(qs("Detune"))->setRange(0.0, 1.0, 0.001);
//(new KnobGadget(l))->bind(shift)->setLabel(qs("Shift"))->setRange(0.0, 25.0, 0.01);
l->addSpacer();
KnobGadget::autoCreate(l, adsr);
}

View File

@ -8,10 +8,11 @@ namespace Xybrid::Instruments {
NodeLib::ADSR adsr;
int wave = 0;
int voices = 1;
double mod = 0.0;
double detune = 0.0;
//double shift = 0.0;
public:
Thicc();