将 MIDI 歌曲事件与初始设置事件分开

Posted

技术标签:

【中文标题】将 MIDI 歌曲事件与初始设置事件分开【英文标题】:Separate MIDI song events from initial setup events 【发布时间】:2011-07-17 11:44:14 【问题描述】:

我正在使用 Java Sequencer 播放 MIDI 歌曲。这首歌被设计为连续循环播放,我可以很容易地做到这一点sequencer.@987654322@(Sequencer.LOOP_CONTINUOUSLY) 当通过内部(声卡)合成器播放时,它可以正常工作并且(如果需要,可以添加 dummy event)循环时间是正确的。

但是,当通过外部(USB 或串行)合成器播放时,在输出循环点处会出现明显的间隙。这是因为在 .mid 文件的开头有许多设置事件需要一些时间才能通过串行线路发送。

我想尝试将一次性设置事件隔离到它们自己的Sequence 中,当歌曲加载时发送到设备一次,但不会进入主(循环)Sequence

有没有简单的算法(或库函数)可以区分这两种事件?

需要提供:

Registered parameter 更改,作为一组相关消息发送。 偶尔会在曲目中间发送频道节目更改(并且必须是循环序列的一部分),但如果在整个歌曲中保留相同的节目(大多数情况下),节目更改应该是曲目的一部分设置顺序。这同样适用于节奏变化。

【问题讨论】:

这是因为 .mid 文件开头有许多设置事件需要一些时间才能通过串行线路发送 - 这是一个假设或猜测,或者您是否有来源(技术文章或调试输出)来证明它? @Charles Goodwin,不,我通过手动删除事件对此进行了测试 【参考方案1】:

看看 javax.sound.midi。序列由轨道组成。轨道包含 MidiEvents。 MidiEvents 是时间戳和 MidiMessage 的组合。

MidiMessage 有子类 ShortMessage、MetaMessage 和 SysexMessage。

最有可能在第 0 点 (MidiEvent.getTick() == 0) 过滤掉 SysexMessages 就可以了。如果没有,请尝试在刻度 0 处过滤 MetaMessage。注意信息、程序更改等都是通过 ShortMessage 完成的,不要过滤这些。

for each track in sequence 
  for all midievents in track at tick 0 
    remove from track if instanceof SysexMessage or MetaMessage
  

另一部分是创建初始化序列。只需创建具有相同分割类型和分辨率的序列。一个track就够了,你可以将所有从looping Sequence中移除的事件添加到初始化Sequence中的一个Track中。

【讨论】:

元消息不是问题的一部分,因为它们从未通过网络发送。

以上是关于将 MIDI 歌曲事件与初始设置事件分开的主要内容,如果未能解决你的问题,请参考以下文章

BLE MIDIMIDI 时间标志分析 ( 音符速度设置事件 | 拍号设置事件 | 基本时间 - 每个四分音符有多少 tick 或 pulse | 节拍时值计算 | 小节时值计算 )

UIAnimations 响应 Swift 中的 MIDI 事件

Actionscript 3 - 处理事件是不是与函数分开工作

将 MIDI 事件转换为 pygame 事件

解析 MIDI 文件以记录事件

从 PortMIDI 发送虚拟 MIDI 事件