Browse Source

Scope: Refactor pointBuffer to avoid re-calculations.

tags/v2.5.0
Andrew Belt 2 years ago
parent
commit
080bca3108
1 changed files with 62 additions and 50 deletions
  1. +62
    -50
      src/Scope.cpp

+ 62
- 50
src/Scope.cpp View File

@@ -36,26 +36,15 @@ struct Scope : Module {
}; };


struct Point { struct Point {
float minX[16] = {};
float maxX[16] = {};
float minY[16] = {};
float maxY[16] = {};

Point() {
for (int c = 0; c < 16; c++) {
minX[c] = INFINITY;
maxX[c] = -INFINITY;
minY[c] = INFINITY;
maxY[c] = -INFINITY;
}
}
float min = INFINITY;
float max = -INFINITY;
}; };
Point pointBuffer[BUFFER_SIZE];
Point pointBuffer[BUFFER_SIZE][2][PORT_MAX_CHANNELS];
Point currentPoint[2][PORT_MAX_CHANNELS];
int channelsX = 0; int channelsX = 0;
int channelsY = 0; int channelsY = 0;
int bufferIndex = 0; int bufferIndex = 0;
int frameIndex = 0; int frameIndex = 0;
Point currentPoint;


dsp::SchmittTrigger triggers[16]; dsp::SchmittTrigger triggers[16];


@@ -85,7 +74,11 @@ struct Scope : Module {


void onReset() override { void onReset() override {
for (int i = 0; i < BUFFER_SIZE; i++) { for (int i = 0; i < BUFFER_SIZE; i++) {
pointBuffer[i] = Point();
for (int w = 0; w < 2; w++) {
for (int c = 0; c < 16; c++) {
pointBuffer[i][w][c] = Point();
}
}
} }
} }


@@ -158,21 +151,29 @@ struct Scope : Module {
// Get input // Get input
for (int c = 0; c < channelsX; c++) { for (int c = 0; c < channelsX; c++) {
float x = inputs[X_INPUT].getVoltage(c); float x = inputs[X_INPUT].getVoltage(c);
currentPoint.minX[c] = std::min(currentPoint.minX[c], x);
currentPoint.maxX[c] = std::max(currentPoint.maxX[c], x);
currentPoint[0][c].min = std::min(currentPoint[0][c].min, x);
currentPoint[0][c].max = std::max(currentPoint[0][c].max, x);
} }
for (int c = 0; c < channelsY; c++) { for (int c = 0; c < channelsY; c++) {
float y = inputs[Y_INPUT].getVoltage(c); float y = inputs[Y_INPUT].getVoltage(c);
currentPoint.minY[c] = std::min(currentPoint.minY[c], y);
currentPoint.maxY[c] = std::max(currentPoint.maxY[c], y);
currentPoint[1][c].min = std::min(currentPoint[1][c].min, y);
currentPoint[1][c].max = std::max(currentPoint[1][c].max, y);
} }


if (++frameIndex >= frameCount) { if (++frameIndex >= frameCount) {
frameIndex = 0; frameIndex = 0;
// Push current point // Push current point
pointBuffer[bufferIndex] = currentPoint;
for (int w = 0; w < 2; w++) {
for (int c = 0; c < 16; c++) {
pointBuffer[bufferIndex][w][c] = currentPoint[w][c];
}
}
// Reset current point // Reset current point
currentPoint = Point();
for (int w = 0; w < 2; w++) {
for (int c = 0; c < 16; c++) {
currentPoint[w][c] = Point();
}
}
bufferIndex++; bufferIndex++;
} }
} }
@@ -199,6 +200,24 @@ struct Scope : Module {
}; };




Scope::Point DEMO_POINT_BUFFER[BUFFER_SIZE];

void demoPointBufferInit() {
static bool init = false;
if (init)
return;
init = true;

// Calculate demo point buffer
for (size_t i = 0; i < BUFFER_SIZE; i++) {
float phase = float(i) / BUFFER_SIZE;
Scope::Point point;
point.min = point.max = 4.f * std::sin(2 * M_PI * phase * 2.f);
DEMO_POINT_BUFFER[i] = point;
}
}


