如何将从音轨 1 提取的速度应用到 MIDI 文件的其他音轨?
Posted
技术标签:
【中文标题】如何将从音轨 1 提取的速度应用到 MIDI 文件的其他音轨?【英文标题】:How to apply the tempo extracted from track 1 to other tracks of a MIDI file? 【发布时间】:2017-05-31 06:30:28 【问题描述】:我正在尝试从 midi 文件的第一首曲目中提取旋律的节奏,并将其应用于包含音符事件的其余曲目。
基本上,我一直在尝试在 noteOn()
消息之后替换 Thread.sleep()
方法,该消息每次都以固定的时间间隔播放一个音符。因此,我失去了整首曲目的节奏。
我成功地从之前提出的问题How does Midi TEMPO message apply to other tracks? 中提取了第一首曲目的速度信息,但无法将其应用于其余曲目。
是否有特定的功能可以做到这一点?我尝试搜索但找不到。
这是我的代码供参考。
int trackNumber = 0;
for (Track track : sequence.getTracks())
trackNumber++;
System.out.println();
for (int i=0; i < track.size(); i++)
MidiEvent event = track.get(i);
MidiMessage message = event.getMessage();
if (message instanceof MetaMessage)
MetaMessage mm = (MetaMessage) message;
if(mm.getType()==SET_TEMPO)
byte[] data = mm.getData();
int tempo = (data[0] & 0xff) << 16 | (data[1] & 0xff) << 8 | (data[2] & 0xff);
int bpm = 60000000 / tempo;
if (message instanceof ShortMessage)
ShortMessage sm = (ShortMessage) message;
if (sm.getCommand() == NOTE_ON)
int key = sm.getData1();
int velocity = sm.getData2();
channels[0].noteOn(key,velocity);
Thread.sleep(280);//Pays all the note for fixed duration
else if (sm.getCommand() == NOTE_OFF)
int key = sm.getData1();
int velocity = sm.getData2();
channels[0].noteOff(key);
System.out.println();
【问题讨论】:
只需从第一个轨道克隆 SetTempo 事件,add 克隆实例到具有相同时间戳的其他轨道。 你修改方法了吗? 【参考方案1】:多个轨道中的事件同时发生,因此您不能单独处理轨道。
你必须要么
将所有事件放到一个列表中,并按时间戳排序(但要确保时间戳相同的事件保持顺序,所以使用稳定的排序算法);或 为每个轨道设置一个当前位置,并在确定下一个事件时,在所有轨道中搜索具有最小时间戳的尚未使用的事件。请注意,播放过程中速度会发生变化,因此单个 bpm
值是不够的。请参阅How to correctly convert MIDI ticks to milliseconds? 和How can I parse a tempo of midi using Java?。
【讨论】:
据我了解,在根据时间戳值对事件进行排序后,我应该将从它评估的增量时间值作为参数传递给Thread.sleep(millisec)
函数。让我知道这是否是您一直试图解释的。谢谢。
滴答声不是毫秒,增量时间是在单个轨道中的事件之间。排序后,需要重新计算相邻事件之间的定时器间隔。
相邻事件是什么意思?您有计算该间隔的公式吗?
@Stephane 查看链接的问题。以上是关于如何将从音轨 1 提取的速度应用到 MIDI 文件的其他音轨?的主要内容,如果未能解决你的问题,请参考以下文章
使用 MetaMessage getData() 和/或 MetaMessage 值从 java 中的 MIDI 文件中提取速度?
BLE MIDIMIDI 文件格式分析 ( FF 58 04 拍号 | 音符开指令 | 音符关指令 | 音轨结束标志 )
BLE MIDIMIDI 文件格式分析 ( FF 58 04 拍号 | 音符开指令 | 音符关指令 | 音轨结束标志 )