Skip to content

Commit 5dc33b1

Browse files
committed
feat: add manual benchmarking control
1 parent 44190e6 commit 5dc33b1

16 files changed

+254
-9
lines changed

src/audio/base/Base.pri

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ INCLUDEPATH += $$PWD
22

33
HEADERS += \
44
$$PWD/AppNode.h \
5+
$$PWD/BenchmarkWorker.h \
56
$$PWD/DspHost.h \
67
$$PWD/DspStatus.h \
78
$$PWD/EelVariable.h \
@@ -13,5 +14,6 @@ HEADERS += \
1314
$$PWD/Utils.h
1415

1516
SOURCES += \
17+
$$PWD/BenchmarkWorker.cpp \
1618
$$PWD/DspHost.cpp \
1719
$$PWD/Utils.cpp

src/audio/base/BenchmarkWorker.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#include "BenchmarkWorker.h"
2+
3+
#include "config/AppConfig.h"
4+
#include "utils/Log.h"
5+
6+
extern "C" {
7+
#include <jdsp_header.h>
8+
}
9+
10+
BenchmarkWorker::BenchmarkWorker(QObject *parent) : QObject{parent} {}
11+
12+
void BenchmarkWorker::writeCache(int num, double* data) {
13+
QString result = QString::number(data[0]);
14+
15+
for(int i = 1; i < MAX_BENCHMARK; i++)
16+
result.append(";" + QString::number(data[i]));
17+
18+
AppConfig::instance().set(num == 0 ? AppConfig::BenchmarkCacheC0 : AppConfig::BenchmarkCacheC1, result);
19+
}
20+
21+
void BenchmarkWorker::process() {
22+
Log::debug("Starting benchmark...");
23+
JamesDSP_Start_benchmark();
24+
25+
double* c0 = new double[MAX_BENCHMARK];
26+
double* c1 = new double[MAX_BENCHMARK];
27+
JamesDSP_Save_benchmark(c0, c1);
28+
29+
writeCache(0, c0);
30+
writeCache(1, c1);
31+
delete[] c0;
32+
delete[] c1;
33+
34+
emit finished();
35+
}

src/audio/base/BenchmarkWorker.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#ifndef BENCHMARKWORKER_H
2+
#define BENCHMARKWORKER_H
3+
4+
#include <QObject>
5+
6+
class BenchmarkWorker : public QObject {
7+
Q_OBJECT
8+
public:
9+
BenchmarkWorker(QObject *parent = nullptr);
10+
11+
public slots:
12+
void process();
13+
14+
signals:
15+
void finished();
16+
17+
private:
18+
void writeCache(int num, double *data);
19+
20+
};
21+
22+
#endif // BENCHMARKWORKER_H

src/audio/base/DspHost.cpp

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#include "config/DspConfig.h"
22
#include "Utils.h"
3+
#include "BenchmarkWorker.h"
34

5+
#include <QTimer>
46
#include <sstream>
57
#include <string>
68

