AD envelope with splitting

This commit is contained in:
Christian Colglazier 2021-11-13 14:16:41 -05:00
parent 1ab75579c5
commit 5cc3195db3
14 changed files with 148 additions and 64 deletions

View File

@ -2,16 +2,15 @@
void AD::Init(DaisyPatch* m_patch,
float sample_rate,
AnalogControl attack_knob,
AnalogControl decay_knob) {
DropletState* m_state) {
patch = m_patch;
state = m_state;
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);
curve_param.Init(attack_knob, -10.f, 10.0f, Parameter::LINEAR);
SetControls();
}
void AD::Process(DacHandle::Channel chn,
@ -19,19 +18,26 @@ void AD::Process(DacHandle::Channel chn,
if(patch->gate_input[gate].Trig()) {
env.Trigger();
}
if (curve_menu) {
if (*state == DropletState::kFull) {
attack = attack_param.Process();
decay = decay_param.Process();
curve = curve_param.Process();
amp = amp_param.Process();
} else if (curve_menu) {
curve = curve_param.Process();
amp = amp_param.Process();
} else {
attack = attack_param.Process();
decay = decay_param.Process();
}
decay = decay_param.Process();
env.SetTime(ADENV_SEG_ATTACK, attack);
env.SetTime(ADENV_SEG_DECAY, decay);
env.SetCurve(curve);
sig = env.Process();
patch->seed.dac.WriteValue(chn,
sig * 4095.0f);
sig * amp * 4095.0f);
}
float AD::GetSignal() {
@ -50,6 +56,10 @@ float AD::GetCurve() {
return curve;
}
float AD::GetAmp() {
return amp;
}
bool AD::GetMenu() {
return curve_menu;
}
@ -58,36 +68,51 @@ void AD::ToggleCurve() {
curve_menu = !curve_menu;
}
ADDroplet::ADDroplet(DaisyPatch* m_patch,
DropletState m_state,
float sample_rate) :
Droplet(m_patch,
m_state) {
switch (GetState()) {
void AD::SetControls() {
AnalogControl attack_knob, decay_knob, curve_knob, amp_knob;
switch (*state) {
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]);
attack_knob = patch->controls[patch->CTRL_1];
decay_knob = patch->controls[patch->CTRL_2];
curve_knob = patch->controls[patch->CTRL_3];
amp_knob = 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]);
attack_knob = patch->controls[patch->CTRL_1];
decay_knob = patch->controls[patch->CTRL_2];
curve_knob = patch->controls[patch->CTRL_1];
amp_knob = 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]);
attack_knob = patch->controls[patch->CTRL_3];
decay_knob = patch->controls[patch->CTRL_4];
curve_knob = patch->controls[patch->CTRL_3];
amp_knob = patch->controls[patch->CTRL_4];
break;
}
attack_param.Init(attack_knob, .01f, 3.0f, Parameter::EXPONENTIAL);
decay_param.Init(decay_knob, .01f, 3.0f, Parameter::EXPONENTIAL);
curve_param.Init(curve_knob, -10.f, 10.0f, Parameter::LINEAR);
amp_param.Init(amp_knob, 0.0f, 1.0f, Parameter::LINEAR);
}
ADDroplet::ADDroplet(DaisyPatch* m_patch,
DropletState m_state,
float m_sample_rate) :
Droplet(m_patch,
m_state) {
sample_rate = m_sample_rate;
ad[0].Init(Patch(),
sample_rate,
&m_state);
if (m_state == DropletState::kFull) {
ad[1].Init(Patch(),
sample_rate,
&m_state);
}
}
ADDroplet::~ADDroplet() {}
@ -105,7 +130,6 @@ 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);
@ -120,7 +144,8 @@ void ADDroplet::Process(AudioHandle::InputBuffer in, AudioHandle::OutputBuffer o
if(GetState() == DropletState::kFull && chn > 1) {
env_sel = 1;
}
out[chn][i] = in[chn][i] * ad[env_sel].GetSignal();
out[chn][i] = in[chn][i] * ad[env_sel].GetSignal() *
ad[env_sel].GetAmp();
}
}
}
@ -146,36 +171,31 @@ void ADDroplet::Draw() {
Font_6x8,
"C: " +
FloatToString(ad[0].GetCurve(), 2));
if(GetState() == DropletState::kFull) {
int mid = (GetScreenMax() - GetScreenMin())/2;
WriteString(Patch(),
mid,
11,
Font_6x8,
"A: " +
FloatToString(ad[1].GetAttack(), 2) +
"s");
WriteString(Patch(),
mid,
21,
Font_6x8,
"D: " +
FloatToString(ad[1].GetDecay(), 2) +
"s");
WriteString(Patch(),
mid,
31,
Font_6x8,
"C: " +
FloatToString(ad[1].GetCurve(), 2));
}
WriteString(Patch(),
GetScreenMin()+3,
41,
Font_6x8,
"Amp: " +
FloatToString(ad[0].GetAmp(), 2));
if (ad[0].GetMenu()) {
DrawSolidRect(Patch(), GetScreenMin(), 30, GetScreenMin()+1, 39, true);
} else {
DrawSolidRect(Patch(), GetScreenMin(), 10, GetScreenMin()+1, 19, true);
if (GetState() != DropletState::kFull) {
if (ad[0].GetMenu()) {
DrawSolidRect(Patch(), GetScreenMin(), 30, GetScreenMin()+1, 49, true);
} else {
DrawSolidRect(Patch(), GetScreenMin(), 10, GetScreenMin()+1, 29, true);
}
}
DrawSolidRect(Patch(), GetScreenMin(), 20, GetScreenMin()+1, 29, true);
DrawName("AD");
}
void ADDroplet::UpdateStateCallback() {
ad[0].Init(Patch(),
sample_rate,
State());
if (GetState() == DropletState::kFull) {
ad[1].Init(Patch(),
sample_rate,
State());
}
}

View File

@ -16,17 +16,20 @@ class AD {
private:
AdEnv env;
float attack, decay, curve = 0;
float amp = 1.0f;
Parameter attack_param;
Parameter decay_param;
Parameter curve_param;
Parameter amp_param;
float sig;
DaisyPatch* patch;
bool curve_menu = false;
DropletState* state;
public:
void Init(DaisyPatch* m_patch,
float sample_rate,
AnalogControl attack_knob,
AnalogControl decay_knob);
DropletState* state);
void Process(DacHandle::Channel chn, DaisyPatch::GateInput gate);
@ -34,13 +37,16 @@ public:
float GetAttack();
float GetDecay();
float GetCurve();
float GetAmp();
bool GetMenu();
void ToggleCurve();
void SetControls();
};
class ADDroplet: public Droplet {
private:
AD ad[2];
float sample_rate;
public:
/*
@ -78,6 +84,11 @@ public:
* Processes information to be shown on the display.
*/
void Draw();
/*
* Runs when droplet state is updated.
*/
void UpdateStateCallback();
};
#endif // CASCADE_DROPLETS_AD_DROPLET_H_

View File

@ -9,6 +9,10 @@ DaisyPatch* Droplet::Patch() {
return patch;
}
DropletState* Droplet::State() {
return &state;
}
DropletState Droplet::GetState() {
return state;
}
@ -51,6 +55,7 @@ void Droplet::UpdateState(DropletState m_state) {
chn_min = 2;
screen_min = SSD1309_WIDTH / 2;
}
UpdateStateCallback();
}
void Droplet::AnimationInc() {

View File

@ -47,7 +47,7 @@ public:
/*
* Processes audio input and outputs.
*
2 *
* @param in the audio inputs for the patch
* @param out the audio outputs for the patch
* @param size the number of inputs and outputs
@ -62,12 +62,24 @@ public:
virtual void Draw()=0;
/*
* Returns patch
* Runs when droplet state is updated.
*/
virtual void UpdateStateCallback() {}
/*
* Returns patch.
*
* @return pointer to patch
*/
DaisyPatch* Patch();
/*
* Returns droplet state.
*
* @return pointer to state
*/
DropletState* State();
/*
* Returns the size of the droplet.
*

View File

@ -106,3 +106,5 @@ void LFODroplet::Draw() {
}
DrawName("LFO");
}
void LFODroplet::UpdateStateCallback() {}

View File

@ -77,6 +77,11 @@ public:
* Processes information to be shown on the display.
*/
void Draw();
/*
* Runs when droplet state is updated.
*/
void UpdateStateCallback();
};
#endif // CASCADE_DROPLETS_LFO_DROPLET_H_

View File

@ -58,3 +58,5 @@ void MixerDroplet::Process(AudioHandle::InputBuffer in, AudioHandle::OutputBuffe
void MixerDroplet::Draw() {
DrawName("Mixer");
}
void MixerDroplet::UpdateStateCallback() {}

View File

@ -51,6 +51,11 @@ public:
* Processes information to be shown on the display.
*/
void Draw();
/*
* Runs when droplet state is updated.
*/
void UpdateStateCallback();
};
#endif // CASCADE_DROPLETS_VCA_DROPLET_H_

View File

@ -26,3 +26,5 @@ void NoiseDroplet::Draw() {
}
DrawName("Noise");
}
void NoiseDroplet::UpdateStateCallback() {}

View File

@ -41,6 +41,11 @@ public:
* Processes information to be shown on the display.
*/
void Draw();
/*
* Runs when droplet state is updated.
*/
void UpdateStateCallback();
};
#endif // CASCADE_DROPLETS_NOISE_DROPLET_H_

View File

@ -109,3 +109,5 @@ void VCADroplet::Draw() {
}
DrawName("VCA");
}
void VCADroplet::UpdateStateCallback() {}

View File

@ -51,6 +51,11 @@ public:
* Processes information to be shown on the display.
*/
void Draw();
/*
* Runs when droplet state is updated.
*/
void UpdateStateCallback();
};
#endif // CASCADE_DROPLETS_VCA_DROPLET_H_

View File

@ -144,3 +144,5 @@ void VCODroplet::SetWaveShape(int ws) {
wave = ws % Oscillator::WAVE_LAST;
last_wave_ctrl = ws;
}
void VCODroplet::UpdateStateCallback() {}

View File

@ -68,6 +68,12 @@ public:
*/
void Draw();
/*
* Runs when droplet state is updated.
*/
void UpdateStateCallback();
/*
* Changes the wave shape of the VCO.
*