Files
kolaytercih-post/ses/uret.py
bilalgursen dc5c87b6aa 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>
2026-09-30 20:22:38 +03:00

679 lines
23 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
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)