@@ -18,6 +20,7 @@ extern "C" {
1820

1921
#include <QElapsedTimer>
2022
#include <QTextStream>
23+
#include <QThread>
2124
#include <QDebug>
2225
#include <cstring>
2326
#include <assert.h>
@@ -45,11 +48,81 @@ DspHost::DspHost(void* dspPtr, MessageHandlerFunc&& extraHandler) : _extraFunc(s
4548

4649
_dsp = dsp;
4750
_cache = new DspConfig();
51+
52+
benchmarkThread = new QThread();
53+
benchmarkWorker = new BenchmarkWorker();
54+
55+
QObject::connect(benchmarkThread, &QThread::started, benchmarkWorker, &BenchmarkWorker::process);
56+
QObject::connect(benchmarkWorker, &BenchmarkWorker::finished, benchmarkThread, &QThread::quit);
57+
QObject::connect(benchmarkWorker, &BenchmarkWorker::finished, benchmarkThread, [this] {
58+
dispatch(Message::BenchmarkDone, nullptr);
59+
});
60+
61+
62+
if(AppConfig::instance().get<bool>(AppConfig::BenchmarkOnBoot))
63+
QTimer::singleShot(30000, [this]{ runBenchmarks(); });
4864
}
4965

5066
DspHost::~DspHost()
5167
{
5268
setStdOutHandler(NULL, NULL);
69+
70+
_cache->deleteLater();
71+
benchmarkThread->deleteLater();
72+
benchmarkWorker->deleteLater();
73+
74+
_cache = nullptr;
75+
benchmarkWorker = nullptr;
76+
benchmarkThread = nullptr;
77+
}
78+
79+
void DspHost::runBenchmarks()
80+
{
81+
if(benchmarkThread->isRunning()) {
82+
Log::warning("Another benchmark is already active");
83+
return;
84+
}
85+
86+
benchmarkWorker->moveToThread(benchmarkThread);
87+
benchmarkThread->start();
88+
}
89+
90+
void DspHost::loadBenchmarkData()
91+
{
92+
// Empty cache = no benchmark data stored
93+
if(AppConfig::instance().get<QString>(AppConfig::BenchmarkCacheC0).isEmpty() &&
94+
AppConfig::instance().get<QString>(AppConfig::BenchmarkCacheC1).isEmpty())
95+
return;
96+
97+
auto loadFromCache = [](int num, double* output){
98+
auto values = AppConfig::instance().get<QString>(num == 0 ? AppConfig::BenchmarkCacheC0 : AppConfig::BenchmarkCacheC1).split(';', Qt::SkipEmptyParts);
99+
if(values.size() != MAX_BENCHMARK)
100+
return false;
101+
102+
for(int i = 0; i < values.size(); i++) {
103+
bool ok = false;
104+
output[i] = values[i].toInt(&ok);
105+
if(!ok)
106+
return false;
107+
}
108+
return true;
109+
};
110+
111+
double* c0 = new double[MAX_BENCHMARK];
112+
double* c1 = new double[MAX_BENCHMARK];
113+
114+
bool ok0 = loadFromCache(0, c0);
115+
bool ok1 = loadFromCache(1, c1);
116+
117+
if(!ok0 || !ok1) {
118+
Log::error("Failed to parse cached benchmark data");
119+
return;
120+
}
121+
122+
JamesDSP_Load_benchmark(c0, c1);
123+
124+
delete[] c0;
125+
delete[] c1;
53126
}
54127

55128
void DspHost::updateLimiter(DspConfig* config)

src/audio/base/DspHost.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
#include "EelVariable.h"
1010
#include "Utils.h"
1111

12+
class BenchmarkWorker;
1213
class DspConfig;
14+
class QThread;
1315
class QVariant;
1416

1517
class DspHost
@@ -21,7 +23,8 @@ class DspHost
2123
EelCompilerResult,
2224
EelWriteOutputBuffer,
2325
ConvolverInfoChanged,
24-
PrintfWriteOutputBuffer
26+
PrintfWriteOutputBuffer,
27+
BenchmarkDone
2528
};
2629

2730
typedef std::function<void(Message,std::any)> MessageHandlerFunc;
@@ -35,6 +38,9 @@ class DspHost
3538
std::vector<EelVariable> enumEelVariables();
3639
bool manipulateEelVariable(const char *name, float value);
3740
void freezeLiveprogExecution(bool freeze);
41+
void runBenchmarks();
42+
void loadBenchmarkData();
43+
3844
void dispatch(Message msg, std::any value);
3945

4046
private:
@@ -46,6 +52,9 @@ class DspHost
4652
void* _dsp; // JamesDSPLib*
4753
DspConfig* _cache;
4854

55+
QThread* benchmarkThread;
56+
BenchmarkWorker* benchmarkWorker;
57+
4958
void updateLimiter(DspConfig *config);
5059
void updateFirEqualizer(DspConfig *config);
5160
void updateVdc(DspConfig *config);

src/audio/base/IAudioService.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ public slots:
3232

3333
void reloadLiveprog();
3434
void enumerateLiveprogVariables();
35+
void runBenchmarks();
3536

3637
void handleMessage(DspHost::Message msg, std::any arg);
3738

@@ -43,6 +44,7 @@ public slots:
4344
void convolverInfoChanged(const ConvolverInfoEventArgs& args);
4445
void logOutputReceived(const QString& output);
4546
void outputDeviceChanged(const QString& deviceName, const QString& deviceId);
47+
void benchmarkDone();
4648

