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.
@@ -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
- // std::cout << "[DEBUG] DspPipeline::Constructor - this=" << this
112
- // << ", creating pipeline" << std::endl;
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
- // std::cout << "[DEBUG] DspPipeline::Constructor - m_isBusy=" << m_isBusy.get() << std::endl;
128
+ if (isDebugEnabled())
129
+ {
130
+ std::cout << "[DEBUG] DspPipeline::Constructor - m_isBusy=" << m_isBusy.get() << std::endl;
131
+ }
116
132
  InitializeStageFactories();
117
- // std::cout << "[DEBUG] DspPipeline::Constructor - complete, this=" << this << std::endl;
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 &params)
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
- // std::cout << "[DEBUG] DspPipeline::AddStage - this=" << this << std::endl;
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
- // std::cout << "[DEBUG] AddStage - pipeline disposed, this=" << this << std::endl;
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
- // std::cout << "[DEBUG] AddStage - pipeline busy, this=" << this << std::endl;
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
- // std::cout << "[DEBUG] AddStage - stageName=" << stageName << ", this=" << this << std::endl;
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
- // std::cout << "[DEBUG] DspPipeline::AddFilterStage - this=" << this << std::endl;
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
- // std::cout << "[DEBUG] AddFilterStage - pipeline disposed, this=" << this << std::endl;
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
- // std::cout << "[DEBUG] ProcessWorker::ProcessWorker - this=" << this << std::endl;
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
- // std::cout << "[DEBUG] ProcessWorker::Execute - START, this=" << this
1892
- // << ", data=" << m_data << ", numSamples=" << m_numSamples
1893
- // << ", channels=" << m_channels << std::endl;
1894
- // std::cout << "[WORKER-" << std::this_thread::get_id() << "] Execute START (stages="
1895
- // << m_stages.size() << ")" << std::endl;
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
- // std::cout << "[DEBUG] Execute - generating timestamps, sampleRate=" << m_sampleRate << std::endl;
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
- // std::cout << "[DEBUG] Execute - timestamps generated, addr=" << m_timestamps << std::endl;
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
- // std::cout << "[DEBUG] Execute - processing through " << m_stages.size() << " stages" << std::endl;
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
- // std::cout << "[DEBUG] Execute - stage " << stageIdx << ", type="
1934
- // << stage->getType() << ", addr=" << stage.get()
1935
- // << ", isResizing=" << stage->isResizing() << std::endl;
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 outputSize = stage->calculateOutputSize(currentSize);
1941
- float *outputBuffer = new float[outputSize];
2045
+ // Calculate output size estimate
2046
+ size_t estimatedSize = stage->calculateOutputSize(currentSize);
1942
2047
 
