mirror of
https://codeberg.org/armin/tcd.git
synced 2026-09-01 05:50:46 +02:00
fix noise floor detection
This commit is contained in:
parent
422a758cb2
commit
1072dfba65
1 changed files with 38 additions and 13 deletions
51
tcd.c
51
tcd.c
|
|
@ -170,7 +170,8 @@ static int detect_cutoff(const Analyzer *a, double threshold_db,
|
|||
double sensitivity,
|
||||
double *out_cutoff, double *out_steepness,
|
||||
double *out_noise_db, double *out_roughness,
|
||||
double *out_band_ratio)
|
||||
double *out_band_ratio,
|
||||
double *out_extended_cutoff)
|
||||
{
|
||||
int n = a->fft_size / 2;
|
||||
int sr = a->sample_rate;
|
||||
|
|
@ -221,6 +222,21 @@ static int detect_cutoff(const Analyzer *a, double threshold_db,
|
|||
double noise_floor = (noise_count > 0) ? (noise_sum / noise_count) : 1e-12;
|
||||
*out_noise_db = 20.0 * log10(noise_floor / peak);
|
||||
|
||||
/* Compute extended cutoff at noise floor + 6 dB margin.
|
||||
Catches high-frequency content below the user's threshold but
|
||||
above the noise floor, proving the file isn't a low-bitrate
|
||||
re-encode even when high frequencies are very quiet.
|
||||
Limit to at most 30 dB more sensitive than user threshold. */
|
||||
double ext_db = *out_noise_db + 6.0;
|
||||
double min_ext_db = threshold_db - 30.0;
|
||||
if (ext_db < min_ext_db) ext_db = min_ext_db;
|
||||
double ext_peak = peak * pow(10.0, ext_db / 20.0);
|
||||
double ext_cutoff = 0;
|
||||
for (int i = n - 1; i >= 0; i--) {
|
||||
if (mag[i] >= ext_peak) { ext_cutoff = (double)i * sr / a->fft_size; break; }
|
||||
}
|
||||
*out_extended_cutoff = ext_cutoff;
|
||||
|
||||
double roughness = 0.0;
|
||||
double cutoff_idx = cutoff_hz * a->fft_size / sr;
|
||||
int lo = (int)(cutoff_idx * 0.60);
|
||||
|
|
@ -494,7 +510,8 @@ static void freq_label_row(int chart_w, double nyquist)
|
|||
|
||||
static void render_visual_spectrum(
|
||||
const Analyzer *a,
|
||||
double cutoff_hz, double steepness, double noise_db,
|
||||
double cutoff_hz, double effective_cutoff_hz,
|
||||
double steepness, double noise_db,
|
||||
double roughness, double band_ratio,
|
||||
int is_transcode, int is_native_lossy, int upscaled,
|
||||
double peak_db, double threshold_db,
|
||||
|
|
@ -671,8 +688,10 @@ static void render_visual_spectrum(
|
|||
draw_hline(chart_w + label_w);
|
||||
|
||||
double cutoff_ratio = cutoff_hz / nyquist;
|
||||
double eff_cutoff_ratio = effective_cutoff_hz / nyquist;
|
||||
double confidence = compute_confidence(
|
||||
cutoff_ratio, steepness, roughness, band_ratio, is_native_lossy);
|
||||
is_native_lossy ? eff_cutoff_ratio : cutoff_ratio,
|
||||
steepness, roughness, band_ratio, is_native_lossy);
|
||||
|
||||
printf(" " ANSI_BOLD "Decision:" ANSI_RESET " ");
|
||||
if (peak_db < -90.0) {
|
||||
|
|
@ -723,18 +742,18 @@ static void render_visual_spectrum(
|
|||
char line[128];
|
||||
snprintf(line, sizeof(line),
|
||||
" cutoff_ratio=%.3f < expected for bitrate (%lld kbps)",
|
||||
cutoff_ratio, (long long)(bitrate / 1000));
|
||||
eff_cutoff_ratio, (long long)(bitrate / 1000));
|
||||
printf(" %s " ANSI_GREEN "✓" ANSI_RESET, line);
|
||||
printf("\n");
|
||||
|
||||
const char *src_hint = "";
|
||||
if (cutoff_ratio < 0.70) src_hint = "≤ 64 kbps source";
|
||||
else if (cutoff_ratio < 0.80) src_hint = "96–128 kbps source";
|
||||
else if (cutoff_ratio < 0.88) src_hint = "128–192 kbps source";
|
||||
if (eff_cutoff_ratio < 0.70) src_hint = "≤ 64 kbps source";
|
||||
else if (eff_cutoff_ratio < 0.80) src_hint = "96–128 kbps source";
|
||||
else if (eff_cutoff_ratio < 0.88) src_hint = "128–192 kbps source";
|
||||
printf(" → " ANSI_BOLD "Suggest %s" ANSI_RESET, src_hint);
|
||||
printf("\n");
|
||||
} else {
|
||||
printf(" cutoff_ratio=%.3f within expected range for this bitrate " ANSI_GREEN "✓" ANSI_RESET, cutoff_ratio);
|
||||
printf(" cutoff_ratio=%.3f within expected range for this bitrate " ANSI_GREEN "✓" ANSI_RESET, eff_cutoff_ratio);
|
||||
printf("\n");
|
||||
}
|
||||
} else {
|
||||
|
|
@ -1129,11 +1148,12 @@ static int process_file(const char *filename, const Options *opts)
|
|||
}
|
||||
|
||||
double cutoff_hz = 0, steepness = 0, noise_db = 0;
|
||||
double roughness = 0, band_ratio = 0;
|
||||
double roughness = 0, band_ratio = 0, extended_cutoff = 0;
|
||||
int is_transcode = detect_cutoff(&analyzer, opts->threshold_db,
|
||||
opts->sensitivity,
|
||||
&cutoff_hz, &steepness, &noise_db,
|
||||
&roughness, &band_ratio);
|
||||
&roughness, &band_ratio,
|
||||
&extended_cutoff);
|
||||
double nyquist = sample_rate / 2.0;
|
||||
|
||||
double peak_mag = 0;
|
||||
|
|
@ -1155,7 +1175,9 @@ static int process_file(const char *filename, const Options *opts)
|
|||
return 2;
|
||||
}
|
||||
|
||||
double cutoff_ratio = cutoff_hz / nyquist;
|
||||
double effective_cutoff = cutoff_hz;
|
||||
if (extended_cutoff > effective_cutoff) effective_cutoff = extended_cutoff;
|
||||
double cutoff_ratio = effective_cutoff / nyquist;
|
||||
int upscaled = 0;
|
||||
if (is_native_lossy) {
|
||||
double expected_min = 0.90;
|
||||
|
|
@ -1167,7 +1189,8 @@ static int process_file(const char *filename, const Options *opts)
|
|||
|
||||
render_visual_spectrum(
|
||||
&analyzer,
|
||||
cutoff_hz, steepness, noise_db, roughness, band_ratio,
|
||||
cutoff_hz, effective_cutoff, steepness, noise_db,
|
||||
roughness, band_ratio,
|
||||
is_transcode, is_native_lossy, upscaled,
|
||||
peak_db, opts->threshold_db,
|
||||
filename, fmt_name,
|
||||
|
|
@ -1211,7 +1234,9 @@ static int process_file(const char *filename, const Options *opts)
|
|||
return 2;
|
||||
}
|
||||
|
||||
double cutoff_ratio = cutoff_hz / nyquist;
|
||||
double effective_cutoff = cutoff_hz;
|
||||
if (extended_cutoff > effective_cutoff) effective_cutoff = extended_cutoff;
|
||||
double cutoff_ratio = effective_cutoff / nyquist;
|
||||
int upscaled = 0;
|
||||
|
||||
if (is_native_lossy) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue