Skip to content

Commit

Permalink
[amp] Move processor to grit/eurorack
Browse files Browse the repository at this point in the history
  • Loading branch information
tobiashienzsch committed Feb 17, 2024
1 parent 1583380 commit 204b4a3
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 140 deletions.
2 changes: 2 additions & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ add_library(gritwave::eurorack ALIAS gritwave-eurorack)
target_link_libraries(gritwave-eurorack PUBLIC gritwave::grit)
target_sources(gritwave-eurorack
PRIVATE
"grit/eurorack/amp.cpp"
"grit/eurorack/amp.hpp"
"grit/eurorack/hades.cpp"
"grit/eurorack/hades.hpp"
)
85 changes: 85 additions & 0 deletions lib/grit/eurorack/amp.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#include "amp.hpp"

#include <etl/algorithm.hpp>
#include <etl/functional.hpp>

namespace grit {

auto Amp::prepare(float sampleRate, etl::size_t blockSize) -> void
{
auto const blockRate = sampleRate / static_cast<float>(blockSize);

_gainKnob.setSampleRate(blockRate);
_toneKnob.setSampleRate(blockRate);
_outputKnob.setSampleRate(blockRate);
_mixKnob.setSampleRate(blockRate);
_gainCV.setSampleRate(blockRate);
_toneCV.setSampleRate(blockRate);
_outputCV.setSampleRate(blockRate);
_mixCV.setSampleRate(blockRate);

_channels[0].setSampleRate(sampleRate);
_channels[1].setSampleRate(sampleRate);
}

auto Amp::process(StereoBlock<float> const& buffer, ControlInput const& inputs) -> void
{
auto const gainKnob = _gainKnob(inputs.gainKnob);
auto const toneKnob = _toneKnob(inputs.toneKnob);
auto const outputKnob = _outputKnob(inputs.outputKnob);
auto const mixKnob = _mixKnob(inputs.mixKnob);

auto const gainCV = _gainCV(inputs.gainCV);
auto const toneCV = _toneCV(inputs.toneCV);
auto const outputCV = _outputCV(inputs.outputCV);
auto const mixCV = _mixCV(inputs.mixCV);

auto const parameter = Channel::Parameter{
.mode = inputs.mode,
.gain = etl::clamp(gainKnob + gainCV, 0.0F, 1.0F),
.tone = etl::clamp(toneKnob + toneCV, 0.0F, 1.0F),
.output = etl::clamp(outputKnob + outputCV, 0.0F, 1.0F),
.mix = etl::clamp(mixKnob + mixCV, 0.0F, 1.0F),
};

for (auto& channel : _channels) {
channel.setParameter(parameter);
}

for (auto i = size_t(0); i < buffer.extent(1); ++i) {
buffer(0, i) = etl::invoke(_channels[0], buffer(0, i));
buffer(1, i) = etl::invoke(_channels[1], buffer(1, i));
}
}

auto Amp::Channel::setParameter(Parameter const& parameter) -> void
{
if (parameter.mode != _mode) {
_fire.reset();
_grind.reset();
}

_mode = parameter.mode;

if (parameter.mode == Mode::Fire) {
_fire.setParameter({parameter.gain, parameter.tone, parameter.output, parameter.mix});
} else {
_grind.setParameter({parameter.gain, parameter.tone, parameter.output, parameter.mix});
}
}

auto Amp::Channel::setSampleRate(float sampleRate) -> void
{
_fire.setSampleRate(sampleRate);
_grind.setSampleRate(sampleRate);
}

auto Amp::Channel::operator()(float sample) -> float
{
if (_mode == Mode::Fire) {
return _fire(sample);
}
return _grind(sample);
}

} // namespace grit
78 changes: 78 additions & 0 deletions lib/grit/eurorack/amp.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#pragma once

#include <grit/audio/airwindows/airwindows_fire_amp.hpp>
#include <grit/audio/airwindows/airwindows_grind_amp.hpp>
#include <grit/audio/filter/dynamic_smoothing.hpp>
#include <grit/audio/stereo/stereo_block.hpp>

#include <etl/array.hpp>

namespace grit {

struct Amp
{
enum struct Mode
{
Fire,
Grind,
};

struct ControlInput
{
Mode mode{Mode::Fire};

float gainKnob{0};
float toneKnob{0};
float outputKnob{0};
float mixKnob{0};

float gainCV{0};
float toneCV{0};
float outputCV{0};
float mixCV{0};
};

Amp() = default;

auto prepare(float sampleRate, etl::size_t blockSize) -> void;
auto process(StereoBlock<float> const& buffer, ControlInput const& inputs) -> void;

private:
struct Channel
{
struct Parameter
{
Mode mode{Mode::Fire};
float gain{0};
float tone{0};
float output{0};
float mix{0};
};

Channel() = default;

auto setParameter(Parameter const& parameter) -> void;
auto setSampleRate(float sampleRate) -> void;

[[nodiscard]] auto operator()(float sample) -> float;

private:
Mode _mode{Mode::Fire};

AirWindowsFireAmp<float> _fire{};
AirWindowsGrindAmp<float> _grind{};
};

DynamicSmoothing<float> _gainKnob{};
DynamicSmoothing<float> _toneKnob{};
DynamicSmoothing<float> _outputKnob{};
DynamicSmoothing<float> _mixKnob{};
DynamicSmoothing<float> _gainCV{};
DynamicSmoothing<float> _toneCV{};
DynamicSmoothing<float> _outputCV{};
DynamicSmoothing<float> _mixCV{};

etl::array<Channel, 2> _channels{};
};

} // namespace grit
144 changes: 4 additions & 140 deletions src/amp/main.cpp
Original file line number Diff line number Diff line change
@@ -1,149 +1,13 @@
#include <grit/eurorack/hades.hpp>
#include <grit/eurorack/amp.hpp>

