mirror of
https://github.com/pyscript/pyscript.git
synced 2025-12-19 18:27:29 -05:00
84 lines
2.4 KiB
Python
84 lines
2.4 KiB
Python
from dataclasses import dataclass, field
|
|
import sys
|
|
|
|
@dataclass
|
|
class BeatSync:
|
|
fft_res: int = field()
|
|
|
|
on_beat: bool = False
|
|
beat: int = -1
|
|
since_last_beat: float = sys.maxsize
|
|
|
|
_prev: int = 0
|
|
_count: int = 0
|
|
_bins: list[int] = field(default_factory=list)
|
|
_last_detection: float = -1.0
|
|
_threshold: int = 50
|
|
_diff: int = 40
|
|
_cooldown: float = 0.2
|
|
|
|
_highest: int = 0
|
|
|
|
def __post_init__(self):
|
|
self._bins = [int(13/16*self.fft_res/2)+17, int(13/16*self.fft_res/2)+18]
|
|
|
|
def reset(self):
|
|
self.beat = -1
|
|
self._prev = 0
|
|
self._count = 0
|
|
self._last_detection = -1.0
|
|
self.since_last_beat = sys.maxsize
|
|
# print('bs reset')
|
|
|
|
def update(self, data, running_time):
|
|
self._count += 1
|
|
self.since_last_beat = running_time - self._last_detection
|
|
d = sum(data[bin] for bin in self._bins)
|
|
if d < self._threshold:
|
|
self.on_beat = False
|
|
elif d - self._prev < self._diff:
|
|
self.on_beat = False
|
|
elif self.since_last_beat < self._cooldown:
|
|
self.on_beat = False
|
|
else:
|
|
self._last_detection = running_time
|
|
self.since_last_beat = 0
|
|
self.on_beat = True
|
|
self.beat += 1
|
|
self._prev = d
|
|
|
|
@dataclass
|
|
class FreqIntensity:
|
|
freq: float = field()
|
|
fft_res: int = field()
|
|
|
|
intensity: float = 0.0
|
|
intensity_slew: float = 0.0
|
|
scale_min: float = 0.0
|
|
scale_max: float = 350
|
|
max: float = 0.0
|
|
_sample_rate: int = 48000
|
|
_bin_indexes: list[int] = field(default_factory=list)
|
|
_harmonics: int = 8
|
|
_slew_factor: float = 0.8
|
|
|
|
def __post_init__(self):
|
|
self._bin_indexes = [
|
|
round((harmonic+1) * self.freq / self._sample_rate * self.fft_res / 2)
|
|
for harmonic in range(self._harmonics)
|
|
]
|
|
print(self._bin_indexes)
|
|
|
|
def update(self, data):
|
|
intensity = 0.0
|
|
for bin in range(self._harmonics):
|
|
intensity += data[self._bin_indexes[bin]]/(bin+1)
|
|
self.intensity = intensity
|
|
self.intensity_slew = self._slew_factor * self.intensity_slew + (1 - self._slew_factor) * intensity
|
|
self.max = max(intensity, self.max)
|
|
|
|
@property
|
|
def intensity_scaled(self):
|
|
raw = max(0, min(1.0, (self.intensity_slew - self.scale_min)/(self.scale_max - self.scale_min)))
|
|
return raw * raw
|