From 2e824d26b8c918f301ed5aaea3b6a11d46b7d4fe Mon Sep 17 00:00:00 2001 From: Christian Colglazier Date: Sun, 7 Nov 2021 16:12:41 -0500 Subject: [PATCH] Basic AD droplet --- src/droplets/ad_droplet.cpp | 94 +++++++++++++++++++++++++++++++++++++ src/droplets/ad_droplet.h | 76 ++++++++++++++++++++++++++++++ src/main.cpp | 4 ++ src/main.h | 1 + src/menu.cpp | 1 + src/menu_item.h | 2 +- 6 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 src/droplets/ad_droplet.cpp create mode 100644 src/droplets/ad_droplet.h diff --git a/src/droplets/ad_droplet.cpp b/src/droplets/ad_droplet.cpp new file mode 100644 index 0000000..f69678c --- /dev/null +++ b/src/droplets/ad_droplet.cpp @@ -0,0 +1,94 @@ +#include "ad_droplet.h" + +void AD::Init(DaisyPatch* m_patch, + float sample_rate, + AnalogControl attack_knob, + AnalogControl decay_knob) { + patch = m_patch; + env.Init(sample_rate); + env.SetMax(1.0f); + env.SetMin(0.0f); + env.SetCurve(0.0f); + attack_param.Init(attack_knob, .01f, 3.0f, Parameter::EXPONENTIAL); + decay_param.Init(decay_knob, .01f, 3.0f, Parameter::EXPONENTIAL); + } + +void AD::Process(DacHandle::Channel chn, + DaisyPatch::GateInput gate) { + if(patch->gate_input[gate].Trig()) { + env.Trigger(); + } + + env.SetTime(ADENV_SEG_ATTACK, attack_param.Process()); + env.SetTime(ADENV_SEG_DECAY, decay_param.Process()); + + sig = env.Process(); + patch->seed.dac.WriteValue(chn, + sig * 4095.0f); +} + +float AD::GetSignal() { + return sig; +} + +ADDroplet::ADDroplet(DaisyPatch* m_patch, + DropletState m_state, + float sample_rate) : + Droplet(m_patch, + m_state) { + switch (GetState()) { + default: + case DropletState::kFull: + ad[0].Init(Patch(), + sample_rate, + Patch()->controls[Patch()->CTRL_1], + Patch()->controls[Patch()->CTRL_2]); + ad[1].Init(Patch(), + sample_rate, + Patch()->controls[Patch()->CTRL_3], + Patch()->controls[Patch()->CTRL_4]); + break; + case DropletState::kLeft: + ad[0].Init(Patch(), + sample_rate, + Patch()->controls[Patch()->CTRL_1], + Patch()->controls[Patch()->CTRL_2]); + break; + case DropletState::kRight: + ad[0].Init(Patch(), + sample_rate, + Patch()->controls[Patch()->CTRL_3], + Patch()->controls[Patch()->CTRL_4]); + break; + } +} + +ADDroplet::~ADDroplet() {} + +void ADDroplet::Control() {} + +void ADDroplet::Process(AudioHandle::InputBuffer in, AudioHandle::OutputBuffer out, size_t size) { + Patch()->ProcessAnalogControls(); + + for(size_t i = 0; i < size; i++) { + if (GetState() == DropletState::kRight) { + ad[0].Process(DacHandle::Channel::TWO, DaisyPatch::GATE_IN_2); + } else { + ad[0].Process(DacHandle::Channel::ONE, DaisyPatch::GATE_IN_1); + } + if (GetState() == DropletState::kFull) { + ad[1].Process(DacHandle::Channel::TWO, DaisyPatch::GATE_IN_2); + } + int env_sel = 0; + for (size_t chn = GetChannelMin(); chn < GetChannelMax(); chn++) { + if(GetState() == DropletState::kFull && chn > 1) { + env_sel = 1; + } + out[chn][i] = in[chn][i] * ad[env_sel].GetSignal(); + } + } +} + +void ADDroplet::Draw() { + DrawName("AD"); +} diff --git a/src/droplets/ad_droplet.h b/src/droplets/ad_droplet.h new file mode 100644 index 0000000..7c08ead --- /dev/null +++ b/src/droplets/ad_droplet.h @@ -0,0 +1,76 @@ +#pragma once + +#ifndef CASCADE_DROPLETS_AD_DROPLET_H_ +#define CASCADE_DROPLETS_AD_DROPLET_H_ + +#include "daisysp.h" +#include "daisy_patch.h" + +#include "droplet.h" +#include "../util.h" + +using namespace daisy; +using namespace daisysp; + +class AD { +private: + AdEnv env; + Parameter attack_param; + Parameter decay_param; + Parameter curve_param; + float sig; + DaisyPatch* patch; +public: + void Init(DaisyPatch* m_patch, + float samplerate, + AnalogControl attackKnob, + AnalogControl decaynob); + + void Process(DacHandle::Channel chn, DaisyPatch::GateInput gate); + + float GetSignal(); +}; + +class ADDroplet: public Droplet { +private: + AD ad[2]; + +public: + /* + * Constructor for a AD droplet. + * + * @param m_patch pointer to patch + * @param m_state droplet position + */ + ADDroplet(DaisyPatch* m_patch, + DropletState m_state, + float sample_rate); + + /* + * Destructor for vco droplet. + */ + ~ADDroplet(); + + /* + * Processes user controls and inputs. + */ + void Control(); + + /* + * Processes audio input and outputs. + * + * @param in the audio inputs for the patch + * @param out the audio outputs for the patch + * @param size the number of inputs and outputs + */ + void Process(AudioHandle::InputBuffer in, + AudioHandle::OutputBuffer out, + size_t size); + + /* + * Processes information to be shown on the display. + */ + void Draw(); +}; + +#endif // CASCADE_DROPLETS_AD_DROPLET_H_ diff --git a/src/main.cpp b/src/main.cpp index 4aefe8e..b838207 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -115,6 +115,10 @@ static void AudioThrough(AudioHandle::InputBuffer in, Droplet* GetDroplet(DropletState state) { switch(selected_menu->GetState()) { default: + case MenuState::kAD: + return new ADDroplet(&patch, + state, + sample_rate); case MenuState::kLFO: return new LFODroplet(&patch, state, diff --git a/src/main.h b/src/main.h index 39bbef4..795178d 100644 --- a/src/main.h +++ b/src/main.h @@ -12,6 +12,7 @@ #include "menu.h" #include "droplets/droplet.h" #include "droplets/droplet_manager.h" +#include "droplets/ad_droplet.h" #include "droplets/lfo_droplet.h" #include "droplets/mixer_droplet.h" #include "droplets/noise_droplet.h" diff --git a/src/menu.cpp b/src/menu.cpp index b6728d6..569825c 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -9,6 +9,7 @@ Menu::Menu(DaisyPatch* m_patch, head = new MenuItem(MenuState::kSplit, "Split"); head->AddItemEnd(new MenuItem(MenuState::kChange, "")); + head->AddItemEnd(new MenuItem(MenuState::kAD, "AD")); head->AddItemEnd(new MenuItem(MenuState::kLFO, "LFO")); head->AddItemEnd(new MenuItem(MenuState::kMixer, "Mixer")); head->AddItemEnd(new MenuItem(MenuState::kNoise, "Noise")); diff --git a/src/menu_item.h b/src/menu_item.h index 2e29c60..22ccbdd 100644 --- a/src/menu_item.h +++ b/src/menu_item.h @@ -5,7 +5,7 @@ #include -enum class MenuState {kSplit, kChange, kLFO, kMixer, kNoise, kVCA, kVCO}; +enum class MenuState {kSplit, kChange, kAD, kLFO, kMixer, kNoise, kVCA, kVCO}; class MenuItem { private: