设计简谱转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(前一个 <6n → 大写)
b>3 降高音3 W(前一个 >2w → 大写)
b1 降中音1 J(前一个 7j → 大写)

✅ 更新后的完整程序(已支持全域降半音)

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 或演奏音频
我也可以继续帮你加上!

全部评论

·