Hezu06 commited on
Commit
10597f8
·
1 Parent(s): 99aac9d

Refactor chord voicings and add pentatonic snapping function for improved melody generation and tonal consistency

Browse files
Files changed (1) hide show
  1. main.py +38 -16
main.py CHANGED
@@ -60,24 +60,39 @@ SEQ_LEN = 128
60
  BARS_PER_BATCH = 2
61
 
62
  # Chord progressions — 2 màu sắc luân phiên để tránh lặp
63
- # Chord voicings nằm trong vùng C4–B4 (MIDI 60–71)
64
- # để không bị quá trầm gần với vùng melody (C4–C5).
65
- # Mỗi chord tăng +12 so với trước (nâng 1 octave).
 
66
  CHORD_SETS = {
67
- "calm": [ # BPM cao — tông mềm, dreamy
68
- [60, 64, 67, 71], # Cmaj7 (C4 E4 G4 B4)
69
- [57, 60, 64, 67], # Am7 (A3 C4 E4 G4)
70
- [53, 57, 60, 64], # Fmaj7 (F3 A3 C4 E4)
71
- [55, 59, 62, 67], # G9 (G3 B3 D4 G4)
72
  ],
73
- "groove": [ # BPM thấp — tông rõ hơn, có chiều sâu
74
- [60, 64, 67, 71], # Cmaj7 (C4 E4 G4 B4)
75
- [55, 59, 62, 65], # G7 (G3 B3 D4 F4)
76
- [57, 60, 64, 69], # Am9 (A3 C4 E4 A4)
77
- [53, 56, 60, 64], # Fm7 (F3 Ab3 C4 Eb4)
78
  ],
79
  }
80
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  # ==========================================
82
  # ENTRAINMENT HELPERS
83
  # ==========================================
@@ -115,8 +130,10 @@ def get_melody_params(bpm: int, music_beat: float) -> dict:
115
  dur_factor = 0.72 + t * 0.48 # 0.72 -> 1.20 (legato khi BPM cao)
116
  duration = round(music_beat * dur_factor, 4)
117
 
118
- midi_low = int(59 + t * 5) # 59 -> 64
119
- midi_high = int(71 + t * 5) # 71 -> 76
 
 
120
 
121
  return {
122
  "vel_low": max(40, vel_low),
@@ -221,9 +238,14 @@ async def websocket_vibe(websocket: WebSocket):
221
  while midi < lo: midi += 12
222
  while midi > hi: midi -= 12
223
 
 
 
 
 
224
  if midi == last_midi and random.random() < 0.40:
225
  step = random.choice([-2, 2, 3, -3, 5])
226
- midi = max(lo - 2, min(hi + 2, midi + step))
 
227
 
228
  last_midi = midi
229
  velocity = random.randint(mel_params["vel_low"],
 
60
  BARS_PER_BATCH = 2
61
 
62
  # Chord progressions — 2 màu sắc luân phiên để tránh lặp
63
+ # ── CHORD VOICINGS ───────────────────────────────────────────────────────
64
+ # Tất cả trong vùng G3–B4 (MIDI 55–71) không quá trầm, không quá cao.
65
+ # Chỉ dùng chord diatonic trong C major để melody pentatonic luôn fit.
66
+ # Fm7 (borrowed chord) đã bỏ vì Ab/Eb xung đột với C major pentatonic.
67
  CHORD_SETS = {
68
+ "calm": [ # BPM cao (tim nhanh, cần calming) — tông mềm, mơ màng
69
+ [60, 64, 67, 71], # Cmaj7 C4 E4 G4 B4
70
+ [57, 60, 64, 67], # Am7 A3 C4 E4 G4
71
+ [53, 57, 60, 64], # Fmaj7 F3 A3 C4 E4
72
+ [55, 59, 62, 67], # G9 G3 B3 D4 G4
73
  ],
74
+ "groove": [ # BPM thấp (tim chậm, ok groove) — tông rõ hơn
75
+ [60, 64, 67, 71], # Cmaj7 C4 E4 G4 B4
76
+ [57, 60, 64, 67], # Am7 A3 C4 E4 G4
77
+ [55, 59, 62, 65], # G7 G3 B3 D4 F4
78
+ [53, 57, 60, 64], # Fmaj7 F3 A3 C4 E4
79
  ],
80
  }
81
 
82
+ # ── C MAJOR PENTATONIC SNAP ───────────────────────────────────────────────
83
+ # Pitch classes: C=0 D=2 E=4 G=7 A=9
84
+ # Snap mỗi nốt AI về pentatonic gần nhất → luôn consonant với mọi chord trên.
85
+ _PENTA = [0, 2, 4, 7, 9]
86
+
87
+ def snap_pentatonic(midi: int) -> int:
88
+ """Snap MIDI note về C major pentatonic gần nhất, giữ nguyên octave."""
89
+ pc = midi % 12
90
+ best = min(_PENTA, key=lambda p: min(abs(p - pc), 12 - abs(p - pc)))
91
+ diff = best - pc
92
+ if diff > 6: diff -= 12
93
+ if diff < -6: diff += 12
94
+ return midi + diff
95
+
96
  # ==========================================
97
  # ENTRAINMENT HELPERS
98
  # ==========================================
 
130
  dur_factor = 0.72 + t * 0.48 # 0.72 -> 1.20 (legato khi BPM cao)
131
  duration = round(music_beat * dur_factor, 4)
132
 
133
+ # Hạ range xuống ~1 quart so với trước: G3–G4 thay vì B3–E5
134
+ # Lofi melody nghe tốt nhất vùng mid (G3–A4, MIDI 55–69)
135
+ midi_low = int(55 + t * 3) # 55 (G3) → 58 (Bb3)
136
+ midi_high = int(67 + t * 3) # 67 (G4) → 70 (Bb4)
137
 
138
  return {
139
  "vel_low": max(40, vel_low),
 
238
  while midi < lo: midi += 12
239
  while midi > hi: midi -= 12
240
 
241
+ # Snap về C major pentatonic trước
242
+ midi = snap_pentatonic(midi)
243
+
244
+ # Tránh lặp nốt — nhảy sang pentatonic liền kề
245
  if midi == last_midi and random.random() < 0.40:
246
  step = random.choice([-2, 2, 3, -3, 5])
247
+ midi = snap_pentatonic(
248
+ max(lo - 2, min(hi + 2, midi + step)))
249
 
250
  last_midi = midi
251
  velocity = random.randint(mel_params["vel_low"],