~jojo/jojos-hue

fd25d622b8969d915895c1eaf2ab89acf284d0f9 — JoJo 11 days ago 1ca4225 master
color correct strips & preamp in audiovis based on base color value
3 files changed, 37 insertions(+), 51 deletions(-)

M client/client.ino
M server/src/audiovis.rs
M server/src/main.rs
M client/client.ino => client/client.ino +6 -3
@@ 1,14 1,15 @@
#include <FastLED.h>

#define UNO_WS2812B
// #define ESP32_WS2801
// #define ESP32_WS2813
//#define ESP32_WS2801
//#define ESP32_WS2813

// vvvvvvv UNIT vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
#if                               defined(UNO_WS2812B)
#define LED_PINS 8
#define LED_TYPE WS2812B
#define COLOR_ORDER GRB
#define CORRECTION TypicalLEDStrip
#define NUM_LEDS 48
#define MAX_MILLIAMPS 2000
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };


@@ 17,6 18,7 @@ static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
#define LED_PINS G33, G23
#define LED_TYPE WS2801
#define COLOR_ORDER RGB
#define CORRECTION CRGB(255, 242, 220)
#define NUM_LEDS 50
#define MAX_MILLIAMPS 3000
#define CONN_WIFI


@@ 24,6 26,7 @@ static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
#define LED_PINS G33
#define LED_TYPE WS2813
#define COLOR_ORDER GRB
#define CORRECTION TypicalLEDStrip
#define NUM_LEDS 60
#define MAX_MILLIAMPS 2000
#define DUALCORE_FASTLED


