Детский синтезатор "Музыка с мамой"

Музыка с мамой

Детский синтезатор для малышей
ИГРАЙ!
До
Я / Z
Ре
Ч / X
Ми
С / C
Фа
М / V
Соль
И / B
Ля
Т / N
Си
Ь / M
До
Б / ,
????

Как играть:

Нажимайте мышкой на клавиши или используйте клавиши на клавиатуре:

Я или Z
Ч или X
С или C
М или V
И или B
Т или N
Ь или M
Б или ,

При нажатии появится пальчик и прозвучит нота!

from music21 import stream, note, meter, clef, environment import tkinter as tk from tkinter import ttk, filedialog, messagebox import os # Основной класс приложения class MusicNotationApp: def __init__(self, root): self.root = root self.root.title("Нотный редактор") self.root.geometry("800x600") self.root.configure(bg="#f0f0f0") # Инициализация партитуры self.score = stream.Score() self.part = stream.Part() self.part.insert(0, clef.TrebleClef()) self.part.insert(0, meter.TimeSignature('4/4')) self.score.append(self.part) # Переменные интерфейса self.note_var = tk.StringVar(value="C4") self.duration_var = tk.StringVar(value="quarter") self.position_var = tk.StringVar(value="0.0") self.create_widgets() self.setup_environment() def setup_environment(self): """Настройка путей для MuseScore""" try: # Попробуем автоматически найти MuseScore if os.name == 'nt': # Windows paths = [ "C:/Program Files/MuseScore 4/bin/MuseScore4.exe", "C:/Program Files/MuseScore 3/bin/MuseScore3.exe" ] else: # Mac/Linux paths = [ "/Applications/MuseScore 4.app/Contents/MacOS/mscore", "/usr/bin/musescore", "/usr/local/bin/musescore" ] for path in paths: if os.path.exists(path): environment.set('musescoreDirectPNGPath', path) environment.set('musicxmlPath', path) break except Exception as e: messagebox.showerror("Ошибка", f"MuseScore не найден: {str(e)}") def create_widgets(self): """Создание элементов интерфейса""" # Стили style = ttk.Style() style.configure("TFrame", background="#f0f0f0") style.configure("TButton", padding=6, font=("Arial", 10)) style.configure("TLabel", background="#f0f0f0", font=("Arial", 10)) # Основные фреймы control_frame = ttk.Frame(self.root, padding=10) control_frame.pack(fill=tk.X, padx=10, pady=5) display_frame = ttk.Frame(self.root) display_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5) # Поля ввода ttk.Label(control_frame, text="Высота ноты (C4, D#3, etc):").grid(row=0, column=0, sticky=tk.W) note_entry = ttk.Entry(control_frame, textvariable=self.note_var, width=10) note_entry.grid(row=0, column=1, padx=5) ttk.Label(control_frame, text="Длительность:").grid(row=0, column=2, sticky=tk.W, padx=(10,0)) durations = ["whole", "half", "quarter", "eighth", "16th"] duration_combo = ttk.Combobox(control_frame, textvariable=self.duration_var, values=durations, width=8) duration_combo.grid(row=0, column=3) ttk.Label(control_frame, text="Позиция:").grid(row=0, column=4, sticky=tk.W, padx=(10,0)) ttk.Entry(control_frame, textvariable=self.position_var, width=8).grid(row=0, column=5) # Кнопки управления buttons = [ ("Добавить ноту", self.add_note), ("Добавить паузу", self.add_rest), ("Удалить последнюю", self.delete_last), ("Показать партитуру", self.show_score), ("Воспроизвести", self.play_score), ("Сохранить", self.save_score), ("Очистить", self.clear_score) ] for i, (text, command) in enumerate(buttons): ttk.Button(control_frame, text=text, command=command).grid(row=1, column=i, padx=5, pady=10) # Область отображения нот self.text_display = tk.Text(display_frame, wrap=tk.WORD, font=("Courier New", 12)) self.text_display.pack(fill=tk.BOTH, expand=True) self.text_display.insert(tk.END, "Партитура пуста. Добавьте ноты.") self.text_display.config(state=tk.DISABLED) # Статус бар self.status_var = tk.StringVar(value="Готово") status_bar = ttk.Label(self.root, textvariable=self.status_var, relief=tk.SUNKEN, anchor=tk.W) status_bar.pack(side=tk.BOTTOM, fill=tk.X) def add_note(self): """Добавление ноты в партитуру""" try: pitch = self.note_var.get() duration_type = self.duration_var.get() position = float(self.position_var.get()) n = note.Note(pitch) n.duration.type = duration_type self.part.insert(position, n) self.update_display(f"Добавлена нота: {pitch} ({duration_type}) на позиции {position}") self.status_var.set(f"Добавлена нота: {pitch}") except Exception as e: messagebox.showerror("Ошибка", f"Невозможно добавить ноту: {str(e)}") def add_rest(self): """Добавление паузы в партитуру""" try: duration_type = self.duration_var.get() position = float(self.position_var.get()) r = note.Rest() r.duration.type = duration_type self.part.insert(position, r) self.update_display(f"Добавлена пауза: ({duration_type}) на позиции {position}") self.status_var.set(f"Добавлена пауза") except Exception as e: messagebox.showerror("Ошибка", f"Невозможно добавить паузу: {str(e)}") def delete_last(self): """Удаление последнего элемента""" if len(self.part.notesAndRests) > 0: last_element = self.part.notesAndRests[-1] self.part.remove(last_element) self.update_display("Удалён последний элемент") self.status_var.set("Удалён последний элемент") else: messagebox.showinfo("Информация", "Партитура пуста") def show_score(self): """Отображение нотного стана""" try: self.score.show('musicxml.png') self.status_var.set("Партитура отображена") except Exception as e: messagebox.showerror("Ошибка", f"Невозможно отобразить партитуру: {str(e)}\nУстановите MuseScore") def play_score(self): """Воспроизведение MIDI""" try: self.score.show('midi') self.status_var.set("Воспроизведение...") except Exception as e: messagebox.showerror("Ошибка", f"Невозможно воспроизвести: {str(e)}") def save_score(self): """Сохранение партитуры в файл""" try: file_path = filedialog.asksaveasfilename( defaultextension=".musicxml", filetypes=[ ("MusicXML", "*.musicxml"), ("MIDI", "*.mid"), ("PDF", "*.pdf") ] ) if file_path: if file_path.endswith(".pdf"): self.score.write('musicxml.pdf', fp=file_path) elif file_path.endswith(".mid"): self.score.write('midi', fp=file_path) else: self.score.write('musicxml', fp=file_path) self.status_var.set(f"Файл сохранён: {file_path}") except Exception as e: messagebox.showerror("Ошибка", f"Ошибка сохранения: {str(e)}") def clear_score(self): """Очистка партитуры""" if messagebox.askyesno("Подтверждение", "Очистить всю партитуру?"): self.part.clear() self.update_display("Партитура очищена") self.status_var.set("Партитура очищена") def update_display(self, action_message): """Обновление текстового отображения партитуры""" self.text_display.config(state=tk.NORMAL) self.text_display.delete(1.0, tk.END) if len(self.part.notesAndRests) == 0: self.text_display.insert(tk.END, "Партитура пуста. Добавьте ноты.") else: self.text_display.insert(tk.END, "Текущая партитура:\n\n") for i, element in enumerate(self.part.notesAndRests): if isinstance(element, note.Note): info = f"{i+1}. Нота: {element.pitch} | Длительность: {element.duration.type} | Позиция: {element.offset}" else: info = f"{i+1}. Пауза | Длительность: {element.duration.type} | Позиция: {element.offset}" self.text_display.insert(tk.END, info + "\n") self.text_display.insert(tk.END, f"\n{action_message}") self.text_display.config(state=tk.DISABLED) if __name__ == "__main__": root = tk.Tk() app = MusicNotationApp(root) root.mainloop()
Made on
Tilda