@@ -208,6 +208,91 @@ impl App {
208208 }
209209 }
210210
211+ fn tick_oscilloscope_time_domain_single_stereo (
212+ canvas : & mut Canvas < Window > ,
213+ screen_size : Coord ,
214+ scope_state : & ScopeState ,
215+ ui_state : & OscilloscopeUiState ,
216+ rgb : Rgb24 ,
217+ ) {
218+ // A zero crossing of the left channel will be centered in an attempt to stabalize the
219+ // visualization over time.
220+ let num_samples_to_draw = screen_size. x as usize ;
221+ // Take the mean so it can be used to identify the relative 0 crossing in case the waveform
222+ // has drifted above 0 mean.
223+ let left_mean = {
224+ let sum = scope_state. samples . iter ( ) . map ( |( x, _) | x) . sum :: < f32 > ( ) ;
225+ sum / ( scope_state. samples . len ( ) ) as f32
226+ } ;
227+ let mut samples_to_scan_for_zero_crossing = scope_state
228+ . samples
229+ . iter ( )
230+ . map ( |( x, _) | * x)
231+ . enumerate ( )
232+ . rev ( )
233+ // skip half a screen worth of samples
234+ . skip ( num_samples_to_draw / 2 ) ;
235+ let mut zero_crossing_index =
236+ scope_state. samples . len ( ) - num_samples_to_draw / 2 ;
237+ if let Some ( ( _, mut prev) ) = samples_to_scan_for_zero_crossing. next ( ) {
238+ for ( i, sample) in samples_to_scan_for_zero_crossing {
239+ if prev > left_mean && sample <= left_mean {
240+ zero_crossing_index = i;
241+ break ;
242+ }
243+ prev = sample;
244+ }
245+ }
246+ // Subtract half the screen width so that the crossing point is in the centre of the
247+ // screen.
248+ let left_most_sample = zero_crossing_index - num_samples_to_draw / 2 ;
249+ let make_sample_pair_iter =
250+ || scope_state. samples . iter ( ) . skip ( left_most_sample) ;
251+ let sample_left_iter = make_sample_pair_iter ( ) . map ( |( x, _) | x) ;
252+ let sample_right_iter = make_sample_pair_iter ( ) . map ( |( _, x) | x) ;
253+ canvas. set_draw_color ( Color :: RGBA ( rgb. r , rgb. g , rgb. b , 255 ) ) ;
254+ let mut prev = None ;
255+ for ( x, sample) in sample_left_iter. enumerate ( ) {
256+ let x = x as i32 ;
257+ let y = screen_size. y
258+ - ( ( sample * ui_state. scale ) as i32
259+ + ( ( 2 * screen_size. y ) / 3 ) ) ;
260+ let coord = Coord { x, y } ;
261+ if let Some ( prev) = prev {
262+ for Coord { x, y } in line_2d:: coords_between ( prev, coord) {
263+ let rect = Rect :: new (
264+ x,
265+ y,
266+ ui_state. line_width ,
267+ ui_state. line_width ,
268+ ) ;
269+ let _ = canvas. fill_rect ( rect) ;
270+ }
271+ }
272+ prev = Some ( coord) ;
273+ }
274+ let mut prev = None ;
275+ for ( x, sample) in sample_right_iter. enumerate ( ) {
276+ let x = x as i32 ;
277+ let y = screen_size. y
278+ - ( ( sample * ui_state. scale ) as i32
279+ + ( ( 1 * screen_size. y ) / 3 ) ) ;
280+ let coord = Coord { x, y } ;
281+ if let Some ( prev) = prev {
282+ for Coord { x, y } in line_2d:: coords_between ( prev, coord) {
283+ let rect = Rect :: new (
284+ x,
285+ y,
286+ ui_state. line_width ,
287+ ui_state. line_width ,
288+ ) ;
289+ let _ = canvas. fill_rect ( rect) ;
290+ }
291+ }
292+ prev = Some ( coord) ;
293+ }
294+ }
295+
211296 fn run_oscilloscope (
212297 mut self ,
213298 args : OscilloscopeCommand ,
@@ -322,65 +407,13 @@ impl App {
322407 ) ;
323408 }
324409 OscilloscopeStyle :: TimeDomainStereo => {
325- let num_samples_to_draw = screen_size. x as usize ;
326- let make_sample_pair_iter = || {
327- scope_state
328- . samples
329- . iter ( )
330- . rev ( )
331- . take ( num_samples_to_draw)
332- . rev ( )
333- } ;
334- let sample_left_iter =
335- make_sample_pair_iter ( ) . map ( |( x, _) | x) ;
336- let sample_right_iter =
337- make_sample_pair_iter ( ) . map ( |( _, x) | x) ;
338- self . canvas
339- . set_draw_color ( Color :: RGBA ( rgb. r , rgb. g , rgb. b , 255 ) ) ;
340- let mut prev = None ;
341- for ( x, sample) in sample_left_iter. enumerate ( ) {
342- let x = x as i32 ;
343- let y = screen_size. y
344- - ( ( sample * ui_state. scale ) as i32
345- + ( screen_size. y / 3 ) ) ;
346- let coord = Coord { x, y } ;
347- if let Some ( prev) = prev {
348- for Coord { x, y } in
349- line_2d:: coords_between ( prev, coord)
350- {
351- let rect = Rect :: new (
352- x,
353- y,
354- ui_state. line_width ,
355- ui_state. line_width ,
356- ) ;
357- let _ = self . canvas . fill_rect ( rect) ;
358- }
359- }
360- prev = Some ( coord) ;
361- }
362- let mut prev = None ;
363- for ( x, sample) in sample_right_iter. enumerate ( ) {
364- let x = x as i32 ;
365- let y = screen_size. y
366- - ( ( sample * ui_state. scale ) as i32
367- + ( ( 2 * screen_size. y ) / 3 ) ) ;
368- let coord = Coord { x, y } ;
369- if let Some ( prev) = prev {
370- for Coord { x, y } in
371- line_2d:: coords_between ( prev, coord)
372- {
373- let rect = Rect :: new (
374- x,
375- y,
376- ui_state. line_width ,
377- ui_state. line_width ,
378- ) ;
379- let _ = self . canvas . fill_rect ( rect) ;
380- }
381- }
382- prev = Some ( coord) ;
383- }
410+ Self :: tick_oscilloscope_time_domain_single_stereo (
411+ & mut self . canvas ,
412+ screen_size,
413+ & scope_state,
414+ & ui_state,
415+ rgb,
416+ ) ;
384417 }
385418 OscilloscopeStyle :: Xy => {
386419 let mut coord_iter =
0 commit comments