diff --git a/src/main.rs b/src/main.rs
index fac64cd..12f7da3 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -7,7 +7,7 @@ use {
     winit::event::{Event, WindowEvent},
     winit::event_loop::{ControlFlow, EventLoop},
     winit::window::WindowBuilder,
-    prisma::{Rgb,Hsv,FromColor},
+    prisma::{Rgb,Hsv,FromColor, Lerp},
     cgmath::{Point2, Vector2},
     std::time::Duration,
     angle::Turns
@@ -31,6 +31,9 @@ use crate::{
 #[derive(Clone)]
 struct Inputs {
     t: Duration,
+    transition_time: Duration,
+
+    scene_select: usize,
 
     intensity: f32,
     cycle_len: Duration,
@@ -78,16 +81,109 @@ impl ColorGrid for Anim2 {
     fn get(&self, p: &Vector2<f32>) -> Rgb<f32> {
         let inputs = self.inputs.read().unwrap().clone();
 //        let millis = self
+
+        let i = ( inputs.t.as_millis() as f32 / (4.0*inputs.cycle_len.as_millis() as f32) ) % 1.0;
+
         Rgb::from_color(
             &Hsv::<f32, Turns<f32>>::new(
-                Turns( 0.0 ),
+                Turns( i ),
                 0.5,
-                ( inputs.t.as_millis() as f32 / inputs.cycle_len.as_millis() as f32 ) % 1.0
+                (4.0*i) %1.0
             )
         )
     }
 }
 
+enum Waveform {
+    Sawtooth{ pulse_width: Duration },
+    Square{  },
+}
+
+struct Strobe {
+    inputs: Arc<RwLock< Inputs >>,
+    //waveform: Waveform,
+    subdivision: u32,
+}
+
+impl ColorGrid for Strobe {
+    fn get(&self, p: &Vector2<f32>) -> Rgb<f32> {
+        let inputs = self.inputs.read().unwrap().clone();
+
+        let t = (self.subdivision as f32 * inputs.t.as_millis() as f32 / inputs.cycle_len.as_millis() as f32) % 1.0;
+
+        if t < 0.6 {
+            Rgb::new(0.6, 0.6, 0.6)
+        } else {
+            Rgb::new(0.0, 0.0, 0.0)
+        }
+    }
+}
+
+
+pub struct SceneLibrary {
+    library: Vec< Box<dyn ColorGrid> >,
+    current_scene: RwLock<usize>,
+    inputs: Arc<RwLock< Inputs >>,
+
+    transition_length: Duration,
+//    transition_curve: enum { Constant, Linear, Sigmoid, Sinus }
+}
+
+impl SceneLibrary {
+    pub fn new( inputs: Arc<RwLock<Inputs>> ) -> Self {
+        SceneLibrary {
+            library: vec![
+                // 0
+                Box::new( Breathing{ inputs: inputs.clone() } ),
+
+                // 1 - 4
+                Box::new( Strobe{ inputs: inputs.clone(), subdivision: 4 } ),
+                Box::new( Strobe{ inputs: inputs.clone(), subdivision: 8 } ),
+                Box::new( Strobe{ inputs: inputs.clone(), subdivision: 12 } ),
+                Box::new( Strobe{ inputs: inputs.clone(), subdivision: 16 } ),
+
+                // others
+                Box::new( Anim2{ inputs: inputs.clone() } ),
+            ],
+            current_scene: RwLock::new(0),
+            inputs,
+            transition_length: Duration::from_millis(200),
+        }
+    }
+}
+
+impl ColorGrid for SceneLibrary {
+    fn get(&self, p: &Vector2<f32>) -> Rgb<f32> {
+        let inputs = self.inputs.read().unwrap().clone();
+
+        let sc = *self.current_scene.read().unwrap();
+
+        if inputs.scene_select == sc {
+            // display only one animation
+            self.library[ sc ].get(p)
+        } else {
+            // display transition
+            let cur_scene = &self.library[ sc ];
+            let nxt_scene = &self.library[ inputs.scene_select ];
+
+            // crossfade param
+            let w = ( inputs.transition_time.as_millis() as f32 / self.transition_length.as_millis() as f32 );
+
+            if w >= 1.0 {
+                // change own state:
+                *self.current_scene.write().unwrap() = inputs.scene_select;
+            }
+
+            cur_scene.get(p)
+                .lerp(
+                    &nxt_scene.get(p),
+                    w
+                )
+        }
+    }
+}
+
+
 #[async_std::main]
 async fn main() {
     let event_loop = EventLoop::new().unwrap();
@@ -100,14 +196,17 @@ async fn main() {
     let socket = Arc::new(RwLock::new(std::net::UdpSocket::bind("0.0.0.0:4210").expect("failed to bind UDP socket")));
     socket.write().unwrap().set_read_timeout(Some(std::time::Duration::from_millis(500)));
     socket.write().unwrap().set_write_timeout(Some(std::time::Duration::from_millis(50)));
-    
+
     let inputs = Arc::new(RwLock::new(
         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
         }
     ));
 
@@ -133,14 +232,13 @@ async fn main() {
                 .offset(Vector2::new(0.5, 0.0))
         ],
 
-        Box::new(
-            Anim2{ inputs: inputs.clone() }
-        )
+        Box::new( SceneLibrary::new(inputs.clone()) )
     );
 
-    let tbegin = std::time::Instant::now();
+    let mut tbegin = std::time::Instant::now();
+    let mut transition_begin = std::time::Instant::now();
     let mut last_tap = std::time::Instant::now();
-    
+
     event_loop.run(move |event, elwt| {
         let tcur = std::time::Instant::now();
         elwt.set_control_flow(ControlFlow::WaitUntil(
@@ -148,12 +246,11 @@ async fn main() {
         ));
 
         inputs.write().unwrap().t = tcur - tbegin;
+        inputs.write().unwrap().transition_time = tcur - transition_begin;
         lighting_setup.update_buffers();
         //lighting_setup.update_outputs();
 
         match event {
-            //Event::
-
             Event::WindowEvent { window_id, event: WindowEvent::RedrawRequested } if window_id == window.id() => {
                 let (width, height) = {
                     let size = window.inner_size();
@@ -178,12 +275,45 @@ async fn main() {
                         winit::keyboard::Key::Character(c) => {
                             eprintln!("pressed {}", c);
 
-                            if c == "x" {
-                                // tap tempo
-                                let old_tap = last_tap;
-                                last_tap = std::time::Instant::now();
+                            match &c[0..1] {
+                                "x" => {
+                                    // tap tempo
+                                    let old_tap = last_tap;
+                                    last_tap = std::time::Instant::now();
 
-                                inputs.write().unwrap().cycle_len = last_tap - old_tap;
+                                    if (last_tap - old_tap) < Duration::from_millis(20000) {
+                                        inputs.write().unwrap().cycle_len = last_tap - old_tap;
+                                    }
+                                }
+
+                                "q" => {
+                                    // sync
+                                    inputs.write().unwrap().t = Duration::from_millis(0);
+                                    tbegin = std::time::Instant::now();
+                                },
+
+                                "0" => {
+                                    inputs.write().unwrap().scene_select = 0;
+                                    transition_begin = std::time::Instant::now();
+                                }
+                                "1" => {
+                                    inputs.write().unwrap().scene_select = 1;
+                                    transition_begin = std::time::Instant::now();
+                                }
+                                "2" => {
+                                    inputs.write().unwrap().scene_select = 2;
+                                    transition_begin = std::time::Instant::now();
+                                }
+                                "3" => {
+                                    inputs.write().unwrap().scene_select = 3;
+                                    transition_begin = std::time::Instant::now();
+                                }
+                                "4" => {
+                                    inputs.write().unwrap().scene_select = 4;
+                                    transition_begin = std::time::Instant::now();
+                                }
+
+                                _=>{}
                             }
                         }
                         _ => {}