refactor: simplify clock drift compensation with hardcoded parameters and improved frame drop logic
This commit is contained in:
@@ -42,7 +42,6 @@ class AuracastGlobalConfig(BaseModel):
|
||||
assisted_listening_stream: bool = False
|
||||
# Clock drift compensation: discard excess samples when buffer exceeds threshold
|
||||
enable_drift_compensation: bool = False
|
||||
drift_threshold_ms: float = 2.0 # Discard threshold in milliseconds
|
||||
|
||||
# "Audio input. "
|
||||
# "'device' -> use the host's default sound input device, "
|
||||
|
||||
@@ -651,19 +651,22 @@ class Streamer():
|
||||
bigs = self.bigs
|
||||
self.is_streaming = True
|
||||
|
||||
# Sample discard stats (clock drift compensation)
|
||||
# frame drop algo parameters
|
||||
sample_rate = big['audio_input']._pcm_format.sample_rate
|
||||
samples_discarded_total = 0 # Total samples discarded
|
||||
discard_events = 0 # Number of times we discarded samples
|
||||
frames_since_last_discard = 999 # Guard: frames since last discard (start high to allow first drop)
|
||||
enable_drift_compensation = global_config.enable_drift_compensation
|
||||
discard_guard_frames = sample_rate // 100 # Don't allow discard within this many frames of previous discard
|
||||
# Calculate threshold based on config (default 2ms)
|
||||
drift_threshold_ms = global_config.drift_threshold_ms if global_config.enable_drift_compensation else 0
|
||||
# Hardcoded parameters (unit: milliseconds)
|
||||
drift_threshold_ms = 2.0 if enable_drift_compensation else 0.0
|
||||
static_drop_ms = 0.5 if enable_drift_compensation else 0.0
|
||||
# Guard interval measured in LC3 frames (10 ms each); 50 => 500 ms cooldown
|
||||
discard_guard_frames = int(2*sample_rate / 1000) if enable_drift_compensation else 0
|
||||
# Derived sample counts
|
||||
drop_threshold_samples = int(sample_rate * drift_threshold_ms / 1000.0)
|
||||
static_drop_samples = int(sample_rate * 0.0005) # Always drop a static amount of samples
|
||||
|
||||
if global_config.enable_drift_compensation:
|
||||
static_drop_samples = int(sample_rate * static_drop_ms / 1000.0)
|
||||
|
||||
if enable_drift_compensation:
|
||||
logging.info(f"Clock drift compensation ENABLED: threshold={drift_threshold_ms}ms, guard={discard_guard_frames} frames")
|
||||
else:
|
||||
logging.info("Clock drift compensation DISABLED")
|
||||
@@ -699,12 +702,6 @@ class Streamer():
|
||||
stream_finished[i] = True
|
||||
continue
|
||||
|
||||
# Calculate threshold samples based on sample rate (only once per BIG)
|
||||
if enable_drift_compensation and drop_threshold_samples == 0:
|
||||
drop_threshold_samples = int(sample_rate * drift_threshold_ms / 1000.0)
|
||||
logging.info(f"Drift compensation threshold: {drop_threshold_samples} samples ({drift_threshold_ms}ms @ {sample_rate}Hz)")
|
||||
logging.info(f"Static drop amount: {static_drop_samples} samples (3.0ms @ {sample_rate}Hz)")
|
||||
|
||||
# Discard excess samples in buffer if above threshold (clock drift compensation)
|
||||
if enable_drift_compensation and hasattr(big['audio_input'], '_stream') and big['audio_input']._stream:
|
||||
sd_buffer_samples = big['audio_input']._stream.read_available
|
||||
@@ -713,7 +710,7 @@ class Streamer():
|
||||
if sd_buffer_samples > drop_threshold_samples and frames_since_last_discard >= discard_guard_frames:
|
||||
# Always drop a static amount (3ms) for predictable behavior
|
||||
# This matches the crossfade duration better for smoother transitions
|
||||
samples_to_drop = static_drop_samples
|
||||
samples_to_drop = min(static_drop_samples, max(1, big['lc3_frame_samples'] - 1))
|
||||
try:
|
||||
discarded_data = await anext(big['audio_input'].frames(samples_to_drop))
|
||||
samples_discarded_total += samples_to_drop
|
||||
|
||||
@@ -111,7 +111,6 @@ if __name__ == "__main__":
|
||||
octets_per_frame = OCTETS_PER_FRAME,
|
||||
transport=TRANSPORT1,
|
||||
enable_drift_compensation=True,
|
||||
drift_threshold_ms=2.0
|
||||
)
|
||||
config.debug = False
|
||||
|
||||
|
||||
Reference in New Issue
Block a user