dsp/: C++ skeleton with working FFT/WOLA STFT

- Cooley-Tukey radix-2 FFT (forward + inverse with /N normalization)
- WOLA STFT/ISTFT with Hann window (nfft=2048, hop=512)
- WAV16 read + WAV24 write (fixed aliasing bug in read)
- Fixed in-place processing bug (separate input/output buffers)
- Biquad filter (peak/shelf/reject)
- Peak detector skeleton
- MS encode/decode (M8 stereo)
- Harness: WAV16 → STFT → WAV24 passthrough verified non-zero output

Verified: burst500.wav passthrough produces output RMS=0.0678
This commit is contained in:
2026-08-17 11:25:35 +03:00
parent 81cfca70a9
commit 7dcbcf49b4
21 changed files with 894 additions and 8 deletions
+54
View File
@@ -0,0 +1,54 @@
#include "detect.hpp"
#include <cmath>
Detector::Detector() : sharpness_(10), selectivity_(10), depth_(0.864) {
}
void Detector::setParams(float sharpness, float selectivity, float depth) {
sharpness_ = sharpness;
selectivity_ = selectivity;
depth_ = depth;
}
float Detector::computeReduction(float magnitude, float freq) {
float level_db = 20 * std::log10(std::max(magnitude, 1e-12f));
float base_red = std::min(std::max(level_db + 10, 0.0f), 60.0f);
float amount = base_red * depth_;
return std::min(amount, 60.0f);
}
size_t Detector::detectPeaks(const std::complex<double>* spectrum, size_t n,
float sample_rate, Peak* peaks, size_t max_peaks) {
float spacing_bins = std::max(2.0f, selectivity_ * 0.5f);
size_t count = 0;
for (size_t k = 1; k < n - 1; k++) {
double mag = std::abs(spectrum[k]);
double mag_prev = std::abs(spectrum[k - 1]);
double mag_next = std::abs(spectrum[k + 1]);
if (mag > mag_prev && mag > mag_next) {
float freq = k * sample_rate / (2 * n);
float red = computeReduction(static_cast<float>(mag), freq);
if (red > 3.0f) {
bool is_peak = true;
for (size_t i = 0; i < count; i++) {
if (std::abs(peaks[i].freq - freq) < spacing_bins * sample_rate / (2 * n)) {
is_peak = false;
break;
}
}
if (is_peak && count < max_peaks) {
peaks[count].bin = k;
peaks[count].freq = freq;
peaks[count].magnitude = static_cast<float>(mag);
peaks[count].reduction = red;
count++;
}
}
}
}
return count;
}