17
inc/ADSR.h
17
inc/ADSR.h
@@ -3,18 +3,14 @@
|
||||
#include "Ramp.h"
|
||||
#include <cstddef>
|
||||
|
||||
struct ADSRParameters {
|
||||
float attack_time; // Attack time in seconds
|
||||
float decay_time; // Decay time in seconds
|
||||
float sustain_level; // Sustain level (0 to 1)
|
||||
float release_time;
|
||||
};
|
||||
|
||||
enum ADSRState { sOff, sAttack, sDecay, sSustain, sRelease };
|
||||
|
||||
class ADSR : public Effect {
|
||||
enum ADSRState { sOff, sAttack, sDecay, sSustain, sRelease };
|
||||
|
||||
private:
|
||||
ADSRParameters m_parameters;
|
||||
float m_attack_time;
|
||||
float m_decay_time;
|
||||
float m_sustain_level;
|
||||
float m_release_time;
|
||||
ADSRState m_state;
|
||||
Ramp* m_ramp;
|
||||
|
||||
@@ -26,7 +22,6 @@ class ADSR : public Effect {
|
||||
|
||||
public:
|
||||
ADSR(/* args */);
|
||||
ADSR(ADSRParameters param);
|
||||
~ADSR();
|
||||
void Trigger() override;
|
||||
void Release() override;
|
||||
|
||||
@@ -13,7 +13,7 @@ struct Adder {
|
||||
for (size_t i = 0; i < sample_count; i++) {
|
||||
float sample = 0.0f;
|
||||
for (Oscillator* osc : oscillators) {
|
||||
sample += osc->GenerateSample(1.f);
|
||||
sample += osc->Process();
|
||||
}
|
||||
|
||||
signal[i] = sample;
|
||||
|
||||
@@ -13,11 +13,11 @@ class Application {
|
||||
int m_sound_played_count;
|
||||
Note* m_current_note;
|
||||
Renderer m_renderer;
|
||||
bool detect_note_pressed(Note* note);
|
||||
void init_synth();
|
||||
void init_audio();
|
||||
void update_on_note_input();
|
||||
void play_buffered_audio();
|
||||
bool DetectNotePressed(Note* note);
|
||||
void InitSynth();
|
||||
void InitAudio();
|
||||
void UpdateOnNoteInput();
|
||||
void PlayBufferedAudio();
|
||||
|
||||
public:
|
||||
Application(/* args */);
|
||||
|
||||
14
inc/BandPassFilter.h
Normal file
14
inc/BandPassFilter.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
#include "Filter.h"
|
||||
|
||||
class BandPassFilter : public Filter {
|
||||
private:
|
||||
void CalculateCoefficients() override;
|
||||
|
||||
public:
|
||||
BandPassFilter(Filter* filter);
|
||||
BandPassFilter(float freq, float res, float q);
|
||||
BandPassFilter(/* args */);
|
||||
~BandPassFilter();
|
||||
bool IsSameFilterType(FilterType type) override { return type == BandPass; };
|
||||
};
|
||||
35
inc/Filter.h
Normal file
35
inc/Filter.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
#include "Effect.h"
|
||||
|
||||
enum FilterType {
|
||||
LowPass,
|
||||
BandPass,
|
||||
HighPass
|
||||
};
|
||||
|
||||
class Filter : public Effect {
|
||||
protected:
|
||||
float m_freq; // cutoff frequency
|
||||
float m_q; // filter quantity (resonance)
|
||||
float m_order; // filter order (peakGain)
|
||||
/* todo: filter adsr */
|
||||
float m_norm, m_v, m_k;
|
||||
float m_a0, m_a1, m_a2, m_b1, m_b2;
|
||||
float m_z1, m_z2;
|
||||
|
||||
void CalculateNormals();
|
||||
virtual void CalculateCoefficients(){};
|
||||
|
||||
public:
|
||||
Filter(/* args */);
|
||||
virtual ~Filter();
|
||||
void Trigger() override;
|
||||
void Release() override;
|
||||
float Process(float in);
|
||||
void Process(std::vector<float>& samples) override;
|
||||
void SetParameters(float freq, float res, float q);
|
||||
float GetFreq() { return m_freq; }
|
||||
float GetRes() { return m_q; }
|
||||
float GetPeakGain() { return m_norm; }
|
||||
virtual bool IsSameFilterType(FilterType type){ return false; };
|
||||
};
|
||||
29
inc/FilterFactory.h
Normal file
29
inc/FilterFactory.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
#include "Filter.h"
|
||||
#include "LowPassFilter.h"
|
||||
#include "BandPassFilter.h"
|
||||
#include "HighPassFilter.h"
|
||||
|
||||
struct FilterFactory {
|
||||
static Filter* CreateFilter(Filter* old_filter, FilterType new_type) {
|
||||
Filter* new_filter;
|
||||
switch (new_type) {
|
||||
case LowPass:
|
||||
new_filter = new LowPassFilter(old_filter);
|
||||
break;
|
||||
case BandPass:
|
||||
new_filter = new BandPassFilter(old_filter);
|
||||
break;
|
||||
case HighPass:
|
||||
new_filter = new HighPassFilter(old_filter);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return new_filter;
|
||||
}
|
||||
|
||||
static Filter* GetDefaultFilter() {
|
||||
return new LowPassFilter();
|
||||
}
|
||||
};
|
||||
14
inc/HighPassFilter.h
Normal file
14
inc/HighPassFilter.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
#include "Filter.h"
|
||||
|
||||
class HighPassFilter : public Filter {
|
||||
private:
|
||||
void CalculateCoefficients() override;
|
||||
|
||||
public:
|
||||
HighPassFilter();
|
||||
HighPassFilter(Filter* filter);
|
||||
HighPassFilter(float freq, float res, float q);
|
||||
~HighPassFilter();
|
||||
bool IsSameFilterType(FilterType type) override { return type == HighPass; };
|
||||
};
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
class KeyBoard {
|
||||
private:
|
||||
static int get_semitone_shift_internal(const char* root_note,
|
||||
static int GetSemitoneShiftInternal(const char* root_note,
|
||||
char* target_note) {
|
||||
const char* pitch_classes[12] = {"C", "C#", "D", "D#", "E", "F",
|
||||
"F#", "G", "G#", "A", "A#", "B"};
|
||||
@@ -65,7 +65,7 @@ class KeyBoard {
|
||||
char* target_note_cstr = new char[target_note.length() + 1];
|
||||
strcpy(target_note_cstr, target_note.c_str());
|
||||
|
||||
int result = get_semitone_shift_internal("A4", target_note_cstr);
|
||||
int result = GetSemitoneShiftInternal("A4", target_note_cstr);
|
||||
|
||||
delete[] target_note_cstr;
|
||||
return result;
|
||||
|
||||
15
inc/LowPassFilter.h
Normal file
15
inc/LowPassFilter.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "Filter.h"
|
||||
|
||||
class LowPassFilter : public Filter {
|
||||
protected:
|
||||
void CalculateCoefficients() override;
|
||||
|
||||
public:
|
||||
LowPassFilter();
|
||||
LowPassFilter(Filter* filter);
|
||||
LowPassFilter(float freq, float res, float q);
|
||||
~LowPassFilter();
|
||||
bool IsSameFilterType(FilterType type) override { return type == LowPass; };
|
||||
};
|
||||
@@ -31,5 +31,5 @@ class Oscillator {
|
||||
float GetFreq() { return m_freq; }
|
||||
void SetFreq(float freq);
|
||||
void Reset();
|
||||
float GenerateSample(float duration);
|
||||
float Process();
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "ADSR.h"
|
||||
#include "Filter.h"
|
||||
#include "Synth.h"
|
||||
#include "SynthGuiState.h"
|
||||
#include "raylib.h"
|
||||
@@ -19,6 +20,9 @@ class Renderer {
|
||||
void draw_signal(Synth& synth, SynthGuiState& synth_gui);
|
||||
void draw_adsr_panel(ADSR* adsr, ADSRGuiState& gui_adsr,
|
||||
const Rectangle& panel_bounds, float panel_y_offset);
|
||||
void draw_second_panel(Rectangle& bounds);
|
||||
float DrawFilterPanel(Synth& synth, FilterGuiState& gui_filter,
|
||||
const Rectangle& panel_bounds);
|
||||
|
||||
public:
|
||||
Renderer(/* args */);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "ADSR.h"
|
||||
#include "Filter.h"
|
||||
#include "Adder.h"
|
||||
#include "Effect.h"
|
||||
#include "Note.h"
|
||||
@@ -14,13 +15,14 @@ class Synth {
|
||||
std::vector<Oscillator*> m_oscillators;
|
||||
std::vector<Effect*> m_effects;
|
||||
std::vector<float> m_out_signal;
|
||||
Oscillator* m_lfo;
|
||||
void zero_signal();
|
||||
void get_note();
|
||||
void trigger_note_on_effects();
|
||||
void untrigger_note_on_effects();
|
||||
void apply_effects();
|
||||
void add_oscillator();
|
||||
|
||||
void apply_filter_lfo();
|
||||
public:
|
||||
Synth(/* args */);
|
||||
~Synth();
|
||||
@@ -32,4 +34,6 @@ class Synth {
|
||||
const std::vector<Oscillator*>& GetOscillators() { return m_oscillators; }
|
||||
const bool& GetIsNoteTriggered() { return is_note_triggered; }
|
||||
ADSR* GetADSR() { return (ADSR*)m_effects[0]; }
|
||||
Filter* GetFilter() { return (Filter*)m_effects[1]; }
|
||||
void SetFilter(FilterType type);
|
||||
};
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "OscillatorType.h"
|
||||
#include "raygui.h"
|
||||
#include <vector>
|
||||
#include "Filter.h"
|
||||
|
||||
struct OscillatorGuiState {
|
||||
float volume;
|
||||
@@ -18,7 +19,15 @@ struct ADSRGuiState {
|
||||
float release;
|
||||
};
|
||||
|
||||
struct FilterGuiState {
|
||||
float freq;
|
||||
float res; //todo: res
|
||||
FilterType type;
|
||||
bool is_dropdown_open;
|
||||
};
|
||||
|
||||
struct SynthGuiState {
|
||||
std::vector<OscillatorGuiState*> oscillators;
|
||||
ADSRGuiState adsr;
|
||||
FilterGuiState filter;
|
||||
};
|
||||
Reference in New Issue
Block a user