pub fn update_waveform( rgba: &mut crate::Rgba, samples: (&Vec, &Vec), resolution: f32 ) { let (left_samples, right_samples) = samples; let mut last_rows = ((rgba.height/2) as usize, (rgba.height/2) as usize); let span = (rgba.width as f32 * resolution) as usize; let moved_start = rgba.width as usize - span; if resolution < 1.0 { let mut previous_left_row = (rgba.height as usize, 0usize); let mut previous_right_row = (rgba.height as usize, 0usize); for row in 0..rgba.height as usize { // Get min/max left/right values for last column looking in each row let last_pixel_idx = (((row+1)*rgba.width as usize)-1)*4; let last_row_pixel = &rgba.pixels[last_pixel_idx..last_pixel_idx+4]; // LEFT if last_row_pixel[2] == 0 { if row < previous_left_row.0 { previous_left_row.0 = row; } if row > previous_left_row.1 { previous_left_row.1 = row; } } // RIGHT if last_row_pixel[0] == 0 { if row < previous_right_row.0 { previous_right_row.0 = row; } if row > previous_right_row.1 { previous_right_row.1 = row; } } let row_offset = row * rgba.width as usize*4; // Translate image to the left // |--^#####^xx| => |#####^xx^xx| let moved_slice : Vec = rgba.pixels[row_offset+span*4..row_offset+rgba.width as usize*4].into(); rgba.pixels[row_offset..row_offset+moved_start*4].copy_from_slice(&moved_slice); // |#####^xx^xx| => |#####^xx^ | let blank = vec![255; span*4]; rgba.pixels[row_offset+moved_start*4..row_offset+rgba.width as usize*4].copy_from_slice(&blank); } // Set function scoped last rows if previous_left_row.0 != rgba.height as usize && previous_left_row.1 != 0 { last_rows.0 = if (previous_left_row.0 as f32 - 128f32).abs() < (previous_left_row.1 as f32 - 128f32).abs() {previous_left_row.0} else {previous_left_row.1}; } if previous_right_row.0 != rgba.height as usize && previous_right_row.1 != 0 { last_rows.1 = if (previous_right_row.0 as f32 - 128f32).abs() < (previous_right_row.1 as f32 - 128f32).abs() {previous_right_row.0} else {previous_right_row.1}; } } else { rgba.pixels.fill(255); } let left_column_width : usize = left_samples.len() / span; let right_column_width : usize = right_samples.len() / span; for x in 0..span { // LEFT CHANNEL let column_values : &[f32] = &left_samples[x*left_column_width..(x+1)*left_column_width]; let column_average : f32 = (column_values.iter().cloned().reduce(|acc, v| acc+v).unwrap_or(0f32) / column_values.len() as f32).clamp(-0.99, 0.99); let row = (128f32 - (column_average * 128f32)).round() as usize; // Draw vertical lines from last row let range : Vec = if row <= last_rows.0 {(row..=last_rows.0).collect()} else {(last_rows.0..=row).rev().collect()}; for row in range { let coord = (row * rgba.width as usize * 4) + ((moved_start + x) * 4); rgba.pixels[coord+0] = 0; rgba.pixels[coord+1] = 0; } last_rows.0 = row; // RIGHT CHANNEL let column_values : &[f32] = &right_samples[x*right_column_width..(x+1)*right_column_width]; let column_average : f32 = (column_values.iter().cloned().reduce(|acc, v| acc+v).unwrap_or(0f32) / column_values.len() as f32).clamp(-0.99, 0.99); let row = (128f32 - (column_average * 128f32)).round() as usize; // Draw vertical lines from last row let range : Vec = if row <= last_rows.1 {(row..=last_rows.1).collect()} else {(last_rows.1..=row).rev().collect()}; for row in range { let coord = (row * rgba.width as usize * 4) + ((moved_start + x) * 4); rgba.pixels[coord+1] = 0; rgba.pixels[coord+2] = 0; } last_rows.1 = row; } }