import numpy as np
import sounddevice as sd
from scipy.io.wavfile import write
import tkinter as tk
from tkinter import ttk, messagebox

# 脳波と周波数差
brainwave_freqs = {
    "Delta (深い睡眠)": 2,
    "Theta (瞑想・創造)": 6,
    "Alpha (リラックス・集中)": 10,
    "Beta (活動・思考)": 20,
    "Gamma (高度認知)": 40
}

def generate_holophonic_binaural(base_freq, beat_freq, duration, volume, holophonic, sample_rate=44100):
    t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)
    left = np.sin(2 * np.pi * base_freq * t)
    right = np.sin(2 * np.pi * (base_freq + beat_freq) * t)

    if holophonic:
        # 音が左右に揺れ動くパン効果をつける
        pan = 0.5 * (1 + np.sin(2 * np.pi * 0.2 * t))  # 0.2Hzで左右に揺れる
        left *= (1 - pan)
        right *= pan

    stereo = np.stack([left, right], axis=1)
    return (stereo * volume).astype(np.float32), sample_rate

def play_sound():
    selection = combo.get()
    if selection not in brainwave_freqs:
        messagebox.showerror("エラー", "脳波タイプを選択してください。")
        return

    stereo, sr = generate_holophonic_binaural(
        base_freq=base_freq_slider.get(),
        beat_freq=brainwave_freqs[selection],
        duration=duration_slider.get(),
        volume=volume_slider.get(),
        holophonic=bool(holophonic_var.get())
    )
    sd.play(stereo, samplerate=sr)
    sd.wait()

def save_wav():
    selection = combo.get()
    if selection not in brainwave_freqs:
        messagebox.showerror("エラー", "脳波タイプを選択してください。")
        return

    stereo, sr = generate_holophonic_binaural(
        base_freq=base_freq_slider.get(),
        beat_freq=brainwave_freqs[selection],
        duration=duration_slider.get(),
        volume=volume_slider.get(),
        holophonic=bool(holophonic_var.get())
    )
    suffix = "_holo" if holophonic_var.get() else ""
    filename = f"{selection.split()[0]}_{base_freq_slider.get()}Hz_{duration_slider.get()}s{suffix}.wav"
    write(filename, sr, (stereo * 32767).astype(np.int16))
    messagebox.showinfo("保存完了", f"{filename} を保存しました。")

# GUI構築
root = tk.Tk()
root.title("ホロフォニック・バイノーラルビートジェネレーター")
root.geometry("520x460")

tk.Label(root, text="脳波を選択:", font=("Arial", 13)).pack(pady=5)
combo = ttk.Combobox(root, values=list(brainwave_freqs.keys()), font=("Arial", 12), state="readonly")
combo.pack(pady=5)

tk.Label(root, text="ベース周波数（Hz）:", font=("Arial", 11)).pack()
base_freq_slider = tk.Scale(root, from_=100, to=1000, orient="horizontal", resolution=10)
base_freq_slider.set(400)
base_freq_slider.pack()

tk.Label(root, text="音量（0.0〜1.0）:", font=("Arial", 11)).pack()
volume_slider = tk.Scale(root, from_=0.0, to=1.0, resolution=0.01, orient="horizontal")
volume_slider.set(0.5)
volume_slider.pack()

tk.Label(root, text="再生時間（秒）:", font=("Arial", 11)).pack()
duration_slider = tk.Scale(root, from_=5, to=60, orient="horizontal")
duration_slider.set(10)
duration_slider.pack()

# ホロフォニックON/OFF
holophonic_var = tk.IntVar()
tk.Checkbutton(root, text="ホロフォニック効果を有効にする（左右パンニング）", variable=holophonic_var).pack(pady=10)

frame = tk.Frame(root)
frame.pack(pady=15)
tk.Button(frame, text="▶ 再生", command=play_sound, width=15).pack(side="left", padx=10)
tk.Button(frame, text="💾 保存（.wav）", command=save_wav, width=15).pack(side="right", padx=10)

root.mainloop()

