import tkinter as tk
import pygame.midi
import time
# 初始化 pygame.midi
pygame.midi.init()
# 获取 MIDI 输出设备
midi_out = pygame.midi.Output(0)
# 乐器名称映射
instrument_names = {
0:"大钢琴(声学钢琴)",
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:"小号",
57:"长号",
58:"大号",
59:"加弱音器小号",
60:"法国号(圆号)",
61:"铜管组(铜管乐器合奏音色)",
62:"合成铜管音色",
63:"合成铜管音色",
64:"高音萨克斯风",
65:"次中音萨克斯风",
66:"中音萨克斯风",
67:"低音萨克斯风",
68:"双簧管",
69:"英国管",
70:"巴松(大管)",
71:"单簧管(黑管)",
72:"短笛",
73:"长笛",
74:"竖笛",
75:"排箫",
76:"吹瓶声",
77:"日本尺八",
78:"口哨声",
79:"奥卡雷那",
80:"合成主音(方波)",
81:"合成主音(锯齿波)",
82:"合成主音",
83:"合成主音",
84:"合成主音",
85:"合成主音(人声)",
86:"合成主音(平行五度)",
87:"合成主音(贝司加主音)",
88:"合成音色(新世纪)",
89:"合成音色(温暖)",
90:"合成音色",
91:"合成音色(合唱)",
92:"合成音色",
93:"合成音色(金属声)",
94:"合成音色(光环)",
95:"合成音色",
96:"合成效果雨声",
97:"合成效果音轨",
98:"合成效果水晶",
99:"合成效果大气",
100:"合成效果明亮",
101:"合成效果鬼怪",
102:"合成效果回声",
103:"合成效果科幻",
104:"西塔尔(印度)",
105:"班卓琴(美洲)",
106:"三昧线(日本)",
107:"十三弦筝(日本)",
108:"卡林巴",
109:"风笛",
110:"民族提琴",
111:"唢呐",
112:"叮当铃",
113:"阿哥哥鼓",
114:"钢鼓",
115:"木鱼",
116:"太鼓",
117:"古高音鼓",
118:"合成鼓",
119:"铜钹",
120:"磨弦",
121:"呼吸声",
122:"海浪声",
123:"鸟鸣",
124:"电话铃",
125:"直升机",
126:"鼓掌声",
127:"枪声"
}
def play_note(note_number, duration, instrument):
midi_out.set_instrument(instrument)
midi_out.note_on(note_number, 125)
pygame.time.wait(duration)
midi_out.note_off(note_number, 125)
root = tk.Tk()
root.title("Digital Music Player")
# 设置窗口大小
root.geometry("800x600")
# 创建主旋律文本框
entry_main = tk.Text(root, wrap="word", height=5)
entry_main.pack(pady=10)
entry_main.place(x=10, y=10, width=300, height=100)
entry_main.insert(tk.END, "1155665/4433221/5544332/5544332/1155665/4433221/")
# 创建伴奏文本框
entry_accompaniment = tk.Text(root, wrap="word", height=5)
entry_accompaniment.pack(pady=10)
entry_accompaniment.place(x=10, y=200, width=300, height=100)
# 为主旋律选择乐器的下拉菜单
main_instrument_var = tk.StringVar(root)
default_main_instrument = 2
main_instrument_var.set(f"{default_main_instrument} - {instrument_names.get(default_main_instrument, 'Unknown')}")
main_instrument_menu = tk.OptionMenu(root, main_instrument_var, *[f"{i} - {instrument_names.get(i, 'Unknown')}" for i in range(128)])
main_instrument_menu.pack(pady=10)
main_instrument_menu.place(x=320, y=40, width=150, height=50)
# 为伴奏选择乐器的下拉菜单
accompaniment_instrument_var = tk.StringVar(root)
default_accompaniment_instrument = 116
accompaniment_instrument_var.set(f"{default_accompaniment_instrument} - {instrument_names.get(default_accompaniment_instrument, 'Unknown')}")
accompaniment_instrument_menu = tk.OptionMenu(root, accompaniment_instrument_var, *[f"{i} - {instrument_names.get(i, 'Unknown')}" for i in range(128)])
accompaniment_instrument_menu.pack(pady=10)
accompaniment_instrument_menu.place(x=320, y=230, width=150, height=50)
# 为主旋律选择调式的下拉菜单
main_tune_var = tk.StringVar(root)
default_main_tune = "C 大调"
main_tune_var.set(default_main_tune)
main_tune_menu = tk.OptionMenu(root, main_tune_var, "C 大调", "D 大调", "E 大调", "F 大调", "G 大调", "A 大调", "B 大调")
main_tune_menu.pack(pady=10)
main_tune_menu.place(x=500, y=40, width=150, height=50)
# 为伴奏选择调式的下拉菜单
accompaniment_tune_var = tk.StringVar(root)
default_accompaniment_tune = "C 大调"
accompaniment_tune_var.set(default_accompaniment_tune)
accompaniment_tune_menu = tk.OptionMenu(root, accompaniment_tune_var, "C 大调", "D 大调", "E 大调", "F 大调", "G 大调", "A 大调", "B 大调")
accompaniment_tune_menu.pack(pady=10)
accompaniment_tune_menu.place(x=500, y=230, width=150, height=50)
# 创建文本框的右键菜单
def show_textbox_menu(event):
menu = tk.Menu(root, tearoff=0)
menu.add_command(label="剪切", command=lambda: event.widget.event_generate("<<Cut>>"))
menu.add_command(label="复制", command=lambda: event.widget.event_generate("<<Copy>>"))
menu.add_command(label="粘贴", command=lambda: event.widget.event_generate("<<Paste>>"))
menu.add_separator()
menu.add_command(label="全选", command=lambda: event.widget.event_generate("<<SelectAll>>"))
menu.post(event.x_root, event.y_root)
entry_main.bind("<Button-3>", show_textbox_menu)
entry_accompaniment.bind("<Button-3>", show_textbox_menu)
def play_music():
main_music_notes = entry_main.get("1.0", "end-1c")
accompaniment_music_notes = entry_accompaniment.get("1.0", "end-1c")
base_duration = 100 # 基础音符时长
main_note_index = 0
accompaniment_note_index = 0
main_notes_playing = []
accompaniment_notes_playing = []
while main_note_index < len(main_music_notes) or accompaniment_note_index < len(accompaniment_music_notes):
main_note_char = main_music_notes[main_note_index] if main_note_index < len(main_music_notes) else None
accompaniment_note_char = accompaniment_music_notes[accompaniment_note_index] if accompaniment_note_index < len(accompaniment_music_notes) else None
if main_note_char == '/':
time.sleep(0.5)
main_note_index += 1
continue
if accompaniment_note_char == '/':
time.sleep(0.5)
accompaniment_note_index += 1
continue
main_note_number = convert_note(main_note_char)
accompaniment_note_number = convert_note(accompaniment_note_char)
if main_note_number is not None:
main_tune =