dspx 1.2.4 → 1.3.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 +40 -78
- package/binding.gyp +10 -0
- package/dist/FilterBankDesign.d.ts +233 -0
- package/dist/FilterBankDesign.d.ts.map +1 -0
- package/dist/FilterBankDesign.js +247 -0
- package/dist/FilterBankDesign.js.map +1 -0
- package/dist/advanced-dsp.d.ts +6 -6
- package/dist/advanced-dsp.d.ts.map +1 -1
- package/dist/advanced-dsp.js +35 -12
- package/dist/advanced-dsp.js.map +1 -1
- package/dist/backends.d.ts +0 -103
- package/dist/backends.d.ts.map +1 -1
- package/dist/backends.js +0 -217
- package/dist/backends.js.map +1 -1
- package/dist/bindings.d.ts +216 -17
- package/dist/bindings.d.ts.map +1 -1
- package/dist/bindings.js +503 -43
- package/dist/bindings.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +67 -8
- package/dist/types.d.ts.map +1 -1
- package/dist/utils.d.ts +38 -8
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +84 -26
- package/dist/utils.js.map +1 -1
- package/package.json +1 -2
- package/prebuilds/win32-x64/dspx.node +0 -0
- package/scripts/add-dispose-to-tests.js +145 -0
- package/src/native/DspPipeline.cc +668 -118
- package/src/native/DspPipeline.h +13 -0
- package/src/native/FilterBankDesignBindings.cc +241 -0
- package/src/native/IDspStage.h +24 -0
- package/src/native/UtilityBindings.cc +130 -0
- package/src/native/adapters/ClipDetectionStage.h +15 -4
- package/src/native/adapters/ConvolutionStage.h +101 -0
- package/src/native/adapters/CumulativeMovingAverageStage.h +264 -0
- package/src/native/adapters/DecimatorStage.h +80 -0
- package/src/native/adapters/DifferentiatorStage.h +13 -0
- package/src/native/adapters/ExponentialMovingAverageStage.h +290 -0
- package/src/native/adapters/FilterBankStage.cc +336 -0
- package/src/native/adapters/FilterBankStage.h +170 -0
- package/src/native/adapters/FilterStage.cc +122 -0
- package/src/native/adapters/FilterStage.h +4 -0
- package/src/native/adapters/HilbertEnvelopeStage.h +55 -0
- package/src/native/adapters/IntegratorStage.h +15 -0
- package/src/native/adapters/InterpolatorStage.h +51 -0
- package/src/native/adapters/LinearRegressionStage.h +40 -0
- package/src/native/adapters/LmsStage.h +63 -0
- package/src/native/adapters/MeanAbsoluteValueStage.h +76 -0
- package/src/native/adapters/MovingAverageStage.h +119 -0
- package/src/native/adapters/PeakDetectionStage.h +53 -0
- package/src/native/adapters/RectifyStage.h +14 -0
- package/src/native/adapters/ResamplerStage.h +67 -0
- package/src/native/adapters/RlsStage.h +76 -0
- package/src/native/adapters/RmsStage.h +72 -0
- package/src/native/adapters/SnrStage.h +45 -0
- package/src/native/adapters/SscStage.h +65 -0
- package/src/native/adapters/StftStage.h +62 -0
- package/src/native/adapters/VarianceStage.h +59 -0
- package/src/native/adapters/WampStage.h +59 -0
- package/src/native/adapters/WaveformLengthStage.h +51 -0
- package/src/native/adapters/ZScoreNormalizeStage.h +64 -0
- package/src/native/core/CumulativeMovingAverageFilter.h +123 -0
- package/src/native/core/ExponentialMovingAverageFilter.h +129 -0
- package/src/native/core/FilterBankDesign.h +266 -0
- package/src/native/core/Policies.h +124 -0
- package/src/native/utils/CircularBufferArray.cc +2 -1
- package/src/native/utils/Toon.h +195 -0
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
#include "../core/FftEngine.h"
|
|
32
32
|
#include "../utils/CircularBufferArray.h"
|
|
33
33
|
#include "../utils/SimdOps.h"
|
|
34
|
+
#include "../utils/Toon.h"
|
|
34
35
|
#include <vector>
|
|
35
36
|
#include <complex>
|
|
36
37
|
#include <memory>
|
|
@@ -199,6 +200,60 @@ namespace dsp::adapters
|
|
|
199
200
|
}
|
|
200
201
|
}
|
|
201
202
|
|
|
203
|
+
inline void serializeToon(dsp::toon::Serializer &s) const override
|
|
204
|
+
{
|
|
205
|
+
// Write configuration
|
|
206
|
+
s.writeInt32(static_cast<int32_t>(m_window_size));
|
|
207
|
+
s.writeInt32(static_cast<int32_t>(m_hop_size));
|
|
208
|
+
s.writeInt32(static_cast<int32_t>(m_channel_buffers.size()));
|
|
209
|
+
|
|
210
|
+
// Write per-channel state
|
|
211
|
+
for (size_t i = 0; i < m_channel_buffers.size(); ++i)
|
|
212
|
+
{
|
|
213
|
+
std::vector<float> buffer_data = m_channel_buffers[i].toVector();
|
|
214
|
+
s.writeFloatArray(buffer_data);
|
|
215
|
+
s.writeInt32(static_cast<int32_t>(m_samples_since_output[i]));
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
inline void deserializeToon(dsp::toon::Deserializer &d) override
|
|
220
|
+
{
|
|
221
|
+
// Read configuration
|
|
222
|
+
int32_t window_size = d.readInt32();
|
|
223
|
+
int32_t hop_size = d.readInt32();
|
|
224
|
+
|
|
225
|
+
if (window_size <= 0 || hop_size <= 0)
|
|
226
|
+
throw std::runtime_error("Invalid window/hop size in HilbertEnvelopeStage deserialization");
|
|
227
|
+
|
|
228
|
+
if (static_cast<size_t>(window_size) != m_window_size || static_cast<size_t>(hop_size) != m_hop_size)
|
|
229
|
+
throw std::runtime_error("Window/hop size mismatch in HilbertEnvelopeStage deserialization");
|
|
230
|
+
|
|
231
|
+
int32_t num_channels = d.readInt32();
|
|
232
|
+
if (num_channels < 0)
|
|
233
|
+
throw std::runtime_error("Invalid num_channels in HilbertEnvelopeStage deserialization");
|
|
234
|
+
|
|
235
|
+
// Recreate channel buffers
|
|
236
|
+
m_channel_buffers.clear();
|
|
237
|
+
m_samples_since_output.clear();
|
|
238
|
+
|
|
239
|
+
for (int32_t i = 0; i < num_channels; ++i)
|
|
240
|
+
{
|
|
241
|
+
m_channel_buffers.emplace_back(m_window_size);
|
|
242
|
+
m_samples_since_output.push_back(0);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Restore per-channel state
|
|
246
|
+
for (int32_t i = 0; i < num_channels; ++i)
|
|
247
|
+
{
|
|
248
|
+
std::vector<float> buffer_data = d.readFloatArray();
|
|
249
|
+
for (float value : buffer_data)
|
|
250
|
+
{
|
|
251
|
+
m_channel_buffers[i].push(value);
|
|
252
|
+
}
|
|
253
|
+
m_samples_since_output[i] = static_cast<size_t>(d.readInt32());
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
202
257
|
void reset() override
|
|
203
258
|
{
|
|
204
259
|
for (auto &buffer : m_channel_buffers)
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
#define INTEGRATOR_STAGE_H
|
|
3
3
|
|
|
4
4
|
#include "../IDspStage.h"
|
|
5
|
+
#include "../utils/Toon.h"
|
|
5
6
|
#include <vector>
|
|
6
7
|
#include <cmath>
|
|
7
8
|
#include <stdexcept>
|
|
@@ -129,6 +130,20 @@ namespace dsp::adapters
|
|
|
129
130
|
std::fill(m_prev_output.begin(), m_prev_output.end(), 0.0f);
|
|
130
131
|
}
|
|
131
132
|
|
|
133
|
+
void serializeToon(dsp::toon::Serializer &s) const override
|
|
134
|
+
{
|
|
135
|
+
s.writeFloat(m_alpha);
|
|
136
|
+
s.writeInt32(m_num_channels);
|
|
137
|
+
s.writeFloatArray(m_prev_output);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
void deserializeToon(dsp::toon::Deserializer &d) override
|
|
141
|
+
{
|
|
142
|
+
m_alpha = d.readFloat();
|
|
143
|
+
m_num_channels = d.readInt32();
|
|
144
|
+
m_prev_output = d.readFloatArray();
|
|
145
|
+
}
|
|
146
|
+
|
|
132
147
|
bool isResizing() const override
|
|
133
148
|
{
|
|
134
149
|
return false;
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
#pragma once
|
|
9
9
|
|
|
10
10
|
#include "../IDspStage.h"
|
|
11
|
+
#include "../utils/Toon.h"
|
|
11
12
|
#include <vector>
|
|
12
13
|
#include <cmath>
|
|
13
14
|
#include <stdexcept>
|
|
@@ -154,6 +155,56 @@ namespace dsp
|
|
|
154
155
|
}
|
|
155
156
|
}
|
|
156
157
|
|
|
158
|
+
void serializeToon(dsp::toon::Serializer &s) const override
|
|
159
|
+
{
|
|
160
|
+
s.writeInt32(interpolationFactor_);
|
|
161
|
+
s.writeInt32(filterOrder_);
|
|
162
|
+
s.writeDouble(sampleRate_);
|
|
163
|
+
s.writeInt32(numChannels_);
|
|
164
|
+
|
|
165
|
+
// Serialize state buffers for each channel
|
|
166
|
+
for (const auto &buf : stateBuffers_)
|
|
167
|
+
{
|
|
168
|
+
s.writeFloatArray(buf);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Serialize state indices
|
|
172
|
+
for (size_t idx : stateIndices_)
|
|
173
|
+
{
|
|
174
|
+
s.writeInt32(static_cast<int32_t>(idx));
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
void deserializeToon(dsp::toon::Deserializer &d) override
|
|
179
|
+
{
|
|
180
|
+
int32_t factor = d.readInt32();
|
|
181
|
+
int32_t order = d.readInt32();
|
|
182
|
+
double sr = d.readDouble();
|
|
183
|
+
int32_t nCh = d.readInt32();
|
|
184
|
+
|
|
185
|
+
if (factor != interpolationFactor_ || order != filterOrder_)
|
|
186
|
+
{
|
|
187
|
+
throw std::runtime_error("Interpolator TOON: parameter mismatch");
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (nCh != numChannels_)
|
|
191
|
+
{
|
|
192
|
+
initializeStateBuffers(nCh);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Deserialize state buffers
|
|
196
|
+
for (auto &buf : stateBuffers_)
|
|
197
|
+
{
|
|
198
|
+
buf = d.readFloatArray();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Deserialize state indices
|
|
202
|
+
for (size_t &idx : stateIndices_)
|
|
203
|
+
{
|
|
204
|
+
idx = static_cast<size_t>(d.readInt32());
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
157
208
|
private:
|
|
158
209
|
int interpolationFactor_;
|
|
159
210
|
int filterOrder_;
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
#include "../IDspStage.h"
|
|
5
5
|
#include "../utils/SimdOps.h"
|
|
6
|
+
#include "../utils/Toon.h"
|
|
6
7
|
#include <vector>
|
|
7
8
|
#include <cmath>
|
|
8
9
|
#include <stdexcept>
|
|
@@ -321,6 +322,45 @@ namespace dsp
|
|
|
321
322
|
}
|
|
322
323
|
}
|
|
323
324
|
|
|
325
|
+
inline void serializeToon(dsp::toon::Serializer &s) const override
|
|
326
|
+
{
|
|
327
|
+
// Write configuration
|
|
328
|
+
s.writeInt32(static_cast<int32_t>(m_windowSize));
|
|
329
|
+
s.writeInt32(static_cast<int32_t>(m_numChannels));
|
|
330
|
+
|
|
331
|
+
// Write per-channel state
|
|
332
|
+
for (size_t ch = 0; ch < m_numChannels; ++ch)
|
|
333
|
+
{
|
|
334
|
+
s.writeFloatArray(m_buffers[ch]);
|
|
335
|
+
s.writeInt32(static_cast<int32_t>(m_writeIndices[ch]));
|
|
336
|
+
s.writeInt32(static_cast<int32_t>(m_sampleCounts[ch]));
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
inline void deserializeToon(dsp::toon::Deserializer &d) override
|
|
341
|
+
{
|
|
342
|
+
// Read configuration
|
|
343
|
+
int32_t windowSize = d.readInt32();
|
|
344
|
+
if (windowSize < 2)
|
|
345
|
+
throw std::runtime_error("Invalid windowSize in LinearRegressionStage deserialization");
|
|
346
|
+
if (static_cast<size_t>(windowSize) != m_windowSize)
|
|
347
|
+
throw std::runtime_error("Window size mismatch in LinearRegressionStage deserialization");
|
|
348
|
+
|
|
349
|
+
int32_t numChannels = d.readInt32();
|
|
350
|
+
if (numChannels < 0)
|
|
351
|
+
throw std::runtime_error("Invalid numChannels in LinearRegressionStage deserialization");
|
|
352
|
+
|
|
353
|
+
init(static_cast<size_t>(numChannels));
|
|
354
|
+
|
|
355
|
+
// Read per-channel state
|
|
356
|
+
for (size_t ch = 0; ch < m_numChannels; ++ch)
|
|
357
|
+
{
|
|
358
|
+
m_buffers[ch] = d.readFloatArray();
|
|
359
|
+
m_writeIndices[ch] = static_cast<size_t>(d.readInt32());
|
|
360
|
+
m_sampleCounts[ch] = static_cast<size_t>(d.readInt32());
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
324
364
|
void reset() override
|
|
325
365
|
{
|
|
326
366
|
for (size_t ch = 0; ch < m_numChannels; ++ch)
|
|
@@ -176,6 +176,69 @@ namespace dsp
|
|
|
176
176
|
}
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
+
void serializeToon(dsp::toon::Serializer &s) const override
|
|
180
|
+
{
|
|
181
|
+
s.startObject();
|
|
182
|
+
|
|
183
|
+
s.writeString("numTaps");
|
|
184
|
+
s.writeInt32(static_cast<int32_t>(m_numTaps));
|
|
185
|
+
|
|
186
|
+
s.writeString("learningRate");
|
|
187
|
+
s.writeFloat(m_learningRate);
|
|
188
|
+
|
|
189
|
+
s.writeString("normalized");
|
|
190
|
+
s.writeBool(m_normalized);
|
|
191
|
+
|
|
192
|
+
s.writeString("lambda");
|
|
193
|
+
s.writeFloat(m_lambda);
|
|
194
|
+
|
|
195
|
+
s.writeString("initialized");
|
|
196
|
+
s.writeBool(m_initialized);
|
|
197
|
+
|
|
198
|
+
if (m_initialized)
|
|
199
|
+
{
|
|
200
|
+
auto weights = m_filter->getWeights(0);
|
|
201
|
+
s.writeString("weights");
|
|
202
|
+
s.writeFloatArray(weights);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
s.endObject();
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
void deserializeToon(dsp::toon::Deserializer &d) override
|
|
209
|
+
{
|
|
210
|
+
d.consumeToken(dsp::toon::T_OBJECT_START);
|
|
211
|
+
|
|
212
|
+
std::string key = d.readString(); // "numTaps"
|
|
213
|
+
m_numTaps = d.readInt32();
|
|
214
|
+
|
|
215
|
+
key = d.readString(); // "learningRate"
|
|
216
|
+
m_learningRate = d.readFloat();
|
|
217
|
+
|
|
218
|
+
key = d.readString(); // "normalized"
|
|
219
|
+
m_normalized = d.readBool();
|
|
220
|
+
|
|
221
|
+
key = d.readString(); // "lambda"
|
|
222
|
+
m_lambda = d.readFloat();
|
|
223
|
+
|
|
224
|
+
key = d.readString(); // "initialized"
|
|
225
|
+
m_initialized = d.readBool();
|
|
226
|
+
|
|
227
|
+
// Recreate filter with restored parameters
|
|
228
|
+
m_filter = std::make_unique<dsp::core::DifferentiableFilter<float>>(m_numTaps, m_learningRate, m_lambda, m_normalized);
|
|
229
|
+
|
|
230
|
+
if (m_initialized)
|
|
231
|
+
{
|
|
232
|
+
m_filter->init(1); // Reinitialize filter
|
|
233
|
+
|
|
234
|
+
key = d.readString(); // "weights"
|
|
235
|
+
std::vector<float> weights = d.readFloatArray();
|
|
236
|
+
m_filter->setWeights(0, weights);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
d.consumeToken(dsp::toon::T_OBJECT_END);
|
|
240
|
+
}
|
|
241
|
+
|
|
179
242
|
private:
|
|
180
243
|
void ensureScratchBuffers(size_t samplesPerChannel)
|
|
181
244
|
{
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
#include "../IDspStage.h"
|
|
4
4
|
#include "../core/MovingAbsoluteValueFilter.h" // Include the new core filter
|
|
5
|
+
#include "../utils/Toon.h"
|
|
5
6
|
#include <vector>
|
|
6
7
|
#include <stdexcept>
|
|
7
8
|
#include <cmath>
|
|
@@ -168,10 +169,85 @@ namespace dsp::adapters
|
|
|
168
169
|
}
|
|
169
170
|
}
|
|
170
171
|
|
|
172
|
+
inline void serializeToon(dsp::toon::Serializer &s) const override
|
|
173
|
+
{
|
|
174
|
+
// Write mode
|
|
175
|
+
s.writeInt32(static_cast<int32_t>(m_mode));
|
|
176
|
+
|
|
177
|
+
// Write configuration parameters
|
|
178
|
+
s.writeInt32(static_cast<int32_t>(m_window_size));
|
|
179
|
+
s.writeFloat(static_cast<float>(m_window_duration_ms));
|
|
180
|
+
s.writeBool(m_is_initialized);
|
|
181
|
+
|
|
182
|
+
// Write number of channels and filter states
|
|
183
|
+
s.writeInt32(static_cast<int32_t>(m_filters.size()));
|
|
184
|
+
|
|
185
|
+
// For Moving mode, serialize each filter's state
|
|
186
|
+
if (m_mode == MavMode::Moving)
|
|
187
|
+
{
|
|
188
|
+
for (const auto &filter : m_filters)
|
|
189
|
+
{
|
|
190
|
+
auto [bufferData, runningSum] = filter.getState();
|
|
191
|
+
s.writeFloatArray(bufferData);
|
|
192
|
+
s.writeFloat(runningSum);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
inline void deserializeToon(dsp::toon::Deserializer &d) override
|
|
198
|
+
{
|
|
199
|
+
// Read mode
|
|
200
|
+
int32_t mode_int = d.readInt32();
|
|
201
|
+
if (mode_int < 0 || mode_int > 1)
|
|
202
|
+
throw std::runtime_error("Invalid mode in MeanAbsoluteValueStage deserialization");
|
|
203
|
+
m_mode = static_cast<MavMode>(mode_int);
|
|
204
|
+
|
|
205
|
+
// Read configuration parameters
|
|
206
|
+
int32_t window_size = d.readInt32();
|
|
207
|
+
if (window_size < 0)
|
|
208
|
+
throw std::runtime_error("Invalid window_size in MeanAbsoluteValueStage deserialization");
|
|
209
|
+
m_window_size = static_cast<size_t>(window_size);
|
|
210
|
+
|
|
211
|
+
m_window_duration_ms = static_cast<double>(d.readFloat());
|
|
212
|
+
m_is_initialized = d.readBool();
|
|
213
|
+
|
|
214
|
+
// Read number of channels
|
|
215
|
+
int32_t num_channels = d.readInt32();
|
|
216
|
+
if (num_channels < 0)
|
|
217
|
+
throw std::runtime_error("Invalid num_channels in MeanAbsoluteValueStage deserialization");
|
|
218
|
+
|
|
219
|
+
// Reconstruct filters
|
|
220
|
+
m_filters.clear();
|
|
221
|
+
|
|
222
|
+
if (m_mode == MavMode::Moving)
|
|
223
|
+
{
|
|
224
|
+
for (int32_t i = 0; i < num_channels; ++i)
|
|
225
|
+
{
|
|
226
|
+
// Read buffer data
|
|
227
|
+
std::vector<float> bufferData = d.readFloatArray();
|
|
228
|
+
|
|
229
|
+
// Read running sum
|
|
230
|
+
float runningSum = d.readFloat();
|
|
231
|
+
|
|
232
|
+
// Create filter and restore state
|
|
233
|
+
if (m_window_duration_ms > 0.0)
|
|
234
|
+
{
|
|
235
|
+
m_filters.emplace_back(m_window_size, m_window_duration_ms);
|
|
236
|
+
}
|
|
237
|
+
else
|
|
238
|
+
{
|
|
239
|
+
m_filters.emplace_back(m_window_size);
|
|
240
|
+
}
|
|
241
|
+
m_filters.back().setState(bufferData, runningSum);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
171
246
|
// Reset all filters to initial state
|
|
172
247
|
void reset() override
|
|
173
248
|
{
|
|
174
249
|
for (auto &filter : m_filters)
|
|
250
|
+
|
|
175
251
|
{
|
|
176
252
|
filter.clear();
|
|
177
253
|
}
|
|
@@ -177,6 +177,125 @@ namespace dsp::adapters
|
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
+
// TOON Binary Serialization - CRITICAL OPTIMIZATION for large buffers
|
|
181
|
+
void serializeToon(dsp::toon::Serializer &serializer) const override
|
|
182
|
+
{
|
|
183
|
+
serializer.startObject();
|
|
184
|
+
|
|
185
|
+
// 1. Mode
|
|
186
|
+
serializer.writeString("mode");
|
|
187
|
+
serializer.writeString((m_mode == AverageMode::Moving) ? "moving" : "batch");
|
|
188
|
+
|
|
189
|
+
if (m_mode == AverageMode::Moving)
|
|
190
|
+
{
|
|
191
|
+
// 2. Config
|
|
192
|
+
serializer.writeString("windowSize");
|
|
193
|
+
serializer.writeInt32(static_cast<int32_t>(m_window_size));
|
|
194
|
+
|
|
195
|
+
serializer.writeString("windowDuration");
|
|
196
|
+
serializer.writeDouble(m_window_duration_ms);
|
|
197
|
+
|
|
198
|
+
serializer.writeString("initialized");
|
|
199
|
+
serializer.writeBool(m_is_initialized);
|
|
200
|
+
|
|
201
|
+
// 3. Channels - Zero-copy-like binary arrays
|
|
202
|
+
serializer.writeString("channels");
|
|
203
|
+
serializer.startArray();
|
|
204
|
+
|
|
205
|
+
for (const auto &filter : m_filters)
|
|
206
|
+
{
|
|
207
|
+
auto [bufferData, runningSum] = filter.getState();
|
|
208
|
+
|
|
209
|
+
serializer.startObject();
|
|
210
|
+
|
|
211
|
+
// CRITICAL: Direct binary copy of float buffer (not text!)
|
|
212
|
+
serializer.writeString("buffer");
|
|
213
|
+
serializer.writeFloatArray(bufferData);
|
|
214
|
+
|
|
215
|
+
serializer.writeString("sum");
|
|
216
|
+
serializer.writeFloat(runningSum);
|
|
217
|
+
|
|
218
|
+
serializer.endObject();
|
|
219
|
+
}
|
|
220
|
+
serializer.endArray();
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
serializer.endObject();
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// TOON Binary Deserialization - CRITICAL OPTIMIZATION for large buffers
|
|
227
|
+
void deserializeToon(dsp::toon::Deserializer &deserializer) override
|
|
228
|
+
{
|
|
229
|
+
deserializer.consumeToken(dsp::toon::T_OBJECT_START);
|
|
230
|
+
|
|
231
|
+
// 1. Mode
|
|
232
|
+
std::string key = deserializer.readString(); // "mode"
|
|
233
|
+
std::string modeStr = deserializer.readString();
|
|
234
|
+
|
|
235
|
+
AverageMode newMode = (modeStr == "moving") ? AverageMode::Moving : AverageMode::Batch;
|
|
236
|
+
if (newMode != m_mode)
|
|
237
|
+
{
|
|
238
|
+
throw std::runtime_error("MovingAverage mode mismatch during TOON deserialization");
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (modeStr == "moving")
|
|
242
|
+
{
|
|
243
|
+
// 2. Config
|
|
244
|
+
key = deserializer.readString(); // "windowSize"
|
|
245
|
+
int32_t windowSize = deserializer.readInt32();
|
|
246
|
+
|
|
247
|
+
key = deserializer.readString(); // "windowDuration"
|
|
248
|
+
double windowDuration = deserializer.readDouble();
|
|
249
|
+
|
|
250
|
+
key = deserializer.readString(); // "initialized"
|
|
251
|
+
bool initialized = deserializer.readBool();
|
|
252
|
+
|
|
253
|
+
// Validate window size
|
|
254
|
+
if (windowSize != static_cast<int32_t>(m_window_size))
|
|
255
|
+
{
|
|
256
|
+
throw std::runtime_error("MovingAverage window size mismatch during TOON deserialization");
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
m_window_duration_ms = windowDuration;
|
|
260
|
+
m_is_initialized = initialized;
|
|
261
|
+
|
|
262
|
+
// 3. Channels
|
|
263
|
+
key = deserializer.readString(); // "channels"
|
|
264
|
+
deserializer.consumeToken(dsp::toon::T_ARRAY_START);
|
|
265
|
+
|
|
266
|
+
m_filters.clear();
|
|
267
|
+
|
|
268
|
+
while (deserializer.peekToken() != dsp::toon::T_ARRAY_END)
|
|
269
|
+
{
|
|
270
|
+
deserializer.consumeToken(dsp::toon::T_OBJECT_START);
|
|
271
|
+
|
|
272
|
+
// Buffer - CRITICAL: Direct binary memcpy (not parsing text!)
|
|
273
|
+
deserializer.readString(); // "buffer"
|
|
274
|
+
std::vector<float> bufferData = deserializer.readFloatArray();
|
|
275
|
+
|
|
276
|
+
// Sum
|
|
277
|
+
deserializer.readString(); // "sum"
|
|
278
|
+
float runningSum = deserializer.readFloat();
|
|
279
|
+
|
|
280
|
+
// Reconstruct filter with time-aware support
|
|
281
|
+
if (m_window_duration_ms > 0.0)
|
|
282
|
+
{
|
|
283
|
+
m_filters.emplace_back(m_window_size, m_window_duration_ms);
|
|
284
|
+
}
|
|
285
|
+
else
|
|
286
|
+
{
|
|
287
|
+
m_filters.emplace_back(m_window_size);
|
|
288
|
+
}
|
|
289
|
+
m_filters.back().setState(bufferData, runningSum);
|
|
290
|
+
|
|
291
|
+
deserializer.consumeToken(dsp::toon::T_OBJECT_END);
|
|
292
|
+
}
|
|
293
|
+
deserializer.consumeToken(dsp::toon::T_ARRAY_END);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
deserializer.consumeToken(dsp::toon::T_OBJECT_END);
|
|
297
|
+
}
|
|
298
|
+
|
|
180
299
|
private:
|
|
181
300
|
/**
|
|
182
301
|
* @brief Statelessly calculates the average for each channel
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
#include "../IDspStage.h"
|
|
4
4
|
#include "../core/PeakDetection.h"
|
|
5
|
+
#include "../utils/Toon.h"
|
|
5
6
|
#include <cmath>
|
|
6
7
|
#include <stdexcept>
|
|
7
8
|
#include <string>
|
|
@@ -143,6 +144,58 @@ namespace dsp::adapters
|
|
|
143
144
|
}
|
|
144
145
|
}
|
|
145
146
|
|
|
147
|
+
inline void serializeToon(dsp::toon::Serializer &s) const override
|
|
148
|
+
{
|
|
149
|
+
// Write configuration
|
|
150
|
+
s.writeFloat(m_threshold);
|
|
151
|
+
s.writeInt32(m_num_channels);
|
|
152
|
+
s.writeString(m_mode);
|
|
153
|
+
s.writeString(m_domain);
|
|
154
|
+
s.writeInt32(m_windowSize);
|
|
155
|
+
s.writeInt32(m_minPeakDistance);
|
|
156
|
+
|
|
157
|
+
// Write state (only for moving mode)
|
|
158
|
+
if (m_mode == "moving" && !m_prev_sample.empty())
|
|
159
|
+
{
|
|
160
|
+
s.writeFloatArray(m_prev_sample);
|
|
161
|
+
s.writeFloatArray(m_prev_prev_sample);
|
|
162
|
+
|
|
163
|
+
// Write peakCooldown as int array (convert to float array)
|
|
164
|
+
std::vector<float> cooldown_float(m_peakCooldown.begin(), m_peakCooldown.end());
|
|
165
|
+
s.writeFloatArray(cooldown_float);
|
|
166
|
+
}
|
|
167
|
+
else
|
|
168
|
+
{
|
|
169
|
+
// Write empty arrays
|
|
170
|
+
s.writeFloatArray(std::vector<float>());
|
|
171
|
+
s.writeFloatArray(std::vector<float>());
|
|
172
|
+
s.writeFloatArray(std::vector<float>());
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
inline void deserializeToon(dsp::toon::Deserializer &d) override
|
|
177
|
+
{
|
|
178
|
+
// Read configuration
|
|
179
|
+
m_threshold = d.readFloat();
|
|
180
|
+
m_num_channels = d.readInt32();
|
|
181
|
+
m_mode = d.readString();
|
|
182
|
+
m_domain = d.readString();
|
|
183
|
+
m_windowSize = d.readInt32();
|
|
184
|
+
m_minPeakDistance = d.readInt32();
|
|
185
|
+
|
|
186
|
+
// Read state arrays
|
|
187
|
+
m_prev_sample = d.readFloatArray();
|
|
188
|
+
m_prev_prev_sample = d.readFloatArray();
|
|
189
|
+
|
|
190
|
+
// Read peakCooldown (convert from float array to int)
|
|
191
|
+
std::vector<float> cooldown_float = d.readFloatArray();
|
|
192
|
+
m_peakCooldown.clear();
|
|
193
|
+
for (float val : cooldown_float)
|
|
194
|
+
{
|
|
195
|
+
m_peakCooldown.push_back(static_cast<int>(val));
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
146
199
|
void reset() override
|
|
147
200
|
{
|
|
148
201
|
std::fill(m_prev_sample.begin(), m_prev_sample.end(), 0.0f);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
#include "../IDspStage.h"
|
|
3
3
|
#include "../utils/SimdOps.h"
|
|
4
|
+
#include "../utils/Toon.h"
|
|
4
5
|
#include <cmath>
|
|
5
6
|
#include <stdexcept>
|
|
6
7
|
|
|
@@ -80,6 +81,19 @@ namespace dsp::adapters
|
|
|
80
81
|
throw std::runtime_error("Invalid rectify mode");
|
|
81
82
|
}
|
|
82
83
|
|
|
84
|
+
inline void serializeToon(dsp::toon::Serializer &s) const override
|
|
85
|
+
{
|
|
86
|
+
s.writeInt32(static_cast<int32_t>(m_mode));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
inline void deserializeToon(dsp::toon::Deserializer &d) override
|
|
90
|
+
{
|
|
91
|
+
int32_t mode_int = d.readInt32();
|
|
92
|
+
if (mode_int < 0 || mode_int > 1)
|
|
93
|
+
throw std::runtime_error("Invalid mode in RectifyStage deserialization");
|
|
94
|
+
m_mode = static_cast<RectifyMode>(mode_int);
|
|
95
|
+
}
|
|
96
|
+
|
|
83
97
|
void reset() override {} // No internal buffers
|
|
84
98
|
|
|
85
99
|
private:
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
#pragma once
|
|
9
9
|
|
|
10
10
|
#include "../IDspStage.h"
|
|
11
|
+
#include "../utils/Toon.h"
|
|
11
12
|
#include <vector>
|
|
12
13
|
#include <cmath>
|
|
13
14
|
#include <stdexcept>
|
|
@@ -187,6 +188,72 @@ namespace dsp
|
|
|
187
188
|
}
|
|
188
189
|
}
|
|
189
190
|
|
|
191
|
+
void serializeToon(dsp::toon::Serializer &s) const override
|
|
192
|
+
{
|
|
193
|
+
s.writeInt32(upFactor_);
|
|
194
|
+
s.writeInt32(downFactor_);
|
|
195
|
+
s.writeInt32(filterOrder_);
|
|
196
|
+
s.writeDouble(sampleRate_);
|
|
197
|
+
s.writeInt32(numChannels_);
|
|
198
|
+
s.writeInt32(static_cast<int32_t>(phaseAccumulator_));
|
|
199
|
+
|
|
200
|
+
// Serialize state buffers for each channel
|
|
201
|
+
for (const auto &buf : stateBuffers_)
|
|
202
|
+
{
|
|
203
|
+
s.writeFloatArray(buf);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Serialize state indices
|
|
207
|
+
for (size_t idx : stateIndices_)
|
|
208
|
+
{
|
|
209
|
+
s.writeInt32(static_cast<int32_t>(idx));
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Serialize phase accumulators
|
|
213
|
+
for (size_t pa : phaseAccumulators_)
|
|
214
|
+
{
|
|
215
|
+
s.writeInt32(static_cast<int32_t>(pa));
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
void deserializeToon(dsp::toon::Deserializer &d) override
|
|
220
|
+
{
|
|
221
|
+
int32_t upF = d.readInt32();
|
|
222
|
+
int32_t downF = d.readInt32();
|
|
223
|
+
int32_t order = d.readInt32();
|
|
224
|
+
double sr = d.readDouble();
|
|
225
|
+
int32_t nCh = d.readInt32();
|
|
226
|
+
phaseAccumulator_ = static_cast<size_t>(d.readInt32());
|
|
227
|
+
|
|
228
|
+
if (upF != upFactor_ || downF != downFactor_ || order != filterOrder_)
|
|
229
|
+
{
|
|
230
|
+
throw std::runtime_error("Resampler TOON: parameter mismatch");
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (nCh != numChannels_)
|
|
234
|
+
{
|
|
235
|
+
initializeStateBuffers(nCh);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Deserialize state buffers
|
|
239
|
+
for (auto &buf : stateBuffers_)
|
|
240
|
+
{
|
|
241
|
+
buf = d.readFloatArray();
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Deserialize state indices
|
|
245
|
+
for (size_t &idx : stateIndices_)
|
|
246
|
+
{
|
|
247
|
+
idx = static_cast<size_t>(d.readInt32());
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Deserialize phase accumulators
|
|
251
|
+
for (size_t &pa : phaseAccumulators_)
|
|
252
|
+
{
|
|
253
|
+
pa = static_cast<size_t>(d.readInt32());
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
190
257
|
private:
|
|
191
258
|
int upFactor_;
|
|
192
259
|
int downFactor_;
|