我试图用C#编写MIDI文件。我正在使用Sanford MIDI工具包。以下是我用来编写NoteOnNoteOff事件的代码段。

private static void InsertNoteOn(Track t, int pitch, int velocity, int position, int duration, int channel)
{
    ChannelMessageBuilder builder = new ChannelMessageBuilder();
    builder.Command = ChannelCommand.NoteOn;
    builder.Data1 = pitch;
    builder.Data2 = velocity;
    builder.MidiChannel = channel;
    builder.Build();
    t.Insert(position, builder.Result);
}

private static void InsertNoteOff(Track t, int pitch, int velocity, int position, int duration, int channel)
{
    ChannelMessageBuilder builder = new ChannelMessageBuilder();
    builder.Command = ChannelCommand.NoteOff;
    builder.Data1 = pitch;
    builder.Data2 = velocity;
    builder.MidiChannel = channel;
    builder.Build();
    t.Insert((position + duration), builder.Result);
}


首先,我为曲目的所有音符插入所有NoteOn事件,然后插入曲目的所有NoteOff事件。

该方法大多数时候都有效。但是,有时生成的MIDI文件显示不正确。当两个相同音高的音符接连写入时,有时会出现问题。第一个音符的长度等于两个音符的长度,第二个音符的长度为零。

我的假设是,第一个音符的NoteOff事件被解释为第二个音符的NoteOff,反之亦然。

我尝试了以下变体:


在轨道中按时间顺序添加每个音符及其NoteOnNoteOff事件


如果音符的位置相同,则从上音高到下音高
如果音符的位置相同,则从下音高到上音高

按时间顺序添加所有NoteOn事件,然后按时间顺序添加所有NoteOff事件
按时间顺序添加所有NoteOff事件,然后按时间顺序添加所有NoteOn事件
尽可能减少所有音符的长度


只有最后一种方法有效,但是音符的长度较短,不能解决问题。

有没有解决的办法?跟踪中的NoteOnNoteOff事件是否有特定顺序?是否有特定的顺序调用轨道插入方法?

编辑:在以下情况下会出现问题:
c# - MIDI音符长度不正确-LMLPHP

为了提高可见性,将较高的音符从C移至C#。这些应该是两个具有相同长度的音符,但是相反,一个具有两个音符的长度,而另一个具有零长度。

最佳答案

在MIDI文件中,多个事件可能具有相同的时间戳。在这种情况下,它们以与写入文件时相同的顺序通过电线发送。

Sanford MIDI工具包仅使用时间戳来指定事件的位置,而没有说明如何处理具有相同时间戳的多个事件。

为了确保音符关闭事件先于音符打开事件,您必须使用不同的时间戳,即减少音符的长度。 (要降低实际差异,请增加时间戳分辨率。)

关于c# - MIDI音符长度不正确,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34107258/

10-12 12:43