#include <daisy_patch_sm.h>

namespace amp {

struct Amp
{
enum struct Mode
{
Fire,
Grind,
};

struct ControlInput
{
Mode mode{Mode::Fire};

float gainKnob{0};
float toneKnob{0};
float outputKnob{0};
float mixKnob{0};

float gainCV{0};
float toneCV{0};
float outputCV{0};
float mixCV{0};
};

Amp() = default;

auto prepare(float sampleRate, etl::size_t blockSize) -> void
{
auto const blockRate = sampleRate / static_cast<float>(blockSize);

_gainKnob.setSampleRate(blockRate);
_toneKnob.setSampleRate(blockRate);
_outputKnob.setSampleRate(blockRate);
_mixKnob.setSampleRate(blockRate);
_gainCV.setSampleRate(blockRate);
_toneCV.setSampleRate(blockRate);
_outputCV.setSampleRate(blockRate);
_mixCV.setSampleRate(blockRate);

_channels[0].setSampleRate(sampleRate);
_channels[1].setSampleRate(sampleRate);
}

[[nodiscard]] auto process(grit::StereoBlock<float> const& buffer, ControlInput const& inputs) -> void
{
auto const gainKnob = _gainKnob(inputs.gainKnob);
auto const toneKnob = _toneKnob(inputs.toneKnob);
auto const outputKnob = _outputKnob(inputs.outputKnob);
auto const mixKnob = _mixKnob(inputs.mixKnob);

auto const gainCV = _gainCV(inputs.gainCV);
auto const toneCV = _toneCV(inputs.toneCV);
auto const outputCV = _outputCV(inputs.outputCV);
auto const mixCV = _mixCV(inputs.mixCV);

auto const parameter = Channel::Parameter{
.mode = inputs.mode,
.gain = etl::clamp(gainKnob + gainCV, 0.0F, 1.0F),
.tone = etl::clamp(toneKnob + toneCV, 0.0F, 1.0F),
.output = etl::clamp(outputKnob + outputCV, 0.0F, 1.0F),
.mix = etl::clamp(mixKnob + mixCV, 0.0F, 1.0F),
};

for (auto& channel : _channels) {
channel.setParameter(parameter);
}

for (auto i = size_t(0); i < buffer.extent(1); ++i) {
buffer(0, i) = etl::invoke(_channels[0], buffer(0, i));
buffer(1, i) = etl::invoke(_channels[1], buffer(1, i));
}
}

private:
struct Channel
{
struct Parameter
{
Mode mode{Mode::Fire};
float gain{0};
float tone{0};
float output{0};
float mix{0};
};

Channel() = default;

auto setParameter(Parameter const& parameter) -> void
{
if (parameter.mode != _mode) {
_fire.reset();
_grind.reset();
}

_mode = parameter.mode;

if (parameter.mode == Mode::Fire) {
_fire.setParameter({parameter.gain, parameter.tone, parameter.output, parameter.mix});
} else {
_grind.setParameter({parameter.gain, parameter.tone, parameter.output, parameter.mix});
}
}

auto setSampleRate(float sampleRate) -> void
{
_fire.setSampleRate(sampleRate);
_grind.setSampleRate(sampleRate);
}

[[nodiscard]] auto operator()(float sample) -> float
{
if (_mode == Mode::Fire) {
return _fire(sample);
} else {
return _grind(sample);
}
}

private:
Mode _mode{Mode::Fire};

grit::AirWindowsFireAmp<float> _fire{};
grit::AirWindowsGrindAmp<float> _grind{};
};

grit::DynamicSmoothing<float> _gainKnob{};
grit::DynamicSmoothing<float> _toneKnob{};
grit::DynamicSmoothing<float> _outputKnob{};
grit::DynamicSmoothing<float> _mixKnob{};
grit::DynamicSmoothing<float> _gainCV{};
grit::DynamicSmoothing<float> _toneCV{};
grit::DynamicSmoothing<float> _outputCV{};
grit::DynamicSmoothing<float> _mixCV{};

etl::array<Channel, 2> _channels{};
};

static constexpr auto blockSize = 32U;
static constexpr auto sampleRate = 96'000.0F;

auto processor = Amp{};
auto processor = grit::Amp{};
auto patch = daisy::patch_sm::DaisyPatchSM{};
auto button = daisy::Switch{};
auto toggle = daisy::Switch{};
Expand All @@ -163,8 +27,8 @@ auto audioCallback(daisy::AudioHandle::InputBuffer in, daisy::AudioHandle::Outpu
block(1, i) = in[1][i];
}

auto const controls = Amp::ControlInput{
.mode = toggle.Pressed() ? Amp::Mode::Fire : Amp::Mode::Grind,
auto const controls = grit::Amp::ControlInput{
.mode = toggle.Pressed() ? grit::Amp::Mode::Fire : grit::Amp::Mode::Grind,
.gainKnob = patch.GetAdcValue(daisy::patch_sm::CV_1),
.toneKnob = patch.GetAdcValue(daisy::patch_sm::CV_2),
.outputKnob = patch.GetAdcValue(daisy::patch_sm::CV_3),
Expand Down

0 comments on commit 204b4a3

Please sign in to comment.