dspx 1.3.6 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -26
- package/binding.gyp +2 -1
- package/dist/bindings.d.ts +74 -0
- package/dist/bindings.d.ts.map +1 -1
- package/dist/bindings.js +94 -0
- package/dist/bindings.js.map +1 -1
- package/package.json +1 -1
- package/prebuilds/win32-x64/dspx.node +0 -0
- package/src/native/DspPipeline.cc +320 -81
- package/src/native/IDspStage.h +2 -10
- package/src/native/adapters/ChannelMergeStage.h +31 -0
- package/src/native/adapters/ChannelSelectStage.h +31 -0
- package/src/native/adapters/ChannelSelectorStage.h +17 -0
- package/src/native/adapters/FftStage.cc +20 -0
- package/src/native/adapters/FftStage.h +2 -0
- package/src/native/adapters/GscPreprocessorStage.h +44 -0
- package/src/native/adapters/MatrixTransformStage.h +48 -0
- package/src/native/adapters/MelSpectrogramStage.h +33 -0
- package/src/native/adapters/MfccStage.h +22 -0
- package/src/native/adapters/TimeAlignmentStage.cc +743 -0
- package/src/native/adapters/TimeAlignmentStage.h +183 -0
- package/src/native/adapters/WaveletTransformStage.h +16 -0
|
@@ -38,6 +38,10 @@
|
|
|
38
38
|
#include "adapters/IntegratorStage.h" // Integrator stage
|
|
39
39
|
#include "adapters/SnrStage.h" // SNR stage
|
|
40
40
|
#include "adapters/KalmanFilterStage.h" // Kalman Filter stage
|
|
41
|
+
#include "adapters/TimeAlignmentStage.h" // Time Alignment stage
|
|
42
|
+
|
|
43
|
+
#include <iostream>
|
|
44
|
+
#include <thread> // For std::this_thread in debug code
|
|
41
45
|
|
|
42
46
|
namespace dsp
|
|
43
47
|
{
|
|
@@ -51,6 +55,12 @@ namespace dsp
|
|
|
51
55
|
#include <cstdlib>
|
|
52
56
|
#include "utils/Toon.h"
|
|
53
57
|
|
|
58
|
+
// Helper function to check debug flag
|
|
59
|
+
inline bool isDebugEnabled()
|
|
60
|
+
{
|
|
61
|
+
return std::getenv("DSPX_DEBUG") != nullptr;
|
|
62
|
+
}
|
|
63
|
+
|
|
54
64
|
// SIMD optimizations for timestamp interpolation
|
|
55
65
|
// Priority: AVX2 (8-wide) > SSE (4-wide) > NEON (4-wide) > Scalar
|
|
56
66
|
#if defined(__AVX2__) || (defined(_MSC_VER) && defined(__AVX2__))
|
|
@@ -108,13 +118,22 @@ namespace dsp
|
|
|
108
118
|
DspPipeline::DspPipeline(const Napi::CallbackInfo &info)
|
|
109
119
|
: Napi::ObjectWrap<DspPipeline>(info)
|
|
110
120
|
{
|
|
111
|
-
|
|
112
|
-
|
|
121
|
+
if (isDebugEnabled())
|
|
122
|
+
{
|
|
123
|
+
std::cout << "[DEBUG] DspPipeline::Constructor - this=" << this
|
|
124
|
+
<< ", creating pipeline" << std::endl;
|
|
125
|
+
}
|
|
113
126
|
// Initialize the lock
|
|
114
127
|
m_isBusy = std::make_shared<std::atomic<bool>>(false);
|
|
115
|
-
|
|
128
|
+
if (isDebugEnabled())
|
|
129
|
+
{
|
|
130
|
+
std::cout << "[DEBUG] DspPipeline::Constructor - m_isBusy=" << m_isBusy.get() << std::endl;
|
|
131
|
+
}
|
|
116
132
|
InitializeStageFactories();
|
|
117
|
-
|
|
133
|
+
if (isDebugEnabled())
|
|
134
|
+
{
|
|
135
|
+
std::cout << "[DEBUG] DspPipeline::Constructor - complete, this=" << this << std::endl;
|
|
136
|
+
}
|
|
118
137
|
}
|
|
119
138
|
|
|
120
139
|
/**
|
|
@@ -1165,6 +1184,57 @@ namespace dsp
|
|
|
1165
1184
|
return std::make_unique<adapters::KalmanFilterStage>(
|
|
1166
1185
|
dimensions, processNoise, measurementNoise, initialError);
|
|
1167
1186
|
};
|
|
1187
|
+
|
|
1188
|
+
// ===================================================================
|
|
1189
|
+
// Time Alignment Stage
|
|
1190
|
+
// ===================================================================
|
|
1191
|
+
m_stageFactories["timeAlignment"] = [](const Napi::Object ¶ms)
|
|
1192
|
+
{
|
|
1193
|
+
float targetSampleRate = params.Has("targetSampleRate")
|
|
1194
|
+
? params.Get("targetSampleRate").As<Napi::Number>().FloatValue()
|
|
1195
|
+
: 1000.0f;
|
|
1196
|
+
|
|
1197
|
+
adapters::InterpolationMethod interpMethod = adapters::InterpolationMethod::LINEAR;
|
|
1198
|
+
if (params.Has("interpolationMethod"))
|
|
1199
|
+
{
|
|
1200
|
+
std::string method = params.Get("interpolationMethod").As<Napi::String>().Utf8Value();
|
|
1201
|
+
if (method == "cubic")
|
|
1202
|
+
interpMethod = adapters::InterpolationMethod::CUBIC;
|
|
1203
|
+
else if (method == "sinc")
|
|
1204
|
+
interpMethod = adapters::InterpolationMethod::SINC;
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
adapters::GapPolicy gapPolicy = adapters::GapPolicy::INTERPOLATE;
|
|
1208
|
+
if (params.Has("gapPolicy"))
|
|
1209
|
+
{
|
|
1210
|
+
std::string policy = params.Get("gapPolicy").As<Napi::String>().Utf8Value();
|
|
1211
|
+
if (policy == "error")
|
|
1212
|
+
gapPolicy = adapters::GapPolicy::ERROR;
|
|
1213
|
+
else if (policy == "zero-fill")
|
|
1214
|
+
gapPolicy = adapters::GapPolicy::ZERO_FILL;
|
|
1215
|
+
else if (policy == "hold")
|
|
1216
|
+
gapPolicy = adapters::GapPolicy::HOLD;
|
|
1217
|
+
else if (policy == "extrapolate")
|
|
1218
|
+
gapPolicy = adapters::GapPolicy::EXTRAPOLATE;
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
float gapThreshold = params.Has("gapThreshold")
|
|
1222
|
+
? params.Get("gapThreshold").As<Napi::Number>().FloatValue()
|
|
1223
|
+
: 1.5f;
|
|
1224
|
+
|
|
1225
|
+
adapters::DriftCompensation driftComp = adapters::DriftCompensation::NONE;
|
|
1226
|
+
if (params.Has("driftCompensation"))
|
|
1227
|
+
{
|
|
1228
|
+
std::string drift = params.Get("driftCompensation").As<Napi::String>().Utf8Value();
|
|
1229
|
+
if (drift == "regression")
|
|
1230
|
+
driftComp = adapters::DriftCompensation::REGRESSION;
|
|
1231
|
+
else if (drift == "pll")
|
|
1232
|
+
driftComp = adapters::DriftCompensation::PLL;
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
return std::make_unique<adapters::TimeAlignmentStage>(
|
|
1236
|
+
targetSampleRate, interpMethod, gapPolicy, gapThreshold, driftComp);
|
|
1237
|
+
};
|
|
1168
1238
|
}
|
|
1169
1239
|
|
|
1170
1240
|
/**
|
|
@@ -1174,26 +1244,38 @@ namespace dsp
|
|
|
1174
1244
|
Napi::Value DspPipeline::AddStage(const Napi::CallbackInfo &info)
|
|
1175
1245
|
{
|
|
1176
1246
|
Napi::Env env = info.Env();
|
|
1177
|
-
|
|
1247
|
+
if (isDebugEnabled())
|
|
1248
|
+
{
|
|
1249
|
+
std::cout << "[DEBUG] DspPipeline::AddStage - this=" << this << std::endl;
|
|
1250
|
+
}
|
|
1178
1251
|
|
|
1179
1252
|
// Check if pipeline is disposed
|
|
1180
1253
|
if (m_disposed)
|
|
1181
1254
|
{
|
|
1182
|
-
|
|
1255
|
+
if (isDebugEnabled())
|
|
1256
|
+
{
|
|
1257
|
+
std::cout << "[DEBUG] AddStage - pipeline disposed, this=" << this << std::endl;
|
|
1258
|
+
}
|
|
1183
1259
|
Napi::Error::New(env, "Pipeline is disposed").ThrowAsJavaScriptException();
|
|
1184
1260
|
return env.Undefined();
|
|
1185
1261
|
}
|
|
1186
1262
|
|
|
1187
1263
|
if (*m_isBusy)
|
|
1188
1264
|
{
|
|
1189
|
-
|
|
1265
|
+
if (isDebugEnabled())
|
|
1266
|
+
{
|
|
1267
|
+
std::cout << "[DEBUG] AddStage - pipeline busy, this=" << this << std::endl;
|
|
1268
|
+
}
|
|
1190
1269
|
Napi::Error::New(env, "Cannot add stage while processing").ThrowAsJavaScriptException();
|
|
1191
1270
|
return env.Undefined();
|
|
1192
1271
|
}
|
|
1193
1272
|
|
|
1194
1273
|
// 1. Get arguments from TypeScript
|
|
1195
1274
|
std::string stageName = info[0].As<Napi::String>();
|
|
1196
|
-
|
|
1275
|
+
if (isDebugEnabled())
|
|
1276
|
+
{
|
|
1277
|
+
std::cout << "[DEBUG] AddStage - stageName=" << stageName << ", this=" << this << std::endl;
|
|
1278
|
+
}
|
|
1197
1279
|
Napi::Object params = info[1].As<Napi::Object>();
|
|
1198
1280
|
|
|
1199
1281
|
// 2. Look up the stage factory in the map
|
|
@@ -1234,12 +1316,18 @@ namespace dsp
|
|
|
1234
1316
|
Napi::Value DspPipeline::AddFilterStage(const Napi::CallbackInfo &info)
|
|
1235
1317
|
{
|
|
1236
1318
|
Napi::Env env = info.Env();
|
|
1237
|
-
|
|
1319
|
+
if (isDebugEnabled())
|
|
1320
|
+
{
|
|
1321
|
+
std::cout << "[DEBUG] DspPipeline::AddFilterStage - this=" << this << std::endl;
|
|
1322
|
+
}
|
|
1238
1323
|
|
|
1239
1324
|
// Check if pipeline is disposed
|
|
1240
1325
|
if (m_disposed)
|
|
1241
1326
|
{
|
|
1242
|
-
|
|
1327
|
+
if (isDebugEnabled())
|
|
1328
|
+
{
|
|
1329
|
+
std::cout << "[DEBUG] AddFilterStage - pipeline disposed, this=" << this << std::endl;
|
|
1330
|
+
}
|
|
1243
1331
|
Napi::Error::New(env, "Pipeline is disposed").ThrowAsJavaScriptException();
|
|
1244
1332
|
return env.Undefined();
|
|
1245
1333
|
}
|
|
@@ -1875,7 +1963,10 @@ namespace dsp
|
|
|
1875
1963
|
m_timestampRef(std::move(timestampRef)),
|
|
1876
1964
|
m_busyLock(busyLock)
|
|
1877
1965
|
{
|
|
1878
|
-
|
|
1966
|
+
if (isDebugEnabled())
|
|
1967
|
+
{
|
|
1968
|
+
std::cout << "[DEBUG] ProcessWorker::ProcessWorker - this=" << this << std::endl;
|
|
1969
|
+
}
|
|
1879
1970
|
m_stageCount = m_stages.size();
|
|
1880
1971
|
m_stageTypes.reserve(m_stageCount);
|
|
1881
1972
|
for (const auto &stage : m_stages)
|
|
@@ -1888,11 +1979,14 @@ namespace dsp
|
|
|
1888
1979
|
// This runs on a worker thread (not blocking the event loop)
|
|
1889
1980
|
void Execute() override
|
|
1890
1981
|
{
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1982
|
+
if (isDebugEnabled())
|
|
1983
|
+
{
|
|
1984
|
+
std::cout << "[DEBUG] ProcessWorker::Execute - START, this=" << this
|
|
1985
|
+
<< ", data=" << m_data << ", numSamples=" << m_numSamples
|
|
1986
|
+
<< ", channels=" << m_channels << std::endl;
|
|
1987
|
+
std::cout << "[WORKER-" << std::this_thread::get_id() << "] Execute START (stages="
|
|
1988
|
+
<< m_stages.size() << ")" << std::endl;
|
|
1989
|
+
}
|
|
1896
1990
|
|
|
1897
1991
|
// CRITICAL FIX: Use a unique_ptr for timestamp ownership
|
|
1898
1992
|
std::vector<float> generatedTimestamps;
|
|
@@ -1903,7 +1997,10 @@ namespace dsp
|
|
|
1903
1997
|
// 1. Generate Timestamps if missing
|
|
1904
1998
|
if (m_timestamps == nullptr)
|
|
1905
1999
|
{
|
|
1906
|
-
|
|
2000
|
+
if (isDebugEnabled())
|
|
2001
|
+
{
|
|
2002
|
+
std::cout << "[DEBUG] Execute - generating timestamps, sampleRate=" << m_sampleRate << std::endl;
|
|
2003
|
+
}
|
|
1907
2004
|
|
|
1908
2005
|
generatedTimestamps.resize(m_numSamples);
|
|
1909
2006
|
double dt = (m_sampleRate > 0.0) ? (1000.0 / m_sampleRate) : 1.0;
|
|
@@ -1914,7 +2011,10 @@ namespace dsp
|
|
|
1914
2011
|
}
|
|
1915
2012
|
|
|
1916
2013
|
m_timestamps = generatedTimestamps.data();
|
|
1917
|
-
|
|
2014
|
+
if (isDebugEnabled())
|
|
2015
|
+
{
|
|
2016
|
+
std::cout << "[DEBUG] Execute - timestamps generated, addr=" << m_timestamps << std::endl;
|
|
2017
|
+
}
|
|
1918
2018
|
}
|
|
1919
2019
|
|
|
1920
2020
|
// 2. Process the buffer through all stages
|
|
@@ -1925,23 +2025,34 @@ namespace dsp
|
|
|
1925
2025
|
|
|
1926
2026
|
const bool debugStageDumps = std::getenv("DSPX_DEBUG_STAGE_DUMPS") != nullptr;
|
|
1927
2027
|
|
|
1928
|
-
|
|
2028
|
+
if (isDebugEnabled())
|
|
2029
|
+
{
|
|
2030
|
+
std::cout << "[DEBUG] Execute - processing through " << m_stages.size() << " stages" << std::endl;
|
|
2031
|
+
}
|
|
1929
2032
|
for (size_t stageIdx = 0; stageIdx < m_stages.size(); ++stageIdx)
|
|
1930
2033
|
{
|
|
1931
2034
|
const auto &stage = m_stages[stageIdx];
|
|
1932
2035
|
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
2036
|
+
if (isDebugEnabled())
|
|
2037
|
+
{
|
|
2038
|
+
std::cout << "[DEBUG] Execute - stage " << stageIdx << ", type="
|
|
2039
|
+
<< stage->getType() << ", addr=" << stage.get()
|
|
2040
|
+
<< ", isResizing=" << stage->isResizing() << std::endl;
|
|
2041
|
+
}
|
|
1936
2042
|
|
|
1937
2043
|
if (stage->isResizing())
|
|
1938
2044
|
{
|
|
1939
|
-
// Calculate output size
|
|
1940
|
-
size_t
|
|
1941
|
-
float *outputBuffer = new float[outputSize];
|
|
2045
|
+
// Calculate output size estimate
|
|
2046
|
+
size_t estimatedSize = stage->calculateOutputSize(currentSize);
|
|
1942
2047
|
|
|
1943
|
-
//
|
|
1944
|
-
|
|
2048
|
+
// Allocate buffer with estimate
|
|
2049
|
+
float *outputBuffer = new float[estimatedSize];
|
|
2050
|
+
|
|
2051
|
+
if (isDebugEnabled())
|
|
2052
|
+
{
|
|
2053
|
+
std::cout << "[DEBUG] Execute - allocated output buffer, size=" << estimatedSize
|
|
2054
|
+
<< ", addr=" << outputBuffer << std::endl;
|
|
2055
|
+
}
|
|
1945
2056
|
|
|
1946
2057
|
// CRITICAL: Save the PREVIOUS size before processResizing updates currentSize
|
|
1947
2058
|
size_t prevSize = currentSize;
|
|
@@ -1951,14 +2062,34 @@ namespace dsp
|
|
|
1951
2062
|
outputBuffer, actualOutputSize,
|
|
1952
2063
|
m_channels, m_timestamps);
|
|
1953
2064
|
|
|
1954
|
-
//
|
|
1955
|
-
|
|
1956
|
-
|
|
2065
|
+
// Safety check: if actual size exceeds estimate, reallocate
|
|
2066
|
+
if (actualOutputSize > estimatedSize)
|
|
2067
|
+
{
|
|
2068
|
+
std::cerr << "[WARNING] Stage calculateOutputSize() underestimated: "
|
|
2069
|
+
<< "estimated=" << estimatedSize
|
|
2070
|
+
<< ", actual=" << actualOutputSize << std::endl;
|
|
2071
|
+
|
|
2072
|
+
// Reallocate with correct size and copy data
|
|
2073
|
+
float *newBuffer = new float[actualOutputSize];
|
|
2074
|
+
std::memcpy(newBuffer, outputBuffer, estimatedSize * sizeof(float));
|
|
2075
|
+
delete[] outputBuffer;
|
|
2076
|
+
outputBuffer = newBuffer;
|
|
2077
|
+
}
|
|
2078
|
+
|
|
2079
|
+
if (isDebugEnabled())
|
|
2080
|
+
{
|
|
2081
|
+
std::cout << "[DEBUG] Execute - stage " << stageIdx << " resized: "
|
|
2082
|
+
<< prevSize << " -> " << actualOutputSize // Use prevSize!
|
|
2083
|
+
<< ", buffer=" << outputBuffer << std::endl;
|
|
2084
|
+
}
|
|
1957
2085
|
|
|
1958
2086
|
// Free previous temp buffer if we owned it
|
|
1959
2087
|
if (usingTempBuffer && tempBuffer != nullptr)
|
|
1960
2088
|
{
|
|
1961
|
-
|
|
2089
|
+
if (isDebugEnabled())
|
|
2090
|
+
{
|
|
2091
|
+
std::cout << "[DEBUG] Execute - freeing previous temp buffer=" << tempBuffer << std::endl;
|
|
2092
|
+
}
|
|
1962
2093
|
delete[] tempBuffer;
|
|
1963
2094
|
}
|
|
1964
2095
|
|
|
@@ -1975,15 +2106,21 @@ namespace dsp
|
|
|
1975
2106
|
int outputChannels = stage->getOutputChannels();
|
|
1976
2107
|
if (outputChannels > 0)
|
|
1977
2108
|
{
|
|
1978
|
-
|
|
1979
|
-
|
|
2109
|
+
if (isDebugEnabled())
|
|
2110
|
+
{
|
|
2111
|
+
std::cout << "[DEBUG] Execute - channels changed: " << m_channels
|
|
2112
|
+
<< " -> " << outputChannels << std::endl;
|
|
2113
|
+
}
|
|
1980
2114
|
m_channels = outputChannels;
|
|
1981
2115
|
}
|
|
1982
2116
|
|
|
1983
2117
|
// Re-interpolate timestamps if needed
|
|
1984
2118
|
if (m_timestamps != nullptr)
|
|
1985
2119
|
{
|
|
1986
|
-
|
|
2120
|
+
if (isDebugEnabled())
|
|
2121
|
+
{
|
|
2122
|
+
std::cout << "[DEBUG] Execute - reinterpolating timestamps" << std::endl;
|
|
2123
|
+
}
|
|
1987
2124
|
|
|
1988
2125
|
double timeScale = stage->getTimeScaleFactor();
|
|
1989
2126
|
size_t numOutputSamples = actualOutputSize / m_channels;
|
|
@@ -2008,21 +2145,31 @@ namespace dsp
|
|
|
2008
2145
|
allocatedTimestamps = std::move(newTimestamps);
|
|
2009
2146
|
m_timestamps = allocatedTimestamps->data();
|
|
2010
2147
|
|
|
2011
|
-
|
|
2012
|
-
|
|
2148
|
+
if (isDebugEnabled())
|
|
2149
|
+
{
|
|
2150
|
+
std::cout << "[DEBUG] Execute - timestamps reinterpolated (SIMD), new addr="
|
|
2151
|
+
<< m_timestamps << std::endl;
|
|
2152
|
+
}
|
|
2013
2153
|
}
|
|
2014
2154
|
}
|
|
2015
2155
|
else
|
|
2016
2156
|
{
|
|
2017
2157
|
// In-place processing
|
|
2018
|
-
|
|
2158
|
+
if (isDebugEnabled())
|
|
2159
|
+
{
|
|
2160
|
+
std::cout << "[DEBUG] Execute - stage " << stageIdx << " in-place processing, buffer="
|
|
2161
|
+
<< currentBuffer << ", size=" << currentSize << std::endl;
|
|
2162
|
+
}
|
|
2019
2163
|
stage->process(currentBuffer, currentSize, m_channels, m_timestamps);
|
|
2020
2164
|
|
|
2021
2165
|
if (debugStageDumps)
|
|
2022
2166
|
{
|
|
2023
2167
|
const char *stype = stage->getType();
|
|
2024
2168
|
size_t toShow = std::min<size_t>(8, currentSize);
|
|
2025
|
-
|
|
2169
|
+
if (isDebugEnabled())
|
|
2170
|
+
{
|
|
2171
|
+
std::cout << "[DUMP] after '" << stype << "':";
|
|
2172
|
+
}
|
|
2026
2173
|
for (size_t i = 0; i < toShow; ++i)
|
|
2027
2174
|
{
|
|
2028
2175
|
std::cout << (i == 0 ? ' ' : ',') << currentBuffer[i];
|
|
@@ -2036,21 +2183,30 @@ namespace dsp
|
|
|
2036
2183
|
m_finalSize = currentSize;
|
|
2037
2184
|
m_ownsBuffer = usingTempBuffer;
|
|
2038
2185
|
|
|
2039
|
-
|
|
2040
|
-
|
|
2186
|
+
if (isDebugEnabled())
|
|
2187
|
+
{
|
|
2188
|
+
std::cout << "[DEBUG] Execute - COMPLETE, finalBuffer=" << m_finalBuffer
|
|
2189
|
+
<< ", finalSize=" << m_finalSize << ", ownsBuffer=" << m_ownsBuffer << std::endl;
|
|
2190
|
+
}
|
|
2041
2191
|
}
|
|
2042
2192
|
catch (const std::exception &e)
|
|
2043
2193
|
{
|
|
2044
|
-
|
|
2045
|
-
|
|
2194
|
+
if (isDebugEnabled())
|
|
2195
|
+
{
|
|
2196
|
+
std::cout << "[DEBUG] Execute - EXCEPTION: " << e.what() << ", this=" << this << std::endl;
|
|
2197
|
+
std::cout << "[WORKER-" << std::this_thread::get_id() << "] EXCEPTION: " << e.what() << std::endl;
|
|
2198
|
+
}
|
|
2046
2199
|
SetError(e.what());
|
|
2047
2200
|
}
|
|
2048
2201
|
} // This runs on the main thread after Execute() completes
|
|
2049
2202
|
|
|
2050
2203
|
void OnOK() override
|
|
2051
2204
|
{
|
|
2052
|
-
|
|
2053
|
-
|
|
2205
|
+
if (isDebugEnabled())
|
|
2206
|
+
{
|
|
2207
|
+
std::cout << "[DEBUG] ProcessWorker::OnOK - START, this=" << this
|
|
2208
|
+
<< ", finalBuffer=" << (void *)m_finalBuffer << ", finalSize=" << m_finalSize << std::endl;
|
|
2209
|
+
}
|
|
2054
2210
|
*m_busyLock = false; // unlock the pipeline
|
|
2055
2211
|
|
|
2056
2212
|
Napi::Env env = Env();
|
|
@@ -2064,22 +2220,34 @@ namespace dsp
|
|
|
2064
2220
|
// Clean up temporary buffer if we allocated one
|
|
2065
2221
|
if (m_ownsBuffer)
|
|
2066
2222
|
{
|
|
2067
|
-
|
|
2223
|
+
if (isDebugEnabled())
|
|
2224
|
+
{
|
|
2225
|
+
std::cout << "[DEBUG] OnOK - deleting owned temp buffer=" << (void *)m_finalBuffer << std::endl;
|
|
2226
|
+
}
|
|
2068
2227
|
delete[] m_finalBuffer;
|
|
2069
2228
|
}
|
|
2070
2229
|
|
|
2071
|
-
|
|
2230
|
+
if (isDebugEnabled())
|
|
2231
|
+
{
|
|
2232
|
+
std::cout << "[DEBUG] ProcessWorker::OnOK - resolving promise, this=" << this << std::endl;
|
|
2233
|
+
}
|
|
2072
2234
|
// Resolve the promise with the processed buffer
|
|
2073
2235
|
m_deferred.Resolve(outputArray);
|
|
2074
2236
|
}
|
|
2075
2237
|
|
|
2076
2238
|
void OnError(const Napi::Error &error) override
|
|
2077
2239
|
{
|
|
2078
|
-
|
|
2079
|
-
|
|
2240
|
+
if (isDebugEnabled())
|
|
2241
|
+
{
|
|
2242
|
+
std::cout << "[DEBUG] ProcessWorker::OnError - START, this=" << this
|
|
2243
|
+
<< ", error=" << error.Message() << std::endl;
|
|
2244
|
+
}
|
|
2080
2245
|
m_deferred.Reject(error.Value());
|
|
2081
2246
|
*m_busyLock = false; // unlock the pipeline
|
|
2082
|
-
|
|
2247
|
+
if (isDebugEnabled())
|
|
2248
|
+
{
|
|
2249
|
+
std::cout << "[DEBUG] ProcessWorker::OnError - promise rejected, this=" << this << std::endl;
|
|
2250
|
+
}
|
|
2083
2251
|
}
|
|
2084
2252
|
|
|
2085
2253
|
private:
|
|
@@ -2117,19 +2285,28 @@ namespace dsp
|
|
|
2117
2285
|
Napi::Value DspPipeline::ProcessAsync(const Napi::CallbackInfo &info)
|
|
2118
2286
|
{
|
|
2119
2287
|
Napi::Env env = info.Env();
|
|
2120
|
-
|
|
2288
|
+
if (isDebugEnabled())
|
|
2289
|
+
{
|
|
2290
|
+
std::cout << "[DEBUG] DspPipeline::ProcessAsync - this=" << this << std::endl;
|
|
2291
|
+
}
|
|
2121
2292
|
|
|
2122
2293
|
// Check if pipeline is disposed
|
|
2123
2294
|
if (m_disposed)
|
|
2124
2295
|
{
|
|
2125
|
-
|
|
2296
|
+
if (isDebugEnabled())
|
|
2297
|
+
{
|
|
2298
|
+
std::cout << "[DEBUG] ProcessAsync - pipeline disposed, this=" << this << std::endl;
|
|
2299
|
+
}
|
|
2126
2300
|
Napi::Error::New(env, "Pipeline is disposed").ThrowAsJavaScriptException();
|
|
2127
2301
|
return env.Undefined();
|
|
2128
2302
|
}
|
|
2129
2303
|
|
|
2130
2304
|
if (*m_isBusy)
|
|
2131
2305
|
{
|
|
2132
|
-
|
|
2306
|
+
if (isDebugEnabled())
|
|
2307
|
+
{
|
|
2308
|
+
std::cout << "[DEBUG] ProcessAsync - pipeline busy, this=" << this << std::endl;
|
|
2309
|
+
}
|
|
2133
2310
|
Napi::Error::New(env, "Pipeline is busy: Cannot call process() while another operation is running.").ThrowAsJavaScriptException();
|
|
2134
2311
|
return env.Undefined();
|
|
2135
2312
|
}
|
|
@@ -2198,13 +2375,22 @@ namespace dsp
|
|
|
2198
2375
|
}
|
|
2199
2376
|
|
|
2200
2377
|
*m_isBusy = true; // lock the pipeline
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2378
|
+
|
|
2379
|
+
if (isDebugEnabled())
|
|
2380
|
+
{
|
|
2381
|
+
std::cout << "[DEBUG] ProcessAsync - creating worker, data=" << (void *)data
|
|
2382
|
+
<< ", numSamples=" << numSamples << ", channels=" << channels
|
|
2383
|
+
<< ", this=" << this << std::endl;
|
|
2384
|
+
}
|
|
2204
2385
|
|
|
2205
2386
|
ProcessWorker *worker = new ProcessWorker(env, std::move(deferred), m_stages, data, timestamps, sampleRate, numSamples, channels, std::move(bufferRef), std::move(timestampRef), m_isBusy);
|
|
2206
|
-
|
|
2207
|
-
|
|
2387
|
+
|
|
2388
|
+
if (isDebugEnabled())
|
|
2389
|
+
{
|
|
2390
|
+
std::cout << "[DEBUG] ProcessAsync - queuing worker=" << (void *)worker
|
|
2391
|
+
<< ", this=" << this << std::endl;
|
|
2392
|
+
}
|
|
2393
|
+
|
|
2208
2394
|
worker->Queue();
|
|
2209
2395
|
|
|
2210
2396
|
return promise;
|
|
@@ -2222,19 +2408,28 @@ namespace dsp
|
|
|
2222
2408
|
Napi::Value DspPipeline::ProcessSync(const Napi::CallbackInfo &info)
|
|
2223
2409
|
{
|
|
2224
2410
|
Napi::Env env = info.Env();
|
|
2225
|
-
|
|
2411
|
+
if (isDebugEnabled())
|
|
2412
|
+
{
|
|
2413
|
+
std::cout << "[DEBUG] DspPipeline::ProcessSync - this=" << this << std::endl;
|
|
2414
|
+
}
|
|
2226
2415
|
|
|
2227
2416
|
// Check if pipeline is disposed
|
|
2228
2417
|
if (m_disposed)
|
|
2229
2418
|
{
|
|
2230
|
-
|
|
2419
|
+
if (isDebugEnabled())
|
|
2420
|
+
{
|
|
2421
|
+
std::cout << "[DEBUG] ProcessSync - pipeline disposed, this=" << this << std::endl;
|
|
2422
|
+
}
|
|
2231
2423
|
Napi::Error::New(env, "Pipeline is disposed").ThrowAsJavaScriptException();
|
|
2232
2424
|
return env.Undefined();
|
|
2233
2425
|
}
|
|
2234
2426
|
|
|
2235
2427
|
if (*m_isBusy)
|
|
2236
2428
|
{
|
|
2237
|
-
|
|
2429
|
+
if (isDebugEnabled())
|
|
2430
|
+
{
|
|
2431
|
+
std::cout << "[DEBUG] ProcessSync - pipeline busy, this=" << this << std::endl;
|
|
2432
|
+
}
|
|
2238
2433
|
Napi::Error::New(env, "Pipeline is busy: Cannot call processSync() while an async operation is running.").ThrowAsJavaScriptException();
|
|
2239
2434
|
return env.Undefined();
|
|
2240
2435
|
}
|
|
@@ -2361,13 +2556,19 @@ namespace dsp
|
|
|
2361
2556
|
Napi::Value DspPipeline::SaveState(const Napi::CallbackInfo &info)
|
|
2362
2557
|
{
|
|
2363
2558
|
Napi::Env env = info.Env();
|
|
2364
|
-
|
|
2365
|
-
|
|
2559
|
+
if (isDebugEnabled())
|
|
2560
|
+
{
|
|
2561
|
+
std::cout << "[DEBUG] DspPipeline::SaveState - this=" << this
|
|
2562
|
+
<< ", stages=" << m_stages.size() << std::endl;
|
|
2563
|
+
}
|
|
2366
2564
|
|
|
2367
2565
|
// Check if pipeline is disposed
|
|
2368
2566
|
if (m_disposed)
|
|
2369
2567
|
{
|
|
2370
|
-
|
|
2568
|
+
if (isDebugEnabled())
|
|
2569
|
+
{
|
|
2570
|
+
std::cout << "[DEBUG] SaveState - pipeline disposed, this=" << this << std::endl;
|
|
2571
|
+
}
|
|
2371
2572
|
Napi::Error::New(env, "Pipeline is disposed").ThrowAsJavaScriptException();
|
|
2372
2573
|
return env.Undefined();
|
|
2373
2574
|
}
|
|
@@ -2461,12 +2662,18 @@ namespace dsp
|
|
|
2461
2662
|
Napi::Value DspPipeline::LoadState(const Napi::CallbackInfo &info)
|
|
2462
2663
|
{
|
|
2463
2664
|
Napi::Env env = info.Env();
|
|
2464
|
-
|
|
2465
|
-
|
|
2665
|
+
if (isDebugEnabled())
|
|
2666
|
+
{
|
|
2667
|
+
std::cout << "[DEBUG] DspPipeline::LoadState - this=" << this
|
|
2668
|
+
<< ", current stages=" << m_stages.size() << std::endl;
|
|
2669
|
+
}
|
|
2466
2670
|
// Check if pipeline is disposed
|
|
2467
2671
|
if (m_disposed)
|
|
2468
2672
|
{
|
|
2469
|
-
|
|
2673
|
+
if (isDebugEnabled())
|
|
2674
|
+
{
|
|
2675
|
+
std::cout << "[DEBUG] LoadState - pipeline disposed, this=" << this << std::endl;
|
|
2676
|
+
}
|
|
2470
2677
|
Napi::Error::New(env, "Pipeline is disposed").ThrowAsJavaScriptException();
|
|
2471
2678
|
return env.Undefined();
|
|
2472
2679
|
}
|
|
@@ -2710,13 +2917,19 @@ namespace dsp
|
|
|
2710
2917
|
Napi::Value DspPipeline::ClearState(const Napi::CallbackInfo &info)
|
|
2711
2918
|
{
|
|
2712
2919
|
Napi::Env env = info.Env();
|
|
2713
|
-
|
|
2714
|
-
|
|
2920
|
+
if (isDebugEnabled())
|
|
2921
|
+
{
|
|
2922
|
+
std::cout << "[DEBUG] DspPipeline::ClearState - this=" << this
|
|
2923
|
+
<< ", stages=" << m_stages.size() << std::endl;
|
|
2924
|
+
}
|
|
2715
2925
|
|
|
2716
2926
|
// Check if pipeline is disposed
|
|
2717
2927
|
if (m_disposed)
|
|
2718
2928
|
{
|
|
2719
|
-
|
|
2929
|
+
if (isDebugEnabled())
|
|
2930
|
+
{
|
|
2931
|
+
std::cout << "[DEBUG] ClearState - pipeline disposed, this=" << this << std::endl;
|
|
2932
|
+
}
|
|
2720
2933
|
Napi::Error::New(env, "Pipeline is disposed").ThrowAsJavaScriptException();
|
|
2721
2934
|
return env.Undefined();
|
|
2722
2935
|
}
|
|
@@ -2724,13 +2937,20 @@ namespace dsp
|
|
|
2724
2937
|
// Reset all stages
|
|
2725
2938
|
for (size_t i = 0; i < m_stages.size(); ++i)
|
|
2726
2939
|
{
|
|
2727
|
-
|
|
2728
|
-
|
|
2940
|
+
if (isDebugEnabled())
|
|
2941
|
+
{
|
|
2942
|
+
std::cout << "[DEBUG] ClearState - resetting stage " << i
|
|
2943
|
+
<< ", type=" << m_stages[i]->getType()
|
|
2944
|
+
<< ", addr=" << m_stages[i].get() << std::endl;
|
|
2945
|
+
}
|
|
2729
2946
|
m_stages[i]->reset();
|
|
2730
2947
|
}
|
|
2731
2948
|
|
|
2732
|
-
|
|
2733
|
-
|
|
2949
|
+
if (isDebugEnabled())
|
|
2950
|
+
{
|
|
2951
|
+
std::cout << "[DEBUG] Pipeline state cleared (" << m_stages.size()
|
|
2952
|
+
<< " stages reset), this=" << this << std::endl;
|
|
2953
|
+
}
|
|
2734
2954
|
|
|
2735
2955
|
return env.Undefined();
|
|
2736
2956
|
}
|
|
@@ -2826,27 +3046,40 @@ namespace dsp
|
|
|
2826
3046
|
Napi::Value DspPipeline::Dispose(const Napi::CallbackInfo &info)
|
|
2827
3047
|
{
|
|
2828
3048
|
Napi::Env env = info.Env();
|
|
2829
|
-
|
|
2830
|
-
|
|
3049
|
+
|
|
3050
|
+
if (isDebugEnabled())
|
|
3051
|
+
{
|
|
3052
|
+
std::cout << "[DEBUG] DspPipeline::Dispose - this=" << this
|
|
3053
|
+
<< ", stages=" << m_stages.size() << ", disposed=" << m_disposed << std::endl;
|
|
3054
|
+
}
|
|
2831
3055
|
|
|
2832
3056
|
// Already disposed - silently succeed (idempotent behavior)
|
|
2833
3057
|
if (m_disposed)
|
|
2834
3058
|
{
|
|
2835
|
-
|
|
3059
|
+
if (isDebugEnabled())
|
|
3060
|
+
{
|
|
3061
|
+
std::cout << "[DEBUG] Dispose - already disposed, this=" << this << std::endl;
|
|
3062
|
+
}
|
|
2836
3063
|
return env.Undefined();
|
|
2837
3064
|
}
|
|
2838
3065
|
|
|
2839
3066
|
// Cannot dispose while processing is in progress
|
|
2840
3067
|
if (*m_isBusy)
|
|
2841
3068
|
{
|
|
2842
|
-
|
|
3069
|
+
if (isDebugEnabled())
|
|
3070
|
+
{
|
|
3071
|
+
std::cout << "[DEBUG] Dispose - pipeline busy, cannot dispose, this=" << this << std::endl;
|
|
3072
|
+
}
|
|
2843
3073
|
Napi::Error::New(env, "Cannot dispose pipeline: process() is still running.")
|
|
2844
3074
|
.ThrowAsJavaScriptException();
|
|
2845
3075
|
return env.Undefined();
|
|
2846
3076
|
}
|
|
2847
3077
|
|
|
2848
|
-
|
|
2849
|
-
|
|
3078
|
+
if (isDebugEnabled())
|
|
3079
|
+
{
|
|
3080
|
+
std::cout << "[DEBUG] Dispose - clearing " << m_stages.size()
|
|
3081
|
+
<< " stages, this=" << this << std::endl;
|
|
3082
|
+
}
|
|
2850
3083
|
// Clear all stages - triggers RAII cleanup of all stage resources
|
|
2851
3084
|
// This will:
|
|
2852
3085
|
// - Free all stage internal buffers
|
|
@@ -2855,14 +3088,20 @@ namespace dsp
|
|
|
2855
3088
|
// - Free all detachable buffers
|
|
2856
3089
|
// - Free timestamp and resize buffers
|
|
2857
3090
|
m_stages.clear();
|
|
2858
|
-
|
|
3091
|
+
if (isDebugEnabled())
|
|
3092
|
+
{
|
|
3093
|
+
std::cout << "[DEBUG] Dispose - stages cleared, this=" << this << std::endl;
|
|
3094
|
+
}
|
|
2859
3095
|
|
|
2860
3096
|
// Reset busy flag (defensive programming)
|
|
2861
3097
|
*m_isBusy = false;
|
|
2862
3098
|
|
|
2863
3099
|
// Mark as disposed to prevent further operations
|
|
2864
3100
|
m_disposed = true;
|
|
2865
|
-
|
|
3101
|
+
if (isDebugEnabled())
|
|
3102
|
+
{
|
|
3103
|
+
std::cout << "[DEBUG] Dispose - complete, this=" << this << std::endl;
|
|
3104
|
+
}
|
|
2866
3105
|
|
|
2867
3106
|
return env.Undefined();
|
|
2868
3107
|
}
|