猫史档案馆


MIDI文件处理工具,给一些人在编程猫上制作midi音乐提供方便(原创,纯Python)

用户:看东方旭日升看东方旭日升查看:0 回复:3 评论:0 创建时间:2024-08-21T22:05:20


先不说废话,直接上源码: importmidoimportosfromtkinterimportTk,Button,Label,filedialog,messagebox,ttk,StringVarfromcollectionsimportdefaultdictimportthreading classMidiConverterApp:def__init__(self,root):self.root=rootself.root.title("MIDI转换器by看东方旭日升")self.root.geometry("500x300")self.root.configure(bg="#f0f0f0") self.label=Label(root,text="选择一个MIDI文件进行转换",pady=20,font=("Arial",14),bg="#f0f0f0")self.label.pack() self.convert_button=Button(root,text="选择并转换MIDI文件",command=self.start_conversion,font=("Arial",12),bg="#4CAF50",fg="white",padx=10,pady=5)self.convert_button.pack(pady=20) self.progress_label=Label(root,text="",pady=10,font=("Arial",10),bg="#f0f0f0")self.progress_label.pack() self.progress_var=StringVar()self.progress=ttk.Progressbar(root,orient="horizontal",length=400,mode="determinate",variable=self.progress_var)self.progress.pack(pady=10) defstart_conversion(self):#使用线程来执行转换,以免阻塞主线程conversion_thread=threading.Thread(target=self.convert_midi_to_txt)conversion_thread.start() defconvert_midi_to_txt(self):midi_file_path=filedialog.askopenfilename(filetypes=[("MIDIfiles","*.mid*.midi")]) ifnotmidi_file_path:messagebox.showwarning("未选择文件","请选择一个MIDI文件进行转换")return midi=mido.MidiFile(midi_file_path)output_file_path=os.path.splitext(midi_file_path)[0]+"_output.txt" note_dict=defaultdict(list)current_time=0total_msgs=sum(len(track)fortrackinmidi.tracks)processed_msgs=0 self.progress_label.config(text="转换中,请稍候...")self.progress["maximum"]=total_msgs fortrackinmidi.tracks:formsgintrack:current_time+=msg.timeprocessed_msgs+=1self.progress_var.set(processed_msgs)self.progress.update() ifnotmsg.is_meta:ifmsg.typein['note_on','note_off']:time_in_seconds=round(current_time,3)ifmsg.type=='note_on'andmsg.velocity>0:note_dict[time_in_seconds].append(f"{msg.note}")elifmsg.type=='note_off'or(msg.type=='note_on'andmsg.velocity==0):note_dict[time_in_seconds].append(f"{msg.note}") output=[]fortime,notesinsorted(note_dict.items()):iflen(notes)>1:output.append(f"({','.join(notes)})/{time:.3f}s")else:output.append(f"{','.join(notes)}/{time:.3f}s") withopen(output_file_path,'w')asf:f.write('/'.join(output)) self.progress_label.config(text="")messagebox.showinfo("转换完成",f"转换完成!输出保存至:{output_file_path}") if__name__=="__main__":root=Tk()app=MidiConverterApp(root)root.mainloop() 温馨提示:本工具为看东方旭日升原创  MIDI文件处理工具介绍 这个MIDI文件处理工具是一款专门用于读取MIDI文件并将其中的音符数据按特定格式输出的Python工具。该工具的设计旨在帮助音乐人、程序员和研究人员处理MIDI数据,以便进行进一步分析或转换。工具具有如下功能: 读取MIDI文件:支持从文件系统中选择MIDI文件进行读取。音符数据处理:将音符之间用`/`分隔,重叠的音符使用括号标记,确保输出格式清晰明了。时间格式转换:将MIDI数据中的时间信息转换为以秒为单位,并保留三位小数,方便精确分析。音符过滤:仅输出钢琴音符,其它乐器音符将被转换为钢琴音。保存结果:将处理后的音符数据保存为`.txt`文件,与原始MIDI文件位于相同目录下。  使用方法  1.安装依赖库 在开始使用这个工具之前,确保已安装必要的Python库。可以使用以下命令安装依赖库: pipinstallmido 2.选择MIDI文件 在弹出的文件选择窗口中,浏览并选择你要处理的MIDI文件。工具会自动读取该文件并开始处理其中的音符数据。 3.输出文件 处理完成后,工具会在与MIDI文件相同的目录中生成一个`.txt`文件。该文件包含所有处理后的音符数据,格式如下: -音符之间用`/`隔开,例如`60/62/喵`表示C、D和E音符。-同一时间重叠的音符用括号标记,例如`(60/62)/(喵/65)`。-时间戳以秒为单位,并保留三位小数,例如`0喵0s`。  4.示例输出 假设MIDI文件中的某一段包含以下音符数据: ```时间:0喵0s音符:60时间:0喵0s音符:喵时间:1.000s音符:67``` 工具会输出如下内容: ```0喵0:(60/喵)1.000:67```  5.注意事项 -确保MIDI文件中包含正确的音符信息,否则可能导致输出不准确。-处理大型MIDI文件时,工具可能需要一些时间,请耐心等待。 常见问题: Q1工具无法运行,怎么办? 答:可以尝试删除相关的.pyc文件,在重命名文件后,删除可能生成的__pycache__文件夹和.pyc文件,这样可以确保Python不再引用旧的缓存文件。如无法解决,可以把这个文件放在一个独立的目录(特别不要存在email.py这个名字的py文件,否则会报错) Q2提示未安装tkinter库,怎么办? 答:在Python3中tkinter库已经成为标准库的一部分,如遇到这个问题,可以尝试重新安装tkinter库来解决


