[FM] functional vibrato

This commit is contained in:
thibaud keller 2024-10-07 22:53:11 +01:00
parent abd170d77a
commit 9568198a1c
3 changed files with 66 additions and 25 deletions

View file

@ -14,10 +14,10 @@ void Senior::operator()(tick t)
} }
// Only compute skipped_frames when the control changes // Only compute skipped_frames when the control changes
if (inputs.rate != previous_rate) if (inputs.s_rate != previous_rate)
{ {
step_size = (1. - inputs.rate) * RATE; step_size = (1. - inputs.s_rate) * RATE;
previous_rate = inputs.rate; previous_rate = inputs.s_rate;
} }
// Process the input buffer // Process the input buffer
@ -27,7 +27,7 @@ void Senior::operator()(tick t)
auto* out = outputs.audio[i % outputs.audio.channels]; auto* out = outputs.audio[i % outputs.audio.channels];
// Init current_frame for each channel // Init current_frame for each channel
double current_frame{crush_frame(in[i])}; double current_frame{crush(in[i])};
for(int j{0}; j < t.frames; j++) for(int j{0}; j < t.frames; j++)
{ {
@ -36,21 +36,28 @@ void Senior::operator()(tick t)
else else
{ {
skipped_frames[i] = 0; skipped_frames[i] = 0;
current_frame = crush_frame(in[j]); current_frame = crush(in[j]);
} }
fms[i].delay(lfos[i].cos()*0.0025 + 0.05); if (!inputs.depth)
out[j] = current_frame;
else
{
lfo.set(inputs.freq, phases[i], 0);
fms[i].delay(lfo.cos() * inputs.depth + .5);
phases[i] = lfo.phase();
out[j] = fms[i](current_frame); out[j] = fms[i](current_frame);
} }
} }
} }
}
void Senior::set_bit_factor() void Senior::set_bit_factor()
{ {
bit_factor = pow(2, inputs.bits) - 1; bit_factor = pow(2, inputs.bits) - 1;
} }
double Senior::crush_frame(const double& f) double Senior::crush(const double& f)
{ {
if (inputs.bits == BITS) if (inputs.bits == BITS)
return f; return f;
@ -60,4 +67,5 @@ double Senior::crush_frame(const double& f)
// Close, but prefer the use of roundMagic from Lance Putnam's Gama // Close, but prefer the use of roundMagic from Lance Putnam's Gama
return gam::scl::round<double>(f * bit_factor) / bit_factor; return gam::scl::round<double>(f * bit_factor) / bit_factor;
} }
}
} // namespace Ottobit

View file

@ -30,11 +30,22 @@ public:
struct ins struct ins
{ {
halp::dynamic_audio_bus<"Input", double> audio; halp::dynamic_audio_bus<"Input", double> audio;
struct : halp::knob_f32<"Bits", halp::range{.min = 3, .max = BITS, .init = BITS}> halp::knob_f32<"SAMPLE RATE", halp::range{.min = .1, .max = 1., .init = 1.}> s_rate;
using log_map = halp::log_mapper<std::ratio<95, 100>>;
struct : halp::knob_f32<"BITS", halp::range{.min = 3, .max = BITS, .init = BITS}>
{ {
using mapper = halp::log_mapper<std::ratio<95, 100>>; using mapper = log_map;
} bits; } bits;
halp::knob_f32<"Rate", halp::range{.min = .1, .max = 1., .init = 1.}> rate; struct : halp::knob_f32<"FREQ", halp::range{.min = .4, .max = 200., .init = 5.}>
{
using mapper = log_map;
} freq;
struct : halp::knob_f32<"DEPTH", halp::range{.min = .0, .max = 1., .init = 0.}>
{
using mapper = log_map;
}
depth;
} inputs; } inputs;
struct struct
@ -47,17 +58,26 @@ public:
{ {
// Initialization, this method will be called with buffer size, etc. // Initialization, this method will be called with buffer size, etc.
set_bit_factor(); set_bit_factor();
lfo.set_sample_rate(info.rate);
lfo.freq(5);
skipped_frames.resize(info.input_channels); skipped_frames.resize(info.input_channels);
lfos.resize(info.input_channels);
fms.resize(info.input_channels); fms.resize(info.input_channels);
for (auto [lfo, fm] : std::views::zip(lfos, fms)) for (auto& fm : fms)
{ {
lfo.set_sample_rate(info.rate);
lfo.set(5, 0, 0);
fm.set_sample_rate(info.rate); fm.set_sample_rate(info.rate);
fm.maxDelay(0.1); fm.maxDelay(0.1);
} }
phases.resize(info.output_channels);
float phase_frac{1.f / info.output_channels};
for (int i{0}; i < info.output_channels; i++)
{
phases[i] = i * phase_frac;
}
} }
// Do our processing for N samples // Do our processing for N samples
@ -72,18 +92,21 @@ public:
private: private:
int bit_factor, step_size{0}; int bit_factor, step_size{0};
double previous_bits{BITS},
previous_rate{1};
std::vector<float> phases;
std::vector<int> skipped_frames; std::vector<int> skipped_frames;
double previous_bits{BITS}, previous_rate{1};
std::vector<gam::LFO<gam::phsInc::Loop,
halp::compat::gamma_domain>> lfos;
std::vector<gam::Delay<double, std::vector<gam::Delay<double,
gam::ipl::Linear, gam::ipl::Linear,
halp::compat::gamma_domain>> fms; halp::compat::gamma_domain>> fms;
gam::LFO<gam::phsInc::Loop, halp::compat::gamma_domain> lfo{5.};
void set_bit_factor(); void set_bit_factor();
double crush_frame(const double& f); double crush(const double& f);
}; };
} } // namespace Ottobit

View file

@ -10,11 +10,21 @@ struct Senior::ui
using enum halp::layouts; using enum halp::layouts;
halp_meta(name, "Senior") halp_meta(name, "Senior")
halp_meta(layout, hbox) halp_meta(layout, vbox)
halp_meta(background, dark) halp_meta(background, dark)
struct
{
halp_meta(layout, hbox)
halp::item<&ins::bits> bits; halp::item<&ins::bits> bits;
halp::item<&ins::s_rate> s_rate;
} res;
halp::item<&ins::rate> rate; struct
{
halp_meta(layout, hbox)
halp::item<&ins::depth> depth;
halp::item<&ins::freq> freq;
} mod;
}; };
} }