print('Hello world!')
import struct
import base64
class SimpleMIDIWriter:
def __init__(self, bpm=160, ticks_per_beat=480):
self.bpm = bpm
self.ticks = ticks_per_beat
self.tracks = []
def _varlen(self, value):
buf = bytearray()
buf.append(value & 0x7F)
value >>= 7
while value:
buf.append((value & 0x7F) | 0x80)
value >>= 7
buf.reverse()
return buf
def add_track(self, events):
self.tracks.append(events)
def write(self, filename):
num_tracks = len(self.tracks) + 1
data = bytearray(b'MThd\x00\x00\x00\x06')
data += struct.pack('>HHH', 1, num_tracks, self.ticks)
# テンポ設定トラック
tempo_track = bytearray()
us_per_beat = int(60000000 / self.bpm)
tempo_track += b'\x00\xFF\x51\x03' + us_per_beat.to_bytes(3, 'big') + b'\x00\xFF\x2F\x00'
data += b'MTrk' + struct.pack('>I', len(tempo_track)) + tempo_track
# 演奏トラック
for track_events in self.tracks:
t_data = bytearray()
last_time = 0
# time_tick順にソート
track_events.sort(key=lambda x: x[0])
for time_tick, ev_type, ch, p1, p2 in track_events:
delta = time_tick - last_time
last_time = time_tick
t_data += self._varlen(delta)
if ev_type == 'note_on':
t_data += bytes([0x90 | ch, p1, p2])
elif ev_type == 'note_off':
t_data += bytes([0x80 | ch, p1, p2])
t_data += b'\x00\xFF\x2F\x00'
data += b'MTrk' + struct.pack('>I', len(t_data)) + t_data
with open(filename, 'wb') as f:
f.write(data)
return data
# MIDI生成インスタンス
midi = SimpleMIDIWriter(bpm=160, ticks_per_beat=480)
TPB = 480 # 1拍
BAR = TPB * 4 # 1小節
# コード構成 (Cm, Gm, Ab, Bb)
CHORDS = {
"Cm": {"bass": 36, "notes": [48, 51, 55]},
"Gm": {"bass": 43, "notes": [43, 46, 50]},
"Ab": {"bass": 44, "notes": [44, 48, 51]},
"Bb": {"bass": 46, "notes": [46, 50, 53]}
}
progression = ["Cm", "Gm", "Ab", "Bb"]
piano_events = []
melody_events = []
def add_note(events, start_tick, duration_tick, pitch, vel, ch=0):
events.append((start_tick, 'note_on', ch, pitch, vel))
events.append((start_tick + duration_tick, 'note_off', ch, pitch, 0))
# --- ピアノ伴奏生成 ---
curr_tick = 0
# Intro (8小節)
for _ in range(2):
for chord in progression:
c = CHORDS[chord]
add_note(piano_events, curr_tick, BAR, c["bass"], 80)
for i in range(8):
t = curr_tick + i * (TPB // 2)
for p in c["notes"]:
add_note(piano_events, t, int(TPB * 0.4), p, 70)
curr_tick += BAR
# Aメロ (16小節)
for _ in range(4):
for chord in progression:
c = CHORDS[chord]
add_note(piano_events, curr_tick, BAR, c["bass"], 75)
for i in range(4):
t = curr_tick + i * TPB
add_note(piano_events, t, int(TPB * 0.8), c["notes"][i % len(c["notes"])] + 12, 65)
curr_tick += BAR
# サビ (16小節)
for _ in range(4):
for chord in progression:
c = CHORDS[chord]
add_note(piano_events, curr_tick, BAR, c["bass"], 95)
add_note(piano_events, curr_tick, BAR, c["bass"] - 12, 90)
for r in [0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5]:
t = curr_tick + int(r * TPB)
for p in c["notes"]:
add_note(piano_events, t, int(TPB * 0.4), p + 12, 85)
curr_tick += BAR
# --- メロディー生成 ---
melody_verse = [(72, 0.5), (72, 0.5), (72, 0.5), (75, 0.5), (74, 1.0), (70, 1.0), (68, 0.5), (68, 0.5), (68, 0.5), (72, 0.5), (70, 1.5), (67, 0.5)]
melody_chorus = [(75, 1.0), (77, 1.0), (79, 1.5), (77, 0.5), (75, 1.0), (74, 1.0), (72, 1.0), (74, 1.0), (75, 1.5), (74, 0.5), (72, 1.0), (70, 1.0)]
# Aメロメロディー
m_tick = BAR * 8
for _ in range(4):
for pitch, dur in melody_verse:
add_note(melody_events, m_tick, int(dur * TPB * 0.9), pitch, 90, ch=1)
m_tick += int(dur * TPB)
# サビメロディー
m_tick = BAR * 24
for _ in range(4):
for pitch, dur in melody_chorus:
add_note(melody_events, m_tick, int(dur * TPB * 0.9), pitch, 100, ch=1)
m_tick += int(dur * TPB)
midi.add_track(piano_events)
midi.add_track(melody_events)
# 出力
filename = "You_are_my_curse_full.mid"
raw_bytes = midi.write(filename)
print("=== MIDI生成完了 ===")
print(f"ファイル '{filename}' が保存されました。")
# ブラウザ等で直接ダウンロード用のBase64リンク生成
b64 = base64.b64encode(raw_bytes).decode('utf-8')
print("\n▼ 以下のURLをコピーしてブラウザのURL欄に貼り付けると直接ダウンロードできます:")
print(f"data:audio/midi;base64,{b64}")
To embed this project on your website, copy the following code and paste it into your website's HTML: