Created
December 22, 2025 10:26
-
-
Save cheebow/22fc3248d2703f6bb49a288922cea8bb to your computer and use it in GitHub Desktop.
コード名からコードの構成音を求める
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 音階リストを定義 | |
| NOTES = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B'] | |
| # アルファベット順の音名 | |
| LETTERS = "CDEFGAB" | |
| # 異名同音の対応表(変換用:入力されたflatの場合も内部計算はsharpsで行う) | |
| ENHARMONIC = { | |
| 'Db': 'C#', 'Eb': 'D#', 'Fb': 'E', 'Gb': 'F#', 'Ab': 'G#', 'Bb': 'A#', 'Cb': 'B', | |
| 'B#': 'C', 'E#': 'F' | |
| } | |
| # 出力をflat表記にするための変換表 | |
| SHARP_TO_FLAT = { | |
| "C#": "Db", | |
| "D#": "Eb", | |
| "F#": "Gb", | |
| "G#": "Ab", | |
| "A#": "Bb", | |
| "E#": "F", | |
| "B#": "C" | |
| } | |
| # コードタイプと対応する音程(半音単位) | |
| CHORD_TYPES = { | |
| '': [0, 4, 7], # メジャー (例: C) | |
| 'm': [0, 3, 7], # マイナー (例: Cm) | |
| 'dim': [0, 3, 6], # ディミニッシュ (例: Cdim) | |
| 'aug': [0, 4, 8], # オーギュメント (例: Caug) | |
| '7': [0, 4, 7, 10], # ドミナント7th (例: C7) | |
| 'M7': [0, 4, 7, 11], # メジャー7th (例: CM7) | |
| 'm7': [0, 3, 7, 10], # マイナー7th (例: Cm7) | |
| 'mM7': [0, 3, 7, 11], # マイナーメジャー7th (例: CmM7) | |
| 'dim7': [0, 3, 6, 9], # ディミニッシュ7th (例: Cdim7) | |
| 'm7b5': [0, 3, 6, 10], # ハーフディミニッシュ (例: Cm7b5) | |
| 'aug7': [0, 4, 8, 10], # オーギュメント7th (例: Caug7) | |
| '6': [0, 4, 7, 9], # メジャー6th (例: C6) | |
| 'm6': [0, 3, 7, 9], # マイナー6th (例: Cm6) | |
| '9': [0, 4, 7, 10, 14], # ドミナント9th (例: C9) | |
| 'M9': [0, 4, 7, 11, 14], # メジャー9th (例: CM9) | |
| 'm9': [0, 3, 7, 10, 14], # マイナー9th (例: Cm9) | |
| '11': [0, 4, 7, 10, 14, 17], # 11th (例: C11) | |
| '13': [0, 4, 7, 10, 14, 17, 21], # 13th (例: C13) | |
| 'sus4': [0, 5, 7], # サスペンデッド4th (例: Csus4) | |
| 'add9': [0, 4, 7, 14], # アド9 (例: Cadd9) | |
| 'madd9': [0, 3, 7, 14], # マイナーアド9 (例: Cmadd9) | |
| } | |
| # 音程に対応する音名のアルファベットオフセット | |
| INTERVAL_OFFSETS = { | |
| 0: 0, # ルート | |
| 3: 2, # マイナー3度 | |
| 4: 2, # メジャー3度 | |
| 5: 3, # 完全4度 | |
| 6: 4, # 減5度 | |
| 7: 4, # 完全5度 | |
| 8: 4, # 増5度 | |
| 10: 6, # マイナー7度 | |
| 11: 6 # メジャー7度 | |
| } | |
| # 各アルファベットの基本ピッチ(C, D, E, F, G, A, B) | |
| BASE_PITCHES = [0, 2, 4, 5, 7, 9, 11] | |
| def analyze_chord(chord_name): | |
| """コード名から構成音を求める関数""" | |
| # 入力に "b" が含まれていればflat表記で出力する | |
| use_flat = 'b' in chord_name | |
| # ルート音と残りの部分を分離(表示用のルートを保持) | |
| root = chord_name[0].upper() | |
| idx = 1 | |
| if idx < len(chord_name) and chord_name[idx] in ['#', 'b']: | |
| root += chord_name[idx] | |
| idx += 1 | |
| chord_type = chord_name[idx:] | |
| # 内部計算用のルート(sharps表記に統一) | |
| computed_root = ENHARMONIC.get(root, root) | |
| if computed_root not in NOTES: | |
| raise ValueError(f"ルート音 '{root}' はサポートされていません。") | |
| root_idx = NOTES.index(computed_root) | |
| # ルート音のアルファベット(表示用は元の入力を利用) | |
| root_letter_idx = LETTERS.index(root[0]) | |
| # コードタイプに対応する音程を取得 | |
| if chord_type not in CHORD_TYPES: | |
| return [root] # 未対応のコードタイプの場合はルートのみ返す | |
| intervals = CHORD_TYPES[chord_type] | |
| # 構成音を計算 | |
| chord_notes = [] | |
| for interval in intervals: | |
| # 半音単位での音高(内部計算用) | |
| pitch_idx = (root_idx + interval) % 12 | |
| # アルファベット順での位置を計算(元のルート音のアルファベットを基準) | |
| letter_offset = INTERVAL_OFFSETS.get(interval, 0) | |
| letter_idx = (root_letter_idx + letter_offset) % 7 | |
| letter = LETTERS[letter_idx] | |
| # 対応する基本ピッチ | |
| base_pitch = BASE_PITCHES[letter_idx] | |
| # 必要な変化記号を計算 | |
| pitch_diff = (pitch_idx - base_pitch) % 12 | |
| if pitch_diff == 0: | |
| note = letter | |
| elif pitch_diff == 1: | |
| note = letter + "#" | |
| elif pitch_diff == 11: | |
| note = letter + "b" | |
| else: | |
| # 複雑な場合は内部リストから取得 | |
| note = NOTES[pitch_idx] | |
| chord_notes.append(note) | |
| # flat表記を希望する場合、変換可能な音はflat表記に変換する | |
| if use_flat: | |
| chord_notes = [SHARP_TO_FLAT.get(n, n) for n in chord_notes] | |
| return chord_notes | |
| # 使用例 | |
| if __name__ == "__main__": | |
| """コード分析の使用例""" | |
| test_chords = [ | |
| "C", "Cm", "C7", "CM7", "Cm7", "CmM7", "Cdim", "Caug", | |
| "G", "Gm", "G7", "GM7", "Gm7", "GmM7", "Gsus4", | |
| "F", "FM7", "Fm", "FmM7", "Fsus4", "F#m7", "F#mM7", "D#dim7", | |
| "Db", "Ebm", "EbmM7", "Bb7", "AbM7", "Gbm7", "GbmM7", "Bbdim", | |
| "E", "Em7", "EmM7", "A", "Am7", "AmM7", "B", "Bm7", "BmM7", | |
| "C#", "C#m", "C#mM7", "D", "D#", "F#", "F#m", "F#mM7", "G#", | |
| "G#m", "G#mM7", "A#", "A#m", "A#mM7" | |
| ] | |
| for chord in test_chords: | |
| notes = analyze_chord(chord) | |
| print(f"{chord}: {notes}") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment