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.
146 lines
3.7 KiB
146 lines
3.7 KiB
4 years ago
|
#include "../utility/dsp.h"
|
||
|
#include "grainlet.h"
|
||
|
#include <math.h>
|
||
|
|
||
|
using namespace daisysp;
|
||
|
|
||
|
void GrainletOscillator::Init(float sample_rate)
|
||
|
{
|
||
|
sample_rate_ = sample_rate;
|
||
|
|
||
|
carrier_phase_ = 0.0f;
|
||
|
formant_phase_ = 0.0f;
|
||
|
next_sample_ = 0.0f;
|
||
|
|
||
|
carrier_shape_ = 0.f;
|
||
|
carrier_bleed_ = 0.f;
|
||
|
|
||
|
SetFreq(440.f);
|
||
|
SetFormantFreq(220.f);
|
||
|
SetShape(.5f);
|
||
|
SetBleed(.5f);
|
||
|
}
|
||
|
|
||
|
float GrainletOscillator::Process()
|
||
|
{
|
||
|
float this_sample = next_sample_;
|
||
|
float next_sample = 0.0f;
|
||
|
|
||
|
carrier_phase_ += carrier_frequency_;
|
||
|
|
||
|
if(carrier_phase_ >= 1.0f)
|
||
|
{
|
||
|
carrier_phase_ -= 1.0f;
|
||
|
float reset_time = carrier_phase_ / carrier_frequency_;
|
||
|
|
||
|
float shape_inc = new_carrier_shape_ - carrier_shape_;
|
||
|
float bleed_inc = new_carrier_bleed_ - carrier_bleed_;
|
||
|
|
||
|
float before = Grainlet(
|
||
|
1.0f,
|
||
|
formant_phase_ + (1.0f - reset_time) * formant_frequency_,
|
||
|
new_carrier_shape_ + shape_inc * (1.0f - reset_time),
|
||
|
new_carrier_bleed_ + bleed_inc * (1.0f - reset_time));
|
||
|
|
||
|
float after
|
||
|
= Grainlet(0.0f, 0.0f, new_carrier_shape_, new_carrier_bleed_);
|
||
|
|
||
|
float discontinuity = after - before;
|
||
|
this_sample += discontinuity * ThisBlepSample(reset_time);
|
||
|
next_sample += discontinuity * NextBlepSample(reset_time);
|
||
|
formant_phase_ = reset_time * formant_frequency_;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
formant_phase_ += formant_frequency_;
|
||
|
if(formant_phase_ >= 1.0f)
|
||
|
{
|
||
|
formant_phase_ -= 1.0f;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
carrier_bleed_ = new_carrier_bleed_;
|
||
|
carrier_shape_ = new_carrier_shape_;
|
||
|
next_sample += Grainlet(
|
||
|
carrier_phase_, formant_phase_, carrier_shape_, carrier_bleed_);
|
||
|
next_sample_ = next_sample;
|
||
|
return this_sample;
|
||
|
}
|
||
|
|
||
|
void GrainletOscillator::SetFreq(float freq)
|
||
|
{
|
||
|
carrier_frequency_ = freq / sample_rate_;
|
||
|
carrier_frequency_ = carrier_frequency_ > 0.5f ? 0.5f : carrier_frequency_;
|
||
|
}
|
||
|
|
||
|
void GrainletOscillator::SetFormantFreq(float freq)
|
||
|
{
|
||
|
formant_frequency_ = freq / sample_rate_;
|
||
|
formant_frequency_ = formant_frequency_ > 0.5f ? 0.5f : formant_frequency_;
|
||
|
}
|
||
|
|
||
|
void GrainletOscillator::SetShape(float shape)
|
||
|
{
|
||
|
new_carrier_shape_ = shape;
|
||
|
}
|
||
|
|
||
|
void GrainletOscillator::SetBleed(float bleed)
|
||
|
{
|
||
|
new_carrier_bleed_ = bleed;
|
||
|
}
|
||
|
|
||
|
|
||
|
float GrainletOscillator::Sine(float phase)
|
||
|
{
|
||
|
return sinf(phase * TWOPI_F);
|
||
|
}
|
||
|
|
||
|
float GrainletOscillator::Carrier(float phase, float shape)
|
||
|
{
|
||
|
shape *= 3.0f;
|
||
|
int shape_integral = static_cast<int>(shape);
|
||
|
float shape_fractional = shape - static_cast<float>(shape_integral);
|
||
|
|
||
|
float t = 1.0f - shape_fractional;
|
||
|
|
||
|
if(shape_integral == 0)
|
||
|
{
|
||
|
phase = phase * (1.0f + t * t * t * 15.0f);
|
||
|
if(phase >= 1.0f)
|
||
|
{
|
||
|
phase = 1.0f;
|
||
|
}
|
||
|
phase += 0.75f;
|
||
|
}
|
||
|
else if(shape_integral == 1)
|
||
|
{
|
||
|
float breakpoint = 0.001f + 0.499f * t * t * t;
|
||
|
if(phase < breakpoint)
|
||
|
{
|
||
|
phase *= (0.5f / breakpoint);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
phase = 0.5f + (phase - breakpoint) * 0.5f / (1.0f - breakpoint);
|
||
|
}
|
||
|
phase += 0.75f;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
t = 1.0f - t;
|
||
|
phase = 0.25f + phase * (0.5f + t * t * t * 14.5f);
|
||
|
if(phase >= 0.75f)
|
||
|
phase = 0.75f;
|
||
|
}
|
||
|
return (Sine(phase) + 1.0f) * 0.25f;
|
||
|
}
|
||
|
|
||
|
float GrainletOscillator::Grainlet(float carrier_phase,
|
||
|
float formant_phase,
|
||
|
float shape,
|
||
|
float bleed)
|
||
|
{
|
||
|
float carrier = Carrier(carrier_phase, shape);
|
||
|
float formant = Sine(formant_phase);
|
||
|
return carrier * (formant + bleed) / (1.0f + bleed);
|
||
|
}
|