play tests improvements #2

This commit is contained in:
Patrick Moessler 2023-03-05 01:46:59 +01:00
parent 2c7a3f61e4
commit 345c06611b
9 changed files with 303 additions and 60 deletions

2
.vscode/launch.json vendored
View file

@ -11,7 +11,7 @@
"program": "beamshow.py",
"console": "integratedTerminal",
"justMyCode": true,
"args": ["-w","-b","-a","Notepad"]
"args": ["-w","-b","-a","Notepad", "--fps"]
}
]
}

View file

@ -7,7 +7,7 @@ import sys
from effects.effect import Effect
from effects.presets import Presets
from util.color import Colors
from util.audio import AudioProcess
from util.audio import AudioProcess, find_all_inputs
def print_displays() -> None:
@ -18,6 +18,12 @@ def print_displays() -> None:
sys.exit(0)
def print_inputs() -> None:
devs = find_all_inputs()
print("\n".join((x["name"] for x in devs)))
sys.exit(0)
class Beamshow:
def __init__(
self,
@ -313,6 +319,9 @@ def app_main() -> None:
argparser.add_argument(
"--list-displays", action="store_true", help="Show available displays"
)
argparser.add_argument(
"--list-inputs", action="store_true", help="Show available audio inputs"
)
argparser.add_argument(
"-w", "--window", action="store_true", help="Display in a window"
)
@ -348,6 +357,9 @@ def app_main() -> None:
if args.list_displays:
print_displays()
if args.list_displays:
print_inputs()
show = Beamshow(
audio_device_name=args.audio,
render3d=args.render3d,

View file

@ -31,22 +31,15 @@ class MovingEffect(Effect):
"""
ring chase two colors
square
square two color
line scan vh
starfield spawn chance
rainbow circle rotate
spot row
alles größer
fix double spot 4 spots
"""

View file

@ -3,9 +3,11 @@ import pygame as pg
from typing import Iterator, List
from random import choice, randint, randrange
from effects.chase_circle import ChaseCircle
from effects.effect import Effect
from effects.line import Lines
from effects.rectangle import Rectangle
from util.color import (
color_darken,
color_randomize,
@ -38,9 +40,10 @@ class Presets:
def __init__(self, bounds: pg.Rect, beat_reactive: bool = False) -> None:
self.bounds = bounds
self.beat_reactive = beat_reactive
self.shuffles = list(iter(self)) * 2
def default(self) -> List[Effect]:
return self.StrobeLine()
return self.Rectangle()
def __getitem__(self, idx: str) -> List[Effect]:
return getattr(self, idx)()
@ -52,18 +55,24 @@ class Presets:
return (
func
for func in dir(self)
if callable(getattr(self, func)) and not func.startswith("__")
if callable(getattr(self, func))
and not (func.startswith("__") or func == "randomize")
)
def randomize(self) -> str:
return choice(
[
func
for func in dir(self)
if callable(getattr(self, func))
and not (func.startswith("__") or func == "randomize")
]
)
selected = choice(self.shuffles)
self.shuffles.remove(selected)
if not self.shuffles:
self.shuffles = list(iter(self)) * 2
return selected
# return choice(
# [
# func
# for func in dir(self)
# if callable(getattr(self, func))
# and not (func.startswith("__") or func == "randomize")
# ]
# )
def DoubleSpotRandomColor(self) -> List[Effect]:
return [
@ -358,28 +367,28 @@ class Presets:
mover=transform_bounce(
bounds=self.bounds,
velocity=(0.5, 1),
x_factor=(3, 3),
x_factor=(2, 2),
y_factor=(0.5, 1),
),
)
]
def FallingLine(self) -> List[Effect]:
bounds = pg.rect.Rect(0, 0, self.bounds.width, 30)
return [
Lines(
bounds=bounds,
vectors=(((0, 15), (self.bounds.width, 15), color_wheel()),),
thickness=30,
mover=transform_falling(
bounds,
acceleration=0.8,
initial_pos=(0, 0),
initial_velocity=0.01,
on_beat_reset=True,
),
),
]
# def FallingLine(self) -> List[Effect]:
# bounds = pg.rect.Rect(0, 0, self.bounds.width, 30)
# return [
# Lines(
# bounds=bounds,
# vectors=(((0, 15), (self.bounds.width, 15), color_wheel()),),
# thickness=30,
# mover=transform_falling(
# bounds,
# acceleration=0.8,
# initial_pos=(0, 0),
# initial_velocity=0.01,
# on_beat_reset=True,
# ),
# ),
# ]
def StrobeLine(self) -> List[Effect]:
thickness = 50
@ -481,3 +490,108 @@ class Presets:
)
for i in range(count)
]
def StrobeRect(self) -> List[Effect]:
thickness = 50
color_lr = color_wheel(hue=0, increase=1, repeat=4)
color_ud = color_wheel(hue=180, increase=1, repeat=4)
color_lr_s = color_strobe(color=color_lr, rate=(30, 120), flash_color=color_ud)
color_ud_s = color_strobe(color=color_ud, rate=(30, 120), flash_color=color_lr)
return [
Lines(
bounds=self.bounds,
vectors=(
(
(0, thickness // 2),
(self.bounds.width, thickness // 2),
color_ud_s,
),
(
(0, self.bounds.height - thickness // 2),
(self.bounds.width, self.bounds.height - thickness // 2),
color_ud_s,
),
),
thickness=thickness,
mover=transform_static((0, 0)),
),
Lines(
bounds=self.bounds,
vectors=(
(
(thickness // 2, 0),
(thickness // 2, self.bounds.height),
color_lr_s,
),
(
(self.bounds.width - thickness // 2, 0),
(self.bounds.width - thickness // 2, self.bounds.height),
color_lr_s,
),
),
thickness=thickness,
mover=transform_static((0, 0)),
),
]
def ChaseCircle(self) -> List[Effect]:
return [
ChaseCircle(
bounds=self.bounds,
colors=(
color_wheel(increase=(75 if self.beat_reactive else 0)),
color_wheel(hue=180, increase=(75 if self.beat_reactive else 0)),
),
on_beat_color=self.beat_reactive,
size=int(self.bounds.height * 0.7),
rot_speed=5,
thickness=80,
size_factor=1,
mover=transform_bounce(
bounds=self.bounds,
velocity=(0.1, 0.5),
x_factor=(0.5, 1),
y_factor=(0.1, 0.3),
),
)
]
def ChaseCircleLine(self) -> List[Effect]:
return [
ChaseCircle(
bounds=self.bounds,
colors=(
color_wheel(increase=(75 if self.beat_reactive else 0)),
color_wheel(hue=180, increase=(75 if self.beat_reactive else 0)),
),
on_beat_color=self.beat_reactive,
size=int(self.bounds.height * 0.7),
rot_speed=-20,
thickness=80,
size_factor=0.2,
mover=transform_bounce(
bounds=self.bounds,
velocity=(0.1, 0.5),
x_factor=(0.5, 1),
y_factor=(0.1, 0.3),
),
)
]
def Rectangle(self) -> List[Effect]:
return [
Rectangle(
bounds=self.bounds,
color=color_wheel(increase=(75 if self.beat_reactive else 1)),
size=int(self.bounds.height*0.9),
aspect=1.0,
rot_speed=0.5,
thickness=80,
mover=transform_bounce(
bounds=self.bounds,
velocity=(0.1, 0.5),
x_factor=(0.5, 1),
y_factor=(0.1, 0.3),
),
)
]

125
effects/rectangle.py Normal file
View file

@ -0,0 +1,125 @@
from effects.effect import MovingEffect
from typing import Any, Optional
from util import XYCoord
from util.color import Colors, ColorGenerator, color_fade, copy_color
import math
import pygame as pg
from util.transform import PositionGenerator
def calc_x(R, T, D):
a = 1 + R**2
b = 2 * T * (1 + R)
c = T**2 * (1 + R**2) - D**2
return max(
(-b + math.sqrt(b**2 - 4 * a * c)) / (2 * a),
(-b - math.sqrt(b**2 - 4 * a * c)) / (2 * a),
)
class Rectangle(MovingEffect):
def __init__(
self,
bounds: pg.Rect,
color: ColorGenerator,
size: int,
aspect: float = 1.0,
rot_speed: float = 0.5,
thickness: int = 30,
mover: Optional[PositionGenerator] = None,
*groups: pg.sprite.Group,
) -> None:
self.color_gen = color
self.color = copy_color(next(color))
self.fader = color_fade(
initial_color=self.color, end_color=next(self.color_gen), duration=10
)
self.angle = 45.0
self.rot_speed = rot_speed
self.thickness = thickness
x = calc_x(aspect, thickness, size)
print(x)
print(size)
self.rsize = (x, (x + 2 * thickness) * aspect - 2 * thickness)
print(self.rsize)
self.rect_image = pg.Surface(self.rsize)
self.rect_image.fill(Colors.Black)
self.rect_image.set_colorkey(Colors.Black)
image = pg.Surface((size, size))
image.fill(Colors.Black)
image.set_colorkey(Colors.Black)
super().__init__(
image,
pg.Rect(
bounds.centerx - size // 2,
bounds.centery - size // 2,
size,
size,
),
mover,
*groups,
)
self.update(is_beat=True)
def update(self, *args: Any, **kwargs: Any) -> None:
# self.rect.center = self.mover.send((self.rect.size, kwargs["is_beat"]))
self.image.fill(Colors.Blue)
self.rect_image.fill(Colors.Green)
# rc = next(self.fader)
# pg.draw.rect(
# self.rect_image,
# rc,
# ((0, 0), self.rsize),
# 0,
# )
# pg.draw.rect(
# self.rect_image,
# Colors.Black,
# (
# self.thickness // 2,
# self.thickness // 2,
# self.rsize[0] - self.thickness,
# self.rsize[1] - self.thickness,
# ),
# 0,
# )
# if kwargs["is_beat"]:
# new_color = next(self.color_gen)
# self.fader = color_fade(
# initial_color=self.color, end_color=new_color, duration=10
# )
# self.color = copy_color(new_color)
# pg.draw.rect(
# self.rect_image,
# Colors.White,
# (
# self.thickness,
# self.thickness,
# self.rsize[0] - self.thickness * 2,
# self.rsize[1] - self.thickness * 2,
# ),
# 0,
# )
r2 = pg.transform.rotate(self.rect_image, self.angle)
print(self.image.get_width()-r2.get_width())
self.image.blit(
r2,
(
(self.image.get_width() - r2.get_width()) // 2,
(self.image.get_height() - r2.get_height()) // 2,
),
)
# self.angle = (self.angle + self.rot_speed) % (360)

View file

@ -18,7 +18,7 @@ class ScanReticle(MovingEffect):
) -> None:
self.colors = colors
self.bounds = bounds
self.rect_size = min(self.bounds.width // 6, self.bounds.height // 6)
self.rect_size = min(self.bounds.width // 3, self.bounds.height // 3)
image = pg.Surface(self.bounds.size)
image.fill(Colors.Black)

View file

@ -1,3 +1,4 @@
pygame==2.1.3
soundcard==0.4.2
pyaudiowpatch==0.2.12.5
pyaudiowpatch==0.2.12.5
aubio==0.4.9

View file

@ -1,4 +1,5 @@
import time
from typing import List
import aubio
import pyaudiowpatch as pa
@ -7,6 +8,17 @@ import numpy as np
import threading
def find_all_inputs() -> List[dict]:
devices: List[dict] = []
p = pa.PyAudio()
api_info = p.get_host_api_info_by_type(pa.paWASAPI)
for i in range(api_info["deviceCount"]):
dev_info = p.get_device_info_by_host_api_device_index(api_info["index"], i)
if dev_info["maxInputChannels"] > 0:
devices.append(dev_info)
return devices
def find_audio_device(p: pa.PyAudio, api: int, name: str) -> dict:
api_info = p.get_host_api_info_by_type(api)
for i in range(api_info["deviceCount"]):

View file

@ -66,29 +66,15 @@ def color_fadeout(initial_color: pg.Color, fade_speed: float) -> ColorGenerator:
def color_fade(
initial_color: pg.Color, end_color: pg.Color, duration: int
) -> ColorGenerator:
color = copy_color(initial_color)
h, s, l, a = color.hsla
h2, s2, l2, a2 = end_color.hsla
h_inc = (h2 - h) / duration
s_inc = (s2 - s) / duration
l_inc = (l2 - l) / duration
a_inc = (a2 - a) / duration
h_f = float(h)
s_f = float(s)
l_f = float(l)
a_f = float(a)
inc = 1.0 / duration
factor = 0.0
col1 = copy_color(initial_color)
col2 = copy_color(end_color)
while True:
yield color
color.hsla = int(h_f), int(s_f), int(l_f), int(a_f)
if h_f < h2:
h_f += h_inc
if s_f < s2:
s_f += s_inc
if l_f < l2:
l_f += l_inc
if a_f < a2:
a_f += a_inc
yield col1.lerp(col2, factor)
factor += inc
if factor > 1:
factor = 1
def color_cycle(seq: Sequence[pg.Color]) -> ColorGenerator: