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

wavetable morph interpolation discontinuity #7778

Merged
merged 2 commits into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
51 changes: 19 additions & 32 deletions src/common/dsp/oscillators/WavetableOscillator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,12 @@ void WavetableOscillator::init(float pitch, bool is_display, bool nonzero_init_d

n_unison = limit_range(oscdata->p[wt_unison_voices].val.i, 1, MAX_UNISON);

isOneShot = 0;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is a bool you can use the constant true and false for better readability here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isOneShot is actually not used anymore. I added it because it was used as a check in convolute(), but I realised later that it wasn't needed. I forgot to remove it.
Should I remove it or just change it to a bool?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it is completely unused it can be removed.

if (oscdata->wt.flags & wtf_is_sample)
{
sampleloop = n_unison;
n_unison = 1;
isOneShot = 1;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And here

}

if (is_display)
Expand All @@ -89,7 +91,8 @@ void WavetableOscillator::init(float pitch, bool is_display, bool nonzero_init_d

float intpart;
shape *= ((float)oscdata->wt.n_tables - 1.f + nointerp) * 0.99999f;
tableipol = modff(shape, &intpart);
tableipol = 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;
Expand Down Expand Up @@ -194,7 +197,7 @@ void WavetableOscillator::convolute(int voice, bool FM, bool stereo)
if (oscdata->wt.flags & wtf_is_sample)
{
tableid++;
if (tableid > oscdata->wt.n_tables - 3 + nointerp)
if (tableid > oscdata->wt.n_tables - 4)
{
if (sampleloop < 7)
sampleloop--;
Expand All @@ -205,11 +208,14 @@ void WavetableOscillator::convolute(int voice, bool FM, bool stereo)
}
else
{
tableid = oscdata->wt.n_tables - 2 + nointerp;
tableid = oscdata->wt.n_tables - 1;
oscstate[voice] = 100000000000.f; // rather large number
return;
}
}

tableipol = tableid;
last_tableipol = tableid;
}

int ts = oscdata->wt.size;
Expand Down Expand Up @@ -297,15 +303,16 @@ void WavetableOscillator::convolute(int voice, bool FM, bool stereo)
float newlevel;

// 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;
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]][tableid][state[voice]] * (1.f - lipol)) +
(oscdata->wt.TableF32WeakPointers[mipmap[voice]][tableid + 1 - nointerp][state[voice]] *
lipol));
(oscdata->wt.TableF32WeakPointers[mipmap[voice]][tempTableId][state[voice]] *
(1.f - interpolationProc)) +
(oscdata->wt.TableF32WeakPointers[mipmap[voice]][tempTableId + 1 - nointerp][state[voice]] *
interpolationProc));

g = newlevel - last_level[voice];
last_level[voice] = newlevel;
Expand Down Expand Up @@ -427,8 +434,8 @@ void WavetableOscillator::process_block(float pitch0, float drift, bool stereo,
}
else if (oscdata->wt.flags & wtf_is_sample)
{
tableipol = 0.f;
last_tableipol = 0.f;
tableipol = tableid;
last_tableipol = tableid;
}
else
{
Expand All @@ -438,29 +445,9 @@ void WavetableOscillator::process_block(float pitch0, float drift, bool stereo,
float shape = l_shape.v;
float intpart;
shape *= ((float)oscdata->wt.n_tables - 1.f + nointerp) * 0.99999f;
tableipol = modff(shape, &intpart);
tableipol = shape;
modff(shape, &intpart);
tableid = limit_range((int)intpart, 0, (int)oscdata->wt.n_tables - 2 + nointerp);

if (tableid > last_tableid)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this code removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the logic for the old morph interpolation. It has to be removed for the new one to work.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case please comment it out instead of removing it, since this code will have to remain here in order for the option switch to work.

Copy link
Contributor Author

@blancoberg blancoberg Aug 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case please comment it out instead of removing it, since this code will have to remain here in order for the option switch to work.

ok, but you you told me the opposite about my last pr that I should just remove instead of commenting out, since there is a git history :)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The difference is that we know we'll need this code soon. :) Leaving commented-out code blocks hanging around indefinitely is what we want to avoid.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

got it. I'll change it to a comment

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

if (FM)
Expand Down
1 change: 1 addition & 0 deletions src/common/dsp/oscillators/WavetableOscillator.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ class WavetableOscillator : public AbstractBlitOscillator
int nointerp;
float FMmul_inv;
int sampleloop;
bool isOneShot;
};

#endif // SURGE_SRC_COMMON_DSP_OSCILLATORS_WAVETABLEOSCILLATOR_H
Loading