MIDIのトラックを簡単に編集できるトラックエディターを作っています。前に作った音色の変更機能もここに組み込みたいと思います。
JavaとMIDI:音色を変更する(1)
JavaとMIDI:音色を変更する(2)
JavaとMIDI:音色を変更する(3)
音色変更に必要な3つのメッセージ
サウンドバンクを利用した音の変更には3つのメッセージが必要でした。メッセージの順番はMSB、LSB、プログラムチェンジにする必要があります。
ShortMessage[] messages = new ShortMessage[3]; messages[0] = new ShortMessage(ShortMessage.CONTROL_CHANGE, channel, 0x00, bank_m); messages[1] = new ShortMessage(ShortMessage.CONTROL_CHANGE, channel, 0x20, bank_l); messages[2] = new ShortMessage(ShortMessage.PROGRAM_CHANGE, channel, program, 0);
実装
音色変更のメソッドを作ります。引数は小節と拍、MSB、LSB、プログラムチェンジの設定値を取ります。
public void setProgram(int measure, double beat, int bank_m, int bank_l, int program) {
小節と拍の情報からティック位置を求めます。
long tick = timeSign.getTick(measure, beat);
トラックに三つのメッセージを登録します。例外が投げられる可能性があるためtry-catch節で囲み実行時例外であるillegalStateExceptionを投げ直します。実際になにか問題があれば中断してかまわないですし、これでメソッドの宣言にthrowsを書かなくてよくなります。
try { track.add(new MidiEvent(new ShortMessage(ShortMessage.CONTROL_CHANGE, channel, 0x00, bank_m), tick)); track.add(new MidiEvent(new ShortMessage(ShortMessage.CONTROL_CHANGE, channel, 0x20, bank_l), tick)); track.add(new MidiEvent(new ShortMessage(ShortMessage.PROGRAM_CHANGE, channel, program, 0), tick)); } catch (InvalidMidiDataException ex) { throw new IllegalStateException(ex); }
ソース
ここまででできたトラックエディターのソースです。次回は曲を編集していきたいと思います。
/* * mocha-java.com * */ package mocha.sound.midi; import javax.sound.midi.InvalidMidiDataException; import javax.sound.midi.MidiEvent; import javax.sound.midi.ShortMessage; import javax.sound.midi.Track; /** * * @author minaberger */ public class TrackEditor { MidiTimeSign timeSign; Track track; int channel; public TrackEditor(MidiTimeSign timeSign, Track track, int channel) { this.timeSign = timeSign; this.track = track; this.channel = channel; } public void setProgram(int measure, double beat, int bank_m, int bank_l, int program) { long tick = timeSign.getTick(measure, beat); try { track.add(new MidiEvent(new ShortMessage(ShortMessage.CONTROL_CHANGE, channel, 0x00, bank_m), tick)); track.add(new MidiEvent(new ShortMessage(ShortMessage.CONTROL_CHANGE, channel, 0x20, bank_l), tick)); track.add(new MidiEvent(new ShortMessage(ShortMessage.PROGRAM_CHANGE, channel, program, 0), tick)); } catch (InvalidMidiDataException ex) { throw new IllegalStateException(ex); } } public void play(int measure, double beat, int note, int velocity, double duration) { long tickOn = timeSign.getTick(measure, beat); long tickOff = timeSign.getTick(measure, beat + duration); try { track.add(new MidiEvent(new ShortMessage(ShortMessage.NOTE_ON, channel, note, velocity), tickOn)); track.add(new MidiEvent(new ShortMessage(ShortMessage.NOTE_ON, channel, note, 0), tickOff)); } catch (InvalidMidiDataException ex) { throw new IllegalStateException(ex); } } }