4749
};
4850

@@ -57,6 +59,11 @@ inline void IAudioService::enumerateLiveprogVariables()
5759
emit eelVariablesEnumerated(vars);
5860
}
5961

62+
inline void IAudioService::runBenchmarks()
63+
{
64+
host()->runBenchmarks();
65+
}
66+
6067
inline void IAudioService::handleMessage(DspHost::Message msg, std::any value)
6168
{
6269
switch(msg)
@@ -80,6 +87,9 @@ inline void IAudioService::handleMessage(DspHost::Message msg, std::any value)
8087
case DspHost::PrintfWriteOutputBuffer:
8188
emit logOutputReceived(std::any_cast<QString>(value));
8289
break;
90+
case DspHost::BenchmarkDone:
91+
emit benchmarkDone();
92+
break;
8393
default:
8494
break;
8595
}

src/audio/pipewire/PipewireAudioService.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ PipewireAudioService::PipewireAudioService()
1616

1717
mgr = std::make_unique<PwPipelineManager>();
1818
appMgr = std::make_unique<PwAppManager>(mgr.get());
19-
plugin = new PwJamesDspPlugin(mgr.get(), AppConfig::instance().get<bool>(AppConfig::BenchmarkOnBoot), this);
19+
plugin = new PwJamesDspPlugin(mgr.get(), this);
2020
effects = std::make_unique<FilterContainer>(mgr.get(), plugin, &AppConfig::instance());
2121

2222
mgr.get()->new_default_sink_name.connect([=](const std::string& name) {

src/audio/pipewire/PwJamesDspPlugin.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ void receivePrintfStdout(const char* msg, void* userdata) {
1515
}
1616
}
1717

18-
PwJamesDspPlugin::PwJamesDspPlugin(PwPipelineManager* pipe_manager, bool enableBenchmark, IAudioService* parent_service)
18+
PwJamesDspPlugin::PwJamesDspPlugin(PwPipelineManager* pipe_manager, IAudioService* parent_service)
1919
: PwPluginBase("@PwJamesDspPlugin: ", "JamesDsp", pipe_manager)
2020
{
2121
setMessageHandler(std::bind(&IAudioService::handleMessage, parent_service, std::placeholders::_1, std::placeholders::_2));
@@ -29,8 +29,6 @@ PwJamesDspPlugin::PwJamesDspPlugin(PwPipelineManager* pipe_manager, bool enableB
2929
#endif
3030
JamesDSPGlobalMemoryAllocation();
3131
JamesDSPInit(this->dsp, 128, 48000);
32-
if(enableBenchmark)
33-
JamesDSP_Start_benchmark();
3432
#ifdef DEBUG_FPE
3533
fedisableexcept(FE_ALL_EXCEPT & ~FE_INEXACT & ~FE_INVALID);
3634
#endif

src/audio/pipewire/PwJamesDspPlugin.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ extern "C" {
1111

1212
class PwJamesDspPlugin : public PwPluginBase, public IDspElement {
1313
public:
14-
PwJamesDspPlugin(PwPipelineManager* pipe_manager, bool enableBenchmark, IAudioService* parent_service);
14+
PwJamesDspPlugin(PwPipelineManager* pipe_manager, IAudioService* parent_service);
1515
PwJamesDspPlugin(const PwJamesDspPlugin&) = delete;
1616
auto operator=(const PwJamesDspPlugin&) -> PwJamesDspPlugin& = delete;
1717
PwJamesDspPlugin(const PwJamesDspPlugin&&) = delete;

src/config/AppConfig.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ AppConfig::AppConfig()
4343
DEFINE_KEY(AudioAppBlocklistInvert, false);
4444
DEFINE_KEY(AudioInactivityTimeout, 10);
4545

46-
DEFINE_KEY(BenchmarkOnBoot, true);
46+
DEFINE_KEY(BenchmarkOnBoot, false);
47+
DEFINE_KEY(BenchmarkCacheC0, "");
48+
DEFINE_KEY(BenchmarkCacheC1, "");
4749

4850
DEFINE_KEY(AeqPlotDarkMode, false);
4951

0 commit comments

Comments
 (0)