Skip to content

Instantly share code, notes, and snippets.

@cheebow
Created December 22, 2025 10:26
Show Gist options
  • Select an option

  • Save cheebow/22fc3248d2703f6bb49a288922cea8bb to your computer and use it in GitHub Desktop.

Select an option

Save cheebow/22fc3248d2703f6bb49a288922cea8bb to your computer and use it in GitHub Desktop.
コード名からコードの構成音を求める
# 音階リストを定義
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