midiについてさらに掘り下げてみた。
連続したノートの演奏
まず前日のソースコードから連続で違うノートを演奏してみた。連続で音を演奏するためには前の音を消す必要がある。消さないと同時に音が鳴り響くために和音となる。音を消すコードは以下になる。
message.setMessage(ShortMessage.NOTE_OFF, 69, 127);
バイオリンのチューニングを考えてA, D, E, Gを鳴らす。
package midi02;
/*
* midi02
* 指定した音を連続して演奏してみる
*
*/
import java.io.*;
import javax.sound.midi.*;
class Test {
public static void main(String[] args) throws Exception {
int[] notenums = { 69, 74, 76, 79 }; /* A, D, E, G */
Receiver midireceiver = MidiSystem.getReceiver();
ShortMessage smsg = new ShortMessage();
try {
for(int num : notenums) {
smsg.setMessage(ShortMessage.NOTE_ON, num, 127);
midireceiver.send(smsg, -1);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
// handle the exception...
// For example consider calling Thread.currentThread().interrupt(); here.
}
smsg.setMessage(ShortMessage.NOTE_OFF, num, 127);
midireceiver.send(smsg, -1);
}
} finally {
if (midireceiver != null) midireceiver.close();
}
}
}
MIDIデバイスの取得
さて次にすこし方向性を変えてみて、システムで利用しているMIDIデバイスについて確認をする。この情報はMidiSystemとMidiDeviceオブジェクトから簡単に取得できる。
package midi03;
import javax.sound.midi.*;
import java.util.*;
class Test {
public static void main(String[] args) {
System.out.println("----- システムデフォルト情報 ----- ");
try {
Sequencer sequencer = MidiSystem.getSequencer();
System.out.println("デフォルトシステムシーケンサ: " +
sequencer.getDeviceInfo().toString());
Synthesizer synthesizer = MidiSystem.getSynthesizer();
System.out.println("デフォルトシステムシンセサイザ: " +
synthesizer.getDeviceInfo().toString());
} catch (Exception e) {
e.printStackTrace();
}
MidiDevice.Info[] devices;
System.out.println("\n----- システム MIDIデバイス情報 -----");
devices = MidiSystem.getMidiDeviceInfo();
for(MidiDevice.Info info : devices) {
System.out.println("名前:" + info.getName() +
", Version: " + info.getVersion() +
", 会社:" + info.getVendor() +
", 詳細:" + info.getDescription());
MidiDevice device = null;
try {
device = MidiSystem.getMidiDevice(info);
if (! device.isOpen()) {
device.open();
}
} catch (Exception e){
e.printStackTrace();
}
if (device instanceof Sequencer) {
System.out.println(" デバイスタイプ: シーケンサ");
}
if (device instanceof Synthesizer) {
System.out.println(" デバイスタイプ: シンセサイザ");
}
System.out.println("\n レシーバ--------------------------------");
List receivers = device.getReceivers();
for (Receiver r: receivers) {
System.out.println(" " + r.toString());
}
try {
System.out.println(" デフォルトのレシーバ: " +
device.getReceiver().toString());
System.out.println(" 現在開いているレシーバー:");
receivers = device.getReceivers();
for (Receiver r: receivers) {
System.out.println(" " + r.toString());
}
} catch(MidiUnavailableException e) {
System.out.println(" デフォルトレシーバばなし");
}
System.out.println("\n トランスミッター--------------------------------");
List transmitters = device.getTransmitters();
for (Transmitter t: transmitters) {
System.out.println(" " + t.toString());
}
try {
System.out.println(" デフォルトトランスミッター: " +
device.getTransmitter().toString());
System.out.println(" 現在開いているトランスミッター:");
transmitters = device.getTransmitters();
for (Transmitter t: transmitters) {
System.out.println(" " + t.toString());
}
} catch(MidiUnavailableException e) {
System.out.println(" デフォルトトランスミッターなし");
}
device.close();
}
}
}
レシーバとシーケンサの違い
レシーバを使って連続したピッチを再生しようとしたがうまくいかなかった。調べてみるとレシーバはビープのような単一の音を再生をする機能しかない。音楽のように複雑なノートが合わさった曲はシーケンサを使う。
レシーバとシーケンサの違いを調べてみた。
Oracleが提供するJava SE documentからの抜粋である。本文はこちらにある。
Transmitters and Receivers
Most MIDI devices are capable of sending
MidiMessages, receiving them, or both. The way a device sends data is via one or more transmitter objects that it “owns.”Sequencers
A sequencer is a device for capturing and playing back sequences of MIDI events. It has transmitters, because it typically sends the MIDI messages stored in the sequence to another device, such as a synthesizer or MIDI output port. It also has receivers, because it can capture MIDI messages and store them in a sequence.
レシーバはMidiMessagを送る機能があると説明されている。それに対してSequencerは一連のMidiイベントをキャプチャおよび再生できるとしている。またこのMidiイベントにはMIDIメッセ―ジも含まれている。
MIDIシーケンサを利用すれば連続したノートを再生できるらしい。
Instrument
midiでは楽器の種類を変えて同じ音を演奏することができる。まずシステムで利用できる楽器の一覧を取得する。
package midi04;
import javax.sound.midi.*;
import java.util.*;
public class midi04main {
public static void main(String[] args)
{
try {
Synthesizer synthesizer = MidiSystem.getSynthesizer();
synthesizer.open();
Instrument[] ints = synthesizer.getAvailableInstruments();
int index = 0;
for (Instrument i: ints) {
index++;
System.out.println(index + " : " + i.getName());
}
} catch (Exception e)
{
e.printStackTrace();
}
}
}
midiで楽器を変えてみる
midiでは楽器をシンセサイザから変えることができる。violinは楽器番号が40であることがわかっているので、ノート69をバイオリンで再生する。
package midi05;
import javax.sound.midi.*;
import javax.sound.*;
public class midi05main {
static int instrument = 41;
static int note = 69;
static int velocity = 127;
public static void main(String[] args) {
Synthesizer synth = null;
try {
synth = MidiSystem.getSynthesizer();
synth.open();
}
catch (Exception e) {
System.out.println(e);
}
Soundbank soundbank = synth.getDefaultSoundbank();
Instrument[] instr = soundbank.getInstruments();
synth.loadInstrument(instr[instrument]);
//Changing this int (instrument) does nothing
MidiChannel[] mc = synth.getChannels();
mc[0].programChange(0, instrument);
mc[0].noteOn(note, velocity);
try { Thread.sleep(5000); } catch (InterruptedException e) {}
System.out.println(instr[instrument].getName());
synth.close();
}
}
[…] バイオリンのチューナーを作る – midiをさらに掘り下げた […]