@@ -12,6 +12,7 @@ interface AdaptiveWaveformRenderVersionOptions {
1212 baseVersion : string ;
1313 pixelsPerSecond : number ;
1414 activeTileCount : number ;
15+ phaseKey ?: string ;
1516}
1617
1718function nowMs ( ) : number {
@@ -46,10 +47,36 @@ export function getWaveformZoomRedrawIntervalMs(activeTileCount: number): number
4647 return 32 ;
4748}
4849
50+ function hashPhaseKey ( phaseKey : string ) : number {
51+ let hash = 0 ;
52+ for ( let i = 0 ; i < phaseKey . length ; i += 1 ) {
53+ hash = ( ( hash << 5 ) - hash ) + phaseKey . charCodeAt ( i ) ;
54+ hash |= 0 ;
55+ }
56+ return Math . abs ( hash ) ;
57+ }
58+
59+ export function getWaveformZoomCommitPhaseMs ( activeTileCount : number , phaseKey ?: string ) : number {
60+ if ( ! phaseKey || activeTileCount <= 2 ) {
61+ return 0 ;
62+ }
63+
64+ if ( activeTileCount <= 4 ) {
65+ return ( hashPhaseKey ( phaseKey ) % 2 ) * 8 ;
66+ }
67+
68+ if ( activeTileCount <= 8 ) {
69+ return ( hashPhaseKey ( phaseKey ) % 4 ) * 8 ;
70+ }
71+
72+ return ( hashPhaseKey ( phaseKey ) % 6 ) * 10 ;
73+ }
74+
4975export function useAdaptiveWaveformRenderVersion ( {
5076 baseVersion,
5177 pixelsPerSecond,
5278 activeTileCount,
79+ phaseKey,
5380} : AdaptiveWaveformRenderVersionOptions ) : string {
5481 const zoomVersion = useMemo (
5582 ( ) => `e${ Math . round ( Math . max ( 1 , pixelsPerSecond ) * 1000 ) } ` ,
@@ -59,6 +86,10 @@ export function useAdaptiveWaveformRenderVersion({
5986 ( ) => getWaveformZoomRedrawIntervalMs ( activeTileCount ) ,
6087 [ activeTileCount ] ,
6188 ) ;
89+ const phaseDelayMs = useMemo (
90+ ( ) => getWaveformZoomCommitPhaseMs ( activeTileCount , phaseKey ) ,
91+ [ activeTileCount , phaseKey ] ,
92+ ) ;
6293 const [ committedZoomVersion , setCommittedZoomVersion ] = useState ( zoomVersion ) ;
6394 const latestZoomVersionRef = useRef ( zoomVersion ) ;
6495 const lastCommitAtRef = useRef ( 0 ) ;
@@ -89,7 +120,11 @@ export function useAdaptiveWaveformRenderVersion({
89120 } ;
90121
91122 const now = nowMs ( ) ;
92- if ( lastCommitAtRef . current === 0 || now - lastCommitAtRef . current >= redrawIntervalMs ) {
123+ const elapsedMs = now - lastCommitAtRef . current ;
124+ if (
125+ lastCommitAtRef . current === 0
126+ || ( elapsedMs >= redrawIntervalMs && phaseDelayMs === 0 )
127+ ) {
93128 clearPending ( ) ;
94129 commit ( ) ;
95130 return ;
@@ -99,17 +134,19 @@ export function useAdaptiveWaveformRenderVersion({
99134 return ;
100135 }
101136
102- const remainingMs = Math . max ( 0 , redrawIntervalMs - ( now - lastCommitAtRef . current ) ) ;
137+ const remainingMs = Math . max ( 0 , redrawIntervalMs - elapsedMs ) ;
138+ const scheduledDelayMs = lastCommitAtRef . current === 0
139+ ? phaseDelayMs
140+ : remainingMs + phaseDelayMs ;
103141 timeoutRef . current = setTimeout ( ( ) => {
104142 timeoutRef . current = null ;
105143 rafRef . current = requestAnimationFrame ( ( ) => {
106144 rafRef . current = null ;
107145 commit ( ) ;
108146 } ) ;
109- } , remainingMs ) ;
110-
147+ } , scheduledDelayMs ) ;
111148 return clearPending ;
112- } , [ committedZoomVersion , redrawIntervalMs , zoomVersion ] ) ;
149+ } , [ committedZoomVersion , phaseDelayMs , redrawIntervalMs , zoomVersion ] ) ;
113150
114151 useEffect ( ( ) => {
115152 return ( ) => {
0 commit comments