From 1b94695d5778e19e39f99c87cc342850abfb905b Mon Sep 17 00:00:00 2001 From: Michael Sippel Date: Thu, 2 May 2024 22:19:17 +0200 Subject: [PATCH] master wave --- src/main.rs | 89 ++++++++++++++++++++++++++------------- src/patterns/alternate.rs | 2 +- src/patterns/mod.rs | 4 +- src/patterns/wave_fade.rs | 43 +++++++++++++++++++ src/scene_library.rs | 32 +++++++++++++- src/waveform.rs | 37 ++++++++++++++++ 6 files changed, 173 insertions(+), 34 deletions(-) create mode 100644 src/patterns/wave_fade.rs create mode 100644 src/waveform.rs diff --git a/src/main.rs b/src/main.rs index 3b079e1..28fa5b7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,6 +19,7 @@ mod setup; mod view; mod stripe_driver; mod jack; +mod waveform; mod patterns; mod scene_library; @@ -30,21 +31,24 @@ use crate::{ stripe_driver::StripeDriver, util::get_angle, - scene_library::SceneLibrary + scene_library::SceneLibrary, + waveform::Waveform }; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct Inputs { t: Duration, transition_time: Duration, scene_select: usize, - - intensity: f32, cycle_len: Duration, - wave_peak: f32, - wheel: i32 + + master_wave: Option< Waveform >, + master_subdivision: i32, + master_intensity: f32, + wheel: i32, + wheel2: i32, } #[async_std::main] @@ -64,13 +68,16 @@ async fn main() { Inputs { t: Duration::from_millis(0), transition_time: Duration::from_millis(0), - - intensity: 0.5, cycle_len: Duration::from_millis(300), wave_peak: 0.5, scene_select: 0, - wheel: 0 + + master_wave: None, + master_subdivision: 0, + master_intensity: 1.0, + wheel: 0, + wheel2: 0 } )); @@ -118,7 +125,7 @@ async fn main() { lighting_setup.update_buffers(); if active { - for i in 1..4 { + for i in 1..5 { lighting_setup.update_outputs(i); } } @@ -148,6 +155,7 @@ async fn main() { winit::keyboard::Key::Character(c) => { eprintln!("pressed {}", c); + let mut inputs = inputs.write().unwrap(); match &c[0..1] { "x" => { // tap tempo @@ -155,61 +163,84 @@ async fn main() { last_tap = std::time::Instant::now(); if (last_tap - old_tap) < Duration::from_millis(20000) { - inputs.write().unwrap().cycle_len = last_tap - old_tap; + inputs.cycle_len = last_tap - old_tap; } } "q" => { // sync - inputs.write().unwrap().t = Duration::from_millis(0); + inputs.t = Duration::from_millis(0); tbegin = std::time::Instant::now(); }, "0" => { - inputs.write().unwrap().scene_select = 0; + inputs.scene_select = 0; transition_begin = std::time::Instant::now(); } "1" => { - inputs.write().unwrap().scene_select = 1; + inputs.scene_select = 1; transition_begin = std::time::Instant::now(); } "2" => { - inputs.write().unwrap().scene_select = 2; + inputs.scene_select = 2; transition_begin = std::time::Instant::now(); } "3" => { - inputs.write().unwrap().scene_select = 3; + inputs.scene_select = 3; transition_begin = std::time::Instant::now(); } "4" => { - inputs.write().unwrap().scene_select = 4; + inputs.scene_select = 4; transition_begin = std::time::Instant::now(); } "5" => { - inputs.write().unwrap().scene_select = 5; + inputs.scene_select = 5; transition_begin = std::time::Instant::now(); }, "6" => { - inputs.write().unwrap().scene_select = 6; + inputs.scene_select = 6; transition_begin = std::time::Instant::now(); } "7" => { - inputs.write().unwrap().scene_select = 7; + inputs.scene_select = 7; transition_begin = std::time::Instant::now(); } "8" => { - inputs.write().unwrap().scene_select = 8; + inputs.scene_select = 8; transition_begin = std::time::Instant::now(); } "9" => { - inputs.write().unwrap().scene_select = 9; + inputs.scene_select = 9; transition_begin = std::time::Instant::now(); } "a" => { - inputs.write().unwrap().scene_select = 10; + inputs.scene_select = 10; transition_begin = std::time::Instant::now(); } - "m" => { + "p" => { + inputs.scene_select = 11; + transition_begin = std::time::Instant::now(); + } + "r" => { inputs.master_wave = match inputs.master_wave { + None => Some(Waveform::Sine), + Some(Waveform::Sine) => Some(Waveform::Triangle), + Some(Waveform::Triangle) => Some(Waveform::Square), + Some(Waveform::Square) => Some(Waveform::Sawtooth), + Some(Waveform::Sawtooth) => None + } + } + "," => { inputs.master_wave = None; } + "n" => { inputs.master_intensity += 0.1; } + "m" => { inputs.master_intensity -= 0.1; } + "s" => { inputs.master_subdivision +=1; } + "b" => { inputs.master_subdivision -=1; } + "o" => { inputs.wheel +=1; } + "z" => { inputs.wheel -=1; } + "e" => { inputs.wheel2 += 1; } + "p"=> { inputs.wheel2 -= 1; } + + "-" => {inputs.master_intensity *= -1.0; } + "." => { if active { eprintln!("DEACTIVATED"); active = false; @@ -218,15 +249,13 @@ async fn main() { eprintln!("ACTIVATED"); } } - "+" => { - inputs.write().unwrap().wheel +=1; - } - "-" => { - inputs.write().unwrap().wheel -=1; - } _=>{} } + + eprintln!("--------------"); + eprintln!("updated inputs:\n {:?}", inputs); + eprintln!("--------------"); } _ => {} } diff --git a/src/patterns/alternate.rs b/src/patterns/alternate.rs index 2e4f3dd..52f57d8 100644 --- a/src/patterns/alternate.rs +++ b/src/patterns/alternate.rs @@ -35,7 +35,7 @@ impl ColorGrid for Alternate { if t < 0.5 { Rgb::new(0.05, 0.05, 0.05) } else { - Rgb::new(0.3, 0.3, 0.6) + Rgb::new(0.0, 0.0, 0.6) } } diff --git a/src/patterns/mod.rs b/src/patterns/mod.rs index 98529f0..ea1796a 100644 --- a/src/patterns/mod.rs +++ b/src/patterns/mod.rs @@ -5,6 +5,7 @@ pub mod arctic_rain; pub mod pastel_fade; pub mod gastel_fade; pub mod wheel; +pub mod wave_fade; pub mod alternate; #[path = "uboot_prüfstand_fade.rs"] @@ -16,9 +17,10 @@ pub use { arctic_rain::ArcticRain, pastel_fade::PastelFade, gastel_fade::GastelFade, + wave_fade::WaveFade, uboot::UbootPrüfstandFade, wheel::Wheel, alternate::Alternate }; - + diff --git a/src/patterns/wave_fade.rs b/src/patterns/wave_fade.rs new file mode 100644 index 0000000..d71643f --- /dev/null +++ b/src/patterns/wave_fade.rs @@ -0,0 +1,43 @@ +use { + std::num::NonZeroU32, + std::sync::{Arc, RwLock, Mutex}, + std::rc::Rc, + winit::event::{Event, WindowEvent}, + winit::event_loop::{ControlFlow, EventLoop}, + winit::window::WindowBuilder, + prisma::{Rgb,Hsv,FromColor, Lerp}, + cgmath::{Point2, Vector2}, + std::time::Duration, + angle::Turns, + + crate::{Inputs, view::ColorGrid, util::get_angle, waveform::Waveform} +}; + +pub struct WaveFade { pub inputs: Arc>, + pub hue: f32, +} + +impl ColorGrid for WaveFade { + fn get(&self, p: &Vector2) -> Rgb { + let inputs = self.inputs.read().unwrap().clone(); + + let nt = ( inputs.t.as_millis() as f32 / inputs.cycle_len.as_millis() as f32 ); + + let i = + match inputs.wheel % 4 { + 0 => Waveform::Sine{}.get_norm(nt), + 1 => Waveform::Triangle{}.get_norm(nt), + 2 => Waveform::Sawtooth{}.get_norm(nt), + 3 => Waveform::Square{}.get_norm(nt), + _ => 0.0 + }; + + Rgb::from_color( + &Hsv::>::new( + Turns( self.hue ), + 0.5, + i + ) + ) + } +} diff --git a/src/scene_library.rs b/src/scene_library.rs index 3c703c1..a6c2490 100644 --- a/src/scene_library.rs +++ b/src/scene_library.rs @@ -39,7 +39,7 @@ impl SceneLibrary { Box::new( Strobe{ inputs: inputs.clone(), subdivision: 16 } ), // others - Box::new( PastelFade{ inputs: inputs.clone() } ), + Box::new( WaveFade{ inputs: inputs.clone(), hue: 0.5 } ), Box::new( UbootPrüfstandFade{ inputs: inputs.clone() } ), Box::new( ArcticRain{ inputs: inputs.clone() } ), @@ -48,6 +48,7 @@ impl SceneLibrary { Box::new( Alternate{ inputs: inputs.clone() } ), + Box::new( PastelFade{ inputs: inputs.clone() } ), ], current_scene: RwLock::new(0), inputs, @@ -62,9 +63,35 @@ impl ColorGrid for SceneLibrary { let sc = *self.current_scene.read().unwrap(); + let mut intensity: f32 = inputs.master_intensity; + if intensity > 1.0 { + intensity = 1.0; + } + if intensity < -1.0 { + intensity = -1.0; + } + + if let Some(w) = inputs.master_wave { + intensity *= w.get_doub( + inputs.t.as_millis() as f32 + / inputs.cycle_len.as_millis() as f32 + ); + } + + if inputs.scene_select == sc { // display only one animation - self.library[ sc ].get(p) + let mut hsv = Hsv::from_color( + &self.library[ sc ].get(p) + ); + + hsv = Hsv::::new( + hsv.hue(), + hsv.saturation(), + hsv.value() * (0.5 + 0.5*intensity) + ); + + Rgb::from_color(&hsv) } else { // display transition let cur_scene = &self.library[ sc ]; @@ -83,6 +110,7 @@ impl ColorGrid for SceneLibrary { &nxt_scene.get(p), w ) + } } } diff --git a/src/waveform.rs b/src/waveform.rs new file mode 100644 index 0000000..7c7527a --- /dev/null +++ b/src/waveform.rs @@ -0,0 +1,37 @@ + +#[derive(Clone, Debug)] +pub enum Waveform { + Triangle, + Sawtooth, + Square, + Sine, +} + +impl Waveform { + pub fn get_doub(&self, x: f32) -> f32 { + self.get_norm(x) * 2.0 - 1.0 + } + + pub fn get_norm(&self, x: f32) -> f32 { + match self { + Waveform::Sine => 0.5 + 0.5*(x * 2.0*3.1415926).sin(), + Waveform::Square => + if x % 1.0 < 0.5 { + 0.0 + } else { + 1.0 + } + Waveform::Sawtooth => { + x % 1.0 + } + Waveform::Triangle => { + if (x%1.0) > 0.5 { + 1.0-(x%1.0) + } else { + x%1.0 + } + } + } + } +} +