870920 Menu

MIDI编程的基础常识 2-2

  • SMF:标准MIDI文件(Standard MIDI File),二进制文件,扩展名为“.mid”。格式1为通道分轨,格式0为所有通道集中为一轨。
  • 采用格式1的MIDI文件,其每一轨通常以这些MIDI消息作为其参数:Program Change, Volume, Pan, Reverb, Chorus等等。
  • 时间戳(Time Stamp):每个MIDI消息均有一个时间戳信息,该信息标示了本条消息所执行的时间点,亦即本条消息在MIDI序列中的“位置”。

 Tempo(速度元事件):每个四分音符的时值为多少毫秒。不给出则默认500毫秒(对应120 BPM)。
 BPM(音乐速度):每分钟几拍(每分钟几个四分音符),此值与拍号无关。Tempo速度元事件转换为BPM的公式为:BPM = 60,000 / Tempo
 PPQ(时基):每个四分音符的嘀嗒值。嘀嗒值与乐曲的速度值无关。比如:可以使用120 PPQ嘀嗒值播放速度为100 BPM的乐曲,也可以使用480或960 PPQ的嘀嗒值来播放同一个乐曲。
 MIDI时钟(Clock):用于两个设备之间的播放同步。每个四分音符有24个MIDI时钟。比如:一个设备按其当前速度生成MIDI时钟,另一个设备收到该时钟后,以此为时间单位进行同步。MIDI时钟与SMPTE不同,MIDI时钟发送的字节数据是乐曲速度的相对比率。可以按PPQN嘀嗒值计算MIDI时钟,如果每个四分音符为96 PPQN,则MIDI时钟则为96 / 24 = 4,即每四个PPQN出现一个MIDI时钟。
 SMPTE(时间码):单位为:“时:分:秒”,允许将秒分为更小的单位“帧”,有4种不同的帧率:每秒24、25、29或30帧,每一帧又可以细分为subframes(子帧)。SMPTE不直接关联到乐曲速度,也不随乐曲速度而改变。
 MIDI文件可使用两种时间格式:SMF:每个四分音符多少个PPQ(嘀嗒);SMPTE:每秒多少个PPQ。某个MIDI文件具体使用了哪种时间格式,可使用JUCE类库中MidiFile::getTimeFormat()函数来获取,其返回值为正数,代表使用了SMF格式,返回值为负数,则代表使用了SMPTE格式。同理,写入MIDI文件时,可使用MidiFile::setTicksPerQuarterNote()或者MidiFile::setSmpteTimeFormat()设置其时间格式。

MIDI速度、时基与时间码的计算公式
 BPM = 60,000 / Tempo(MIDI文件中的速度元事件)
 每个PPQN的毫秒时间 = Tempo / PPQN(960,480,120等等)
 每个MIDI时钟的毫秒时间 = Tempo / 24
 每个MIDI时钟对应的PPQN = PPQN / 24
 每个四分音符的子帧时间 = Tempo / (帧率 * 子帧率)
 每个PPQN的子帧时间 = 每个四分音符的子帧时间/嘀嗒时基
 每个PPQN的毫秒时间 = 每个PPQN的子帧时间 * 帧率 * 子帧率

关于MIDI消息与MIDI事件(JUCE类库的硬性规定和内部做法):
 MIDI消息和MIDI事件是两个概念。MIDI消息无时间戳,MIDI事件则是带有时间戳的MIDI消息
 外部的MIDI数据在读入内存时就已忽略(丢弃)其原始时间戳信息
 JUCE内部为每个MIDI消息添加“位置”信息,该信息相当于无单位的时间戳