Skip to content

Commit

Permalink
new 3D wavetable display (#7799)
Browse files Browse the repository at this point in the history
* new 3d wavetable display

* 3d wavetable display fix

Added override and removed virtual from processSamplesForDisplay

* wt display additional fixes

* replaced string comparison with @mkruselj diff
* rebuilt the resize handling of the bitmap.
* added setZoomFactor to waveformdisplay

* resize bug fixed

First resize event is now fired after display has been added to stage.
  • Loading branch information
blancoberg authored Sep 27, 2024
1 parent c954969 commit 3cea5c8
Show file tree
Hide file tree
Showing 10 changed files with 425 additions and 196 deletions.
2 changes: 2 additions & 0 deletions src/common/SurgeStorage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1272,6 +1272,7 @@ void SurgeStorage::perform_queued_wtloads()
patch.isDirty = true;
load_wt(patch.scene[sc].osc[o].wt.queue_id, &patch.scene[sc].osc[o].wt,
&patch.scene[sc].osc[o]);
patch.scene[sc].osc[o].wt.is_dnd_imported = false;
patch.scene[sc].osc[o].wt.refresh_display = true;
}
else if (patch.scene[sc].osc[o].wt.queue_filename[0])
Expand All @@ -1293,6 +1294,7 @@ void SurgeStorage::perform_queued_wtloads()
patch.scene[sc].osc[o].wt.current_id = wtidx;
load_wt(patch.scene[sc].osc[o].wt.queue_filename, &patch.scene[sc].osc[o].wt,
&patch.scene[sc].osc[o]);
patch.scene[sc].osc[o].wt.is_dnd_imported = true;
patch.scene[sc].osc[o].wt.refresh_display = true;
if (patch.scene[sc].osc[o].wt.everBuilt)
patch.isDirty = true;
Expand Down
1 change: 1 addition & 0 deletions src/common/dsp/Wavetable.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class Wavetable

int current_id, queue_id;
bool refresh_display;
bool is_dnd_imported;
std::string queue_filename;
std::string current_filename;
int frame_size_if_absent{-1};
Expand Down
3 changes: 3 additions & 0 deletions src/common/dsp/oscillators/OscillatorBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ class alignas(16) Oscillator
float FMdepth = 0.f)
{
}

virtual void processSamplesForDisplay(float *samples, int size, bool real){};

virtual void assign_fm(float *master_osc) { this->master_osc = master_osc; }
virtual bool allow_display() { return true; }
inline double pitch_to_omega(float x)
Expand Down
77 changes: 77 additions & 0 deletions src/common/dsp/oscillators/WavetableOscillator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,83 @@ float WavetableOscillator::distort_level(float x)
return x;
}

void WavetableOscillator::processSamplesForDisplay(float *samples, int size, bool real)
{
if (!real)
{
// saturate and skewY
for (int i = 0; i < size; i++)
{
samples[i] = distort_level(samples[i]);
}

// formant
if (oscdata->p[wt_formant].val.f > 0.f)
{
float mult = pow(2, oscdata->p[wt_formant].val.f * 0.08333333333333333);

for (int i = 0; i < size; i++)
{
float pos = limit_range((float)i * mult, 0.f, (float)size - 1.f);
int from = floor(pos);
int to = limit_range(from + 1, 0, size - 1);

float proc = pos - (float)from;

samples[i] = samples[from] * (1.f - proc) + samples[to] * proc;
}
}

// skewX
/*
TODO
this is not even close to the correct inplementation of skewx.
*/
/*
float samplePos = 0.f;
float mul = 1.f / (float)size;
float fsize = (float)size;
float tempSamples[64];
float hskew = -oscdata->p[wt_skewh].val.f;
float taylorscale = sqrtf(27.f / 4);
for (int i = 0; i < size; i++)
{
float xt = (i + 0.5) * mul;
xt = 1 + hskew * 4 * xt * (xt - 1) * (2 * xt - 1) * taylorscale;
samplePos = (samplePos + xt);
if (samplePos > fsize - 1.f)
samplePos -= fsize;
int from = ((int)samplePos + size * 2) % size;
float proc = samplePos - from;
int to = (from + 1) % size;
// interpolate samples
tempSamples[i] = samples[from] * (1.f - proc) + samples[to] * proc;
}
for (int i = 0; i < size; i++)
{
samples[i] = tempSamples[i];
}
*/
}
else
{

// todo populate samples with process_block()
for (int i = 0; i < size; i++)
{
samples[i] = 0;
}
}
// saturation
};

