From de2b0593aeca7da3d1e7aa962eee49635d3d194a Mon Sep 17 00:00:00 2001 From: Patrick Moessler <pub@asaril.de> Date: Sat, 22 Mar 2025 00:59:47 +0100 Subject: [PATCH] separate effects --- src/effects/bass_hi_beat_strobe.rs | 114 +++++++++++++++++++++++++++++ src/effects/bass_hue_fade.rs | 67 +++++++++++++++++ src/effects/bass_sparks.rs | 23 ++++-- src/effects/mod.rs | 4 +- src/main.rs | 7 +- 5 files changed, 205 insertions(+), 10 deletions(-) create mode 100644 src/effects/bass_hi_beat_strobe.rs create mode 100644 src/effects/bass_hue_fade.rs diff --git a/src/effects/bass_hi_beat_strobe.rs b/src/effects/bass_hi_beat_strobe.rs new file mode 100644 index 0000000..c1d1bfc --- /dev/null +++ b/src/effects/bass_hi_beat_strobe.rs @@ -0,0 +1,114 @@ +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_time::{Duration, Ticker}; + +use crate::audio_process::{AudioStats, DspBuffer}; +use crate::effects::led_effect::{LedColors, LedData, LedEffect, Rgbv}; +use crate::triple_buffer::{Receiver, Sender}; +use crate::LED_COUNT; + +pub struct LedEffectBassHiBeatStrobe { + bass_color_hue: u32, + bass_color_fill: Rgbv, + hi_beat: u8, +} +impl Default for LedEffectBassHiBeatStrobe { + fn default() -> Self { + Self { + bass_color_hue: 300, + bass_color_fill: Rgbv::black(0), + hi_beat: 0, + } + } +} +impl LedEffect for LedEffectBassHiBeatStrobe { + fn render( + &mut self, + _: bool, + _: &DspBuffer, + stats: &AudioStats, + leds: &mut LedColors, + ) -> Duration { + if stats.floating_max > 10100000 && (stats.current_powers[0] > 1.25 * stats.avg_powers[0]) { + self.bass_color_fill = Rgbv::from_hsv(self.bass_color_hue, 100, 100, 1).unwrap(); + } + + leds.fill(self.bass_color_fill); + + // for i in 0..32 { + // leds[i] = self.bass_color_fill.with_o(Rgbv::MAX_O - i as u8); + // leds[LED_COUNT-1-i] = self.bass_color_fill.with_o(Rgbv::MAX_O - i as u8); + // } + + self.bass_color_fill.decrease( + std::cmp::max(self.bass_color_fill.r / 4, 1), + std::cmp::max(self.bass_color_fill.g / 4, 1), + std::cmp::max(self.bass_color_fill.b / 4, 1), + 0, + ); + + if stats.floating_max > 10100000 + && (stats.current_powers[1] > 1.35 * stats.avg_powers[1]) + && (stats.current_powers[2] > 1.35 * stats.avg_powers[2]) + { + // for led_index in LED_COUNT / 2 - 4..LED_COUNT / 2 + 4 { + // leds[led_index] = Rgbv::white(31); + // } + + // let mut tmp = LED_COUNT / 2 - 4..LED_COUNT / 2 + 4; + // while let Some(led_index) = tmp.next() { + // leds[led_index] = Rgbv::white(31); + // } + + // for led in leds + // .iter_mut() + // .take(LED_COUNT / 2 + 4) + // .skip(LED_COUNT / 2 - 4) + // { + // *led = Rgbv::white(31); + // } + + // for _ in 0..20 { + // let led_index = random_at_most(LED_COUNT as u32 - 1) as usize; + // leds[led_index] = Rgbv::white(31); + // } + self.hi_beat = 6; + } + + if self.hi_beat > 0 { + (LED_COUNT / 2 - 8..LED_COUNT / 2 + 8).for_each(|led_index| { + leds[led_index] = if self.hi_beat % 2 == 0 { + Rgbv::black(0) + } else { + Rgbv::white(31) + } + }); + self.hi_beat -= 1; + } + + self.bass_color_hue = (self.bass_color_hue + 1) % 360; + + Duration::from_hz(50) + } + + async fn process_led_effect( + &mut self, + mut input: Receiver<'static, NoopRawMutex, (DspBuffer, AudioStats)>, + mut output: Sender<'static, NoopRawMutex, LedData>, + ) { + let mut set_interval = Duration::from_hz(100); + let mut ticker = Ticker::every(set_interval); + loop { + let ((fft, stats), was_new) = input.receive_cached().await; + let leds = output.send().await; + + let interval = self.render(was_new, fft, stats, &mut leds.leds); + output.send_done(); + + if set_interval != interval { + set_interval = interval; + ticker = Ticker::every(set_interval); + } + ticker.next().await; + } + } +} diff --git a/src/effects/bass_hue_fade.rs b/src/effects/bass_hue_fade.rs new file mode 100644 index 0000000..272a84a --- /dev/null +++ b/src/effects/bass_hue_fade.rs @@ -0,0 +1,67 @@ +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_time::{Duration, Ticker}; + +use crate::audio_process::{AudioStats, DspBuffer}; +use crate::effects::led_effect::{LedColors, LedData, LedEffect, Rgbv}; +use crate::triple_buffer::{Receiver, Sender}; + +pub struct LedEffectBassHueFade { + bass_color_hue: u32, + bass_color_fill: Rgbv, +} +impl Default for LedEffectBassHueFade { + fn default() -> Self { + Self { + bass_color_hue: 300, + bass_color_fill: Rgbv::black(0), + } + } +} +impl LedEffect for LedEffectBassHueFade { + fn render( + &mut self, + _: bool, + _: &DspBuffer, + stats: &AudioStats, + leds: &mut LedColors, + ) -> Duration { + if stats.floating_max > 10100000 && (stats.current_powers[0] > 1.25 * stats.avg_powers[0]) { + self.bass_color_fill = Rgbv::from_hsv(self.bass_color_hue, 100, 100, 1).unwrap(); + } + + leds.fill(self.bass_color_fill); + + self.bass_color_fill.decrease( + std::cmp::max(self.bass_color_fill.r / 4, 1), + std::cmp::max(self.bass_color_fill.g / 4, 1), + std::cmp::max(self.bass_color_fill.b / 4, 1), + 0, + ); + + self.bass_color_hue = (self.bass_color_hue + 1) % 360; + + Duration::from_hz(50) + } + + async fn process_led_effect( + &mut self, + mut input: Receiver<'static, NoopRawMutex, (DspBuffer, AudioStats)>, + mut output: Sender<'static, NoopRawMutex, LedData>, + ) { + let mut set_interval = Duration::from_hz(100); + let mut ticker = Ticker::every(set_interval); + loop { + let ((fft, stats), was_new) = input.receive_cached().await; + let leds = output.send().await; + + let interval = self.render(was_new, fft, stats, &mut leds.leds); + output.send_done(); + + if set_interval != interval { + set_interval = interval; + ticker = Ticker::every(set_interval); + } + ticker.next().await; + } + } +} diff --git a/src/effects/bass_sparks.rs b/src/effects/bass_sparks.rs index 598745b..c044a7d 100644 --- a/src/effects/bass_sparks.rs +++ b/src/effects/bass_sparks.rs @@ -8,12 +8,14 @@ use crate::triple_buffer::{Receiver, Sender}; use crate::LED_COUNT; pub struct LedEffectBassSparks { - bass_color: Rgbv, + bass_color_hue: u32, + bass_color_fill: Rgbv, } impl Default for LedEffectBassSparks { fn default() -> Self { Self { - bass_color: Rgbv::black(0), + bass_color_hue: 300, + bass_color_fill: Rgbv::black(0), } } } @@ -26,22 +28,31 @@ impl LedEffect for LedEffectBassSparks { leds: &mut LedColors, ) -> Duration { if stats.floating_max > 10100000 && (stats.current_powers[0] > 1.25 * stats.avg_powers[0]) { - self.bass_color = Rgbv::new(127, 0, 255, 4) + self.bass_color_fill = Rgbv::from_hsv(self.bass_color_hue, 100, 100, 1).unwrap(); } - leds.fill(self.bass_color); + leds.fill(self.bass_color_fill); - self.bass_color.decrease(10, 15, 20, 0); + self.bass_color_fill.decrease( + std::cmp::max(self.bass_color_fill.r / 4, 1), + std::cmp::max(self.bass_color_fill.g / 4, 1), + std::cmp::max(self.bass_color_fill.b / 4, 1), + 0, + ); if stats.floating_max > 10100000 && (stats.current_powers[1] > 1.35 * stats.avg_powers[1]) && (stats.current_powers[2] > 1.35 * stats.avg_powers[2]) { + let alternate_color = + Rgbv::from_hsv((self.bass_color_hue + 180) % 360, 100, 100, 5).unwrap(); for _ in 0..20 { let led_index = random_at_most(LED_COUNT as u32 - 1) as usize; - leds[led_index] = Rgbv::white(31); + // leds[led_index] = Rgbv::white(31); + leds[led_index] = alternate_color; } } + self.bass_color_hue = (self.bass_color_hue + 1) % 360; Duration::from_hz(50) } diff --git a/src/effects/mod.rs b/src/effects/mod.rs index 3faa122..6511360 100644 --- a/src/effects/mod.rs +++ b/src/effects/mod.rs @@ -1,2 +1,4 @@ pub mod led_effect; -pub mod bass_sparks; \ No newline at end of file +pub mod bass_sparks; +pub mod bass_hi_beat_strobe; +pub mod bass_hue_fade; \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index eaa45bd..f29fb27 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,7 +19,8 @@ use audio_input::mic_input_task; use audio_process::{process_audio, AudioBuffer, AudioStats, DspBuffer}; use config::{AUDIO_SAMPLES_PER_BUF, LED_COUNT}; use effects::{ - bass_sparks::LedEffectBassSparks, + // bass_sparks::LedEffectBassSparks as LedSelectedEffect, + bass_hue_fade::LedEffectBassHueFade as LedSelectedEffect, led_effect::{LedData, LedEffect}, }; use led_output::output_leds; @@ -27,7 +28,7 @@ use triple_buffer::{Receiver, Sender, TripleBuffer}; #[embassy_executor::task] async fn effect_task( - mut led_effect: LedEffectBassSparks, + mut led_effect: LedSelectedEffect, input: Receiver<'static, NoopRawMutex, (DspBuffer, AudioStats)>, output: Sender<'static, NoopRawMutex, LedData>, ) { @@ -99,7 +100,7 @@ async fn main(spawner: Spawner) { spawner .spawn(effect_task( - LedEffectBassSparks::default(), + LedSelectedEffect::default(), fft_receiver, led_sender, ))