diff --git a/src/app.rs b/src/app.rs index 7303c59..283205c 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,11 +1,25 @@ use eframe::{egui_glow, glow}; use egui::mutex::Mutex; +use std::sync::mpsc; use std::sync::Arc; mod waterfall; use waterfall::Waterfall; pub mod turbo_colormap; +mod deadbeef_rand { + static mut RNG_SEED: u32 = 0x3d2faba7; + static mut RNG_BEEF: u32 = 0xdeadbeef; + pub fn rand() -> u8 { + unsafe { + RNG_SEED = (RNG_SEED << 7) ^ ((RNG_SEED >> 25).wrapping_add(RNG_BEEF)); + RNG_BEEF = (RNG_BEEF << 7) ^ ((RNG_BEEF >> 25).wrapping_add(0xdeadbeef)); + (RNG_SEED & 0xff) as u8 + } + } +} +use deadbeef_rand::rand; + /// We derive Deserialize/Serialize so we can persist app state on shutdown. pub struct TemplateApp { // Example stuff: @@ -13,6 +27,7 @@ pub struct TemplateApp { value: f32, /// Behind an `Arc>` so we can pass it to [`egui::PaintCallback`] and paint later. waterfall: Arc>, + fft_sender: mpsc::Sender>, } impl TemplateApp { @@ -24,6 +39,7 @@ impl TemplateApp { // Load previous app state (if any). // Note that you must enable the `persistence` feature for this to work. + let (tx, rx) = mpsc::channel(); let gl = cc .gl .as_ref() @@ -33,7 +49,8 @@ impl TemplateApp { // Example stuff: label: "Hello World!".to_owned(), value: 2.7, - waterfall: Arc::new(Mutex::new(Waterfall::new(gl, 300, 300))), + waterfall: Arc::new(Mutex::new(Waterfall::new(gl, 300, 300, rx))), + fft_sender: tx, } } } @@ -104,6 +121,12 @@ impl eframe::App for TemplateApp { let _angle = response.drag_motion().x * 0.01; + let mut new_data = vec![0_u8; 300]; + for data in new_data.iter_mut() { + *data = rand(); + } + self.fft_sender.send(new_data).unwrap(); + // Clone locals so we can move them into the paint callback: let waterfall = self.waterfall.clone(); diff --git a/src/app/waterfall.rs b/src/app/waterfall.rs index 4d8b6f1..0f95995 100644 --- a/src/app/waterfall.rs +++ b/src/app/waterfall.rs @@ -3,6 +3,7 @@ use glow::HasContext as _; use glow::{NEAREST, TEXTURE_2D, TEXTURE_MAG_FILTER, TEXTURE_MIN_FILTER}; use log; use std::mem::{size_of, transmute}; +use std::sync::mpsc::Receiver; const SIZE_OF_F32: i32 = size_of::() as i32; @@ -15,19 +16,6 @@ unsafe fn check_for_gl_errors(gl: &glow::Context, msg: &str) { } } -mod deadbeef_rand { - static mut RNG_SEED: u32 = 0x3d2faba7; - static mut RNG_BEEF: u32 = 0xdeadbeef; - pub fn rand() -> u8 { - unsafe { - RNG_SEED = (RNG_SEED << 7) ^ ((RNG_SEED >> 25).wrapping_add(RNG_BEEF)); - RNG_BEEF = (RNG_BEEF << 7) ^ ((RNG_BEEF >> 25).wrapping_add(0xdeadbeef)); - (RNG_SEED & 0xff) as u8 - } - } -} -use deadbeef_rand::rand; - use crate::app::turbo_colormap; pub struct Waterfall { @@ -38,6 +26,8 @@ pub struct Waterfall { vbo: glow::Buffer, ebo: glow::Buffer, offset: usize, + width: usize, + fft_in: Receiver>, } impl Waterfall { @@ -54,11 +44,6 @@ impl Waterfall { pub fn paint(&mut self, gl: &glow::Context, _angle: f32) { use glow::HasContext as _; - let mut new_data: [u8; 300] = [0; 300]; - for data in new_data.iter_mut() { - *data = rand(); - } - unsafe { // Bind our texturs gl.active_texture(TEXTURE1); @@ -80,22 +65,27 @@ impl Waterfall { check_for_gl_errors(&gl, "bind vao"); // Update texture - gl.tex_sub_image_2d( - glow::TEXTURE_2D, - 0, - 0, - self.offset as i32, - 300, - 1, - glow::RED, - glow::UNSIGNED_BYTE, - PixelUnpackData::Slice(&new_data), - ); - check_for_gl_errors(&gl, "update texture"); - self.offset = (self.offset + 1) % 300; + while let Ok(fft) = self.fft_in.try_recv() { + if fft.len() != self.width { + todo!(); + } + gl.tex_sub_image_2d( + glow::TEXTURE_2D, + 0, + 0, + self.offset as i32, + self.width as i32, + 1, + glow::RED, + glow::UNSIGNED_BYTE, + PixelUnpackData::Slice(&fft), + ); + check_for_gl_errors(&gl, "update texture"); + self.offset = (self.offset + 1) % self.width; + } if let Some(uniform) = gl.get_uniform_location(self.program, "offset") { - gl.uniform_1_f32(Some(&uniform), self.offset as f32 / 300.0); + gl.uniform_1_f32(Some(&uniform), self.offset as f32 / self.width as f32); } check_for_gl_errors(&gl, "update uniform"); @@ -106,7 +96,7 @@ impl Waterfall { check_for_gl_errors(&gl, "APP PAINT"); } } - pub fn new(gl: &glow::Context, width: usize, height: usize) -> Self { + pub fn new(gl: &glow::Context, width: usize, height: usize, fft_in: Receiver>) -> Self { let vertices: [f32; 32] = [ // positions // colors // texture coords 1.0, 1.0, 0.0, /**/ 1.0, 0.0, 0.0, /**/ 1.0, 1.0, // top right @@ -320,6 +310,8 @@ impl Waterfall { vbo, ebo, offset: 0_usize, + width, + fft_in, } } }