Skip to content

Commit 662999a

Browse files
kako-junclaude
andcommitted
docs: 仕様書5本追加 + .claude/→docs/移行 + バグ修正4件
- docs/: overview, features, user-guide, platforms, roadmap 新規 + todo, wasm-progress を.claude/から移行 - fix: 異名同音判定(C#=Db), aug7の#5二重追加, getInterval未定義ルート, scaleText undefined Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 79c7e0d commit 662999a

10 files changed

Lines changed: 379 additions & 24 deletions

File tree

docs/features.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# 機能一覧
2+
3+
## 運指記譜
4+
5+
音符ごとに左手(押弦)と右手(ピッキング)の情報を記録できる。
6+
7+
**左手の記録項目:**
8+
- 指番号(1〜4)
9+
- 弦番号(1〜4弦)
10+
- フレット番号(0〜24フレット)
11+
- 種別(通常押弦 / ミュート / ゴーストノート / コード一括)
12+
- ピッチ(例: A2, C#3)
13+
- 音程(例: 1, ♭3, 5, ♭7)
14+
15+
**右手の記録項目:**
16+
- 弦番号
17+
- ストロークの向き(ダウン / アップ / サムピック)
18+
- ミュートする弦の一覧
19+
20+
## コード分解
21+
22+
コード名(例: Cmaj7, Am, G7)を入力すると、4弦ベース上のすべての弦・フレットの組み合わせを自動計算して表示する。
23+
24+
ルート音から半音インデックスを使って各構成音のフレット位置を求め、弦ごとのポジションに変換する。
25+
26+
**対応するコードタイプ:**
27+
- メジャー / マイナー / ディミニッシュ / オーギュメント
28+
- sus4
29+
- メジャー7 / ドミナント7 / マイナー7 / オーギュメント7
30+
- パワーコード(5th)
31+
- オクターブユニゾン(8)
32+
- ALL_KEYS(全12半音)/ WHITE_KEYS(白鍵のみ)
33+
34+
## スケール表示
35+
36+
キー(調)を指定すると以下の情報を表示する:
37+
38+
- スケール構成音(全24キー対応:メジャー12キー+マイナー12キー)
39+
- ダイアトニックコード(トライアド)
40+
- ダイアトニックコード(7th)
41+
- 五度圏上の位置(外円=メジャーキー、内円=マイナーキー)
42+
43+
## 和声分析
44+
45+
コードとキーを指定すると以下を表示する:
46+
47+
- 機能和声のディグリー(Ⅰ〜Ⅶ)
48+
- 各ディグリーの説明(例: Ⅴ Dominant — 緊張・推進)
49+
- ローマ数字表記(トライアド:Ⅰ / Ⅱm / Ⅶdim など)
50+
- 7thコードのローマ数字表記(ⅠM7 / Ⅱm7 / Ⅶm7♭5 など)
51+
- カデンツの種類(完全終止 / 変格終止 / 偽終止 / 半終止 / フリジアン終止)
52+
- 各音のコードトーンラベル(例: Tonic Note, Dominant Note)
53+
54+
## 異名同音の正規化
55+
56+
C# と D♭ のように表記は異なるが音高が同じ音を正しく同一視する。
57+
58+
Rust 実装では半音インデックスで比較するため、正確に判定できる。
59+
TypeScript 実装は文字列比較のため、この判定に既知のバグがある(詳細は `docs/todo.md` 参照)。
60+
61+
## WASM 高速化(準備中)
62+
63+
音楽理論計算のロジックを Rust で実装し、WebAssembly としてビルドする準備が整っている。
64+
65+
Phase 3 時点で Rust 側のすべての関数(26関数)の実装とテストが完了している。
66+
Phase 4(Next.js からの WASM 呼び出し)は保留中。
67+
68+
Rust 実装の主な利点:
69+
- 半音インデックスによる正確な異名同音判定
70+
- コンパイル時の型検証
71+
- 将来的な npm パッケージとしての切り出し

docs/overview.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# sid-note とは何か
2+
3+
## 動機
4+
5+
ベースを弾くとき、楽譜やTAB譜だけでは「どの指でどの弦を押さえるか」が直感的に伝わらない。
6+
7+
TAB譜は弦番号とフレット番号を示せるが、音楽理論との接点がない。
8+
五線譜は音の高さと長さを正確に表せるが、指板上の位置は奏者に委ねられる。
9+
10+
sid-note はこの溝を埋めるために作られた。**「ベースの運指を直感的に記譜したい」**という一点から出発している。
11+
12+
## 何ができるのか
13+
14+
1 音符ごとに、以下の情報をまとめて扱う:
15+
16+
- 音高(ピッチ)と音価(全音符・四分音符・八分音符など)
17+
- 弦番号とフレット番号(左手の指板位置)
18+
- ピッキングの向きと弦(右手の動き)
19+
- そのコードにおける音程(ルート・3度・5度・7度)
20+
- 機能和声(Ⅰ・Ⅱ・Ⅲ・Ⅳ・Ⅴ・Ⅵ・Ⅶ)とカデンツ
21+
22+
## TAB譜との違い
23+
24+
| 観点 | TAB譜 | sid-note |
25+
|------|-------|----------|
26+
| 指板位置 | あり | あり |
27+
| 音楽理論との結びつき | なし | あり(コード・スケール・機能和声) |
28+
| 音高の明示 | なし(フレットから推定) | あり |
29+
| ピッキング情報 | なし | あり |
30+
| 複数のポジション候補 | 手動で選択 | 自動計算で提示 |
31+
32+
## アーキテクチャの方針
33+
34+
- UI は Next.js / React で構成する
35+
- 音楽理論の計算ロジックは TypeScript で実装済み。将来的に Rust/WASM へ移行して高速化する
36+
- データはトラック単位の YAML ファイルで管理する(Zod でスキーマ検証)
37+
- Cloudflare Pages または Docker でホスティングできる
38+
39+
## 現在の状態
40+
41+
Phase 3(TypeScript 実装 + Rust への移植 + テスト)まで完了。
42+
Phase 4(WASM 統合)は保留中。
43+
TypeScript 実装で動作するアプリとして公開済み。

docs/platforms.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# 動作環境とデプロイ
2+
3+
## ブラウザ
4+
5+
モダンブラウザであれば動作する。
6+
Canvas API を使用しているため、IE などのレガシーブラウザは非対応。
7+
8+
Windows 環境では線の太さを自動調整する処理が含まれている(`navigator.userAgent` で判定)。
9+
10+
## ローカル開発
11+
12+
```bash
13+
npm install
14+
npm run dev
15+
```
16+
17+
`http://localhost:3000` で開発サーバーが起動する。
18+
19+
テストの実行:
20+
21+
```bash
22+
# TypeScript テスト(Jest)
23+
npm test
24+
25+
# Rust テスト
26+
cd rust-music && cargo test
27+
```
28+
29+
## Cloudflare Pages
30+
31+
Next.js の静的エクスポートまたは Edge Runtime を使って Cloudflare Pages にデプロイできる。
32+
33+
`next.config.ts` で設定を確認すること。
34+
35+
## Docker
36+
37+
`Dockerfile``compose.yaml` が同梱されている。
38+
39+
```bash
40+
# イメージのビルドと起動
41+
docker compose up --build
42+
```
43+
44+
コンテナ内で Next.js の本番ビルドが実行される。
45+
46+
## WASM ビルド(Phase 4 以降)
47+
48+
Rust 製の音楽理論ライブラリを WASM としてビルドするには `wasm-pack` が必要:
49+
50+
```bash
51+
# wasm-pack のインストール
52+
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
53+
54+
# WASM ビルド
55+
cd rust-music
56+
wasm-pack build --target web --out-dir pkg
57+
```
58+
59+
ビルド後の `pkg/` ディレクトリを Next.js から参照する形で統合する予定。

docs/roadmap.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# ロードマップ
2+
3+
## 現在の状態
4+
5+
Phase 3 完了(2025-11-16 時点)。
6+
7+
| フェーズ | 内容 | 状態 |
8+
|---------|------|------|
9+
| Phase 1 | Rust プロジェクト基盤構築 | 完了 |
10+
| Phase 2 | 音楽理論 26 関数を Rust に移植 | 完了 |
11+
| Phase 3 | TypeScript テスト 34 個・Rust テスト 21 個の作成とデグレチェック | 完了 |
12+
| Phase 4 | WASM 統合(Next.js から Rust 関数を呼び出す) | 保留中 |
13+
| Phase 5 | WASM バンドルサイズ最適化・並列処理 | 未着手 |
14+
| Phase 6 | 音楽理論ライブラリの独立 npm パッケージ化 | 未着手 |
15+
16+
---
17+
18+
## Phase 4: WASM 統合
19+
20+
**優先度: 高**
21+
22+
1. `wasm-pack` でビルドして `pkg/` ディレクトリを生成する
23+
2. `src/lib/wasm-init.ts` を作成して初期化処理を一元管理する
24+
3. まず `Keyboard.tsx` など 1 コンポーネントで試験統合する
25+
4. TypeScript 実装から段階的に置き換えていく
26+
5. 置き換え前後でパフォーマンス測定を行う
27+
28+
---
29+
30+
## 6 弦対応・ギター対応
31+
32+
現在は 4 弦ベース(標準チューニング E1-A1-D2-G2)のみ対応。
33+
34+
**拡張候補:**
35+
- 5 弦ベース(B0 弦を追加)
36+
- 6 弦ギター(E2-A2-D3-G3-B3-E4)
37+
- ウクレレ(G4-C4-E4-A4)
38+
- カスタムチューニング(ユーザー定義)
39+
40+
`convertFretsToPositions()` の弦判定ロジックを楽器定義として抽象化することで対応できる。
41+
42+
---
43+
44+
## npm パッケージとしての切り出し
45+
46+
Rust 製音楽理論ライブラリ(`rust-music/`)を独立した npm パッケージとして公開する。
47+
48+
**想定する手順:**
49+
1. `git subtree split``rust-music/` を独立リポジトリに分離
50+
2. WASM ビルドの CI/CD を構築(GitHub Actions)
51+
3. `kordweb` のように npm レジストリに公開
52+
4. sid-note 本体はこのパッケージに依存する形に変更
53+
54+
**意義:**
55+
- ベースやギターの音楽理論アプリを作る他の開発者が利用できる
56+
- 日本語表記(全角 #・♭)や機能和声・カデンツ判定など、sid-note 固有の要件が汎用ライブラリとして活用できる
57+
58+
---
59+
60+
## モードスケール対応
61+
62+
現在はメジャー・ナチュラルマイナーのみ対応。
63+
64+
追加候補:
65+
- ドリアン / フリジアン / リディアン / ミクソリディアン / エオリアン / ロクリアン
66+
- メロディックマイナー / ハーモニックマイナー
67+
- テンションノート(9th, 11th, 13th)の表示
68+
- 代理コードの提案
69+
70+
---
71+
72+
## UI/UX 改善
73+
74+
- レスポンシブデザインの改善(モバイル対応)
75+
- ダークモード
76+
- キーボードショートカット
77+
- コード進行の音声再生(Web Audio API)
78+
- MIDI ファイルのインポート
79+
- Progressive Web App(オフライン対応)
File renamed without changes.

docs/user-guide.md

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# 使い方ガイド
2+
3+
## トラックの作成
4+
5+
トラックは YAML ファイルとして `public/` 以下に配置する。
6+
`track.schema.json` に従ってデータを記述する。
7+
8+
**基本構造:**
9+
```yaml
10+
title: "曲名"
11+
artist: "アーティスト名"
12+
album: "アルバム名"
13+
year: 2024
14+
key: "Am"
15+
timeSignature: "4/4"
16+
bpm: 120
17+
sections:
18+
- name: "イントロ"
19+
chordSegments:
20+
- chord: "Am"
21+
notes:
22+
- ...
23+
```
24+
25+
**必須フィールド:**
26+
- `title`, `artist`, `album`, `year` — 楽曲の基本情報
27+
- `key` — 調(例: `C`, `Am`, `G#`, `B♭m`)
28+
- `timeSignature` — 拍子(`2/4` / `3/4` / `4/4`)
29+
- `bpm` — テンポ
30+
- `sections` — セクション(イントロ・Aメロ・サビなど)の配列
31+
32+
## ノート入力
33+
34+
各ノートは `NoteSchema` に従って記述する。
35+
36+
**音符の記述例:**
37+
```yaml
38+
notes:
39+
- pitch: "A2"
40+
value: "quarter"
41+
lefts:
42+
- finger: 2
43+
string: 1
44+
fret: 5
45+
type: "press"
46+
pitch: "A2"
47+
interval: "1"
48+
right:
49+
string: 1
50+
stroke: "down"
51+
muteStrings: []
52+
```
53+
54+
**音価の種類:**
55+
| 値 | 意味 |
56+
|----|------|
57+
| `whole` | 全音符 |
58+
| `half` | 二分音符 |
59+
| `quarter` | 四分音符 |
60+
| `8th` | 八分音符 |
61+
| `16th` | 十六分音符 |
62+
| `dotted_*` | 付点(例: `dotted_quarter`) |
63+
| `triplet_*` | 三連符(例: `triplet_8th`) |
64+
65+
**ピッチの書き方:**
66+
- アルファベット + 臨時記号 + オクターブ番号(例: `C#3`, `B♭2`)
67+
- シャープは全角 `#`、フラットは半角 `♭` を使う
68+
- 対応範囲: E1〜G4
69+
70+
## 表示の見方
71+
72+
**鍵盤ビュー(Keyboard):**
73+
- 横軸がピッチ(E1 左端〜G4 右端)
74+
- 現在の音符を白い円で表示
75+
- 次の音符をシアンの発光円で表示
76+
77+
**五線譜ビュー(Staff):**
78+
- 縦軸がピッチ(下から上に音が高くなる)
79+
- ベース音域(低音部譜表相当)を3段に分けて表示
80+
- 臨時記号(#・♭)は円の左側に表示
81+
82+
**五度圏ビュー(CircleOfFifths):**
83+
- 外円がメジャーキー、内円がマイナーキー
84+
- 現在のキーを白い円でハイライト
85+
86+
**ダイアトニックコード表(DiatonicChordTable):**
87+
- 現在のキーに対するⅠ〜Ⅶのコードを一覧表示
88+
- 現在演奏中のコードがハイライトされる
89+
90+
## 再生
91+
92+
開発サーバーを起動してブラウザで確認する:
93+
94+
```bash
95+
npm run dev
96+
```
97+
98+
`http://localhost:3000` を開くと楽曲一覧が表示される。
99+
楽曲を選択するとセクション・コード・ノートを順に表示できる。
100+
101+
## エクスポート
102+
103+
現時点では明示的なエクスポート機能はない。
104+
五度圏の画像は `getCircleOfFifthsImage(scale)` を呼ぶことでデータ URL(PNG)として取得できる。

.claude/music-theory-wasm-rust-progress.md renamed to docs/wasm-progress.md

File renamed without changes.

src/utils/chordUtil.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ export const getChordPositions = (chord: string) => {
222222
}
223223

224224
if (f.interval === "5") {
225+
if (isAug7) return { ...f, interval: "#5", fret: 8 };
225226
if (isAug) return { ...f, interval: "#5", fret: 8 };
226227
if (isDim) return { ...f, interval: "♭5", fret: 6 };
227228
return f;
@@ -232,7 +233,6 @@ export const getChordPositions = (chord: string) => {
232233

233234
// 7th
234235
if (isAug7) {
235-
baseFrets.push({ interval: "#5", fret: 8 });
236236
baseFrets.push({ interval: "♭7", fret: 10 });
237237
} else if (isMaj7) {
238238
baseFrets.push({ interval: "7", fret: 11 });
@@ -288,10 +288,13 @@ export const getInterval = (chord: string, targetPitch: string) => {
288288
const targetName = targetPitch.replace(/\d+$/, "");
289289
const root = getRootNote(chord);
290290
const pitches = pitchMap[root];
291+
// ルート音がpitchMapにない場合はフォールバック
292+
if (!pitches) return "";
291293
const index = pitches.findIndex((pitch) => {
292294
const names = pitch.split("/").map((p) => p.replace(/\d+$/, ""));
293295
return names.includes(targetName);
294296
});
297+
if (index === -1) return "";
295298
const intervalMap: { [key: number]: string } = {
296299
0: "1",
297300
1: "♭2",
@@ -306,6 +309,5 @@ export const getInterval = (chord: string, targetPitch: string) => {
306309
10: "♭7",
307310
11: "7",
308311
};
309-
const interval = intervalMap[index] || "";
310-
return interval;
312+
return intervalMap[index] ?? "";
311313
};

0 commit comments

Comments
 (0)