Cài đặt thư viện bằng lệnh: pip install mido
Thư viện mido hỗ trợ xử lý các tệp MIDI một cách hiệu quả, cho phép trích xuất dữ liệu âm nhạc từ các bản nhạc cụ thể.
Trích xuất dữ liệu bản nhạc đơn lẻ
Mã nguồn sau sẽ đọc tệp MIDI được chỉ định và trích xuất dữ liệu âm thanh của bản nhạc theo số thứ tự, bao gồm các sự kiện nốt nhạc và thông tin liên quan.
Tạo tập tin mido_extract.py với nội dung:
# -*- coding: utf-8 -*-
""" Trích xuất dữ liệu bản nhạc từ tệp MIDI sử dụng mido """
import os
import sys
from tkinter import filedialog
import mido
def get_music_track_data(midi_content, track_index):
try:
extracted_events = []
all_tracks = midi_content.tracks
for idx, single_track in enumerate(all_tracks):
print(f"Nhạc {idx}: {single_track.name}")
if track_index < len(all_tracks):
selected_track = all_tracks[track_index]
for event in selected_track:
if event.type in ['note_on', 'note_off', 'control_change', 'program_change']:
extracted_events.append(event)
else:
print(f"Số thứ tự bản nhạc {track_index} vượt quá giới hạn, tệp MIDI này có tổng cộng {len(all_tracks)} bản nhạc.")
return extracted_events
except:
print(" Không thể đọc tệp MIDI.")
return None
def save_events_to_midi(events_list, output_path, source_midi):
result_midi = mido.MidiFile(ticks_per_beat=source_midi.ticks_per_beat)
result_track = mido.MidiTrack()
for event in events_list:
result_track.append(event)
result_midi.tracks.append(result_track)
result_midi.save(output_path)
# main()
if len(sys.argv) == 1:
file_types = [('tệp midi','.mid')]
input_file = filedialog.askopenfilename(initialdir='D:/Music', filetypes=file_types)
elif len(sys.argv) == 2:
input_file = sys.argv[1]
else:
print('sử dụng: python mido_extract.py file1.mid')
sys.exit(1)
if not os.path.exists(input_file):
print(f"{input_file} không tồn tại.")
sys.exit(2)
file_name, extension = os.path.splitext(input_file)
if extension.lower() != '.mid':
print('đuôi không phải là .mid ')
sys.exit(2)
source_midi_path = input_file # Thay thế đường dẫn tệp MIDI thực tế
target_track = 1 # Chỉ định số thứ tự bản nhạc cần trích xuất, bắt đầu từ 0
result_output_path = f"music_track_{target_track}.mid" # Đường dẫn tệp MIDI đầu ra
try:
source_midi = mido.MidiFile(source_midi_path)
extracted_data = get_music_track_data(source_midi, target_track)
if extracted_data:
save_events_to_midi(extracted_data, result_output_path, source_midi)
print(f"Đã lưu thành công dữ liệu nhạc {target_track} vào {result_output_path}")
except mido.MidiFileError:
print(f"Không thể đọc tệp MIDI {source_midi_path}")
Chạy lệnh: python mido_extract.py moon_river.mid
Kết quả tạo ra: music_track_1.mid
Trong đoạn mã trên, hàm get_music_track_data chịu trách nhiệm lấy dữ liệu bản nhạc đã chỉ định, hàm save_events_to_midi sẽ ghi dữ liệu đã lấy vào tệp MIDI mới. Bạn cần thay đổi source_midi_path thành đường dẫn tệp MIDI gốc, target_track là số thứ tự bản nhạc mục tiêu, result_output_path xác định đường dẫn tệp đầu ra.
Kết hợp giữ nguyên bản nhạc đầu tiên và trích xuất bản nhạc thứ hai
Đoạn mã dưới đây sẽ sao chép toàn bộ thông tin từ Nhạc 0 trong tệp MIDI gốc, đồng thời trích xuất dữ liệu âm nhạc từ Nhạc 1, sau đó kết hợp chúng vào một tệp MIDI mới.
Tạo tập tin mido_combine.py như sau:
# -*- coding: utf-8 -*-
""" Sao chép giữ nguyên Nhạc 0, trích xuất dữ liệu Nhạc 1 sử dụng mido """
import mido
def duplicate_first_and_retrieve_second(midi_input_path, midi_output_path):
try:
# Đọc tệp MIDI gốc
base_midi = mido.MidiFile(midi_input_path)
if len(base_midi.tracks) < 2:
print("Tệp MIDI không có đủ bản nhạc (cần tối thiểu 2 bản nhạc).")
return
# Tạo tệp MIDI mới, sao chép giá trị ticks_per_beat từ tệp gốc
combined_midi = mido.MidiFile(ticks_per_beat=base_midi.ticks_per_beat)
# Sao chép Nhạc 0 sang tệp MIDI mới
combined_midi.tracks.append(base_midi.tracks[0])
# Trích xuất dữ liệu âm nhạc từ Nhạc 1
second_track = base_midi.tracks[1]
second_track_events = []
for message in second_track:
if message.type in ['note_on', 'note_off', 'control_change', 'program_change']:
second_track_events.append(message)
# Tạo bản nhạc mới và thêm dữ liệu Nhạc 1
new_second_track = mido.MidiTrack()
for message in second_track_events:
new_second_track.append(message)
combined_midi.tracks.append(new_second_track)
# Lưu tệp MIDI mới
combined_midi.save(midi_output_path)
print(f"Đã lưu thành công thông tin Nhạc 0 và dữ liệu Nhạc 1 vào {midi_output_path}")
except mido.MidiFileError:
print(f"Không thể đọc tệp MIDI {midi_input_path}")
if __name__ == "__main__":
input_midi_path = "your_midi_file.mid" # Thay thế đường dẫn tệp MIDI thực tế
output_midi_path = "combined_midi_file.mid" # Đường dẫn tệp MIDI đầu ra mong muốn
duplicate_first_and_retrieve_second(input_midi_path, output_midi_path)
Giải thích mã nguồn:
- Đọc tệp MIDI gốc: Sử dụng
mido.MidiFileđể đọc tệp MIDI theo đường dẫn đã chỉ định. - Kiểm tra số lượng bản nhạc: Đảm bảo tệp MIDI chứa ít nhất 2 bản nhạc.
- Tạo tệp MIDI mới: Sử dụng giá trị
ticks_per_beattừ tệp gốc để tạo tệp MIDI mới. - Sao chép Nhạc 0: Thêm trực tiếp
Nhạc 0từ tệp gốc vào tệp MIDI mới. - Trích xuất dữ liệu Nhạc 1: Duyệt qua
Nhạc 1, lấy các tin nhắn loạinote_on,note_off,control_changevàprogram_change. - Tạo bản nhạc mới và thêm dữ liệu: Tạo một bản nhạc mới, thêm dữ liệu
Nhạc 1đã trích xuất vào bản nhạc đó, sau đó thêm bản nhạc này vào tệp MIDI mới. - Lưu tệp MIDI mới: Lưu tệp MIDI mới đến đường dẫn đầu ra đã chỉ định.
Bạn cần thay đổi input_midi_path thành đường dẫn tệp MIDI thực tế, thay đổi output_midi_path thành đường dẫn nơi bạn muốn lưu tệp MIDI mới.