Skip to content

Commit

Permalink
morph switch (#7787)
Browse files Browse the repository at this point in the history
Implemented switch for handling legacy vs new interpolation
  • Loading branch information
blancoberg committed Sep 17, 2024
1 parent be317f2 commit 736ca19
Show file tree
Hide file tree
Showing 2 changed files with 187 additions and 44 deletions.
222 changes: 178 additions & 44 deletions src/common/dsp/oscillators/WavetableOscillator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ WavetableOscillator::~WavetableOscillator() {}
void WavetableOscillator::init(float pitch, bool is_display, bool nonzero_init_drift)
{
assert(storage);
readDeformType();
first_run = true;
osc_out = _mm_set1_ps(0.f);
osc_outR = _mm_set1_ps(0.f);
Expand Down Expand Up @@ -86,15 +87,25 @@ void WavetableOscillator::init(float pitch, bool is_display, bool nonzero_init_d
// rather than wavetable from first to second to last frame
nointerp = !oscdata->p[wt_morph].extend_range;

float shape = limit_range(
l_shape.v + (localcopy[id_shape].f - unmodulatedLocalcopy[id_shape].f), 0.f, 1.f);
float shape;
float intpart;
if (deformType == XT_134_EARLIER)
{
shape = oscdata->p[wt_morph].val.f;
}
else
{
shape = getMorph();
}

shape *= ((float)oscdata->wt.n_tables - 1.f + nointerp) * 0.99999f;
tableipol = shape;
modff(shape, &intpart);
tableipol = deformType == XT_134_EARLIER ? shape : modff(shape, &intpart);
tableid = limit_range((int)intpart, 0, std::max((int)oscdata->wt.n_tables - 2 + nointerp, 0));
last_tableipol = tableipol;
last_tableid = tableid;

selectDeform();

hskew = 0.f;
last_hskew = 0.f;

Expand Down Expand Up @@ -194,10 +205,19 @@ void WavetableOscillator::convolute(int voice, bool FM, bool stereo)
last_hskew = hskew;
hskew = l_hskew.v;

int paddingLoop = 4;
int paddingEnd = 1;

if (deformType == XT_134_EARLIER)
{
paddingLoop = 3 - nointerp;
paddingEnd = 2 - nointerp;
}

if (oscdata->wt.flags & wtf_is_sample)
{
tableid++;
if (tableid > oscdata->wt.n_tables - 4)
if (tableid > oscdata->wt.n_tables - paddingLoop)
{
if (sampleloop < 7)
sampleloop--;
Expand All @@ -208,14 +228,17 @@ void WavetableOscillator::convolute(int voice, bool FM, bool stereo)
}
else
{
tableid = oscdata->wt.n_tables - 1;
tableid = oscdata->wt.n_tables - paddingEnd;
oscstate[voice] = 100000000000.f; // rather large number
return;
}
}

tableipol = tableid;
last_tableipol = tableid;
if (deformType != XT_134_EARLIER)
{
tableipol = tableid;
last_tableipol = tableid;
}
}

int ts = oscdata->wt.size;
Expand Down Expand Up @@ -299,20 +322,8 @@ void WavetableOscillator::convolute(int voice, bool FM, bool stereo)

state[voice] = state[voice] & (wtsize - 1);

float tblip_ipol = (1 - block_pos) * last_tableipol + block_pos * tableipol;
float newlevel;

// in Continuous Morph mode tblip_ipol gives us position between current and next frame
int tempTableId = floor(tblip_ipol);
float interpolationProc = (tblip_ipol - tempTableId) * (1 - nointerp);

// that 1 - nointerp makes sure we don't read the table off memory, keeps us bounded
// and since it gets multiplied by lipol, in morph mode ends up being zero - no sweat!
newlevel = distort_level(
(oscdata->wt.TableF32WeakPointers[mipmap[voice]][tempTableId][state[voice]] *
(1.f - interpolationProc)) +
(oscdata->wt.TableF32WeakPointers[mipmap[voice]][tempTableId + 1 - nointerp][state[voice]] *
interpolationProc));
newlevel = distort_level((this->*deformSelected)(block_pos, voice));

g = newlevel - last_level[voice];
last_level[voice] = newlevel;
Expand Down Expand Up @@ -379,7 +390,16 @@ template <bool is_init> void WavetableOscillator::update_lagvals()
l_hskew.newValue(limit_range(localcopy[id_hskew].f, -1.f, 1.f));
float a = limit_range(localcopy[id_clip].f, 0.f, 1.f);
l_clip.newValue(-8 * a * a * a);
l_shape.newValue(unmodulatedLocalcopy[id_shape].f);

if (deformType == XT_134_EARLIER)
{
l_shape.newValue(localcopy[id_shape].f);
}
else
{
l_shape.newValue(unmodulatedLocalcopy[id_shape].f);
}

formant_t = max(0.f, localcopy[id_formant].f);

float invt = min(1.0, (8.175798915 * storage->note_to_pitch_tuningctr(pitch_t)) *
Expand All @@ -405,10 +425,108 @@ template <bool is_init> void WavetableOscillator::update_lagvals()
}
}

void WavetableOscillator::readDeformType()
{
deformType = (FeatureDeform)oscdata->p[wt_morph].deform_type;
}

void WavetableOscillator::selectDeform()
{
if (deformType == XT_134_EARLIER)
{
deformSelected = &WavetableOscillator::deformLegacy;
}
else
{
/*
switch to morph mode when frame skips are larger than x amount of frames in one block.
this will reduce noise from scrubbing over a short amount of time and also reduce noise from
adjusting values via GUI
*/
if (abs(last_tableipol - tableipol) > 5)
{
deformSelected = &WavetableOscillator::deformMorph;
}
else
{
deformSelected = &WavetableOscillator::deformContinuous;
}
}
}

float WavetableOscillator::getMorph()
{

float shape;
if (deformType == XT_134_EARLIER)
{

shape = l_shape.v;
}
else
{
shape = limit_range(l_shape.v + (localcopy[id_shape].f - unmodulatedLocalcopy[id_shape].f),
0.f, 1.f);
}
return shape;
}
/*
Interpolation modes
*/
float WavetableOscillator::deformLegacy(float block_pos, int voice)
{
float tblip_ipol = (1 - block_pos) * last_tableipol + block_pos * tableipol;

// in Continuous Morph mode tblip_ipol gives us position between current and next frame
// when not in Continuous Morph mode, we don't interpolate so this position should be
// zero
float lipol = (1 - nointerp) * tblip_ipol;

// that 1 - nointerp makes sure we don't read the table off memory, keeps us bounded
// and since it gets multiplied by lipol, in morph mode ends up being zero - no sweat!
return (oscdata->wt.TableF32WeakPointers[mipmap[voice]][tableid][state[voice]] *
(1.f - lipol)) +
(oscdata->wt.TableF32WeakPointers[mipmap[voice]][tableid + 1 - nointerp][state[voice]] *
lipol);
}

float WavetableOscillator::deformContinuous(float block_pos, int voice)
{

float tblip_ipol = (1 - block_pos) * last_tableipol + block_pos * tableipol;

int tempTableId = floor(tblip_ipol);
float interpolationProc = (tblip_ipol - tempTableId) * (1 - nointerp);

return (oscdata->wt.TableF32WeakPointers[mipmap[voice]][tempTableId][state[voice]] *
(1.f - interpolationProc)) +
(oscdata->wt
.TableF32WeakPointers[mipmap[voice]][tempTableId + 1 - nointerp][state[voice]] *
interpolationProc);
}

float WavetableOscillator::deformMorph(float block_pos, int voice)
{

float frames[2] = {(last_tableipol), (tableipol)};
for (int i = 0; i < 2; i++)
{
int actualFrame = floor(frames[i]);
float proc = frames[i] - floor(frames[i]);

int d = min((int)(actualFrame + 1), (int)(oscdata->wt.n_tables - 1));
frames[i] = oscdata->wt.TableF32WeakPointers[mipmap[voice]][actualFrame][state[voice]] *
(1.f - proc) +
oscdata->wt.TableF32WeakPointers[mipmap[voice]][d][state[voice]] * (proc);
}

return frames[0] * (1.f - block_pos) + frames[1] * block_pos;
}

void WavetableOscillator::process_block(float pitch0, float drift, bool stereo, bool FM,
float depth)
{
auto fd = (FeatureDeform)oscdata->p[wt_morph].deform_type;

#if 0
if (fd == XT_134_EARLIER)
{
Expand All @@ -420,6 +538,8 @@ void WavetableOscillator::process_block(float pitch0, float drift, bool stereo,
}
#endif

readDeformType();

pitch_last = pitch_t;
pitch_t = min(148.f, pitch0);
pitchmult_inv =
Expand All @@ -446,43 +566,57 @@ void WavetableOscillator::process_block(float pitch0, float drift, bool stereo,
}
else if (oscdata->wt.flags & wtf_is_sample)
{
tableipol = tableid;
last_tableipol = tableid;
if (deformType == XT_134_EARLIER)
{
tableipol = 0.f;
last_tableipol = 0.f;
}
else
{
tableipol = tableid;
last_tableipol = tableid;
}
}
else
{
last_tableipol = tableipol;
last_tableid = tableid;

float shape = limit_range(
l_shape.v + (localcopy[id_shape].f - unmodulatedLocalcopy[id_shape].f), 0.f, 1.f);
float shape;
float intpart;

shape = getMorph();

shape *= ((float)oscdata->wt.n_tables - 1.f + nointerp) * 0.99999f;
tableipol = shape;
tableipol = deformType == XT_134_EARLIER ? modff(shape, &intpart) : shape;
modff(shape, &intpart);
tableid = limit_range((int)intpart, 0, (int)oscdata->wt.n_tables - 2 + nointerp);
/*
if (tableid > last_tableid)

selectDeform();

if (deformType == XT_134_EARLIER)
{
if (last_tableipol != 1.f)
if (tableid > last_tableid)
{
tableid = last_tableid;
tableipol = 1.f;
if (last_tableipol != 1.f)
{
tableid = last_tableid;
tableipol = 1.f;
}
else
last_tableipol = 0.0f;
}
else
last_tableipol = 0.0f;
}
else if (tableid < last_tableid)
{
if (last_tableipol != 0.f)
else if (tableid < last_tableid)
{
tableid = last_tableid;
tableipol = 0.f;
if (last_tableipol != 0.f)
{
tableid = last_tableid;
tableipol = 0.f;
}
else
last_tableipol = 1.0f;
}
else
last_tableipol = 1.0f;
}
*/
}

if (FM)
Expand Down
9 changes: 9 additions & 0 deletions src/common/dsp/oscillators/WavetableOscillator.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,14 @@ class WavetableOscillator : public AbstractBlitOscillator
void convolute(int voice, bool FM, bool stereo);
template <bool is_init> void update_lagvals();
inline float distort_level(float);
void readDeformType();
void selectDeform();
float getMorph();
float deformLegacy(float, int);
float deformContinuous(float, int);
float deformMorph(float, int);

float (WavetableOscillator::*deformSelected)(float, int);
bool first_run;
float oscpitch[MAX_UNISON];
float dc, dc_uni[MAX_UNISON], last_level[MAX_UNISON];
Expand All @@ -80,6 +88,7 @@ class WavetableOscillator : public AbstractBlitOscillator
float FMmul_inv;
int sampleloop;
pdata *unmodulatedLocalcopy;
FeatureDeform deformType;
};

#endif // SURGE_SRC_COMMON_DSP_OSCILLATORS_WAVETABLEOSCILLATOR_H

0 comments on commit 736ca19

Please sign in to comment.