Skip to content

Commit 6b70018

Browse files
committedJul 8, 2023
added ability to select 4x upsampling on any plot mode
1 parent ce7cb86 commit 6b70018

10 files changed

+178
-130
lines changed
 

‎interpolator.h

+18-35
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#define INTERPOLATOR_H
1212

1313

14-
//#define INTERPOLATOR_TIME_FUNC
14+
#define INTERPOLATOR_TIME_FUNC
1515

1616
#ifdef INTERPOLATOR_TIME_FUNC
1717
#include "movingaverage.h"
@@ -140,6 +140,8 @@ class Interpolator
140140
Interpolator()
141141
{
142142
switch(L) {
143+
case 1:
144+
break;
143145
case 2:
144146
setCoefficients(coeffs2);
145147
break;
@@ -183,6 +185,13 @@ class Interpolator
183185
index = fir_length - 1;
184186
}
185187

188+
void reset()
189+
{
190+
std::fill(history0.begin(), history0.end(), 0.0);
191+
std::fill(history1.begin(), history1.end(), 0.0);
192+
index = fir_length - 1;
193+
}
194+
186195
void upsampleBlockMono(OutputType* output, const InputType* input, size_t sampleCount)
187196
{
188197
for(size_t s = 0; s < sampleCount; s++) {
@@ -224,22 +233,11 @@ class Interpolator
224233
history0[index] = static_cast<OutputType>(input);
225234
size_t p = index;
226235

227-
if constexpr(L == 2) {
228-
output[0] = output[1] = 0.0;
229-
} else {
230-
for(int k = 0; k < L; k++) {
231-
output[k] = 0;
232-
}
233-
}
236+
memset(output, 0.0, L * sizeof(OutputType));
234237

235238
for(size_t j = 0; j < n * L; j+= L) {
236-
if constexpr(L == 2) {
237-
output[0] += fir_coeffs[j] * history0[p];
238-
output[1] += fir_coeffs[j+1] * history0[p];
239-
} else {
240-
for(size_t k = 0; k < L; k++) {
241-
output[k] += fir_coeffs[j+k] * history0[p];
242-
}
239+
for(size_t k = 0; k < L; k++) {
240+
output[k] += fir_coeffs[j+k] * history0[p];
243241
}
244242

245243
if(++p == fir_length) {
@@ -259,28 +257,13 @@ class Interpolator
259257

260258
size_t p = index;
261259

262-
if constexpr(L == 2) {
263-
output0[0] = output0[1] = 0.0;
264-
output1[0] = output1[1] = 0.0;
265-
266-
} else {
267-
for(int k = 0; k < L; k++) {
268-
output0[k] = 0;
269-
output1[k] = 0;
270-
}
271-
}
260+
memset(output0, 0.0, L * sizeof(OutputType));
261+
memset(output1, 0.0, L * sizeof(OutputType));
272262

273263
for(size_t j = 0; j < n * L; j+= L) {
274-
if constexpr(L == 2) {
275-
output0[0] += fir_coeffs[j] * history0[p];
276-
output0[1] += fir_coeffs[j+1] * history0[p];
277-
output1[0] += fir_coeffs[j] * history1[p];
278-
output1[1] += fir_coeffs[j+1] * history1[p];
279-
} else {
280-
for(size_t k = 0; k < L; k++) {
281-
output0[k] += fir_coeffs[j+k] * history0[p];
282-
output1[k] += fir_coeffs[j+k] * history1[p];
283-
}
264+
for(size_t k = 0; k < L; k++) {
265+
output0[k] += fir_coeffs[j+k] * history0[p];
266+
output1[k] += fir_coeffs[j+k] * history1[p];
284267
}
285268

286269
if(++p == fir_length) {

‎mainwindow.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -139,17 +139,19 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
139139

140140
connect(plotmodeWidget, &PlotmodeWidget::plotmodeChanged, scopeWidget, &ScopeWidget::setPlotmode);
141141
connect(plotmodeWidget, &PlotmodeWidget::plotmodeChanged, this, [sweepSettingsWidget](Plotmode plotmode){
142-
sweepSettingsWidget->setEnabled(plotmode == Sweep || plotmode == SweepUpsampled);
142+
sweepSettingsWidget->setEnabled(plotmode == Sweep);
143143
});
144144

145+
connect(plotmodeWidget, &PlotmodeWidget::upsamplingChanged, scopeWidget, &ScopeWidget::setUpsampling);
146+
145147
scopeWidget->setBrightness(80.0);
146148
scopeWidget->setFocus(80.0);
147149
scopeWidget->setPersistence(48);
148150

149151
sweepSettingsWidget->setSweepParameters(scopeWidget->getSweepParameters());
150152
Plotmode plotmode = scopeWidget->getPlotmode();
151153
plotmodeWidget->setPlotmode(plotmode);
152-
sweepSettingsWidget->setEnabled(plotmode == Sweep || plotmode == SweepUpsampled);
154+
sweepSettingsWidget->setEnabled(plotmode == Sweep);
153155

154156
}
155157

‎plotmode.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ QMap<Plotmode, PlotmodeDefinition> PlotmodeManager::plotmodeMap
44
{
55
{XY, {XY, "X / Y", "X Axis: Ch0<br/>Y Axis: Ch1"}},
66
{MidSide, {MidSide, "Mid / Side", "X Axis: Ch0 - Ch1<br/>Y Axis: Ch0 + Ch1"}},
7-
{Sweep, {Sweep, "Sweep", "X Axis: Sweep<br/>Y Axis: ch0"}},
8-
{SweepUpsampled, {SweepUpsampled, "Sweep, Upsampled", "X Axis: Sweep<br/>Y Axis: ch0"}}
7+
{Sweep, {Sweep, "Sweep", "X Axis: Sweep<br/>Y Axis: ch0"}}
98
};
109

1110
const QMap<Plotmode, PlotmodeDefinition>& PlotmodeManager::getPlotmodeMap()

‎plotmode.h

+1-4
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,9 @@ enum Plotmode
88
{
99
XY,
1010
MidSide,
11-
Sweep,
12-
SweepUpsampled
11+
Sweep
1312
};
1413

15-
16-
1714
struct PlotmodeDefinition
1815
{
1916
Plotmode plotMode;

‎plotmodewidget.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@ PlotmodeWidget::PlotmodeWidget(QWidget *parent)
88
: QWidget{parent}
99
{
1010
plotmodeSelector = new QComboBox;
11+
upsamplingCheckbox = new QCheckBox("upsampling");
12+
1113
auto plotmodeLayout = new QHBoxLayout;
1214
auto mainLayout = new QVBoxLayout;
1315
plotmodeLayout->addWidget(plotmodeSelector);
16+
plotmodeLayout->addWidget(upsamplingCheckbox);
1417

1518

1619
for (const PlotmodeDefinition& p : PlotmodeManager::getPlotmodeMap())
@@ -29,6 +32,10 @@ PlotmodeWidget::PlotmodeWidget(QWidget *parent)
2932
emit plotmodeChanged(getPlotmode());
3033
});
3134

35+
connect(upsamplingCheckbox, &QCheckBox::toggled, this, [this](){
36+
emit upsamplingChanged(upsamplingCheckbox->isChecked());
37+
});
38+
3239
}
3340

3441
Plotmode PlotmodeWidget::getPlotmode() const

‎plotmodewidget.h

+3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <QWidget>
66

77
#include <QComboBox>
8+
#include <QCheckBox>
89

910
#include "plotmode.h"
1011

@@ -23,9 +24,11 @@ class PlotmodeWidget : public QWidget
2324

2425
signals:
2526
void plotmodeChanged(Plotmode plotmode);
27+
void upsamplingChanged(bool enableUpsampling);
2628

2729
private:
2830
QComboBox *plotmodeSelector{nullptr};
31+
QCheckBox *upsamplingCheckbox{nullptr};
2932

3033
};
3134

‎scopewidget.cpp

+86-67
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
#include "scopewidget.h"
1111
#include "delayline.h"
1212
#include "differentiator.h"
13-
#include "interpolator.h"
1413
#include "movingaverage.h"
1514

1615
#include <QVBoxLayout>
@@ -44,7 +43,9 @@ ScopeWidget::ScopeWidget(QWidget *parent) : QWidget(parent)
4443
const auto divs = scopeDisplay->getDivisions();
4544
sweepParameters.horizontalDivisions = divs.first;
4645
sweepParameters.verticalDivisions = divs.second;
47-
sweepParameters.sweepUnused = {plotMode != Sweep && plotMode != SweepUpsampled};
46+
sweepParameters.sweepUnused = {plotMode != Sweep};
47+
48+
setUpsampling(getUpsampling());
4849

4950
calcScaling();
5051
connect(scopeDisplay, &ScopeDisplay::pixmapResolutionChanged, this, [this](){
@@ -53,10 +54,15 @@ ScopeWidget::ScopeWidget(QWidget *parent) : QWidget(parent)
5354

5455
connect(&plotTimer, &QTimer::timeout, this, [this]{
5556
if(!paused) {
56-
//plotTest();
57+
58+
//plotTest();
59+
readInput();
60+
61+
// send audio to output
62+
pushOut->write(reinterpret_cast<char*>(rawinputBuffer.data()), framesRead * audioFormat.bytesPerFrame());
63+
64+
// plot it
5765
render();
58-
freshRender = true;
59-
emit renderedFrame(currentFrame * msPerAudioFrame);
6066
}
6167
});
6268

@@ -89,13 +95,25 @@ QPair<bool, QString> ScopeWidget::loadSoundFile(const QString& filename)
8995
if(fileLoaded) {
9096

9197
// set up rendering parameters, based on soundfile properties
92-
inputChannels = sndfile->channels();
93-
inputBuffer.resize(sndfile->channels() * sndfile->samplerate()); // 1s of storage
98+
numInputChannels = sndfile->channels();
99+
100+
// initialize raw (interleaved) input buffer
101+
rawinputBuffer.resize(numInputChannels * sndfile->samplerate()); // 1s of storage
102+
103+
// initialize channel input buffers
104+
inputBuffers.resize(numInputChannels);
105+
for(int ch = 0; ch < numInputChannels; ch++) {
106+
size_t chbufSize = sndfile->samplerate() * upsampleFactor; // allow for upsampling
107+
inputBuffers[ch].resize(chbufSize);
108+
}
109+
94110
audioFramesPerMs = sndfile->samplerate() / 1000;
111+
expectedFrames = plotTimer.interval() * audioFramesPerMs;
95112
msPerAudioFrame = 1000.0 / sndfile->samplerate();
96113
calcScaling();
97114

98-
maxFramesToRead = inputBuffer.size() / sndfile->channels();
115+
maxFramesToRead = rawinputBuffer.size() / sndfile->channels();
116+
99117
totalFrames = sndfile->frames();
100118
returnToStart();
101119

@@ -258,6 +276,40 @@ void ScopeWidget::setTotalFrames(const int64_t &value)
258276
totalFrames = value;
259277
}
260278

279+
void ScopeWidget::readInput()
280+
{
281+
// estimate how far ahead to read
282+
const int64_t toFrame = qMin(totalFrames - 1, startFrame + static_cast<int64_t>(elapsedTimer.elapsed() * audioFramesPerMs));
283+
284+
// read from file
285+
framesRead = sndfile->readf(rawinputBuffer.data(), qMin(maxFramesToRead, toFrame - currentFrame));
286+
currentFrame += framesRead;
287+
288+
constexpr bool debugExpectedFrames = false;
289+
if constexpr(debugExpectedFrames) {
290+
if(framesRead > expectedFrames)
291+
qDebug() << "expected" << expectedFrames << "got" << framesRead;
292+
}
293+
294+
// de-interleave
295+
if(upsampling && numInputChannels <= 2) {
296+
if(numInputChannels == 1) {
297+
upsampler.upsampleBlockMono(inputBuffers[0].data(), rawinputBuffer.constData(), framesRead);
298+
framesAvailable = framesRead * upsampleFactor;
299+
} else if(numInputChannels == 2) {
300+
upsampler.upsampleBlockStereo(inputBuffers[0].data(), inputBuffers[1].data(), rawinputBuffer.constData(), framesRead);
301+
framesAvailable = framesRead * upsampleFactor;
302+
}
303+
} else {
304+
for(int64_t f = 0ll; f < framesRead; f++) {
305+
for(int ch = 0; ch < numInputChannels; ch++) {
306+
inputBuffers[ch][f] = rawinputBuffer[f * numInputChannels + ch];
307+
}
308+
}
309+
framesAvailable = framesRead;
310+
}
311+
}
312+
261313
void ScopeWidget::render()
262314
{
263315
constexpr size_t historyLength = 10;
@@ -293,14 +345,11 @@ void ScopeWidget::render()
293345
constexpr bool catchAllFrames = false;
294346
constexpr double rsqrt2 = 0.707;
295347
const bool drawLines = ( sweepParameters.connectDots &&
296-
(plotMode == Sweep || plotMode == SweepUpsampled) &&
348+
plotMode == Sweep &&
297349
!panicMode &&
298350
(sweepParameters.getSamplesPerSweep() > 25)
299351
);
300352

301-
const int64_t expectedFrames = plotTimer.interval() * audioFramesPerMs;
302-
const int64_t toFrame = qMin(totalFrames - 1, startFrame + static_cast<int64_t>(elapsedTimer.elapsed() * audioFramesPerMs));
303-
const int64_t framesRead = sndfile->readf(inputBuffer.data(), qMin(maxFramesToRead, toFrame - currentFrame));
304353

305354
auto pixmap = scopeDisplay->getPixmap();
306355
QPainter painter(pixmap);
@@ -323,21 +372,15 @@ void ScopeWidget::render()
323372
Qt::BevelJoin};
324373
painter.setPen(pen);
325374

326-
constexpr bool debugExpectedFrames = false;
327-
if constexpr(debugExpectedFrames) {
328-
if(framesRead > expectedFrames)
329-
qDebug() << "expected" << expectedFrames << "got" << framesRead;
330-
}
331-
332-
int64_t firstFrameToPlot = catchAllFrames ? 0ll : std::max(0ll, framesRead - expectedFrames * 2);
333-
375+
int64_t expected = expectedFrames * (upsampling ? upsampleFactor : 1);
376+
int64_t firstFrameToPlot = catchAllFrames ? 0ll : std::max(0ll, framesAvailable - 2 * expected);
334377

335378
// draw
336379
const double w = 2.0 * cx;
337-
for(int64_t i = firstFrameToPlot; i < inputChannels * framesRead; i+= inputChannels) {
380+
for(int64_t i = firstFrameToPlot; i < framesAvailable; i++) {
338381

339-
double ch0val = inputBuffer.at(i);
340-
double ch1val = (inputChannels > 1 ? inputBuffer.at(i + 1) : 0.0);
382+
double ch0val = inputBuffers[0][i];
383+
double ch1val = (numInputChannels > 1 ? inputBuffers[1][i] : 0.0);
341384

342385
switch(plotMode) {
343386
case XY:
@@ -380,44 +423,6 @@ void ScopeWidget::render()
380423
}
381424
break;
382425

383-
case SweepUpsampled:
384-
{
385-
constexpr int upsampleFactor = 4;
386-
static Interpolator<float, double, upsampleFactor> upsampler;
387-
static Differentiator<double> d;
388-
static DelayLine<double, d.delayTime> delayLine;
389-
static bool triggered = false;
390-
static double x = 0.0;
391-
static QPointF lastPoint{0.0, cy * (1.0 - sweepParameters.triggerLevel)};
392-
const double &source = ch0val;
393-
394-
double upsampled[upsampleFactor];
395-
upsampler.upsampleSingleMono(upsampled, source);
396-
for(int u = 0; u < upsampleFactor; u++) {
397-
double slope = d.get(upsampled[u]) * sweepParameters.slope;
398-
double delayed = delayLine.get(upsampled[u]);
399-
400-
triggered = triggered
401-
|| !sweepParameters.triggerEnabled // when trigger disabled -> Always Triggered
402-
|| (sweepParameters.triggerMin <= delayed && delayed <= sweepParameters.triggerMax && slope > 0.0);
403-
404-
if(triggered) {
405-
QPointF pt{x, cy * (1.0 - delayed)};
406-
if(drawLines) {
407-
plotBuffer.append(lastPoint);
408-
}
409-
lastPoint = pt;
410-
plotBuffer.append(pt);
411-
x += sweepParameters.sweepAdvanceInterpolated;
412-
if(x > w) { // sweep completed
413-
x = 0.0;
414-
triggered = false;
415-
lastPoint = {x, cy * (1.0 - sweepParameters.triggerLevel)};
416-
}
417-
}
418-
}
419-
}
420-
421426
} // ends switch
422427
} // ends loop over i
423428

@@ -428,10 +433,6 @@ void ScopeWidget::render()
428433
}
429434
plotBuffer.clear();
430435

431-
const int bytesPerFrame = audioFormat.bytesPerFrame();
432-
pushOut->write(reinterpret_cast<char*>(inputBuffer.data()), framesRead * bytesPerFrame);
433-
currentFrame += framesRead;
434-
435436
constexpr bool debugPlotBufferSize = false;
436437
if constexpr(debugPlotBufferSize) {
437438
static decltype(plotBuffer.size()) maxSize = 0ll;
@@ -446,6 +447,8 @@ void ScopeWidget::render()
446447
}
447448

448449
painter.endNativePainting();
450+
freshRender = true;
451+
emit renderedFrame(currentFrame * msPerAudioFrame);
449452
}
450453

451454
void ScopeWidget::plotTest()
@@ -556,13 +559,27 @@ Plotmode ScopeWidget::getPlotmode() const
556559
void ScopeWidget::setPlotmode(Plotmode newPlotmode)
557560
{
558561
plotMode = newPlotmode;
559-
if(plotMode == Sweep || plotMode == SweepUpsampled) {
562+
if(plotMode == Sweep) {
560563
//
561564
} else {
562565
sweepParameters.sweepUnused = true;
563566
}
564567
}
565568

569+
bool ScopeWidget::getUpsampling() const
570+
{
571+
return upsampling;
572+
}
573+
574+
void ScopeWidget::setUpsampling(bool val)
575+
{
576+
upsampling = val;
577+
sweepParameters.setUpsampleFactor(upsampling ? static_cast<double>(upsampleFactor) : 1.0);
578+
if(upsampling) {
579+
upsampler.reset();
580+
}
581+
}
582+
566583
void ScopeWidget::calcScaling()
567584
{
568585
auto pixmap = scopeDisplay->getPixmap();
@@ -579,6 +596,8 @@ void ScopeWidget::calcScaling()
579596
sweepParameters.setWidthFrameRate(w, audioFramesPerMs);
580597
}
581598

599+
600+
582601
void ScopeWidget::setAudioVolume(qreal linearVolume)
583602
{
584603
audioController->setOutputVolume(linearVolume);
@@ -615,7 +634,7 @@ bool ScopeWidget::getShowTrigger() const
615634

616635
void ScopeWidget::setShowTrigger(bool val)
617636
{
618-
showTrigger = (plotMode == Sweep || plotMode == SweepUpsampled) && val;
637+
showTrigger = (plotMode == Sweep) && val;
619638
if(paused) {
620639

621640
auto pixmap = scopeDisplay->getPixmap();

‎scopewidget.h

+38-15
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "plotmode.h"
3232
#include "sweepparameters.h"
3333
#include "audiocontroller.h"
34+
#include "interpolator.h"
3435

3536
// ScopeDisplay : this is the Oscilloscope's screen
3637
// it owns a QPixmap as an image buffer, which is accessed via getPixmap()
@@ -207,6 +208,8 @@ class ScopeWidget : public QWidget
207208
{
208209
Q_OBJECT
209210

211+
static constexpr int upsampleFactor = 4;
212+
210213
public:
211214
explicit ScopeWidget(QWidget *parent = nullptr);
212215
QPair<bool, QString> loadSoundFile(const QString &filename);
@@ -236,15 +239,18 @@ class ScopeWidget : public QWidget
236239
void setBackgroundColor(const QColor &value);
237240
void setOutputDevice(const QAudioDeviceInfo &newOutputDeviceInfo);
238241
void setShowTrigger(bool val);
239-
240242
void plotTest();
243+
244+
bool getUpsampling() const;
245+
241246
public slots:
242247
void returnToStart();
243248
void gotoPosition(int64_t milliSeconds);
244249
void wipeScreen();
245250
void setAudioVolume(qreal linearVolume);
246251
void setSweepParameters(const SweepParameters &newSweepParameters);
247252
void setPlotmode(Plotmode newPlotmode);
253+
void setUpsampling(bool val);
248254

249255
signals:
250256
void loadedFile();
@@ -258,30 +264,46 @@ public slots:
258264
AudioController *audioController{nullptr};
259265
QIODevice* pushOut{nullptr};
260266
QHBoxLayout *screenLayout{nullptr};
261-
262267
std::unique_ptr<SndfileHandle> sndfile;
263-
QVector<float> inputBuffer;
264268
QAudioFormat audioFormat;
265269
QAudioDeviceInfo outputDeviceInfo;
270+
Interpolator<float, float, upsampleFactor> upsampler;
271+
272+
// audio buffers
273+
QVector<float> rawinputBuffer; // interleaved
274+
QVector<QVector<float>> inputBuffers; // de-interleaved
275+
276+
// timing
266277
QTimer plotTimer;
267278
QTimer screenUpdateTimer;
268279
QElapsedTimer elapsedTimer;
269280

281+
// plot buffers
270282
QVector<QPointF> testPlot;
271283
QVector<QPointF> plotBuffer;
272284

273285
Plotmode plotMode{XY};
274286
bool showTrigger{false};
275287
SweepParameters sweepParameters;
276-
int inputChannels{0};
288+
289+
bool upsampling{false};
290+
int numInputChannels{0};
277291
int audioFramesPerMs{0};
278292
double msPerAudioFrame{0.0};
279-
int64_t startFrame{0};
280-
int64_t currentFrame{0ll};
281-
int64_t maxFramesToRead{0};
282-
int64_t totalFrames{0ll};
293+
294+
// audio frame accounting
295+
int64_t startFrame{0ll}; // start position for playback
296+
int64_t currentFrame{0ll}; // start position of next read
297+
int64_t framesRead{0ll}; // number of audioframes last read from file
298+
int64_t framesAvailable{011}; // number of audioframes currently stored in input buffers; after upsampling
299+
int64_t expectedFrames{0ll}; // number of audioframes expected per plotTimer timeout
300+
int64_t maxFramesToRead{0ll}; // limit of how many audioframes can fit in buffer
301+
int64_t totalFrames{0ll}; // total number of audioframes in sound file
302+
283303
bool fileLoaded{false};
284304
bool paused{true};
305+
306+
// crt properties
285307
double brightness{80.0};
286308
double focus{80.0};
287309
double persistence{32.0};
@@ -291,26 +313,27 @@ public slots:
291313
QColor darkencolor{0, 0, 0, 0};
292314
QColor backgroundColor{0, 0, 0, 255};
293315
QPainter::CompositionMode compositionMode{QPainter::CompositionMode_SourceOver};
316+
int darkenAlpha;
317+
int beamAlpha;
318+
double beamWidth;
319+
double beamIntensity;
320+
294321
bool freshRender{false};
295322

296-
// midpoint of pixmap
323+
// plot dimensions
297324
double cx;
298325
double cy;
299326
double w;
300327
double h;
301328
double divx;
302329
double divy;
303330

304-
int darkenAlpha;
305-
int beamAlpha;
306-
double beamWidth;
307-
double beamIntensity;
308-
331+
// private functions
309332
void calcScaling();
333+
void readInput();
310334
void render();
311335
void renderTest();
312336
void calcBeamAlpha();
313-
314337
void renderTrigger(QPainter *painter);
315338
void makeTestPlot();
316339
signals:

‎sndscope.pro

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ QT += core gui multimedia widgets
1010
CONFIG += c++17
1111

1212
# force -O3
13-
# QMAKE_CXXFLAGS_RELEASE -= -O2
14-
# QMAKE_CXXFLAGS_RELEASE += -O3
15-
# QMAKE_CXXFLAGS_RELEASE += -mavx2
13+
QMAKE_CXXFLAGS_RELEASE -= -O2
14+
QMAKE_CXXFLAGS_RELEASE += -O3
15+
QMAKE_CXXFLAGS_RELEASE += -mavx2
1616
# --
1717

1818
#import libsndfile

‎sweepparameters.h

+17-2
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ struct SweepParameters
4747

4848
bool getConnectDots() const;
4949

50+
double getUpsampleFactor() const;
51+
5052
static QString formatMeasurementUnits(double duration_s, const QString& units, int precision = 2)
5153
{
5254
// constexpr int m = 999;
@@ -90,10 +92,13 @@ struct SweepParameters
9092

9193

9294

95+
void setUpsampleFactor(double newUpsampleFactor);
96+
9397
private:
9498
double duration_ms{10.0};
9599
int width_pixels{640};
96100
double inputFrames_per_ms{44.1};
101+
double upsampleFactor{1.0};
97102
double sweepAdvance; // pixels per input frame
98103
double sweepAdvanceInterpolated;
99104
double triggerMin{triggerLevel - triggerTolerance};
@@ -109,8 +114,7 @@ struct SweepParameters
109114

110115
void calcSweepAdvance()
111116
{
112-
sweepAdvance = width_pixels / inputFrames_per_ms / duration_ms;
113-
sweepAdvanceInterpolated = sweepAdvance / 4;
117+
sweepAdvance = width_pixels / inputFrames_per_ms / duration_ms / upsampleFactor;
114118
}
115119
};
116120

@@ -119,6 +123,17 @@ inline bool SweepParameters::getConnectDots() const
119123
return connectDots;
120124
}
121125

126+
inline double SweepParameters::getUpsampleFactor() const
127+
{
128+
return upsampleFactor;
129+
}
130+
131+
inline void SweepParameters::setUpsampleFactor(double newUpsampleFactor)
132+
{
133+
upsampleFactor = newUpsampleFactor;
134+
calcSweepAdvance();
135+
}
136+
122137
inline void SweepParameters::setConnectDots(bool newConnectDots)
123138
{
124139
connectDots = newConnectDots;

0 commit comments

Comments
 (0)
Please sign in to comment.