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}")

Embed on website

To embed this project on your website, copy the following code and paste it into your website's HTML: