このドキュメントは大規模なリファクタリングの設計と実装計画を記録するものです。
- C++側:
src/Node.h
にJoinNode
クラスが定義- 複数の入力(最大 5 つ)を受け取り、それらを加算して 1 つの出力に
step()
メソッドで L/R チャンネルを個別に加算処理
- フロントエンド:
frontend/src/App.tsx
でnodeInfo
として定義numberOfInputs: 5, numberOfOutputs: 1
- UI では「+」アイコンで表示
- グラフ構築:
src/Voice.cpp
のupdateGraph()
でノード間接続を管理 - パス挿入:
frontend/src/component/graph/Path.tsx
で「Insert Join」オプション提供
osc.0 ─→ join ─→ filter.0 ─→ destination
osc.1 ─→ join ─→ filter.0 ─→ destination
Parameters.h
:MAX_JOINS = 5
,NODE_KIND::Join
Voice.h
:std::vector<std::shared_ptr<JoinNode>> joins
配列
- Join ノードが常に表示されることで、シンプルな接続でも中間ノードが必要
- 「+」ボタンが視覚的なノイズとなり、直感的でない操作感
- 単純な 1 対 1 接続でも Join ノードが必要
- グラフ構築時の不要な中間処理
- メモリ使用量の増加(未使用の Join ノードインスタンス)
-
Join ノードの完全削除
- UI から「+」ボタンを削除
- C++コードから JoinNode クラスを削除
- 関連する定数・enum・配列を削除
-
直接接続の実現
osc.0 -> filter.0
の直接接続を可能に- 複数入力が必要な場合の新しいアーキテクチャ設計
-
UI の簡素化
- パス挿入メニューから Join オプションを削除
- グラフ表示の視覚的な改善
- ユーザビリティ向上: より直感的な操作性
- 「filter に音源を追加したい」→ filter の"Add Input"をクリック
- 中間の「+」ボタンが不要になり、直接的な操作が可能
- グラフがよりシンプルで理解しやすく
- パフォーマンス改善: 不要な中間処理の削除
- メモリ効率: 未使用ノードインスタンスの削除
- コードの簡素化: 保守性の向上
- UI 一貫性: すべての入力可能ノードで統一された操作方法
# 1対1接続の場合(従来通り)
osc.0 ─→ filter.0 ─→ destination
# 複数入力が必要な場合(新方式)
# ユーザーの視点
osc.0 ──┐
├─→ filter.0 ─→ destination
osc.1 ──┘
# 内部実装
osc.0 ──┐
├─→ [内部JoinNode] ──→ filter.0 ─→ destination
osc.1 ──┘
- 各ノードの
addInput()
メソッドを改良 - 単一入力: 従来通りの処理
- 複数入力: 内部的に
JoinNode
を自動作成 removeAllInputs()
で内部JoinNode
もリセット
-
後方互換性の維持
- 既存のプロジェクトファイルで動作するように配慮
- 段階的な移行アプローチ
-
安全な削除手順
- フロントエンドから先に削除
- バックエンドは最後に削除
- 各段階でのテスト実施
完了済み: 現状分析
- Join ノードの実装詳細を確認
- 複数入力を受け付けるノードの調査
- 関連するファイルとコードの特定
次のステップ: 複数入力対応方針の決定
- 採用方針: 内部的な
JoinNode
の活用 - コンセプト: UI から Join ノードを削除しつつ、バックエンドでは既存の
JoinNode
を内部的に使用 - 理由:
- 既存の実装を最大限再利用
- 各ノードの単一入力制約を保持
- 大幅な変更を避けて安全にリファクタリング
- UI 改善と実装安定性の両立
- 改善点:
- ユーザーには直感的な直接接続が見える
- 複数入力時も内部的に安定した処理
- 既存の
JoinNode
のテスト済み実装を活用
Join 関連の削除:
-
frontend/src/App.tsx
: nodeInfo から join エントリを削除 -
frontend/src/component/graph/Path.tsx
: "Insert Join"メニューオプションを削除 -
frontend/src/Icon.tsx
: join アイコンを削除(または非使用にマーク)
"Add Input"機能の移行:
-
frontend/src/component/graph/Node.tsx
: 入力可能ノードの "Add Input" 表示ロジック変更- 現在: join ノードのみ "Add Input" 表示
- 新方針: filter, pan, destination など入力可能な全ノードで "Add Input" 表示
- 表示条件:
hidden: numberOfConnectedInputs >= numberOfInputs
(変更なし)
-
frontend/src/App.tsx
: nodeInfo のnumberOfInputs
調整const nodeInfo: Record<string, NodeInfo> = { filter: { numberOfInputs: 5, // 複数入力対応(内部的にJoinNode使用) numberOfOutputs: 1, icon: icons.filter, primary: true, }, pan: { numberOfInputs: 5, // 複数入力対応 numberOfOutputs: 1, icon: icons.pan, primary: true, }, dest: { numberOfInputs: 5, // 複数入力対応 numberOfOutputs: 0, icon: icons.dest, primary: false, }, // join エントリは削除 };
- 動作確認:
handleAddInputNode(node.index)
の流れ- ユーザーが filter の"Add Input"をクリック
onAddInputNode()
→handlers.handleAddInputNode(node.index)
addInputNode(toRefIndex)
native function 呼び出し- バックエンドで新しい osc が作成され、filter に接続
- バックエンドの FilterNode::addInput()で内部的に JoinNode を作成(2 つ目以降の入力)
-
src/Node.h
: 複数入力を受け取る可能性のあるノードを内部JoinNode
対応に変更FilterNode
,DestinationNode
,PanNode
などに適用addInput
が複数回呼ばれた場合に内部的にJoinNode
を作成- 既存の単一入力の場合はそのまま、複数入力の場合は自動的に
JoinNode
経由に
- 実装例:
FilterNode::addInput()
の改良void addInput(std::shared_ptr<AudioNode> newInput) override { if (this->input == zero) { this->input = newInput; // 最初の入力はそのまま } else if (this->internalJoin == nullptr) { // 2つ目の入力で内部JoinNodeを作成 this->internalJoin = std::make_shared<JoinNode>(); this->internalJoin->addInput(this->input); this->internalJoin->addInput(newInput); this->input = this->internalJoin; } else { // 3つ目以降は内部JoinNodeに追加 this->internalJoin->addInput(newInput); } }
-
src/Parameters.h
:MAX_JOINS
定数を削除(内部的なJoinNode
は動的に作成するため不要)NODE_KIND::Join
を enum から削除NODE_KIND_NAMES
から join を削除JoinParams
クラスを削除(UI からの制御が不要になるため)
-
src/Voice.h
:joins
配列を削除 -
src/Voice.cpp
: joins の初期化・参照を削除
-
src/Node.h
:JoinNode
クラスはそのまま保持- 内部的な使用のため、インターフェースの調整のみ
- 関連する switch 文から Join ケースを削除(UI からの作成は不要)
-
JoinNode
を内部専用クラスとしてリファクタリング
- 基本的な音声出力の確認
- 複数オシレーターからの直接接続テスト
- 既存プロジェクトファイルの互換性テスト
- メモリ使用量の削減確認
- 処理速度の改善測定
- 音声品質の確認
- グラフ表示の動作確認
- ノード追加・削除操作の確認
- 直感的な操作性の向上確認
-
音声出力の不具合
- 内部
JoinNode
の動的作成によるメモリ管理の問題 - 複数入力の加算処理でノイズや音量問題
- 依存関係の順序が変わることによる音質変化
- 内部
-
既存プロジェクトの互換性問題
- 保存されたプロジェクトファイルが読み込めない
- パラメータの参照エラー
-
パフォーマンスの劣化
- 予期しない処理負荷の増加
- メモリリークの発生
-
UI 操作の混乱
- 既存ユーザーの操作方法の変更
- グラフ表示の不具合
-
段階的なテスト実施
- 各フェーズで十分な動作確認
- 音声品質の詳細チェック
- 内部
JoinNode
の動的作成・削除のメモリリークテスト
-
バックアップと復旧計画
- 変更前の状態を git で管理
- 問題発生時の即座な復旧手順
-
互換性保持
- 既存の保存形式をサポート
- 徐々に新形式へ移行
-
ユーザーフィードバック
- ベータ版での事前テスト
- 操作性の改善点を収集
src/Node.h
- オーディオノードの基底クラスsrc/Voice.cpp
- グラフ構築ロジックsrc/Parameters.h
- パラメータ管理frontend/src/App.tsx
- フロントエンドのメインコンポーネントfrontend/src/component/graph/Path.tsx
- パス挿入 UI
- JUCE オーディオプロセッサーのアーキテクチャ
- トポロジカルソートによるノード実行順序
- React と C++の連携方法
Last updated: 2024 年 12 月現在