void WavetableOscillator::convolute(int voice, bool FM, bool stereo)
{
float block_pos = oscstate[voice] * BLOCK_SIZE_OS_INV * pitchmult_inv;
Expand Down
2 changes: 2 additions & 0 deletions src/common/dsp/oscillators/WavetableOscillator.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ class WavetableOscillator : public AbstractBlitOscillator
virtual void handleStreamingMismatches(int streamingRevision,
int currentSynthStreamingRevision) override;

void processSamplesForDisplay(float *samples, int size, bool real) override;

private:
void convolute(int voice, bool FM, bool stereo);
template <bool is_init> void update_lagvals();
Expand Down
80 changes: 80 additions & 0 deletions src/common/dsp/oscillators/WindowOscillator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,86 @@ inline unsigned int BigMULr16(unsigned int a, unsigned int b)
return c >> 16u;
}

void WindowOscillator::processSamplesForDisplay(float *samples, int size, bool real)
{
if (!real)
{

// formant

float formant = oscdata->p[win_formant].val.f;
float newSamples[64];

float mult = pow(2.f, formant / 12.f);

for (int i = 0; i < size; i++)
{
float pos = (float)i * mult;
int from = (int)(pos);

float proc = pos - (float)from;
from = from % (size);
int to = (from + 1) % size;
newSamples[i] = samples[from] * (1.f - proc) + samples[to] * proc;
}

int window = limit_range(oscdata->p[win_window].val.i, 0, 8);
int windowSize = storage->WindowWT.size;

for (int i = 0; i < size; i++)
{
samples[i] = newSamples[i];
}

// apply window

for (int i = 0; i < size; i++)
{
float windowPos = ((float)i / (float)size); // correct
windowPos *= (float)windowSize;
float v = storage->WindowWT.TableI16WeakPointers[0][window][(int)windowPos];
samples[i] = samples[i] * v * 0.00006103515625; // there is most likely a better way
// of doing this ( divide by 2pow13)
}

// filters

for (int k = 0; k < size; k += BLOCK_SIZE)
{
float blockSamples[BLOCK_SIZE];

for (int i = 0; i < BLOCK_SIZE; i++)
{
int s = i + k;
blockSamples[i] = s < size ? samples[s] : 0;
}

if (!oscdata->p[win_lowcut].deactivated)
hp.process_block(blockSamples, samples);
if (!oscdata->p[win_highcut].deactivated)
lp.process_block(blockSamples, samples);

for (int i = 0; i < BLOCK_SIZE; i++)
{
int s = i + k;
if (s < size)
{
samples[s] = blockSamples[i];
}
}
}
}
else
{

// todo populate samples with process_block()
for (int i = 0; i < size; i++)
{
samples[i] = 0;
}
}
};

template <bool FM, bool Full16> void WindowOscillator::ProcessWindowOscs(bool stereo)
{
const unsigned int M0Mask = 0x07f8;
Expand Down
2 changes: 2 additions & 0 deletions src/common/dsp/oscillators/WindowOscillator.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ class WindowOscillator : public Oscillator
virtual void handleStreamingMismatches(int streamingRevision,
int currentSynthStreamingRevision) override;

void processSamplesForDisplay(float *samples, int size, bool real) override;

private:
int IOutputL alignas(16)[BLOCK_SIZE_OS];
int IOutputR alignas(16)[BLOCK_SIZE_OS];
Expand Down
21 changes: 13 additions & 8 deletions src/surge-xt/gui/SurgeGUIEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -771,23 +771,24 @@ void SurgeGUIEditor::idle()
}

auto ol = getOverlayIfOpenAs<Surge::Overlays::FormulaModulatorEditor>(FORMULA_EDITOR);

if (ol)
{
ol->updateDebuggerIfNeeded();
}

if (synth->storage.getPatch()
.scene[current_scene]
.osc[current_osc[current_scene]]
.wt.refresh_display)
auto wt =
&synth->storage.getPatch().scene[current_scene].osc[current_osc[current_scene]].wt;
if (wt->refresh_display)
{
synth->storage.getPatch()
.scene[current_scene]
.osc[current_osc[current_scene]]
.wt.refresh_display = false;
wt->refresh_display = false;

if (oscWaveform)
{
if (wt->is_dnd_imported)
{
oscWaveform->repaintForceForWT();
}
oscWaveform->repaint();
}
}
Expand Down Expand Up @@ -3008,6 +3009,7 @@ void SurgeGUIEditor::setZoomFactor(float zf) { setZoomFactor(zf, false); }

void SurgeGUIEditor::setZoomFactor(float zf, bool resizeWindow)
{

zoomFactor = std::max(zf, static_cast<float>(minimumZoom));

#if LINUX
Expand Down Expand Up @@ -3035,6 +3037,9 @@ void SurgeGUIEditor::setZoomFactor(float zf, bool resizeWindow)
frame->setTransform(juce::AffineTransform().scaled(zff));
}

if (oscWaveform)
oscWaveform->setZoomFactor(zoomFactor);

setBitmapZoomFactor(zoomFactor);
rezoomOverlays();
}
Expand Down
Loading

0 comments on commit 3cea5c8

Please sign in to comment.