@@ -91,20 +91,24 @@ export function drawSpectrogram(
9191 for ( let k = 0 ; k < bins ; k ++ ) magDb [ k ] = 20 * Math . log10 ( Math . hypot ( re [ k ] , im [ k ] ) * scale + 1e-12 ) ;
9292
9393 const MIN_DB = - 100 , MAX_DB = 0 ;
94- const specWidth = canvas . width , specHeight = canvas . height ;
95- // scroll left
96- ctx . drawImage ( canvas , 1 , 0 , specWidth - 1 , specHeight , 0 , 0 , specWidth - 1 , specHeight ) ;
97- // draw rightmost column via ImageData for speed
98- const column = ctx . createImageData ( 1 , specHeight ) ;
94+ // Use device-pixel dimensions to avoid DPR transform mismatch
95+ const wDev = canvas . width ;
96+ const hDev = canvas . height ;
97+ // Scroll left by 1 device pixel in an identity transform space
98+ ctx . save ( ) ;
99+ ctx . setTransform ( 1 , 0 , 0 , 1 , 0 , 0 ) ;
100+ ctx . drawImage ( canvas , 1 , 0 , wDev - 1 , hDev , 0 , 0 , wDev - 1 , hDev ) ;
101+ // draw rightmost column via ImageData for speed (device pixels)
102+ const column = ctx . createImageData ( 1 , hDev ) ;
99103 const data = column . data ;
100104 const nyquist = Math . max ( 1 , sampleRate / 2 ) ;
101105 const F_MIN = 50 ; // Hz floor for display (avoid DC dominance)
102106 const fMin = Math . min ( nyquist * 0.9 , Math . max ( 1 , F_MIN ) ) ;
103107 const logDen = Math . log ( nyquist / fMin + 1e-12 ) ;
104108
105- for ( let y = 0 ; y < specHeight ; y ++ ) {
109+ for ( let y = 0 ; y < hDev ; y ++ ) {
106110 // Bottom low, top high with true log frequency scaling
107- const yTop = y / ( specHeight - 1 ) ; // 0 at top, 1 at bottom
111+ const yTop = y / ( hDev - 1 ) ; // 0 at top, 1 at bottom
108112 const yBottom = 1 - yTop ; // 0 at bottom? actually 0 at top; bottom=1
109113 const f = fMin * Math . exp ( yBottom * logDen ) ; // f in [fMin, nyquist]
110114 const k = Math . min ( bins - 1 , Math . floor ( ( f / nyquist ) * ( bins - 1 ) ) ) ;
@@ -122,7 +126,8 @@ export function drawSpectrogram(
122126 const o4 = y * 4 ; // top row index (no vertical flip; top shows low freqs)
123127 data [ o4 ] = rgb [ 0 ] ; data [ o4 + 1 ] = rgb [ 1 ] ; data [ o4 + 2 ] = rgb [ 2 ] ; data [ o4 + 3 ] = 255 ;
124128 }
125- ctx . putImageData ( column , specWidth - 1 , 0 ) ;
129+ ctx . putImageData ( column , wDev - 1 , 0 ) ;
130+ ctx . restore ( ) ;
126131}
127132
128133
0 commit comments