This commit is contained in:
2021-10-28 03:07:03 +02:00
parent 5a71aa2cf0
commit 763aa23ca8
9 changed files with 302 additions and 35 deletions

View File

@@ -0,0 +1,24 @@
use super::OutputLayer;
pub struct ConstantBrightness {
pub brightness: f32,
}
impl OutputLayer for ConstantBrightness {
fn tick(&mut self, _dt: std::time::Duration) {}
fn draw_sdl(
&self,
_canvas: &mut sdl2::render::Canvas<sdl2::video::Window>,
_texture_size: u32,
) {
}
fn on_sdl_event(&mut self, _event: &sdl2::event::Event) {}
fn update_dmx(&self, output: &mut [crate::fixtures::MovingHead; 4]) {
for head in output.iter_mut() {
head.dimmer = self.brightness;
}
}
}

View File

@@ -32,7 +32,7 @@ impl OutputLayer for HSLCycle {
0.5,
)
.into_color();
self.rgb = hsl.into_format().into_raw();
}
@@ -42,9 +42,7 @@ impl OutputLayer for HSLCycle {
canvas.fill_rect(Rect::new(0, 0, 5, 5)).unwrap();
}
fn on_sdl_event(&mut self, _event: &sdl2::event::Event) {
}
fn on_sdl_event(&mut self, _event: &sdl2::event::Event) {}
fn update_dmx(&self, output: &mut [crate::fixtures::MovingHead; 4]) {
let [r, g, b] = self.rgb;

View File

@@ -1,5 +1,8 @@
pub mod hsl_cycle;
pub mod beat_detector;
pub mod constant_brightness;
pub mod hsl_cycle;
pub mod movement;
pub mod tap;
use std::time::Duration;
@@ -11,8 +14,8 @@ pub trait OutputLayer {
fn tick(&mut self, dt: Duration);
fn draw_sdl(&self, canvas: &mut Canvas<Window>, texture_size: u32);
fn on_sdl_event(&mut self, event: &Event);
fn update_dmx(&self, output: &mut [MovingHead; 4]);
}
}

View File

@@ -0,0 +1,78 @@
use std::{
f32::consts::PI,
time::{Duration, Instant},
};
use rand::random;
use sdl2::{event::Event, keyboard::Keycode};
use crate::util::rescale;
use super::OutputLayer;
pub struct HeadMover {
movement_duration: Duration,
last_timestamp: Instant,
targets: [(f32, f32); 4],
}
impl HeadMover {
pub fn new(movement_duration: Duration) -> Self {
Self {
movement_duration,
last_timestamp: Instant::now() - movement_duration,
targets: Default::default(),
}
}
}
fn sample_random_point() -> (f32, f32) {
let pan = rescale(random::<f32>(), (0.0, 1.0), (-0.5 * PI, 0.5 * PI));
let tilt = random::<f32>().acos();
(pan, tilt)
}
impl OutputLayer for HeadMover {
fn tick(&mut self, _dt: Duration) {
let now = Instant::now();
if now - self.last_timestamp >= self.movement_duration {
for target in self.targets.iter_mut() {
*target = sample_random_point();
}
self.last_timestamp = now;
}
}
fn draw_sdl(
&self,
_canvas: &mut sdl2::render::Canvas<sdl2::video::Window>,
_texture_size: u32,
) {
}
fn on_sdl_event(&mut self, event: &sdl2::event::Event) {
match event {
Event::KeyDown {
keycode: Some(Keycode::Return),
..
} => {
let now = Instant::now();
for target in self.targets.iter_mut() {
*target = sample_random_point();
}
self.last_timestamp = now;
}
_ => {}
}
}
fn update_dmx(&self, output: &mut [crate::fixtures::MovingHead; 4]) {
for (head, target) in output.iter_mut().zip(self.targets.iter()) {
let (pan, tilt) = target;
head.pan = *pan;
head.tilt = *tilt;
}
}
}

View File

@@ -0,0 +1,102 @@
use std::{
collections::VecDeque,
time::{Duration, Instant},
};
use sdl2::{event::Event, keyboard::Keycode, pixels::Color};
use super::OutputLayer;
pub struct TapMetronome {
max_time: Duration,
timestamps: VecDeque<Instant>,
seconds_per_beat: Option<f32>,
brightness: f32,
decay: f32,
}
impl TapMetronome {
pub fn new(max_time: Duration) -> Self {
Self {
max_time,
timestamps: VecDeque::new(),
seconds_per_beat: None,
brightness: 0.0,
decay: 1.0,
}
}
}
impl OutputLayer for TapMetronome {
fn tick(&mut self, _dt: std::time::Duration) {
let now = Instant::now();
if let (Some(stamp), Some(spb)) = (self.timestamps.back(), self.seconds_per_beat) {
let dt = (now - *stamp).as_secs_f32();
let beat_offset = dt % spb;
self.brightness = (-1.0 * self.decay * beat_offset).exp()
} else {
self.brightness = 0.0;
}
}
fn draw_sdl(&self, canvas: &mut sdl2::render::Canvas<sdl2::video::Window>, _texture_size: u32) {
let v = (255.0 * self.brightness) as u8;
canvas.set_draw_color(Color::RGB(v, v, v));
canvas.clear();
}
fn on_sdl_event(&mut self, event: &sdl2::event::Event) {
match event {
Event::KeyDown {
keycode: Some(Keycode::Space),
..
} => {
let now = Instant::now();
while let Some(stamp) = self.timestamps.front() {
if now - *stamp < self.max_time {
break;
}
self.timestamps.pop_front();
}
self.timestamps.push_back(now);
if self.timestamps.len() >= 2 {
let dt = *self.timestamps.back().unwrap() - *self.timestamps.front().unwrap();
let spb = dt.as_secs_f32() / (self.timestamps.len() - 1) as f32;
println!("Detected BPM: {:.2}", 60.0 / spb);
self.seconds_per_beat = Some(spb);
} else {
self.seconds_per_beat = None;
}
}
Event::KeyDown {
keycode: Some(Keycode::Down),
..
} => {
self.decay += 0.1;
println!("Decay: {:.3}", self.decay)
}
Event::KeyDown {
keycode: Some(Keycode::Up),
..
} => {
self.decay -= 0.1;
println!("Decay: {:.3}", self.decay)
}
_ => {}
}
}
fn update_dmx(&self, output: &mut [crate::fixtures::MovingHead; 4]) {
for head in output.iter_mut() {
head.dimmer = 0.2 + 0.8 * self.brightness;
}
}
}