设计简谱转88键钢琴音程序
11 2025-11-16 11:58
提问过程:
用python写一个简谱换算程序,将1234567 对应asdfghj,当碰到数字前有b那么就降半音,当碰到数字前有<那么久对应zxcvbnm,当碰到数字前有>那么就对应qwertyu,用tk实现,输入是一个文本框,点击按钮输出,输出是一个文本框,再有一个按钮可以导出成文本文件。
补充一下解决方案,降半音,用上一个音的大写表示
不对,降半音,用前面的音的大写字母表示
当碰到低音或高音,降半音,也适用上述规则,举例:b<7应该输出N
根据输入的回车换行,输出对应换行
✅ 完全理解你的意思了:
降半音规则适用于所有音区(低音、中音、高音),
即:b<7→ 前一个音是<6→ 对应n→ 大写 →N
✅ 更新规则(通用)
我们将音阶按顺序排列成一条“循环链”:
复制
中音:1 2 3 4 5 6 7
低音:<1 <2 <3 <4 <5 <6 <7
高音:>1 >2 >3 >4 >5 >6 >7
降半音 = 在当前音区中,找前一个音,输出其对应字母的大写
✅ 实现方式:统一映射 + 降半音链
我们用三个列表表示顺序,统一处理:
Python
复制
# 音阶顺序(用于降半音查找)
basic_order = ['1', '2', '3', '4', '5', '6', '7']
low_order = ['<1', '<2', '<3', '<4', '<5', '<6', '<7']
high_order = ['>1', '>2', '>3', '>4', '>5', '>6', '>7']
# 映射表
basic_map = {'1': 'a', '2': 's', '3': 'd', '4': 'f', '5': 'g', '6': 'h', '7': 'j'}
low_map = {'<1': 'z', '<2': 'x', '<3': 'c', '<4': 'v', '<5': 'b', '<6': 'n', '<7': 'm'}
high_map = {'>1': 'q', '>2': 'w', '>3': 'e', '>4': 'r', '>5': 't', '>6': 'y', '>7': 'u'}
# 合并映射
all_map = {**basic_map, **low_map, **high_map}
# 降半音处理函数
def get_flat_note(note):
if note.startswith('<'):
order = low_order
elif note.startswith('>'):
order = high_order
else:
order = basic_order
index = order.index(note)
prev_index = (index - 1) % 7
prev_note = order[prev_index]
return all_map[prev_note].upper()
✅ 示例对照表
表格
复制
| 输入 | 含义 | 输出 |
|---|---|---|
b<7 |
降低音7 | N(前一个 <6 → n → 大写) |
b>3 |
降高音3 | W(前一个 >2 → w → 大写) |
b1 |
降中音1 | J(前一个 7 → j → 大写) |
✅ 更新后的完整程序(已支持全域降半音)
Python
复制
import tkinter as tk
from tkinter import filedialog, messagebox
# 音阶顺序
basic_order = ['1', '2', '3', '4', '5', '6', '7']
low_order = ['<1', '<2', '<3', '<4', '<5', '<6', '<7']
high_order = ['>1', '>2', '>3', '>4', '>5', '>6', '>7']
# 映射表
basic_map = {'1': 'a', '2': 's', '3': 'd', '4': 'f', '5': 'g', '6': 'h', '7': 'j'}
low_map = {'<1': 'z', '<2': 'x', '<3': 'c', '<4': 'v', '<5': 'b', '<6': 'n', '<7': 'm'}
high_map = {'>1': 'q', '>2': 'w', '>3': 'e', '>4': 'r', '>5': 't', '>6': 'y', '>7': 'u'}
all_map = {**basic_map, **low_map, **high_map}
def get_flat_note(note):
if note.startswith('<'):
order = low_order
elif note.startswith('>'):
order = high_order
else:
order = basic_order
index = order.index(note)
prev_index = (index - 1) % 7
prev_note = order[prev_index]
return all_map[prev_note].upper()
def convert_note(note):
note = note.strip()
if note.startswith('b'):
base = note[1:]
if base in all_map:
return get_flat_note(base)
else:
return f"[无效:{note}]"
else:
return all_map.get(note, f"[无效:{note}]")
def convert():
input_text = input_box.get("1.0", tk.END).strip()
if not input_text:
messagebox.showwarning("输入为空", "请输入简谱内容!")
return
notes = input_text.split()
converted = " ".join(convert_note(n) for n in notes)
output_box.delete("1.0", tk.END)
output_box.insert(tk.END, converted)
def export_to_file():
content = output_box.get("1.0", tk.END).strip()
if not content:
messagebox.showwarning("无内容", "没有可导出的内容!")
return
file_path = filedialog.asksaveasfilename(defaultextension=".txt",
filetypes=[("文本文件", "*.txt")])
if file_path:
with open(file_path, "w", encoding="utf-8") as f:
f.write(content)
messagebox.showinfo("导出成功", f"已保存为:{file_path}")
# GUI
root = tk.Tk()
root.title("简谱换算器")
root.geometry("600x500")
tk.Label(root, text="输入简谱:").pack(anchor="w", padx=10)
input_box = tk.Text(root, height=8)
input_box.pack(fill="both", padx=10, pady=5)
tk.Label(root, text="输出结果:").pack(anchor="w", padx=10)
output_box = tk.Text(root, height=8)
output_box.pack(fill="both", padx=10, pady=5)
button_frame = tk.Frame(root)
button_frame.pack(pady=10)
tk.Button(button_frame, text="换算", width=10, command=convert).pack(side="left", padx=5)
tk.Button(button_frame, text="导出文本", width=10, command=export_to_file).pack(side="left", padx=5)
tk.Button(button_frame, text="清空", width=10, command=lambda: (input_box.delete("1.0", tk.END), output_box.delete("1.0", tk.END))).pack(side="left", padx=5)
root.mainloop()
✅ 最终示例
输入:
b<7 b>3 b1 <1 >5
输出:
N W J z t
如需支持:
-
升半音(如
#) -
节奏符号
-
导出为 MIDI 或演奏音频
我也可以继续帮你加上!
全部评论