[feat]: Oscillator fine-tune #22

Merged
e1lama merged 6 commits from feature/osc-19 into master 2023-09-16 23:26:45 +00:00
12 changed files with 112 additions and 114 deletions
Showing only changes of commit 71e1622627 - Show all commits

View File

@@ -54,10 +54,9 @@ class KeyBoard {
}
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);
}
@@ -71,7 +70,3 @@ class KeyBoard {
return result;
}
};
KeyBoard::KeyBoard(/* args */) {}
KeyBoard::~KeyBoard() {}

View File

@@ -5,31 +5,34 @@
class Oscillator {
private:
OscillatorType m_osc;
float m_freq;
float m_fine;
float m_key;
float m_volume;
float m_phase;
float m_phase_dt;
float (Oscillator::*m_osc_function)(void);
float (Oscillator::*m_dt_function)(float freq);
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();
void SineOscPhaseIncr();
void SawOscPhaseIncr();
float CalcSawPhaseDelta(float freq);
float CalcSinePhaseDelta(float freq);
float SawOsc();
float TriangleOsc();
float SquareOsc();
float Sign(float v);
float SineOsc();
public:
Oscillator(OscillatorType osc, float freq, float volume);
Oscillator(OscillatorType osc, float fine, 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);
float GetKey() { return m_key; }
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();
float Process();
};

View File

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

View File

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

View File

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

View File

@@ -56,15 +56,14 @@ void Synth::UntriggerNoteOnEffects() {
void Synth::AddOscillator() {
m_oscillators.push_back(
new Oscillator(OscillatorType::Sine, 440.f, VOLUME));
new Oscillator(OscillatorType::Sine, 0.0f, VOLUME));
}
void Synth::Trigger(Note input) {
int semitone_shift = KeyBoard::GetSemitoneShift(input.name);
float hz = KeyBoard::GetHzBySemitone(semitone_shift);
for (Oscillator* osc : m_oscillators) {
osc->SetFreq(hz);
osc->SetKey(semitone_shift);
}
is_note_triggered = true;
TriggerNoteOnEffects();