現在JavaFXでMIDIシーケンサーの制作を行っています。
Java(JavaFX)については初心者で、今回が初めてのJavaFXを用いた作品の制作になります。
MIDIに関しては今までは使う側でしたが今回初めて作る側の立場です。
開発環境:windows10pro/Eclipse 4.4
現時点では1つのトラックで音を配置して鳴らす事はできました。曲を作るにあたって複数の楽器を同時に演奏しなければならないので、トラックを複数作りそれぞれに音色を割り当てる事にしました。
複数のトラックを同時に鳴らす事はできたのですが、各々音色を割り当てた筈が最後のトラックに割り当てた音色が他のトラックでも鳴るようになってしまいました。
以下コードです。
[codejavaFX]
public class Controller implements Initializable {
public Sequencer sequencer;
public Sequence sequence;
public final static int VELOCITY = 127;
//
//
@Override
public void initialize(URL location, ResourceBundle resources) {
createSequencer();
}
public void createSequencer(){ //シーケンサー生成
try {
sequence = new Sequence(Sequence.PPQ,240);
sequencer = MidiSystem.getSequencer();
} catch (InvalidMidiDataException | MidiUnavailableException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
}
}
public static MidiEvent NoteOn(int time, int noteno, int velocity) //ノートオン
throws Exception {
ShortMessage sm = new ShortMessage();
sm.setMessage(ShortMessage.NOTE_ON, noteno, velocity);
return new MidiEvent(sm, time);
}
public static MidiEvent NoteOff(int time, int noteno, int velocity) //ノートオフ
throws Exception {
ShortMessage sm = new ShortMessage();
sm.setMessage(ShortMessage.NOTE_OFF, noteno, velocity);
return new MidiEvent(sm, time);
}
public MidiEvent programChange(int namber){ //音色を変えるメソッド
ShortMessage sm = new ShortMessage();
try {
sm.setMessage(ShortMessage.PROGRAM_CHANGE,namber,0);
} catch (InvalidMidiDataException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
}
return new MidiEvent(sm, 0);
}
@FXML
public void mmlTranslation(){ //fxmlで配置したボタンを鳴らすと再生
Track track = sequence.createTrack(); //1つ目のトラック生成
Track track2 = sequence.createTrack(); //2つ目のトラック生成
track.add(programChange(0)); //ここでトラック1にピアノを割り当てている・・・はず
track2.add(programChange(50)); //ここでトラック2にストリングスを割り当てている・・・はず
try {
track.add(NoteOn(0,72,VELOCITY)); //音を並べる
track.add(NoteOff(479,72,VELOCITY));
track.add(NoteOn(480,74,VELOCITY));
track.add(NoteOff(960,74,VELOCITY));
track2.add(NoteOn(0,60,VELOCITY));
track2.add(NoteOff(479,60,VELOCITY));
track2.add(NoteOn(480,62,VELOCITY));
track2.add(NoteOff(960,62,VELOCITY));
} catch (Exception e1) {
// TODO 自動生成された catch ブロック
e1.printStackTrace();
}
try {
sequencer.open(); //再生
sequencer.setSequence(sequence);
sequencer.start();
if(sequencer.isRunning()) System.out.println("start");
while (sequencer.isRunning()) Thread.sleep(100);
sequencer.close();
sequence.deleteTrack(track);
sequence.deleteTrack(track2);
} catch (MidiUnavailableException | InvalidMidiDataException | InterruptedException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
}
}
}
[/code]
このコードの場合、トラック1にピアノを割り当てトラック2にストリングスを割り当てたのですが、トラック1もストリングスで鳴ってしまいます。
どうすればトラックによって音色を分けられるのでしょうか?
MIDIシーケンサーでトラック毎に音色を割り当てられない
Re: MIDIシーケンサーでトラック毎に音色を割り当てられない
単純にここでエラーになってコンパイル出来ないのではありませんか?
@FXML
public void mmlTranslation(){ //fxmlで配置したボタンを鳴らすと再生
Track track = sequence.createTrack(); //1つ目のトラック生成
Track track2 = sequence.createTrack(); //2つ目のトラック生成
track.add(programChange(0)); //ここでトラック1にピアノを割り当てている・・・はず
track2.add(programChange(50)); //ここでトラック2にストリングスを割り当てている・・・はず
try {
track.add(NoteOn(0,72,VELOCITY)); //音を並べる
track.add(NoteOff(479,72,VELOCITY));
track.add(NoteOn(480,74,VELOCITY));
track.add(NoteOff(960,74,VELOCITY));
track2.add(NoteOn(0,60,VELOCITY));
track2.add(NoteOff(479,60,VELOCITY));
track2.add(NoteOn(480,62,VELOCITY));
track2.add(NoteOff(960,62,VELOCITY));
} catch (Exception e1) {
// TODO 自動生成された catch ブロック
e1.printStackTrace();
}
try {
sequencer.open(); //再生
sequencer.setSequence(sequence);
sequencer.start();
if(sequencer.isRunning()) System.out.println("start");
Re: MIDIシーケンサーでトラック毎に音色を割り当てられない
こちらのサイトを利用するのは初めてなので書き写す際にインデント等おかしくなってしまいましたがコンパイルや実行した際のエラーメッセージはありませんでした。
Re: MIDIシーケンサーでトラック毎に音色を割り当てられない
音色などのパラメータを保持して音を出すのはチャンネルの仕事であって、
トラックを分けても同じチャンネルを指定していれば後から送信された方で上書きされますので、
別の音色を使用したければチャンネルを分けてください。
そのソースであればこんな感じにすればチャンネルを指定できるでしょう。
channelは0~15。9はドラム用。
sm.setMessage(ShortMessage.NOTE_ON, channel, noteno, velocity);
トラックを分けても同じチャンネルを指定していれば後から送信された方で上書きされますので、
別の音色を使用したければチャンネルを分けてください。
そのソースであればこんな感じにすればチャンネルを指定できるでしょう。
channelは0~15。9はドラム用。
sm.setMessage(ShortMessage.NOTE_ON, channel, noteno, velocity);
Re: MIDIシーケンサーでトラック毎に音色を割り当てられない
ARCS様ありがとうございます。おかげ様で解決しました。
NoteOnとNoteOff、programChangeの引数にchannelを追加し、setMessageの第二引数にchannnelを当てる事で個々に鳴らす事ができました。
MIDIの仕組みも分かってきました。これからも頑張ろうと思います。
NoteOnとNoteOff、programChangeの引数にchannelを追加し、setMessageの第二引数にchannnelを当てる事で個々に鳴らす事ができました。
MIDIの仕組みも分かってきました。これからも頑張ろうと思います。