wip: oscillator fine-tune

This commit is contained in:
2023-09-10 07:13:51 +04:00
parent c76f3ef3f8
commit 71e1622627
6 changed files with 49 additions and 49 deletions

View File

@@ -54,10 +54,9 @@ class KeyBoard {
} }
public: public:
KeyBoard(/* args */);
~KeyBoard();
static float GetHzBySemitone(int semitone) { static float GetHzBySemitone(float semitone) {
//440 * Math.Pow(2, (note - 69) / 12.0) would it be better?
return PITCH_STANDARD * powf(powf(2.f, (1.f / 12.f)), semitone); return PITCH_STANDARD * powf(powf(2.f, (1.f / 12.f)), semitone);
} }
@@ -71,7 +70,3 @@ class KeyBoard {
return result; return result;
} }
}; };
KeyBoard::KeyBoard(/* args */) {}
KeyBoard::~KeyBoard() {}

View File

@@ -5,31 +5,34 @@
class Oscillator { class Oscillator {
private: private:
OscillatorType m_osc; OscillatorType m_osc;
float m_freq; float m_fine;
float m_key;
float m_volume; float m_volume;
float m_phase; float m_phase;
float m_phase_dt; float m_phase_dt;
float (Oscillator::*m_osc_function)(void); float (Oscillator::*m_osc_function)(void);
float (Oscillator::*m_dt_function)(float freq); float (Oscillator::*m_dt_function)(float freq);
void sine_osc_phase_incr(); void SineOscPhaseIncr();
void saw_osc_phase_incr(); void SawOscPhaseIncr();
float calc_saw_phase_delta(float freq); float CalcSawPhaseDelta(float freq);
float calc_sine_phase_delta(float freq); float CalcSinePhaseDelta(float freq);
float sawosc(); float SawOsc();
float triangleosc(); float TriangleOsc();
float squareosc(); float SquareOsc();
float sign(float v); float Sign(float v);
float sineosc(); float SineOsc();
public: public:
Oscillator(OscillatorType osc, float freq, float volume); Oscillator(OscillatorType osc, float fine, float volume);
~Oscillator(); ~Oscillator();
OscillatorType GetType() { return m_osc; } OscillatorType GetType() { return m_osc; }
void SetType(OscillatorType osc); void SetType(OscillatorType osc);
float GetVolume() { return m_volume; } float GetVolume() { return m_volume; }
void SetVolume(float volume) { m_volume = volume; } void SetVolume(float volume) { m_volume = volume; }
float GetFreq() { return m_freq; } float GetKey() { return m_key; }
void SetFreq(float freq); void SetKey(float key);
float GetFine() { return m_fine; }
void SetFine(float fine) { assert(fine >= -2.f && fine <= 2.f); m_fine = fine; }
void Reset(); void Reset();
float Process(); float Process();
}; };

View File

