Python使用PyGame模块播放midi音符(二)

本文是关于Python使用PyGame模块播放midi音符系列的第二部分,继续探讨如何导入和播放midi音乐,帮助开发者实现自动化音频处理。
摘要由CSDN通过智能技术生成

(换了个号发)

接上回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: 拍号, 由两
  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值