You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
106 lines
3.2 KiB
106 lines
3.2 KiB
4 years ago
|
#include "../utility/dsp.h"
|
||
|
#include "variablesawosc.h"
|
||
|
#include <math.h>
|
||
|
|
||
|
using namespace daisysp;
|
||
|
|
||
|
void VariableSawOscillator::Init(float sample_rate)
|
||
|
{
|
||
|
sample_rate_ = sample_rate;
|
||
|
|
||
|
phase_ = 0.0f;
|
||
|
next_sample_ = 0.0f;
|
||
|
previous_pw_ = 0.5f;
|
||
|
high_ = false;
|
||
|
|
||
|
SetFreq(220.f);
|
||
|
SetPW(0.f);
|
||
|
SetWaveshape(1.f);
|
||
|
}
|
||
|
|
||
|
float VariableSawOscillator::Process()
|
||
|
{
|
||
|
float next_sample = next_sample_;
|
||
|
|
||
|
float this_sample = next_sample;
|
||
|
next_sample = 0.0f;
|
||
|
|
||
|
const float triangle_amount = waveshape_;
|
||
|
const float notch_amount = 1.0f - waveshape_;
|
||
|
const float slope_up = 1.0f / (pw_);
|
||
|
const float slope_down = 1.0f / (1.0f - pw_);
|
||
|
|
||
|
phase_ += frequency_;
|
||
|
|
||
|
if(!high_ && phase_ >= pw_)
|
||
|
{
|
||
|
const float triangle_step
|
||
|
= (slope_up + slope_down) * frequency_ * triangle_amount;
|
||
|
const float notch
|
||
|
= (kVariableSawNotchDepth + 1.0f - pw_) * notch_amount;
|
||
|
const float t = (phase_ - pw_) / (previous_pw_ - pw_ + frequency_);
|
||
|
this_sample += notch * ThisBlepSample(t);
|
||
|
next_sample += notch * NextBlepSample(t);
|
||
|
this_sample -= triangle_step * ThisIntegratedBlepSample(t);
|
||
|
next_sample -= triangle_step * NextIntegratedBlepSample(t);
|
||
|
high_ = true;
|
||
|
}
|
||
|
else if(phase_ >= 1.0f)
|
||
|
{
|
||
|
phase_ -= 1.0f;
|
||
|
const float triangle_step
|
||
|
= (slope_up + slope_down) * frequency_ * triangle_amount;
|
||
|
const float notch = (kVariableSawNotchDepth + 1.0f) * notch_amount;
|
||
|
const float t = phase_ / frequency_;
|
||
|
this_sample -= notch * ThisBlepSample(t);
|
||
|
next_sample -= notch * NextBlepSample(t);
|
||
|
this_sample += triangle_step * ThisIntegratedBlepSample(t);
|
||
|
next_sample += triangle_step * NextIntegratedBlepSample(t);
|
||
|
high_ = false;
|
||
|
}
|
||
|
|
||
|
next_sample += ComputeNaiveSample(
|
||
|
phase_, pw_, slope_up, slope_down, triangle_amount, notch_amount);
|
||
|
previous_pw_ = pw_;
|
||
|
|
||
|
next_sample_ = next_sample;
|
||
|
return (2.0f * this_sample - 1.0f) / (1.0f + kVariableSawNotchDepth);
|
||
|
}
|
||
|
|
||
|
void VariableSawOscillator::SetFreq(float frequency)
|
||
|
{
|
||
|
frequency = frequency / sample_rate_;
|
||
|
frequency = frequency >= .25f ? .25f : frequency;
|
||
|
pw_ = frequency >= .25f ? .5f : pw_;
|
||
|
frequency_ = frequency;
|
||
|
}
|
||
|
|
||
|
void VariableSawOscillator::SetPW(float pw)
|
||
|
{
|
||
|
if(frequency_ >= .25f)
|
||
|
{
|
||
|
pw_ = .5f;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pw_ = fclamp(pw, frequency_ * 2.0f, 1.0f - 2.0f * frequency_);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void VariableSawOscillator::SetWaveshape(float waveshape)
|
||
|
{
|
||
|
waveshape_ = waveshape;
|
||
|
}
|
||
|
|
||
|
float VariableSawOscillator::ComputeNaiveSample(float phase,
|
||
|
float pw,
|
||
|
float slope_up,
|
||
|
float slope_down,
|
||
|
float triangle_amount,
|
||
|
float notch_amount)
|
||
|
{
|
||
|
float notch_saw = phase < pw ? phase : 1.0f + kVariableSawNotchDepth;
|
||
|
float triangle
|
||
|
= phase < pw ? phase * slope_up : 1.0f - (phase - pw) * slope_down;
|
||
|
return notch_saw * notch_amount + triangle * triangle_amount;
|
||
|
}
|