From ccf21dac7636ee2b0a2098702c5f235c34ee1744 Mon Sep 17 00:00:00 2001 From: Seiji Nakamura Date: Mon, 12 May 2025 15:19:47 +0900 Subject: [PATCH] first commit --- .gitignore | 1 + holphonix.py | 98 +++++++++++++++++++++++++++++++++ run.py | 93 ++++++++++++++++++++++++++++++++ setup.md | 150 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 342 insertions(+) create mode 100644 .gitignore create mode 100644 holphonix.py create mode 100644 run.py create mode 100644 setup.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..691037e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.venv/* diff --git a/holphonix.py b/holphonix.py new file mode 100644 index 0000000..48ee557 --- /dev/null +++ b/holphonix.py @@ -0,0 +1,98 @@ +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() + diff --git a/run.py b/run.py new file mode 100644 index 0000000..735d265 --- /dev/null +++ b/run.py @@ -0,0 +1,93 @@ +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_binaural(base_freq, beat_freq, duration, volume, 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) + 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_binaural( + base_freq=base_freq_slider.get(), + beat_freq=brainwave_freqs[selection], + duration=duration_slider.get(), + volume=volume_slider.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_binaural( + base_freq=base_freq_slider.get(), + beat_freq=brainwave_freqs[selection], + duration=duration_slider.get(), + volume=volume_slider.get() + ) + filename = f"{selection.split()[0]}_{base_freq_slider.get()}Hz_{duration_slider.get()}s.wav" + write(filename, sr, (stereo * 32767).astype(np.int16)) + messagebox.showinfo("保存完了", f"{filename} を保存しました。") + +# GUI作成 +root = tk.Tk() +root.title("脳波バイノーラルビート ジェネレーター Pro") +root.geometry("500x400") + +# 脳波選択 +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() + +# ボタン +frame = tk.Frame(root) +frame.pack(pady=20) + +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() + diff --git a/setup.md b/setup.md new file mode 100644 index 0000000..9653387 --- /dev/null +++ b/setup.md @@ -0,0 +1,150 @@ +ホロフォニクス(**Holophonics**)は、3D空間的な定位を再現する音響技術で、**左右耳の時間差・位相差・音量差**などを利用して「音が動いている」「周囲に存在している」ように錯覚させるものです。ASMRやバイノーラル録音と非常に近い技術です。 + +--- + +## ✅ 今回の目的 + +バイノーラルビート生成GUIを拡張して、 + +> **音が左右に移動するホロフォニクス効果を再現**できるツールを作成します。 + +--- + +## 🧩 Holophonics 効果を再現する仕組み(簡易) + +* 音を左右にゆっくりパン(left→right→left)させる +* 各チャネルに **音量差 + 遅延** をつけて移動感を出す + +--- + +## 🎛️ コントロール内容 + +* 脳波選択(例:Alpha) +* ベース周波数・差分周波数 +* 再生時間 +* 音量 +* 「ホロフォニック効果」ON/OFFスイッチ ✅ + +--- + +## 🧩 コード(ホロフォニック効果付きGUI) + +```python +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() +``` + +--- + +## 🎧 効果確認方法 + +* **ステレオヘッドホンを必ず使用**してください(イヤホン不可)。 +* 「ホロフォニック効果ON」にすると、音が**左右にふわふわ動く感覚**が得られます。 +* 目を閉じると「空間に音があるような感覚」に。 + +--- + +## ✅ 今後追加できるアイデア + +* 🎞️ リアルタイム波形ビジュアライザー +* 🎯 音像位置をマウスで操る3Dマップ +* 🌗 フェードイン・フェードアウト +* ⏺️ ホロフォニック録音からの再現 + +ご希望があれば、それらの機能も順次実装していけます。どれを優先して追加しましょうか? +