feat: KolayTercih lansman videosu (Remotion, v3)
64 saniyelik, kesintisiz döngü lansman filmi; 9:16 ve 16:9. - remocn.dev bileşenleri (sheen-slide-in, tracking-in, gradient-scale-cut-text, outline-fill-track-text, perspective-marquee, path-ride, zoom-blur, lens-zoom) KolayTercih piksel diline uyarlandı (src/kinetik.tsx) - Sahne içi imleç + imleci takip eden kamera, piksel iz ve tık patlaması - Sessizlik → BAM kurgusu (lensZoom), punch zoom ve hareket bulanıklığı - Müzik ve efektler numpy ile sentezlendi (ses/uret.py), zaman.json tek kaynak - Örnek taban sıralamaları gerçek YÖK Atlas 2026 kayıtları Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
678
ses/uret.py
Normal file
678
ses/uret.py
Normal file
@@ -0,0 +1,678 @@
|
||||
"""
|
||||
KolayTercih lansman videosunun müziği ve ses efektleri — tamamen sentez
|
||||
(numpy), dışarıdan örnek/sample yok, lisans derdi yok.
|
||||
|
||||
Zaman çizelgesi src/zaman.json'dan okunur; video ile aynı kaynak.
|
||||
120 BPM (1 vuruş = 0.5 sn = 15 kare), Do majör. Video döngüye girer: son kare ilk kareyle aynıdır, ses de öyle — SON'dan
|
||||
taşan kuyruk dosyanın başına eklenir. Çıktılar:
|
||||
public/ses/muzik.wav — müzik (stereo, 44.1 kHz, 16 bit)
|
||||
public/ses/efekt.wav — ses efektleri
|
||||
Çalıştırma: python3 ses/uret.py
|
||||
"""
|
||||
|
||||
import json
|
||||
import wave
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
|
||||
KOK = Path(__file__).resolve().parent.parent
|
||||
SR = 44100
|
||||
Z = json.loads((KOK / "src/zaman.json").read_text())
|
||||
FPS = Z["fps"]
|
||||
S = {s["id"]: s["bas"] / FPS for s in Z["sahneler"]}
|
||||
SON = Z["son"] / FPS
|
||||
# Döngü: SON'dan sonra taşan kuyruk (reverb, son akor) başa sarılır
|
||||
KUYRUK = 3.5
|
||||
N = int((SON + KUYRUK) * SR)
|
||||
rng = np.random.default_rng(11)
|
||||
B = 0.5 # vuruş (sn)
|
||||
ZAMAN_TIK = Z["tiklar"]
|
||||
|
||||
|
||||
def lf(sahne, kare):
|
||||
"""Sahne içi kare → mutlak saniye."""
|
||||
return S[sahne] + kare / FPS
|
||||
|
||||
|
||||
# ------------------------------------------------------------------ #
|
||||
# Temel araçlar #
|
||||
# ------------------------------------------------------------------ #
|
||||
|
||||
|
||||
def zaman(d):
|
||||
return np.arange(int(d * SR)) / SR
|
||||
|
||||
|
||||
def mf(m):
|
||||
return 440.0 * 2 ** ((m - 69) / 12)
|
||||
|
||||
|
||||
def fftconv(x, h):
|
||||
n = len(x) + len(h) - 1
|
||||
boy = 1 << (n - 1).bit_length()
|
||||
y = np.fft.irfft(np.fft.rfft(x, boy) * np.fft.rfft(h, boy), boy)[:n]
|
||||
return y
|
||||
|
||||
|
||||
def sinc_lp(fc, taps=255):
|
||||
n = np.arange(taps) - (taps - 1) / 2
|
||||
h = np.sinc(2 * fc / SR * n) * np.blackman(taps)
|
||||
return h / h.sum()
|
||||
|
||||
|
||||
def lp(x, fc, taps=255):
|
||||
return fftconv(x, sinc_lp(fc, taps))[(taps - 1) // 2 : (taps - 1) // 2 + len(x)]
|
||||
|
||||
|
||||
def hp(x, fc, taps=255):
|
||||
return x - lp(x, fc, taps)
|
||||
|
||||
|
||||
def bp(x, f1, f2, taps=255):
|
||||
return lp(hp(x, f1, taps), f2, taps)
|
||||
|
||||
|
||||
def gurultu(d):
|
||||
return rng.standard_normal(int(d * SR))
|
||||
|
||||
|
||||
def zarf(d, a=0.005, r=0.05):
|
||||
n = int(d * SR)
|
||||
e = np.ones(n)
|
||||
na = max(1, min(n, int(a * SR)))
|
||||
e[:na] = np.linspace(0, 1, na)
|
||||
nr = max(1, min(n, int(r * SR)))
|
||||
e[n - nr :] *= np.linspace(1, 0, nr)
|
||||
return e
|
||||
|
||||
|
||||
def bos():
|
||||
return np.zeros((N, 2))
|
||||
|
||||
|
||||
def ekle(tampon, sinyal, t0, kazanc=1.0, pan=0.0):
|
||||
i = int(round(t0 * SR))
|
||||
if i >= N or i + len(sinyal) <= 0:
|
||||
return
|
||||
if sinyal.ndim == 1:
|
||||
a = (pan + 1) * np.pi / 4
|
||||
sinyal = np.stack([sinyal * np.cos(a), sinyal * np.sin(a)], 1) * np.sqrt(2)
|
||||
if i < 0:
|
||||
sinyal = sinyal[-i:]
|
||||
i = 0
|
||||
n = min(len(sinyal), N - i)
|
||||
tampon[i : i + n] += sinyal[:n] * kazanc
|
||||
|
||||
|
||||
def reverb(tampon, sure=2.4, tau=0.55, karisim=1.0):
|
||||
t = zaman(sure)
|
||||
cikis = np.zeros_like(tampon)
|
||||
for k in range(2):
|
||||
ir = rng.standard_normal(len(t)) * np.exp(-t / tau)
|
||||
ir[: int(0.012 * SR)] = 0
|
||||
ir = lp(ir, 5500)
|
||||
ir /= np.sqrt((ir**2).sum())
|
||||
cikis[:, k] = fftconv(tampon[:, k], ir)[: len(tampon)]
|
||||
return cikis * karisim
|
||||
|
||||
|
||||
# ------------------------------------------------------------------ #
|
||||
# Enstrümanlar #
|
||||
# ------------------------------------------------------------------ #
|
||||
|
||||
|
||||
def kick(guc=1.0):
|
||||
t = zaman(0.55)
|
||||
f = 44 + 120 * np.exp(-t / 0.032)
|
||||
faz = 2 * np.pi * np.cumsum(f) / SR
|
||||
govde = np.sin(faz) * np.exp(-t / 0.26)
|
||||
tik = hp(gurultu(0.55), 2500) * np.exp(-t / 0.003) * 0.35
|
||||
return np.tanh((govde + tik) * 1.6 * guc) * 0.9
|
||||
|
||||
|
||||
def clap():
|
||||
d = 0.35
|
||||
t = zaman(d)
|
||||
g = bp(gurultu(d), 900, 6000)
|
||||
e = np.zeros_like(t)
|
||||
for o in (0.0, 0.011, 0.022):
|
||||
e += np.where(t >= o, np.exp(-(t - o) / (0.006 if o < 0.02 else 0.13)), 0)
|
||||
return g * e * 0.55
|
||||
|
||||
|
||||
def hat(acik=False):
|
||||
d = 0.35 if acik else 0.08
|
||||
t = zaman(d)
|
||||
return hp(gurultu(d), 7500) * np.exp(-t / (0.11 if acik else 0.022)) * 0.28
|
||||
|
||||
|
||||
def bas(m, d):
|
||||
t = zaman(d)
|
||||
f = mf(m)
|
||||
s = sum(np.sin(2 * np.pi * f * k * t + k) / k ** 1.4 for k in range(1, 7))
|
||||
return s * zarf(d, 0.004, 0.06) * np.exp(-t / 0.9) * 0.55
|
||||
|
||||
|
||||
def ped(notalar, d, parlak=1.0):
|
||||
t = zaman(d)
|
||||
sol = np.zeros(len(t))
|
||||
sag = np.zeros(len(t))
|
||||
for m in notalar:
|
||||
for cent, pan in ((-8, -0.7), (0, 0.0), (8, 0.7)):
|
||||
f = mf(m) * 2 ** (cent / 1200)
|
||||
v = np.zeros(len(t))
|
||||
for k in range(1, 11):
|
||||
if f * k > 9000:
|
||||
break
|
||||
v += np.sin(2 * np.pi * f * k * t + rng.uniform(0, 6.28)) / k ** (1.9 - 0.4 * parlak)
|
||||
a = (pan + 1) * np.pi / 4
|
||||
sol += v * np.cos(a)
|
||||
sag += v * np.sin(a)
|
||||
e = zarf(d, 0.5, 0.9)
|
||||
# yavaş nefes: pedin içinde hafif hareket
|
||||
e *= 0.85 + 0.15 * np.sin(2 * np.pi * 0.25 * t)
|
||||
return np.stack([sol * e, sag * e], 1) * (0.06 / max(1, len(notalar) / 3))
|
||||
|
||||
|
||||
def pluck(m, d=0.5, parlak=1.0):
|
||||
t = zaman(d)
|
||||
f = mf(m)
|
||||
s = (
|
||||
np.sin(2 * np.pi * f * t) * np.exp(-t / 0.32)
|
||||
+ 0.45 * parlak * np.sin(2 * np.pi * 2 * f * t) * np.exp(-t / 0.14)
|
||||
+ 0.18 * parlak * np.sin(2 * np.pi * 3 * f * t) * np.exp(-t / 0.06)
|
||||
)
|
||||
return s * zarf(d, 0.002, 0.03) * 0.3
|
||||
|
||||
|
||||
def piyano(m, d=1.8):
|
||||
t = zaman(d)
|
||||
f = mf(m)
|
||||
s = (
|
||||
np.sin(2 * np.pi * f * t) * np.exp(-t / 0.9)
|
||||
+ 0.5 * np.sin(2 * np.pi * 2.001 * f * t) * np.exp(-t / 0.5)
|
||||
+ 0.22 * np.sin(2 * np.pi * 3.004 * f * t) * np.exp(-t / 0.25)
|
||||
+ 0.1 * np.sin(2 * np.pi * 4.01 * f * t) * np.exp(-t / 0.12)
|
||||
)
|
||||
return s * zarf(d, 0.003, 0.2) * 0.32
|
||||
|
||||
|
||||
def zil(m, d=1.4):
|
||||
t = zaman(d)
|
||||
f = mf(m)
|
||||
s = np.sin(2 * np.pi * f * t) * np.exp(-t / 0.5) + 0.35 * np.sin(2 * np.pi * 2.76 * f * t) * np.exp(-t / 0.25)
|
||||
return s * zarf(d, 0.002, 0.2) * 0.25
|
||||
|
||||
|
||||
def yukselen(d, f0=180, f1=1500):
|
||||
t = zaman(d)
|
||||
p = t / d
|
||||
f = f0 * (f1 / f0) ** p
|
||||
faz = 2 * np.pi * np.cumsum(f) / SR
|
||||
ton = (np.sin(faz) + 0.5 * np.sin(faz * 1.005 + 1)) * 0.25
|
||||
g = gurultu(d)
|
||||
parlak = hp(g, 3000)
|
||||
koyu = lp(g, 900)
|
||||
gur = koyu * (1 - p) + parlak * p
|
||||
return (ton + gur * 0.35) * p ** 2.2 * 0.6
|
||||
|
||||
|
||||
def darbe():
|
||||
"""Logo / final vuruşu: alt bas düşüşü + gövde + parlak patlama."""
|
||||
d = 2.6
|
||||
t = zaman(d)
|
||||
f = 30 + 45 * np.exp(-t / 0.25)
|
||||
faz = 2 * np.pi * np.cumsum(f) / SR
|
||||
alt = np.sin(faz) * np.exp(-t / 1.1)
|
||||
govde = lp(gurultu(d), 1400) * np.exp(-t / 0.18) * 0.8
|
||||
parlak = hp(gurultu(d), 4000) * np.exp(-t / 0.35) * 0.25
|
||||
return np.tanh((alt * 1.2 + govde + parlak) * 1.4) * 0.95
|
||||
|
||||
|
||||
def ters_sisme(notalar, d=1.2):
|
||||
"""Ters çevrilmiş ped + reverb: vuruştan önce çekilen nefes."""
|
||||
p = ped(notalar, d, parlak=1.4)
|
||||
p = p + reverb(p, 1.2, 0.35, 0.8)
|
||||
t = zaman(d)[:, None]
|
||||
return (p * (t / d) ** 2)[::-1] * 3.2
|
||||
|
||||
|
||||
# ------------------------------------------------------------------ #
|
||||
# Efektler #
|
||||
# ------------------------------------------------------------------ #
|
||||
|
||||
|
||||
def whoosh(d=0.7, tur="zoom"):
|
||||
t = zaman(d)
|
||||
g = gurultu(d)
|
||||
koyu = lp(g, 500 if tur == "zoom" else 900)
|
||||
acik = lp(g, 7000)
|
||||
p = t / d
|
||||
tepe = 0.62 if tur != "yuksel" else 0.5
|
||||
iz = np.exp(-((p - tepe) / 0.23) ** 2)
|
||||
karisim = koyu * (1 - iz) + acik * iz
|
||||
e = np.where(p < tepe, (p / tepe) ** 2.2, np.exp(-(p - tepe) / 0.12))
|
||||
s = karisim * e * 0.4
|
||||
if tur == "kaydir":
|
||||
pan = np.linspace(-0.8, 0.8, len(t))
|
||||
else:
|
||||
pan = np.zeros(len(t))
|
||||
a = (pan + 1) * np.pi / 4
|
||||
return np.stack([s * np.cos(a), s * np.sin(a)], 1) * np.sqrt(2)
|
||||
|
||||
|
||||
def pop(f=700, guc=1.0):
|
||||
t = zaman(0.12)
|
||||
fr = f * (1 + 0.9 * np.exp(-t / 0.012))
|
||||
faz = 2 * np.pi * np.cumsum(fr) / SR
|
||||
return np.sin(faz) * np.exp(-t / 0.045) * zarf(0.12, 0.001, 0.02) * 0.4 * guc
|
||||
|
||||
|
||||
def tik(f=2600, guc=1.0):
|
||||
t = zaman(0.03)
|
||||
s = hp(gurultu(0.03), 3000) * np.exp(-t / 0.0025) * 0.5 + np.sin(2 * np.pi * f * t) * np.exp(-t / 0.008) * 0.3
|
||||
return s * guc
|
||||
|
||||
|
||||
def tus():
|
||||
"""Klavye tuşu: kısa, gövdeli tık."""
|
||||
t = zaman(0.05)
|
||||
g = bp(gurultu(0.05), 1200, 6000) * np.exp(-t / 0.006)
|
||||
return (g * 0.5 + np.sin(2 * np.pi * rng.uniform(180, 260) * t) * np.exp(-t / 0.01) * 0.3) * rng.uniform(0.6, 1.0)
|
||||
|
||||
|
||||
def tiklama():
|
||||
"""Buton basışı."""
|
||||
t = zaman(0.08)
|
||||
return (bp(gurultu(0.08), 800, 5000) * np.exp(-t / 0.008) * 0.6 + np.sin(2 * np.pi * 160 * t) * np.exp(-t / 0.02) * 0.5)
|
||||
|
||||
|
||||
def pirilti(sure, yogun=40, f0=2200, f1=5200, guc=0.12):
|
||||
"""Pikseller dökülürken minik ışıltılar."""
|
||||
s = np.zeros((int((sure + 0.2) * SR), 2))
|
||||
for _ in range(int(yogun * sure)):
|
||||
t0 = rng.uniform(0, sure)
|
||||
b = pop(rng.uniform(f0, f1), guc=rng.uniform(0.3, 1.0))
|
||||
i = int(t0 * SR)
|
||||
a = (rng.uniform(-0.9, 0.9) + 1) * np.pi / 4
|
||||
s[i : i + len(b), 0] += b * np.cos(a) * guc * 1.4
|
||||
s[i : i + len(b), 1] += b * np.sin(a) * guc * 1.4
|
||||
return s
|
||||
|
||||
|
||||
def gumbur(d=1.0):
|
||||
t = zaman(d)
|
||||
return lp(gurultu(d), 180) * np.sin(np.pi * t / d) ** 2 * 1.2
|
||||
|
||||
|
||||
|
||||
def tok_whoosh(d=0.9, tur="zoom"):
|
||||
"""Geçiş sesi: tok, gövdeli. Alçak "vuuş" + varışta alt bas darbesi."""
|
||||
t = zaman(d)
|
||||
p = t / d
|
||||
g = gurultu(d)
|
||||
koyu = lp(g, 260)
|
||||
orta = lp(g, 1300)
|
||||
tepe = 0.68
|
||||
iz = np.clip((p / tepe), 0, 1) ** 1.5
|
||||
karisim = koyu * (1 - iz) + orta * iz
|
||||
e = np.where(p < tepe, (p / tepe) ** 2.4, np.exp(-(p - tepe) / 0.07))
|
||||
vuus = karisim * e * 0.9
|
||||
# Varış darbesi: 95 → 42 Hz inen sinüs
|
||||
d0 = int(tepe * d * SR)
|
||||
tt = zaman(d)[: len(t) - d0]
|
||||
f = 42 + 55 * np.exp(-tt / 0.06)
|
||||
faz = 2 * np.pi * np.cumsum(f) / SR
|
||||
darbe_ = np.zeros(len(t))
|
||||
darbe_[d0:] = np.sin(faz) * np.exp(-tt / 0.22) * 0.9
|
||||
govde = np.zeros(len(t))
|
||||
govde[d0:] = lp(gurultu(len(tt) / SR), 400)[: len(tt)] * np.exp(-tt / 0.05) * 0.5
|
||||
s = np.tanh((vuus + darbe_ + govde) * 1.3)
|
||||
pan = np.linspace(-0.6, 0.6, len(t)) if tur == "kaydir" else np.zeros(len(t))
|
||||
a = (pan + 1) * np.pi / 4
|
||||
return np.stack([s * np.cos(a), s * np.sin(a)], 1) * np.sqrt(2)
|
||||
|
||||
|
||||
def tok_vurus():
|
||||
"""Sert kesmelerin (bölüm kartları) vuruşu: tok davul + alt bas."""
|
||||
d = 0.9
|
||||
t = zaman(d)
|
||||
f = 40 + 90 * np.exp(-t / 0.045)
|
||||
faz = 2 * np.pi * np.cumsum(f) / SR
|
||||
alt = np.sin(faz) * np.exp(-t / 0.35)
|
||||
tom = np.sin(2 * np.pi * 92 * t) * np.exp(-t / 0.16) * 0.5
|
||||
tok = lp(gurultu(d), 700) * np.exp(-t / 0.035) * 0.8
|
||||
return np.tanh((alt + tom + tok) * 1.5) * 0.95
|
||||
|
||||
|
||||
# ------------------------------------------------------------------ #
|
||||
# Müzik #
|
||||
# ------------------------------------------------------------------ #
|
||||
|
||||
C9 = ([60, 67, 74, 76], 36)
|
||||
G6 = ([59, 67, 71, 74], 43)
|
||||
AM7 = ([57, 64, 67, 72], 45)
|
||||
FM9 = ([53, 60, 64, 67, 69], 41)
|
||||
ILERLEYIS = [C9, G6, AM7, FM9]
|
||||
ILERLEYIS_YZ = [AM7, FM9, C9, G6]
|
||||
|
||||
|
||||
def bam_ani(sahne):
|
||||
"""lensZoom geçişi 30 kare; kesme yarısında (15. kare) olur: BAM anı."""
|
||||
return S[sahne] + 15 / FPS
|
||||
|
||||
|
||||
def bwomp():
|
||||
"""'Off.' için esprili inen iki nota (tuba gibi yumuşak)."""
|
||||
d = 0.7
|
||||
t = zaman(d)
|
||||
f = np.where(t < 0.28, mf(52), mf(47)) * (1 - 0.04 * t)
|
||||
faz = 2 * np.pi * np.cumsum(f) / SR
|
||||
s = (np.sin(faz) + 0.3 * np.sin(2 * faz) + 0.1 * np.sin(3 * faz)) * zarf(d, 0.02, 0.2)
|
||||
s *= np.where(t < 0.28, 1, 0.9) * np.exp(-np.maximum(0, t - 0.28) / 0.35)
|
||||
return lp(s, 1800) * 0.5
|
||||
|
||||
|
||||
def soru_plink():
|
||||
"""'Kafan mı karıştı?' için yükselen soru tınısı."""
|
||||
a = zil(79, 0.5) * 0.8
|
||||
b = zil(84, 0.9)
|
||||
out = np.zeros(len(a) + int(0.16 * SR) + len(b))
|
||||
out[: len(a)] += a
|
||||
out[int(0.16 * SR) : int(0.16 * SR) + len(b)] += b
|
||||
return out
|
||||
|
||||
|
||||
def muzik():
|
||||
davul = bos()
|
||||
ahenk = bos()
|
||||
parlak = bos()
|
||||
kickler = []
|
||||
|
||||
def groove(bas_t, bitis_t, ilerleyis, arp=True, arp_parlak=1.0, davul_var=True, hafif=False):
|
||||
bar = 0
|
||||
t = bas_t
|
||||
while t < bitis_t - 0.01:
|
||||
notalar, kok = ilerleyis[bar % 4]
|
||||
d = min(2.0, bitis_t - t)
|
||||
ekle(ahenk, ped(notalar, d + 0.05) * zarf(d + 0.05, 0.4, 0.05)[:, None], t, 1.0)
|
||||
for k in range(8):
|
||||
tt = t + k * B / 2
|
||||
if tt >= bitis_t - 0.02:
|
||||
break
|
||||
ekle(ahenk, bas(kok + (12 if k % 4 == 3 else 0), B / 2 * 0.9), tt, 0.85)
|
||||
if arp:
|
||||
ton = sorted(set(notalar + [n + 12 for n in notalar]))
|
||||
desen = [0, 2, 1, 3, 2, 4, 3, 5, 4, 3, 2, 4, 1, 3, 2, 5]
|
||||
for k in range(16):
|
||||
tt = t + k * B / 4
|
||||
if tt >= bitis_t - 0.02:
|
||||
break
|
||||
ekle(ahenk, pluck(ton[desen[k] % len(ton)] + 12, 0.35, arp_parlak), tt, 0.5 if k % 4 else 0.7, pan=np.sin(k * 0.8) * 0.5)
|
||||
if davul_var:
|
||||
for k in range(4):
|
||||
tt = t + k * B
|
||||
if tt >= bitis_t - 0.02:
|
||||
break
|
||||
ekle(davul, kick(), tt, 0.8 if hafif else 0.95)
|
||||
kickler.append(tt)
|
||||
if k % 2 == 1 and not hafif:
|
||||
ekle(davul, clap(), tt, 0.6)
|
||||
ekle(davul, hat(), tt + B / 2, 0.5, pan=0.25)
|
||||
ekle(davul, hat(), tt + B / 4, 0.18, pan=-0.2)
|
||||
ekle(davul, hat(), tt + 3 * B / 4, 0.18, pan=-0.2)
|
||||
t += 2.0
|
||||
bar += 1
|
||||
|
||||
def saat(bas_t, bitis_t, guc=0.6):
|
||||
t = bas_t
|
||||
while t < bitis_t - 0.01:
|
||||
ekle(davul, tik(3400, 0.25), t, guc, pan=0.4)
|
||||
t += B / 2
|
||||
|
||||
def bam(t0, akor=C9):
|
||||
ekle(davul, darbe(), t0, 1.0)
|
||||
ekle(parlak, zil(84, 2.2), t0, 0.6)
|
||||
ekle(parlak, zil(79, 2.2), t0, 0.5)
|
||||
for j, m in enumerate(akor[0]):
|
||||
ekle(parlak, piyano(m + 12, 1.8), t0 + j * 0.02, 0.4)
|
||||
|
||||
def sessizlik_sonu(t_bam):
|
||||
"""Sessizliğin sonunda BAM'e çekilen ters nefes."""
|
||||
ekle(parlak, ters_sisme(C9[0], 0.7), t_bam - 0.7, 0.9)
|
||||
|
||||
b_logo, b_yz, b_final = bam_ani("logo"), bam_ani("danisman"), bam_ani("final")
|
||||
tik_final = S["final"] + ZAMAN_TIK["final"][0] / FPS
|
||||
|
||||
# --- Giriş: saat + ped + piyano; seçeneklerde kalp atışı
|
||||
saat(0, S["kaos"])
|
||||
ekle(ahenk, ped(AM7[0], S["secenek"] + 0.6), 0, 0.8)
|
||||
ekle(ahenk, ped(FM9[0], S["kaos"] - S["secenek"] + 0.3), S["secenek"], 0.9)
|
||||
for i, m in enumerate([76, 72, 69, 72, 76, 79, 76, 72, 69]):
|
||||
ekle(parlak, piyano(m), i * 0.75, 0.5, pan=0.3 if i % 2 else -0.3)
|
||||
t = S["secenek"]
|
||||
while t < S["kaos"]:
|
||||
ekle(davul, kick(0.5), t, 0.45)
|
||||
ekle(davul, kick(0.35), t + 0.18, 0.25)
|
||||
t += 1.0
|
||||
|
||||
# --- Kaos: gerilim → SERT DURUŞ (nefes sahnesi sessiz)
|
||||
dur1 = S["nefes"]
|
||||
ekle(ahenk, ped(FM9[0], 2.0) , S["kaos"], 1.0)
|
||||
ekle(ahenk, ped([55, 62, 67, 71, 74], dur1 - S["kaos"] - 2.0), S["kaos"] + 2.0, 1.1)
|
||||
ekle(parlak, yukselen(dur1 - S["kaos"] - 0.4), S["kaos"] + 0.4, 0.9)
|
||||
t = S["kaos"] + 1.0
|
||||
while t < dur1 - 1.0:
|
||||
ekle(davul, kick(0.8), t, 0.7)
|
||||
kickler.append(t)
|
||||
t += B
|
||||
adim = B / 2
|
||||
t = dur1 - 1.0
|
||||
while t < dur1 - 0.05:
|
||||
ekle(davul, clap(), t, 0.35 + 0.45 * (t - (dur1 - 1.0)))
|
||||
t += adim
|
||||
adim = max(B / 8, adim * 0.8)
|
||||
# Sessizlik: tek piyano notası, sonra ters nefes → BAM
|
||||
ekle(parlak, piyano(76, 2.4), dur1 + 0.45, 0.35)
|
||||
sessizlik_sonu(b_logo)
|
||||
bam(b_logo)
|
||||
|
||||
# --- Groove: logo (arp'sız) → üç adım (arp'lı), Off'ta SERT DURUŞ
|
||||
dur2 = S["off"]
|
||||
groove(b_logo, S["adim1"], ILERLEYIS, arp=False)
|
||||
groove(S["adim1"], dur2, ILERLEYIS, arp_parlak=1.2)
|
||||
# Off: esprili bwomp + soru tınısı; ters nefes → BAM (DanışmanlaKonuş)
|
||||
sessizlik_sonu(b_yz)
|
||||
bam(b_yz, AM7)
|
||||
|
||||
# --- Yapay zekâ: parlak groove; paket kartlarında vurgular
|
||||
groove(b_yz, S["paket"], ILERLEYIS_YZ, arp_parlak=1.6, hafif=True)
|
||||
groove(S["paket"], S["durust"], ILERLEYIS, arp_parlak=1.4)
|
||||
for k in range(3):
|
||||
ekle(davul, tok_vurus() * 0.6, S["paket"] + k * 1.5, 0.8)
|
||||
|
||||
# --- Dürüstlük: kırılma (piyano + ped) → Hazır'da SERT DURUŞ
|
||||
dur3 = S["hazir"]
|
||||
for i, (notalar, kok) in enumerate([AM7, FM9]):
|
||||
tt = S["durust"] + i * 2.0
|
||||
ekle(ahenk, ped(notalar, 2.0) * zarf(2.0, 0.3, 0.1)[:, None], tt, 1.1)
|
||||
for j, m in enumerate(notalar[1:]):
|
||||
ekle(parlak, piyano(m + 12, 1.8), tt + j * 0.18, 0.5)
|
||||
ekle(ahenk, bas(kok, 1.8), tt, 0.6)
|
||||
# Hazır: iki yumuşak tık, ters nefes → BAM (final)
|
||||
ekle(davul, tik(2400, 0.5), dur3 + 0.5, 0.6)
|
||||
ekle(davul, tik(2600, 0.5), dur3 + 1.0, 0.6)
|
||||
sessizlik_sonu(b_final)
|
||||
bam(b_final)
|
||||
|
||||
# --- Final: groove → butona tık = son akor → saat tıkırtısı döngüye
|
||||
groove(b_final, tik_final, ILERLEYIS, arp_parlak=1.3)
|
||||
ekle(davul, darbe(), tik_final, 0.7)
|
||||
ekle(ahenk, ped(C9[0] + [48], 2.8), tik_final, 1.2)
|
||||
for j, m in enumerate([72, 76, 79, 84, 88]):
|
||||
ekle(parlak, piyano(m, 2.6), tik_final + j * 0.06, 0.45)
|
||||
ekle(parlak, zil(96, 2.5), tik_final, 0.3)
|
||||
saat(SON - 1.0, SON + 0.01, 0.45)
|
||||
|
||||
zarf_sc = np.ones(N)
|
||||
tt = np.arange(N) / SR
|
||||
for k in kickler:
|
||||
i = int(k * SR)
|
||||
n = min(int(0.35 * SR), N - i)
|
||||
if n > 0:
|
||||
zarf_sc[i : i + n] = np.minimum(zarf_sc[i : i + n], 1 - 0.45 * np.exp(-tt[:n] / 0.11))
|
||||
ahenk *= zarf_sc[:, None]
|
||||
|
||||
karisim = davul * 0.9 + ahenk + parlak
|
||||
yanki = reverb(ahenk * 0.35 + parlak * 0.6 + davul * 0.08, 2.6, 0.6)
|
||||
# Sert duruşlar gerçekten sessiz olsun: yankı kuyruğu sessizlik başında hızla kısılır
|
||||
for d in (S["nefes"], S["off"], S["hazir"]):
|
||||
i0 = int(d * SR)
|
||||
n = int(0.35 * SR)
|
||||
z = np.ones(N)
|
||||
z[i0 : i0 + n] = np.linspace(1, 0.08, n)
|
||||
z[i0 + n : int((d + 1.7) * SR)] = 0.08
|
||||
yanki *= z[:, None]
|
||||
return karisim + yanki
|
||||
|
||||
|
||||
# ------------------------------------------------------------------ #
|
||||
# Efekt izi #
|
||||
# ------------------------------------------------------------------ #
|
||||
|
||||
ZAMAN_TIK = Z["tiklar"]
|
||||
ZAMAN_YAZ = Z["yazma"]
|
||||
|
||||
|
||||
def efektler():
|
||||
e = bos()
|
||||
|
||||
# Geçişler: zoomBlur → tok vuuş; lensZoom → emiş + alt bas düşüşü (BAM müzikte)
|
||||
for s in Z["sahneler"][1:]:
|
||||
g = s.get("gecis", {})
|
||||
tur = g.get("tur")
|
||||
if tur == "zoomBlur":
|
||||
ekle(e, tok_whoosh(0.9), S[s["id"]] + 0.3 - 0.9 * 0.68, 0.9)
|
||||
elif tur == "lensZoom":
|
||||
t_bam = bam_ani(s["id"])
|
||||
ekle(e, whoosh(0.5, "zoom")[::-1] * 0.8, t_bam - 0.5, 0.9)
|
||||
ekle(e, tok_vurus(), t_bam, 0.9)
|
||||
|
||||
# İmleç tıkları ve yazma (tek kaynak: zaman.json)
|
||||
for sahne, kareler in ZAMAN_TIK.items():
|
||||
for f in kareler:
|
||||
ekle(e, tiklama(), lf(sahne, f), 0.75)
|
||||
ekle(e, pop(1300, 0.35), lf(sahne, f) + 0.01)
|
||||
for sahne, araliklar in ZAMAN_YAZ.items():
|
||||
for a, b in araliklar:
|
||||
f = a
|
||||
while f < b:
|
||||
ekle(e, tus(), lf(sahne, f), 0.7)
|
||||
f += 4 if sahne == "adim1" else rng.choice([2, 3])
|
||||
|
||||
# Açılış: rozet, iz açılışı
|
||||
ekle(e, pop(900, 0.5), lf("acilis", 8))
|
||||
ekle(e, whoosh(0.6, "yuksel") * 0.4, lf("acilis", 14), 0.6)
|
||||
# Seçenekler: sayaç, sheen
|
||||
for k in range(16):
|
||||
ekle(e, tik(2000 + k * 70, 0.4), lf("secenek", 4 + 36 * (k / 15) ** 1.9))
|
||||
ekle(e, pop(1100, 0.8), lf("secenek", 38))
|
||||
ekle(e, pirilti(0.5, 60, 3000, 6000), lf("secenek", 50), 0.7)
|
||||
# Kaos: kartlar
|
||||
for i in range(8):
|
||||
ekle(e, pop(rng.uniform(420, 880), 0.7), lf("kaos", 6 + i * 5), pan=rng.uniform(-0.7, 0.7))
|
||||
# Off: esprili ses
|
||||
ekle(e, bwomp(), lf("off", 3), 0.9)
|
||||
ekle(e, soru_plink() * 0.8, lf("off", 20), 0.8)
|
||||
# Logo: dev kelime → kesme, rota, sheen
|
||||
ekle(e, whoosh(0.5, "kaydir") * 0.6, lf("logo", 18), 0.8)
|
||||
ekle(e, pop(700, 0.9), lf("logo", 26))
|
||||
ekle(e, pirilti(0.5, 60, 3000, 6000), lf("logo", 46), 0.7)
|
||||
# Adımlar: başlık sheen
|
||||
for a in ("adim1", "adim2", "adim3"):
|
||||
ekle(e, pop(620, 0.8), lf(a, 2))
|
||||
ekle(e, pirilti(0.45, 50, 3000, 6000), lf(a, 4), 0.6)
|
||||
ekle(e, pop(600, 0.8), lf("adim1", 104))
|
||||
for i in range(24):
|
||||
ekle(e, pop(1800 + i * 40, 0.25), lf("adim1", ZAMAN_TIK["adim1"][-1] + 10 + i * 1.1))
|
||||
# Adım 2: harita yağmuru, ısı fırçası, kontur dolgu
|
||||
ekle(e, pirilti(1.4, 90), lf("adim2", 4), 0.9)
|
||||
ekle(e, pirilti(2.3, 32, 1500, 3000, 0.08), lf("adim2", 50), 0.7)
|
||||
ekle(e, whoosh(1.2, "yuksel") * 0.35, lf("adim2", 146), 0.7)
|
||||
# Adım 3: yol çizimi, 24 kare pentatonik
|
||||
ekle(e, pirilti(1.3, 40, 2400, 4800, 0.1), lf("adim3", 6), 0.7)
|
||||
penta = [60, 62, 64, 67, 69]
|
||||
for i in range(24):
|
||||
m = penta[i % 5] + 12 * (i // 5)
|
||||
ekle(e, pop(min(mf(m + 12), 5000), 0.55), lf("adim3", 62 + i * 2), pan=((i % 8) / 7 - 0.5) * 0.8)
|
||||
for f in (112, 117, 122):
|
||||
ekle(e, pop(800, 0.5), lf("adim3", f))
|
||||
# Danışman: piksel patlaması, sheen
|
||||
ekle(e, pirilti(0.8, 90, 1800, 5200, 0.14), lf("danisman", 15), 0.9)
|
||||
ekle(e, pirilti(0.5, 60, 3000, 6000), lf("danisman", 28), 0.7)
|
||||
# Sohbet: araç, cevaplar
|
||||
ts = ZAMAN_TIK["sohbet"]
|
||||
for bas_f, bit_f, cev_f in [(ts[1] + 6, ts[1] + 32, 90), (ts[3] + 6, ts[3] + 22, 224)]:
|
||||
ekle(e, pop(1200, 0.4), lf("sohbet", bas_f))
|
||||
f = bas_f + 6
|
||||
while f < bit_f:
|
||||
ekle(e, tik(4200, 0.15), lf("sohbet", f), 0.6)
|
||||
f += 6
|
||||
ekle(e, zil(88, 0.9), lf("sohbet", cev_f), 0.3)
|
||||
ekle(e, zil(95, 0.9), lf("sohbet", cev_f + 3), 0.22)
|
||||
for f in (100, 107, 114):
|
||||
ekle(e, pop(900, 0.5), lf("sohbet", f))
|
||||
ekle(e, pop(1000, 0.8), lf("sohbet", 242))
|
||||
# Paket: kart sheen'leri, sürükle-bırak
|
||||
for f in (2, 47, 92):
|
||||
ekle(e, pirilti(0.45, 50, 3000, 6000), lf("paket", f), 0.6)
|
||||
tp = ZAMAN_TIK["paket"]
|
||||
ekle(e, whoosh(0.8, "kaydir") * 0.4, lf("paket", tp[0]), 0.6)
|
||||
ekle(e, tok_vurus() * 0.3, lf("paket", tp[1]), 0.8)
|
||||
# Dürüstlük
|
||||
ekle(e, pop(330, 1.0), lf("durust", 0))
|
||||
ekle(e, pirilti(1.2, 36, 1600, 3200, 0.09), lf("durust", 56), 0.7)
|
||||
for k, f in enumerate([94, 99, 104]):
|
||||
ekle(e, pop([784, 659, 523][k], 0.7), lf("durust", f))
|
||||
# Hazır: üç kare
|
||||
for i in range(3):
|
||||
ekle(e, pop([660, 880, 990][i], 0.6), lf("hazir", 4 + i * 6))
|
||||
# Final: buton, çöküş
|
||||
ekle(e, pop(700, 0.9), lf("final", 38))
|
||||
tf = ZAMAN_TIK["final"][0]
|
||||
ekle(e, tok_whoosh(0.9)[::-1] * 0.8, lf("final", tf + 30) - 0.9, 0.8)
|
||||
|
||||
e += reverb(e, 1.4, 0.3, 0.25)
|
||||
return e
|
||||
|
||||
|
||||
# ------------------------------------------------------------------ #
|
||||
# Yazım #
|
||||
# ------------------------------------------------------------------ #
|
||||
|
||||
|
||||
def yaz(yol, x, hedef_tepe=0.89, hedef_rms=None):
|
||||
n = int(SON * SR)
|
||||
# Döngü: SON'dan taşan kuyruğu başa ekle ki son → ilk kare geçişi kesintisiz olsun
|
||||
kuyruk = x[n:]
|
||||
x = x[:n].copy()
|
||||
x[: len(kuyruk)] += kuyruk
|
||||
if hedef_rms:
|
||||
rms = np.sqrt((x**2).mean())
|
||||
x = x * (hedef_rms / rms)
|
||||
x = np.tanh(x * 1.1) / np.tanh(1.1) # yumuşak limitleyici
|
||||
x = x / np.abs(x).max() * hedef_tepe
|
||||
veri = (x * 32767).astype("<i2")
|
||||
yol.parent.mkdir(parents=True, exist_ok=True)
|
||||
with wave.open(str(yol), "wb") as w:
|
||||
w.setnchannels(2)
|
||||
w.setsampwidth(2)
|
||||
w.setframerate(SR)
|
||||
w.writeframes(veri.tobytes())
|
||||
print(f"{yol.relative_to(KOK)} {len(x) / SR:.1f} sn")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
yaz(KOK / "public/ses/muzik.wav", muzik(), 0.89, hedef_rms=0.16)
|
||||
yaz(KOK / "public/ses/efekt.wav", efektler(), 0.8)
|
||||
Reference in New Issue
Block a user