diff --git a/roadscore/prototype/stream_clock_bridge.py b/roadscore/prototype/stream_clock_bridge.py index f29c1b83e8..19af31c7a6 100644 --- a/roadscore/prototype/stream_clock_bridge.py +++ b/roadscore/prototype/stream_clock_bridge.py @@ -7,6 +7,34 @@ class StreamClockBridge: def __init__(self, offset, uncertainty): self.offset = offset self.uncertainty = uncertainty + self.source = 'bracketed-stream-time' + self.offset_spread = None + + @classmethod + def from_callbacks(cls, observations): + """Freeze one offset from silent pre-roll, before any route is released. + + Some ALSA streams report zero from stream.time until their first callback, + then return the latest callback timestamp. Callback entry is later than its + timestamp: the minimum offset minimizes that nonnegative scheduling bias. + It does not measure Bluetooth acoustic latency. + """ + if len(observations)<8:raise ValueError('Output clock needs more silent callbacks') + offsets=[];previous=None + for wall,current,dac in observations: + if (not all(type(value) in (int,float) and math.isfinite(value) for value in (wall,current,dac)) + or current<=0 or dac<=0 or not -.02<=dac-current<=5): + raise ValueError('Invalid callback clock sample') + if previous is not None and (wall