Отделить события MIDI-песни от событий начальной настройки - PullRequest
5 голосов
/ 17 июля 2011

Я играю MIDI-песню, используя Java Sequencer . Песня предназначена для непрерывного зацикливания, что я легко могу сделать с
sequencer.<a href="http://download.oracle.com/javase/6/docs/api/javax/sound/midi/Sequencer.html#setLoopCount%28int%29" rel="nofollow">setLoopCount</a>(Sequencer.LOOP_CONTINUOUSLY)
При воспроизведении через внутренний синтезатор (звуковая карта) это работает нормально и (с добавлением фиктивного события , если необходимо) время цикла увеличивается.

Однако при воспроизведении через внешний (USB или последовательный) синтезатор в выходном сигнале появляется заметный разрыв в той точке, где он зацикливается. Это объясняется тем фактом, что в начале файла .mid имеется много событий установки, которые для передачи по последовательной линии занимают некоторое время.

Я хотел бы попытаться изолировать одноразовые события настройки в свои собственные Sequence, которые отправляются на устройство один раз при загрузке песни, но не попадают в основной (зацикленный) Sequence.

Существует ли простой алгоритм (или библиотечная функция), который может различать два типа событий?

Это должно было бы обеспечить:

  • Зарегистрированный параметр Изменения, которые отправляются в виде группы связанных сообщений.
  • Иногда изменения программы канала отправляются в середине дорожки (и должны быть частью зацикленной последовательности), но там, где одна и та же программа сохраняется в течение всей песни (в большинстве случаев), изменение программы должно быть частью последовательность настройки То же самое относится и к изменениям темпа.

1 Ответ

3 голосов
/ 17 июля 2011

Взгляните на javax.sound.midi. Последовательность состоит из треков. Треки содержат MidiEvents. MidiEvents - это комбинация метки времени и MidiMessage.

MidiMessage имеет подклассы ShortMessage, MetaMessage и SysexMessage.

Скорее всего, фильтрация SysexMessages на отметке 0 (MidiEvent.getTick () == 0) поможет. Если нет, попробуйте также отфильтровать MetaMessages на отметке 0. Примечание: информация, изменения в программе и т. Д. Выполняются через ShortMessages, не фильтруйте их.

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

Другая часть заключается в создании последовательности инициализации. Просто создайте последовательность с тем же типом деления и разрешением. Достаточно одной дорожки, вы можете добавить все события, удаленные из последовательности зацикливания, в одну дорожку в последовательности инициализации.

...