@@ 133,7 136,7 @@ void setup() {
#endif

    FastLED.addLeds<LED_TYPE, LED_PINS, COLOR_ORDER>(leds, NUM_LEDS)
        .setCorrection(TypicalLEDStrip);
        .setCorrection(CORRECTION);
    FastLED.setMaxPowerInVoltsAndMilliamps(5, MAX_MILLIAMPS);
#ifdef DUALCORE_FASTLED
    xTaskCreatePinnedToCore(showTask, "showTask", 2048, NULL, 2, &showTaskHandle, FASTLED_SHOW_CORE);

M server/src/audiovis.rs => server/src/audiovis.rs +30 -47
@@ 1,5 1,5 @@
use num::Complex;
use palette::{Blend, FromColor, Hsv, Mix, Saturate, Srgb};
use palette::{FromColor, Hsv, Mix, Saturate, Srgb};
use pulse_simple::Record;
use rustfft::FftPlanner;
use std::{


@@ 12,7 12,7 @@ const SAMPLE_RATE: usize = 48000;
const SAMPLES_PER_PERIOD: usize = 256;

const BASS_CUTOFF: f32 = 400.0;
const HIGH_CUTOFF: f32 = 2900.0;
const HIGH_CUTOFF: f32 = 3000.0;

const MAX_FREQ: f32 = 20_000.0;



@@ 22,7 22,7 @@ pub struct AudioVis {
}

impl AudioVis {
    pub fn new() -> Self {
    pub fn new(base: Hsv) -> Self {
        let (tx, rx) = channel();
        thread::spawn(move || {
            let recorder = Record::new(


@@ 50,40 50,31 @@ impl AudioVis {
                for (bin, &amp) in bin_amps.iter().enumerate() {
                    high_amps[bin] = high_pass(bin_to_freq(bin), amp);
                }
                let max_amp_bass = max_amp(&bass_amps[..bass_cutoff_bin]).1;
                let m_m = max_amp(&mid_amps[bass_cutoff_bin..high_cutoff_bin]);
                let m_h = max_amp(&high_amps[high_cutoff_bin..]);
                let max_amp_mid = (m_m.0 + bass_cutoff_bin, m_m.1).1;
                let max_amp_high = (m_h.0 + high_cutoff_bin, m_h.1).1;
                let amp_bass = max_amp(&bass_amps[..bass_cutoff_bin]);
                let amp_mid = max_amp(&mid_amps[bass_cutoff_bin..high_cutoff_bin]);
                let amp_high = max_amp(&high_amps[high_cutoff_bin..]);
                let preamp = base.value * 8.0;
                let (bass_lvl, mid_lvl, high_lvl) = (
                    norm_amp(max_amp_bass).powf(1.22),       // .powf(2.5),
                    norm_amp(max_amp_mid * 1.6).powf(1.25),  // .powf(2.6),
                    norm_amp(max_amp_high * 3.2).powf(1.12), // .powf(2.4),
                    norm_amp(preamp * amp_bass).powf(2.5),
                    norm_amp(preamp * amp_mid * 1.4).powf(2.55),
                    norm_amp(preamp * amp_high * 3.5).powf(2.3),
                );
                //let brightness = (bass_lvl * 1.6 + mid_lvl * 0.7 + high_lvl * 0.7) / 3.0;
                let color = Hsv::from_color(Srgb::new(bass_lvl, mid_lvl, high_lvl)).saturate(0.3);
                //let c1 = color.clone();
                //color.value = brightness;

                i += 1;
                if i > 40 {
                    i = 0;
                    let (max_bin_all, max_amp_all) = max_amp(&bin_amps);
                    println!(
                        "f: {:6.0}, amp: {:4.1}, vol: {:1.3}\namp: bass: {}, mid: {}, high: {}\nlvl: bass: {}, mid: {}, high: {}\nc2: {:?}\n",
                        bin_to_freq(max_bin_all),
                        max_amp_all,
                        norm_amp(max_amp_all),
                        max_amp_bass,
                        max_amp_mid,
                        max_amp_high,
                        bass_lvl,
                        mid_lvl,
                        high_lvl,
                        //c1,
                        color
                    );
                }
                let color = Hsv::from_color(Srgb::new(bass_lvl, mid_lvl, high_lvl)).saturate(0.4);

                // i += 1;
                // if i > 40 {
                //     i = 0;
                //     println!(
                //         "amp: bass: {}, mid: {}, high: {}\nlvl: bass: {}, mid: {}, high: {}\nc2: {:?}\n",
                //         amp_bass,
                //         amp_mid,
                //         amp_high,
                //         bass_lvl,
                //         mid_lvl,
                //         high_lvl,
                //         color
                //     );
                // }

                tx.send(color).unwrap();
            }


@@ 96,14 87,7 @@ impl AudioVis {
    pub fn color(&mut self) -> Hsv {
        if let Some(c2) = self.rx.try_iter().last() {
            let c1 = self.color;
            let mut c3 = c1.mix(&c2, 0.6);
            let r = 0.2 + 0.8 * c2.value; // become bright fast, and dark more slowly
            c3.value = (1.0 - r) * c1.value + r * c2.value;
            self.color = c3;
            // let c1 = Srgb::from_color(self.color).into_linear();
            // let c2 = Srgb::from_color(c2).into_linear();
            // let c3 = c1.dodge(c2).mix(&c2, 0.6);
            // self.color = Hsv::from_color(Srgb::from_linear(c3)).saturate(0.15);
            self.color = c1.mix(&c2, 0.1).saturate(0.2);
        }
        self.color
    }


@@ 198,13 182,12 @@ fn stereo_pcm_to_bins(
    bin_amps
}

fn max_amp(amps: &[f32]) -> (usize, f32) {
    let (mut max_bin, mut max_amp) = (0, 0.0);
fn max_amp(amps: &[f32]) -> f32 {
    let mut max_amp = 0.0;
    for i in 0..amps.len() {
        if amps[i] > max_amp {
            max_amp = amps[i];
            max_bin = i;
        }
    }
    (max_bin, max_amp)
    max_amp
}

M server/src/main.rs => server/src/main.rs +1 -1
@@ 161,7 161,7 @@ fn controller(heartbeat_rx: Receiver<Heartbeat>, cmd_rx: Receiver<QueryCmd>) {
                QueryCmd::Off => cmd = Cmd::Off,
                QueryCmd::Cycle => cmd = Cmd::Cycle,
                QueryCmd::Breathing => cmd = Cmd::Breathing,
                QueryCmd::AudioVis => cmd = Cmd::AudioVis(AudioVis::new()),
                QueryCmd::AudioVis => cmd = Cmd::AudioVis(AudioVis::new(base)),
            }
        }
        for (_, tx) in clients.values() {