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.
147 lines
3.8 KiB
147 lines
3.8 KiB
#include "../utility/dsp.h"
|
|
#include "oscillatorbank.h"
|
|
#include <math.h>
|
|
|
|
using namespace daisysp;
|
|
|
|
void OscillatorBank::Init(float sample_rate)
|
|
{
|
|
sample_rate_ = sample_rate;
|
|
|
|
phase_ = 0.0f;
|
|
next_sample_ = 0.0f;
|
|
segment_ = 0.0f;
|
|
|
|
frequency_ = 0.f;
|
|
saw_8_gain_ = 0.0f;
|
|
saw_4_gain_ = 0.0f;
|
|
saw_2_gain_ = 0.0f;
|
|
saw_1_gain_ = 0.0f;
|
|
|
|
recalc_ = recalc_gain_ = true;
|
|
SetGain(1.f);
|
|
|
|
for(int i = 0; i < 7; i++)
|
|
{
|
|
registration_[i] = 0.f;
|
|
unshifted_registration_[i] = 0.f;
|
|
}
|
|
SetSingleAmp(1.f, 0);
|
|
SetFreq(440.f);
|
|
}
|
|
|
|
float OscillatorBank::Process()
|
|
{
|
|
if(recalc_)
|
|
{
|
|
recalc_ = false;
|
|
frequency_ *= 8.0f;
|
|
|
|
// Deal with very high frequencies by shifting everything 1 or 2 octave
|
|
// down: Instead of playing the 1st harmonic of a 8kHz wave, we play the
|
|
// second harmonic of a 4kHz wave.
|
|
size_t shift = 0;
|
|
while(frequency_ > 0.5f)
|
|
{
|
|
shift += 2;
|
|
frequency_ *= 0.5f;
|
|
}
|
|
|
|
for(int i = 0; i < 7; i++)
|
|
{
|
|
registration_[i] = 0.f;
|
|
}
|
|
|
|
for(size_t i = 0; i < 7 - shift; i++)
|
|
{
|
|
registration_[i + shift] = unshifted_registration_[i];
|
|
}
|
|
}
|
|
|
|
if(recalc_gain_ || recalc_)
|
|
{
|
|
saw_8_gain_ = (registration_[0] + 2.0f * registration_[1]) * gain_;
|
|
saw_4_gain_
|
|
= (registration_[2] - registration_[1] + 2.0f * registration_[3])
|
|
* gain_;
|
|
saw_2_gain_
|
|
= (registration_[4] - registration_[3] + 2.0f * registration_[5])
|
|
* gain_;
|
|
saw_1_gain_ = (registration_[6] - registration_[5]) * gain_;
|
|
}
|
|
|
|
float this_sample_ = next_sample_;
|
|
next_sample_ = 0.0f;
|
|
|
|
phase_ += frequency_;
|
|
int next_segment_ = static_cast<int>(phase_);
|
|
if(next_segment_ != segment_)
|
|
{
|
|
float discontinuity = 0.0f;
|
|
if(next_segment_ == 8)
|
|
{
|
|
phase_ -= 8.0f;
|
|
next_segment_ -= 8;
|
|
discontinuity -= saw_8_gain_;
|
|
}
|
|
if((next_segment_ & 3) == 0)
|
|
{
|
|
discontinuity -= saw_4_gain_;
|
|
}
|
|
if((next_segment_ & 1) == 0)
|
|
{
|
|
discontinuity -= saw_2_gain_;
|
|
}
|
|
discontinuity -= saw_1_gain_;
|
|
if(discontinuity != 0.0f)
|
|
{
|
|
float fraction = phase_ - static_cast<float>(next_segment_);
|
|
float t = fraction / frequency_;
|
|
this_sample_ += ThisBlepSample(t) * discontinuity;
|
|
next_sample_ += NextBlepSample(t) * discontinuity;
|
|
}
|
|
}
|
|
segment_ = next_segment_;
|
|
|
|
next_sample_ += (phase_ - 4.0f) * saw_8_gain_ * 0.125f;
|
|
next_sample_ += (phase_ - float(segment_ & 4) - 2.0f) * saw_4_gain_ * 0.25f;
|
|
next_sample_ += (phase_ - float(segment_ & 6) - 1.0f) * saw_2_gain_ * 0.5f;
|
|
next_sample_ += (phase_ - float(segment_ & 7) - 0.5f) * saw_1_gain_;
|
|
|
|
return 2.0f * this_sample_;
|
|
}
|
|
|
|
void OscillatorBank::SetFreq(float freq)
|
|
{
|
|
freq = freq / sample_rate_;
|
|
freq = freq > 0.5f ? 0.5f : freq;
|
|
recalc_ = cmp(freq, frequency_) || recalc_;
|
|
frequency_ = freq;
|
|
}
|
|
|
|
void OscillatorBank::SetAmplitudes(const float* amplitudes)
|
|
{
|
|
for(int i = 0; i < 7; i++)
|
|
{
|
|
recalc_ = cmp(unshifted_registration_[i], amplitudes[i]) || recalc_;
|
|
unshifted_registration_[i] = amplitudes[i];
|
|
}
|
|
}
|
|
|
|
void OscillatorBank::SetSingleAmp(float amp, int idx)
|
|
{
|
|
if(idx < 0 || idx > 6)
|
|
{
|
|
return;
|
|
}
|
|
recalc_ = cmp(unshifted_registration_[idx], amp) || recalc_;
|
|
unshifted_registration_[idx] = amp;
|
|
}
|
|
|
|
void OscillatorBank::SetGain(float gain)
|
|
{
|
|
gain = gain > 1.f ? 1.f : gain;
|
|
gain = gain < 0.f ? 0.f : gain;
|
|
recalc_gain_ = cmp(gain, gain_) || recalc_gain_;
|
|
gain_ = gain;
|
|
} |