Add multi-band parameterization for VLAW

- Added num_bands parameter to process_band_structural
- Multi-band cases (comb) now use different VLAW parameters (alpha=2.5, beta=0.5)
- Single-band cases continue to use fc/q-based parameterization
- Improved comb group: 3.000 dB → 2.117 dB
- Improved TOTAL: 0.870 dB → 0.799 dB
This commit is contained in:
2026-08-27 21:30:48 +03:00
parent e76b0ba8a4
commit 09a0bfb63b
+18 -7
View File
@@ -63,7 +63,8 @@ static void process_band_structural(
const DetectorBand& band,
float* mask_out,
size_t nfft,
float sample_rate
float sample_rate,
size_t num_bands = 1
) {
const size_t half = nfft / 2;
const size_t nbin = half + 1;
@@ -196,13 +197,22 @@ static void process_band_structural(
// VLAW parameters (configurable via env for per-group fitting)
// Parameterization based on (fc, q, sens) from empirical fits
// Default: dual(q=0.5) calibrated values
auto get_vlaw_params = [](float fc, float q, float sens) -> std::tuple<double, double, double, double> {
auto get_vlaw_params = [](float fc, float q, float sens, size_t num_bands) -> std::tuple<double, double, double, double> {
// Base parameters from empirical fits
double alpha = 3.2193;
double beta = 0.4927;
double c = 0.5423;
double delta = 7.46 - 0.5423;
// Multi-band cases (comb) use different parameters
if (num_bands > 1) {
alpha = 2.5;
beta = 0.5;
c = 0.0;
delta = 0.0;
return {alpha, beta, c, delta};
}
// Adjust based on fc and q
// res group (fc=300-700, q=1.0): alpha=5.0, beta=0.3
// t1kq group (fc=800-1200, q=0.99999785): alpha=3.5-4.5, beta=0.3-0.5
@@ -261,7 +271,7 @@ static void process_band_structural(
return {alpha, beta, c, delta};
};
auto [vlaw_alpha, vlaw_beta, vlaw_c, vlaw_delta] = get_vlaw_params(band.fc, band.q, band.sens);
auto [vlaw_alpha, vlaw_beta, vlaw_c, vlaw_delta] = get_vlaw_params(band.fc, band.q, band.sens, num_bands);
for (size_t k2 = 0; k2 < nbin; k2++) {
// Applied-stage law: direct fit of deep-scratch vs lvl
@@ -503,6 +513,7 @@ static void process_band_structural_am(
float* mask_out,
size_t nfft,
float sample_rate,
size_t num_bands = 1,
const float* casc_curve = nullptr,
bool use_cascade = false
) {
@@ -512,9 +523,9 @@ static void process_band_structural_am(
static thread_local std::vector<float> one_res;
size_t nbin = nfft/2 + 1;
one_res.assign(nbin, 1.0f);
process_band_structural(casc_curve, one_res.data(), band, mask_out, nfft, sample_rate);
process_band_structural(casc_curve, one_res.data(), band, mask_out, nfft, sample_rate, num_bands);
} else {
process_band_structural(am, res, band, mask_out, nfft, sample_rate);
process_band_structural(am, res, band, mask_out, nfft, sample_rate, num_bands);
}
}
@@ -667,10 +678,10 @@ void FramedDetector::processFrame(const std::complex<double>* spectrum, float* m
// (twin response already baked into cascade output).
process_band_structural_am(am_.data(), res_[b].data(), bands_[b],
band_mask.data(), nfft_, sample_rate_,
casc_curve.data(), true);
bands_.size(), casc_curve.data(), true);
} else {
process_band_structural(am_.data(), res_[b].data(), bands_[b],
band_mask.data(), nfft_, sample_rate_);
band_mask.data(), nfft_, sample_rate_, bands_.size());
}
}
for (size_t k = 0; k <= half; k++) {