diff --git a/inc/Note.h b/inc/Note.h new file mode 100644 index 0000000..d934a36 --- /dev/null +++ b/inc/Note.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +struct Note { + std::string& name; + int length; +} \ No newline at end of file diff --git a/inc/Oscillator.h b/inc/Oscillator.h new file mode 100644 index 0000000..0e53dbb --- /dev/null +++ b/inc/Oscillator.h @@ -0,0 +1,38 @@ +#pragma once +#include +#include "OscillatorType.h" + +typedef float (Oscillator::*OscFunction)(void); +typedef float (Oscillator::*DtFunction)(float); + +class Oscillator +{ + private: + OscillatorType m_osc; + float m_freq; + float m_volume; + float m_phase; + float m_phase_dt; + OscFunction m_osc_function; + DtFunction m_dt_function; + void sine_osc_phase_incr(); + void saw_osc_phase_incr(); + float calc_saw_phase_delta(float freq); + float calc_sine_phase_delta(float freq); + float sawosc(); + float triangleosc(); + float squareosc(); + float sign(float v); + float sineosc(); + public: + Oscillator(OscillatorType osc, float freq, float volume); + ~Oscillator(); + OscillatorType GetType() { return m_osc; } + void SetType(OscillatorType osc); + float GetVolume() { return m_volume; } + void SetVolume(float volume) { m_volume = volume; } + float GetFreq() { return m_freq; } + void SetFreq(float freq); + void Reset(); + float GenerateSample(float duration); +}; diff --git a/inc/OscillatorType.h b/inc/OscillatorType.h new file mode 100644 index 0000000..9ddaaac --- /dev/null +++ b/inc/OscillatorType.h @@ -0,0 +1,7 @@ +#pragma once +typedef enum { + Sine, + Triangle, + Saw, + Square +} OscillatorType; \ No newline at end of file diff --git a/inc/Settings.h b/inc/Settings.h new file mode 100644 index 0000000..dbf08e5 --- /dev/null +++ b/inc/Settings.h @@ -0,0 +1,16 @@ +#pragma once + +#define SAMPLE_RATE 48000.f +#define BPM 120.f +#define BEAT_DURATION 60.f/BPM +#define PITCH_STANDARD 440.f +#define VOLUME 0.5f +#define ATTACK_MS 100.f +#define STREAM_BUFFER_SIZE 4096 + +#define SYNTH_PI 3.1415926535f +#define SYNTH_VOLUME 0.5f + +#define WINDOW_WIDTH 640 +#define WINDOW_HEIGHT 480 +#define OSCILLATOR_PANEL_WIDTH 200 \ No newline at end of file diff --git a/src/Oscillator.cpp b/src/Oscillator.cpp new file mode 100644 index 0000000..37bf1a0 --- /dev/null +++ b/src/Oscillator.cpp @@ -0,0 +1,103 @@ +#include "Oscillator.h" +#include "Settings.h" + +#define TWO_PI 2*SYNTH_PI + +Oscillator::Oscillator(OscillatorType osc, float freq, float volume) +{ + SetType(osc); + m_freq = freq; + m_volume = volume; +} + +Oscillator::~Oscillator() +{ +} + +void Oscillator::Reset() +{ + m_volume = 0; + m_phase = 0; + m_phase_dt = 0; +} + +void Oscillator::SetType(OscillatorType osc) +{ + m_osc = osc; + switch (m_osc) { + case Sine: + m_osc_function = &sineosc; + m_dt_function = &calc_sine_phase_delta; + break; + case Triangle: + m_osc_function = &triangleosc; + m_dt_function = &calc_saw_phase_delta; + break; + case Square: + m_osc_function = &squareosc; + m_dt_function = &calc_sine_phase_delta; + break; + case Saw: + m_osc_function = &sawosc; + m_dt_function = &calc_saw_phase_delta; + break; + } +} + +void Oscillator::SetFreq(float freq) +{ + m_freq = freq; + m_phase = 0; + m_phase_dt = m_dt_function(freq); +} + +float Oscillator::GenerateSample(float duration) +{ + return m_osc_function() * m_volume; +} + +void Oscillator::sine_osc_phase_incr() { + m_phase += m_phase_dt; + if (m_phase >= TWO_PI) + m_phase -= TWO_PI; +} + +void Oscillator::saw_osc_phase_incr() { + m_phase += m_phase_dt; + if (m_phase >= 1.0f) + m_phase -= 1.0f; +} + +float Oscillator::calc_saw_phase_delta(float freq) { + return freq / SAMPLE_RATE; +} + +float Oscillator::calc_sine_phase_delta(float freq) { + return (TWO_PI * freq) / SAMPLE_RATE; +} + +float Oscillator::sineosc() { + float result = sinf(m_phase); + sine_osc_phase_incr(); + return result; +} + +float Oscillator::sign(float v) { + return (v > 0.0) ? 1.f : -1.f; +} + +float Oscillator::squareosc() { + return sign(sineosc()); +} + +float Oscillator::triangleosc() { + float result = 1.f - fabsf(m_phase - 0.5f) * 4.f; + saw_osc_phase_incr(); + return result; +} + +float Oscillator::sawosc() { + float result = m_phase * 2.f - 1.f; + saw_osc_phase_incr(); + return result; +} \ No newline at end of file