struct ScopeDisplay : LedDisplay { struct ScopeDisplay : LedDisplay {
Scope* module; Scope* module;
ModuleWidget* moduleWidget; ModuleWidget* moduleWidget;
@@ -214,6 +233,8 @@ struct ScopeDisplay : LedDisplay {


ScopeDisplay() { ScopeDisplay() {
fontPath = asset::system("res/fonts/ShareTechMono-Regular.ttf"); fontPath = asset::system("res/fonts/ShareTechMono-Regular.ttf");

demoPointBufferInit();
} }


void calculateStats(Stats& stats, int wave, int channels) { void calculateStats(Stats& stats, int wave, int channels) {
@@ -225,32 +246,18 @@ struct ScopeDisplay : LedDisplay {


stats = Stats(); stats = Stats();
for (int i = 0; i < BUFFER_SIZE; i++) { for (int i = 0; i < BUFFER_SIZE; i++) {
Scope::Point point = module->pointBuffer[i];
for (int c = 0; c < channels; c++) { for (int c = 0; c < channels; c++) {
float max = (wave == 0) ? point.maxX[c] : point.maxY[c];
float min = (wave == 0) ? point.minX[c] : point.minY[c];

stats.max = std::fmax(stats.max, max);
stats.min = std::fmin(stats.min, min);
Scope::Point point = module->pointBuffer[i][wave][c];
stats.max = std::fmax(stats.max, point.max);
stats.min = std::fmin(stats.min, point.min);
} }
} }
} }


void drawWave(const DrawArgs& args, int wave, int channel, float offset, float gain) { void drawWave(const DrawArgs& args, int wave, int channel, float offset, float gain) {
// Copy point buffer to stack to prevent min/max values being different phase.
// This is currently only 256*4*16*4 = 64 kiB.
Scope::Point pointBuffer[BUFFER_SIZE]; Scope::Point pointBuffer[BUFFER_SIZE];
if (module) {
std::copy(std::begin(module->pointBuffer), std::end(module->pointBuffer), std::begin(pointBuffer));
}
else {
for (size_t i = 0; i < BUFFER_SIZE; i++) {
float phase = float(i) / BUFFER_SIZE;
Scope::Point point;
point.minX[0] = point.maxX[0] = 4.f * std::sin(2 * M_PI * phase * 2.f) + 5.f;
point.minY[0] = point.maxY[0] = 4.f * std::sin(2 * M_PI * phase * 2.f) - 5.f;
pointBuffer[i] = point;
}
for (int i = 0; i < BUFFER_SIZE; i++) {
pointBuffer[i] = module ? module->pointBuffer[i][wave][channel] : DEMO_POINT_BUFFER[i];
} }


nvgSave(args.vg); nvgSave(args.vg);
@@ -260,7 +267,7 @@ struct ScopeDisplay : LedDisplay {
// Draw max points on top // Draw max points on top
for (int i = 0; i < BUFFER_SIZE; i++) { for (int i = 0; i < BUFFER_SIZE; i++) {
const Scope::Point& point = pointBuffer[i]; const Scope::Point& point = pointBuffer[i];
float max = (wave == 0) ? point.maxX[channel] : point.maxY[channel];
float max = point.max;
if (!std::isfinite(max)) if (!std::isfinite(max))
max = 0.f; max = 0.f;


@@ -277,7 +284,7 @@ struct ScopeDisplay : LedDisplay {
// Draw min points on bottom // Draw min points on bottom
for (int i = BUFFER_SIZE - 1; i >= 0; i--) { for (int i = BUFFER_SIZE - 1; i >= 0; i--) {
const Scope::Point& point = pointBuffer[i]; const Scope::Point& point = pointBuffer[i];
float min = (wave == 0) ? point.minX[channel] : point.minY[channel];
float min = point.min;
if (!std::isfinite(min)) if (!std::isfinite(min))
min = 0.f; min = 0.f;


@@ -301,8 +308,12 @@ struct ScopeDisplay : LedDisplay {
if (!module) if (!module)
return; return;


Scope::Point pointBuffer[BUFFER_SIZE];
std::copy(std::begin(module->pointBuffer), std::end(module->pointBuffer), std::begin(pointBuffer));
Scope::Point pointBufferX[BUFFER_SIZE];
Scope::Point pointBufferY[BUFFER_SIZE];
for (int i = 0; i < BUFFER_SIZE; i++) {
pointBufferX[i] = module->pointBuffer[i][0][channel];
pointBufferY[i] = module->pointBuffer[i][1][channel];
}


nvgSave(args.vg); nvgSave(args.vg);
Rect b = box.zeroPos().shrink(Vec(0, 15)); Rect b = box.zeroPos().shrink(Vec(0, 15));
@@ -311,9 +322,10 @@ struct ScopeDisplay : LedDisplay {
int bufferIndex = module->bufferIndex; int bufferIndex = module->bufferIndex;
for (int i = 0; i < BUFFER_SIZE; i++) { for (int i = 0; i < BUFFER_SIZE; i++) {
// Get average point // Get average point
const Scope::Point& point = pointBuffer[(i + bufferIndex) % BUFFER_SIZE];
float avgX = (point.minX[channel] + point.maxX[channel]) / 2;
float avgY = (point.minY[channel] + point.maxY[channel]) / 2;
const Scope::Point& pointX = pointBufferX[(i + bufferIndex) % BUFFER_SIZE];
const Scope::Point& pointY = pointBufferY[(i + bufferIndex) % BUFFER_SIZE];
float avgX = (pointX.min + pointX.max) / 2;
float avgY = (pointY.min + pointY.max) / 2;
if (!std::isfinite(avgX) || !std::isfinite(avgY)) if (!std::isfinite(avgX) || !std::isfinite(avgY))
continue; continue;


@@ -430,8 +442,8 @@ struct ScopeDisplay : LedDisplay {
gainX = std::pow(2.f, std::round(gainX)) / 10.f; gainX = std::pow(2.f, std::round(gainX)) / 10.f;
float gainY = module ? module->params[Scope::Y_SCALE_PARAM].getValue() : 0.f; float gainY = module ? module->params[Scope::Y_SCALE_PARAM].getValue() : 0.f;
gainY = std::pow(2.f, std::round(gainY)) / 10.f; gainY = std::pow(2.f, std::round(gainY)) / 10.f;
float offsetX = module ? module->params[Scope::X_POS_PARAM].getValue() : 0.f;
float offsetY = module ? module->params[Scope::Y_POS_PARAM].getValue() : 0.f;
float offsetX = module ? module->params[Scope::X_POS_PARAM].getValue() : 5.f;
float offsetY = module ? module->params[Scope::Y_POS_PARAM].getValue() : -5.f;


// Get input colors // Get input colors
PortWidget* inputX = moduleWidget->getInput(Scope::X_INPUT); PortWidget* inputX = moduleWidget->getInput(Scope::X_INPUT);


Loading…
Cancel
Save