1943
- // std::cout << "[DEBUG] Execute - allocated output buffer, size=" << outputSize
1944
- // << ", addr=" << outputBuffer << std::endl;
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
- // std::cout << "[DEBUG] Execute - stage " << stageIdx << " resized: "
1955
- // << prevSize << " -> " << actualOutputSize // Use prevSize!
1956
- // << ", buffer=" << outputBuffer << std::endl;
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
- // std::cout << "[DEBUG] Execute - freeing previous temp buffer=" << tempBuffer << std::endl;
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
- // std::cout << "[DEBUG] Execute - channels changed: " << m_channels
1979
- // << " -> " << outputChannels << std::endl;
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
- // std::cout << "[DEBUG] Execute - reinterpolating timestamps" << std::endl;
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
- // std::cout << "[DEBUG] Execute - timestamps reinterpolated (SIMD), new addr="
2012
- // << m_timestamps << std::endl;
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
- // std::cout << "[DEBUG] Execute - stage " << stageIdx << " in-place processing" << std::endl;
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
- // std::cout << "[DUMP] after '" << stype << "':";
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
- // std::cout << "[DEBUG] Execute - COMPLETE, finalBuffer=" << m_finalBuffer
2040
- // << ", finalSize=" << m_finalSize << ", ownsBuffer=" << m_ownsBuffer << std::endl;
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
- // std::cout << "[DEBUG] Execute - EXCEPTION: " << e.what() << ", this=" << this << std::endl;
2045
- // std::cout << "[WORKER-" << std::this_thread::get_id() << "] EXCEPTION: " << e.what() << std::endl;
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
- // std::cout << "[DEBUG] ProcessWorker::OnOK - START, this=" << this
2053
- // << ", finalBuffer=" << (void *)m_finalBuffer << ", finalSize=" << m_finalSize << std::endl;
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
- // std::cout << "[DEBUG] OnOK - deleting temp buffer=" << (void *)m_finalBuffer << std::endl;
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
- // std::cout << "[DEBUG] OnOK - COMPLETE, resolving promise, this=" << this << std::endl;
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
- // std::cout << "[DEBUG] ProcessWorker::OnError - this=" << this
2079
- // << ", error=" << error.Message() << std::endl;
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
- // std::cout << "[DEBUG] OnError - COMPLETE, this=" << this << std::endl;
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
- // std::cout << "[DEBUG] DspPipeline::ProcessAsync - this=" << this << std::endl;
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
- // std::cout << "[DEBUG] ProcessAsync - pipeline disposed, this=" << this << std::endl;
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
- // std::cout << "[DEBUG] ProcessAsync - pipeline busy, this=" << this << std::endl;
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
- // std::cout << "[DEBUG] ProcessAsync - creating worker, data=" << (void *)data
2202
- // << ", numSamples=" << numSamples << ", channels=" << channels
2203
- // << ", this=" << this << std::endl;
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
- // std::cout << "[DEBUG] ProcessAsync - queuing worker=" << (void *)worker
2207
- // << ", this=" << this << std::endl;
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
- // std::cout << "[DEBUG] DspPipeline::ProcessSync - this=" << this << std::endl;
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
- // std::cout << "[DEBUG] ProcessSync - pipeline disposed, this=" << this << std::endl;
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
- // std::cout << "[DEBUG] ProcessSync - pipeline busy, this=" << this << std::endl;
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
- // std::cout << "[DEBUG] DspPipeline::SaveState - this=" << this
2365
- // << ", stages=" << m_stages.size() << std::endl;
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
- // std::cout << "[DEBUG] SaveState - pipeline disposed, this=" << this << std::endl;
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
- // std::cout << "[DEBUG] DspPipeline::LoadState - this=" << this
2465
- // << ", current stages=" << m_stages.size() << std::endl;
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
- // std::cout << "[DEBUG] LoadState - pipeline disposed, this=" << this << std::endl;
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
- // std::cout << "[DEBUG] DspPipeline::ClearState - this=" << this
2714
- // << ", stages=" << m_stages.size() << std::endl;
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
- // std::cout << "[DEBUG] ClearState - pipeline disposed, this=" << this << std::endl;
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
- // std::cout << "[DEBUG] ClearState - resetting stage " << i
2728
- // << ", addr=" << m_stages[i].get() << std::endl;
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
- // std::cout << "[DEBUG] Pipeline state cleared (" << m_stages.size()
2733
- // << " stages reset), this=" << this << std::endl;
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
- // std::cout << "[DEBUG] DspPipeline::Dispose - this=" << this
2830
- // << ", stages=" << m_stages.size() << ", disposed=" << m_disposed << std::endl;
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
- // std::cout << "[DEBUG] Dispose - already disposed, this=" << this << std::endl;
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
- // std::cout << "[DEBUG] Dispose - pipeline busy, cannot dispose, this=" << this << std::endl;
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
- // std::cout << "[DEBUG] Dispose - clearing " << m_stages.size()
2849
- // << " stages, this=" << this << std::endl;
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
- // std::cout << "[DEBUG] Dispose - stages cleared, this=" << this << std::endl;
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
- // std::cout << "[DEBUG] Dispose - complete, this=" << this << std::endl;
3101
+ if (isDebugEnabled())
3102
+ {
3103
+ std::cout << "[DEBUG] Dispose - complete, this=" << this << std::endl;
3104
+ }
2866
3105
 
2867
3106
  return env.Undefined();
2868
3107
  }