深入理解Mido项目中的MIDI元消息类型
什么是MIDI元消息?
在MIDI文件处理中,元消息(Meta Messages)是一种特殊的消息类型,它们不包含实际的音乐数据,而是提供关于MIDI文件的结构、内容和播放方式的元信息。Mido项目作为一个强大的MIDI处理库,提供了对这些元消息类型的完整支持。
Mido支持的元消息类型详解
1. 序列相关消息
sequence_number (0x00)
- 作用:在类型0和1的MIDI文件中表示序列号,在类型2文件中表示模式号
- 属性:number (0-65535)
- 默认值:0
2. 文本信息类消息
text (0x01)
- 通用文本消息,可用于任何基于文本的数据
- 属性:text (字符串)
- 默认值:空字符串
copyright (0x02)
- 提供MIDI文件的版权信息
- 属性:text (字符串)
- 默认值:空字符串
track_name (0x03)
- 存储MIDI音轨名称
- 属性:name (字符串)
- 默认值:空字符串
instrument_name (0x04)
- 存储乐器名称
- 属性:name (字符串)
- 默认值:空字符串
lyrics (0x05)
- 存储歌曲歌词,通常每个消息对应一个音节
- 属性:text (字符串)
- 默认值:空字符串
3. 标记类消息
marker (0x06)
- 标记MIDI文件中的兴趣点,如歌曲的段落开始
- 属性:text (字符串)
- 默认值:空字符串
cue_marker (0x07)
- 标记提示点,如"提示表演者1"等
- 属性:text (字符串)
- 默认值:空字符串
4. 设备与通道配置
device_name (0x09)
- 提供设备名称
- 属性:name (字符串)
- 默认值:空字符串
channel_prefix (0x20)
- 指定事件播放的通道前缀
- 属性:channel (0-255)
- 默认值:0
midi_port (0x21)
- 指定事件播放的MIDI端口
- 属性:port (0-255)
- 默认值:0
5. 音轨控制
end_of_track (0x2f)
- 标记音轨结束的空消息
- 无属性
6. 时间与节奏控制
set_tempo (0x51)
- 设置节奏,单位为每拍(四分音符)微秒数
- 属性:tempo (0-16777215)
- 默认值:500000
- 注意:可以使用bpm2tempo和tempo2bpm函数在BPM和tempo之间转换
smpte_offset (0x54)
- 设置SMPTE时间码偏移
- 属性:
- frame_rate (24,25,29.97,30)
- hours (0-255)
- minutes (0-59)
- seconds (0-59)
- frames (0-255)
- sub_frames (0-99)
time_signature (0x58)
- 设置拍号
- 属性:
- numerator (0-255)
- denominator (1-2^255)
- clocks_per_click (0-255)
- notated_32nd_notes_per_beat (0-255)
- 默认值:4/4拍号
key_signature (0x59)
- 设置调号
- 属性:key (如'C', 'F#m'等)
- 默认值:'C'
- 注意:小调调号以'm'结尾
7. 特殊消息
sequencer_specific (0x7f)
- 特定于音序器的原始数据消息
- 属性:data (字节列表)
- 默认值:空列表
处理未知元消息
当Mido遇到未实现的元消息时,会返回UnknownMetaMessage
对象,包含:
- type_byte:标识消息类型的字节
- data:消息数据的字节列表
这类消息会被原样保存回文件,但依赖它们的代码在未来该消息被实现时可能会失效。
实现自定义元消息
Mido允许开发者添加新的或自定义的元消息类型。实现步骤:
- 创建MetaSpec子类
- 实现必要的解码/编码方法
- 添加新的消息类型
示例实现一个灯光颜色消息:
from mido.midifiles.meta import MetaSpec, add_meta_spec
class MetaSpec_light_color(MetaSpec):
type_byte = 0xf0
attributes = ['r', 'g', 'b']
defaults = [0, 0, 0]
def decode(self, message, data):
message.r, message.g, message.b = data
def encode(self, message):
return [message.r, message.g, message.b]
def check(self, name, value):
if not isinstance(value, int):
raise TypeError(f'{name} must be an integer')
if not 0 <= value <= 255:
raise TypeError(f'{name} must be in range 0..255')
add_meta_spec(MetaSpec_light_color)
之后就可以像其他消息一样使用:
MetaMessage('light_color', r=120, g=60, b=10)
对于只包含单个文本属性的消息,可以继承现有的文本消息类来简化实现。
总结
Mido项目提供了对MIDI元消息的全面支持,从基本的文本信息到复杂的节奏和调号控制。通过理解这些消息类型,开发者可以更好地处理和创建MIDI文件。同时,Mido的扩展性允许添加自定义消息类型,为特殊应用场景提供了灵活性。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考