Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

morph switch #7787

Merged
merged 1 commit into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading