(换了个号发)
接上回Python使用PyGame模块播放midi音符(一)_python如何导入midi音乐-CSDN博客
但懒了,直接自己看吧:
'''
Author: Zhu Yiqi
version: 1.20.3
Date: 2023-08-29 08:05:38
FilePath: \code\python\MIDI\Music.py
LastEditors: Zhu Yiqi
LastEditTime: 2024-02-17 22:18:05
Encoding: UTF-8
Description: A python module used to play midi music
Usage:
from Music import Music
music = Music()
music.play('C')
music.sosPedal()
( ... )
music.close()
'''
from pygame.midi import *#导入pygame.midi模块,用于播放midi音乐
import pygame.midi
import re #导入re模块,用于正则表达式
import music21 #导入music21模块,用于音乐分析
import time #导入time模块,用于计时
from threading import Thread #导入Thread类,用于多线程播放音乐
class Check:
"""
这是一个用于检查踏板状态和开关状态的类。
"""
def check_pedal_state(self, state):
"""
检查踏板的状态, 并返回相应的结果。
参数:
- state: 踏板的状态, 可以是布尔值、整数或字符串类型。
返回值:
- 如果踏板状态为真或者等于 'on' 或者等于 1, 则返回 '踩下'。
- 否则返回 '松开'。
"""
if isinstance(state, str):
state.lower()
if state or state == 'on' or state == 1:
return '踩下'
else:
return '松开'
def check_on_off(self, on_off, original=None):
"""
检查开关的状态, 并返回相应的结果。
参数:
- on_off: 开关的状态, 可以是布尔值、整数或字符串类型。
- original: 原始状态, 可选参数。
返回值:
- 如果开关状态为 'on'、True 或者 1, 则返回 True。
- 如果开关状态为 'off'、False 或者 0, 则返回 False。
- 其他情况下, 返回取反后的 original 值。
"""
if isinstance(on_off, str): #如果传入的是字符串
on_off = on_off.lower() #将字符串转换为小写
if on_off == 'on' or on_off == True or on_off == 1:
return True
elif on_off == 'off' or on_off == False or on_off == 0:
return False
else:
return not original
class PrintMusicInfo:
'''
打印音乐信息、音符信息、和弦信息、休止符信息、踏板信息
需要传入Midi类的对象、通道
与Midi类的对象的isPrintInfo属性配合使用
'''
"""
这是一个用于打印音乐信息的类, 包含了打印音乐的各种元素的方法。
"""
def prt_init(self, music, channel, tune, isPrintInfo=True):
"""
初始化打印音乐信息的对象。
参数:
- music: MidiMusic类的对象, 表示要打印信息的音乐。
- channel: 通道, 表示音乐所在的通道。
- isPrintInfo: 是否打印信息, 默认为True。
返回值: 无。
"""
self.note_count = 0 #音符计数器,用于计算音符个数
self.chord_count = 0 #和弦计数器,用于计算和弦个数
self.rest_count = 0 #休止符计数器,用于计算休止符个数
self.pedal_count = 0 #踏板计数器,用于计算踏板操作次数
self.music = music #MidiMusic类的对象
self.ctrl = MidiControl #MidiControl类的对象
self.channel = channel #通道
self.tune = tune #曲调
self.isPrintInfo = isPrintInfo #是否打印信息
def print_musicInfo(self):
"""
打印音乐的基本信息。
参数: 无。
返回值: 无。
"""
if self.isPrintInfo:
print('---音乐信息---')
print('曲调:', self.tune)
print('拍号:', self.music.signature)
print('八分音符时长(秒):', self.music.quarterNote_duration)
print('基础力度:', self.music.base_dynamics)
print('强弱规律:', self.music.rhythm)
print('通道:', self.music.channel)
print('乐器名:', self.music.instrument_name, '乐器id:', self.music.instrument_id)
print('设备id:', self.music.output.device_id)
print('设备信息:', get_device_info(self.music.output.device_id))
print('\n')
print('---音乐开始---')
self.start_time = time.time() #记录开始时间
def print_noteInfo(self, note, duration, dynamics_value):
"""
打印音符的详细信息。
参数:
- note: 音符。
- duration: 音符的时长。
- dynamics_mark: 力度标记。
- dynamics_value: 力度值。
返回值: 无。
"""
self.note_count += 1
if self.isPrintInfo:
print('第', self.note_count, '个单音')
print('音符:', note, '--- midi码:', self.music.note2midi(note))
print('时长(四分音符):', duration/self.music.quarterNote_duration, '--- 时长(秒):', duration)
print('力度标记:', self.music.dynamics_val2mark(dynamics_value), ' --- 力度值:', dynamics_value)
print('\n')
def print_chordInfo(self, duration, dynamics_mark, dynamics_value, *notes):
"""
打印和弦的详细信息。
参数:
- duration: 和弦的时长。
- dynamics_mark: 力度标记。
- dynamics_value: 力度值。
- *notes: 和弦中的音符。
返回值: 无。
"""
self.chord_count += 1
if self.isPrintInfo:
print(notes)
print('第', self.chord_count, '个和弦')
print('音符:', notes, sep='\n')
midis=[]
for note in notes:
midis.append(self.music.note2midi(note))
print('midi码:', midis, sep='\n')
print('时长(秒):', duration, '--- 时长(四分音符): ', duration/self.music.quarterNote_duration)
print('力度标记:', dynamics_mark, '--- 力度值:', dynamics_value)
print('\n')
#打印休止符信息
def print_restInfo(self, duration):
"""
打印休止符的详细信息。
参数:
- duration: 休止符的时长。
返回值: 无。
"""
self.rest_count += 1
if self.isPrintInfo:
print('第', self.rest_count, '个休止符')
print('时长(秒):', duration, '--- 时长(四分音符):', duration/self.music.quarterNote_duration)
print('\n')
#打印踏板信息
def print_pedalInfo(self):
"""
打印踏板的详细信息。
参数: 无。
返回值: 无。
"""
self.pedal_count += 1
if self.isPrintInfo:
print('第', self.pedal_count, '次踏板操作')
print('延音踏板(右踏板):', self.ctrl.check_pedal_state(self.ctrl, self.music.sostenutoPedal_state))
print('弱音踏板(左踏板):', self.ctrl.check_pedal_state(self.ctrl, self.music.softPedal_state))
print('\n')
def print_endingInfo(self):
"""
打印音乐结束的信息。
参数: 无。
返回值: 无。
"""
if self.isPrintInfo:
print('---音乐结束---')
print('音符个数:', self.note_count)
print('和弦个数:', self.chord_count)
print('休止符个数:', self.rest_count)
print('踏板操作次数:', self.pedal_count)
print('音乐时长(秒):', round(time.time()-self.start_time, 2))
class MusicConvert:
'''
转换音乐数据
转换音符名、midi码、简谱音符
分析曲调、bpm、拍号
计算音符时长、力度
'''
def cvt_init(self, tune='C', bpm=120, signature=[4,4], instrument="piano", default_noteDuration=1, base_dynamics=16):
"""
初始化音乐转换器。
参数:
- tune: 曲调, 默认为 'C'。
- bpm: 每分钟的节拍数, 默认为 120。
- signature: 拍号, 由两