[refactor]: trigger-process-release therms
This commit is contained in:
@@ -10,7 +10,7 @@ struct ADSRParameters {
|
|||||||
float release_time;
|
float release_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ADSRState { Off, Attack, Decay, Sustain, Release };
|
enum ADSRState { sOff, sAttack, sDecay, sSustain, sRelease };
|
||||||
|
|
||||||
class ADSR : public Effect {
|
class ADSR : public Effect {
|
||||||
private:
|
private:
|
||||||
@@ -28,8 +28,8 @@ class ADSR : public Effect {
|
|||||||
ADSR(/* args */);
|
ADSR(/* args */);
|
||||||
ADSR(ADSRParameters param);
|
ADSR(ADSRParameters param);
|
||||||
~ADSR();
|
~ADSR();
|
||||||
void OnSetNote() override;
|
void Trigger() override;
|
||||||
void OnUnsetNote() override;
|
void Release() override;
|
||||||
// void RetriggerState() override;
|
// void RetriggerState() override;
|
||||||
void Process(std::vector<float>& samples) override;
|
void Process(std::vector<float>& samples) override;
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ class Effect {
|
|||||||
public:
|
public:
|
||||||
Effect(/* args */){};
|
Effect(/* args */){};
|
||||||
~Effect(){};
|
~Effect(){};
|
||||||
virtual void OnSetNote(){};
|
virtual void Trigger(){};
|
||||||
virtual void OnUnsetNote(){};
|
virtual void Release(){};
|
||||||
// virtual void RetriggerState(){};
|
// virtual void RetriggerState(){};
|
||||||
virtual void Process(std::vector<float>& samples){};
|
virtual void Process(std::vector<float>& samples){};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -25,9 +25,9 @@ class Synth {
|
|||||||
public:
|
public:
|
||||||
Synth(/* args */);
|
Synth(/* args */);
|
||||||
~Synth();
|
~Synth();
|
||||||
void TriggerNote(Note input);
|
void Trigger(Note input);
|
||||||
void ProduceSound();
|
void Process();
|
||||||
void StopSound();
|
void Release();
|
||||||
void AddOscillator();
|
void AddOscillator();
|
||||||
void AddEffect(Effect* fx);
|
void AddEffect(Effect* fx);
|
||||||
const std::vector<float>& GetOutSignal() { return m_out_signal; }
|
const std::vector<float>& GetOutSignal() { return m_out_signal; }
|
||||||
|
|||||||
42
src/ADSR.cpp
42
src/ADSR.cpp
@@ -15,34 +15,34 @@ ADSR::ADSR(ADSRParameters param) { m_parameters = param; }
|
|||||||
ADSR::~ADSR() { delete m_ramp; }
|
ADSR::~ADSR() { delete m_ramp; }
|
||||||
|
|
||||||
bool ADSR::is_attack_elapsed() {
|
bool ADSR::is_attack_elapsed() {
|
||||||
return m_state == Attack && m_ramp->IsCompleted();
|
return m_state == sAttack && m_ramp->IsCompleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ADSR::is_decay_elapsed() {
|
bool ADSR::is_decay_elapsed() {
|
||||||
return m_state == Decay && m_ramp->IsCompleted();
|
return m_state == sDecay && m_ramp->IsCompleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ADSR::is_release_elapsed() {
|
bool ADSR::is_release_elapsed() {
|
||||||
return m_state == Release && m_ramp->IsCompleted();
|
return m_state == sRelease && m_ramp->IsCompleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ADSR::recheck_state() {
|
void ADSR::recheck_state() {
|
||||||
switch (m_state) {
|
switch (m_state) {
|
||||||
case Attack:
|
case sAttack:
|
||||||
if (is_attack_elapsed()) {
|
if (is_attack_elapsed()) {
|
||||||
m_state = Decay;
|
m_state = sDecay;
|
||||||
m_ramp->RampTo(m_parameters.sustain_level,
|
m_ramp->RampTo(m_parameters.sustain_level,
|
||||||
m_parameters.decay_time);
|
m_parameters.decay_time);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Decay:
|
case sDecay:
|
||||||
if (is_decay_elapsed()) {
|
if (is_decay_elapsed()) {
|
||||||
m_state = Sustain;
|
m_state = sSustain;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Release:
|
case sRelease:
|
||||||
if (is_release_elapsed()) {
|
if (is_release_elapsed()) {
|
||||||
m_state = Off;
|
m_state = sOff;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -51,33 +51,33 @@ void ADSR::recheck_state() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ADSR::process_sample(float* sample) {
|
void ADSR::process_sample(float* sample) {
|
||||||
if (m_state == Off) {
|
if (m_state == sOff) {
|
||||||
(*sample) = 0;
|
(*sample) = 0;
|
||||||
} else if (m_state == Attack) {
|
} else if (m_state == sAttack) {
|
||||||
(*sample) = (*sample) * m_ramp->Process();
|
(*sample) = (*sample) * m_ramp->Process();
|
||||||
} else if (m_state == Decay) {
|
} else if (m_state == sDecay) {
|
||||||
(*sample) = (*sample) * m_ramp->Process();
|
(*sample) = (*sample) * m_ramp->Process();
|
||||||
} else if (m_state == Sustain) {
|
} else if (m_state == sSustain) {
|
||||||
(*sample) = (*sample) * m_parameters.sustain_level;
|
(*sample) = (*sample) * m_parameters.sustain_level;
|
||||||
} else if (m_state == Release) {
|
} else if (m_state == sRelease) {
|
||||||
(*sample) = (*sample) * m_ramp->Process();
|
(*sample) = (*sample) * m_ramp->Process();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ADSR::OnSetNote() {
|
void ADSR::Trigger() {
|
||||||
write_log("Set ADSR\n");
|
write_log("Set ADSR\n");
|
||||||
if (m_state == Off) {
|
if (m_state == sOff) {
|
||||||
m_state = Attack;
|
m_state = sAttack;
|
||||||
} else if (m_state == Release) {
|
} else if (m_state == sRelease) {
|
||||||
m_state = Attack;
|
m_state = sAttack;
|
||||||
};
|
};
|
||||||
|
|
||||||
m_ramp->RampTo(1, m_parameters.attack_time);
|
m_ramp->RampTo(1, m_parameters.attack_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ADSR::OnUnsetNote() {
|
void ADSR::Release() {
|
||||||
write_log("Unset ADSR\n");
|
write_log("Unset ADSR\n");
|
||||||
m_state = Release;
|
m_state = sRelease;
|
||||||
m_ramp->RampTo(0, m_parameters.release_time);
|
m_ramp->RampTo(0, m_parameters.release_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -96,16 +96,16 @@ void Application::update_on_note_input() {
|
|||||||
if (detect_note_pressed(m_current_note)) {
|
if (detect_note_pressed(m_current_note)) {
|
||||||
|
|
||||||
if (!m_synth.GetIsNoteTriggered()) {
|
if (!m_synth.GetIsNoteTriggered()) {
|
||||||
m_synth.TriggerNote((*m_current_note));
|
m_synth.Trigger((*m_current_note));
|
||||||
}
|
}
|
||||||
|
|
||||||
// m_sound_played_count = 0;
|
// m_sound_played_count = 0;
|
||||||
write_log("Note played: %s\n", m_current_note->name.c_str());
|
write_log("Note played: %s\n", m_current_note->name.c_str());
|
||||||
} else if (is_note_up() && m_synth.GetIsNoteTriggered()) {
|
} else if (is_note_up() && m_synth.GetIsNoteTriggered()) {
|
||||||
m_synth.StopSound();
|
m_synth.Release();
|
||||||
}
|
}
|
||||||
// will produce 0 signal if ADSR is in off state
|
// will produce 0 signal if ADSR is in off state
|
||||||
m_synth.ProduceSound();
|
m_synth.Process();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Play ring-buffered audio
|
// Play ring-buffered audio
|
||||||
|
|||||||
@@ -41,17 +41,17 @@ void Synth::apply_effects() {
|
|||||||
|
|
||||||
void Synth::trigger_note_on_effects() {
|
void Synth::trigger_note_on_effects() {
|
||||||
for (Effect* effect : m_effects) {
|
for (Effect* effect : m_effects) {
|
||||||
effect->OnSetNote();
|
effect->Trigger();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Synth::untrigger_note_on_effects() {
|
void Synth::untrigger_note_on_effects() {
|
||||||
for (Effect* effect : m_effects) {
|
for (Effect* effect : m_effects) {
|
||||||
effect->OnUnsetNote();
|
effect->Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Synth::TriggerNote(Note input) {
|
void Synth::Trigger(Note input) {
|
||||||
int semitone_shift = KeyBoard::GetSemitoneShift(input.name);
|
int semitone_shift = KeyBoard::GetSemitoneShift(input.name);
|
||||||
float hz = KeyBoard::GetHzBySemitone(semitone_shift);
|
float hz = KeyBoard::GetHzBySemitone(semitone_shift);
|
||||||
|
|
||||||
@@ -63,13 +63,13 @@ void Synth::TriggerNote(Note input) {
|
|||||||
trigger_note_on_effects();
|
trigger_note_on_effects();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Synth::ProduceSound() {
|
void Synth::Process() {
|
||||||
get_note();
|
get_note();
|
||||||
apply_effects();
|
apply_effects();
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: rename to something like untrigger note
|
// todo: rename to something like untrigger note
|
||||||
void Synth::StopSound() {
|
void Synth::Release() {
|
||||||
zero_signal();
|
zero_signal();
|
||||||
is_note_triggered = false;
|
is_note_triggered = false;
|
||||||
untrigger_note_on_effects();
|
untrigger_note_on_effects();
|
||||||
|
|||||||
Reference in New Issue
Block a user