@@ -6,7 +6,7 @@
struct OscillatorGuiState { struct OscillatorGuiState {
float volume; float volume;
float freq; // todo: remove or change to pitch shift float fine;
OscillatorType waveshape; OscillatorType waveshape;
bool is_dropdown_open; bool is_dropdown_open;
Rectangle shape_dropdown_rect; Rectangle shape_dropdown_rect;

View File

@@ -43,7 +43,7 @@ void Application::InitSynth() {
assert(osc); assert(osc);
OscillatorGuiState* ui = OscillatorGuiState* ui =
new OscillatorGuiState{.freq = osc->GetFreq(), new OscillatorGuiState{.fine = osc->GetFine(),
.waveshape = osc->GetType(), .waveshape = osc->GetType(),
.volume = osc->GetVolume()}; .volume = osc->GetVolume()};
m_synth_gui_state.oscillators.push_back(ui); m_synth_gui_state.oscillators.push_back(ui);

View File

@@ -1,11 +1,13 @@
#include "Oscillator.h" #include "Oscillator.h"
#include "Settings.h" #include "Settings.h"
#include "KeyBoard.h"
#include "Logger.h"
#define TWO_PI 2 * SYNTH_PI #define TWO_PI 2 * SYNTH_PI
Oscillator::Oscillator(OscillatorType osc, float freq, float volume) { Oscillator::Oscillator(OscillatorType osc, float fine, float volume) {
SetType(osc); SetType(osc);
m_freq = freq; m_fine = fine;
m_volume = volume; m_volume = volume;
} }
@@ -21,26 +23,27 @@ void Oscillator::SetType(OscillatorType osc) {
m_osc = osc; m_osc = osc;
switch (m_osc) { switch (m_osc) {
case Sine: case Sine:
m_osc_function = &Oscillator::sineosc; m_osc_function = &Oscillator::SineOsc;
m_dt_function = &Oscillator::calc_sine_phase_delta; m_dt_function = &Oscillator::CalcSinePhaseDelta;
break; break;
case Triangle: case Triangle:
m_osc_function = &Oscillator::triangleosc; m_osc_function = &Oscillator::TriangleOsc;
m_dt_function = &Oscillator::calc_saw_phase_delta; m_dt_function = &Oscillator::CalcSawPhaseDelta;
break; break;
case Square: case Square:
m_osc_function = &Oscillator::squareosc; m_osc_function = &Oscillator::SquareOsc;
m_dt_function = &Oscillator::calc_sine_phase_delta; m_dt_function = &Oscillator::CalcSinePhaseDelta;
break; break;
case Saw: case Saw:
m_osc_function = &Oscillator::sawosc; m_osc_function = &Oscillator::SawOsc;
m_dt_function = &Oscillator::calc_saw_phase_delta; m_dt_function = &Oscillator::CalcSawPhaseDelta;
break; break;
} }
} }
void Oscillator::SetFreq(float freq) { void Oscillator::SetKey(float key) {
m_freq = freq; float freq = KeyBoard::GetHzBySemitone(key + m_fine);
write_log("Frequency: %.1f\n", freq);
m_phase = 0; m_phase = 0;
m_phase_dt = (this->*m_dt_function)(freq); m_phase_dt = (this->*m_dt_function)(freq);
} }
@@ -49,44 +52,44 @@ float Oscillator::Process() {
return (this->*m_osc_function)() * m_volume; return (this->*m_osc_function)() * m_volume;
} }
void Oscillator::sine_osc_phase_incr() { void Oscillator::SineOscPhaseIncr() {
m_phase += m_phase_dt; m_phase += m_phase_dt;
if (m_phase >= TWO_PI) if (m_phase >= TWO_PI)
m_phase -= TWO_PI; m_phase -= TWO_PI;
} }
void Oscillator::saw_osc_phase_incr() { void Oscillator::SawOscPhaseIncr() {
m_phase += m_phase_dt; m_phase += m_phase_dt;
if (m_phase >= 1.0f) if (m_phase >= 1.0f)
m_phase -= 1.0f; m_phase -= 1.0f;
} }
float Oscillator::calc_saw_phase_delta(float freq) { float Oscillator::CalcSawPhaseDelta(float freq) {
return freq / SAMPLE_RATE; return freq / SAMPLE_RATE;
} }
float Oscillator::calc_sine_phase_delta(float freq) { float Oscillator::CalcSinePhaseDelta(float freq) {
return (TWO_PI * freq) / SAMPLE_RATE; return (TWO_PI * freq) / SAMPLE_RATE;
} }
float Oscillator::sineosc() { float Oscillator::SineOsc() {
float result = sinf(m_phase); float result = sinf(m_phase);
sine_osc_phase_incr(); SineOscPhaseIncr();
return result; return result;
} }
float Oscillator::sign(float v) { return (v > 0.0) ? 1.f : -1.f; } float Oscillator::Sign(float v) { return (v > 0.0) ? 1.f : -1.f; }
float Oscillator::squareosc() { return sign(sineosc()); } float Oscillator::SquareOsc() { return Sign(SineOsc()); }
float Oscillator::triangleosc() { float Oscillator::TriangleOsc() {
float result = 1.f - fabsf(m_phase - 0.5f) * 4.f; float result = 1.f - fabsf(m_phase - 0.5f) * 4.f;
saw_osc_phase_incr(); SawOscPhaseIncr();
return result; return result;
} }
float Oscillator::sawosc() { float Oscillator::SawOsc() {
float result = m_phase * 2.f - 1.f; float result = m_phase * 2.f - 1.f;
saw_osc_phase_incr(); SawOscPhaseIncr();
return result; return result;
} }

View File

@@ -56,15 +56,14 @@ void Synth::UntriggerNoteOnEffects() {
void Synth::AddOscillator() { void Synth::AddOscillator() {
m_oscillators.push_back( m_oscillators.push_back(
new Oscillator(OscillatorType::Sine, 440.f, VOLUME)); new Oscillator(OscillatorType::Sine, 0.0f, VOLUME));
} }
void Synth::Trigger(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);
for (Oscillator* osc : m_oscillators) { for (Oscillator* osc : m_oscillators) {
osc->SetFreq(hz); osc->SetKey(semitone_shift);
} }
is_note_triggered = true; is_note_triggered = true;
TriggerNoteOnEffects(); TriggerNoteOnEffects();