- Replace all bare 'size_t' with 'std::size_t' in core/*.cpp, io/*.cpp, headers
- Fix distance_estimator: 'threat' class now uses config.ref_spl_gunshot instead of hardcoded 150.0f
- Add --threshold CLI arg to demo_offline (default 0.5)
- Rewrite mobile_phone_source.cpp to match PIMPL header API
- All tests pass: test_core_lib 6/6, demo_offline 20/20, extract_mel_cpp, test_classifier_cpp
- Rewrite acoustic_node.cpp:
- Use PipelineConfig instead of removed PipelineParams
- Use Pipeline::Process(flat_samples) returning AcousticFrame
- Remove obsolete init() and process_single_channel() calls
- Add flatten_audio helper for interleaved multi-channel data
- Rewrite threat_publisher.cpp:
- Implement ThreatPublisher::Impl PIMPL pattern
- Accept AcousticFrame instead of old TrackedThreat vector
- Add NumPublished() counter
- Fix CMakeLists.txt: remove stale KISSFFT_DIR from test includes
- Add build_core_test.bat for compiling all test targets on Windows
- All core tests pass (test_core_lib 6/6)
- Implement iterative complex FFT in fft_utils.cpp (power-of-2 only)
- Replace O(n^2) DFT with O(n log n) FFT in compute_power_spectrum
- Validation time drops from ~3200ms to ~97ms total (~160ms -> ~5ms per file)
- All tests pass (test_core_lib 6/6, demo_offline 20/20)
- Cache Ort::MemoryInfo and I/O names in gunshot_classifier (avoid per-inference alloc)
- Reuse single FeatureExtractor across all files in demo_offline
- Add per-file and total inference timing to demo_offline
- Remove third_party/kiss_fft directory (fully replaced by inline FFT)
- Update fft_utils.h comments to remove stale kiss_fft references
- Verify 20/20 validation accuracy maintained, ~160ms avg per file