Files
4k_synthwave/test.py

80 lines
2.2 KiB
Python

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
class DecayingSineWave:
def __init__(self, freq=5, decay=0.05, sample_rate=60):
self.freq = freq
self.decay = decay
self.sample_rate = sample_rate
self.triggers = []
def trigger(self, t):
self.triggers.append(t)
def sample(self, t):
value = 0.0
still_active = []
for start_time in self.triggers:
age = t - start_time
if age >= 0:
v = np.sin(2 * np.pi * self.freq * age / self.sample_rate) * np.exp(-self.decay * age)
value += v
if np.exp(-self.decay * age) > 1e-3:
still_active.append(start_time)
self.triggers = still_active
return value
# --- Initialize ---
wave = DecayingSineWave(freq=5, decay=0.05, sample_rate=60)
wave_array = np.zeros(512)
time = [0]
max_len = 512
fig, ax = plt.subplots()
line, = ax.plot(np.arange(512), wave_array, lw=2)
trig_dots, = ax.plot([], [], 'ro', markersize=4)
ax.set_xlim(0, 511)
ax.set_ylim(-1.2, 1.2)
ax.set_title("Click to Trigger Decaying Sine Wave")
ax.set_xlabel("Sample Index (0 = current)")
ax.set_ylabel("Amplitude")
ax.grid(True)
trigger_times = []
# --- Click handler ---
def on_click(event):
current_time = time[0]
wave.trigger(current_time)
trigger_times.append(current_time)
fig.canvas.mpl_connect('button_press_event', on_click)
# --- Animation update ---
def update(frame):
global wave_array
current_time = time[0]
# Shift buffer to the right (older samples move toward the end)
wave_array = wave_array * 0.995
wave_array = np.roll(wave_array, 1)
# Insert new sample at index 0
wave_array[0] = wave.sample(current_time)
print (wave_array)
line.set_data(np.arange(512), wave_array)
# Trigger markers
visible_triggers = [tt for tt in trigger_times if current_time - 512 < tt <= current_time]
x = [current_time - tt for tt in visible_triggers] # 0 = current time
y = [1.0 for _ in x]
trig_dots.set_data(x, y)
time[0] += 1
return line, trig_dots
ani = FuncAnimation(fig, update, interval=1000 / 60, blit=True)
plt.show()