feat: live fx/mix values from time/beats
This commit is contained in:
@@ -84,10 +84,13 @@ def __get_running_display(data: ForgeData) -> Image.Image:
|
||||
draw2.text((45, 44), hex(data.frag_state(3))[2].upper(), fill="white", font=FONT_2)
|
||||
draw2.text((103, 32), hex(data.frag_state(5))[2].upper(), fill="white", font=FONT_2)
|
||||
# TODO print when random
|
||||
# TODO print when inverted
|
||||
|
||||
draw2.text((74, 32), "K" if data.mix_mode_key else "M", fill="white", font=FONT_2)
|
||||
|
||||
# TODO show feedback
|
||||
# TODO show blank out
|
||||
# TODO show inverted out
|
||||
|
||||
return __xor(im, im_overlay)
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import typing
|
||||
|
||||
from .constants import FORGE_SAVE_BACKUP_PATH, FORGE_SAVE_PATH, MOCK_SAVE_PATH
|
||||
from .enums import ForgeState
|
||||
from .glsl_funcs import fract, magic, magic_trigger
|
||||
|
||||
|
||||
class ForgeRawData:
|
||||
@@ -77,13 +78,16 @@ class ForgeData:
|
||||
def active(self, n: int) -> int:
|
||||
return int(self.__data[f"active_{n}"])
|
||||
|
||||
def seed(self, n: int) -> int:
|
||||
return int(self.__data[f"seed_{n}"])
|
||||
|
||||
@property
|
||||
def time(self) -> float:
|
||||
return self.__data["time"]
|
||||
|
||||
@property
|
||||
def time_progress(self) -> float:
|
||||
return self.time - int(self.time)
|
||||
return fract(self.time)
|
||||
|
||||
@property
|
||||
def tempo(self) -> float:
|
||||
@@ -95,7 +99,7 @@ class ForgeData:
|
||||
|
||||
@property
|
||||
def beat_progress(self) -> float:
|
||||
return self.beats - int(self.beats)
|
||||
return fract(self.beats)
|
||||
|
||||
@property
|
||||
def page(self) -> int:
|
||||
@@ -107,24 +111,33 @@ class ForgeData:
|
||||
|
||||
@property
|
||||
def fxa_value(self) -> float:
|
||||
# todo random and time based
|
||||
return self.value(18)[0]
|
||||
return magic(
|
||||
self.time, self.beats, self.value(18), (1.0, 0.0, 0.0), self.seed(2)
|
||||
)
|
||||
|
||||
@property
|
||||
def fxb_value(self) -> float:
|
||||
return self.value(25)[0]
|
||||
|
||||
@property
|
||||
def mfx_value(self) -> float:
|
||||
return self.value(32)[0]
|
||||
return magic(
|
||||
self.time, self.beats, self.value(25), (1.0, 0.0, 0.0), self.seed(3)
|
||||
)
|
||||
|
||||
@property
|
||||
def mix_value(self) -> float:
|
||||
return self.value(34)[0]
|
||||
return magic(
|
||||
self.time, self.beats, self.value(34), (1.0, 0.0, 0.0), self.seed(4)
|
||||
)
|
||||
|
||||
@property
|
||||
def mix_mode_key(self) -> bool:
|
||||
return self.value(33)[0] > 0.
|
||||
return magic_trigger(
|
||||
self.time, self.beats, (self.value(33)[0], 0.0, 0.0), self.seed(4) + 10.0
|
||||
)
|
||||
|
||||
@property
|
||||
def mfx_value(self) -> float:
|
||||
return magic(
|
||||
self.time, self.beats, self.value(32), (1.0, 0.0, 0.0), self.seed(5)
|
||||
)
|
||||
|
||||
def mock(self) -> typing.Self:
|
||||
self.__data.read(MOCK_SAVE_PATH)
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
from math import cos, floor, sin
|
||||
|
||||
# glsl base
|
||||
|
||||
PI = 3.1415927
|
||||
|
||||
|
||||
def mod(x: float, y: float) -> float:
|
||||
return x % y
|
||||
|
||||
|
||||
def fract(x: float) -> float:
|
||||
return mod(x, 1.0)
|
||||
|
||||
|
||||
def mix(x: float, y: float, a: float) -> float:
|
||||
if a <= 0.0:
|
||||
return x
|
||||
if a >= 1.0:
|
||||
return y
|
||||
return x + (y - x) * a
|
||||
|
||||
|
||||
def step(edge: float, x: float) -> float:
|
||||
if x < edge:
|
||||
return 0.0
|
||||
return 1.0
|
||||
|
||||
|
||||
# inc_rand.glsl
|
||||
|
||||
RAND_C = 43758.5453
|
||||
|
||||
|
||||
def rand(seed: float) -> float:
|
||||
return fract(sin(seed) * RAND_C)
|
||||
|
||||
|
||||
# inc_time.glsl
|
||||
|
||||
|
||||
def rand_time(itime: float, ibeats: float, seed: float, beats: int = 4) -> float:
|
||||
return rand(seed + floor(ibeats / beats))
|
||||
|
||||
|
||||
def divider(x: float) -> float:
|
||||
if x < 0.1:
|
||||
return 0.0
|
||||
if x < 0.2:
|
||||
return 0.125
|
||||
if x < 0.3:
|
||||
return 0.25
|
||||
if x < 0.4:
|
||||
return 0.5
|
||||
if x < 0.6:
|
||||
return 1.0
|
||||
if x < 0.8:
|
||||
return 2.0
|
||||
return 4.0
|
||||
|
||||
|
||||
def mod_time(ibeats: float, k: float, k2: float = 1.0) -> float:
|
||||
return mod(divider(k) * ibeats * k2 * 0.25, 1.0)
|
||||
|
||||
|
||||
def cos_time(ibeats: float, k: float) -> float:
|
||||
return cos(mod_time(ibeats, k, 5.0) * 2.0 * PI)
|
||||
|
||||
|
||||
# inc_magic.glsl
|
||||
|
||||
|
||||
def magic_f(
|
||||
itime: float,
|
||||
ibeats: float,
|
||||
f: tuple[float, float, float],
|
||||
b: tuple[float, float, float],
|
||||
i: float,
|
||||
) -> tuple[float, float]:
|
||||
return (
|
||||
mix(f[0], rand_time(itime, ibeats, i + 1.0), min(1.0, b[2])),
|
||||
mix(f[1], rand_time(itime, ibeats, i + 2.0), min(1.0, b[2])),
|
||||
)
|
||||
|
||||
|
||||
def magic_b(
|
||||
itime: float, ibeats: float, b: tuple[float, float, float], i: float
|
||||
) -> tuple[float, float, float]:
|
||||
return (
|
||||
mix(b[0], step(0.2, rand_time(itime, ibeats, i + 3.0)), min(1.0, b[2])),
|
||||
mix(b[1], step(0.5, rand_time(itime, ibeats, i + 4.0)), min(1.0, b[2])),
|
||||
min(1.0, b[2]),
|
||||
)
|
||||
|
||||
|
||||
def magic_trigger(
|
||||
itime: float, ibeats: float, b: tuple[float, float, float], i: float
|
||||
) -> bool:
|
||||
return magic_b(itime, ibeats, b, i)[0] > 0.0
|
||||
|
||||
|
||||
def magic(
|
||||
itime: float,
|
||||
ibeats: float,
|
||||
f: tuple[float, float, float],
|
||||
b: tuple[float, float, float],
|
||||
i: float,
|
||||
) -> float:
|
||||
mf = magic_f(itime, ibeats, f, b, i)
|
||||
mb = magic_b(itime, ibeats, b, i)
|
||||
|
||||
return mix(
|
||||
0.0,
|
||||
mf[0]
|
||||
* mix(
|
||||
1.0 - mod_time(ibeats, mf[1]),
|
||||
cos_time(ibeats, mf[1]) * 0.5 + 0.5,
|
||||
mb[1],
|
||||
),
|
||||
mb[0],
|
||||
)
|
||||
Reference in New Issue
Block a user