refactor: IEffect interface

This commit is contained in:
2023-09-10 06:38:41 +04:00
parent bb3ccc296a
commit c76f3ef3f8
7 changed files with 63 additions and 65 deletions

View File

@@ -1,9 +1,9 @@
#pragma once #pragma once
#include "Effect.h" #include "IEffect.h"
#include "Ramp.h" #include "Ramp.h"
#include <cstddef> #include <cstddef>
class ADSR : public Effect { class ADSR : public IEffect {
enum ADSRState { sOff, sAttack, sDecay, sSustain, sRelease }; enum ADSRState { sOff, sAttack, sDecay, sSustain, sRelease };
private: private:
@@ -14,11 +14,11 @@ class ADSR : public Effect {
ADSRState m_state; ADSRState m_state;
Ramp* m_ramp; Ramp* m_ramp;
void process_sample(float* sample); void ProcessSample(float* sample);
bool is_attack_elapsed(); bool IsAttackElapsed();
bool is_decay_elapsed(); bool IsDecayElapsed();
bool is_release_elapsed(); bool IsReleaseElapsed();
void recheck_state(); void RecheckState();
public: public:
ADSR(/* args */); ADSR(/* args */);

View File

@@ -1,12 +0,0 @@
#pragma once
#include <vector>
class Effect {
private:
/* data */
public:
Effect(/* args */){};
~Effect(){};
virtual void Trigger(){};
virtual void Release(){};
virtual void Process(std::vector<float>& samples){};
};

View File

@@ -1,5 +1,5 @@
#pragma once #pragma once
#include "Effect.h" #include "IEffect.h"
enum FilterType { enum FilterType {
LowPass, LowPass,
@@ -7,7 +7,7 @@ enum FilterType {
HighPass HighPass
}; };
class Filter : public Effect { class Filter : public IEffect {
protected: protected:
float m_freq; // cutoff frequency float m_freq; // cutoff frequency
float m_q; // filter quantity (resonance) float m_q; // filter quantity (resonance)
@@ -23,10 +23,10 @@ class Filter : public Effect {
public: public:
Filter(/* args */); Filter(/* args */);
virtual ~Filter(); virtual ~Filter();
void Trigger() override; void Trigger() override final;
void Release() override; void Release() override final;
float Process(float in); float Process(float in);
void Process(std::vector<float>& samples) override; void Process(std::vector<float>& samples) override final;
void SetParameters(float freq, float res, float q); void SetParameters(float freq, float res, float q);
float GetFreq() { return m_freq; } float GetFreq() { return m_freq; }
float GetRes() { return m_q; } float GetRes() { return m_q; }

10
inc/IEffect.h Normal file
View File

@@ -0,0 +1,10 @@
#pragma once
#include <vector>
class IEffect {
private:
/* data */
public:
virtual void Trigger() = 0;
virtual void Release() = 0;
virtual void Process(std::vector<float>& samples) = 0;
};

View File

@@ -3,7 +3,7 @@
#include "ADSR.h" #include "ADSR.h"
#include "Filter.h" #include "Filter.h"
#include "Adder.h" #include "Adder.h"
#include "Effect.h" #include "IEffect.h"
#include "Note.h" #include "Note.h"
#include "Oscillator.h" #include "Oscillator.h"
#include "Settings.h" #include "Settings.h"
@@ -13,23 +13,23 @@ class Synth {
private: private:
bool is_note_triggered; bool is_note_triggered;
std::vector<Oscillator*> m_oscillators; std::vector<Oscillator*> m_oscillators;
std::vector<Effect*> m_effects; std::vector<IEffect*> m_effects;
std::vector<float> m_out_signal; std::vector<float> m_out_signal;
Oscillator* m_lfo; Oscillator* m_lfo;
void zero_signal(); void ZeroSignal();
void get_note(); void GetNote();
void trigger_note_on_effects(); void TriggerNoteOnEffects();
void untrigger_note_on_effects(); void UntriggerNoteOnEffects();
void apply_effects(); void ApplyEffects();
void add_oscillator(); void AddOscillator();
void apply_filter_lfo(); void ApplyFilterLfo();
public: public:
Synth(/* args */); Synth(/* args */);
~Synth(); ~Synth();
void Trigger(Note input); void Trigger(Note input);
void Process(); void Process();
void Release(); void Release();
void AddEffect(Effect* fx); void AddEffect(IEffect* fx);
const std::vector<float>& GetOutSignal() { return m_out_signal; } const std::vector<float>& GetOutSignal() { return m_out_signal; }
const std::vector<Oscillator*>& GetOscillators() { return m_oscillators; } const std::vector<Oscillator*>& GetOscillators() { return m_oscillators; }
const bool& GetIsNoteTriggered() { return is_note_triggered; } const bool& GetIsNoteTriggered() { return is_note_triggered; }

View File

@@ -12,33 +12,33 @@ ADSR::ADSR(/* args */) {
ADSR::~ADSR() { delete m_ramp; } ADSR::~ADSR() { delete m_ramp; }
bool ADSR::is_attack_elapsed() { bool ADSR::IsAttackElapsed() {
return m_state == sAttack && m_ramp->IsCompleted(); return m_state == sAttack && m_ramp->IsCompleted();
} }
bool ADSR::is_decay_elapsed() { bool ADSR::IsDecayElapsed() {
return m_state == sDecay && m_ramp->IsCompleted(); return m_state == sDecay && m_ramp->IsCompleted();
} }
bool ADSR::is_release_elapsed() { bool ADSR::IsReleaseElapsed() {
return m_state == sRelease && m_ramp->IsCompleted(); return m_state == sRelease && m_ramp->IsCompleted();
} }
void ADSR::recheck_state() { void ADSR::RecheckState() {
switch (m_state) { switch (m_state) {
case sAttack: case sAttack:
if (is_attack_elapsed()) { if (IsAttackElapsed()) {
m_state = sDecay; m_state = sDecay;
m_ramp->RampTo(m_sustain_level, m_decay_time); m_ramp->RampTo(m_sustain_level, m_decay_time);
} }
break; break;
case sDecay: case sDecay:
if (is_decay_elapsed()) { if (IsDecayElapsed()) {
m_state = sSustain; m_state = sSustain;
} }
break; break;
case sRelease: case sRelease:
if (is_release_elapsed()) { if (IsReleaseElapsed()) {
m_state = sOff; m_state = sOff;
} }
break; break;
@@ -47,7 +47,7 @@ void ADSR::recheck_state() {
} }
} }
void ADSR::process_sample(float* sample) { void ADSR::ProcessSample(float* sample) {
if (m_state == sOff) { if (m_state == sOff) {
(*sample) = 0; (*sample) = 0;
} else if (m_state == sAttack) { } else if (m_state == sAttack) {
@@ -80,8 +80,8 @@ void ADSR::Release() {
void ADSR::Process(std::vector<float>& samples) { void ADSR::Process(std::vector<float>& samples) {
for (std::size_t i = 0; i < samples.size(); i++) { for (std::size_t i = 0; i < samples.size(); i++) {
recheck_state(); RecheckState();
process_sample(&samples[i]); ProcessSample(&samples[i]);
} }
} }

View File

@@ -7,15 +7,15 @@
Synth::Synth(/* args */) { Synth::Synth(/* args */) {
m_lfo = new Oscillator(OscillatorType::Sine, 5.f, VOLUME); m_lfo = new Oscillator(OscillatorType::Sine, 5.f, VOLUME);
add_oscillator(); AddOscillator();
add_oscillator(); AddOscillator();
AddEffect(new ADSR()); AddEffect(new ADSR());
AddEffect(FilterFactory::GetDefaultFilter()); AddEffect(FilterFactory::GetDefaultFilter());
for (size_t i = 0; i < STREAM_BUFFER_SIZE; i++) { for (size_t i = 0; i < STREAM_BUFFER_SIZE; i++) {
float sample = 0.0f; float sample = 0.0f;
m_out_signal.push_back(sample); m_out_signal.push_back(sample);
} }
zero_signal(); ZeroSignal();
} }
Synth::~Synth() { Synth::~Synth() {
@@ -24,37 +24,37 @@ Synth::~Synth() {
m_out_signal.clear(); m_out_signal.clear();
} }
void Synth::zero_signal() { void Synth::ZeroSignal() {
float sample = 0.0f; float sample = 0.0f;
for (size_t i = 0; i < STREAM_BUFFER_SIZE; i++) { for (size_t i = 0; i < STREAM_BUFFER_SIZE; i++) {
m_out_signal[i] = sample; m_out_signal[i] = sample;
} }
} }
void Synth::get_note() { void Synth::GetNote() {
zero_signal(); ZeroSignal();
Adder::SumOscillators(m_oscillators, m_out_signal); Adder::SumOscillators(m_oscillators, m_out_signal);
} }
void Synth::apply_effects() { void Synth::ApplyEffects() {
for (Effect* effect : m_effects) { for (IEffect* effect : m_effects) {
effect->Process(m_out_signal); effect->Process(m_out_signal);
} }
} }
void Synth::trigger_note_on_effects() { void Synth::TriggerNoteOnEffects() {
for (Effect* effect : m_effects) { for (IEffect* effect : m_effects) {
effect->Trigger(); effect->Trigger();
} }
} }
void Synth::untrigger_note_on_effects() { void Synth::UntriggerNoteOnEffects() {
for (Effect* effect : m_effects) { for (IEffect* effect : m_effects) {
effect->Release(); effect->Release();
} }
} }
void Synth::add_oscillator() { void Synth::AddOscillator() {
m_oscillators.push_back( m_oscillators.push_back(
new Oscillator(OscillatorType::Sine, 440.f, VOLUME)); new Oscillator(OscillatorType::Sine, 440.f, VOLUME));
} }
@@ -67,11 +67,11 @@ void Synth::Trigger(Note input) {
osc->SetFreq(hz); osc->SetFreq(hz);
} }
is_note_triggered = true; is_note_triggered = true;
trigger_note_on_effects(); TriggerNoteOnEffects();
} }
// todo: fix this // todo: fix this
void Synth::apply_filter_lfo() { void Synth::ApplyFilterLfo() {
float dt = m_lfo->Process(); float dt = m_lfo->Process();
Filter* filter = (Filter*)m_effects[1]; Filter* filter = (Filter*)m_effects[1];
float freq = filter->GetFreq(); float freq = filter->GetFreq();
@@ -82,18 +82,18 @@ void Synth::apply_filter_lfo() {
void Synth::Process() { void Synth::Process() {
//todo: on each sample. //todo: on each sample.
//in order to do that, we need to move to per-sample processing //in order to do that, we need to move to per-sample processing
apply_filter_lfo(); ApplyFilterLfo();
get_note(); GetNote();
apply_effects(); ApplyEffects();
} }
void Synth::Release() { void Synth::Release() {
zero_signal(); ZeroSignal();
is_note_triggered = false; is_note_triggered = false;
untrigger_note_on_effects(); UntriggerNoteOnEffects();
} }
void Synth::AddEffect(Effect* fx) { m_effects.push_back(fx); } void Synth::AddEffect(IEffect* fx) { m_effects.push_back(fx); }
void Synth::SetFilter(FilterType type) { void Synth::SetFilter(FilterType type) {
Filter* old_filter = this->GetFilter(); Filter* old_filter = this->GetFilter();