Skip to content

Commit dd3bdc6

Browse files
committed
Temporary patch for racing condition crash in libjamesdsp (stereo enhancement)
1 parent 1f49c84 commit dd3bdc6

File tree

3 files changed

+65
-3
lines changed

3 files changed

+65
-3
lines changed

src/audio/base/DspHost.cpp

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "Utils.h"
33

44
#include <sstream>
5+
#include <string>
56

67
#include "DspHost.h"
78
#include "EventArgs.h"
@@ -17,6 +18,7 @@ extern "C" {
1718
#include <QDebug>
1819
#include <cstring>
1920
#include <assert.h>
21+
#include <QTimer>
2022

2123
/* C interop */
2224
inline JamesDSPLib* cast(void* raw){
@@ -50,7 +52,7 @@ inline void* GetStringForIndex(eel_string_context_state *st, float val, int32_t
5052
return (void*)&st->m_literal_strings[idx];
5153
}
5254

53-
DspHost::DspHost(void* dspPtr, MessageHandlerFunc&& extraHandler) : _extraFunc(std::move(extraHandler))
55+
DspHost::DspHost(void* dspPtr, MessageHandlerFunc&& extraHandler) : _extraFunc(std::move(extraHandler)), _stereoWideDebounce(new QTimer())
5456
{
5557
auto dsp = static_cast<JamesDSPLib*>(dspPtr);
5658
if(!dsp)
@@ -68,10 +70,23 @@ DspHost::DspHost(void* dspPtr, MessageHandlerFunc&& extraHandler) : _extraFunc(s
6870

6971
_dsp = dsp;
7072
_cache = new DspConfig();
73+
74+
75+
/* Workaround: calling StereoEnhancementSetParam while processing has a small chance of causing a crash inside analysisWarpedPFBStereo
76+
* due to the possiblity that snh->subband[x] is accessed before initWarpedPFB or assignPtrWarpedPFB is called by StereoEnhancementSetParam
77+
-> pausing processing not easily doable (in time); reduce strain on StereoEnhancementSetParam instead */
78+
/* TODO: replace workaround with proper patch */
79+
_stereoWideDebounce->setInterval(750);
80+
_stereoWideDebounce->setSingleShot(true);
81+
QObject::connect(_stereoWideDebounce, &QTimer::timeout, [this]{
82+
util::debug("-> Timer finished!");
83+
StereoEnhancementSetParam(cast(this->_dsp), _cache->get<float>(DspConfig::stereowide_level) / 100.0f);
84+
});
7185
}
7286

7387
DspHost::~DspHost()
7488
{
89+
_stereoWideDebounce->deleteLater();
7590
setStdOutHandler(NULL, NULL);
7691
}
7792

@@ -582,9 +597,28 @@ bool DspHost::update(DspConfig *config, bool ignoreCache)
582597
else
583598
StereoEnhancementDisable(cast(this->_dsp));
584599
break;
585-
case DspConfig::stereowide_level:
586-
StereoEnhancementSetParam(cast(this->_dsp), current.toFloat() / 100.0f);
600+
case DspConfig::stereowide_level: {
601+
_stereoWideClock.tock();
602+
auto duration = _stereoWideClock.duration();
603+
_stereoWideClock.tick();
604+
util::debug(std::to_string(duration.count()));
605+
606+
if(duration.count() > 750 && !_stereoWideDebounce->isActive())
607+
{
608+
util::debug("StereoEnhancementSetParam");
609+
StereoEnhancementSetParam(cast(this->_dsp), _cache->get<float>(DspConfig::stereowide_level) / 100.0f);
610+
}
611+
else if(!_stereoWideDebounce->isActive())
612+
{
613+
util::debug("Timer start!");
614+
_stereoWideDebounce->start();
615+
}
616+
else
617+
{
618+
util::debug("Timer already running!");
619+
}
587620
break;
621+
}
588622
case DspConfig::tone_enable:
589623
if(current.toBool())
590624
FIREqualizerEnable(cast(this->_dsp));

src/audio/base/DspHost.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@
55
#include <any>
66
#include <list>
77
#include <memory>
8+
#include <chrono>
89

910
#include "EelVariable.h"
11+
#include "Utils.h"
1012

1113
class DspConfig;
1214
class QVariant;
15+
class QTimer;
1316

1417
class DspHost
1518
{
@@ -43,6 +46,8 @@ class DspHost
4346
due to #defines and other global definitons that may conflict */
4447
void* _dsp; // JamesDSPLib*
4548
DspConfig* _cache;
49+
ClockMeasure<std::chrono::milliseconds, std::chrono::steady_clock> _stereoWideClock;
50+
QTimer* _stereoWideDebounce;
4651

4752
void updateLimiter(DspConfig *config);
4853
void updateFirEqualizer(DspConfig *config);
@@ -52,6 +57,7 @@ class DspHost
5257
void updateConvolver(DspConfig *config);
5358
void updateGraphicEq(DspConfig *config);
5459
void updateCrossfeed(DspConfig *config);
60+
5561
};
5662

5763
/* C interop function */

src/audio/base/Utils.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,29 @@
55
#include <string>
66
#include <algorithm>
77
#include <map>
8+
#include <chrono>
89

10+
template <class DT = std::chrono::milliseconds,
11+
class ClockT = std::chrono::steady_clock>
12+
class ClockMeasure
13+
{
14+
using timep_t = typename ClockT::time_point;
15+
timep_t _start = {}, _end = {};
16+
17+
public:
18+
void tick() {
19+
_end = timep_t{};
20+
_start = ClockT::now();
21+
}
22+
23+
void tock() { _end = ClockT::now(); }
24+
25+
template <class T = DT>
26+
auto duration() const {
27+
assert(_end != timep_t{} && "toc before reporting");
28+
return std::chrono::duration_cast<T>(_end - _start);
29+
}
30+
};
931
namespace util {
1032

1133
const float minimum_db_level = -100.0F;

0 commit comments

Comments
 (0)