MIDI CSV Data
前回のDeep Learning のようなことをやりたい場合、データが必要になります。
MIDIデバイスをつかったデータ生成->CSVファイル書き込み、およびその逆を試してみました。
環境)Anaconda / Windows 11
MIDI to CSV file
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
import rtmidi import csv import time def midi_to_csv_from_interface(midi_port_name, csv_file_path): midi_in = rtmidi.MidiIn() available_ports = midi_in.get_ports() if midi_port_name not in available_ports: raise ValueError(f"MIDI port {midi_port_name} not found. Available ports: {available_ports}") midi_in.open_port(available_ports.index(midi_port_name)) with open(csv_file_path, mode='w', newline='') as csv_file: csv_writer = csv.writer(csv_file) csv_writer.writerow(['Timestamp', 'Type', 'Channel', 'Note', 'Velocity', 'Control', 'Value']) print(f"Listening on {midi_port_name}... Press Ctrl+C to stop.") start_time = time.time() try: while True: msg = midi_in.get_message() if msg: message, delta_time = msg timestamp = time.time() - start_time status = message[0] data1 = message[1] if len(message) > 1 else 0 data2 = message[2] if len(message) > 2 else 0 if 0x80 <= status < 0x90: # Note Off csv_writer.writerow([timestamp, 'note_off', status & 0x0F, data1, data2, '', '']) elif 0x90 <= status < 0xA0: # Note On csv_writer.writerow([timestamp, 'note_on', status & 0x0F, data1, data2, '', '']) elif 0xB0 <= status < 0xC0: # Control Change csv_writer.writerow([timestamp, 'control_change', status & 0x0F, '', '', data1, data2]) csv_file.flush() except KeyboardInterrupt: print("Stopped by user") finally: midi_in.close_port() print("Available MIDI input ports:") midi_in = rtmidi.MidiIn() available_ports = midi_in.get_ports() for port in available_ports: print(port) midi_port_name = input("Enter the MIDI port name to listen to: ") csv_file_path = 'output.csv' midi_to_csv_from_interface(midi_port_name, csv_file_path) |
CSV file TO MIDI
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
import rtmidi import csv import time def csv_to_midi_interface(csv_file_path, midi_port_name): midi_out = rtmidi.MidiOut() available_ports = midi_out.get_ports() if midi_port_name not in available_ports: raise ValueError(f"MIDI port {midi_port_name} not found. Available ports: {available_ports}") midi_out.open_port(available_ports.index(midi_port_name)) with open(csv_file_path, mode='r') as csv_file: csv_reader = csv.reader(csv_file) header = next(csv_reader) start_time = time.time() for row in csv_reader: timestamp = float(row[0]) msg_type = row[1] channel = int(row[2]) if row[2] else 0 note = int(row[3]) if row[3] else 0 velocity = int(row[4]) if row[4] else 0 control = int(row[5]) if row[5] else 0 value = int(row[6]) if row[6] else 0 current_time = time.time() - start_time if timestamp > current_time: time.sleep(timestamp - current_time) if msg_type == 'note_on': message = [0x90 | channel, note, velocity] elif msg_type == 'note_off': message = [0x80 | channel, note, velocity] elif msg_type == 'control_change': message = [0xB0 | channel, control, value] else: continue midi_out.send_message(message) print(f"Sent: {message}") midi_out.close_port() print("Available MIDI output ports:") midi_out = rtmidi.MidiOut() available_ports = midi_out.get_ports() for port in available_ports: print(port) midi_port_name = input("Enter the MIDI port name to send to: ") csv_file_path = 'output.csv' csv_to_midi_interface(csv_file_path, midi_port_name) |
使用デバイス(Roland S-1。MIDIのIN/OUTはつなぎなおし。PCとはRoland UM-ONE)
操作)
デバイスのフィルタとレゾナンスのつまみをいじってMIDI出力。
キーボードも適当にならす。
つなぎ変えて次はMIDI受信。
先ほどの操作がそのまま復元されることを確認。
下記、CSVファイルをエクセルで編集してフィルタとレゾナンスのコントロールチェンジを可視化した。
今回のコードは、ChatGPTで作成しました。何も修正せずそのまま動きました。
コーディングの生産性はかなり高くなりますね。
コード生成の指示を正確にするためにも、コーディング技術はある程度必要です。
Category: AM