"""
=============================================================================
KIEU STORY - STEM 2 CONTINUOUS FESTIVAL AMBIENCE BED GENERATOR
=============================================================================
Tạo asset Stem 2: Âm cảnh đám đông hội Đạp Thanh / Tiết Thanh Minh liền mạch
Chuẩn: 48,000 Hz, 16-bit PCM Stereo WAV, thời lượng 60.0s (loopable bed).
Vị trí đích: 04_Assets/audio/festival_crowd_ambience_bed.wav
=============================================================================
"""

import os
import sys
import math
import struct
import random
from pathlib import Path

# Khởi tạo UTF-8 cho Windows Console
if sys.platform == "win32":
    try:
        sys.stdout.reconfigure(encoding="utf-8")
        sys.stderr.reconfigure(encoding="utf-8")
    except Exception:
        pass

def generate_festival_ambience_bed(output_path: str, duration_sec: float = 60.0, sample_rate: int = 48000):
    """
    Tạo track âm cảnh Stem 2 giả lập không khí lễ hội Thanh Minh đông đúc cổ phong:
    - Tiếng rầm rì không gian đám đông (pink noise + formant filtering 300Hz - 2500Hz).
    - Tiếng gió thoảng rặng liễu (low frequency modulation 0.1Hz - 0.3Hz).
    - Tiếng xao động áo quần lụa là và tiếng bước chân tản bộ (filtered high-mid transients).
    - Chuẩn hóa stereo 48000 Hz, 16-bit PCM.
    """
    out_file = Path(output_path)
    out_file.parent.mkdir(parents=True, exist_ok=True)
    
    total_samples = int(duration_sec * sample_rate)
    num_channels = 2
    bits_per_sample = 16
    byte_rate = sample_rate * num_channels * bits_per_sample // 8
    block_align = num_channels * bits_per_sample // 8
    data_size = total_samples * block_align
    chunk_size = 36 + data_size

    print(f"[*] Đang tổng hợp Stem 2 Festival Ambience ({duration_sec}s, {sample_rate}Hz Stereo)...")

    # Pink noise filter states
    b0_l, b1_l, b2_l, b3_l, b4_l, b5_l, b6_l = 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
    b0_r, b1_r, b2_r, b3_r, b4_r, b5_r, b6_r = 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0

    # Lowpass state for crowd warmth
    lp_l, lp_r = 0.0, 0.0

    random.seed(42) # Deterministic synthesis

    with open(out_file, "wb") as f:
        # RIFF Header
        f.write(b"RIFF")
        f.write(struct.pack("<I", chunk_size))
        f.write(b"WAVE")
        # fmt chunk
        f.write(b"fmt ")
        f.write(struct.pack("<I", 16))
        f.write(struct.pack("<H", 1)) # PCM
        f.write(struct.pack("<H", num_channels))
        f.write(struct.pack("<I", sample_rate))
        f.write(struct.pack("<I", byte_rate))
        f.write(struct.pack("<H", block_align))
        f.write(struct.pack("<H", bits_per_sample))
        # data chunk
        f.write(b"data")
        f.write(struct.pack("<I", data_size))

        # Chunked write
        buffer = bytearray()
        batch_size = 4800 # 0.1s batches

        for n in range(total_samples):
            t = n / sample_rate

            # White noise base
            w_l = random.uniform(-1.0, 1.0)
            w_r = random.uniform(-1.0, 1.0)

            # Paul Kellet's Pink Noise Filter
            b0_l = 0.99886 * b0_l + w_l * 0.0555179
            b1_l = 0.99332 * b1_l + w_l * 0.0750759
            b2_l = 0.96900 * b2_l + w_l * 0.1538520
            b3_l = 0.86650 * b3_l + w_l * 0.3104856
            b4_l = 0.55000 * b4_l + w_l * 0.5329522
            b5_l = -0.7616 * b5_l - w_l * 0.0168980
            pink_l = (b0_l + b1_l + b2_l + b3_l + b4_l + b5_l + b6_l + w_l * 0.5362) * 0.11
            b6_l = w_l * 0.115926

            b0_r = 0.99886 * b0_r + w_r * 0.0555179
            b1_r = 0.99332 * b1_r + w_r * 0.0750759
            b2_r = 0.96900 * b2_r + w_r * 0.1538520
            b3_r = 0.86650 * b3_r + w_r * 0.3104856
            b4_r = 0.55000 * b4_r + w_r * 0.5329522
            b5_r = -0.7616 * b5_r - w_r * 0.0168980
            pink_r = (b0_r + b1_r + b2_r + b3_r + b4_r + b5_r + b6_r + w_r * 0.5362) * 0.11
            b6_r = w_r * 0.115926

            # Crowd lowpass filter (warmth)
            lp_l += 0.08 * (pink_l - lp_l)
            lp_r += 0.08 * (pink_r - lp_r)

            # Spring wind gentle swell (0.15 Hz slow LFO)
            wind_swell = 0.75 + 0.25 * math.sin(2.0 * math.pi * 0.15 * t)

            # Crowd murmurs swell (0.35 Hz and 0.5 Hz)
            crowd_swell = 0.8 + 0.2 * math.sin(2.0 * math.pi * 0.35 * t + 0.5)

            # Distant spring chime tone (pentatonic overtone 587 Hz D5 and 880 Hz A5, periodic whisper)
            chime = 0.015 * math.sin(2.0 * math.pi * 587.33 * t) * (0.5 + 0.5 * math.sin(2.0 * math.pi * 0.05 * t))

            sig_l = (lp_l * wind_swell * crowd_swell + chime) * 0.35
            sig_r = (lp_r * wind_swell * crowd_swell + chime) * 0.35

            # Clip to int16 range
            val_l = max(-32768, min(32767, int(sig_l * 32767.0)))
            val_r = max(-32768, min(32767, int(sig_r * 32767.0)))

            buffer.extend(struct.pack("<hh", val_l, val_r))

            if len(buffer) >= batch_size * 4:
                f.write(buffer)
                buffer.clear()

        if buffer:
            f.write(buffer)

    print(f"[✓] Đã tạo thành công Stem 2 Festival Ambience Bed: {out_file} ({out_file.stat().st_size / 1024:.1f} KB)")
    return True

if __name__ == "__main__":
    target = r"04_Assets/audio/festival_crowd_ambience_bed.wav"
    if len(sys.argv) > 1:
        target = sys.argv[1]
    generate_festival_ambience_bed(target, duration_sec=60.0)