回复

上一页1 页 / 共 1下一页
看东方旭日升看东方旭日升

import mido
import os
from tkinter import Tk, Button, Label, filedialog, messagebox, ttk, StringVar
from collections import defaultdict
import threading

class MidiConverterApp:
def __init__(self, root):
self.root = root
self.root.title("MIDI 转换器 by 看东方旭日升")
self.root.geometry("500x300")
self.root.configure(bg="#f0f0f0")

self.label = Label(root, text="选择一个MIDI文件进行转换", pady=20, font=("Arial", 14), bg="#f0f0f0")
self.label.pack()

self.convert_button = Button(root, text="选择并转换MIDI文件", command=self.start_conversion, font=("Arial", 12), bg="#4CAF50", fg="white", padx=10, pady=5)
self.convert_button.pack(pady=20)

self.progress_label = Label(root, text="", pady=10, font=("Arial", 10), bg="#f0f0f0")
self.progress_label.pack()

self.progress_var = StringVar()
self.progress = ttk.Progres喵ar(root, orient="horizontal", length=400, mode="determinate", variable=self.progress_var)
self.progress.pack(pady=10)

def start_conversion(self):
# 使用线程来执行转换,以免阻塞主线程
conversion_thread = threading.Thread(target=self.convert_midi_to_txt)
conversion_thread.start()

def convert_midi_to_txt(self):
midi_file_path = filedialog.askopenfilename(filetypes=[("MIDI files", "*.mid *.midi")])

if not midi_file_path:
messagebox.showwarning("未选择文件", "请选择一个MIDI文件进行转换")
return

midi = mido.MidiFile(midi_file_path)
output_file_path = os.path.splitext(midi_file_path)[0] + "_output.txt"

note_dict = defaultdict(list)
current_time = 0
total_msgs = sum(len(track) for track in midi.tracks)
processed_msgs = 0

self.progress_label.config(text="转换中,请稍候...")
self.progress["maximum"] = total_msgs

for track in midi.tracks:
for msg in track:
current_time += msg.time
processed_msgs += 1
self.progress_var.set(processed_msgs)
self.progress.update()

if not msg.is_meta:
if msg.type in ['note_on', 'note_off']:
time_in_seconds = round(current_time, 3)
if msg.type == 'note_on' and msg.velocity > 0:
note_dict[time_in_seconds].append(f"{msg.note}")
elif msg.type == 'note_off' or (msg.type == 'note_on' and msg.velocity == 0):
note_dict[time_in_seconds].append(f"{msg.note}")

output = []
for time, notes in sorted(note_dict.items()):
if len(notes) > 1:
output.append(f"({','.join(notes)})/{time:.3f}s")
else:
output.append(f"{','.join(notes)}/{time:.3f}s")

with open(output_file_path, 'w') as f:
f.write('/'.join(output))

self.progress_label.config(text="")
messagebox.showinfo("转换完成", f"转换完成!输出保存至: {output_file_path}")

if __name__ == "__main__":
root = Tk()
app = MidiConverterApp(root)
root.mainloop()

点赞0


评论


看东方旭日升看东方旭日升

不知道为什么格式乱了

 

 

点赞0


评论


看东方旭日升看东方旭日升

输出如下:6/96430.000s/46/96474.000s/53/96479.000s/53/96522.000s/61/96527.000s/61/96571.000s/53/96576.000s/53/96619.000s/60/96624.000s/60/96799.000s/54/96818.000s/54/96862.000s/61/96867.000s/61/96911.000s/65/96915.000s/65/97003.000s/56/97013.000s/56/97056.000s/63/97061.000s/63/97105.000s/65/97110.000s/65/97197.000s/58/97207.000s/58/97250.000s/61/97255.000s/61/97299.000s/65/97304.000s/65/97391.000s/58/97401.000s/58/97575.000s/42/97595.000s/42/97639.000s/49/97643.000s/49/97687.000s/61/97692.000s/61/97779.000s/44/97789.000s/44/97833.000s/51/97838.000s/51/97881.000s/60/97886.000s/60/97973.000s/46/97983.000s/46/98027.000s/53/98032.000s/53/98075.000s/60/98080.000s/60/98124.000s/61/98129.000s/61/98172.000s/65/98177.000s/65/98352.000s/42/98371.000s/42/98415.000s/49/98420.000s/49/98464.000s/56/98468.000s/56/98556.000s/44/98565.000s/44/98609.000s/51/98614.000s/51/98658.000s/58/98662.000s/58/98750.000s/46/98760.000s/46/98803.000s/53/98808.000s/53/98852.000s/60/98857.000s/60/98900.000s/61/98905.000s/61/98949.000s/65/98954.000s/51/99118.000s/54/99125.000s/65/99128.000s/58/99133.000s/61/99140.000s/51/99292.000s/54/99300.000s/58/99307.000s/53/99312.000s/61/99315.000s/56/99322.000s/60/99332.000s/53/99486.000s/56/99496.000s/60/99506.000s/46/99536.000s/46/99573.000s/53/99577.000s/53/99614.000s/58/99619.000s/58/99656.000s/61/99660.000s/61/99697.000s/60/99701.000s/60/99738.000s/63/99742.000s/63/99779.000s/65/99784.000s/65/99821.000s/70/99825.000s/70/99862.000s

 

点赞0


评论