@@ -144,6 +144,70 @@ impl App {
144144 }
145145 }
146146
147+ fn tick_oscilloscope_time_domain_single (
148+ canvas : & mut Canvas < Window > ,
149+ screen_size : Coord ,
150+ scope_state : & ScopeState ,
151+ ui_state : & OscilloscopeUiState ,
152+ rgb : Rgb24 ,
153+ ) {
154+ let num_samples_to_draw = screen_size. x as usize ;
155+ // Take the mean so it can be used to identify the relative 0 crossing in case the waveform
156+ // has drifted above 0 mean.
157+ let mean = {
158+ let sum =
159+ scope_state. samples . iter ( ) . map ( |( x, y) | x + y) . sum :: < f32 > ( ) ;
160+ sum / ( scope_state. samples . len ( ) * 2 ) as f32
161+ } ;
162+ let mut samples_to_scan_for_zero_crossing = scope_state
163+ . samples
164+ . iter ( )
165+ . map ( |( x, y) | x + y / 2. )
166+ . enumerate ( )
167+ . rev ( )
168+ // skip half a screen worth of samples
169+ . skip ( num_samples_to_draw / 2 ) ;
170+ let mut zero_crossing_index =
171+ scope_state. samples . len ( ) - num_samples_to_draw / 2 ;
172+ if let Some ( ( _, mut prev) ) = samples_to_scan_for_zero_crossing. next ( ) {
173+ for ( i, sample) in samples_to_scan_for_zero_crossing {
174+ if prev > mean && sample <= mean {
175+ zero_crossing_index = i;
176+ break ;
177+ }
178+ prev = sample;
179+ }
180+ }
181+ // Subtract half the screen width so that the crossing point is in the centre of the
182+ // screen.
183+ let left_most_sample = zero_crossing_index - num_samples_to_draw / 2 ;
184+ let sample_mean_iter = scope_state
185+ . samples
186+ . iter ( )
187+ . skip ( left_most_sample)
188+ . map ( |( left, right) | ( left + right) / 2. ) ;
189+ canvas. set_draw_color ( Color :: RGBA ( rgb. r , rgb. g , rgb. b , 255 ) ) ;
190+ let mut prev = None ;
191+ for ( x, sample) in sample_mean_iter. enumerate ( ) {
192+ let x = x as i32 ;
193+ let y = screen_size. y
194+ - ( ( sample * ui_state. scale ) as i32 + ( screen_size. y / 2 ) ) ;
195+ let coord = Coord { x, y } ;
196+ if let Some ( prev) = prev {
197+ for Coord { x, y } in line_2d:: coords_between ( prev, coord) {
198+ let rect = Rect :: new (
199+ x,
200+ y,
201+ ui_state. line_width ,
202+ ui_state. line_width ,
203+ ) ;
204+ let _ = canvas. fill_rect ( rect) ;
205+ }
206+ }
207+ prev = Some ( coord) ;
208+ }
209+ }
210+
147211 fn run_oscilloscope (
148212 mut self ,
149213 args : OscilloscopeCommand ,
@@ -249,38 +313,13 @@ impl App {
249313 } ;
250314 match ui_state. style {
251315 OscilloscopeStyle :: TimeDomain => {
252- let num_samples_to_draw = screen_size. x as usize ;
253- let sample_mean_iter = scope_state
254- . samples
255- . iter ( )
256- . rev ( )
257- . take ( num_samples_to_draw)
258- . rev ( )
259- . map ( |( left, right) | ( left + right) / 2.0 ) ;
260- self . canvas
261- . set_draw_color ( Color :: RGBA ( rgb. r , rgb. g , rgb. b , 255 ) ) ;
262- let mut prev = None ;
263- for ( x, sample) in sample_mean_iter. enumerate ( ) {
264- let x = x as i32 ;
265- let y = screen_size. y
266- - ( ( sample * ui_state. scale ) as i32
267- + ( screen_size. y / 2 ) ) ;
268- let coord = Coord { x, y } ;
269- if let Some ( prev) = prev {
270- for Coord { x, y } in
271- line_2d:: coords_between ( prev, coord)
272- {
273- let rect = Rect :: new (
274- x,
275- y,
276- ui_state. line_width ,
277- ui_state. line_width ,
278- ) ;
279- let _ = self . canvas . fill_rect ( rect) ;
280- }
281- }
282- prev = Some ( coord) ;
283- }
316+ Self :: tick_oscilloscope_time_domain_single (
317+ & mut self . canvas ,
318+ screen_size,
319+ & scope_state,
320+ & ui_state,
321+ rgb,
322+ ) ;
284323 }
285324 OscilloscopeStyle :: TimeDomainStereo => {
286325 let num_samples_to_draw = screen_size. x as usize ;
0 commit comments