import math
import wave
import numpy as np

sample_rate = 48000
duration = 20.0
total_samples = int(duration * sample_rate)
t = np.linspace(0, duration, total_samples, endpoint=False)

# Frequencies in D minor / F pentatonic:
# D2=73.42, A2=110.00, D3=146.83, F3=174.61, G3=196.00, A3=220.00, C4=261.63, D4=293.66, E4=329.63, F4=349.23
freqs = [73.42, 110.00, 146.83, 174.61, 220.00, 261.63, 293.66]
weights = [0.22, 0.18, 0.16, 0.12, 0.10, 0.08, 0.06]

pad_l = np.zeros(total_samples)
pad_r = np.zeros(total_samples)

# Envelope:
# 0s - 3s: soft fade in
# 3s - 12s: warm plateau (0.6)
# 12s - 16s: majestic swell for title reveal (up to 1.0 at 14.5s)
# 16s - 20s: gentle decrescendo down to 0.15 at 20s
env = np.ones(total_samples)
for i in range(total_samples):
    ti = t[i]
    if ti < 3.0:
        env[i] = (ti / 3.0) ** 1.8 * 0.55
    elif ti < 11.5:
        env[i] = 0.55 + 0.10 * math.sin((ti - 3.0) / 8.5 * math.pi * 0.5)
    elif ti < 14.5:
        # Crescendo to title reveal peak
        p = (ti - 11.5) / 3.0
        env[i] = 0.65 + 0.35 * (math.sin(p * math.pi * 0.5) ** 2)
    elif ti < 17.0:
        # Sustain peak
        p = (ti - 14.5) / 2.5
        env[i] = 1.0 - 0.30 * p
    else:
        # Smooth decrescendo to transition into prologue
        p = (ti - 17.0) / 3.0
        env[i] = 0.70 * ((1.0 - p) ** 1.5) + 0.08

for f, w in zip(freqs, weights):
    # Gentle chorusing with slight detuning
    detune = 0.0018
    # Slow vibrato
    vib = 0.002 * np.sin(2.0 * np.pi * 4.2 * t)
    phase_l = np.random.uniform(0, 2 * np.pi)
    phase_r = np.random.uniform(0, 2 * np.pi)
    
    tone_l = np.sin(2.0 * np.pi * f * (1.0 - detune + vib) * t + phase_l)
    tone_r = np.sin(2.0 * np.pi * f * (1.0 + detune + vib) * t + phase_r)
    
    pad_l += w * tone_l
    pad_r += w * tone_r

# Warm sub harmonic (D1 = 36.71 Hz)
pad_l += 0.12 * np.sin(2.0 * np.pi * 36.71 * t)
pad_r += 0.12 * np.sin(2.0 * np.pi * 36.71 * t)

pad_l = pad_l * env
pad_r = pad_r * env

max_val = max(np.max(np.abs(pad_l)), np.max(np.abs(pad_r)))
if max_val > 0:
    pad_l = (pad_l / max_val) * 0.70
    pad_r = (pad_r / max_val) * 0.70

print('Ambient pad synthesized successfully! Length:', len(pad_l))
