Apply per-speaker calibration only to displayed music cues

This commit is contained in:
firestar5683
2026-09-19 18:04:01 -07:00
parent 8c954bfe7b
commit 0ed635026d
3 changed files with 24 additions and 2 deletions
+3 -1
View File
@@ -35,6 +35,8 @@ output_device=select_device(sd.query_devices(),output_metadata) if output_metada
if output_device is not None:
sd.check_output_settings(device=output_device,channels=2,dtype='float32',samplerate=48000)
output_metadata['portaudio_device']=output_device
from operator_output import PresentationDelay
presentation_delay=PresentationDelay(root,output_provider=lambda: {'id':output_metadata['output_identity']} if output_metadata.get('bluetooth_selected') else None)
(run/'output_device.json').write_text(json.dumps(output_metadata,indent=2)+'\n')
if os.environ.get('ROADSCORE_RESIDENT')=='1':
import atexit
@@ -390,7 +392,7 @@ try:
if songform:snapshot.update(songform.snapshot())
if composition:snapshot.update(composition.snapshot(frames/rate))
if gestures:snapshot.update(gestures.status())
trace.write(json.dumps(snapshot)+'\n');f=run/'status.tmp';f.write_text(json.dumps(snapshot));f.replace(run/'status.json')
trace.write(json.dumps(snapshot)+'\n');f=run/'status.tmp';f.write_text(json.dumps(presentation_delay.apply(snapshot)));f.replace(run/'status.json')
if time.monotonic()-last_progress>15:raise RuntimeError('Replay model input stalled')
finally:
audio_started=False
+2 -1
View File
@@ -294,7 +294,8 @@ class OutputOwner:
PRESENTATION_FIELDS = ('phase', 'kind', 'amount', 'activation', 'strength', 'section', 'next_section',
'gesture_active', 'gesture_queued', 'turn_signal_music')
'gesture_active', 'gesture_queued', 'turn_signal_music', 'lead', 'predicted_peak', 'scheduled',
'signal_shaker', 'core_apex', 'alert_accent', 'engagement_presentation')
class PresentationDelay:
@@ -86,6 +86,25 @@ class OutputTests(unittest.TestCase):
self.assertEqual(shown['phase'],'curve');self.assertEqual(shown['readiness'],'DEGRADED')
self.assertEqual(shown['buffered'],80);self.assertEqual(next_snapshot['phase'],'apex')
def test_rendered_cues_delay_without_touching_raw_audio_clock_or_core(self):
import copy
self.owner.dispatch('set_latency',latency_ms=250)
delay=m.PresentationDelay(self.root,lambda:self.output,self.clock)
raw=dict(signal_shaker={'rendered_active':True},core_apex={'rendered_active':True},alert_accent={'rendered_active':False},engagement_presentation={'active':True},elapsed=50,route_t=10,source_cutoff_ns=123,buffered=80,readiness='READY')
original=copy.deepcopy(raw)
first=delay.apply(raw)
self.assertNotIn('signal_shaker',first)
self.assertEqual(first['elapsed'],50);self.assertEqual(first['source_cutoff_ns'],123)
self.clock.value+=.26
current={**raw,'signal_shaker':{'rendered_active':False},'route_t':11,'elapsed':50.26,'readiness':'DEGRADED'}
shown=delay.apply(current)
self.assertTrue(shown['signal_shaker']['rendered_active'])
self.assertEqual(shown['readiness'],'DEGRADED');self.assertEqual(shown['route_t'],11)
self.assertEqual(raw,original);self.assertFalse(current['signal_shaker']['rendered_active'])
self.output=None;self.clock.value+=3
bypass=delay.apply(current)
self.assertEqual(bypass['presentation_latency_ms'],0);self.assertFalse(bypass['signal_shaker']['rendered_active'])
def test_watchdog_cancels_own_audio_and_releases_leases(self):
token=self.owner.dispatch('calibration_start',attended=True)['session']
sink=self.owner.session['sink']