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);
}
}
}