mirror of https://github.com/LedFx/LedFx.git
100 lines
3.3 KiB
Python
100 lines
3.3 KiB
Python
import numpy as np
|
|
import voluptuous as vol
|
|
|
|
from ledfx.color import GRADIENTS
|
|
from ledfx.effects.audio import AudioReactiveEffect
|
|
from ledfx.effects.gradient import GradientEffect
|
|
|
|
|
|
class BarAudioEffect(AudioReactiveEffect, GradientEffect):
|
|
|
|
NAME = "Bar"
|
|
CONFIG_SCHEMA = vol.Schema(
|
|
{
|
|
vol.Optional(
|
|
"gradient_name",
|
|
description="Color scheme to cycle through",
|
|
default="Rainbow",
|
|
): vol.In(list(GRADIENTS.keys())),
|
|
vol.Optional(
|
|
"mode",
|
|
description="Choose from different animations",
|
|
default="wipe",
|
|
): vol.In(list(["bounce", "wipe", "in-out"])),
|
|
vol.Optional(
|
|
"ease_method",
|
|
description="Acceleration profile of bar",
|
|
default="ease_out",
|
|
): vol.In(list(["ease_in_out", "ease_in", "ease_out", "linear"])),
|
|
vol.Optional(
|
|
"color_step",
|
|
description="Amount of color change per beat",
|
|
default=0.125,
|
|
): vol.All(vol.Coerce(float), vol.Range(min=0.0625, max=0.5)),
|
|
}
|
|
)
|
|
|
|
def config_updated(self, config):
|
|
self.phase = 0
|
|
self.color_idx = 0
|
|
self.bar_len = 0.3
|
|
|
|
def audio_data_updated(self, data):
|
|
# Run linear beat oscillator through easing method
|
|
beat_oscillator, beat_now = data.oscillator()
|
|
if self._config["ease_method"] == "ease_in_out":
|
|
x = 0.5 * np.sin(np.pi * (beat_oscillator - 0.5)) + 0.5
|
|
elif self._config["ease_method"] == "ease_in":
|
|
x = beat_oscillator ** 2
|
|
elif self._config["ease_method"] == "ease_out":
|
|
x = -((beat_oscillator - 1) ** 2) + 1
|
|
elif self._config["ease_method"] == "linear":
|
|
x = beat_oscillator
|
|
|
|
# Colour change and phase
|
|
if beat_now:
|
|
self.phase = 1 - self.phase # flip flop 0->1, 1->0
|
|
if self.phase == 0:
|
|
# 8 colours, 4 beats to a bar
|
|
self.color_idx += self._config["color_step"]
|
|
self.color_idx = self.color_idx % 1 # loop back to zero
|
|
|
|
# Compute position of bar start and stop
|
|
if self._config["mode"] == "wipe":
|
|
if self.phase == 0:
|
|
bar_end = x
|
|
bar_start = 0
|
|
elif self.phase == 1:
|
|
bar_end = 1
|
|
bar_start = x
|
|
|
|
elif self._config["mode"] == "bounce":
|
|
x = x * (1 - self.bar_len)
|
|
if self.phase == 0:
|
|
bar_end = x + self.bar_len
|
|
bar_start = x
|
|
elif self.phase == 1:
|
|
bar_end = 1 - x
|
|
bar_start = 1 - (x + self.bar_len)
|
|
|
|
elif self._config["mode"] == "in-out":
|
|
if self.phase == 0:
|
|
bar_end = x
|
|
bar_start = 0
|
|
elif self.phase == 1:
|
|
bar_end = 1 - x
|
|
bar_start = 0
|
|
|
|
# Construct the bar
|
|
color = self.get_gradient_color(self.color_idx)
|
|
p = np.zeros(np.shape(self.pixels))
|
|
p[
|
|
int(self.pixel_count * bar_start) : int(
|
|
self.pixel_count * bar_end
|
|
),
|
|
:,
|
|
] = color
|
|
|
|
# Update the pixel values
|
|
self.pixels = p
|