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 sensitivity,
|
||||||
double *out_cutoff, double *out_steepness,
|
double *out_cutoff, double *out_steepness,
|
||||||
double *out_noise_db, double *out_roughness,
|
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 n = a->fft_size / 2;
|
||||||
int sr = a->sample_rate;
|
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;
|
double noise_floor = (noise_count > 0) ? (noise_sum / noise_count) : 1e-12;
|
||||||
*out_noise_db = 20.0 * log10(noise_floor / peak);
|
*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 roughness = 0.0;
|
||||||
double cutoff_idx = cutoff_hz * a->fft_size / sr;
|
double cutoff_idx = cutoff_hz * a->fft_size / sr;
|
||||||
int lo = (int)(cutoff_idx * 0.60);
|
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(
|
static void render_visual_spectrum(
|
||||||
const Analyzer *a,
|
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,
|
double roughness, double band_ratio,
|
||||||
int is_transcode, int is_native_lossy, int upscaled,
|
int is_transcode, int is_native_lossy, int upscaled,
|
||||||
double peak_db, double threshold_db,
|
double peak_db, double threshold_db,
|
||||||
|
|
@ -671,8 +688,10 @@ static void render_visual_spectrum(
|
||||||
draw_hline(chart_w + label_w);
|
draw_hline(chart_w + label_w);
|
||||||
|
|
||||||
double cutoff_ratio = cutoff_hz / nyquist;
|
double cutoff_ratio = cutoff_hz / nyquist;
|
||||||
|
double eff_cutoff_ratio = effective_cutoff_hz / nyquist;
|
||||||
double confidence = compute_confidence(
|
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 " ");
|
printf(" " ANSI_BOLD "Decision:" ANSI_RESET " ");
|
||||||
if (peak_db < -90.0) {
|
if (peak_db < -90.0) {
|
||||||
|
|
@ -723,18 +742,18 @@ static void render_visual_spectrum(
|
||||||
char line[128];
|
char line[128];
|
||||||
snprintf(line, sizeof(line),
|
snprintf(line, sizeof(line),
|
||||||
" cutoff_ratio=%.3f < expected for bitrate (%lld kbps)",
|
" 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(" %s " ANSI_GREEN "✓" ANSI_RESET, line);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
const char *src_hint = "";
|
const char *src_hint = "";
|
||||||
if (cutoff_ratio < 0.70) src_hint = "≤ 64 kbps source";
|
if (eff_cutoff_ratio < 0.70) src_hint = "≤ 64 kbps source";
|
||||||
else if (cutoff_ratio < 0.80) src_hint = "96–128 kbps source";
|
else if (eff_cutoff_ratio < 0.80) src_hint = "96–128 kbps source";
|
||||||
else if (cutoff_ratio < 0.88) src_hint = "128–192 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(" → " ANSI_BOLD "Suggest %s" ANSI_RESET, src_hint);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
} else {
|
} 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");
|
printf("\n");
|
||||||
}
|
}
|
||||||
} else {
|
} 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 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,
|
int is_transcode = detect_cutoff(&analyzer, opts->threshold_db,
|
||||||
opts->sensitivity,
|
opts->sensitivity,
|
||||||
&cutoff_hz, &steepness, &noise_db,
|
&cutoff_hz, &steepness, &noise_db,
|
||||||
&roughness, &band_ratio);
|
&roughness, &band_ratio,
|
||||||
|
&extended_cutoff);
|
||||||
double nyquist = sample_rate / 2.0;
|
double nyquist = sample_rate / 2.0;
|
||||||
|
|
||||||
double peak_mag = 0;
|
double peak_mag = 0;
|
||||||
|
|
@ -1155,7 +1175,9 @@ static int process_file(const char *filename, const Options *opts)
|
||||||
return 2;
|
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;
|
int upscaled = 0;
|
||||||
if (is_native_lossy) {
|
if (is_native_lossy) {
|
||||||
double expected_min = 0.90;
|
double expected_min = 0.90;
|
||||||
|
|
@ -1167,7 +1189,8 @@ static int process_file(const char *filename, const Options *opts)
|
||||||
|
|
||||||
render_visual_spectrum(
|
render_visual_spectrum(
|
||||||
&analyzer,
|
&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,
|
is_transcode, is_native_lossy, upscaled,
|
||||||
peak_db, opts->threshold_db,
|
peak_db, opts->threshold_db,
|
||||||
filename, fmt_name,
|
filename, fmt_name,
|
||||||
|
|
@ -1211,7 +1234,9 @@ static int process_file(const char *filename, const Options *opts)
|
||||||
return 2;
|
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;
|
int upscaled = 0;
|
||||||
|
|
||||||
if (is_native_lossy) {
|
if (is_native_lossy) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue