MIDI - Смена программы MidiMessage с помощью инструмента из другого банка
Звуковой банк синтезатора по умолчанию, который я использую, содержит множество различных инструментов. Например, этот фрагмент кода...
Synthesizer synthesizer = MidiSystem.getSynthesizer();
synthesizer.open();
Instrument instruments = synthesizer.getDefaultSoundbank().getInstruments();
for (Instrument i : instruments)
System.out.println(i);
... печатает следующее:
Instrument: Piano 1 bank #0 preset #0
Instrument: Piano 2 bank #0 preset #1
[...]
Instrument: Applause bank #0 preset #126
Instrument: Gun Shot bank #0 preset #127
Instrument: SynthBass101 bank #128 preset #38
Instrument: Trombone 2 bank #128 preset #57
[...]
Instrument: Machine Gun bank #128 preset #127
Instrument: Echo Pan bank #256 preset #102
Instrument: String Slap bank #256 preset #120
[...]
Instrument: Lasergun bank #256 preset #127
[...]
Instrument: Starship bank #1024 preset #125
Instrument: Carillon bank #1152 preset #14
[...]
Instrument: Choir Aahs 2 bank #4096 preset #52
Я могу играть на инструменте из любого из этих банков через MidiChannel
, programChange
метод и noteOn
Примерно так (это играет инструмент 14 из банка 1152, "Карильон"):
MidiChannel channel = synthesizer.getChannels()[0];
if (channel != null) {
channel.programChange(1152, 14);
channel.noteOn(70, 100);
}
Я хочу добавить событие изменения программы в дорожку последовательности, чтобы я мог играть на инструменте "Карильон" в последовательности. Я пытался сделать это с ShortMessage
:
Sequence sequence = new Sequence(Sequence.PPQ, 2);
Track track = sequence.createTrack();
ShortMessage pcMessage = new ShortMessage(ShortMessage.PROGRAM_CHANGE, 0, 14, 0);
track.add(new MidiEvent(pcMessage, 0));
Но это меняет инструмент на инструмент 14 в банке 0 ("трубчатый колокол"), когда я вместо этого ищу инструмент 14 в банке 1152. Попытка изменить один из двух последних аргументов в конструкторе ShortMessage на 1152 привела к javax.sound.midi.InvalidMidiDataException
для значения байта данных вне диапазона. Другие подклассы MidiMessage, по-видимому, также не содержат возможности загрузки инструментов из других банков.
Как я могу использовать инструмент из другого банка в MidiMventage MidiEvent?
1 ответ
В самом протоколе MIDI номера банков разделены на две 7-битные части и передаются как значения двух контроллеров: "Выбор банка" и "LSB выбора банка":
... = new ShortMessage(ShortMessage.CONTROL_CHANGE, 0, 0, 1152 >> 7); // = 9
... = new ShortMessage(ShortMessage.CONTROL_CHANGE, 0, 32, 1152 & 0x7f); // = 0
... = new ShortMessage(ShortMessage.PROGRAM_CHANGE, 0, 14, 0);
Обратите внимание, что в разных стандартах (GS, XG, GM2) две части номера выбора банка называются по-разному. В этом случае Carillon взят из стандарта GS, который определяет его как "вариант № 9", который является контроллером MSB. Но имя контроллера не имеет значения; вы получаете правильный инструмент, если вы установите контроллер от 0 до 9.