From fdfe43b6b9d0aaa5b80ef797448c57e2842d6b1e Mon Sep 17 00:00:00 2001 From: pober Date: Tue, 21 Apr 2026 15:07:31 +0200 Subject: [PATCH] Retries on alsa error, coming from the audiointerface. --- config.yaml | 2 +- test_matrix.py | 44 +++++++++++++++++++++++++++++++++----------- 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/config.yaml b/config.yaml index e550ced..99a66f1 100644 --- a/config.yaml +++ b/config.yaml @@ -31,7 +31,7 @@ artifact_detection: threshold_db: -60 # Detect unexpected frequencies above noise floor + this threshold (more negative = less sensitive) amplitude_spikes: enabled: true - threshold_factor: 5.0 # MAD-based outlier detection on envelope (detects clicks, pops, dropouts). Lower = more sensitive. + threshold_factor: 7.0 # MAD-based outlier detection on envelope (detects clicks, pops, dropouts). Lower = more sensitive. zero_crossing: enabled: false threshold_factor: 2.0 # Number of standard deviations for zero-crossing anomalies (detects distortion) diff --git a/test_matrix.py b/test_matrix.py index f2acaab..770e1ae 100644 --- a/test_matrix.py +++ b/test_matrix.py @@ -377,6 +377,7 @@ def main(): if not result['latency'].get('valid', False): print(" Latency invalid — attempting USB recovery, skipping buildup/quality.") + result['latency']['alsa_error'] = True _try_usb_audio_reset(config) return result else: @@ -418,28 +419,49 @@ def main(): print(f"\n[{idx:2d}/{total}] {qos:6s} {rate:3s} {ch:6s} PD={pd:2d}ms") matrix_results[key] = run_combo(qos, rate, ch, pd) - # --- Retry failed combinations if failure rate < 10% --- + # --- Retry failed combinations --- + # ALSA/hardware failures always retry (up to 3 times) regardless of threshold. + # Other failures retry only if the failure rate is <= 10%. def _is_failed(r): lat = r.get('latency') return lat is None or lat.get('valid') is False - failed_keys = [k for k, r in matrix_results.items() if _is_failed(r)] - retry_threshold = total * 0.10 + def _is_alsa_failure(r): + lat = r.get('latency') or {} + return lat.get('alsa_error', False) - if 0 < len(failed_keys) <= retry_threshold: + MAX_RETRIES = 3 + for retry_round in range(1, MAX_RETRIES + 1): + failed_keys = [k for k, r in matrix_results.items() if _is_failed(r)] + if not failed_keys: + break + + alsa_keys = [k for k in failed_keys if _is_alsa_failure(matrix_results[k])] + other_keys = [k for k in failed_keys if k not in alsa_keys] + retry_threshold = total * 0.10 + + keys_to_retry = list(alsa_keys) + if 0 < len(other_keys) <= retry_threshold: + keys_to_retry += other_keys + elif len(other_keys) > retry_threshold: + print(f"\n{len(other_keys)}/{total} non-hardware failures " + f"({len(other_keys)/total*100:.0f}%) — above 10% threshold, skipping retry.") + + if not keys_to_retry: + break + + n_other_retrying = len(keys_to_retry) - len(alsa_keys) print(f"\n{'=' * 70}") - print(f"RETRYING {len(failed_keys)} failed combination(s) " - f"({len(failed_keys)}/{total} = {len(failed_keys)/total*100:.0f}% < 10%)") + print(f"RETRY ROUND {retry_round}/{MAX_RETRIES} — " + f"{len(keys_to_retry)} combo(s) " + f"[{len(alsa_keys)} hw-error, {n_other_retrying} other]") print(f"{'=' * 70}") - for retry_idx, key in enumerate(failed_keys, 1): + for retry_idx, key in enumerate(keys_to_retry, 1): r = matrix_results[key] qos, rate, ch, pd = r['qos'], r['sample_rate'], r['channels'], r['presentation_delay_ms'] - print(f"\n[retry {retry_idx}/{len(failed_keys)}] {qos:6s} {rate:3s} {ch:6s} PD={pd:2d}ms") + print(f"\n[retry {retry_round}.{retry_idx}/{len(keys_to_retry)}] {qos:6s} {rate:3s} {ch:6s} PD={pd:2d}ms") matrix_results[key] = run_combo(qos, rate, ch, pd) matrix_results[key]['retried'] = True - elif len(failed_keys) > retry_threshold: - print(f"\n{len(failed_keys)}/{total} combinations failed " - f"({len(failed_keys)/total*100:.0f}%) — above 10% threshold, skipping retry.") # --- Save results --- output_data = {